如何定义一个命令来排版没有协议的 URL?

如何定义一个命令来排版没有协议的 URL?

有一个相关问题,但答案显示了如何使用 URL 文本手动创建链接。这不是我想要的。

我想创建一个命令(称为\urlb),它将排版带有超链接的 URL,但丢弃链接文本中的协议。这似乎可以使用代码来完成,但我还没有找到可以做到这一点的包。

我是否遗漏了什么?

例子

我想输入:

\urlb{https://mydomain.example.com}

并获取超链接的输出:

mydomain.example.com

因此定义可能看起来像这样:

\newcommand{\urlb}[1]{%
    \href{#1}{\stripProto{#1}}%
}

电子邮件地址

我还希望它适用于电子邮件地址。在这种情况下,输入将是,输出将是带有文本的超链接。mailto:[email protected][email protected]

答案1

为了正确处理 URL 等,我们需要一个不仅仅能根据模式进行拆分的命令。

  1. 需要处理下划线和与号等字符,否则会导致错误。
  2. 如果有一个通用版本能够处理至少一些其他协议(例如等)file那就好了。ftp
  3. 由于 URL 可能很长,并且永远不会构成 TeX 可以使用标准连字符模式断开的单词,因此我们需要启用额外的换行符。

以下代码尝试满足这些标准。

  1. \NewDocumentCommandv参数类型用于确保输入按逐字处理。这将\href{}{}作为第一个参数传递。
  2. 如果标签(默认情况下,第一个参数传递的值)包含://或,则将其拆分,否则,:或,否则,按原样使用。如果拆分,则使用右侧的所有内容,其余部分将被丢弃。
  3. xurl已加载并且链接标签\url{}在传递给之前被包装起来\href{}{}

语法是

\urlb[<alternative label text>]{<content for link>}
\urlb{<content for link>}

如果省略可选参数,<content for link>则用于两个参数。

拆分是使用名为 的参数处理器完成的\HyperSplit。处理后的参数随后被包装在 中\url{},并将结果展开一次,然后作为 的第二个参数传递\href{}{}

  • 扩展由处理在接收它们之前\ExpandArgs {no} ...传递给的参数的处理。只是按原样传递第一个。扩展第二个一次。\href{}{}\href{}{}no

在以下情况下

\urlb{https://mydomain.example.com}

\urlb{mailto:[email protected]}

结果与使用分隔模式拆分输入相同,如LdBeth 的回答。但是,下面的代码在以下情况下也能正确执行

\urlb{file:///etc/ssl/certs/TUBITAK_Kamu_SM_SSL_Kok_Sertifikasi_-_Surum_1.pem}

\urlb{https://www.startpage.com/sp/search?query=protocol+formats&cat=web&pl=opensearch&language=english}

否则会导致错误,因为它们包含“奇怪”(“活动”?)字符,例如_&。由于xurl使用了 ,两个链接也会跨行断开,因此它们不会超出行宽。

可选参数还允许覆盖链接的重复使用,以防万一你想要

\urlb[open file]{file:///etc/ssl/certs/TUBITAK_Kamu_SM_SSL_Kok_Sertifikasi_-_Surum_1.pem}

代码:

\documentclass{article}
% ateb: https://tex.stackexchange.com/a/715932/
\usepackage[T1]{fontenc}
\usepackage{hyperref}
\usepackage{xurl}
\NewDocumentCommand \urlb {>{\HyperSplit}O{#2}v}
{%
  \ExpandArgs {no}\href{#2}{\url{#1}}%
}
\ExplSyntaxOn
\cs_new_protected:Npn \HyperSplit #1
{
  \regex_split:nnNF { :// } { #1 } \l_tmpa_seq
  {
    \regex_split:nnNF { : } { #1 } \l_tmpa_seq
    {
      \seq_put_left:NV \l_tmpa_seq \c_empty_tl
    }
  }
  \seq_get_right:NN \l_tmpa_seq \ProcessedArgument
}
\ExplSyntaxOff

\begin{document}

\urlb{https://mydomain.example.com}

\urlb{mailto:[email protected]}

\urlb{file:///etc/ssl/certs/TUBITAK_Kamu_SM_SSL_Kok_Sertifikasi_-_Surum_1.pem}

\urlb{https://www.startpage.com/sp/search?query=protocol+formats&cat=web&pl=opensearch&language=english}

\urlb[mydomain]{https://mydomain.example.com}

\urlb[email me]{mailto:[email protected]}

\urlb[open file]{file:///etc/ssl/certs/TUBITAK_Kamu_SM_SSL_Kok_Sertifikasi_-_Surum_1.pem}

\urlb[search the 'net]{https://www.startpage.com/sp/search?query=protocol+formats&cat=web&pl=opensearch&language=english}

\urlb{www.my_web.org}

\urlb[my web]{www.my_web.org}

\end{document}

抱歉,没有提供视觉辅助。目前,X 上的 Okular 生成的图像非常糟糕,我已放弃发布它们,直到我想出一个合理的方法或修复错误(或者我弄清楚了 Wayland,我猜)。

答案2

使用普通的 TeX 宏可以很容易地实现这一点。它被设计为能够执行简单的模式匹配任务。

\def\stripProto#1://{}

\stripProto https://mydomain.example.com
=> mydomain.example.com

然后你只需定义

\newcommand{\urlb}[1]{%
    \href{#1}{\stripProto#1}%
}

相似地,

\def\stripMailTo#1:{}

您想让同一个命令对两种类型的链接起作用吗?没问题 :)

\documentclass{article}
\usepackage{url}
\usepackage{hyperref}
% These are TeX's "strip until a string pattern"
\def\stripProto#1://{}
\def\stripMailTo#1:{}
% Save text up to the first `:` to macro definition \proto
\def\getProto#1:#2\end{\def\proto{#1}}
% save protocol names as "string constants"
% so they can be compared with \ifx
\def\strhttp{https}\def\strmto{mailto}
%
\def\stripstrip#1{%
\getProto #1\end
\ifx\proto\strhttp
 \stripProto #1%
\else\ifx\proto\strmto
 \stripMailTo #1\fi\fi}
\newcommand{\urlb}[1]{%
    \href{#1}{\stripstrip{#1}}%
}
\begin{document}
\urlb{https://mydomain.example.com}

\urlb{mailto:[email protected]}
\end{document}

相关内容