2

There is a related question, but the answer shows how manually create a link with the URL text. That's not what I want.

I want to create a command (call it \urlb) that will typeset a URL with a hyperlink, but discard the protocol in the link's text. It seems like something that could be done using code, but I haven't found a package that can do this.

Am I missing something?

Example

I'd like to type:

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

And get the hyperlinked output:

mydomain.example.com

So the definition might look something like this:

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

Email addresses

I also want it to work for email addresses. In that case, the input would be mailto:[email protected] and the output would be a hyperlink with the text [email protected].

1

2 Answers 2

3

To correctly handle URLs etc., we need a command which can do more than simply split according to a pattern.

  1. It is necessary to deal with characters such as underscores and ampersands, which otherwise cause errors.
  2. It would be good to have a general version which can deal with at least some other protocols, such as file, ftp etc.
  3. Since URLs can be long and never constitute words TeX can break using standard hyphenation patterns, we need to enable additional line breaks.

The following code attempts to meet these criteria.

  1. \NewDocumentCommand's v argument type is used to ensure the input is handled as verbatim. This is passed to \href{}{} as the first argument.
  2. The label (by default, the value passed for the first argument) is split if it contains :// or, failing that, : or, failing that, used as is. If split, everything to the right is used and the rest discarded.
  3. xurl is loaded and the link label wrapped in \url{} before being passed to \href{}{}.

The syntax is

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

If the optional argument is omitted, <content for link> is used for both arguments.

The splitting is done using an argument processor called \HyperSplit. The processed argument is then wrapped in \url{} and the result expanded once before being passed as the second argument of \href{}{}.

  • The expansion is handled by \ExpandArgs {no} ... which handles the arguments passed to \href{}{} before \href{}{} receives them. n just passes the first through as-is. o expands the second once.

In cases such as

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

\urlb{mailto:[email protected]}

the result is the same as using a delimited pattern to split the input, as suggested in LdBeth's answer. However, the code below also does the right thing in cases such as

\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}

which otherwise cause errors because they contain 'weird' ('active'?) characters such as _ and &. Because xurl is used, two links are also broken across lines, so they don't exceed the line width.

The optional argument also permits overriding re-use of the link in case you want something like

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

Code:

\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}

Apologies for the lack of visual aids. Current Okular on X produces such terrible images I have given up posting them until I come up with a reasonable method or the bug gets fixed (or I figure out Wayland, I guess).

2
  • 1
    It could be useful to explain L3 function used to treat expansion issue.
    – projetmbc
    Commented Apr 20 at 10:48
  • @projetmbc Thanks. I added a more explicit note regarding \ExpandArgs.
    – cfr
    Commented Apr 20 at 17:04
4

This is very easy with plain TeX macro. It is designed to be capable of simple pattern matching tasks.

\def\stripProto#1://{}

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

Then you just define

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

Similarly,

\def\stripMailTo#1:{}

You want the same command work for both type of links? No problem :)

\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}
6
  • 1
    It would be good to explain your code a little for beginners.
    – projetmbc
    Commented Apr 18 at 7:05
  • @cfr if you mean to distinguish :// and just : without testing the text of protocol type, it can be done by testing if the token after first : is / using the well known \futurelet trick. I cannot deny that doing string split with LaTeX3 can give more consistent results, though.
    – LdBeth
    Commented Apr 19 at 16:40
  • No. I meant that URLs often include characters like underscores and ampersands etc., which won't work with your version. E.g. \urlb{https://www.startpage.com/sp/search?query=protocol+formats&cat=web&pl=opensearch&language=english}.
    – cfr
    Commented Apr 19 at 18:24
  • @cfr good catch, but that can be work around by set catcode to 12, which is also a well known plain TeX technique. While this is still a question about LaTeX, \NewDocumentCommand is definitely the better approach.
    – LdBeth
    Commented Apr 19 at 18:35
  • @cfr While this is likely to be a one shot job, I like to not over complicate the solution and only add features that are explicitly requested, and I do not intend to present a solution that others only need to copy & paste to use in their own document, instead I took this as an invitation to learn something from it and find the use in other situations.
    – LdBeth
    Commented Apr 19 at 19:07

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .