% \iffalse meta-comment % %% File: latex-lab-firstaid.dtx (C) Copyright 2023-2026 LaTeX Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this % license or (at your option) any later version. The latest version % of this license is in the file % % https://www.latex-project.org/lppl.txt % % % The latex-lab bundle is developed in the LaTeX2e GitHub. % Issues may be reported at % % https://github.com/latex3/latex2e/issues % \def\ltlabfirstaiddate{2026-07-29} \def\ltlabfirstaidversion{0.85y} %<*driver> \DocumentMetadata{tagging=on,pdfstandard=ua-2} \documentclass{l3in2edoc} \EnableCrossrefs \CodelineIndex \begin{document} \DocInput{latex-lab-firstaid.dtx} \end{document} % % % \fi % % \title{The \textsf{latex-lab-firstaid} package\\ % Temporary patches to external packages needed for the tagging project} % \author{\LaTeX{} Project\thanks{Initial implementation done by Ulrike Fischer}} % \date{v\ltlabfirstaidversion\ \ltlabfirstaiddate} % % \maketitle % % \newcommand{\xt}[1]{\textsl{\textsf{#1}}} % \newcommand{\TODO}[1]{\textbf{[TODO:} #1\textbf{]}} % \newcommand{\docclass}{document class \marginpar{\raggedright document class % customizations}} % % \providecommand\hook[1]{\texttt{#1}} % % \begin{abstract} % \end{abstract} % % \section{Introduction} % % The following contains small temporary changes to external packages to avoid % errors with the new tagging code. % % Similar to the main firstaid package the goal is to remove the % patches once the packages have been updated. % % \changes{v0.85g}{2024/10/04}{Removed firstaid for blindtext. % No longer needed with new \cs{@doendpe} code.} % \changes{v0.85g}{2024/10/04}{Added firstaid for fancyvrb.} % \changes{v0.85n}{2025-10-12}{Added firstaid for pgf.} % \changes{v0.85t}{2026-03-12}{Switch from \texttt{x}- to \texttt{e}-type % expansion in expl3 code} % \changes{v0.85u}{2026-04-24}{Added firstaid for H-floats.} % \changes{v0.85u}{2026-04-24}{Removed microtype firstaid. No longer needed.} % % \section{Implementation} % % \begin{macrocode} %<*package> %<@@=tag> % \end{macrocode} % \begin{macrocode} \ProvidesPackage {latex-lab-testphase-firstaid} [% \ltlabfirstaiddate\space v\ltlabfirstaidversion\space Temporary patches to external packages needed for the tagging project] % \end{macrocode} % \begin{macro}[no-user-doc]{\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 \providecommand\FirstAidNeededT[3]{ \exp_args:Nce\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:Nce\str_if_eq:onT{ver@#1.#2}{#3} } % \end{macrocode} % \end{macro} % \subsection{tikz/pgf} % ti\textit{k}z inputs libraries with the primitive \cs{input} command. This means that % these libraries are not listed in the file list written by \cs{listfiles} and the new % tagging status report created with the \texttt{check-tagging-status} key. % % We therefore redefine one \texttt{pgf} command to use the \LaTeX{} \cs{input} command. % Check https://github.com/pgf-tikz/pgf/issues/1424 for changes. % \begin{macrocode} \AddToHook{package/pgfrcs/after} {\def\pgfutil@InputIfFileExists#1#2#3{\pgfutil@IfFileExists{#1}{\input{#1}\relax#2}{#3}}} % \end{macrocode} % % \subsection{AMS classes} % % Instead of putting the first aid code into the format we now % write it to files that are loaded after the class has been loaded. % \begin{macrocode} \AddToHook{class/amsbook/after}[latex-lab-firstaid]{\input{latex-lab-firstaid-amsbook.ltx}} \AddToHook{class/amsart/after} [latex-lab-firstaid]{\input{latex-lab-firstaid-amsart.ltx}} \AddToHook{class/amsproc/after}[latex-lab-firstaid]{\input{latex-lab-firstaid-amsproc.ltx}} % \end{macrocode} % % \begin{macrocode} % %<*amscls> \ExplSyntaxOn % \end{macrocode} % % The amsart, amsbook and amsproc classes do not use \cs{@author} % to store the author list but a command \cs{authors}. To be able % to nevertheless use the authors in the % xmp-metadata we map \cs{@author} to this new command. % % The authors are set with a trivlist, this leads to faulty spacing % and wrong tagging. This is not yet handled here, but an example % how to correct this is in the test-amsart-title test. % \begin{macrocode} \def\@author{\authors} % \end{macrocode} % % % % In these classes the abstract is stored in a \cs{vbox}, as it % ends with a list an explicit \cs{par} is needed. % \changes{v0.85i}{2025/01/26}{Add missing \cs{par} to abstract env (gh/1641)} % \begin{macrocode} \renewenvironment{abstract}{% \ifx\maketitle\relax \ClassWarning{\@classname}{Abstract~ should~ precede~ \protect\maketitle\space in~ AMS~ document~ classes;~ reported}% \fi \global\setbox\abstractbox=\vtop \bgroup \normalfont\Small \list{}{\labelwidth\z@ \leftmargin3pc \rightmargin\leftmargin \listparindent\normalparindent \itemindent\z@ \parsep\z@ \@plus\p@ \let\fullwidthdisplay\relax }% \item[\hskip\labelsep\scshape\abstractname.]% }{% \endlist \par % <--- added \egroup \ifx\@setabstract\relax \@setabstracta \fi } % \end{macrocode} % % % \changes{v0.85w}{2026/05/21}{Use new \cs{newtheoremstyle} with AMS classes} % % In the ams classes's \cs{newtheoremstyle} has different defaults % compared to the standalone \pkg{amsthm} package. Therefore the % classes have their own implementation of the command that we need % to overwrite as well. % % Provide a saved version of the \cs{newtheoremstyle} code in the % format to be able to reinstall it after the class got loaded. % \begin{macrocode} % %<+package> \cs_set_eq:NN \newtheoremstyle@saved \newtheoremstyle %<*amscls> % \end{macrocode} % % Then reinstall it and also change the default for the vertical space. % \begin{macrocode} \cs_set_eq:NN \newtheoremstyle \newtheoremstyle@saved \tl_set:Nn \newtheoremstyle@vspace@default { .5\baselineskip \@plus .2\baselineskip \@minus .2\baselineskip } % \end{macrocode} % % % % % \subsubsection{Headings} % % \changes{0.85r}{2026-01-06} % {Add tagging support for headings in ams-classes, tagging issue \#970} % \changes{v0.85u}{2026-04-24}{Adapt keys to changes in sec-template.} % \changes{0.85y}{2026-07-11}{Provide proper heading instances for all % ams classes (tagging/1477)} % % The classes redefine \cs{@startsection} and define their own % heading commands which are not tagging compatible. % This code is therefore disabled and replaced by standard % definitions that process the heading arguments and call a % suitable template instance. The top-level definitions are % identical for all classes (only the heading instances then % differ). % % \begin{macrocode} \DeclareDocumentCommand \part {s ={shorttitle}o m} { \ParseLaTeXeHeading {part} {#1} {#2} {#3} } % \end{macrocode} % % Chapters only exist in \cls{amsbook} and their top-level % definition is also slightly special as we need a different % heading instance for numbered and unnumbered chapters. % \begin{macrocode} %<*amsbook> \DeclareDocumentCommand \chapter {s ={shorttitle}O{} m} { \IfBooleanTF{#1} { \ParseLaTeXeHeading {chapter*} {#1} {#2} {#3} } { \ParseLaTeXeHeading {chapter} {#1} {#2} {#3} } } % % \end{macrocode} % % \begin{macrocode} \DeclareDocumentCommand \section {s ={shorttitle}o m} { \ParseLaTeXeHeading {section} {#1} {#2} {#3} } % \end{macrocode} % % The \cs{specialsection} command is a variation of the % \texttt{section} layout so has its own heading instance. % \begin{macrocode} \DeclareDocumentCommand \specialsection {s ={shorttitle}o m} { \ParseLaTeXeHeading {specialsection} {#1} {#2} {#3} } % \end{macrocode} % % \begin{macrocode} \DeclareDocumentCommand \subsection {s ={shorttitle}o m} { \ParseLaTeXeHeading {subsection} {#1} {#2} {#3} } % \end{macrocode} % % % \begin{macrocode} \DeclareDocumentCommand \subsubsection {s ={shorttitle}o m} { \ParseLaTeXeHeading {subsubsection} {#1} {#2} {#3} } % \end{macrocode} % % % \begin{macrocode} \DeclareDocumentCommand \paragraph {s ={shorttitle}o m} { \ParseLaTeXeHeading {paragraph} {#1} {#2} {#3} } % \end{macrocode} % % % \begin{macrocode} \DeclareDocumentCommand \subparagraph {s ={shorttitle}o m} { \ParseLaTeXeHeading {subparagraph} {#1} {#2} {#3} } % \end{macrocode} % % % % The heading template instances have some subtle differences in the % different AMS classes. We therefore set all of them up by % document class, even though some of the code is the same. % % \begin{macrocode} %<*amsbook> % \end{macrocode} % % % \begin{macrocode} \DeclareInstance{heading}{part}{display} { , name = part , level = -1 , placement = page , start-code = \cleardoublepage \thispagestyle{empty} \null \vfil \markboth{}{} , final-code = \vfil \vfil \newpage\newpage \thispagestyle{empty} , mark-cmd = \partmark {#1} , heading-decls = \centering\huge\bfseries , headformat-instance = part , prefix = \partname , number-format = \theheading . , title-decls = \Huge } \DeclareInstance{headformat}{part}{display} { prefix-number-sep = \WordSpaceAmount{1}, } % \end{macrocode} % % Current heading templates aren't flexible enough and do not % properly support altering the layout for unnumbered headings % compared to their numbered counterparts. For this reason we have % two heading instances, one for \cs{chapter} and one for \cs{chapter*}. % % \begin{macrocode} \DeclareInstance{heading}{chapter}{display} { , name = chapter , level = 0 , mark-cmd = \chaptermark {#1} , para-indent = true , placement = top , after-penalty-vspace = 32pt , after-vspace = 22pt , heading-decls = \normalsize\mdseries\centering , headformat-instance = chapter , prefix = \MakeUppercase{\chaptername} , number-format = \thechapter , title-decls = \fontsize{\@xivpt}{18} \bfseries , contents-extra = \addtocontents{lof}{\protect\addvspace{10\p@}} \addtocontents{lot}{\protect\addvspace{10\p@}} } % \end{macrocode} % % \begin{macrocode} \DeclareInstanceCopy{heading}{chapter*}{chapter} \EditInstance{heading}{chapter*}{ after-penalty-vspace = 62pt } % \end{macrocode} % % \begin{macrocode} \DeclareInstance{headformat}{chapter}{display} { , heading-indent = 0pt %% <-- needed? , number-title-sep = 18pt } % \end{macrocode} % % % \begin{macrocode} \DeclareInstance{heading}{section}{display} { , name = section , level = 1 , mark-cmd = \sectionmark{#1} , para-indent = true , before-vspace = 0.7\linespacing plus \linespacing , after-vspace = 0.5\linespacing , heading-decls = \normalfont \bfseries \centering , headformat-instance = section , number-format = \theheading . , number-decls = \upshape } \DeclareInstance{headformat}{section}{hang} { number-title-sep = 0.5em, } % \end{macrocode} % % A \cs{specialsection} is like a \cs{section} with two changes in % the parameter settings. % \begin{macrocode} \DeclareInstanceCopy{heading}{specialsection}{section} \EditInstance{heading}{specialsection} { , before-vspace = 2\linespacing plus \linespacing , heading-decls = \large \scshape \centering } % \end{macrocode} % % \begin{macrocode} \DeclareInstance{heading}{subsection}{runin} { , name = subsection , level = 2 , mark-cmd = \subsectionmark{#1} , before-vspace = 0.5\linespacing plus 0.7\linespacing , after-vspace = 0.5em , heading-decls = \normalfont \bfseries , headformat-instance = subsection , number-format = \theheading . , number-decls = \upshape } \DeclareInstance{headformat}{subsection}{runin} { , number-title-sep = 0.5em , title-format = #1 \AddPunctuation{.} , heading-indent = \normalparindent } % \end{macrocode} % % \begin{macrocode} \DeclareInstance{heading}{subsubsection}{runin} { , name = subsubsection , level = 3 , mark-cmd = \subsubsectionmark{#1} , before-vspace = 0pt , after-vspace = 0.5em , heading-decls = \normalfont \itshape , headformat-instance = subsubsection , number-format = \theheading . , number-decls = \upshape } \DeclareInstance{headformat}{subsubsection}{runin} { , number-title-sep = 0.5em , title-format = #1 \AddPunctuation{.} , heading-indent = \normalparindent } % \end{macrocode} % % \begin{macrocode} \DeclareInstance{heading}{paragraph}{runin} { , name = paragraph , level = 4 , mark-cmd = \paragraphmark{#1} , before-vspace = 0pt , after-vspace = \fontdimen2 \font , heading-decls = \normalfont , headformat-instance = paragraph , number-format = \theheading . , number-decls = \upshape } \DeclareInstance{headformat}{paragraph}{runin} { , number-title-sep = 0.5em , title-format = #1 \AddPunctuation{.} , heading-indent = \normalparindent } % \end{macrocode} % % \begin{macrocode} \DeclareInstance{heading}{subparagraph}{runin} { , name = subparagraph , level = 5 , mark-cmd = \subparagraphmark{#1} , before-vspace = 0pt , after-vspace = \fontdimen2\font , heading-decls = \normalfont , headformat-instance = subparagraph , number-format = \theheading . , number-decls = \upshape } \DeclareInstance{headformat}{subparagraph}{runin} { , number-title-sep = 0.5em , title-format = #1. } % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % % % % % % \begin{macrocode} %<*amsart> % \end{macrocode} % % The use of \cs{mdseries} in several of the instances is really % odd (and not done in \cls{amsbook} or \cls{amsproc}) but it is % what the current class generates as a layout, so we keep it that % way. % % \begin{macrocode} \DeclareInstance{heading}{part}{display} { , name = part , level = -1 % -1 or 0 ? , mark-cmd = \partmark{#1} , para-indent = true , before-vspace = \linespacing plus \linespacing , after-vspace = 0.5 \linespacing , heading-decls = \normalfont \bfseries \raggedright , headformat-instance = part , prefix = \partname , number-format = \theheading . , number-decls = \mdseries \upshape % proc: has just \upshape } \DeclareInstance{headformat}{part}{hang} { , number-title-sep = 0.5em } % \end{macrocode} % % \begin{macrocode} \DeclareInstance{heading}{section}{display} { , name = section , level = 1 , mark-cmd = \sectionmark{#1} , para-indent = true , before-vspace = 0.7\linespacing plus \linespacing , after-vspace = 0.5\linespacing , heading-decls = \normalfont \scshape \centering , headformat-instance = section , number-format = \theheading . , number-decls = \mdseries \upshape } \DeclareInstance{headformat}{section}{hang} { , number-title-sep = 0.5em } % \end{macrocode} % % The \cs{specialsection} command is a variation of the % \texttt{section} layout. % % \begin{macrocode} \DeclareInstanceCopy{heading}{specialsection}{section} \EditInstance{heading}{specialsection} { , before-vspace = \linespacing plus \linespacing , heading-decls = \normalfont \centering } % \end{macrocode} % % \begin{macrocode} \DeclareInstance{heading}{subsection}{runin} { , name = subsection , level = 2 , mark-cmd = \subsectionmark{#1} , before-vspace = 0.5\linespacing plus 0.7\linespacing , after-vspace = 0.5em , heading-decls = \normalfont \bfseries , headformat-instance = subsection , number-format = \theheading . , number-decls = \mdseries \upshape } \DeclareInstance{headformat}{subsection}{runin} { , number-title-sep = 0.5em , title-format = #1 \AddPunctuation{.} } % \end{macrocode} % % \begin{macrocode} \DeclareInstance{heading}{subsubsection}{runin} { , name = subsubsection , level = 3 , mark-cmd = \subsubsectionmark{#1} , before-vspace = 0.5\linespacing plus 0.7\linespacing , after-vspace = 0.5em , heading-decls = \normalfont \itshape , headformat-instance = subsubsection , number-format = \theheading . , number-decls = \mdseries \upshape } \DeclareInstance{headformat}{subsubsection}{runin} { , number-title-sep = 0.5em , title-format = #1 \AddPunctuation{.} } % \end{macrocode} % % \begin{macrocode} \DeclareInstance{heading}{paragraph}{runin} { , name = paragraph , level = 4 , mark-cmd = \paragraphmark{#1} , before-vspace = 0pt , after-vspace = \fontdimen2\font , heading-decls = \normalfont , headformat-instance = paragraph , number-format = \theheading . , number-decls = \mdseries \upshape } \DeclareInstance{headformat}{paragraph}{runin} { , number-title-sep = 0.5em , title-format = #1 \AddPunctuation{.} } % \end{macrocode} % % \begin{macrocode} \DeclareInstance{heading}{subparagraph}{runin} { , name = subparagraph , level = 5 , mark-cmd = \subparagraphmark{#1} , before-vspace = 0pt , after-vspace = \fontdimen2\font , heading-decls = \normalfont , headformat-instance = subparagraph , number-format = \theheading . , number-decls = \mdseries \upshape } \DeclareInstance{headformat}{subparagraph}{runin} { , number-title-sep = 0.5em , title-format = #1 \AddPunctuation{.} } % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % % % % % \begin{macrocode} %<*amsproc> % \end{macrocode} % % \begin{macrocode} \DeclareInstance{heading}{part}{display} { , name = part , level = -1 % -1 or 0 ? , mark-cmd = \partmark{#1} , para-indent = true , before-vspace = \linespacing plus \linespacing , after-vspace = 0.5 \linespacing , heading-decls = \normalfont \bfseries \raggedright , headformat-instance = part , prefix = \partname , number-format = \theheading . , number-decls = \upshape } \DeclareInstance{headformat}{part}{hang} { , number-title-sep = 0.5em } % \end{macrocode} % % \begin{macrocode} \DeclareInstance{heading}{section}{display} { , name = section , level = 1 , mark-cmd = \sectionmark{#1} , para-indent = true , before-vspace = 0.7\linespacing plus \linespacing , after-vspace = 0.5\linespacing , heading-decls = \normalfont \bfseries \centering , headformat-instance = section , number-format = \theheading . , number-decls = \upshape } \DeclareInstance{headformat}{section}{hang} { , number-title-sep = 0.5em } % \end{macrocode} % % The \cs{specialsection} command is a variation of the % \texttt{section} layout. % \begin{macrocode} \DeclareInstanceCopy{heading}{specialsection}{section} \EditInstance{heading}{specialsection} { , before-vspace = \linespacing plus \linespacing , heading-decls = \large \scshape \centering } % \end{macrocode} % % \begin{macrocode} \DeclareInstance{heading}{subsection}{runin} { , name = subsection , level = 2 , mark-cmd = \subsectionmark{#1} , before-vspace = 0.5\linespacing plus 0.7\linespacing , after-vspace = 0.5em , heading-decls = \normalfont \bfseries , headformat-instance = subsection , number-format = \theheading . , number-decls = \upshape } \DeclareInstance{headformat}{subsection}{runin} { , number-title-sep = 0.5em , title-format = #1 \AddPunctuation{.} , heading-indent = \normalparindent } % \end{macrocode} % % \begin{macrocode} \DeclareInstance{heading}{subsubsection}{runin} { , name = subsubsection , level = 3 , mark-cmd = \subsubsectionmark{#1} , before-vspace = 0.5\linespacing plus 0.7\linespacing , after-vspace = 0.5em , heading-decls = \normalfont \itshape , headformat-instance = subsubsection , number-format = \theheading . , number-decls = \upshape } \DeclareInstance{headformat}{subsubsection}{runin} { , number-title-sep = 0.5em , title-format = #1 \AddPunctuation{.} , heading-indent = \normalparindent } % \end{macrocode} % % \begin{macrocode} \DeclareInstance{heading}{paragraph}{runin} { , name = paragraph , level = 4 , mark-cmd = \paragraphmark{#1} , before-vspace = 0pt , after-vspace = \fontdimen2\font , heading-decls = \normalfont , headformat-instance = paragraph , number-format = \theheading . , number-decls = \upshape } \DeclareInstance{headformat}{paragraph}{runin} { , number-title-sep = 0.5em , title-format = #1 \AddPunctuation{.} , heading-indent = \normalparindent } % \end{macrocode} % % \begin{macrocode} \DeclareInstance{heading}{subparagraph}{runin} { , name = subparagraph , level = 5 , mark-cmd = \subparagraphmark{#1} , before-vspace = 0pt , after-vspace = \fontdimen2\font , heading-decls = \normalfont , headformat-instance = subparagraph , number-format = \theheading . , number-decls = \upshape } \DeclareInstance{headformat}{subparagraph}{runin} { , number-title-sep = 0.5em , title-format = #1 \AddPunctuation{.} } % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \begin{macrocode} \ExplSyntaxOff % %<*package> % \end{macrocode} % % % \begin{macrocode} \ExplSyntaxOff % \end{macrocode} % % % \subsection{verse} % % The \pkg{verse} package has its own definition of the % \env{verse} environment, which would tag correctly, except that % it is overwritten by the block code in the hook % \texttt{begindocument/before}. So the simplest way to make % tagging work is to reinstall the package version afterwards, % which is what we are doing here. % \begin{macrocode} \AddToHook{package/verse/after}[latex-lab-firstaid]{% \FirstAidNeededT{verse}{sty}{2014/05/10 v2.4b verse typesetting}% {% \AtBeginDocument{% \renewenvironment{verse}[1][\linewidth]{% \stepcounter{verse@envctr}% \setcounter{poemline}{0}\refstepcounter{poemline}% \setcounter{vslineno}{1}% \let\\=\@vscentercr \list{}{\itemsep \z@ \itemindent -\vindent \listparindent\itemindent \parsep \stanzaskip \ifdim #1 < \linewidth \rightmargin \z@ \setlength{\leftmargin}{\linewidth}% \addtolength{\leftmargin}{-#1}% \addtolength{\leftmargin}{-0.5\leftmargin}% \else \rightmargin \leftmargin \fi \addtolength{\leftmargin}{\vindent}}% \item[]% }% {\endlist}% }% }% } % \end{macrocode} % Of course, this means that the % optional argument of the environment then only accepts a length % value and not any more a key value list for altering the % environment settings. % % A more elaborate version could be something like this that allows % key/val and legacy interface. Or one could extend the list % template to support a \texttt{list-width} key. %\begin{verbatim} % \ExplSyntaxOn % \cs_new_protected:Npn \ExtractAndDropKey #1#2#3#4#5 { % \tl_set_eq:NN #4 \c_novalue_tl % or empty? % \keys_define:nn { #1 } { #2 .code:n = \tl_set:Nn #4{##1} } % \keys_set_known:nnN { #1 } { #3 } #5 % } % \ExplSyntaxOff % % % Change the env definition for verse matching verse.sty % % This keeps the verse.sty interface as it is and only adjusts the % % main environment to use the basic list env with the verse.sty % % specific settings. % \makeatletter % % \AddToHook{package/verse/after}{% % \AtBeginDocument{% % \RenewDocumentEnvironment{verse}{={verse-width}!O{\linewidth}}% % {% % \stepcounter{verse@envctr}% % \setcounter{poemline}{0}\refstepcounter{poemline}% % \setcounter{vslineno}{1}% % \let\\=\@vscentercr % % % \ExtractAndDropKey{verse}{verse-width}{#1}\@vswidth\@vsremainingkvlist % % If other keys have been specified but not verse-width we have no % % default for \@vswidth and need to set it again % \ExpandArgs{o}\IfNoValueT \@vswidth % {\def\@vswidth{\linewidth}}% % % % % This is a bit ugly but we can't stick \cs{@vsremainingkvlist} into % % the instance argument as keys are expected to be visible on % % top-level not hidden inside a macro. The alternative is to push % % in \verb=#1= but then the key/value \verb/verse-width=.../ is % % passed into the instance which is not known there (not harmful as % % it will get ignored but noticeably more and unnecessary % % processing). % % % \def\next##1{% % \UseInstance{blockenv}{list}% % {% % item-indent = -\vindent,% % para-indent = -\vindent,% % para-vspace = \stanzaskip,% % item-skip = 0pt,% % left-margin = (\linewidth-\@vswidth)/2+\vindent,% % right-margin = \ifdim\@vswidth<\linewidth 0pt % \else (\linewidth-\@vswidth)/2\fi,% % ##1% % }}% % \ExpandArgs{o}\next\@vsremainingkvlist % \item\relax % }{\endblockenv}% % }% % } % \makeatother %\end{verbatim} % % % \subsection{cleveref} % % The cleveref package redefines \cs{@makefntext} and this means that the patches in % the new footnote code fails. We use a hook instead. % \changes{v0.85h}{2024/10/16}{Remove redefinition of refstepcounter. It no longer uses % the hook.} % \begin{macrocode} \AddToHook{package/cleveref/after} { \let\@makefntext\cref@old@makefntext \AddToHook{cmd/@makefntext/before}{% \cref@constructprefix{footnote}{\cref@result}% \protected@edef\cref@currentlabel{% [footnote][\arabic{footnote}][\cref@result]% \p@footnote\@thefnmark}} } % \end{macrocode} % % \subsection{booktabs} % In some cases booktabs inserts a % \cs{multispan} into the table (through the commands \cs{@cmidruleb} % and \cs{@cmidrulea} and this then errors % with the tagging code. % This affects both tabular and longtable % (but longtable more as booktabs handles lines in longtable differently). % See also issue \url{https://github.com/latex3/tagging-project/issues/69} % % \changes{0.85u}{2026-04-24}{Use tagging sockets} % \begin{macrocode} \ExplSyntaxOn \AddToHook{package/booktabs/after} { \def\@cmidrulea{ \multispan\@cmidla &\multispan\@cmidlb \unskip\hskip\cmrkern@l { \UseTaggingSocket{tbl/leaders/begin} \CT@arc@\leaders\hrule \@height\@thisrulewidth\hfill\kern\z@} \hskip\cmrkern@r \UseTaggingSocket{tbl/leaders/end} \tbl_gdecr_row_count: \cr} \def\@cmidruleb{% \multispan\@cmidlb \unskip\hskip \cmrkern@l% { \UseTaggingSocket{tbl/leaders/begin} \CT@arc@\leaders\hrule \@height\@thisrulewidth\hfill\kern\z@} \hskip\cmrkern@r \UseTaggingSocket{tbl/leaders/end} \tbl_gdecr_row_count: \cr} } \ExplSyntaxOff % \end{macrocode} % % % \subsection{fancyvrb} % The firstaid adds first partial tagging support to the environments % of fancyvrb (inline verbatim is untested). % This supports then also packages like minted which internally uses fancyvrb % and classes like l3doc (where currently the verbatim environment based on fancyvrb % is overwritten by the block code). % The environments are surrounded by a \texttt{verbatim} structure, % every line by a \texttt{codeline} % structure. Line numbers are tagged as \texttt{Lbl}, inside of the % \texttt{codeline} structure. The frame lines are marked as artifact. % % \begin{macro}[no-user-doc]{\FV@LeaveVMode} % If we are in vmode we have to open a semantic-para structure, if we are % in hmode we have to set para mode to flattened before the fancyvrb code % issues the\cs{par}. The closing of the semantic-para structure is handled by the % doendpe code in the block code. % \changes{0.85u}{2026-04-24}{Use tagging sockets} % \begin{macrocode} \ExplSyntaxOn \AddToHook{package/fancyvrb/after} { \def\FV@LeaveVMode{% \if@noskipsec \leavevmode \else \if@FV@ResetMargins\if@inlabel\leavevmode\fi\fi \fi \ifvmode \@noparlisttrue \UseTaggingSocket{para/semantic/begin}{} \else \tagpdfsetup{para/flattened=true} \@noparlistfalse \unskip\par \fi } % \end{macrocode} % \end{macro} % % \begin{macro}[no-user-doc]{\FV@List} % At the begin of the list code we have to tag the frame as artifact % and start the \texttt{verbatim} structure % \begin{macrocode} \def\FV@List#1{% \begingroup \FV@UseKeyValues \FV@LeaveVMode \if@inlabel\else\setbox\@labels=\box\voidb@x\fi \FV@ListNesting{#1}% \FV@ListParameterHook \FV@ListVSpace \FV@SetLineWidth \FV@InterLinePenalty \let\FV@ProcessLine\FV@ListProcessLine@i \FV@CatCodes \FV@FormattingPrep \FV@ObeyTabsInit \cs_if_exist:NT \FV@BeginListFrame { \UseTaggingSocket{mc}{artifact}{\FV@BeginListFrame} } \UseTaggingSocket{struct/begin}{tag=\UseStructureName{block/verbatim}} } % \end{macrocode} % \end{macro} % \begin{macro}[no-user-doc]{\FV@EndList} % At the end of the list code we close the \texttt{verbatim} structure and % tag the frame as artifact. % \begin{macrocode} \def\FV@EndList{% \FV@ListProcessLastLine \UseTaggingSocket{struct/end} \cs_if_exist:NT \FV@EndListFrame { \UseTaggingSocket{mc}{artifact}{\FV@EndListFrame} } \@endparenv \endgroup \@endpetrue } % \end{macrocode} % \end{macro} % % \begin{macro}[no-user-doc]{\FV@ListProcessLine} % At last the tagging of the code lines. Here we have to tag also % numbers and frame parts if they exist. % \begin{macrocode} \def\FV@ListProcessLine#1{% \hbox to \hsize{% \kern\leftmargin \hbox to \linewidth{% \UseTaggingSocket{struct/begin}{tag=\UseStructureName{block/verbatim/codeline}} \cs_if_exist:NT \FV@LeftListNumber { \UseTaggingSocket{struct-mc}{tag=\UseStructureName{block/verbatim/linenumber}} { \FV@LeftListNumber } } \cs_if_exist:NT \FV@LeftListFrame { \UseTaggingSocket{mc}{artifact}{\FV@LeftListFrame} } \UseTaggingSocket{mc}{}{\FancyVerbFormatLine{#1}}% \UseTaggingSocket{struct/end}\hss \cs_if_exist:NT \FV@RightListFrame { \UseTaggingSocket{mc}{artifact}{\FV@RightListFrame} } \cs_if_exist:NT \FV@RightListNumber { \UseTaggingSocket{struct-mc}{tag=\UseStructureName{block/verbatim/linenumber}} { \FV@RightListNumber } } } \hss}} } \ExplSyntaxOff % \end{macrocode} % \end{macro} % % \subsection{The \pkg{float} package first aid} % % The float package has a number of incompatibilites: % \begin{itemize} % \item Restyling floats with \cs{restylefloat} breaks the tagging tagging support. % \item New float types created with \cs{newfloat} are not properly tagged (tagging issue 890) % \item Non-floating floats using the \texttt{H} placement are not properly tagged. % \end{itemize} % The following firstaid addresses the last problem. % A flaw is that if the float is inside a paragraph and followed % by text there the text is tagged as a new semantic-para structure. % TODO % \begin{macrocode} \ExplSyntaxOn \AddToHook{package/float/after}[firstaid] { \@@_firstaid_float_patch_H: } \cs_new_protected:Npn \@@_firstaid_float_patch_H: { \NewTaggingSocket{float/H/begin}{1} \NewTaggingSocketPlug{float/H/begin}{default} { \mode_if_horizontal:T {\tag_mc_end_push: \tag_struct_end:} \tag_struct_begin:n {tag=\UseStructureName{float/##1}} } \AssignTaggingSocketPlug{float/H/begin}{default} \NewTaggingSocket{float/H/end}{0} \NewTaggingSocketPlug{float/H/end}{default} { \tag_struct_end: \mode_if_horizontal:T { \tag_struct_begin:n {tag=\UseStructureName{para/textblock}} \tag_mc_begin_pop:n {} } } \AssignTaggingSocketPlug{float/H/end}{default} % \end{macrocode} % and here the redefinitions of the commands of \pkg{float} % \begin{macrocode} \def\@float@HH##1[H]{\UseTaggingSocket{float/H/begin}{##1}% \expandafter\let\csname end##1\endcsname\float@endH \let\@currbox\float@box \def\@captype{##1}\setbox\@floatcapt=\vbox{}% \expandafter\ifx\csname fst@##1\endcsname\relax \@flstylefalse\else\@flstyletrue\fi \setbox\@currbox\color@vbox\normalcolor \vbox\bgroup \hsize\columnwidth \@parboxrestore \@floatboxreset \@setnobreak \ignorespaces} \renewcommand\float@endH{\@endfloatbox\UseTaggingSocket{float/H/end} \vskip\intextsep \if@flstyle\setbox\@currbox\float@makebox\columnwidth\fi \box\@currbox\vskip\intextsep\relax} } \ExplSyntaxOff % \end{macrocode} % \subsection{The \pkg{apacite} firstaid} % The apacite package redefines \cs{@lbibitem} and removes the arguments. % This means that the patching with a generic hook with arguments fails. So we readd the argument. % \changes{0.85x}{2026-06-08}{Correct braces around argument.} % \begin{macrocode} \AddToHook{package/apacite/after} {\if@APAC@natbib@apa\def\@lbibitem[#1]#2{\NAT@swatrue\orig@nat@@@@lbibitem[#1]{#2}}\fi} % \end{macrocode} % \begin{macrocode} % % \end{macrocode}