如果在节命令中使用带星号的宏版本,则会导致超引用错误

如果在节命令中使用带星号的宏版本,则会导致超引用错误

在以下 MWE 中

\documentclass{article}

\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage[utf8]{inputenc}

\usepackage[pdftex,unicode,final]{hyperref}
\input{glyphtounicode}
\pdfgentounicode=1

\makeatletter
\newcommand*{\boilerplate}{\@ifstar\@@boilerplate\@boilerplate}
\newcommand*{\@boilerplate}{Boilerplate for running text}
\newcommand*{\@@boilerplate}{Boilerplate for headings in capalized form}
\makeatother

\begin{document}

\section{\boilerplate*}

\end{document}

星号用于获取样板的替代变体。MWE 失败,

Token not allowed in a PDF string (Unicode):
(hyperref)                removing `\@ifnextchar' on input line 19.

显然,问题在于宏扩展的顺序。我已经尝试过,\expandafter但没有找到解决方案。

评论:如果可能的话,我想保留星号版本以选择样板的变体。这种设计已经达成一致,并在无数地方使用。换句话说,将宏定义更改为类似于\boilerplateNormal和的内容\boilerplateVariant不是一个选择,因为这会破坏与使用 sty 文件的其他作者的兼容性。

答案1

\boilerplate根据当前的定义,该命令很脆弱。

\protect\boilerplate在移动参数中使用when,或者

\DeclareRobustCommand{\boilerplate}{\@ifstar\@@boilerplate\@boilerplate}

代替\newcommand

或者,添加\usepackage{xparse}并修改定义到

\NewDocumentCommand{\boilerplate}{s}{%
  \IfBooleanTF{#1}{%
    Boilerplate for headings in capitalized form% \boilerplate*
  }{%
    Boilerplate for running text% \boilerplate (with no *)
  }%
}

不过,不要指望\boilerplate(带或不带) 的扩展能出现在书签中。如果宏采用常规参数,则*可以做到这一点。\boilerplate

假设在移动参数中使用 *-variant,则可以使用\pdfstringdefDisableCommand

\documentclass{article}

\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{lmodern}
\usepackage{xparse}

\usepackage[unicode,final]{hyperref}
\input{glyphtounicode}
\pdfgentounicode=1

\NewDocumentCommand{\boilerplate}{s}{%
  \IfBooleanTF{#1}{%
    Boilerplate for headings in capitalized form% \boilerplate*
  }{%
    Boilerplate for running text% \boilerplate (with no *)
  }%
}
\pdfstringdefDisableCommands{\def\boilerplate*{Boilerplate for bookmark}}

\begin{document}

\section{\boilerplate*}

\boilerplate

\end{document}

在此处输入图片描述

相关内容