4

I'm trying to add an external link symbol (from https://tex.stackexchange.com/a/294990/163482) to href but for some reason the spacing after the symbol is wrong when I redefine the href command. What would the right way to do it (and what would be the right amount of space)?

\documentclass{article}
\usepackage{tikz,hyperref}
\newcommand{\ExternalLink}{%
  \tikz[x=1.2ex, y=1.2ex, baseline=-0.5ex, scale=0.75]{% 
    \begin{scope}[x=1ex, y=1ex]
      \clip (-0.1,-0.1) 
       --++ (-0, 1.2) 
       --++ (0.6, 0) 
       --++ (0, -0.6) 
       --++ (0.6, 0) 
       --++ (0, -1);
      \path[draw=black, line width = 0.5,
            rounded corners=0.5] (0,0) rectangle (1,1);
    \end{scope}
    \path[draw=black, line width = 0.5] (0.5, 0.5) -- (1, 1);
    \path[draw=black, line width = 0.5] (0.6, 1)   -- (1, 1) -- (1, 0.6);
  }
}

\let\orighref\href
\renewcommand{\href}[2]{\orighref{#1}{#2}$\,$\ExternalLink}

\begin{document}
\noindent
Some text \href{http://google.com}{link} some more text.\\
Some text \orighref{http://google.com}{link}$\,$\ExternalLink some more text.
\end{document}

enter image description here

1 Answers1

7

When you write:

Some text \orighref{http://google.com}{link}$\,$\ExternalLink some more text.

the space after \ExternalLink is ignored by TeX, because \ExternalLink is a control sequence whose name ends with a letter. On the contrary, with:

Some text \href{http://google.com}{link} some more text.

there is a space token after {link}, and it is not ignored. It contributes an interword space to the horizontal list under construction. That is why you see a larger space in the first case of your example (second case here). In order to get rid of this additional space, you can either write:

Some text \href{http://google.com}{link}some more text.

or use \ignorespaces in your redefinition of \href so as to ignore spaces following in the input (\ignorespaces expands tokens from the input stream until it finds an unexpandable token that is not a 〈space token〉, according to the TeX grammar):

\renewcommand*{\href}[2]{\orighref{#1}{#2}$\,$\ExternalLink\ignorespaces}

But actually, you don't want to use any of these suggestions. This is because in your \ExternalLink command, there is a most probably unwanted space:

\newcommand{\ExternalLink}{%

...

    \path[draw=black, ...] ... ;
  } % <------- here, remove the space
}

So, your \ExternalLink command unconditionally adds this space after the icon. I believe this is unwanted when the hyperlink is followed by a comma or a period, for instance. Therefore I'd remove this space; then you don't need \ignorespaces anymore.

Also note that you don't need to be in math mode in order to use \,; it produces a \thinspace when used outside of math mode. So, you can do something like:

\renewcommand*{\href}[2]{\orighref{#1}{#2}\,\ExternalLink}

Other suggestion: you may want to include the icon inside the clickable link:

\renewcommand*{\href}[2]{\orighref{#1}{#2\,\ExternalLink}}

I used \renewcommand* because the arguments of \href most probably shouldn't contain \par tokens; this makes finding errors easier.

Note: there won't be a line break at the \,, because this macro expands to \thinspace in non-math mode, which itself expands to a \kern, and there can be a break at a \kern only if it's immediately followed by glue—which isn't the case here, as \ExternalLink starts with a box: the TikZ picture.

Final remark: your links are going to make TeX work hard on the TikZ picture every time you use this redefined \href (i.e., for every hyperlink). Since the icon is always the same, there is a way to save on compilation time: save the picture once inside a box, then use the box whenever you need it. That is very cheap on computing resources. All in all, here is my suggestion (I added a picture with a caption because of our discussion in the comments—the \usebox command doesn't need to be \protected, as the example shows):

\documentclass{article}
\usepackage{tikz}
\usepackage[hidelinks]{hyperref} % 'hidelinks' removes the border around links

\newsavebox{\ExternalLinkIcon}

\begin{lrbox}{\ExternalLinkIcon}
  \begin{tikzpicture}[x=1.2ex, y=1.2ex, baseline=-0.5ex, scale=0.75]
    \begin{scope}[x=1ex, y=1ex]
      \clip (-0.1,-0.1)
       --++ (-0, 1.2)
       --++ (0.6, 0)
       --++ (0, -0.6)
       --++ (0.6, 0)
       --++ (0, -1);
      \path[draw=black, line width = 0.5,
            rounded corners=0.5] (0,0) rectangle (1,1);
    \end{scope}
    \path[draw=black, line width = 0.5] (0.5, 0.5) -- (1, 1);
    \path[draw=black, line width = 0.5] (0.6, 1)   -- (1, 1) -- (1, 0.6);
  \end{tikzpicture}% <--- important!
\end{lrbox}

\let\orighref\href

\renewcommand*{\href}[2]{%
  \orighref{#1}{#2\,\usebox{\ExternalLinkIcon}}%
}

\begin{document}

\noindent
Some text \href{http://example.com}{link} some more text. Spacing is also fine
before a \href{http://example.com}{comma}, as you can see. Periods are fine
too, of course---we don't have to do anything special.

\begin{figure}[htbp]
  \centering
  This is the figure contents.
  \caption{A caption containing a \href{http://example.com}{hyperlink}}
\end{figure}

\end{document}

Screenshot

frougon
  • 24,283
  • 1
  • 32
  • 55
  • Thanks, works nicely but I just realized the tikz part was not working inside a caption. It needs a \DeclareRobustCommand{\ExternaLink...} – Nicolas Rougier Jul 29 '19 at 17:15
  • 1
    This is probably due to the fact that a caption is subject to \protected@write for the list of figures or list of tables, and \protected@write tries to expand everything that is neither \protected nor preceded by \protect. You can use \newrobustcmd* from the etoolbox package, that is slightly better. – frougon Jul 29 '19 at 17:39
  • 1
    There was a spurious space at the end of your \ExternalLink command. This changes everything! Please reread my answer... – frougon Jul 29 '19 at 19:20