% \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-01-19}
\def\ltlabfirstaidversion{0.85s}

%<*driver>
\DocumentMetadata{tagging=on,pdfstandard=ua-2}
\documentclass{l3in2edoc}

\EnableCrossrefs
\CodelineIndex
\begin{document}
  \DocInput{latex-lab-firstaid.dtx}
\end{document}
%</driver>
%
% \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 followings 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.}
% \section{Implementation}
%
%    \begin{macrocode}
%<*package>
%<@@=tag>
%    \end{macrocode}
%    \begin{macrocode}
\ProvidesPackage {latex-lab-testphase-firstaid} [%
   \ltlabfirstaiddate\space v\ltlabfirstaiddate\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: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}
}
%    \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}
% 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}
\AddToHook{class/amsart/after}
 {\def\@author{\authors}}
\AddToHook{class/amsbook/after}
 {\def\@author{\authors}}
\AddToHook{class/amsproc/after}
 {\def\@author{\authors}}  
%    \end{macrocode}
%
% The classes redefine \cs{@startsection} and define their own heading commands
% which are not tagging compatible. The template code will reinstate the new 
% \cs{@startsection} and so handle the headings using it. But we also need to 
% redefine \cs{chapter} and \cs{part}. The following does not try to create exactly
% the same design, only near enough. This will not properly handle \cs{specialsection}. 
% \changes{0.85r}{2026-01-06}
%   {Add tagging support for headings in ams-classes, tagging issue \#970}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_firstaid_amsbook_heading:
 {
  \DeclareDocumentCommand \chapter {s ={shorttitle}o m}
      {\ParseLaTeXeHeading {chapter}{##1} {##2} {##3}}       
  \DeclareInstance{heading}{chapter}{display}
    {
      , name          = chapter
      , level         = 0
      , placement         = top
      , after-penalty-sep = 32pt
      , after-sep     = 22pt
      , number-format = \MakeUppercase{\chaptername}\enspace \thechapter
      , decls         = \centering 
      , number-decls  = \normalsize\mdseries
      , title-decls   = \fontsize{\@xivpt}{18}\bfseries
      , headformat-instance = chapter
      , mark-cmd = \chaptermark{##1}
      , para-indent = true
      , contents-extra=  \addtocontents{lof}{\protect\addvspace{10\p@}}%
                        \addtocontents{lot}{\protect\addvspace{10\p@}}%
    }
  \DeclareInstance{headformat}{chapter}{display}
    {
      , indent        = 0pt
      , before-code   =
      , after-code    =
      , number-title-sep = 18pt 
    } 
  \DeclareDocumentCommand \part {s ={shorttitle}o m}
      { \ParseLaTeXeHeading {part} {##1} {##2} {##3} }        
  \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}              
     , number-format = \partname\nobreakspace\thepart
     , decls         = \centering\bfseries
     , number-decls  = \huge
     , title-decls   = \Huge
     , headformat-instance = display
     , mark-cmd      = \partmark {##1}
   }      
 }
\cs_new_protected:Npn\@@_firstaid_amsart_heading:
 {
   \DeclareInstance{heading}{part-@startsection}{display}
     {
      name=part,
      level=-1,
      mark-cmd=\partmark {##1},
      para-indent  = true,
      before-sep  = 12.0pt plus 12.0pt,
      after-penalty-sep  =  0pt,
      after-sep  =  6.0pt,
      decls  = \normalfont \bfseries \raggedright,
      headformat-instance  =  part-@startsection,
      number-format  =  \partname\space\theheading.
     } 
   \DeclareInstance{headformat}{part-@startsection}{hang}
    {indent  =  \z@,  number-title-sep  =  0.5em}
 }  
%    \end{macrocode}

% The redefinitions for amsbook:
%    \begin{macrocode}
\AddToHook{class/amsbook/after}[latex-lab-testphase-firstaid/amschap]
   {\@@_firstaid_amsbook_heading:}
%    \end{macrocode}
% amsart and amsproc can use the same definition:
%    \begin{macrocode}
\AddToHook{class/amsproc/after}[latex-lab-testphase-firstaid/amschap]
   {\@@_firstaid_amsart_heading:}
\AddToHook{class/amsart/after}[latex-lab-testphase-firstaid/amschap]
   {\@@_firstaid_amsart_heading:}  
%    \end{macrocode}
%
% \subsection{ams classes and amsthm}
% The amsart, amsbook and amsproc classes redefine the theorem code
% and this breaks the tagging added by the block code. The following
% reenables tagging. It does \emph{not} give a completly identical output
% (similar to the new theorem code, 
%  see \url{https://github.com/latex3/tagging-project/issues/715}). 
%  The code also does not try to use sockets yet, as the theorem definitions
%  in the block code don't do that yet either.  
% \changes{0.85l}{2025-07-02}{Removed \cs{tag_if_active} test, this errors with tagging=off}
%    \begin{macrocode}
\AddToHook{class/amsart/after}[latex-lab-testphase-firstaid/abstract]
          {
            \@@_firstaid_ams_abstract:
          }
\AddToHook{class/amsbook/after}[latex-lab-testphase-firstaid/abstract]
          {
            \@@_firstaid_ams_abstract:
          }
%    \end{macrocode}
%    
% \changes{v0.85i}{2025/01/26}{Add missing \cs{par} to abstract env (gh/1641)}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_firstaid_ams_abstract:
  {
\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
}
  }
\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 elabroate 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}
% 
% 
%    \begin{macrocode}
\ExplSyntaxOn
\AddToHook{package/booktabs/after} 
 {
  \def\@cmidrulea{
   \multispan\@cmidla
   &\multispan\@cmidlb
   \unskip\hskip\cmrkern@l
  {
   \tag_mc_begin:n{artifact}
   \CT@arc@\leaders\hrule \@height\@thisrulewidth\hfill\kern\z@}
   \hskip\cmrkern@r
   \tag_mc_end: \int_gdecr:N \g__tbl_row_int 
   \cr}

  \def\@cmidruleb{%
    \multispan\@cmidlb
    \unskip\hskip \cmrkern@l%
   {
    \tag_mc_begin:n{artifact}
    \CT@arc@\leaders\hrule \@height\@thisrulewidth\hfill\kern\z@}
    \hskip\cmrkern@r
    \tag_mc_end: \int_gdecr:N \g__tbl_row_int 
    \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 (this requires the block code, but firstaid should be used only with
% phase-III anyway). Line numbers are tagged as 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 text-unit structure, if we are 
% in hmode we have to set para mode to flattened before the fancyhdr code
% issues the\cs{par}. The closing of the text-unit structure is handled by the
% doendpe code in the block code.
%    \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
        \__tag_gincr_para_main_begin_int:
        \tag_struct_begin:n{tag=\l__tag_para_main_tag_tl}    
      \else
        \bool_set_true:N\l__tag_para_flattened_bool
        \@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
        {
         \tag_mc_begin:n{artifact}
         \FV@BeginListFrame
         \tag_mc_end:
        } 
      \tag_struct_begin:n{tag=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
      \tag_struct_end:
      \cs_if_exist:NT \FV@EndListFrame
        {
         \tag_mc_begin:n{artifact}
         \FV@EndListFrame
         \tag_mc_end:
        } 
      \@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{%
         \tag_struct_begin:n{tag=codeline}
          \cs_if_exist:NT \FV@LeftListNumber
           {
             \tag_struct_begin:n{tag=Lbl}
             \tag_mc_begin:n{} 
             \FV@LeftListNumber
             \tag_mc_end:
             \tag_struct_end:
           }
          \cs_if_exist:NT \FV@LeftListFrame
           {
             \tag_mc_begin:n{artifact}
             \FV@LeftListFrame
             \tag_mc_end:
           }
          \tag_mc_begin:n{}% 
          \FancyVerbFormatLine{#1}%
          \tag_mc_end:
          \tag_struct_end:\hss
          \cs_if_exist:NT \FV@RightListFrame
           {
             \tag_mc_begin:n{artifact}
             \FV@RightListFrame
             \tag_mc_end:
           }
          \cs_if_exist:NT \FV@RightListNumber
           {
             \tag_struct_begin:n{tag=Lbl}
             \tag_mc_begin:n{} 
             \FV@RightListNumber
             \tag_mc_begin:n{}
             \tag_struct_end:
           }      
          }
          \hss}}
  }          
\ExplSyntaxOff  
%    \end{macrocode}
%
% \subsection{The \pkg{microtype} package first aid}
% 
% The microtype package fails in kernel 2025/11 if tagging is active as due to the
% change to \cs{partokencontext} para tagging is triggered and then is unbalanced in 
% an unwanted place. We disable the tagging in this command.
% \changes{v0.85o}{2025/11/03}{Fix microtype to work with tagging 2025/11 kernel 
% https://github.com/schlcht/microtype/issues/59}
%    \begin{macrocode}
\AddToHook{package/microtype/after}[firstaid]{%
  \FirstAidNeededT{microtype}{sty}{2025/07/09 v3.2b
   Micro-typographical refinements
   (RS)}
  {%
    \def\MT@get@prot#1#2{%
      \begingroup
        \SuspendTagging{\MT@get@prot}%%added by firstaid
        \setbox\MT@tempbox\vbox{%
          \everypar{}%
          \parfillskip=\z@skip
          \hbadness\@M
          \clubpenalty\z@
          \widowpenalty\z@
          \interlinepenalty\z@
          \@newlistfalse
          \MT@prot@hook
          \begingroup
            \MT@noindent #1\relax\MT@csq@eqgroup
          \endgroup}%
        \vbadness=\@M
        \splittopskip=\z@
        \vfuzz=\maxdimen
        \setbox\MT@tempbox\vbox{%
          \ifvbox\MT@tempbox
            \global\setbox\MT@tempbox=\vsplit\MT@tempbox to \normalbaselineskip
            \unvbox\MT@tempbox
            \global\setbox\MT@tempbox=\lastbox
          \fi
        }%
      \endgroup
      \ifhbox\MT@tempbox
        \@tempdima=\@nameuse{#2marginkern}\MT@tempbox\relax
        \expandafter\ifdim\@tempdima=\z@ \else
          \leavevmode
          \MT@vinfo{|<< adding #2 margin kern for `#1':\MessageBreak
            \the\@tempdima \on@line}%
          \kern\@tempdima
        \fi
      \fi
    }}
 }
%    \end{macrocode}
% \end{macro}
%    \begin{macrocode}
%</package>
%    \end{macrocode}
%
%
%    \begin{macrocode}
%<*latex-lab>
\ProvidesFile{firstaid-latex-lab-testphase.ltx}
        [\ltlabfirstaiddate\space v\ltlabfirstaidversion\space
         latex-lab wrapper firstaid]

\RequirePackage{latex-lab-testphase-firstaid}

%</latex-lab>
%    \end{macrocode}
