1

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 test.html}{Link without space}

\href {\base
test.html}{Link with space}
\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.

2
  • 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
1

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 test.html}{Link without space}

\href {\base
test.html}{Link with space}

%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 test.html}{Link without space}

\href {\base
test.html}{Link without space, too}

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.