% \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-04-24}
\def\ltlabfirstaidversion{0.85u}

%<*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.}
% \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}
% 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}
% \changes{v0.85u}{2026-04-24}{Adapt keys to changes in sec-template.}  
%    \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
      , heading-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}
    {
      , heading-indent   = 0pt
      , 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
     , heading-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,
      heading-decls  = \normalfont \bfseries \raggedright,
      headformat-instance  =  part-@startsection,
      number-format  =  \partname\space\theheading.
     }
   \DeclareInstance{headformat}{part-@startsection}{hang}
    {heading-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}
%  In these classes the abstract is stored in a \cs{vbox}, as it ends with a list
%  an explicit \cs{par} is needed.
%    \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 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 text-unit 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 text-unit 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 text-unit 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}
%
%    \begin{macrocode}
%</package>
%    \end{macrocode}
