# Prevent hyperref \href from inserting spaces into target URLs containing macros

I have noticed that some of the links my BibTeX style generates do not work because they have spaces in them. The style (apsrev4-1) hyperlinks the journal part of the reference to the DOI resolver at doi.org using something like

\href {\doibase 10.1234/doi.handle}{Journal 12, 1234 (1984)}


However, BibTeX word-wraps its output and sometimes it inserts a linebreak right behind the \doibase macro. In exactly these cases the resulting URL contains a space right after the expansion of that macro, e.g., https://doi.org/ 10.1234/doi.handle. I can reproduce the behavior:

\documentclass{article}

\usepackage{hyperref}

\newcommand{\base}[0]{http://www.example.com/}

\begin{document}

\href {\base
\end{document}


If I understand correctly, there should be no difference between the two invocations because all whitespace after a macro gets ignored.

How can I make the second version behave like the first? I have tried to append \ignorespaces to the definition of the \base macro but all that does is add a literal (url-encoded) %5Cignorespaces.

• Well you need to add a percentchar to hide the end-of-line. But I have no idea how to tell bibtex. – Ulrike Fischer Oct 2 '20 at 18:10
• @UlrikeFischer bibtex puts percent chars in output when it breaks lines not at spaces (there is code to handle it in url.sty). – Donald Arseneau Oct 2 '20 at 23:33

I don't know if this is of help to you, but when TeX reads input from .tex-input-files it inserts a character with each end of a line of input whose code-point's number in TeX's internal character encoding scheme (which either is ASCII with traditional TeX or is unicode with XeTeX- or LuaTeX based engines) equals the value of the integer-parameter \endlinechar.

If the value of \endlinechar is outside the range of possible code-point-numbers of characters, then no character is inserted.

Usually the value of \endlinechar is 13(decimal) which implies that a return-character is inserted because 13(decimal) is the code-point-number of the return-character both in ASCII and in unicode. (The return-character in TeX's ^^-notation can be denoted via ^^M, M being the 13th letter of the alphabet.)

Usually the return-character has category code 5. If TeX encounters a catcode-5-character while the reading-apparatus is in state S(skipping blanks), then no token at all is inserted into the token-stream for this character. TeX's reading apparatus is switched to state S after tokenizing an explicit space-token of character code 32 and category code 10(space) and after tokenizing a control-word-token and after tokenizing a control-space \ . If TeX encounters a catcode-5-character while the reading-apparatus is in state M(middle of line), then an explicit space-token of character code 32 and category code 10(space) is inserted into the token-stream for this character. TeX's reading-apparatus is switched to state M after tokenizing character-tokens or control-symbol-tokens other than control-spaces. If TeX encounters a catcode-5-character while the reading-apparatus is in state N(new line), then the control-word-token \par is inserted into the token-stream for this character regardless the meaning/definition \par has. TeX's reading-apparatus is switched to state N when beginning tokenization of another line.

So you could assume that after \base, which is a control-word-token, the reading-apparatus is in state S and therefore insertion of the return-character due to the \endlinechar-thingie doesn't yield insertion of whatsoever token into the token-stream.

But the \href-command is somewhat special: \href—before reading from the .tex-input-file and tokenizing the URL-argument begins— calls macros for changing the category-code of the return-character to 13(active) and defining the active-return-character to be a macro which delivers a space-token/a character-token of category code 10(space) and character-code 32. Thus with the URL-argument of \href a linebreak in the .tex-input-file yields insertion of return-character-token of category code 13(active) into the token-stream. That active return-character-token at that time is defined to be a macro which expands to a space-token.

I don't know if the following suggestion suits your workflow but probably you can assign \endlinechar a value outside the range of possible code-point-numbers of characters, e.g., the value -1. This way no character at all will be inserted by TeX at a line-break.

\documentclass{article}

\usepackage{hyperref}

\newcommand{\base}[0]{http://www.example.com/}

\begin{document}

\href {\base

%Probably something like this does the trick for you:

\begingroup
\endlinechar=-1\relax
\href{\base
test.html}{What's this?}
\endgroup

\end{document}


But if you can search through the sources for inserting \begingroup\endlinechar=-1\relax..\endgroup everywhere, then you can also instead search through the sources for removing linebreaks after \base.

Probably you can define \base to call a macro which grabs one non-delimited argument and—assuming this is the next token—checks if that is active-return and puts it back only in case it is not. But this has some drawbacks:

• As everything must be done in terms of macro-expansion, the "lookahead" must also be done by means of macro-arguments. So the lookahead is not on the next token but is on the next macro argument. If there is a multi-token-argument wrapped in curly braces right behind \base, these curly braces get removed. If there is no more token suitable as macro-argument after \base, e.g., \href{\base}{What's this?}, then you may get error-messages with some hyperref-release.
• Only a linebreak right after the token \base will be treated.

\documentclass{article}

\usepackage{hyperref}

\begingroup
\makeatletter
\catcode\^^M=12\relax%
\def\activereturnfork#1{%
\endgroup%
\newcommand\activereturnfork[1]{%
\forkactivereturn##1{}#1{##1}^^M^^M%
}%
\@ifdefinable\forkactivereturn{%
\long\def\forkactivereturn##1#1##2##3^^M^^M{##2}%
}%
}%
\catcode\^^M=13\relax%
\activereturnfork{^^M}%

\newcommand{\base}[0]{http://www.example.com/\activereturnfork}

\begin{document}

\href {\base

But:

% This will not be a link to http://www.example.com/{bracesremoved}.html
% but will be a link to  http://www.example.com/bracesremoved.html :
\href {\base {bracesremoved}.html}{Link with braces removed}
% But curly braces in any case are unsafe-characters and therefore in
% urls should be encoded with percent-encoding as %7B respective %7D .

% With current \hyper@normalize (hyperref 2018/11/30 v6.88e Hypertext links
% for LaTeX) this works by accident:
% \base/\activereturnfork takes \Hy@RemovePercentCr's \ifx for its argument
% and returns it:
\href {\base}{Attempts at creating this link may cause troubles when in future hyperref-releases internals are changed.}

\end{document}


Probably the best option is to modify the BibTeX-style not to do linebreaks within macro-arguments that get tokenized under non-standard category-code-régime.