% \iffalse meta-comment % %% File: latex2e-first-aid-for-external-files.dtx (C) Copyright 2020-2023 %% %% The LaTeX Project and any individual authors listed elsewhere %% in this file. % % It may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3c % of this license or (at your option) any later version. % The latest version of this license is in % https://www.latex-project.org/lppl.txt % and version 1.3c or later is part of all distributions of LaTeX % version 2008 or later. % % This file has the LPPL maintenance status "maintained". % % % %<*driver> \documentclass{ltxdoc} \EnableCrossrefs \CodelineIndex \begin{document} \DocInput{latex2e-first-aid-for-external-files.dtx} \end{document} % % % \fi % % % \providecommand\pkg[1]{\texttt{#1}} % % \title{First aid for external files and packages that need updating} % \author{Frank Mittelbach, \LaTeX{} Project} % % \maketitle % % % \begin{abstract} % This file contains some first aid for packages or classes that % require updates because of internal changes to \LaTeX{} but that % aren't yet reflected in the package/class code. % \end{abstract} % % \tableofcontents % % \section{Introduction} % % Over the years package writers have hooked into % various parts of internal \LaTeX{} commands (largely because % proper interfaces were missing in important places) and if % we are now gradually adding such interfaces these internal % commands do change and as a result patching into them stops % working. % % As part of making such internal changes the \LaTeX{} Project team % attempts to check for such usage in packages, alert the package % maintainers and ensures that the packages get updated alongside % the core \LaTeX{} system. However it is not always possible to % get packages that will fail with a new kernel updated in time and % if that is the case we try to provide a temporary fix in this % file for them. % Once the package gets updated the fix will then be removed again. % % For that reason, it is put into a separate bundle so that we can % update it easily without requiring the CTAN maintainers to % install a new full \LaTeX{} system just because we take out (or add) % a fix for a package here. % % In the best case scenario the file documented here should be % empty. In practice it will probably always contain one or the % other fix while we are waiting for the package to get updated. % % \begin{quote} \textbf{Important notice:} The fixes provided here % are not meant to be a permanent solution, but are only provided % to support the transition period. They are (usually) neither % complete nor necessarily the best solution! Furthermore, as they % are done from the ``outside'', they usually add some burden and % slow down \LaTeX{} processing, even if the package/class is not % used in the document. % % We will therefore remove such code as soon as possible % again. In practice this means that if some package never gets % updated/corrected, then it will eventually fail to work, because % after one or at most two \LaTeX{} releases we will take out the % transition code to ensure that this ``first aid patching'' % doesn't get out of bounds. % \end{quote} % % \subsection{Minor kernel fixes} % % If we encounter issues with the kernel code that should get fixed % before the next main release we normally generate a patch release % for \LaTeX{}. However, depending on the complexity of the fix we % might first add the fix here and generate a full patch release % only when a number of such issues have accumulated. This way we % lessen the impact on CTAN maintainers because for each tach % release we have to make and distribute also a matching % development release. % % \MaybeStop{\setlength\IndexMin{200pt} \PrintIndex } % % % \section{The Implementation} % % This file is meant to be loaded during format generation which is % why we give it the extension \texttt{.ltx}. % \begin{macrocode} %<*kernel> % \end{macrocode} % % \begin{macrocode} \def\LaTeXFirstAidDate{2024/02/29} \def\LaTeXFirstAidVersion{v1.1c} % \end{macrocode} % % \begin{macrocode} \ProvidesFile{latex2e-first-aid-for-external-files.ltx} [\LaTeXFirstAidDate\space \LaTeXFirstAidVersion\space LaTeX kernel fixes to external files and packages] % \end{macrocode} % % % \begin{macro}{\FirstAidNeededT} % This is a very simple help to ensure that we only apply first aid % to an unmodified package or class. It only works in the case the % file has already been loaded and the csname \cs{ver@\#1.\#2} got % defined (holding the current date, version, and short description % info). We then compare its content to a frozen string and make % the modification \verb=#3= only if both agree. If they differ we % assume that the package/class in question got updated by its % maintainer. % \begin{macrocode} \ExplSyntaxOn \cs_new:Npn\FirstAidNeededT#1#2#3{ \exp_args:Ncx\str_if_eq:onF{ver@#1.#2}{#3} { \typeout{==>~ First~ Aid~ for~ #1.#2~ no~ longer~ applied!^^J \@spaces Expected:^^J \@spaces\@spaces #3^^J \@spaces but~ found:^^J \@spaces\@spaces \use:c{ver@#1.#2}^^J \@spaces so~ I'm~ assuming~ it~ got~ fixed. } } \exp_args:Ncx\str_if_eq:onT{ver@#1.#2}{#3} } \ExplSyntaxOff % \end{macrocode} % \end{macro} % % \begin{macrocode} % % \end{macrocode} % % % \subsection{The \pkg{filehook} package first aid} % % The \pkg{filehook} package implements hooks into file loading % commands. These days this is already provided by the kernel % albeit not with the same user interface. Until that package gets % updated (to use the kernel interfaces) we provide a % substitution. This does not offer all hooks from \pkg{filehook} % but all that have been used in packages available in \TeX{} Live. % % Note that this doesn't fix \pkg{currfile} because that package % uses \pkg{filehook} but relies on the internals of the old % implementation. % % The package has now got an update so we aren't activating the % first aid. However, at the moment it basically bypasses the new % hook mechanism and puts the old hooks in thereby disabling, for % example, the possibility to re-order code through rules. % % We therefore keep \texttt{filehook-ltx.sty} around as a guideline % for further updates. % % Replacing \pkg{filehook} with a leaner version would then work % like this: % \begin{macrocode} %<*kernel> %\declare@file@substitution{filehook.sty}{filehook-ltx.sty} % % \end{macrocode} % % What follows is a simplified (partial) implementation of the \pkg{filehook} % interfaces. % Not implemented are: %\begin{verbatim} % \AtBeginOfFiles \AtEndOfFiles % \AtBeginOfInputs \AtEndOfInputs % \AtBeginOfInputFile \AtEndOfInputFile %\end{verbatim} % % \begin{macrocode} %<*filehook-ltx> % \end{macrocode} % % \begin{macrocode} \newcommand\AtBeginOfEveryFile [1] {\AddToHook{file/before}{#1}} \newcommand\AtEndOfEveryFile [1] {\AddToHook{file/after}{#1}} % \end{macrocode} % % \begin{macrocode} \newcommand\AtBeginOfIncludes [1] {\AddToHook{include/before}{#1}} \newcommand\AtEndOfIncludes [1] {\AddToHook{include/end}{#1}} \newcommand\AfterIncludes [1] {\AddToHook{include/after}{#1}} % \end{macrocode} % % \begin{macrocode} \newcommand\AtBeginOfPackages [1] {\AddToHook{package/before}{#1}} \newcommand\AtEndOfPackages [1] {\AddToHook{package/after}{#1}} % \end{macrocode} % % \begin{macrocode} \newcommand\AtBeginOfClasses [1] {\AddToHook{class/before}{#1}} \newcommand\AtEndOfClasses [1] {\AddToHook{class/after}{#1}} % \end{macrocode} % % \begin{macrocode} \newcommand\AtBeginOfFile [2] {\AddToHook{file/#1/before}{#2}} \newcommand\AtEndOfFile [2] {\AddToHook{file/#1/after}{#2}} % \end{macrocode} % % Some commands offered a starred form % \begin{macrocode} \DeclareDocumentCommand \AtBeginOfPackageFile {smm} {\IfBooleanTF{#1}% {\@ifpackageloaded{#2}% {#3}% {\AddToHook{package/#2/before}{#3}}}% {\AddToHook{package/#2/before}{#3}}% } % \end{macrocode} % % \begin{macrocode} \DeclareDocumentCommand \AtEndOfPackageFile {smm} {\IfBooleanTF{#1}% {\@ifpackageloaded{#2}% {#3}% {\AddToHook{package/#2/after}{#3}}}% {\AddToHook{package/#2/after}{#3}}% } % \end{macrocode} % % Are the * forms here of any use? I know they are use 3--4 times % on CTAN but I wonder if those are real or mistaken usages. % \begin{macrocode} \DeclareDocumentCommand \AtBeginOfClassFile {smm} {\IfBooleanTF{#1}% {\@ifclassloaded{#2}% {#3}% {\AddToHook{class/#2/before}{#3}}}% {\AddToHook{class/#2/before}{#3}}% } \DeclareDocumentCommand \AtEndOfClassFile {smm} {\IfBooleanTF{#1}% {\@ifclassloaded{#2}% {#3}% {\AddToHook{class/#2/after}{#3}}}% {\AddToHook{class/#2/after}{#3}}% } % \end{macrocode} % % \begin{macrocode} \newcommand\AtBeginOfIncludeFile [2] {\AddToHook{include/#1/before}{#2}} \newcommand\AtEndOfIncludeFile [2] {\AddToHook{include/#1/end}{#2}} \newcommand\AfterIncludeFile [2] {\AddToHook{include/#1/after}{#2}} % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \begin{macrocode} %<*kernel> % \end{macrocode} % % \subsection{The \pkg{dinbrief} class first aid} % % Again a case of a no longer correct \cs{endgroup} in document. % Here the fix is simply though. % \begin{macrocode} \AddToHook{file/dinbrief.cls/after}[firstaid]{% \FirstAidNeededT{dinbrief}{cls}{2000/03/02 LaTeX2e class}% {\AddToHook{env/document/begin}{\begingroup}}% } % \end{macrocode} % % % \subsection{The \pkg{unicode-math} package first aid} % % If \pkg{unicode-math} is used together with \pkg{doc} there is a % problem because it changes the mathcodes without adjusting the % use in \pkg{doc} that assume standard settings. Could be fixed on % either side, but as \pkg{unicode-math} is derivating from the % standard, the right place is probably a fix in this package. For % now we do it here. See github/820. % \begin{macrocode} \AddToHook{package/unicode-math/after}{% \AddToHook{cmd/mod@math@codes/after}{\mathcode`\|=28796 }} % \end{macrocode} % % % % % \subsection{The \pkg{pgfpages} and \pkg{pgfmorepages} first aid} % % \pkg{pgfpages} alters the \cs{shipout} primitive to support % multiple page up scenarios. If used together with \pkg{atbegshi} % that worked because the alterations done by \pkg{atbegshi} came % later and so used the new definition provide by % \pkg{pgfpages}. Now that the code from \pkg{atbegshi} is already % in the kernel this further redefinition doesn't happen with the % result that the change to \cs{shipout} comes to late and % breaks the kernel processes. % % \begin{macrocode} \ExplSyntaxOn \AddToHook{file/pgfpages.sty/after}[firstaid]{% % \end{macrocode} % Undo overwriting \cs{shipout}: % \begin{macrocode} \cs_gset_eq:NN \shipout \pgfpages@originalshipout % \end{macrocode} % Instead overwrite the L3 programming layer name of the % primitive. This is really an absolute no-go, but for now the % simplest solution to keep the original code running. % % It will be replaced when the ``configuration points'' interface % for \LaTeX{} becomes available. At that point the package will be % able to set up a different strategy for doing shipouts and % without the need to overrite a primitive (which it did in the % past and which we do below) and then this code here can be taken % out again. % \begin{macrocode} \cs_set_eq:NN \pgfpages@originalshipout \tex_shipout:D \cs_set_eq:NN \tex_shipout:D \pgfpages@interceptshipout } \ExplSyntaxOff % \end{macrocode} % % Same issue with \pkg{pgfmorepages} but slightly different implementation (sigh). % % \begin{macrocode} \ExplSyntaxOn \AddToHook{file/pgfmorepages.sty/after}[firstaid]{ \cs_set_nopar:Npn \pgfhookintoshipout { \cs_set_eq:NN \pgfpages@originalshipout \tex_shipout:D \cs_set_eq:NN \tex_shipout:D \pgfpages@interceptshipout } } \ExplSyntaxOff % \end{macrocode} % % \subsection{The \pkg{babel} package} % % Turn off the \pkg{babel} hack. % \begin{macrocode} \AddToHook{file/babel.sty/before}[firstaid]{\def\BabelCaseHack{}} % \end{macrocode} % % % \subsection{The \pkg{songs} package first aid} % % The songs package uses \cs{obeylines} and redefines \cs{par} for special effect. % this no longer works in \LaTeX{} 2022-06-01 (gh issue 367). The following % fixes at least one failure. % \begin{macrocode} \AddToHook{file/songs.sty/after}[firstaid]{% \FirstAidNeededT{songs}{sty}{2018/09/12 v3.1 Songs package}% {% \renewcommand\SB@obeylines{% \let\obeyedline\SB@par% \obeylines% \let\@par\SB@@par% }}% } % \end{macrocode} % % \subsection{The \pkg{crop} package first aid} % % The crop packages fails currently due to two \LaTeX{} changes: % It doesn't know that \cs{stockheight} and \cs{stockwidth} % are now defined, and doesn't take into account that \cs{rlap} % is robust (https://github.com/rrthomas/crop/issues/2). % The first is addressed by setting the dimension if they are zero or % negative. For the second we locally change the meaning of \cs{protect} % % \begin{macrocode} \AddToHook{file/crop.sty/after}[firstaid]{% \FirstAidNeededT{crop}{sty}{2017/11/19 1.10 crop marks (mf)}% {% \ifdim\stockwidth > 0pt \else \stockwidth\paperwidth \fi \ifdim\stockheight > 0pt \else \stockheight\paperheight \fi \renewcommand*\CROP@genreflect[1]{% \leavevmode \dimen0\CROP@horigin \kern2\dimen0 \begingroup \set@typeset@protect %change protect \reflectbox{% \hb@xt@\paperwidth{% \vbox to\paperheight{% #1% \vss }% \hss }% }% \endgroup } }% } % \end{macrocode} % \begin{macrocode} % % \end{macrocode} % % % \begin{macrocode} %<*kernel> % \end{macrocode} % % % % % \subsection{The \pkg{bigfoot} first aid} % % The \pkg{bigfoot} packages makes the assumption that two % \cs{newinsert} allocations have a recognisable order in their % numbers, the second one has a lower number. This was correct in % the classic \TeX{} implementation but with the extended % allocation possibilities of all modern engines is no longer the % case and there is a point where the allocations take a ``jump'' % breaking the odering assumption. These days we are fairly close % to that point and depending on how many packages are loaded % before \pkg{bigfoot} the package breaks. % % This firstaid therefore jumps over the problematical point by % pushing the count allocation to a safe value if necessary. % \begin{macrocode} \AddToHook{file/bigfoot.sty/after}{% \ifnum\count10<\insc@unt \global\count10=\insc@unt \fi % \end{macrocode} % We also correct a bug that \pkg{bigfoot} tries to shift mark % registers, but in \LaTeX{} (at least since 2015) the allocation % number is not 266, so it does that to a random number of mark % registers (which sometimes blows up depending on the value in 266). % \begin{macrocode} \def\FN@allmarks#1{\@elt{#1}% \ifnum#1<\count256 %<--- problem: 266 isn't the counter for marks \expandafter\FN@allmarks\expandafter{\number\numexpr#1+\@ne}% \fi}% } % \end{macrocode} % % % % % \subsection{\pkg{ulem} first aid} % % In 2020 we fixed various kernel commands to accept \pkg{calc} % syntax. The \pkg{ulem} package redefines some internals and that % now conflicts with the new definitions as they involve an extra % group. So we alter the definition of \cs{@hspace} if \pkg{ulem} % was loaded. This is not perfect, obviously, so it will go out the % moment \pkg{ulem} gets adjusted. % % \begin{macrocode} \AddToHook{file/ulem.sty/after}[firstaid]{% \def\@hspace#1{\begingroup\setlength\skip@{#1}% \edef\x{\endgroup\hskip\the\skip@\relax}\x}% } % \end{macrocode} % % % \subsection{\pkg{varwidth} first aid} % % The \pkg{varwidth} package does a lot of low-level paragraph % manipulation assuming traditional \TeX{} paragraphs. However, with % the paragraph hooks we end up with one extra glue 0pt item on the % vertical list and if that isn't removed then the package doesn't % find its penalties. % % So this needs to be removed as well by adding an additional % \cs{unskip}. % % \begin{macrocode} \AddToHook{file/varwidth.sty/after}[firstaid]{% \FirstAidNeededT{varwidth}{sty}% {2009/03/30 ver 0.92; \space Variable-width minipages}% {% \def\@vwid@sift{% \skip@\lastskip\unskip \ifdim\lastskip=\z@\unskip\fi % <---- the first aid here (not just unskip) \dimen@\lastkern\unkern \count@\lastpenalty\unpenalty \setbox\z@\lastbox \ifvoid\z@ \advance\sift@deathcycles\@ne \else \sift@deathcycles\z@ \fi \ifnum\sift@deathcycles>33 \let\@vwid@sift\relax \PackageWarning{varwidth}{Failed to reprocess entire contents}% \fi \ifnum\count@=\@vwid@preeqp \@vwid@eqmodefalse\fi \ifnum\count@=\@vwid@posteqp \@vwid@eqmodetrue\fi \ifnum\count@=\@vwid@toppen % finished \let\@vwid@sift\relax \else\ifnum\count@=\@vwid@offsets \@vwid@setoffsets \else \ifnum\count@=\@vwid@postw \else \@vwid@resetb % reset box \z@ or measure it \fi \@vwid@append \fi\fi \@vwid@sift}% }% } % \end{macrocode} % % \subsection{The \pkg{german} class first aid} % % Handling of \cs{protected} UTF-8 % \begin{macrocode} \AddToHook{file/german.sty/after}[firstaid]{% \FirstAidNeededT{german}{sty}{1998/07/08 v2.5e Support for writing german texts (br)} {% \let\grmn@active@dq@\@active@dq \def\@active@dq{\protect\grmn@active@dq@}% \germanTeX }% } % \end{macrocode} % % \begin{macrocode} \AddToHook{file/ngerman.sty/after}[firstaid]{% \FirstAidNeededT{ngerman}{sty}{1998/07/08 v2.5e Support for writing german texts (br)} {% \let\grmn@active@dq@\@active@dq \def\@active@dq{\protect\grmn@active@dq@}% \ngermanTeX }% } % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % \subsection{The \pkg{underscore} first aid} % % The \pkg{underscore} package makes the underscore active. This means that the % underscore can not be used in label and references unless the package option \texttt{strings} is used % (which patches a selection of problematic commands like \cs{label} and \cs{ref}) % or \pkg{babel} is used which redefines\footnote{unless the recommended option \texttt{safe=none} is used} % a selection of problematic commands like \cs{@testdef} or \cs{@newl@bel}. % % With the new property commands the work-around do not work. We therefore make the % underscore protected and use \cs{ifincsname} to allow its use in csnames. % % \begin{macrocode} %<*underscore-ltx> \ProvidesPackage{underscore-ltx}[2023/09/20 LaTeX firstaid to make underscore protected ] \begingroup \catcode`\_=\active \protected\gdef _{% \ifincsname % \string_% \else \ifx\protect\@typeset@protect \ifmmode \sb \else \BreakableUnderscore \fi \else \ifx\protect\@unexpandable@protect \noexpand_% \else \protect_% \fi\fi \fi } \global\let\ActiveUnderscore=_ \endgroup % % \end{macrocode} % \begin{macrocode} %<*kernel> \AddToHook{file/underscore.sty/after}[firstaid]{% \FirstAidNeededT{underscore}{sty}{2006/09/13}{\RequirePackage{underscore-ltx}}} % % \end{macrocode} % % \begin{macrocode} %<*kernel> % \end{macrocode} % % \subsection{The \pkg{acro} package first aid} % % The package does not declare a \texttt{prop}, which causes an issue with newer % routines in \pkg{expl3}. % \begin{macrocode} \AddToHook{package/acro/after}[firstaid]{% \FirstAidNeededT{acro}{sty}{2022/04/01 v3.8 typeset acronyms and other abbreviations (CN)} {\UseName{prop_new:c}{l__acro_tmpa_prop}}% } % \end{macrocode} % % \subsection{The \pkg{chemformula} package first aid} % % Package \pkg{chemformula} uses \pkg{l3keys2e} for option processing. % This used to be made available as \pkg{chemformula} also loads % \pkg{xfrac}, which loaded \pkg{l3keys2e}. However, \pkg{xfrac} has now % been updated to use the newer kernel method if available, so loading % \pkg{chemformula} fails. % \begin{macrocode} \AddToHook{package/chemformula/before}[firstaid]{% \RequirePackage{l3keys2e}% } % \end{macrocode} % % \subsection{The \pkg{chemnum} package first aid} % % The package does not declare a \texttt{prop}, which causes an issue with newer % routines in \pkg{expl3}. % \begin{macrocode} \AddToHook{package/chemnum/after}[firstaid]{% \FirstAidNeededT{chemnum}{sty}{2021/01/21 v1.3a a comprehensive approach for the numbering of chemical compounds (CN)} {\UseName{prop_new:c}{l__chemnum_tmpa_prop}}% } % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \Finale %