summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2024-11-01 21:23:08 +0000
committerKarl Berry <karl@freefriends.org>2024-11-01 21:23:08 +0000
commit7c1ef55261d9d318083e5bb7b51f216a2fc62eba (patch)
tree9c65da88deb765787dc89b11356b9e66b6c464fa /Master/texmf-dist/source
parent98a2515429596389ba8b1c7bff761316a53eda7c (diff)
latex-dev (1nov24)
git-svn-id: svn://tug.org/texlive/trunk@72738 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source')
-rw-r--r--Master/texmf-dist/source/latex-dev/amsmath/amsmath.dtx31
-rw-r--r--Master/texmf-dist/source/latex-dev/base/doc.dtx4
-rw-r--r--Master/texmf-dist/source/latex-dev/base/ltcmdhooks.dtx78
-rw-r--r--Master/texmf-dist/source/latex-dev/base/ltcounts.dtx11
-rw-r--r--Master/texmf-dist/source/latex-dev/base/lthooks.dtx50
-rw-r--r--Master/texmf-dist/source/latex-dev/base/ltmarks.dtx18
-rw-r--r--Master/texmf-dist/source/latex-dev/base/ltproperties.dtx11
-rw-r--r--Master/texmf-dist/source/latex-dev/base/ltshipout.dtx4
-rw-r--r--Master/texmf-dist/source/latex-dev/base/ltsockets.dtx36
-rw-r--r--Master/texmf-dist/source/latex-dev/base/lttagging.dtx203
-rw-r--r--Master/texmf-dist/source/latex-dev/base/lttextcomp.dtx4
-rw-r--r--Master/texmf-dist/source/latex-dev/base/ltvers.dtx4
-rw-r--r--Master/texmf-dist/source/latex-dev/firstaid/latex2e-first-aid-for-external-files.dtx32
-rw-r--r--Master/texmf-dist/source/latex-dev/latex-lab/latex-lab-firstaid.dtx49
-rw-r--r--Master/texmf-dist/source/latex-dev/latex-lab/latex-lab-math.dtx1209
-rw-r--r--Master/texmf-dist/source/latex-dev/tools/array.dtx179
-rw-r--r--Master/texmf-dist/source/latex-dev/tools/longtable.dtx11
17 files changed, 1244 insertions, 690 deletions
diff --git a/Master/texmf-dist/source/latex-dev/amsmath/amsmath.dtx b/Master/texmf-dist/source/latex-dev/amsmath/amsmath.dtx
index 41a5c64863d..9d45cc2f9df 100644
--- a/Master/texmf-dist/source/latex-dev/amsmath/amsmath.dtx
+++ b/Master/texmf-dist/source/latex-dev/amsmath/amsmath.dtx
@@ -81,11 +81,11 @@ Bug reports can be opened (category \texttt{#1}) at\\%
% \begin{macrocode}
\DeclareRelease{}{1994-06-01}{amsmath-2018-12-01.sty}
\DeclareRelease{}{2018-12-01}{amsmath-2018-12-01.sty}
-\DeclareCurrentRelease{}{2019-04-01}
+\DeclareCurrentRelease{}{2024-10-30}
% \end{macrocode}
%
% \begin{macrocode}
-\ProvidesPackage{amsmath}[2024/08/11 v2.17r AMS math features]
+\ProvidesPackage{amsmath}[2024/10/30 v2.17s AMS math features]
% \end{macrocode}
%
% \section{Catcode defenses}
@@ -1002,6 +1002,10 @@ Foreign command \@backslashchar#1;\MessageBreak
\let\DOTSI\relax
\let\DOTSB\relax
\let\DOTSX\relax
+% \end{macrocode}
+% In the definitions below, special \cs{uccode}s are used to generate macros
+% with arguments delimited by catcode 12 letters as returned by \cs{meaning}.
+% \begin{macrocode}
{\uccode`7=`\\ \uccode`8=`m \uccode`9=`a \uccode`0=`t \uccode`!=`h
\uppercase{%
\gdef\math@#1#2#3#4#5#6\math@{\gtest@false\ifx 7#1\ifx 8#2%
@@ -1039,6 +1043,13 @@ Foreign command \@backslashchar#1;\MessageBreak
}
\fi
% \end{macrocode}
+% \changes{v2.17s}{2024/10/30}{guard against primitive if (gh/1448)}
+% \begin{macrocode}
+{\uccode`7=`\\ \uccode`(=`i \uccode`)=`f
+ \uppercase{\gdef\testif@#1#2#3#4\testif@{%
+ \ifx7#1\ifx(#2\ifx)#3\@tempswafalse\fi\fi\fi}
+}}
+% \end{macrocode}
% \begin{macrocode}
\newcount\classnum@
\def\getmathch@#1.#2\getmathch@{\classnum@#1 \divide\classnum@4096
@@ -1159,11 +1170,17 @@ Foreign command \@backslashchar#1;\MessageBreak
% \changes{v2.15d}{2016/06/28}{Add space token to prevent runaway
% argument error}
% \changes{v2.17r}{2024/06/29}{Drop \cs{protect} if present (gh/1265)}
-% \begin{macrocode}
- \begingroup
- \def\protect{\protect}% % make it a quark
- \xdef\meaning@{\@xp\stripprotect@\@let@token.........\stripprotect@. .........}%
- \endgroup
+% \changes{v2.17s}{2024/10/30}{skip protect testif detect primitive if (gh/1448)}
+% \begin{macrocode}
+ \xdef\meaning@{\meaning\@let@token. .........}%
+ \@tempswatrue
+ \@xp\testif@\meaning@....\testif@
+ \if@tempswa
+ \begingroup
+ \def\protect{\protect}% % make it a quark
+ \xdef\meaning@{\@xp\stripprotect@\@let@token.........\stripprotect@. .........}%
+ \endgroup
+ \fi
% \end{macrocode}
% In previous versions \verb|\long| macros were not seen by the lookahead.
% That was bad as this file uses \verb|\(re)newcommand| for \verb|\implies| etc.
diff --git a/Master/texmf-dist/source/latex-dev/base/doc.dtx b/Master/texmf-dist/source/latex-dev/base/doc.dtx
index 4cb8dd6b1cc..a6af48b88a8 100644
--- a/Master/texmf-dist/source/latex-dev/base/doc.dtx
+++ b/Master/texmf-dist/source/latex-dev/base/doc.dtx
@@ -34,7 +34,7 @@
%\catcode`\<=14
%<+package|shortvrb>\NeedsTeXFormat{LaTeX2e}[1994/12/01]
%<+package>
-% Any rollback request before 2016-02-15 we try to fulfill with the 2016 version:
+% ^^A Any rollback request before 2016-02-15 we try to fulfill with the 2016 version:
%<+package>\DeclareRelease{}{1994-06-01}
%<+package> {doc-2016-02-15.sty}
%<+package>\DeclareRelease{v2.1g}{2016-02-15}
@@ -45,7 +45,7 @@
%<+package>
%<+package>\ProvidesPackage{doc}
%<+shortvrb>\ProvidesPackage{shortvrb}
-%<+package|shortvrb> [2024/06/29 v3.0q
+%<+package|shortvrb> [2024/10/23 v3.0q
%<+package|shortvrb> Standard LaTeX documentation package V3 (FMi)]
%\catcode`\<=12
%
diff --git a/Master/texmf-dist/source/latex-dev/base/ltcmdhooks.dtx b/Master/texmf-dist/source/latex-dev/base/ltcmdhooks.dtx
index e8793817df3..0d14ebfe6bb 100644
--- a/Master/texmf-dist/source/latex-dev/base/ltcmdhooks.dtx
+++ b/Master/texmf-dist/source/latex-dev/base/ltcmdhooks.dtx
@@ -20,7 +20,7 @@
%<*driver>
% \fi
\ProvidesFile{ltcmdhooks.dtx}
- [2024/07/08 v1.0j LaTeX Kernel (Command hooks)]
+ [2024/10/22 v1.0j LaTeX Kernel (Command hooks)]
% \iffalse
%
\documentclass{l3doc}
@@ -68,7 +68,15 @@
% supported
% for all types of commands, see section~\ref{sec:look-ahead} for
% the restrictions that apply and what happens if one tries to use
-% this with commands for which this is not supported.} These are:
+% this with commands for which this is not supported.}
+%
+% However, this is only true \enquote{in theory}. In practice there
+% are a number of restrictions that makes it impossible to use such
+% generic command hooks in a number of cases, so please read all
+% of section~\ref{sec:restrictions} to understand what may prevent
+% you from using them successfully.
+%
+% The generic command hooks are:
% \begin{description}
% \item[\hook{cmd/\meta{name}/before}]
%
@@ -152,7 +160,55 @@
% and \TeX{} doesn't have a reliable way to see that, so some guesswork
% has to be employed.
%
-% \subsection{Patching}
+% We can do this in most cases when commands are defined using
+% \cs{NewDocumentCommand} or \cs{newcommand} (with a few exceptions).
+% For commands defined with \tn{def} the situation is less good.
+% Common cases where the command hooks will not work are:
+% \begin{itemize}
+% \item
+%
+% Commands that use special catcode settings within their
+% definition. In that case it is usually not possible to augment the
+% definition (see~\ref{sec:patching}).
+%
+% \item
+%
+% If a command is defined while \cs{ExplSyntaxOn} is in force
+% \textbf{and} the command contains \verb=~= characters to represent
+% spaces, then it can't be patched to include the command hooks. In
+% fact in some very special circumstances you might even get a
+% low-level error rather than the information that the command can't
+% be patched (see, for example,
+% \url{https://github.com/latex3/latex2e/issues/1430}.
+%
+% \item
+%
+% Commands that have arguments as far as the user is concerned
+% (e.g., \cs{section} or \cs{caption}), but are defined in a way that these
+% arguments are not read by the user level command but only later
+% during the processing. In that case the \texttt{after} hook
+% doesn't work at all. The \text{before} hook only works with
+% \cs{AddToHook} but not with \cs{AddToHookWithArguments} because the
+% arguments haven't been read at that point where the hook is
+% patched in. See
+% section~\ref{sec:look-ahead}.
+%
+%
+% \item
+% Adding a specific generic command hook is only attempted once per
+% command, thus after redefining a command such hooks will no longer
+% be there and will also not being re-added, see section~\ref{sec:timing}.
+%
+% \end{itemize}
+% All this means that you have to have a good understanding of how
+% commands are defined when you attempt to make use of such hooks and
+% something goes wrong.
+% What can help in that case is to turn on \cs{DebugHooksOn} in which
+% case you get much more (low-level) details on why something fails and
+% what was tried to enable the hooks.
+%
+%
+% \subsection{Patching}\label{sec:patching}
%
% The code here tries to find out if a command was defined with
% \tn{newcommand} or \tn{DeclareRobustCommand} or
@@ -172,7 +228,7 @@
% catcode settings are not the same as the ones at the time of command's
% definition, so not always adding a hook to a command will work.
%
-% \subsubsection{Timing}
+% \subsubsection{Timing}\label{sec:timing}
%
% When \cs{AddToHook} (or its \pkg{expl3} equivalent) is called with
% a generic |cmd| hook, say, \hook{cmd/foo/before}, for the first time
@@ -211,12 +267,14 @@
% hooks attached to them.
%
% One good example is the \tn{section} command. You can add something
-% to the \hook{cmd/section/before} hook, but if you try to add something
-% to the \hook{cmd/section/after} hook, \tn{section} will no longer
-% work. That happens because the \tn{section} macro takes no argument,
-% but instead calls a few internal \LaTeX{} macros to look for the
-% optional and mandatory arguments. By adding code to the
-% \hook{cmd/section/after} hook, you get in the way of that scanning.
+% to the \hook{cmd/section/before} hook (but only with \cs{AddToHook}
+% not \cs{AddToHookWithArguments}),
+% but if you try to add anything to the \hook{cmd/section/after}
+% hook, \tn{section} will no longer work at all. That happens because the
+% \tn{section} macro takes no argument, but instead calls a few
+% internal \LaTeX{} macros to look for the optional and mandatory
+% arguments. By adding code to the \hook{cmd/section/after} hook, you
+% get in the way of that scanning.
%
% In such a case, where it is known that a specific generic command
% hook does not work if code is added to it, the package author can
diff --git a/Master/texmf-dist/source/latex-dev/base/ltcounts.dtx b/Master/texmf-dist/source/latex-dev/base/ltcounts.dtx
index 9417769d733..1d3f2024898 100644
--- a/Master/texmf-dist/source/latex-dev/base/ltcounts.dtx
+++ b/Master/texmf-dist/source/latex-dev/base/ltcounts.dtx
@@ -33,7 +33,7 @@
%<*driver>
% \fi
\ProvidesFile{ltcounts.dtx}
- [2024/09/20 v1.1o LaTeX Kernel (Counters)]
+ [2024/10/26 v1.1p LaTeX Kernel (Counters)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltcounts.dtx}
@@ -310,6 +310,7 @@
% \changes{v1.1n}{2023/11/07}{Do not change \cs{the...} if already defined (gh/823)}
% \changes{v1.1o}{2024/09/20}{define theHfoo (used for internal links)}
% \begin{macrocode}
+% \changes{v1.1p}{2024/10/26}{Fully expand counter name in theHfoo commands (gh/1508)}
%</2ekernel>
%<latexrelease>\IncludeInRelease{2024/11/01}{\@definecounter}
%<latexrelease> {provide theHfoo commands}%
@@ -319,7 +320,8 @@
\global\expandafter\let\csname cl@#1\endcsname\@empty
\@addtoreset{#1}{@ckpt}%
\global\expandafter\let\csname p@#1\endcsname\@empty
- \expandafter\gdef\csname theH#1\endcsname{\the\value{#1}}%
+ \expandafter\xdef\csname theH#1\endcsname{%
+ \noexpand\the\noexpand\value{#1}}%
% \end{macrocode}
% If \cs{the\#1} is undefined or \cs{relax} we define it with the
% standard definition for counters, otherwise we warn. This will
@@ -360,6 +362,7 @@
%
% \begin{macro}{\@addtoreset}
% \changes{v1.1o}{2024/09/20}{add the parent theHfoo if a counter is reset}
+% \changes{v1.1p}{2024/10/26}{Fully expand counter name in theHfoo commands (gh/1508)}
% If a counter is reset when a parent counter changes it no longer has an unique value
% across the document. As |\theH<counter>| should be unique
% this representation is changed to include also the
@@ -371,7 +374,9 @@
%<latexrelease> {provide theHfoo commands}%
%<*2ekernel|latexrelease>
\def\@addtoreset#1#2{\expandafter\@cons\csname cl@#2\endcsname {{#1}}%
- \expandafter\gdef\csname theH#1\endcsname{\csname theH#2\endcsname.\the\value{#1}}%
+ \expandafter\xdef\csname theH#1\endcsname{%
+ \expandafter\noexpand\csname theH#2\endcsname.%
+ \noexpand\the\noexpand\value{#1}}%
}
%<latexrelease>\EndIncludeInRelease
%</2ekernel|latexrelease>
diff --git a/Master/texmf-dist/source/latex-dev/base/lthooks.dtx b/Master/texmf-dist/source/latex-dev/base/lthooks.dtx
index 9e4450d628d..0c33c022e3b 100644
--- a/Master/texmf-dist/source/latex-dev/base/lthooks.dtx
+++ b/Master/texmf-dist/source/latex-dev/base/lthooks.dtx
@@ -32,7 +32,7 @@
%<*driver>
% \fi
\ProvidesFile{lthooks.dtx}
- [2024/08/09 v1.1i LaTeX Kernel (hooks)]
+ [2024/10/29 v1.1k LaTeX Kernel (hooks)]
% \iffalse
%
\documentclass{l3doc}
@@ -405,11 +405,17 @@
% Removes any code labeled by \meta{label} from the \meta{hook}.
% When the optional argument \meta{label} is not provided, the
% \meta{default label} is used (see section~\ref{sec:default-label}).
+% \end{function}
%
% If there is no code under the \meta{label} in the \meta{hook},
% or if the \meta{hook} does not exist, a warning is issued when
% you attempt to \cs{RemoveFromHook}, and the command is ignored.
-% \cs{RemoveFromHook} should be used only when you know exactly what
+% \cs{RemoveFromHook}\marginpar{\raggedleft\rightskip5pt\itshape
+% \textbf{Important:}\break The \cs{RemoveFromHook} command should be
+% only used if one has full control over the code chunk to be removed.
+% In particular it should not be used to remove code chunks from other
+% packages! For this the \texttt{voids} relation is provided.}
+% should be used only when you know exactly what
% labels are in a hook. Typically this will be when some code gets added to a hook
% by a package, then later this code is removed by that same package.
% If you want to prevent the execution of code from another
@@ -423,16 +429,15 @@
% The \meta{hook} and \meta{label} can be specified using the
% dot-syntax to denote the current package name.
% See section~\ref{sec:default-label}.
-% \end{function}
-%
-% \medskip
%
-% In contrast to the \texttt{voids} relationship between two labels
+% In contrast to the \texttt {voids} relationship between two labels
% in a \cs{DeclareHookRule} this is a destructive operation as the
% labeled code is removed from the hook data structure, whereas the
% relationship setting can be undone by providing a different
% relationship later.
%
+% \medskip
+%
% A useful application for this declaration inside the document body
% is when one wants to temporarily add code to hooks and later remove
% it again, e.g.,
@@ -538,7 +543,6 @@
%
%
%
-%
% \subsubsection{Hook names and default labels}
% \label{sec:default-label}
%
@@ -894,7 +898,7 @@
% some variant thereof. Generic hooks such as \hook{file} and \hook{env} hooks are
% automatically declared when code is added to them.
%
-% \begin{function}[EXP]{\IfHookEmptyTF}
+% \begin{function}[EXP]{\IfHookEmptyTF,\IfHookEmptyT,\IfHookEmptyF}
% \begin{syntax}
% \cs{IfHookEmptyTF} \Arg{hook} \Arg{true code} \Arg{false code}
% \end{syntax}
@@ -6174,6 +6178,8 @@
}
% \end{macrocode}
%
+% \changes{v1.1k}{2024/10/29}
+% {Skip mapping over undeclared \cs{g_@@_\meta{hook}_code_prop} (gh/1513)}
% \begin{macrocode}
\@@_if_usable:nF {#1}
{ \@@_log_line:x { The~hook~is~not~declared. } }
@@ -6183,7 +6189,9 @@
{ #2 { The~hook~is~empty } }
{
\@@_log_line:x { Code~chunks: }
- \prop_if_empty:cTF { g_@@_#1_code_prop }
+ \bool_lazy_or:nnTF
+ { ! \prop_if_exist_p:c { g_@@_#1_code_prop } }
+ { \prop_if_empty_p:c { g_@@_#1_code_prop } }
{ \@@_log_line_indent:x { --- } }
{
\prop_map_inline:cn { g_@@_#1_code_prop }
@@ -6445,19 +6453,24 @@
% |#2|${}={}$\meta{label_1}\verb=|=\meta{label_2},
% and |#3|${}={}$\meta{hook} (the latter may be the argument |#1| to
% \cs{@@_list_rules:nn}, or \texttt{??} if it is a default rule).
+% \changes{v1.1k}{2024/10/29}
+% {Skip mapping over undeclared \cs{g_@@_\meta{hook}_code_prop} (gh/1513)}
% \begin{macrocode}
\cs_new_protected:Npn \@@_list_rules:nn #1 #2
{
- \cs_set_protected:Npn \@@_tmp:w ##1 ##2 ##3 {#2}
- \prop_map_inline:cn { g_@@_#1_code_prop }
+ \prop_if_exist:cT { g_@@_#1_code_prop }
{
+ \cs_set_protected:Npn \@@_tmp:w ##1 ##2 ##3 {#2}
\prop_map_inline:cn { g_@@_#1_code_prop }
{
- \@@_if_label_case:nnnnn {##1} {####1}
- { \prop_map_break: }
- { \@@_list_one_rule:nnn {##1} {####1} }
- { \@@_list_one_rule:nnn {####1} {##1} }
- {#1}
+ \prop_map_inline:cn { g_@@_#1_code_prop }
+ {
+ \@@_if_label_case:nnnnn {##1} {####1}
+ { \prop_map_break: }
+ { \@@_list_one_rule:nnn {##1} {####1} }
+ { \@@_list_one_rule:nnn {####1} {##1} }
+ {#1}
+ }
}
}
}
@@ -7764,13 +7777,16 @@
% \end{macro}
%
%
-% \begin{macro}[EXP]{\IfHookEmptyTF}
+% \begin{macro}[EXP]{\IfHookEmptyTF,\IfHookEmptyT,\IfHookEmptyF}
+% \changes{v1.1j}{2024/10/21}{Define \cs{IfHookEmptyT}, \cs{IfHookEmptyF}}
% Here we avoid the overhead of \pkg{xparse}, since \cs{IfHookEmptyTF}
% is used in \cs{end} (that is, every \LaTeX{} environment). As a
% further optimization, use \cs{let} rather than \cs{def} to avoid one
% expansion step.
% \begin{macrocode}
\cs_new_eq:NN \IfHookEmptyTF \hook_if_empty:nTF
+\cs_new_eq:NN \IfHookEmptyT \hook_if_empty:nT
+\cs_new_eq:NN \IfHookEmptyF \hook_if_empty:nF
% \end{macrocode}
% \end{macro}
%
diff --git a/Master/texmf-dist/source/latex-dev/base/ltmarks.dtx b/Master/texmf-dist/source/latex-dev/base/ltmarks.dtx
index f71bfab9b63..f769a093240 100644
--- a/Master/texmf-dist/source/latex-dev/base/ltmarks.dtx
+++ b/Master/texmf-dist/source/latex-dev/base/ltmarks.dtx
@@ -17,7 +17,7 @@
%<*driver>
% \fi
\ProvidesFile{ltmarks.dtx}
- [2024/07/08 v1.0g LaTeX Kernel (Marks)]
+ [2024/10/22 v1.0h LaTeX Kernel (Marks)]
% \iffalse
%
\documentclass{l3doc}
@@ -257,7 +257,7 @@
% running headers and footers and shipout out both in one
% go.\footnote{As of now that scenario is not yet officially supported.}
%
-% \begin{function}[EXP]{\IfMarksEqualTF,\mark_if_eq:nnnnTF,\mark_if_eq:nnnnnnTF}
+% \begin{function}[EXP]{\IfMarksEqualTF,\IfMarksEqualT,\IfMarksEqualF,\mark_if_eq:nnnnTF,\mark_if_eq:nnnnnnTF}
% \begin{syntax}
% \cs{IfMarksEqualTF} \oarg{region} \Arg{class} \Arg{pos_1} \Arg{pos_2} \Arg{true} \Arg{false}
% \cs{mark_if_eq:nnnnTF} \Arg{region} \Arg{class} \Arg{pos_1} \Arg{pos_2} \Arg{true} \Arg{false}
@@ -676,7 +676,8 @@
% and adds suitable \cs{mark_insert:nn} in the two token
% lists. These token lists can then be executed at the right place
% to reinsert the marks, e.g., directly after the box. This is, for
-% example, used by \pkg{multicol} when a short balanced
+% example, going to be used\footnote{Probably not before 2025, though.}
+% by \pkg{multicol} when a short balanced
% \env{multicols} is returned to the galley for typesetting.
%
% If the \meta{source} consists of a single vertical box (plus
@@ -1799,8 +1800,9 @@
%
%
%
-% \begin{macro}[EXP]{\IfMarksEqualTF}
-% We only provide a CamelCase command for the case with one region
+% \begin{macro}[EXP]{\IfMarksEqualTF,\IfMarksEqualT,\IfMarksEqualF}
+% \changes{v1.0h}{2024/10/21}{Define \cs{IfMarksEqualT}, \cs{IfMarksEqualF}}
+% We only provide CamelCase commands for the case with one region
% (optional) and one class. One could think of also providing a
% version for the general case with several optional arguments, but
% use cases for this are most likely rare, so not done yet.
@@ -1808,6 +1810,12 @@
\NewExpandableDocumentCommand \IfMarksEqualTF {O{page}mmm} {
\mark_if_eq:nnnnTF {#1}{#2}{#3}{#4}
}
+\NewExpandableDocumentCommand \IfMarksEqualT {O{page}mmm} {
+ \mark_if_eq:nnnnT {#1}{#2}{#3}{#4}
+}
+\NewExpandableDocumentCommand \IfMarksEqualF {O{page}mmm} {
+ \mark_if_eq:nnnnF {#1}{#2}{#3}{#4}
+}
% \end{macrocode}
% \end{macro}
%
diff --git a/Master/texmf-dist/source/latex-dev/base/ltproperties.dtx b/Master/texmf-dist/source/latex-dev/base/ltproperties.dtx
index 23a38c43af9..77d36a43a98 100644
--- a/Master/texmf-dist/source/latex-dev/base/ltproperties.dtx
+++ b/Master/texmf-dist/source/latex-dev/base/ltproperties.dtx
@@ -30,7 +30,7 @@
%<*driver>
% \fi
\ProvidesFile{ltproperties.dtx}
- [2024/09/25 v1.0g LaTeX Kernel (Properties)]
+ [2024/10/21 v1.0h LaTeX Kernel (Properties)]
% \iffalse
%
\documentclass[full]{l3doc}
@@ -363,7 +363,7 @@
% has been set with the standard \cs{label} command.
% \end{function}
%
-% \begin{function}{\IfPropertyRecordedTF}
+% \begin{function}{\IfPropertyRecordedTF,\IfPropertyRecordedT,\IfPropertyRecordedF}
% \begin{syntax}
% \cs{IfPropertyRecordedTF} \Arg{label} \Arg{property} \Arg{true code} \Arg{false code}
% \end{syntax}
@@ -805,9 +805,12 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\IfPropertyRecordedTF}
+% \begin{macro}{\IfPropertyRecordedTF,\IfPropertyRecordedT,\IfPropertyRecordedF}
+% \changes{v1.0h}{2024-10-21}{Define \cs{IfPropertyRecordedT}, \cs{IfPropertyRecordedF}}
% \begin{macrocode}
-\cs_new_eq:NN \IfPropertyRecordedTF \property_if_recorded:eeTF
+\cs_new_eq:NN \IfPropertyRecordedTF \property_if_recorded:eeTF
+\cs_new:Npn \IfPropertyRecordedT #1#2#3 { \property_if_recorded:eeTF {#1}{#2}{#3}{} }
+\cs_new:Npn \IfPropertyRecordedF #1#2#3 { \property_if_recorded:eeTF {#1}{#2}{}{#3} }
% \end{macrocode}
% \end{macro}
%
diff --git a/Master/texmf-dist/source/latex-dev/base/ltshipout.dtx b/Master/texmf-dist/source/latex-dev/base/ltshipout.dtx
index 0c9113ce938..c2e70ba6d54 100644
--- a/Master/texmf-dist/source/latex-dev/base/ltshipout.dtx
+++ b/Master/texmf-dist/source/latex-dev/base/ltshipout.dtx
@@ -34,7 +34,7 @@
%<*driver>
% \fi
\ProvidesFile{ltshipout.dtx}
- [2024/02/11 v1.0n LaTeX Kernel (Shipout)]
+ [2024/10/22 v1.0n LaTeX Kernel (Shipout)]
% \iffalse
%
\documentclass{l3doc}
@@ -469,7 +469,7 @@
%
% \begin{variable}{\PreviousTotalPages}
% \begin{syntax}
-% \cs{thetotalpages}/\cs{PreviousTotalPages}
+% \cs{PreviousTotalPages}
% \end{syntax}
% Command that expands to the number of total pages from the
% previous run. If there was no previous run or if used in the
diff --git a/Master/texmf-dist/source/latex-dev/base/ltsockets.dtx b/Master/texmf-dist/source/latex-dev/base/ltsockets.dtx
index c77c74b57f2..a977f8f6aa5 100644
--- a/Master/texmf-dist/source/latex-dev/base/ltsockets.dtx
+++ b/Master/texmf-dist/source/latex-dev/base/ltsockets.dtx
@@ -33,7 +33,7 @@
%<*driver>
% \fi
\ProvidesFile{ltsockets.dtx}
- [2024/06/29 v0.9a LaTeX Kernel (Sockets)]
+ [2024/10/27 v0.9b LaTeX Kernel (Sockets)]
% \iffalse
%
\documentclass{l3doc}
@@ -371,7 +371,7 @@
% number of inputs = 2
% available plugs = noop, plug-A, plug-B
% current plug = plug-B
-% definition = \protected\long macro:#1#2->\begin {quote}\sffamily
+% definition = \long macro:#1#2->\begin {quote}\sffamily
% foo-B: #2\textsuperscript {2}\end {quote}
% \end{verbatim}
% \LogSocket{foo}
@@ -617,6 +617,22 @@
% \end{function}
%
%
+% \begin{function}[EXP]{\socket_use_expandable:nw,\socket_use_expandable:n}
+% \begin{syntax}
+% \cs{socket_use_expandable:n} \Arg{socket-name}
+% \end{syntax}
+% Fully expandable variant of \cs{socket_use:n}. This can be used in macro code
+% to retrieve code from sockets which need to appear in an expandable context.
+%
+% This usually requires the plug to only contain expandable code and should therefore
+% only be used for sockets which are clearly documented to be used in an expandable context.
+% This command does not print any debugging info when \cs{DebugSocketsOn} is active
+% and should therefore be avoided whenever possible.
+%
+% For performance reasons there is no explicit check that the socket was declared!
+% \end{function}
+%
+%
% \begin{function}{\ShowSocket,\LogSocket,\socket_show:n,\socket_log:n}
% \begin{syntax}
% \cs{ShowSocket} \Arg{socket-name}
@@ -820,6 +836,7 @@
%
%
% \begin{macro}{\socket_new_plug:nnn,\socket_set_plug:nnn}
+% \changes{v0.9b}{2024/10/27}{Make plug definition non-protected}
%
% Declaring a code for a socket is just making a definition, taking
% the number of arguments from the saved int.
@@ -834,7 +851,7 @@
{
\cs_generate_from_arg_count:cNnn
{ @@_#1_plug_#2:w }
- \cs_new_protected:Npn
+ \cs_new:Npn
{ \int_use:c { c_@@_#1_args_int } }
{#3}
% \end{macrocode}
@@ -862,7 +879,7 @@
{
\cs_generate_from_arg_count:cNnn
{ @@_#1_plug_#2:w }
- \cs_set_protected:Npn
+ \cs_set:Npn
{ \int_use:c { c_@@_#1_args_int } }
{#3}
\@@_debug_term:n
@@ -942,6 +959,17 @@
% \fmi{Implement?}
% \end{macro}
%
+% \begin{macro}{\socket_use_expandable:nw,\socket_use_expandable:n}
+% \changes{v0.9b}{2024/10/27}{Added \cs{socket_use_expandable:n}}
+% The same as the non-expandable code, except for the missing debug output.
+% \begin{macrocode}
+\cs_new:Npn \socket_use_expandable:nw #1 {
+ \use:c { @@_#1_plug_ \str_use:c { l_@@_#1_plug_str } :w }
+}
+\cs_new_eq:NN \socket_use_expandable:n \socket_use_expandable:nw % socket with no inputs
+% \end{macrocode}
+% \end{macro}
+%
%
%
%
diff --git a/Master/texmf-dist/source/latex-dev/base/lttagging.dtx b/Master/texmf-dist/source/latex-dev/base/lttagging.dtx
index 74735a37626..6b68cd0e05f 100644
--- a/Master/texmf-dist/source/latex-dev/base/lttagging.dtx
+++ b/Master/texmf-dist/source/latex-dev/base/lttagging.dtx
@@ -33,7 +33,7 @@
%<*driver>
% \fi
\ProvidesFile{lttagging.dtx}
- [2024/10/11 v1.0j LaTeX Kernel (tagging support)]
+ [2024/10/21 v1.0k LaTeX Kernel (tagging support)]
% \iffalse
\documentclass{l3doc}
\GetFileInfo{lttagging.dtx}
@@ -78,7 +78,7 @@
% \DescribeMacro\tag_suspend:n
% \DescribeMacro\tag_resume:n
-%
+%
% The are places in code where it is import top stop any tagging
% activities, e.g., when we are doing trial typesetting that it is
% done several times. In such a case one must tag only the final
@@ -107,46 +107,51 @@
% \DescribeMacro\UseTaggingSocket
% \DescribeMacro\tag_socket_use:n
% \DescribeMacro\tag_socket_use:nn
-% To support tagging in packages we use sockets with names starting
-% with \texttt{tagsupport/}. Usually, these sockets have exactly two
-% plugs defined:
-% \plug{noop} (when no tagging is requested or tagging is not wanted
-% for some reason) and a second plug that enables the tagging. There
-% may be more, e.g., tagging with special debugging, etc., but right
-% now it is usually just on or off.
-%
-% Given that we sometimes have to suspend tagging, it would be fairly
-% inefficient to put different plugs into these sockets whenever that
-% happens. We therefore offer \cs{UseTaggingSocket} which is like
-% \cs{UseSocket} except that the socket name is specified without
-% \texttt{tagsupport/}, i.e.,
+% \DescribeMacro\tag_socket_use:nnn
+% Given that we sometimes have to suspend tagging, it would be fairly
+% inefficient to put different plugs into these sockets whenever that
+% happens. We therefore offer \cs{UseTaggingSocket} which is like
+% \cs{UseSocket} except that is expects a socket starting with
+% \texttt{tagsupport/} but the socket name is specified without
+% this prefix, i.e.,
% \begin{quote}
% \verb=\UseTaggingSocket{foo}= $\to$
% \verb=\UseSocket{tagsupport/foo}=
-% \end{quote}
-% Beside being slightly shorter, the big advantage is that this way
-% we can change \cs{UseTaggingSocket} to do nothing when tagging is
-% suspended with \cs{SuspendTagging} instead of changing the plugs of
-% the tagging support sockets back and forth.
-%
-% This means that with \cs{SuspendTagging} in force all socket
-% arguments are ignored (including the case when there is a single
-% one), i.e., all sockets used with \cs{UseTaggingSocket} behave as
-% if the \text{noop} plug is assigned.
-%
-% It is possible to use the tagging support sockets with
-% \cs{UseSocket} instead of \cs{UseTaggingSocket}, but in this case
-% the socket remains active if \cs{SuspendTagging} is in force. There
-% may be reasons for doing that, but in general we expect to always
-% use \cs{UseTaggingSocket}.
-%
-% The L3 programming layer versions \cs{tag_socket_use:n} and
-% \cs{tag_socket_use:nn} are slightly more efficient than
+% \end{quote}.
+%
+% Beside being slightly shorter, the big advantage is that this way
+% we can change \cs{UseTaggingSocket} to do nothing by switching a boolean
+% instead of changing the plugs of the tagging support sockets back and forth.
+%
+% Usually, these sockets have (beside the default plug defined for every socket)
+% one additional plug defined and directly assigned. This plug is used when
+% tagging is active.
+% There may be more plugs, e.g., tagging with special debugging or special behaviour
+% depending on the class or PDF version etc., but right now it is usually just on or off.
+%
+% When tagging is suspended they all have the same predefined behaviour:
+% The sockets with zero arguments do nothing. The sockets with one argument
+% gobble their argument. The sockets with two arguments
+% will drop their first argument and pass the second unchanged.
+%
+% It is possible to use the tagging support sockets with
+% \cs{UseSocket} directly, but in this case the socket remains active
+% if \cs{SuspendTagging} is in force. There may be reasons for doing
+% that but in general we expect to always use \cs{UseTaggingSocket}.
+%
+% \DescribeMacro\UseExpandableTaggingSocket
+% \DescribeMacro\tag_socket_use_expandable:n
+% For special cases like in some \cs{halign} contexts we need a fully expandable
+% version of the commend. For these cases, \cs{UseExpandableTaggingSocket} can be
+% used. To allow being expandable, it does not output any debugging information
+% if \cs{DebugSocketsOn} is in effect and therefore should be avoided whenever possible.
+%
+% The L3 programming layer versions \cs{tag_socket_use_expandable:n},
+% \cs{tag_socket_use:n}, \cs{tag_socket_use:nn}, and \cs{tag_socket_use:nnn}
+% are slightly more efficient than
% \cs{UseTaggingSocket} because they do not have to determine how
-% many arguments the socket takes when disabling it, so in code that
-% is using the L3 programming layer we recommend to use them instead
-% of the CamelCase command.
-%
+% many arguments the socket takes when disabling it.
+%
%
% \MaybeStop{}
%
@@ -156,12 +161,12 @@
%
%
% \begin{macro}{\tag_suspend:n,\tag_resume:n,\SuspendTagging,\ResumeTagging}
-%
+%
% In the kernel, these commands get dummy definitions so that
% they can be used without harm in packages. The real definition is
% used when tagging gets enabled.
% \begin{macrocode}
-\cs_new_eq:NN \tag_suspend:n \use_none:n
+\cs_new_eq:NN \tag_suspend:n \use_none:n
\cs_new_eq:NN \tag_resume:n \use_none:n
\cs_new_protected:Npn \SuspendTagging #1 { \tag_suspend:n {#1} }
\cs_new_protected:Npn \ResumeTagging #1 { \tag_resume:n {#1} }
@@ -170,7 +175,10 @@
%
% \begin{macro}{\tag_socket_use:n,
% \tag_socket_use:nn,
+% \tag_socket_use:nnn,
+% \tag_socket_use_expandable:n,
% \UseTaggingSocket,
+% \UseExpandableTaggingSocket,
% }
% Again this is not the final definition for the kernel; it is just
% a version to get going while some parts of the kernel support are
@@ -187,19 +195,21 @@
%
% Dummy definitions in the kernel.
% These definitions will get updated in \pkg{tagpdf}.
+% The default in the kernel is just to get rid of the first argument, the second is preserved if present:
+% \changes{v1.0k}{2024/10/21}{Changed behavior of two argument tagging sockets when disabled.}
+% \changes{v1.0k}{2024/10/21}{Added expandable variants}
% \begin{macrocode}
+\cs_new:Npn \tag_socket_use_expandable:n #1 { }
\cs_new_protected:Npn \tag_socket_use:n #1 { }
\cs_new_protected:Npn \tag_socket_use:nn #1#2 { }
-% \end{macrocode}
-% The default in the kernel is just to get rid of the argument:
-% \begin{macrocode}
+\cs_new_protected:Npn \tag_socket_use:nnn #1#2#3 { #3 }
\cs_new_protected:Npn \UseTaggingSocket #1 {
\int_case:nnF
{ \int_use:c { c__socket_tagsupport/#1_args_int } }
{
0 \prg_do_nothing:
1 \use_none:n
- 2 \use_none:nn
+ 2 \use_ii:nn
% \end{macrocode}
% We do not expect tagging sockets with more than one or two
% arguments, so for now we only provide those.
@@ -208,15 +218,28 @@
\ERRORusetaggingsocket % that should get a proper error message
}
% \end{macrocode}
+% The same as an expandable command:
+% \begin{macrocode}
+\cs_new:Npn \UseExpandableTaggingSocket #1 {
+ \int_case:nnF
+ { \int_use:c { c__socket_tagsupport/#1_args_int } }
+ {
+ 0 \prg_do_nothing:
+ 1 \use_none:n
+ 2 \use_ii:nn
+ }
+ \ERRORusetaggingsocket % that should get a proper error message
+}
+% \end{macrocode}
%
% \end{macro}
%
% \subsection{Tagging sockets}
% This collects tagging sockets that should be generally available
-% so that they can also be used even if the tagging code is not loaded.
-%
+% so that they can also be used even if the tagging code is not loaded.
+%
% \subsubsection{Tagging support for paragraph setup}
-%
+%
% Paragraphs are tagged through the code in the para/hooks. This code is sometimes
% adjusted, e.g. to produce a \enquote{flattened} paragraph or to use a different tag.
% Sockets related to such code parts are collected here.
@@ -225,22 +248,22 @@
% The block code needs to know if they are nested blockenvs inside
% a flattened environment. For this it uses a counter. Inside some contexts,
% e.g. at the begin of a minipage or a footnote this counter must be reset.
-% We therefore define the counter here so that we can use it in the following
-% socket.
+% We therefore define the counter here so that we can use it in the following
+% socket.
% \begin{macrocode}
\int_new:N \l__tag_block_flattened_level_int
% \end{macrocode}
% \end{macro}
-%
+%
% \begin{socketdecl}{tagsupport/para/restore}
% This socket restores the para related settings to their default. It
% should be used in places where ``normal'' paragraph tagging must be ensured, for example
-% at the begin of a footnote.
+% at the begin of a footnote.
% \begin{macrocode}
\NewSocket{tagsupport/para/restore}{0}
% \end{macrocode}
% \end{socketdecl}
-%
+%
% \begin{plugdecl}{default}
% \changes{v1.0i}{2024/10/10}{Restore also paratagging (tagging/723)}
% \begin{macrocode}
@@ -255,7 +278,7 @@
\AssignSocketPlug{tagsupport/para/restore}{default}
% \end{macrocode}
% \end{plugdecl}
-%
+%
% \begin{socketdecl}{tagsupport/para/begin,tagsupport/para/end}
% These sockets are currently defined in tagpdf. They overwrite
% definitions in the latex-lab-block code. There is also a simpler
@@ -273,22 +296,22 @@
\NewSocket{tagsupport/recordtarget}{0}
% \end{macrocode}
% \end{socketdecl}
-%
+%
% \begin{plugdecl}{kernel (tagsupport/recordtarget)}
% \begin{macrocode}
-%
+%
\NewSocketPlug{tagsupport/recordtarget}{kernel}
{
\tl_if_blank:VF \@currentHref
{
- \prop_gput:Nee
- \g__tag_struct_dest_num_prop
+ \prop_gput:Nee
+ \g__tag_struct_dest_num_prop
{\@currentHref}
- {\tag_get:n{struct_num}}
+ {\tag_get:n{struct_num}}
}
}
-\AssignSocketPlug{tagsupport/recordtarget}{kernel}
-\ExplSyntaxOff
+\AssignSocketPlug{tagsupport/recordtarget}{kernel}
+\ExplSyntaxOff
% \end{macrocode}
% \end{plugdecl}
% \subsubsection{Tagging sockets for toc}
@@ -307,28 +330,28 @@
% \begin{socketdecl}{tagsupport/toc/starttoc/before,
% tagsupport/toc/starttoc/after}
% Tagging sockets for the begin and end of start of \cs{@starttoc}.
-% They take one argument, the extension.
+% They take one argument, the extension.
% \begin{macrocode}
\NewSocket{tagsupport/toc/starttoc/before}{1}
\NewSocket{tagsupport/toc/starttoc/after}{1}
% \end{macrocode}
% \end{socketdecl}
-%
+%
% \begin{socketdecl}{tagsupport/toc/leaders/before,
% tagsupport/toc/leaders/after}
% Tagging sockets to make the dot leaders an artifact.
-% They do not take an argument.
+% They do not take an argument.
% \begin{macrocode}
\NewSocket{tagsupport/toc/leaders/before}{0}
\NewSocket{tagsupport/toc/leaders/after}{0}
% \end{macrocode}
% \end{socketdecl}
-%
+%
% \subsubsection{Tagging support for table/tabular packages}
%
% The code uses a number of sockets to inject the tagging
% commands. These can be easily set to a noop-plug in case the
-% automated tagging is not wanted.
+% automated tagging is not wanted.
%
% \begin{socketdecl}{tagsupport/tbl/cell/begin,
% tagsupport/tbl/cell/end,
@@ -463,10 +486,10 @@
% \end{socketdecl}
%
% \subsubsection{Tagging Support for floats}
-%
+%
% \begin{socketdecl}{tagsupport/float/hmode/begin,
% tagsupport/float/hmode/end}
-% These sockets are used if the float is called in
+% These sockets are used if the float is called in
% hmode.
% \changes{v1.0h}{2024/09/13}{Sockets for floats added}
% \begin{macrocode}
@@ -484,38 +507,38 @@
% \end{macrocode}
% \end{socketdecl}
%
-%
+%
% \begin{socketdecl}{tagsupport/caption/begin,
% tagsupport/caption/end}
% These sockets are used in \cs{@makecaption}.
% They open and close the \texttt{Caption} structure.
-% Their default plugs assume that they are used in
+% Their default plugs assume that they are used in
% vmode. The argument of the begin socket is
% the structure number of the parent float. If it is
-% empty the current structure number is used.
+% empty the current structure number is used.
% \begin{macrocode}
\NewSocket{tagsupport/caption/begin}{1}
\NewSocket{tagsupport/caption/end}{0}
% \end{macrocode}
% \end{socketdecl}
-%
+%
% \begin{socketdecl}{tagsupport/caption/label/begin,
% tagsupport/caption/label/end}
% These sockets are used in \cs{@makecaption} around the
-% label. Their default plugs ensure that
-% the label is outside the paragraph and that
+% label. Their default plugs ensure that
+% the label is outside the paragraph and that
% the rest of the caption uses flattened para mode. If the
-% caption is not in a hbox, the \texttt{para/begin}
-% socket should follow to properly start the paragraph.
+% caption is not in a hbox, the \texttt{para/begin}
+% socket should follow to properly start the paragraph.
% \begin{macrocode}
\NewSocket{tagsupport/caption/label/begin}{0}
-\NewSocket{tagsupport/caption/label/end}{0}
+\NewSocket{tagsupport/caption/label/end}{0}
% \end{macrocode}
% \end{socketdecl}
-%
+%
% \section{For lttab.dtx parked here for now}
%
-%
+%
% \begin{macrocode}
%<@@=tbl>
\ExplSyntaxOn
@@ -536,7 +559,7 @@
% \g_@@_row_int,
% \g_@@_span_tl,
% \g_@@_table_cols_tl}
-%
+%
% \cs{g_@@_row_int} holds the current row number in the table. The
% value \texttt{0} means we haven't yet processed the table
% preamble (or in case of longtable are just in front of the next
@@ -606,14 +629,14 @@
% \subsection{Tracing/debugging}
%
% \begin{macro}{\DebugTablesOn,\DebugTablesOff}
-%
+%
% \begin{macrocode}
\def\DebugTablesOn{
\cs_set_eq:NN \@@_trace:n \typeout
-}
+}
\def\DebugTablesOff{
\cs_set_eq:NN \@@_trace:n \use_none:n
-}
+}
% \end{macrocode}
%
% \begin{macrocode}
@@ -663,7 +686,7 @@
%
%
% \begin{macro}{\l_@@_tmpa_seq}
-%
+%
% \begin{macrocode}
\seq_new:N \l_@@_tmpa_seq
% \end{macrocode}
@@ -672,7 +695,7 @@
%
%
% \begin{macro}{\tbl_count_missing_cells:n}
-%
+%
% We might have the situation that some table package has not
% implemented the \cs{tbl_count_table_cols:} in which case
% \cs{g_@@_table_cols_tl} would always be zero and we would get an
@@ -708,7 +731,7 @@
%
%
% \begin{macro}{\tbl_save_outer_table_cols:}
-%
+%
% \begin{macrocode}
\cs_new_protected:Npn \tbl_save_outer_table_cols: {
\tl_set_eq:NN \l_@@_saved_table_cols_tl \g_@@_table_cols_tl
@@ -718,7 +741,7 @@
%
%
% \begin{macro}{\tbl_init_cell_data_for_table:}
-%
+%
% \begin{macrocode}
\cs_new_protected:Npn \tbl_init_cell_data_for_table: {
\tl_set:No \l_@@_saved_col_tl {\int_use:N \g_@@_col_int }
@@ -832,14 +855,14 @@
%
%
% \begin{macro}{\tbl_restore_outer_cell_data:}
-%
+%
% \begin{macrocode}
\cs_new_protected:Npn \tbl_restore_outer_cell_data: {
\int_gset:Nn \g_@@_col_int { \l_@@_saved_col_tl }
\int_gset:Nn \g_@@_row_int { \l_@@_saved_row_tl }
\tl_gset_eq:NN \g_@@_span_tl \l_@@_saved_span_tl
\tl_gset_eq:NN \g_@@_table_cols_tl \l_@@_saved_table_cols_tl
- \UseTaggingSocket{tbl/restore/celldata}
+ \UseTaggingSocket{tbl/restore/celldata}
\@@_trace:n { ==>~ restored~cell~data:~
\int_use:N \g_@@_row_int,
\int_use:N \g_@@_col_int,
@@ -901,7 +924,7 @@
% the macro \cs{tbl_count_missing_cells:n} is executed and
% then the row is finished with a final \cs{cr}.
% \begin{macrocode}
-\cs_new:Npn \tbl_crcr:n #1 {
+\cs_new:Npn \tbl_crcr:n #1 {
\int_compare:nNnT \g_@@_col_int > 0
{
\tbl_count_missing_cells:n {#1}
@@ -928,7 +951,7 @@
% \changes{v1.0h}{2024/09/20}{moved \cs{@kernel@refstepcounter} into ltxref}
% This is needed for \pkg{longtable} because \cs{refstepcounter} is
% setting up a target when \pkg{hyperref} is loaded and we don't
-% want that in \pkg{longtable}.%%
+% want that in \pkg{longtable}.%%
% Prevent longtable patching by hyperref until hyperref does so automatically:
% \begin{macrocode}
\def\hyper@nopatch@longtable{}
diff --git a/Master/texmf-dist/source/latex-dev/base/lttextcomp.dtx b/Master/texmf-dist/source/latex-dev/base/lttextcomp.dtx
index 7f247747d6a..1ee4a18b7a9 100644
--- a/Master/texmf-dist/source/latex-dev/base/lttextcomp.dtx
+++ b/Master/texmf-dist/source/latex-dev/base/lttextcomp.dtx
@@ -2357,8 +2357,8 @@
% \changes{v1.1a}{2024/01/27}{Added check file for encoding subset}
% \begin{macrocode}
%<*TS1check>
-\Providesfile{checkencodingsubset.tex}
- [2024/01/27 v0.5a Figure out safe TS1 encoding subsets]
+\ProvidesFile{checkencodingsubset.tex}
+ [2024/10/18 v0.5b Figure out safe TS1 encoding subsets]
% \end{macrocode}
%
% \begin{macrocode}
diff --git a/Master/texmf-dist/source/latex-dev/base/ltvers.dtx b/Master/texmf-dist/source/latex-dev/base/ltvers.dtx
index 50c8b9a91fe..76a16e35281 100644
--- a/Master/texmf-dist/source/latex-dev/base/ltvers.dtx
+++ b/Master/texmf-dist/source/latex-dev/base/ltvers.dtx
@@ -112,10 +112,10 @@
%</2ekernel>
%<latexrelease>\edef\latexreleaseversion
%<*2ekernel|latexrelease>
- {2024-11-01}
+ {2025-06-01}
%</2ekernel|latexrelease>
%<*2ekernel>
-\def\patch@level{-4}
+\def\patch@level{0}
% \end{macrocode}
%
% \begin{macro}{\development@branch@name}
diff --git a/Master/texmf-dist/source/latex-dev/firstaid/latex2e-first-aid-for-external-files.dtx b/Master/texmf-dist/source/latex-dev/firstaid/latex2e-first-aid-for-external-files.dtx
index 4f473276f08..68877bc24dc 100644
--- a/Master/texmf-dist/source/latex-dev/firstaid/latex2e-first-aid-for-external-files.dtx
+++ b/Master/texmf-dist/source/latex-dev/firstaid/latex2e-first-aid-for-external-files.dtx
@@ -111,8 +111,8 @@
% \end{macrocode}
%
% \begin{macrocode}
-\def\LaTeXFirstAidDate{2024/07/05}
-\def\LaTeXFirstAidVersion{v1.1f}
+\def\LaTeXFirstAidDate{2024/10/16}
+\def\LaTeXFirstAidVersion{v1.1g}
% \end{macrocode}
%
% \begin{macrocode}
@@ -717,6 +717,34 @@
{[\@tempb][\arabic{page}][\cref@result]\thepage}{}{}{}}}% <------- five
\@esphack}%
}
+% \end{macrocode}
+% \changes{v1.1g}{2024/10/16}{update cleveref data in label hook}
+% cleveref patches and redefines \cs{refstepcounter} so that a call updates its data.
+% This fails if like e.g. in \pkg{longtable} the counter is stepped with
+% \cs{@kernel@refstepcounter}. We therefore move the data setup into the label hook.
+% As the hook is in a group we have to smuggle the data out of it.
+% \url{https://tex.stackexchange.com/a/722909/2388} and issue \#1393
+% \begin{macrocode}
+ \newcommand\firstaid@cref@smugglelabel{\let\cref@currentlabel\cref@gcurrentlabel@temp}
+ \newcommand\firstaid@cref@updatelabeldata[1]{%
+ \cref@constructprefix{#1}{\cref@result}%
+ \@ifundefined{cref@#1@alias}%
+ {\def\@tempa{#1}}%
+ {\def\@tempa{\csname cref@#1@alias\endcsname}}%
+ \protected@xdef\cref@gcurrentlabel@temp{%
+ [\@tempa][\arabic{#1}][\cref@result]%
+ \csname p@#1\endcsname\csname the#1\endcsname}%
+ \aftergroup\firstaid@cref@smugglelabel
+ }
+% \end{macrocode}
+% we test if \cs{@currentcounter} is empty for unnumbered sections
+% \begin{macrocode}
+ \AddToHook{label}[firstaid/cleveref]
+ {\ifx
+ \@currentcounter\@empty
+ \else
+ \firstaid@cref@updatelabeldata{\@currentcounter}
+ \fi}
}%
}
% \end{macrocode}
diff --git a/Master/texmf-dist/source/latex-dev/latex-lab/latex-lab-firstaid.dtx b/Master/texmf-dist/source/latex-dev/latex-lab/latex-lab-firstaid.dtx
index 083cfcdc40b..118baccd797 100644
--- a/Master/texmf-dist/source/latex-dev/latex-lab/latex-lab-firstaid.dtx
+++ b/Master/texmf-dist/source/latex-dev/latex-lab/latex-lab-firstaid.dtx
@@ -16,8 +16,8 @@
%
% for those people who are interested or want to report an issue.
%
-\def\ltlabfirstaiddate{2024-10-04}
-\def\ltlabfirstaidversion{0.85g}
+\def\ltlabfirstaiddate{2024-10-16}
+\def\ltlabfirstaidversion{0.85h}
%<*driver>
\documentclass{l3doc}
\EnableCrossrefs
@@ -125,6 +125,7 @@
\AddToHook{package/amsthm/after}[latex-lab-testphase-firstaid/amsthm]
{\tag_if_active:T{\@@_firstaid_amsthm:}}
% \end{macrocode}
+% \changes{v0.85h}{2024/10/16}{moved Caption tag into \@begintheorem, tagging issue\#733}
% \begin{macrocode}
\cs_new_protected:Npn \@@_firstaid_amsthm:
{
@@ -166,17 +167,27 @@
\def\@begintheorem##1##2[##3]{%
% \end{macrocode}
% We use the theorem instance.
+% \changes{v0.85h}{2024/10/16}{Added pre and post skips tagging/733}
% \begin{macrocode}
- \UseInstance{blockenv}{theorem}{}
+ \UseInstance{blockenv}{theorem}{beginsep=\thm@preskip}
+% \end{macrocode}
+% There is no working key to set the endskip, so we set the skip directly
+% similar to what amsthm is doing after the \cs{trivlist}.
+% \begin{macrocode}
+ \skip_set:Nn\l__block_topsepadd_skip { \thm@postskip }
% \end{macrocode}
% While create the caption/label we disable para-tagging.
% \begin{macrocode}
\tagpdfparaOff
\mode_leave_vertical:
% \end{macrocode}
-% The anchor for links
+% The anchor for links. amsthm allows for unnumbered theorems so we have to test
+% for an empty counter.
+% \changes{v0.85h}{2024/10/16}{add test if counter is empty tagging/736}
% \begin{macrocode}
- \MakeLinkTarget{\l__block_thm_current_counter_tl}
+ \tl_if_empty:NTF \l__block_thm_current_counter_tl
+ {\MakeLinkTarget[theorem]{}}
+ {\MakeLinkTarget{\l__block_thm_current_counter_tl}}
\group_begin:
\normalfont
\the\thm@headfont \thm@indent
@@ -197,7 +208,10 @@
\@ifempty{##3}
{\let\thmnote\@gobble}
{\def\thmnote####1{\tag_mc_begin:n{}####1\tag_mc_end:}}%
- \thm@swap\swappedhead\thmhead{##1}{##2}{##3}%
+ \tag_struct_begin:n{tag=Caption}
+ \thm@swap\swappedhead\thmhead{##1}{##2}{##3}%
+ \tag_mc_begin:n{}\the\thm@headpunct\tag_mc_end:
+ \tag_struct_end:
\thmheadnl % possibly a newline.
\hskip\thm@headsep
\group_end:
@@ -215,24 +229,17 @@
% to make tagging more easier.
% \begin{macrocode}
\def\thmhead@plain##1##2##3{%
- \tag_struct_begin:n{tag=Caption}
\thmname{##1}
\thmnumber{
\@ifnotempty{##1}{~}\@upn{##2}
}%
- \thmnote{\pdffakespace\space{\the\thm@notefont(##3)}}
- %moved for easier tagging
- \tag_mc_begin:n{}\the\thm@headpunct\tag_mc_end:
- \tag_struct_end:
+ \thmnote{\pdffakespace\space{\the\thm@notefont(##3)}}
}
\let\thmhead\thmhead@plain
\def\swappedhead##1##2##3{%
- \tag_struct_begin:n{tag=Caption}
\thmnumber{##2}
\thmname{\@ifnotempty{##2}{\nobreakspace}##1}
\thmnote{\pdffakespace\space{\the\thm@notefont(##3)}}
- \tag_mc_begin:n{}\the\thm@headpunct\tag_mc_end:
- \tag_struct_end:
}
\let\swappedhead@plain=\swappedhead
% \end{macrocode}
@@ -377,7 +384,9 @@
% \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
+% 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}
{
@@ -387,16 +396,6 @@
\protected@edef\cref@currentlabel{%
[footnote][\arabic{footnote}][\cref@result]%
\p@footnote\@thefnmark}}
-% \end{macrocode}
-% The second problem is that it redefines \cs{refstepcounter} to use an argument.
-% In itself this isn't a problem but as the new definition doesn't grab the arguments
-% directly it fails over the generic hook inserted at the end of the definition
-% \begin{macrocode}
- \RenewDocumentCommand\refstepcounter{om}{%
- \IfNoValueTF{#1}%
- {\refstepcounter@noarg{#2}}%
- {\refstepcounter@optarg[#1]{#2}}%
- }%
}
% \end{macrocode}
%
diff --git a/Master/texmf-dist/source/latex-dev/latex-lab/latex-lab-math.dtx b/Master/texmf-dist/source/latex-dev/latex-lab/latex-lab-math.dtx
index e8710b60a88..94d31c817b4 100644
--- a/Master/texmf-dist/source/latex-dev/latex-lab/latex-lab-math.dtx
+++ b/Master/texmf-dist/source/latex-dev/latex-lab/latex-lab-math.dtx
@@ -19,13 +19,13 @@
% for those people who are interested or want to report an issue.
%
%
-\def\ltlabmathdate{2024-10-12}
-\def\ltlabmathversion{0.6h}
+\def\ltlabmathdate{2024-10-25}
+\def\ltlabmathversion{0.6i}
%
%<*driver>
\documentclass{l3doc}
\EnableCrossrefs
-\CodelineIndex
+\CodelineIndex
\usepackage{todonotes}
@@ -40,7 +40,7 @@
% \title{The \texttt{latex-lab-math} code\thanks{}}
% \author{Frank Mittelbach, Joseph Wright, \LaTeX{} Project}
% \date{v\ltlabmathversion\ \ltlabmathdate}
-%
+%
% \maketitle
%
% \newcommand\NEW[1]{\marginpar{\mbox{}\hfill\fbox{New: #1}}}
@@ -77,21 +77,21 @@
% \tableofcontents
%
% \section{Introduction}
-% \car*{Todo: update all the documentation! Both here and
+% \car*{Todo: update all the documentation! Both here and
% (what little there is!) in the implementation section.}
%
% Tagging math involves a variety of tasks that require that math is captured before the
% typesetting
-% \begin{itemize}
-% \item When typesetting the math MC-tags and structure commands must
-% be inserted at the begin and the end, and perhaps also around lines
-% or other subparts of the equation.
+% \begin{itemize}
+% \item When typesetting the math MC-tags and structure commands must
+% be inserted at the begin and the end, and perhaps also around lines
+% or other subparts of the equation.
% \item The source and/or a mathml-representation of the source must be available
% so that it can be (perhaps after some preprocessing) be used in an associated file
% or in an alternate text
-% \item It must be possible to measure the math for e.g. a bbox setting.
+% \item It must be possible to measure the math for, e.g., a bbox setting.
% \end{itemize}
-%
+%
% This file implements capture of all math mode material at the outer
% level, i.e., a formula is captured in its entirety with inner text
% blocks (possibly containing further math) absorbed as part of the
@@ -101,24 +101,24 @@
%\end{verbatim}
% would only result in a single capture of the tokens
% ``\verb*/a \in A \text{ for all $a<5$}/''.
-%
+%
%
% \section{Math capture} \label{sec:mathcapture}
-% In the current setup
+% In the current setup
% \begin{itemize}
% \item |$|, |\(...\)| and |$$| grab (through a command in \cs{everymath}/cs{everydisplay})
% if the boolean \cs{l_@@_collected_bool} is false.
% If the boolean is true they behave normally and can for example contain verbatim.
-%
-% \item All (registered) environments grab their body
+%
+% \item All (registered) environments grab their body
% regardless of the state of the boolean. For
-% |equation|, |equation*| and |math| this is a change as they no longer can
+% |equation|, |equation*| and |math| this is a change as they no longer can
% contain verbatim.
-%
+%
% \item BUG: |\[...\]| grabs if \cs{l_@@_collected_bool} is false. If it is
-% true it falls back to |equation*| and then errors because this can't find the end.
-% \end{itemize}
-%
+% true it falls back to |equation*| and then errors because this can't find the end.
+% \end{itemize}
+%
% \subsection{Code level interfaces}
%
% \begin{function}{\math_register_env:n, \math_register_env:nn}
@@ -163,51 +163,52 @@
% material.
% \end{itemize}
% \end{function}
-%
+%
% \section{Math tagging}
-%
-% The tagging code has to handle
+%
+% \subsection{Code requirements}
+% The tagging code has to handle
% \begin{itemize}
-% \item the embedding into the surrounding. This means
-% \begin{itemize}
-% \item closing and reopening MC-chunks
+% \item the embedding into the surrounding. This means
+% \begin{itemize}
+% \item closing and reopening MC-chunks
% \item closing and reopening text/P-structures
% \item handling interferences of the tagging code with penalties and spacing.
% \end{itemize}
% \item the actual tagging which means to do some or all of the following tasks:
% \begin{itemize}
% \item setup content for an associated source file
-% \item setup content for an associated mathml file
+% \item setup content for an associated mathml file
% \item setup content for the /Alt key
% \item setup content for the /ActualText key
% \item setup attributes
-% \item add associated files
+% \item add associated files
% \item add a Formula structure
-% \item surround subparts (e.g. lines) with Formula sub structures
+% \item surround subparts (e.g., lines) with Formula sub structures
% (perhaps with their own set of additional content)
-% \item surround elements of the equation with mathml structure elements
+% \item surround elements of the equation with mathml structure elements
% (currently only luatex with luamml)
% \end{itemize}
% \end{itemize}
-%
+%
% \subsection{Inline math}
-%
+%
% The embedding code is added through
-% the sockets
+% the sockets
% \begin{itemize}
-% \item |tagsupport/math/inline/begin|
+% \item |tagsupport/math/inline/begin|
% \item |tagsupport/math/inline/end|
-% \end{itemize}
+% \end{itemize}
% The sockets simply push and pop the MC currently. Without
-% tagging they use the noop-plug.
-%
+% tagging they use the noop-plug.
+%
% The actual tagging is in done through the sockets
% \begin{itemize}
% \item |tagsupport/math/inline/formula/begin|
% This socket takes the math as argument and its code
-% should output it for typesetting.
+% should output it for typesetting.
% It is not \emph{used} as a tagging socket as the math argument should
-% not be lost without tagging, so without tagging the
+% not be lost without tagging, so without tagging the
% socket uses the identity plug.
% The |default| plug of the socket calls these three internal sockets
% for the tagging support:
@@ -218,62 +219,62 @@
% \item |tagsupport/math/struct/begin| This calls \cs{tag_struct_begin:n}.
% It should also write the associated files if needed.
% \item |tagsupport/math/substruct/begin| this handles subparts.
-% TODO: does it really make sense in inline math to have that??
+% TODO: does it really make sense in inline math to have that??
% \end{itemize}
% \item |tagsupport/math/inline/formula/end|
% This socket ends the formula structure(s). The |default|
% plug calls these internal sockets:
% \begin{itemize}
% \item |tagsupport/math/substruct/end|
-% \item |tagsupport/math/struct/end|
+% \item |tagsupport/math/struct/end|
% \end{itemize}
-% \end{itemize}
-%
+% \end{itemize}
+%
% \subsection{Display math}
-%
+%
% \textit{to be written}
-%
+%
% \subsection{Associated Files}
-%
+%
% The current code allows the attachment of two types of associated file to the
% Formula structure:
-% the \LaTeX\ source and a MathML representation.
+% the \LaTeX\ source and a MathML representation.
% Technically both can be attached---AF is an array
-% of file references---practically there can be problems with PDF consumers:
-% e.g. ngpdf used both and so showed the equation twice
-% (this has been corrected in the newest version) and
+% of file references-----in practice there can be problems with PDF consumers:
+% e.g., ngpdf used both and so showed the equation twice
+% (this has been corrected in the newest version) and
% Foxit seems to see only the first AF in the array (so we attach the
% mathml as first file).
-%
-% The \LaTeX\ source can be (and is) attached automatically.
+%
+% The \LaTeX\ source can be (and is) attached automatically.
% It can be suppressed by an option with
-% \texttt{math/tex/AF=false}, see below.
-%
-% The MathML is attached if the files |\jobname-mathml.html| and/or
-% |\jobname-luamml-mathml.html| are found
-% and if they contains a suitable MathML snippet for the current formula.
+% \texttt{math/tex/AF=false}, see below.
+%
+% The MathML is attached if the files |\jobname-mathml.html| and/or
+% |\jobname-luamml-mathml.html| are found
+% and if they contains a suitable MathML snippet for the current formula.
% If the files contain more than one suitable snippet (as identified by the hash)
-% the first one is used.
+% the first one is used.
% |\jobname-luamml-mathml.html| is automatically generated (see below section~\ref{sec:luamml})
% and read after |\jobname-mathml.html|. This means that |\jobname-mathml.html| can contain
-% improved versions of a formula.
-%
+% improved versions of a formula.
+%
% The MathML processing can be suppressed globally by emptying the list of
% mathml files with |math/mathml/sources=|. Locally for a formula |math/mathml/AF=false|
-% can be used.
-%
-% For a MathML representation a file with such representations must be provided.
-% If the equation is numbered the numbering should be part of the MathML as
+% can be used.
+%
+% For a MathML representation a file with such representations must be provided.
+% If the equation is numbered the numbering should be part of the MathML as
% the |Lbl| substructure is ignored if an MathML is used (see https://github.com/foxitsoftware/PDF_UA-2).
-%
-% The MathML representation is given in a special format.
+%
+% The MathML representation is given in a special format.
% It is meant to be a valid html file
% that can be viewed in a browser.
% For this it can start with |<!DOCTYPE html><html>| and end with |</html>|
-% It should have the extension \texttt{.html}. The \meta{mathml} content
+% It should have the extension \texttt{.html}. The \meta{mathml} content
% is read with special catcodes, so can contain ambersands, hashes, comment chars
% and unmatched braces such as |<mo>{</mo>|
-%
+%
% The file should contain a number of representations in this format:
% \begin{quote}
% |<div>| \\
@@ -287,197 +288,338 @@
% \end{quote}
% The keywords |<div>|, |<h2>\mml|, |<p>|, |<math|, |</math>| |</div>| are required as
% they are used to delimit the arguments by the \LaTeX{} code.
-%
+%
% \meta{key} and \meta{source} are only used for debugging, they help to identify
% the equation referred by this representation. The source should be used correctly escaped
% |&| and |<| so that if gives valid html!
-%
-% \meta{attributes} is not required either, but can e.g. contain attributes
+%
+% \meta{attributes} is not required either, but can, e.g., contain attributes
% to improve the display in a browser:
% \begin{verbatim}
% <math alttext="\mathbf{G}" class="ltx_Math" display="inline">
% \end{verbatim}
% It can also contain the name space declaration: |xmlns="http://www.w3.org/1998/Math/MathML"|%
% \footnote{But it is probably not needed and only blows up the PDF.}
-%
-%
-% By default the code tries at the begin of the document
-% to read a file |\jobname-mathml.html| in the |html|-format.
-% The file name can be changed with |mathml/setfiles={filename1,filename2}|
-% (without extension, |html| is added automatically).
-% If there is a list, all files are loaded.
+%
+%
+% By default the code tries at the begin of the document
+% to read a file |\jobname-mathml.html| in the |html|-format.
+% The file name can be changed with |mathml/setfiles={filename1,filename2}|
+% (without extension, |html| is added automatically).
+% If there is a list, all files are loaded.
% If a file doesn't exist it is ignored, only an info is written to the log.
-%
-% Currently every MathML-snippet from a file is embedded into the PDF,
-% it is not checked first if it is actually used (simply writing everything to the PDF
-% is a bit easier than keeping everything in memory and also means that
-% the snippets are one after the other in the PDF).
-%
-% As mentioned above the MathML-AF can be suppressed for the equations in a group with
+%
+% Currently every MathML-snippet from a file is embedded into the PDF,
+% it is not checked first if it is actually used (simply writing everything to the PDF
+% is a bit easier than keeping everything in memory and also means that
+% the snippets are one after the other in the PDF).
+%
+% As mentioned above the MathML-AF can be suppressed for the equations in a group with
% |math/mathml/AF=false|, or
-% completely by setting |math/mathml/sources=| in the preamble.
-%
+% completely by setting |math/mathml/sources=| in the preamble.
+%
% Files embedded in a PDF can be listed in the attachments panel of a PDF viewer.
% This is probably not so useful for lots of small files (but one could create
-% collections), but as long as PDF editors or viewers don't offer
+% collections), but as long as PDF editors or viewers don't offer
% proper support to access the AF it can help so have them there. The MathML are
% added by default, but the \LaTeX{} source not. This can be changed with
% |viewer/pane/mathsource=true| (anywhere in the document) and |viewer/pane/mathml=false| (in the
-% preamble, before the external file is read).
-%
-%
+% preamble, before the external file is read).
+%
+%
% \subsection{Automatic mathml creation with luamml}\label{sec:luamml}
-%
-% If lualatex is used, if the package \texttt{unicode-math} is used
-% and if the package \texttt{luamml} is found
-% then it will automatically generate the file |\jobname-luamml-mathml.html|
+%
+% If lualatex and the package \pkg{unicode-math} is used
+% the package \texttt{luamml} is loaded and
+% will automatically generate the file |\jobname-luamml-mathml.html|
% with mathml representations of all math formulas.
-% The generation of the file can be suppressed with |math/mathml/luamml=false|.
-% If \texttt{unicode-math} is not used,
-% the generation of the file can be forced
-% with |math/mathml/luamml=true| or |math/mathml/luamml| but be aware that
-% it is then probable that various symbols are mapped to the wrong unicode code
-% points.
-% The package is still quite experimental and the output should be checked.
-% The |\jobname-luamml-mathml.html| file may be previewed in a browser although
-% you may need to add additional css or javascript declarations
-% to enable browser support for all mathml constructs.
-% The file is then used in subsequent compilations and works also with
-% pdflatex.
+% This file is then used in subsequent compilations and works also with
+% pdflatex.
%
+% The generation of the file can be suppressed (in the preamble)
+% with |math/mathml/luamml/write=false|.
%
-% \subsection{Options}
-%
-%
+% If the package \pkg{unicode-math} is not used,
+% the loading of \pkg{luamml} and with it the generation of the file can be forced
+% with |math/mathml/luamml/load=true| or |math/mathml/luamml/write=true|
+% but be aware that it is then possible that various symbols
+% are mapped to the wrong Unicode code points.
+%
+% The package \pkg{luamml} is still quite experimental and the output should be checked.
+% The |\jobname-luamml-mathml.html| file may be previewed in a browser although
+% you may need to add additional css or javascript declarations
+% to enable browser support for all mathml constructs.
+%
+%
+% \subsection{Summary of math options}
+% The following options exist to make math more accessible:
+% \begin{description}
+% \item[ActualText] An \texttt{ActualText} can be placed on structure elements,
+% but can also be added in the stream on a \texttt{BDC} marker with a \texttt{Span}
+% tag (normally an independant marker without an MCID number, it is not clear yet
+% if it can be used on a MC-chunk).
+% The content is a text string, typically one or a few Unicode characters.
+% \texttt{ActualText} is meant to replaces the content
+% and should only be used on small entities,
+% e.g., to define the semantic or the Unicode code point of a symbol.
+% \texttt{ActualText} is not supported by all PDF reader.
+% It is also unknown where it should be used at best (in a structure element,
+% or on an independent Span-BDC) and what happens if it is used in more than
+% one place.
+% \begin{description}
+% \item[enabled by default?] False
+% \item[how to enable/disable] No interface yet.
+% \texttt{ActualText} can only be added on the Formula structure element by
+% changing the \texttt{tagsupport/math/content} or some other socket.
+% For a BDC marker one can, e.g., use
+% \begin{verbatim}
+% \pdf_string_from_unicode:nnN{utf16/hex}{€}\l_tmpa_tl
+% \pdf_bdc:ee{Span}{/ActualText\l_tmpa_tl}content\pdf_emc:
+% \end{verbatim}
+% There should be no pagebreak in the \meta{content} and the BDC should be correctly
+% nested into tagging, so, e.g., a \cs{leavevmode} should be issued before the bdc command.
+% \item[Consumer support] in part and in part buggy, needs tests \ldots
+% \end{description}
+%
+% \item[Alt] Like \texttt{ActualText} the \texttt{Alt} key can be used on
+% structure elements and on \texttt{Span} in the stream. It should contain a description
+% of the content and is mainly meant for images. PDF/UA-1,
+% which views math formulas as illustrations, mandates the key
+% also for \texttt{Formula} structure elements.
+% \begin{description}
+% \item[enabled by default?] false unless PDF/UA-1 is detected,
+% then it is enabled in the begindocument/end hook
+% (this will reconsidered when it is clear, that
+% the use of \texttt{Alt} does not shadow mathml). It can be enabled for
+% all engines and PDF versions.
+% \item[enable/disable] \verb+\tagpdfsetup{math/alt/use}+ (local boolean,
+% so can be used on individual equations)
+% \item[default value] A template text (stored in \cs{l_@@_content_template_tl})
+% starting with \texttt{LaTeX formula starts}.
+% \item[user value] No interface currently provided. This needs optional arguments
+% or an external setup command.
+% See \url{https://github.com/latex3/tagging-project/discussions/717}.
+%
+% \end{description}
+%
+% \item[source-AF] The \LaTeX{}-source of the equation can
+% be attached as an associated file with mime-type
+% application/Fx-tex. The \texttt{AFRelationship} is \texttt{Source}.
+% The source is embedded without expansion. This means that targets of
+% references and macros are not resolved.
+% The files are by default not shown in the EmbeddedFiles pane,
+% this can be enabled with |viewer/pane/mathsource=true|.
+% If an A-standard is used, it must be one that allows embedded files, e.g., A-4f.
+%
+% \begin{description}
+% \item[enabled by default?] true for all engines and PDF versions
+% \item[enable/disable] \verb+\tagpdfsetup{math/tex/AF}+ (local boolean, so can
+% be used on individual equations)
+% \item[default value] source code including dollars or environment name.
+% \item[consumer support] Currently only ngpdf makes
+% use of it: if there is no mathml it passes the source to mathjax.
+% \end{description}
+%
+% \item[luamml] The following options make (with lualatex) use
+% of the \pkg{luamml} package. \pkg{luamml} is currently automatically
+% loaded (at the end of the preamble) if \pkg{unicode-math} has been detected.
+% The loading can be forced or suppressed
+% with \verb+\tagpdfsetup{math/mathml/luamml/load=true/false}+.
+%
+% \pkg{luamml} affects all math, locally it can be stopped with |math/mathml/ignore|,
+% or by using the commands described in the package.
+%
+% \item[mathml-AF] A mathml representation of the equation can be attached
+% to the structure. The configuration possibilities are rather complex as the
+% keys have to control three different tasks:
+% The \emph{generation} of the file with the mathml fragments,
+% the \emph{reading} and \emph{embedding} of the mathml fragments,
+% and the \emph{association} of a mathml fragment to a specific equation.
+%
+% \begin{description}
+% \item[generation]
+% With pdf\LaTeX{} mathml fragments can not be generated automatically,
+% but a file with dummy fragments for every equation will be written if
+% \verb+\tagpdfsetup{math/mathml/write-dummy}+ is issued in the preamble.
+%
+% With lua\LaTeX{} a file with mathml fragments will be created automatically
+% if the package \pkg{luamml} has been loaded (see above).
+%
+% \item[reading and embedding]
+% By default the code will read and embed
+% mathml from |\jobname-mathml.html| and |\jobname-luamml-mathml.html| in this order and
+% the first fragment with a new hash value will be inserted.%
+% The list of sources and their order can be changed with the key
+% |math/mathml/sources|, setting that to an empty value suppresses
+% the loading mathml associated files completely. For efficiency reasons
+% it embeds math fragments directly, there is no check yet if the fragment is
+% actually used.
+%
+% The files are by default shown in the EmbeddedFiles pane,
+% this can be disabled with |viewer/pane/mathml=false|.
+%
+% \item[attaching] A mathml fragment is currently
+% attached as an associated file to an Formula if the hash of
+% the source matches the hash of the fragment. This is not a perfect test:
+% equations with the same source and so the same hash
+% can have different mathml representation, e.g.,
+% if there are references or commands or counters in the equation. This
+% will change in a feature version.
+% The attachment can be suppressed locally with |math/mathml/AF=false|.
+% The mathml fragment will still be embedded in the PDF!
+%
+% % TODO: adapt test
+% \end{description}
+%
+% \item[mathml structure elements]
+% Mathml structure elements can be used in PDF~2.0 directly.
+% In PDF~1.7. one could theoretically
+% use them if one declares a role mapping first,
+% (this can be done with \verb+\tagpdfsetup{role/mathml-tags}+)
+% which maps all to \texttt{Span}. But such a role mapping currently breaks reading,
+% e.g. in Adobe, and so it is not recommended.
+%
+% Automatic generation of structure elements is only possible with
+% lualatex. It requires that the packages \pkg{luamml} and \pkg{tagpdf}
+% have been loaded.
+% \begin{description}
+% \item[enabled by default?] false
+% \item[enable/disable] \verb+\tagpdfsetup{math/mathml/structelem}+
+% (local setting, so can be used with grouping on individual equations).
+% \item[consumer support] Needs more tests.
+% \end{description}
+%
+% \end{description}
+%
+%
+%
% \section{Known current bugs, etc.}
-% \car*{New Section, now with subsections.\\
-% As indicated, these lists are probably incomplete.\\
-% Some of these have been addressed in a more recent branch.}
%
% \subsection{Capture/grabbing problems}
-%
+%
% \begin{enumerate}
-% \item Incorrect grabbing of |$|-math when there is also
-% explicit |$|-math within a \textit{text environment}
+% \item Incorrect grabbing of |$|-math when there is also
+% explicit |$|-math within a \textit{text environment}
% that is itself within the math that should all be grabbed.
% For example,
% \begin{verbatim}
% $a\begin{minipage}{1cm}$b$\end{minipage}$
% \end{verbatim}
% would only result in the capture of the tokens
-% ``\verb*/a\begin {minipage}{1cm}/''.
+% ``\verb*/a\begin {minipage}{1cm}/''.
% This can be avoided by an additional brace group:
% \begin{verbatim}
% $a{\begin{minipage}{1cm}$b$\end{minipage}}$
-% \end{verbatim}
-%
+% \end{verbatim}
+%
% \item Similar incorrect grabbing with |$$| also.
-%
+%
% \item The grabbing, for all the display environments (and |\) \]|), needs
-% to deal with nesting: \pkg{amsmath} contains code for this.
-%
-% \item The math can't contain verbatim and verbatim-like commands. This is
+% to deal with nesting: \pkg{amsmath} contains code for this.
+%
+% \item The math can't contain verbatim and verbatim-like commands. This is
% nothing new for the \pkg{amsmath} environments but changes |$| and |\[\]|
-% and |equation*| (see e.g. tagging-project issue \#30).
-%
+% and |equation*| (see, e.g., tagging-project issue \#30).
+%
% \item Begin and end of the math or math environment can not be hidden in commands.
-% For example \verb+>{$}l<{$}+ in a tabular would lead to errors.
-% Defining |\[| to fall back to |equation*| doesn't work if |equation*| is
+% For example \verb+>{$}l<{$}+ in a tabular would lead to errors.
+% Defining |\[| to fall back to |equation*| doesn't work if |equation*| is
% a grabbing environment.
-%
+%
% \item The behaviour of |\[...\]| is faulty. See above.
-% \end{enumerate}
+% \end{enumerate}
%
% \subsection{Fake math}
-% In a number of places in \LaTeX{} math commands (mainly |$|) is used
-% only for technical reason, e.g. to access a math font, to setup a symbol
-% or to use \cs{vcenter}.
-%
+% In a number of places in \LaTeX{} math commands (mainly |$|) is used
+% only for technical reason, e.g., to access a math font, to setup a symbol
+% or to use \cs{vcenter}.
+%
% The code identifies such fake math mostly by making use of the \cs{m@th} command
% where two methods are used for the automatic detection:
-%
+%
% \begin{itemize}
-% \item After grabbing math content the code checks if the content contains the token
+% \item After grabbing math content the code checks if the content contains the token
% \cs{m@th} and if yes it doesn't call the processor before reinserting
% the content and perhaps adding tagging code.
% This method requires that the math can be grabbed (e.g. that the end dollar is visible)
% and that the \cs{m@th} is visible. It applies for example in \cs{@iiiparbox} where the
% code from |$\vcenter| to |\m@th$| is grabbed an put back. It does not work for
% example for |tabular| where the dollars and the \cs{m@th} token are spread around
-% over three commands. |tabular| needs therefore manual intervention.
-%
+% over three commands. |tabular| needs therefore manual intervention.
+%
% A look in the list of usages (in \texttt{usage-of-m@th.md}) justifies this approach.
% All usages are either not math at all, or related to small elements that probably
-% shouldn't be grabbed and processed on their own.
+% shouldn't be grabbed and processed on their own.
%
% \item \cs{m@th} is redefined so that it sets the boolean \cs{l_@@_collected_bool}
% to true. If \cs{m@th} is used inside math that has been grabbed
% this doesn't change much as the boolean is set by the grabbing anyway. For usages
% outside math the benefit is not so clear: The setting avoids that in \cs{LaTeXe}
% the epsilon is processed as math, but it also prevents that the content of the amsmath
-% command \cs{boxed} is processed as math.
+% command \cs{boxed} is processed as math.
% It means that if one wants to reenable math processing inside some (fake) math
% one has to do it after \cs{m@th} calls.
% \end{itemize}
-%
-% Open problems
+%
+% \subsubsection{Open problems}
+%
% \begin{enumerate}
% \item The grabbing code doesn't pass the info that it detected a \cs{m@th} token.
% This means that the tagging code has to do the same check (and doesn't do this
% in all cases yet).
-%
-% \item Commands are missing to locally disable the grabbing and processing, e.g.
+%
+% \item Commands are missing to locally disable the grabbing and processing, e.g.,
% to handle |tabular|.
-%
+%
% \item It must be checked if setting the boolean in \cs{m@th} really makes sense
-% or if commands like \cs{LaTeXe} should be handled manually.
-%
+% or if commands like \cs{LaTeXe} should be handled manually.
+%
% \end{enumerate}
-%
+%
% \subsection{Processor}
-%
+%
% The grabbed math is at first passed to the processor. The processor is not called
-% in a measuring phase (from the amsmath \cs{ifmeasuring@}) and if the \cs{m@th}
-% token is detected.
+% in a measuring phase (from the amsmath \cs{ifmeasuring@}) and if the \cs{m@th}
+% token is detected.
% It is not quite clear what purpose the processor has. As it is a public interface
% it can't be used for internal code. And typesetting happens later and the processor
% can't really change this. Currently it is mostly used for debugging and messages.
% If the \cs{m@th} is found the \cs{l_@@_fakemath_bool} is set, so if the code
% is changed this must be preserved.
-%
+%
% \subsection{Other problems}
-%
-% \begin{enumerate}
-% \item
+%
+% \begin{enumerate}
+% \item
% The presence of \cs{m@th} in association with \cs{ensuremath}
-% does not necessarily indicate fakemath. This is because
-% wanting mathsurround to be zero is very reasonable and common,
+% does not necessarily indicate fakemath. This is because
+% wanting mathsurround to be zero is very reasonable and common,
% \emph{even when the math is genuine} (and hence needs to be collected).
-%
-% TODO: this claim needs some examples.
-%
-% \item User-defined environments can create problems; but this area, of
-% new, copied and changed environments, has not yet been developed.
-%
+%
+% TODO: this claim needs some examples.
+%
+% \item User-defined environments can create problems; but this area, of
+% new, copied and changed environments, has not yet been developed.
+%
% \car*{Joseph wrote, inter alia:\\
% My thinking [regarding] \cs{RegisterMathEnvironment}\\
% - (New) Math environments should not be created-then-patched, but only
-% generated by a [(future)] dedicated command (\cs{DeclareMathEnvironment},
+% generated by a [(future)] dedicated command (\cs{DeclareMathEnvironment},
% presumably)\\
% - Math environments created with \pkg{ltcmd} [commands] should not be copied, . . .\\
% - Package authors should be able to manually set up math environments with a public boolean.}
-% \end{enumerate}
+% \end{enumerate}
%
%
% \subsection{Other ToDos}
%
% \begin{enumerate}
-% \item Add (some of) the math display commands that were \enquote{lifted from
+% \item Add (some of) the math display commands that were \enquote{lifted from
% plain}, e.g., \cs{displaylines} \cs{eqalign}(??).
% \item The breqn packages changes catcodes and that isn't yet covered
% by our mechanism.
% \item \cs{intertext} is not correctly taken into account by the
-% code splitting multiline math into subformulas.
+% code splitting multiline math into subformulas.
% \end{enumerate}
%
%
@@ -524,7 +666,7 @@
% neatly.
% \begin{macrocode}
\AddToHook{begindocument/before}{ \RequirePackage { amsmath } }
-% \end{macrocode}
+% \end{macrocode}
%
%
% \subsection{Data structures}
@@ -532,7 +674,7 @@
% \begin{variable}{\l_@@_collected_bool}
% Tracks whether math mode material has been collected, which happens inside
% \pkg{amsmath} environments as well as those handled directly here.
-% If true following math will not grab and/or process.
+% If true following math will not grab and/or process.
% See \ref{sec:mathcapture} for details.
% \begin{macrocode}
\bool_new:N \l_@@_collected_bool
@@ -541,7 +683,7 @@
%
% \begin{variable}{\l_@@_fakemath_bool}
% Tracks whether math mode material has been identified as fake math during
-% the grabbing phase, which happens currently if the
+% the grabbing phase, which happens currently if the
% grabbed contents contains the \cs{m@th} token.
%
% \begin{macrocode}
@@ -562,7 +704,7 @@
\tl_new:N \g_@@_grabbed_math_tl
% \end{macrocode}
% \end{variable}
-%
+%
% \begin{variable}{\l_@@_tmpa_tl,\l_@@_tmpa_skip,\l_@@_tmpa_str}
% Temporary variables
% \begin{macrocode}
@@ -575,8 +717,8 @@
% \begin{variable}{\l_@@_content_alt_tl,
% \l_@@_content_actual_tl,
% \l_@@_content_AF_tl}
-% Temporary variables to hold math content that should
-% be used in actual or alt text and stored as AF.
+% Temporary variables to hold math content that should
+% be used in actual or alt text and stored as AF.
% \begin{macrocode}
\tl_new:N \l_@@_content_alt_tl
\tl_new:N \l_@@_content_actual_tl
@@ -585,15 +727,15 @@
\tl_new:N \l_@@_content_AF_mathml_tl
% \end{macrocode}
% \end{variable}
-%
+%
% \subsection{Tagging tools}
-% The following commands implement small tagging code chunks.
+% The following commands implement small tagging code chunks.
% This should probably be collected and moved into tagpdf later.
% \begin{macro}{\__tag_tool_close_P:}
% This closes a P/text-chunk, both the MC and the structure and
% increases the counter manually.
% \begin{macrocode}
-\cs_new_protected:Npn \__tag_tool_close_P:
+\cs_new_protected:Npn \__tag_tool_close_P:
{
\tag_if_active:T
{
@@ -605,14 +747,14 @@
}
% \end{macrocode}
% \end{macro}
-%
-% We add also an attribute.
-% \begin{macrocode}
+%
+% We add also an attribute.
+% \begin{macrocode}
\tl_new:N\l_@@_attribute_class_tl
\tagpdfsetup
{role/new-attribute = {inline} {/O /Layout /Placement/Inline},
role/new-attribute = {display} {/O /Layout /Placement/Block},
- }
+ }
% \end{macrocode}
%
% \subsection{Code related to AF}
@@ -640,7 +782,7 @@
\tl_gset:Nn\g__tag_math_luamml_tl {0}
% \end{macrocode}
% \end{variable}
-%
+%
% \begin{variable}{
% \g_@@_mathml_total_int,
% \g_@@_mathml_int,
@@ -650,13 +792,13 @@
% }
% \cs{g_@@_mml_total_int} records the mathml fragments read in.
% \cs{g_@@_mml_int} records the mathml fragments read in with a different hash.
-% \cs{g_@@_AF_total_int} records the number of math structures that try to
-% attach a mathml AF.
+% \cs{g_@@_AF_total_int} records the number of math structures that try to
+% attach a mathml AF.
% \cs{g_@@_AF_found_int} records the number of math structures for which a fitting
-% mathml is found.
+% mathml is found.
% \cs{g_@@_AF_attached_int} records the number of math structures which got a mathml fragment
% (if mathml-AF are not disabled locally this should be the equal to the previous number.
-%
+%
% \begin{macrocode}
\int_new:N\g_@@_mathml_total_int
\int_new:N\g_@@_mathml_int
@@ -668,15 +810,15 @@
%
% \begin{variable}{\l__tag_math_mathml_files_clist}
% A sequence to store the file list for the mathml.
-% If luatex is detected with also check the luamml file.
+% We also check the luamml file.
% \begin{macrocode}
\clist_new:N\l__tag_math_mathml_files_clist
-\clist_put_right:Ne\l__tag_math_mathml_files_clist
+\clist_put_right:Ne\l__tag_math_mathml_files_clist
{\c_sys_jobname_str-mathml,\c_sys_jobname_str-luamml-mathml}
% \end{macrocode}
% \end{variable}
-
-% This is the internal variant of the \cs{mml} command.
+%
+% This is the internal variant of the \cs{mml} command.
% \begin{macro}{\@@_AF_mml:nnnn}
% \begin{macrocode}
\cs_new_protected:Npn \@@_AF_mml:nnnn #1 #2 #3 #4
@@ -692,22 +834,22 @@
% \end{macrocode}
% a simple Desc key, take care that it is a valid string!
% \begin{macrocode}
- \pdfdict_put:nne {l_pdffile/Filespec} {Desc}{(mathml-#1)}
+ \pdfdict_put:nne {l_pdffile/Filespec} {Desc}{(mathml-#1)}
\pdffile_embed_stream:nnN {#4}{mathml-#1.xml}\l_@@_tmpa_tl
% \end{macrocode}
-% not strictly necessary but makes the files visible in the file attachment
-% page
+% not strictly necessary but makes the files visible in the file attachment
+% page
% \begin{macrocode}
\bool_if:NT \l__tag_math_mathml_pane_bool
{\pdfmanagement_add:nne {Catalog/Names}{EmbeddedFiles}{\l_@@_tmpa_tl}}
\tl_new:c{g_@@_mathml_#3_tl}
- \tl_gset_eq:cN{g_@@_mathml_#3_tl}\l_@@_tmpa_tl
+ \tl_gset_eq:cN{g_@@_mathml_#3_tl}\l_@@_tmpa_tl
}
- }
+ }
% \end{macrocode}
% \end{macro}
%
-% The html reader.
+% The html reader.
% \begin{macrocode}
\cs_new_protected:Npn \@@_AF_html_reader:w#1</h2>#2<p>#3</p>#4<p>#5</p>#6<math{
\begingroup
@@ -725,36 +867,36 @@
}
% \end{macrocode}
%
-% As with luatex we write two files we define a few constants for
+% As with luatex we write two files we define a few constants for
% the shared texts.
-%
+%
% \begin{macro}
% {\c_@@_mathml_write_init_tl,\l_@@_mathml_write_before_tl,
-% \c_@@_mathml_write_after_tl,\c_@@_mathml_write_final_tl}
+% \c_@@_mathml_write_after_tl,\c_@@_mathml_write_final_tl}
% \begin{macrocode}
-\tl_const:Nn \c_@@_mathml_write_init_tl
+\tl_const:Nn \c_@@_mathml_write_init_tl
{
<!DOCTYPE~html>
\iow_newline:
<html>
\iow_newline:
}
-\tl_new:N \l_@@_mathml_write_before_tl
-\tl_const:Nn \c_@@_mathml_write_after_tl
+\tl_new:N \l_@@_mathml_write_before_tl
+\tl_const:Nn \c_@@_mathml_write_after_tl
{
\iow_newline:
</div>
\iow_newline:
- }
-\tl_const:Nn \c_@@_mathml_write_final_tl
+ }
+\tl_const:Nn \c_@@_mathml_write_final_tl
{
</html>
- }
+ }
% \end{macrocode}
% \end{macro}
% \begin{socketdecl}{tagsupport/math/mathml/write/prepare}
-% To prepare the hash and the starting command we use a socket, so
+% To prepare the hash and the starting command we use a socket, so
% that both the dummy and luamml can make use of it.
% \begin{macrocode}
\socket_new:nn {tagsupport/math/mathml/write/prepare}{0}
@@ -768,7 +910,7 @@
\str_set:NV\l_@@_tmpa_str\l_@@_content_AF_source_tl
\str_replace_all:Nnn\l_@@_tmpa_str{&}{&amp;}
\str_replace_all:Nnn\l_@@_tmpa_str{<}{&lt;}
- \tl_set:Nn \l_@@_mathml_write_before_tl
+ \tl_set:Nn \l_@@_mathml_write_before_tl
{
<div>
\iow_newline:
@@ -778,39 +920,62 @@
\iow_newline:
<p>\l_@@_content_hash_tl </p>
\iow_newline:
- }
+ }
}
% \end{macrocode}
% \end{plugdecl}
%
-% With luatex we automatically generate mathml with luamml if the package
-% can be loaded and unicode-math is detected.
+% With luatex we automatically generate mathml with \pkg{luamml} if the package
+% can be loaded and \pkg{unicode-math} is detected.
% We start the process in the begindocument/end hook
% so that the reading from a previous compilation can happen before!
+%
+% For other engines, for future name changes
+% and in case luamml is not loaded we provide
+% some commands
% \begin{macrocode}
-\sys_if_engine_luatex:T
- {
- \file_if_exist:nT { luamml.sty }
+\cs_new_protected:Npn\@@_provide_luamml_commands:
+ {
+ \providecommand\luamml_flag_structelem:{}
+ \cs_if_free:NT \luamml_structelem:
{
- \RequirePackage { luamml }
+ \cs_set_eq:NN\luamml_structelem:\luamml_flag_structelem:
+ }
+ \providecommand\luamml_flag_process:{}
+ \cs_if_free:NT \luamml_process:
+ {
+ \cs_set_eq:NN\luamml_process:\luamml_flag_process:
+ }
+ \providecommand\luamml_flag_ignore:{}
+ \cs_if_free:NT \luamml_ignore:
+ {
+ \cs_set_eq:NN\luamml_ignore:\luamml_flag_ignore:
+ }
+ }
+% \end{macrocode}
+% \begin{macrocode}
+\sys_if_engine_luatex:TF
+ {
% \end{macrocode}
-% Temporary (!) fixes for endarray
+% Temporary (!) fixes for endarray
% \begin{macrocode}
+ \cs_new_protected:Npn \@@_correct_luamml_array_patches:
+ {
\AddToHook{package/array/after}
{
- \cs_set:Npn \endarray
+ \cs_set:Npn \endarray
{
\tbl_crcr:n{endarray}
\__luamml_array_save_array:
\egroup
\UseTaggingSocket{tbl/finalize}
- \tbl_restore_outer_cell_data:
+ \tbl_restore_outer_cell_data:
\egroup
\mode_if_math:T { \__luamml_array_finalize_array: }
\@arrayright
\gdef \@preamble {}
}
- \cs_set:Npn \@classz
+ \cs_set:Npn \@classz
{
\@classx
\@tempcnta \count@
@@ -881,125 +1046,198 @@
\fi
}
\prepnext@tok
- }
- }
-% \end{macrocode}
-%
-% \begin{macrocode}
- \AddToHook{begindocument/end}
- {
- \str_case:on \g__tag_math_luamml_tl
- {
- { 1 } {
- \@@_luamml_activate_write:
- \msg_note:nnnn { tag }
- { luamml-status }{ enabled }{ create }
- }
- {-1 } {
- \msg_note:nnnn { tag }
- { luamml-status }{ disabled }{ not~create }
- }
- { 0 }
- {
- \@ifpackageloaded { unicode-math }
- {
- \@@_luamml_activate_write:
- \msg_note:nnnn { tag }
- { luamml-status }{ enabled }{ create }
+ }
+ }
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+ \AddToHook{begindocument/before}
+ {
+ \str_case:on \g_@@_luamml_load_tl
+ {
+ { 1 } {
+ \RequirePackage { luamml }
+ \@@_correct_luamml_array_patches:
+ \AddToHook{begindocument/end}
+ {
+ \@@_luamml_activate_write:
+ }
+ }
+ {-1 } {
+ \AddToHook{begindocument/end}
+ {
+ \msg_note:nnnn { tag }
+ { luamml-status }{ disabled }{ not~create }
+ }
+ }
+ { 0 }
+ {
+ \@ifpackageloaded { unicode-math }
+ {
+ \RequirePackage { luamml }
+ \@@_correct_luamml_array_patches:
+ \AddToHook{begindocument/end}
+ {
+ \@@_luamml_activate_write:
}
- { \msg_warning:nn { tag }{ unicode-math-missing } }
- }
- }
+ }
+ { \msg_warning:nn { tag }{ unicode-math-missing } }
+ }
}
+ \@@_provide_luamml_commands:
}
}
-\msg_new:nnn { tag }{ luamml-status }
+ {
+ \@@_provide_luamml_commands:
+ }
+\msg_new:nnn { tag }{ luamml-status }
{
luamml~has~been~#1~and~will~#2~an~MathML~file.
- }
-
-\msg_new:nnn { tag }{ unicode-math-missing }
+ }
+
+\msg_new:nnn { tag }{ unicode-math-missing }
{
The~package~unicode-math~is~missing\\
luamml~will~not~create~an~MathML~file.\\
To~avoid~this~warning~load~unicode-math~\\
or~disable~luamml~with~\\
- \tl_to_str:n{\tagpdfsetup{math/mathml/luamml=false}}\\
+ \tl_to_str:n{\tagpdfsetup{math/mathml/luamml/load=false}}\\
or~force~luamml~with~\\
- \tl_to_str:n{\tagpdfsetup{math/mathml/luamml=true}}
- }
+ \tl_to_str:n{\tagpdfsetup{math/mathml/luamml/load=true}}
+ }
\cs_new_protected:Npn \@@_luamml_activate_write:
{
+ \bool_if:NT \g_@@_luamml_write_bool
+ {
% \end{macrocode}
% to avoid that nothing is written in the first run, we must activate the sockets:
% \begin{macrocode}
- \bool_gset_true:N\g__tag_math_mathml_AF_bool
- \AssignSocketPlug{tagsupport/math/struct/begin}{test-mathml}
- \AssignSocketPlug{tagsupport/math/struct/end}{test-mathml}
- \AssignSocketPlug{tagsupport/math/substruct/begin}{single}
- \AssignSocketPlug{tagsupport/math/substruct/end}{single}
- \int_set:Nn \l__luamml_pretty_int { 5 }
- \RegisterFamilyMapping\symsymbols{oms}
- \RegisterFamilyMapping\symletters{oml}
- \AssignSocketPlug{tagsupport/math/mathml/write/prepare}{On}
- \iow_new:N \g_@@_luamml_iow
- \iow_open:Nn \g_@@_luamml_iow {\c_sys_jobname_str-luamml-mathml.html}
- \iow_now:Ne \g_@@_luamml_iow { \c_@@_mathml_write_init_tl }
- \cs_new:Npn \@@_luamml_output_hook:n ##1
- {
- \tl_if_empty:NF \l_@@_mathml_write_before_tl
- {
- \iow_now:Ne \g_@@_luamml_iow
- {
- \l_@@_mathml_write_before_tl
- ##1
- \c_@@_mathml_write_after_tl
- }
- }
+ \bool_gset_true:N\g__tag_math_mathml_AF_bool
+ \AssignSocketPlug{tagsupport/math/struct/begin}{mathml-AF}
+ \AssignSocketPlug{tagsupport/math/struct/end}{mathml-AF}
+ \AssignSocketPlug{tagsupport/math/substruct/begin}{single}
+ \AssignSocketPlug{tagsupport/math/substruct/end}{single}
+ \int_set:Nn \l__luamml_pretty_int { 7 }
+ \RegisterFamilyMapping\symsymbols{oms}
+ \RegisterFamilyMapping\symletters{oml}
+ \AssignSocketPlug{tagsupport/math/mathml/write/prepare}{On}
+ \iow_new:N \g_@@_luamml_iow
+ \iow_open:Nn \g_@@_luamml_iow {\c_sys_jobname_str-luamml-mathml.html}
+ \iow_now:Ne \g_@@_luamml_iow { \c_@@_mathml_write_init_tl }
+ \cs_new:Npn \@@_luamml_output_hook:n ##1
+ {
+ \tl_if_empty:NF \l_@@_mathml_write_before_tl
+ {
+ \iow_now:Ne \g_@@_luamml_iow
+ {
+ \l_@@_mathml_write_before_tl
+ ##1
+ \c_@@_mathml_write_after_tl
+ }
+ }
+ }
+ \__luamml_register_output_hook:N \@@_luamml_output_hook:n
+% \end{macrocode}
+% At the end of the document we must finish and close the file:
+% \begin{macrocode}
+ \AddToHook{enddocument/afterlastpage}
+ {
+ \iow_now:Ne \g_@@_luamml_iow
+ { \c_@@_mathml_write_final_tl }
+ \iow_close:N \g_@@_luamml_iow
+ }
+ \msg_note:nnnn { tag }
+ { luamml-status }{ enabled }{ create }
}
- \__luamml_register_output_hook:N \@@_luamml_output_hook:n
+ }
% \end{macrocode}
-% this starts the process and set flag to 3,
-% not really needed, as it is the default but set here for clarity:
+% And now keys to activate/deactivate luamml feature
+% \begin{variable}{\g_@@_luamml_load_tl}
+% This variable will be used to suppress the loading of luamml
+% altogether.
% \begin{macrocode}
- \luamml_flag_process:
+\tl_new:N \g_@@_luamml_load_tl
+\tl_gset:Nn \g_@@_luamml_load_tl {0}
% \end{macrocode}
-% At the end of the document we must finish and close the file:
+% \end{variable}
+% \begin{variable}{\g_@@_luamml_write_bool}
+% This variable decides if luamml writes a mathml
+% altogether.
% \begin{macrocode}
- \AddToHook{enddocument/afterlastpage}
- {
- \iow_now:Ne \g_@@_luamml_iow
- { \c_@@_mathml_write_final_tl }
- \iow_close:N \g_@@_luamml_iow
- }
- }
+\bool_new:N \g_@@_luamml_write_bool
+\bool_gset_true:N \g_@@_luamml_write_bool
% \end{macrocode}
-% And now a key to deactivate luamml
+% \end{variable}
+%
% \begin{macrocode}
-
+\msg_new:nnn { tag }{ PDF-2.0-recommended }
+ {
+ The~key~#1~will~not~work~properly~with~PDF~#2.\\
+ Switching~to~PDF~2.0~is~recommended.
+ }
\keys_define:nn { __tag / setup }
{
- math/mathml/luamml .choice: ,
- math/mathml/luamml/true .code:n = {\tl_gset:Nn \g__tag_math_luamml_tl{1}},
- math/mathml/luamml/false .code:n = {\tl_gset:Nn \g__tag_math_luamml_tl{-1}},
- math/mathml/luamml .default:n = true,
- math/mathml/luamml .usage:n=preamble
+% \end{macrocode}
+% At first a key to suppress the loading altogether
+% \begin{macrocode}
+ math/mathml/luamml/load .choice: ,
+ math/mathml/luamml/load/true .code:n = {\tl_gset:Nn \g_@@_luamml_load_tl{1}},
+ math/mathml/luamml/load/false .code:n = {\tl_gset:Nn \g_@@_luamml_load_tl{-1}},
+ math/mathml/luamml/load .default:n = true,
+ math/mathml/luamml/load .usage:n=preamble,
+% \end{macrocode}
+% A key to activate math structure elements. It shouldn't
+% be issued in the preamble as luamml is not yet loaded.
+% \begin{macrocode}
+ math/mathml/structelem .code:n =
+ {
+ \pdf_version_compare:NnT < {2.0}
+ {
+ \msg_warning:nnne { tag }{ PDF-2.0-recommended }
+ { math/mathml/structelem }{ \pdf_version: }
+ }
+ \AddToHook{begindocument/end}{\luamml_structelem:}
+ },
+% \end{macrocode}
+% and a key to call the ignore flag. This should only be used locally.
+% \begin{macrocode}
+ math/mathml/ignore .code:n = {\luamml_ignore:},
+% \end{macrocode}
+% \begin{macrocode}
+ math/mathml/luamml/write .choice:,
+ math/mathml/luamml/write/true .code:n =
+ {
+ \tl_gset:Nn \g_@@_luamml_load_tl{1}
+ \bool_gset_true:N \g_@@_luamml_write_bool
+ },
+ math/mathml/luamml/write/false .code:n =
+ {
+ \bool_gset_false:N \g_@@_luamml_write_bool
+ },
+ math/mathml/luamml/write .default:n = true,
+ math/mathml/luamml/write .usage:n=preamble,
+% \end{macrocode}
+% alias keys for compatibility
+% \begin{macrocode}
+ math/mathml/luamml .bool_gset:N = \g_@@_luamml_write_bool,
+ math/mathml/luamml .usage:n=preamble
}
% \end{macrocode}
% \begin{socketdecl}{tagsupport/math/mathml/write}
% This writes a html-dummy with the hash and the math content.
% This should be optional, so it uses a socket that can be disabled
-%
+%
% \begin{macrocode}
\socket_new:nn {tagsupport/math/mathml/write}{0}
% \end{macrocode}
% \end{socketdecl}
-%
+%
% \begin{plugdecl}{On}
% \begin{macrocode}
\socket_new_plug:nnn{tagsupport/math/mathml/write}{On}
{
- \iow_now:Ne \g_@@_writedummy_iow
+ \iow_now:Ne \g_@@_writedummy_iow
{
\l_@@_mathml_write_before_tl
<math></math>
@@ -1013,32 +1251,32 @@
\keys_define:nn { __tag / setup }
{
- math/mathml/write-dummy .code:n =
+ math/mathml/write-dummy .code:n =
{
\bool_gset_true:N \g__tag_math_mathml_AF_bool
- \tl_if_exist:NF\g_@@_writedummy_iow
+ \tl_if_exist:NF\g_@@_writedummy_iow
{
\iow_new:N \g_@@_writedummy_iow
- \iow_open:Nn \g_@@_writedummy_iow
- {
+ \iow_open:Nn \g_@@_writedummy_iow
+ {
\c_sys_jobname_str-mathml-dummy.html
}
\iow_now:Ne \g_@@_writedummy_iow
{
\c_@@_mathml_write_init_tl
}
- \AssignSocketPlug {tagsupport/math/mathml/write/prepare}{On}
+ \AssignSocketPlug {tagsupport/math/mathml/write/prepare}{On}
\AssignSocketPlug {tagsupport/math/mathml/write}{On}
\AddToHook{enddocument/afterlastpage}
{
- \iow_now:Ne \g_@@_writedummy_iow
+ \iow_now:Ne \g_@@_writedummy_iow
{ \c_@@_mathml_write_final_tl }
\iow_close:N \g_@@_writedummy_iow
}
- }
+ }
},
- math/mathml/write-dummy .usage:n=preamble
- }
+ math/mathml/write-dummy .usage:n=preamble
+ }
% \end{macrocode}
%
% \begin{macro}{\@@_AF_process_mathml_files:}
@@ -1049,9 +1287,9 @@
\hbox_set:Nn \l_@@_tmpa_box
{
\pdfdict_put:nnn { l_pdffile/Filespec }{AFRelationship} { /Supplement }
- \pdfdict_put:nne
- { l_pdffile }{Subtype}
- { \pdf_name_from_unicode_e:n{application/mathml+xml} }
+ \pdfdict_put:nne
+ { l_pdffile }{Subtype}
+ { \pdf_name_from_unicode_e:n{application/mathml+xml} }
\char_set_catcode_other:N \#
\cs_set_eq:NN\mml \@@_AF_html_reader:w
\clist_map_inline:Nn \l__tag_math_mathml_files_clist
@@ -1065,13 +1303,13 @@
{
\typeout{Info:~mathml~file~##1~does~not~exist}%info message
}
- }
+ }
}
\bool_if:NT\g__tag_math_mathml_AF_bool
{
\typeout{Info:~Activating~mathml~support}
- \AssignSocketPlug{tagsupport/math/struct/begin}{test-mathml}
- \AssignSocketPlug{tagsupport/math/struct/end}{test-mathml}
+ \AssignSocketPlug{tagsupport/math/struct/begin}{mathml-AF}
+ \AssignSocketPlug{tagsupport/math/struct/end}{mathml-AF}
% \end{macrocode}
% mathml handling doesn't like subparts, so we disable them for now:
% \begin{macrocode}
@@ -1081,29 +1319,29 @@
{
\iow_term:n{MathML~statistic}
\iow_term:n{================}
- \iow_term:e{==>~\int_use:N\g_@@_mathml_total_int\c_space_tl
+ \iow_term:e{==>~\int_use:N\g_@@_mathml_total_int\c_space_tl
MathML~fragments~read}
- \iow_term:e{==>~\int_use:N\g_@@_mathml_int\c_space_tl
+ \iow_term:e{==>~\int_use:N\g_@@_mathml_int\c_space_tl
different~MathML~fragments}
- \iow_term:e{==>~\int_use:N\g_@@_math_total_int\c_space_tl
+ \iow_term:e{==>~\int_use:N\g_@@_math_total_int\c_space_tl
math~fragments~found}
- \iow_term:e{==>~\int_use:N\g_@@_mathml_AF_found_int\c_space_tl
+ \iow_term:e{==>~\int_use:N\g_@@_mathml_AF_found_int\c_space_tl
fitting~MathML~AF~found}
- \iow_term:e{==>~\int_use:N\g_@@_mathml_AF_attached_int\c_space_tl
+ \iow_term:e{==>~\int_use:N\g_@@_mathml_AF_attached_int\c_space_tl
MathML~AF~attached}
}
- }
+ }
}
-\AddToHook{begindocument}{\@@_AF_process_mathml_files:}
+\AddToHook{begindocument}{\@@_AF_process_mathml_files:}
% \end{macrocode}
% \end{macro}
-%
+%
% \subsection{Mathstyle detection}
% In some cases we need to detect the mathstyle used in a \cs{mathchoice}
-% command and to disable/enable tagging in the unused branches.
+% command and to disable/enable tagging in the unused branches.
% This is currently only used in the amstext command \cs{text}
% but is perhaps also needed in other cases, so we create a general command.
-%
+%
%\begin{macro}{\l_@@_mathstyle_int,\g_@@_mathchoice_int,mathstyle}
% \begin{macrocode}
\int_new:N \l_@@_mathstyle_int
@@ -1114,12 +1352,12 @@
% For now internal, but perhaps will need a public version.
% The command should be used in every branch of a \cs{mathchoice}
% (with the correct mathstyle number) and with an unique label (which should
-% be the same in every branch).
-% \cs{g_@@_mathchoice_int} can be e.g. increased before the mathchoice and
+% be the same in every branch).
+% \cs{g_@@_mathchoice_int} can be, e.g., increased before the mathchoice and
% then used.
% \begin{macro}{\@@_tag_if_mathstyle:nn}
% \begin{macrocode}
-\cs_new_protected:Npn \@@_tag_if_mathstyle:nn #1 #2
+\cs_new_protected:Npn \@@_tag_if_mathstyle:nn #1 #2
%#1 refers to label
%#2 is a number for the mathstyle (typically 0,2,4,6)
{
@@ -1128,29 +1366,50 @@
\int_compare:nNnTF { \property_ref:nn {#1}{ mathstyle} } = { #2 }
{ \tag_resume:n{\mathchoice} }{ \tag_suspend:n{\mathchoice} }
}
-\cs_generate_variant:Nn \@@_tag_if_mathstyle:nn {en}
+\cs_generate_variant:Nn \@@_tag_if_mathstyle:nn {en}
% \end{macrocode}
% \end{macro}
-%
+%
% \subsection{Tagging options}
% \begin{macrocode}
\keys_define:nn { __tag / setup }
{
math/mathml/sources .clist_set:N = \l__tag_math_mathml_files_clist,
- math/alt/use .bool_set:N = \l__tag_math_alt_bool,
+ math/alt/use .bool_set:N = \l__tag_math_alt_bool,
viewer/pane/mathml .bool_set:N = \l__tag_math_mathml_pane_bool,
viewer/pane/mathml .initial:n = true,
- viewer/pane/mathsource .bool_set:N = \l__tag_math_texsource_pane_bool,
+ viewer/pane/mathsource .bool_set:N = \l__tag_math_texsource_pane_bool,
math/mathml/AF .bool_set:N = \l__tag_math_mathml_AF_bool,
math/mathml/AF .initial:n = true,
math/tex/AF .bool_set:N = \l__tag_math_texsource_AF_bool,
math/tex/AF .initial:n = true
- }
+ }
+% \end{macrocode}
+% alt is required for pdf/UA-1.
+% TODO: l3pdfmeta should support this test.
+% \begin{macrocode}
+\AddToHook{begindocument/end}
+ {
+ \str_if_eq:eeT
+ {1}
+ {
+ \exp_last_unbraced:Ne\use_i:nn
+ {\GetDocumentProperties{document/pdfstandard-UA}}
+ \c_empty_tl\c_empty_tl
+ }
+ {
+ \bool_if:NF \l__tag_math_alt_bool
+ {
+ \typeout{PDF/UA-1~detected.~Enabling~alt~text~on~Formula}
+ }
+ \bool_set_true:N\l__tag_math_alt_bool
+ }
+ }
% \end{macrocode}
%
% \subsection{Sockets}
% \subsubsection{Main inline math sockets}
-%
+%
% \begin{socketdecl}
% {
% tagsupport/math/inline/begin,
@@ -1159,11 +1418,11 @@
% tagsupport/math/inline/formula/end,
% }
% The first two sockets are meant to embed inline
-% math into the surrounding (so to close/reopen e.g. MC-chunks).
-% The other two implement the actual formula structure.
+% math into the surrounding (so to close/reopen, e.g., MC-chunks).
+% The other two implement the actual formula structure.
% The formula sockets are despite their naming not symmetric:
-% the begin socket is issued after the math has started, while
-% the end socket is after the math!
+% the begin socket is issued after the math has started, while
+% the end socket is after the math!
% \begin{macrocode}
\socket_new:nn {tagsupport/math/inline/begin}{0}
\socket_new:nn {tagsupport/math/inline/end}{0}
@@ -1171,8 +1430,8 @@
\socket_new:nn {tagsupport/math/inline/formula/end}{0}
% \end{macrocode}
%\end{socketdecl}
-%
-%
+%
+%
% \begin{plugdecl}{MC}
% \begin{macrocode}
\socket_new_plug:nnn
@@ -1182,10 +1441,10 @@
\socket_new_plug:nnn
{tagsupport/math/inline/end}
{MC}
- {\tag_mc_begin_pop:n{}}
+ {\tag_mc_begin_pop:n{}}
% \end{macrocode}
% \end{plugdecl}
-%
+%
% We probably will want to test different tagging recipes.
% \begin{plugdecl}{default}
% \begin{macrocode}
@@ -1195,7 +1454,7 @@
% \end{macrocode}
% \changes{v0.6g}{2024-10-02}{disable paratagging, issue \#711}
% \begin{macrocode}
- { \tagpdfparaOff
+ { \tagpdfparaOff
\tag_socket_use:n{math/content}
\tag_socket_use:n{math/struct/begin}
% \end{macrocode}
@@ -1209,15 +1468,15 @@
\socket_new_plug:nnn
{tagsupport/math/inline/formula/end}
{default}
- {
+ {
\socket_use:n{tagsupport/math/substruct/end}
\socket_use:n{tagsupport/math/struct/end}
- }
+ }
% \end{macrocode}
% \end{plugdecl}
-%
+%
% \subsubsection{Main display math sockets}
-%
+%
% \begin{socketdecl}
% {
% tagsupport/math/display/begin,
@@ -1226,15 +1485,15 @@
% tagsupport/math/display/formula/end,
% }
% The first two sockets are meant to embed display
-% math into the surrounding (so to close/reopen e.g. MC-chunks and
+% math into the surrounding (so to close/reopen, e.g., MC-chunks and
% P-structure).
-% The other two implement the actual formula structure.
+% The other two implement the actual formula structure.
% The formula sockets are despite their naming not symmetric:
-% the begin socket is issued after the math has started, while
-% the end socket is after the math!
+% the begin socket is issued after the math has started, while
+% the end socket is after the math!
% The socket |tagsupport/math/display/formula/begin| should similar to
% the inline version not be used as tagging socket so that the argument, the math,
-% is not lost.
+% is not lost.
% \begin{macrocode}
\socket_new:nn {tagsupport/math/display/begin}{0}
\socket_new:nn {tagsupport/math/display/end}{0}
@@ -1253,7 +1512,7 @@
{tagsupport/math/display/end}
{default}
{
- }
+ }
% \end{macrocode}
% \end{plugdecl}
@@ -1263,25 +1522,25 @@
\socket_new_plug:nnn
{tagsupport/math/display/formula/begin}
{default}
- {
+ {
\tag_socket_use:n{math/content}
\tag_socket_use:n{math/struct/begin}
\tag_socket_use:n{math/substruct/begin}
- #1
+ #1
\tag_socket_use:n{math/end}
}
\socket_new_plug:nnn
{tagsupport/math/display/formula/end}
{default}
- {
+ {
\socket_use:n{tagsupport/math/substruct/end}
\socket_use:n{tagsupport/math/struct/end}
- }
+ }
% \end{macrocode}
% \end{plugdecl}
%
% \subsubsection{Internal sockets}
-%
+%
% \begin{variable}{\l_@@_content_template_tl}
% The default text used as alt or actual text.
% \begin{macrocode}
@@ -1295,7 +1554,7 @@
\c_space_tl
\exp_not:N\end{\g_@@_grabbed_env_tl}
\c_space_tl LaTeX~ formula~ ends~
- }
+ }
% \end{macrocode}
% \end{variable}
@@ -1305,7 +1564,7 @@
\tl_new:N\l_@@_texsource_template_tl
\tl_const:Nn\c_@@_inline_env_tl {math}
\tl_set:Nn \l_@@_texsource_template_tl
- {
+ {
\tl_if_eq:NNTF\g_@@_grabbed_env_tl\c_@@_inline_env_tl
{
$
@@ -1316,29 +1575,29 @@
\exp_not:N\begin{\g_@@_grabbed_env_tl}
\exp_not:V\g_@@_grabbed_math_tl
\exp_not:N\end{\g_@@_grabbed_env_tl}
- }
- }
+ }
+ }
% \end{macrocode}
% \end{variable}
-%
+%
% \begin{socketdecl}{tagsupport/math/content}
-% The math content is stored in associated files and used for
+% The math content is stored in associated files and used for
% actual and alternative text. As the exact text is still
% unclear we use a socket to be able to test variants.
% The socket should set all four tl vars above, if needed
-% to identical values. It can use the two variables
+% to identical values. It can use the two variables
% \cs{g_@@_grabbed_env_tl} and \cs{g_@@_grabbed_math_tl}
% \begin{macrocode}
\socket_new:nn {tagsupport/math/content}{0}
% \end{macrocode}
% \end{socketdecl}
-%
+%
% Some default sockets to set the contents.
-% TODO: think about naming convention.
+% TODO: think about naming convention.
% TODO: think how this should organized so that one
% has options to change from the outside and so that
-% there are less repetitions.
+% there are less repetitions.
% \begin{plugdecl}{actual+source}
% \begin{macrocode}
\socket_new_plug:nnn
@@ -1348,17 +1607,17 @@
\tl_set:Ne\l_@@_content_actual_tl
{
\l_@@_content_template_tl
- }
- \tl_set:Ne \l_@@_content_AF_source_tl
+ }
+ \tl_set:Ne \l_@@_content_AF_source_tl
{
\l_@@_texsource_template_tl
- }
+ }
\tl_set:Nn \l_@@_content_AF_mathml_tl {}
\tl_set:Nn \l_@@_content_alt_tl {}
}
% \end{macrocode}
-% \end{plugdecl}
-%
+% \end{plugdecl}
+%
% \begin{plugdecl}{alt+source}
% \begin{macrocode}
\socket_new_plug:nnn
@@ -1368,26 +1627,26 @@
\tl_set:Ne\l_@@_content_alt_tl
{
\l_@@_content_template_tl
- }
- \tl_set:Ne \l_@@_content_AF_source_tl
+ }
+ \tl_set:Ne \l_@@_content_AF_source_tl
{
\l_@@_texsource_template_tl
- }
+ }
\tl_set:Nn \l_@@_content_AF_mathml_tl {}
\tl_set:Nn \l_@@_content_actual_tl {}
}
% \end{macrocode}
% \end{plugdecl}
% \begin{macrocode}
-\socket_assign_plug:nn {tagsupport/math/content}{alt+source}
+\socket_assign_plug:nn {tagsupport/math/content}{alt+source}
% \end{macrocode}
%
% \begin{socketdecl}{tagsupport/math/struct/begin,
% tagsupport/math/struct/end}
-% For the main structure we use a socket too.
-% This allow e.g. to create a special one for luamml
-% which setups additional objects.
-% The begin socket can use the two variables
+% For the main structure we use a socket too.
+% This allows, e.g., to create a special one for luamml
+% which setups additional objects.
+% The begin socket can use the two variables
% \cs{g_@@_grabbed_env_tl} and \cs{g_@@_grabbed_math_tl}
% \begin{macrocode}
\socket_new:nn {tagsupport/math/struct/begin}{0}
@@ -1402,12 +1661,22 @@
{tagsupport/math/struct/begin}
{default}
{
- \bool_if:NTF\l__tag_math_texsource_AF_bool
+ \bool_if:NTF\l__tag_math_texsource_AF_bool
{ \tl_set_eq:NN \l_@@_content_AF_source_tmpa_tl \l_@@_content_AF_source_tl }
{ \tl_clear:N \l_@@_content_AF_source_tmpa_tl }
+ \tl_if_eq:NnTF\g_@@_grabbed_env_tl {math}
+ {
+ \tl_set:Nn\l_@@_attribute_class_tl{inline}
+ }
+ {
+ \tl_set:Nn\l_@@_attribute_class_tl{display}
+ }
+ \bool_if:NF\l__tag_math_alt_bool
+ { \tl_set:Nn \l_@@_content_alt_tl{} }
\tag_struct_begin:n
{
tag=Formula,
+ attribute-class=\l_@@_attribute_class_tl,
texsource = \l_@@_content_AF_source_tmpa_tl,
title-o = \g_@@_grabbed_env_tl,
actualtext = \l_@@_content_actual_tl,
@@ -1418,19 +1687,18 @@
{tagsupport/math/struct/end}
{default}
{ \tag_struct_end: }
-
-\socket_assign_plug:nn {tagsupport/math/struct/begin}{default}
-\socket_assign_plug:nn {tagsupport/math/struct/end}{default}
-% \end{macrocode}
-% \end{plugdecl}
-%
-% \begin{plugdecl}{test-mathml}
-% This (test-)socket tries to add a mathml-AF to formula.
-% It is activated if a mathml.html has been found and loaded.
-% Additionally it also sets an attribute
-% (this can perhaps be done by default anyway.)
-% As it disturbs the reading of the AF it currently deactivates the /Alt key,
-% unless it has been reenabled with |math/alt/use=true|
+
+\socket_assign_plug:nn {tagsupport/math/struct/begin}{default}
+\socket_assign_plug:nn {tagsupport/math/struct/end}{default}
+% \end{macrocode}
+% \end{plugdecl}
+%
+% \begin{plugdecl}{mathml-AF}
+% This socket tries to add a mathml-AF to formula.
+% It is activated if a mathml.html has been found and loaded.
+% As it disturbs the reading of the AF
+% it currently deactivates the /Alt key,
+% unless it has been reenabled with |math/alt/use=true|
% \begin{macrocode}
\cs_generate_variant:Nn \str_mdfive_hash:n {o}
\tl_new:N\l_@@_content_hash_tl
@@ -1443,49 +1711,52 @@
% \begin{macrocode}
\socket_new_plug:nnn
{tagsupport/math/struct/begin}
- {test-mathml}
- {
- \int_gincr:N\g_@@_math_total_int
- \tl_set:Ne\l_@@_content_hash_tl
- {\str_mdfive_hash:o { \l_@@_content_AF_source_tl }}
- \tl_set_eq:NN\l_@@_grabbed_math_tl\g_@@_grabbed_math_tl
+ {mathml-AF}
+ {
+ \int_gincr:N\g_@@_math_total_int
+ \tl_set:Ne\l_@@_content_hash_tl
+ {\str_mdfive_hash:o { \l_@@_content_AF_source_tl }}
+ \tl_set_eq:NN\l_@@_grabbed_math_tl\g_@@_grabbed_math_tl
\tl_if_eq:NnTF\g_@@_grabbed_env_tl {math}
{
- \tl_set:Nn\l_@@_attribute_class_tl{inline}
+ \tl_set:Nn\l_@@_attribute_class_tl{inline}
}
{
\tl_set:Nn\l_@@_attribute_class_tl{display}
}
\bool_if:NF\l__tag_math_alt_bool
- { \tl_set:Nn \l_@@_content_alt_tl{} }
+ { \tl_set:Nn \l_@@_content_alt_tl{} }
% \end{macrocode}
% debugging option. TODO: hide in debug key.
% \begin{macrocode}
\tl_if_exist:cTF { g_@@_mathml_ \l_@@_content_hash_tl _tl }
- {
- \int_gincr:N\g_@@_mathml_AF_found_int
- \bool_if:NTF \l__tag_math_mathml_AF_bool
- {
- \int_gincr:N\g_@@_mathml_AF_attached_int
- \typeout {Inserting~mathml~with~Hash~\l_@@_content_hash_tl}
- }
- {
- \typeout {Ignoring~mathml~with~Hash~\l_@@_content_hash_tl}
- }
- }
- {
- \typeout{WARNING:~mathml~missing~for~hash~\l_@@_content_hash_tl}
- }
- \socket_use:n {tagsupport/math/mathml/write/prepare}
- \socket_use:n {tagsupport/math/mathml/write} % write hash if request
- \bool_if:NTF\l__tag_math_texsource_AF_bool
+ {
+ \int_gincr:N\g_@@_mathml_AF_found_int
+ \bool_if:NTF \l__tag_math_mathml_AF_bool
+ {
+ \int_gincr:N\g_@@_mathml_AF_attached_int
+ \typeout {Inserting~mathml~with~Hash~\l_@@_content_hash_tl}
+ }
+ {
+ \typeout {Ignoring~mathml~with~Hash~\l_@@_content_hash_tl}
+ }
+ }
+ {
+ \bool_if:NT \l__tag_math_mathml_AF_bool
+ {
+ \typeout {WARNING:~mathml~missing~for~hash~\l_@@_content_hash_tl}
+ }
+ }
+ \socket_use:n {tagsupport/math/mathml/write/prepare}
+ \socket_use:n {tagsupport/math/mathml/write} % write hash if request
+ \bool_if:NTF\l__tag_math_texsource_AF_bool
{ \tl_set_eq:NN \l_@@_content_AF_source_tmpa_tl \l_@@_content_AF_source_tl }
- { \tl_clear:N \l_@@_content_AF_source_tmpa_tl }
+ { \tl_clear:N \l_@@_content_AF_source_tmpa_tl }
\tag_struct_begin:n
{
tag=Formula,
attribute-class=\l_@@_attribute_class_tl, %
- AFref =
+ AFref =
\bool_if:NT\l__tag_math_mathml_AF_bool
{
\cs_if_exist_use:c {g_@@_mathml_ \l_@@_content_hash_tl _tl}
@@ -1500,13 +1771,13 @@
% \begin{macrocode}
\socket_new_plug:nnn
{tagsupport/math/struct/end}
- {test-mathml}
+ {mathml-AF}
{
\tag_struct_end:
- }
+ }
% \end{macrocode}
% \end{plugdecl}
-%
+%
% \begin{socketdecl}{tagsupport/math/substruct/begin,
% tagsupport/math/substruct/end}
% This holds the code to handle subparts of the formula.
@@ -1515,7 +1786,7 @@
\socket_new:nn {tagsupport/math/substruct/end}{0}
% \end{macrocode}
% \end{socketdecl}
-%
+%
% \begin{plugdecl}{default}
% \begin{macrocode}
\socket_new_plug:nnn
@@ -1525,16 +1796,16 @@
\socket_new_plug:nnn
{tagsupport/math/substruct/end}
{default}
- {
+ {
\tagmcend
\if@subformulas
\tagstructend
\fi
- }
-\socket_assign_plug:nn {tagsupport/math/substruct/begin}{default}
-\socket_assign_plug:nn {tagsupport/math/substruct/end}{default}
-% \end{macrocode}
-% \end{plugdecl}
+ }
+\socket_assign_plug:nn {tagsupport/math/substruct/begin}{default}
+\socket_assign_plug:nn {tagsupport/math/substruct/end}{default}
+% \end{macrocode}
+% \end{plugdecl}
% \begin{plugdecl}{single}
% We need an option to disable subparts as it is unclear
@@ -1546,7 +1817,7 @@
{
\typeout{====>subpart~splitting~deactivated}
\typeout{====>grabbed~math=\meaning\g_@@_grabbed_math_tl}
- \tag_mc_begin:n{}
+ \tag_mc_begin:n{}
}
\socket_new_plug:nnn
{tagsupport/math/substruct/end}
@@ -1554,21 +1825,21 @@
{ \tag_mc_end:}
% \end{macrocode}
% \end{plugdecl}
-%
+%
% \begin{socketdecl}{tagsupport/math/end}
% A socket used at the end of the math (before the closing dollar(s))
-% which can e.g. set a flag for luamml.
+% which can, e.g., set a flag for luamml.
% \begin{macrocode}
\socket_new:nn {tagsupport/math/end}{0}
% \end{macrocode}
% \end{socketdecl}
-
-%
+
+%
% \begin{macro}{\__tag_math_disable:}
% Similar to the table code we collect the plugs that should be
% assigned to do nothing if we don't want tagging
% \begin{macrocode}
-\cs_new_protected:Npn \__tag_math_disable:
+\cs_new_protected:Npn \__tag_math_disable:
{
\socket_assign_plug:nn {tagsupport/math/inline/begin}{noop}
\socket_assign_plug:nn {tagsupport/math/inline/end}{noop}
@@ -1577,16 +1848,16 @@
\socket_assign_plug:nn {tagsupport/math/display/begin}{noop}
\socket_assign_plug:nn {tagsupport/math/display/end}{noop}
\socket_assign_plug:nn {tagsupport/math/display/formula/begin}{identity}
- \socket_assign_plug:nn {tagsupport/math/display/formula/end}{noop}
- }
+ \socket_assign_plug:nn {tagsupport/math/display/formula/end}{noop}
+ }
% \end{macrocode}
% \end{macro}
-%
+%
% \begin{macro}{\__tag_math_enable:}
% Similar to the table code we collect the default plugs that should be
% assigned if we want tagging
% \begin{macrocode}
-\cs_new_protected:Npn \__tag_math_enable:
+\cs_new_protected:Npn \__tag_math_enable:
{
\socket_assign_plug:nn {tagsupport/math/inline/begin}{MC}
\socket_assign_plug:nn {tagsupport/math/inline/end}{MC}
@@ -1596,7 +1867,7 @@
\socket_assign_plug:nn {tagsupport/math/display/end}{default}
\socket_assign_plug:nn {tagsupport/math/display/formula/begin}{default}
\socket_assign_plug:nn {tagsupport/math/display/formula/end}{default}
- }
+ }
% \end{macrocode}
% \end{macro}
% At begin document we can activate:
@@ -1667,7 +1938,7 @@
% We do not want math tagging in fakemath or when measuring,
% We also do not want math tagging if tagging has been suspended.
% \begin{macrocode}
- \bool_lazy_any:nTF
+ \bool_lazy_any:nTF
{
{\legacy_if_p:n { measuring@ }}
{ \l_@@_fakemath_bool }
@@ -1677,7 +1948,7 @@
#1 $ % $
}
{
- \tag_socket_use:n {math/inline/begin} %end P-MC
+ \tag_socket_use:n {math/inline/begin} %end P-MC
% \end{macrocode}
% We do no use a tagging socket here, so that the argument (the
% math) is not lost, tagging-project issue 661.
@@ -1700,7 +1971,7 @@
{ \@@_grab_dollar:n {#1} }
% \end{macrocode}
% \end{macro}
-%
+%
% \begin{macro}{\@@_grab_dollardollar:w}
% And for the classical \TeX{} display structure.
% \begin{macrocode}
@@ -1716,11 +1987,11 @@
$$
}
% \end{macrocode}
-%
+%
% The end code is added through a \cs{aftergroup} so we
% store it inside a command.
% \begin{macrocode}
-\cs_new_protected:Npn \@@_tag_dollardollar_display_end:
+\cs_new_protected:Npn \@@_tag_dollardollar_display_end:
{
% \typeout{== tag dollarldollar display end}
% \ShowTagging{struct-stack}
@@ -2126,7 +2397,7 @@
}
{
% \typeout{==>A3}
- \__tag_tool_close_P:
+ \__tag_tool_close_P:
}
\socket_use:nn{tagsupport/math/display/formula/begin}{}
\tagpdfparaOff
@@ -2144,7 +2415,7 @@
\cs_new_protected:Npn \math_register_env:n #1
{ \math_register_env:nn {#1} { } }
-
+
\NewDocumentCommand \RegisterMathEnvironment { O{} m }
{ \math_register_env:nn {#2} {#1} }
% \end{macrocode}
@@ -2231,7 +2502,7 @@
{
\cs_gset_protected:Npn \[ % \]
{
- \@@_grab_eqn:w
+ \@@_grab_eqn:w
% \bool_if:NTF \l_@@_collected_bool
% { \begin { equation* } }
% { \@@_grab_eqn:w }
@@ -2329,7 +2600,7 @@
% \end{macrocode}
%
% Tabulars currently contain a \$ that shouldn't trigger math
-% tagging.
+% tagging.
% \begin{macrocode}
\RequirePackage{array}
\tl_if_in:NnT\@tabular{$}
@@ -2338,7 +2609,7 @@
\leavevmode
\UseTaggingSocket{tbl/hmode/begin}%
\hbox \bgroup
- \bool_set_true:N \l_@@_collected_bool
+ \bool_set_true:N \l_@@_collected_bool
$
\bool_set_false:N \l_@@_collected_bool
\col@sep\tabcolsep \let\d@llarbegin\begingroup
@@ -2363,10 +2634,10 @@
}
% \end{macrocode}
% \end{macro}
-%
+%
% \subsection{Disable math grabbing in the begindocument hook}
% For example amsart uses math to measure text there.
-%
+%
% \begin{macrocode}
\tl_gput_right:Nn\@kernel@before@begindocument
{
@@ -2490,7 +2761,7 @@
\math_register_halign_env:nn {align}{}
\math_register_halign_env:nn {align*}{}
\math_register_halign_env:nn {alignat}{}
- \math_register_halign_env:nn {alignat*}{}
+ \math_register_halign_env:nn {alignat*}{}
\math_register_halign_env:nn {flalign}{}
\math_register_halign_env:nn {flalign*}{}
\math_register_halign_env:nn {gather}{}
@@ -2571,8 +2842,8 @@
%
% \begin{macro}{\@@_split_at_nl:NN}
-% This splits grabbed math at newlines.
-%
+% This splits grabbed math at newlines.
+%
% \begin{macrocode}
\cs_new:Npn \@@_split_at_nl:NN #1#2 {
\tl_set:Nf \l_@@_tmpa_tl {
@@ -2591,14 +2862,14 @@
#2 \\ #3 \s_stop
}
}
-
+
\cs_new_protected:Npn \@@_split_at_nl_aux:nnNN #1 #2 #3 #4
{
\tl_gset:Nn #4 {#1}
\tl_gset:Nn #3 {#2}
}
-\cs_new:Npn \@@_split_chk_if_begin:ww
+\cs_new:Npn \@@_split_chk_if_begin:ww
#1 \begin #2 #3 \s_mark #4 \\ \q_nil \\ \s_stop
{
\quark_if_nil:nTF {#2}
@@ -2649,11 +2920,11 @@
{ \exp_end: { #4 #1 } }
{ \@@_split_final_cleanup:w #3 \s_mark { #4 #1 #2 } }
}
-
+
\cs_new:Npn \@@_split:n #1 {
\@@_split_at_nl_first:w #1 \\ \q_nil \\ \s_stop }
-
-% this looks unused.
+
+% this looks unused.
%\NewDocumentCommand \splitnl { mm +m }
% {
% \tl_set:Nf \l_@@_tmpa_tl { \split:n {#3} }
@@ -2665,12 +2936,12 @@
%
%
% \begin{macro}{\maybestartnewformulatag}
-%
+%
% \begin{macrocode}
\newif\if@subformulas
-\tl_new:N \result
-
+\tl_new:N \result
+
\cs_new_protected:Npn\grabaformulapartandstart {
\@@_split_at_nl:NN \g_@@_grabbed_math_tl \result
\typeout{====>first-result=\meaning\result}
@@ -2690,7 +2961,7 @@
% but we add a short text to satisfy the pdf/ua-2 validator
% \begin{macrocode}
% alt=\result,
- alt = subformula,
+ alt = subformula,
title-o=\resulttitle
}
}
@@ -2728,7 +2999,7 @@
%
\tl_if_empty:NF \g_@@_grabbed_math_tl
{
- \tagmcend
+ \tagmcend
\tagstructend
\grabaformulapartandmayberestart
}
@@ -2744,21 +3015,21 @@
% \typeout{===>~ in~ hook}
% \math_register_halign_env:nn {dmath}{}
% \math_register_halign_env:nn {dgroup*}{}
-%}
+%}
% \end{macrocode}
-%
+%
% \begin{macrocode}
\ExplSyntaxOff
% \end{macrocode}
-%
+%
% \begin{macrocode}
%<@@=>
% \end{macrocode}
-%
+%
% \begin{macrocode}
%</kernel>
% \end{macrocode}
%
% \Finale
%
-%
+%
diff --git a/Master/texmf-dist/source/latex-dev/tools/array.dtx b/Master/texmf-dist/source/latex-dev/tools/array.dtx
index f141f069e3a..f4c8ab28d8d 100644
--- a/Master/texmf-dist/source/latex-dev/tools/array.dtx
+++ b/Master/texmf-dist/source/latex-dev/tools/array.dtx
@@ -39,7 +39,7 @@
% \begin{macrocode}
%<+package>\NeedsTeXFormat{LaTeX2e}[2024/06/01]
%<+package>\ProvidesPackage{array}
-%<+package> [2024/10/12 v2.6g Tabular extension package (FMi)]
+%<+package> [2024/10/17 v2.6g Tabular extension package (FMi)]
%
% \fi
%
@@ -259,7 +259,7 @@
% \begin{table}[!t]
% \begin{center}
% \setlength{\extrarowheight}{1pt}
-% \begin{tabular}{|>{\tt}c|m{9cm}|}
+% \begin{tabular}{|>{\ttfamily}c|m{9cm}|}
% \hline
% \multicolumn{2}{|c|}{Unchanged options}\\
% \hline
@@ -382,6 +382,20 @@
% \end{itemize}
%
%
+%
+% \subsection{A note on the allowed content of \texttt{>\{...\}} and
+% \texttt{<\{...\}}}
+%
+% These specifiers are meant to hold declarations, such as
+% \verb=>{\itshape}=. They cannot end in commands that take arguments
+% without providing these arguments as part of the \verb={...}=. It
+% would be a mistaken assumption that they pick up all or parts of the
+% alignment entry data if their argument is not provided. E.g.,
+% \verb=>{\textbf}= would not make the whole column bold nor would it
+% make the first character bold (technically it would try to
+% bolden \cs{ignorespaces}). Thus, it would not fail with an error,
+% but effectively the output would be wrong and not as expected.
+%
% \subsection{The behavior of the \texttt{\string\\} command}
%
% In the basic \texttt{tabular} implementation of \LaTeX{} the \cs{\bslash}
@@ -464,16 +478,16 @@
% "\newcolumntype{L}{>{$}l<{$}}" \\
% "\newcolumntype{R}{>{$}r<{$}}"
% \end{quote}
-% Then we can use \texttt{C} to get centred LR-mode in an
-% \texttt{array}, or centred math-mode in a \texttt{tabular}.
+% Then we can use \texttt{C} to get centered LR-mode in an
+% \texttt{array}, or centered math-mode in a \texttt{tabular}.
%
-% The example given above for `centred decimal points' could be
+% The example given above for `center decimal points' could be
% assigned to a \texttt{d} specifier with the following command.
% \begin{quote}
% "\newcolumntype{d}{>{\centerdots}c<{\endcenterdots}}"
% \end{quote}
%
-% The above solution always centres the dot in the
+% The above solution always centers the dot in the
% column. This does not look too good if the column consists of large
% numbers, but to only a few decimal places. An alternative definition
% of a \texttt{d} column is
@@ -734,7 +748,7 @@
% user the opportunity of overriding the settings of a
% "\newcolumntype" defined using these declarations. For example,
% suppose in an \texttt{array} environment we use a \texttt{C}
-% column defined as above. The \texttt{C} specifies a centred text
+% column defined as above. The \texttt{C} specifies a centered text
% column, however ">{\bfseries}C", which re-writes to
% ">{\bfseries}>{$}c<{$}" would not specify a bold column as might
% be expected, as the preamble would essentially expand to
@@ -896,14 +910,14 @@ Bug reports can be opened (category \texttt{#1}) at\\%
%
% \section{A note on the updates done December 2023}
%
-% We introduced support for tagged PDf and at the same time we added
+% We introduced support for tagged PDF and at the same time we added
% code to determine row and column numbers for each cell in
% preparation for supporting formatting or type specifications for individual
% cells (or group of cells) from the outside, e.g., \enquote{rows 1,
% 2, and 10 are header rows} (syntax to be decided).
%
% This new code is already written with L3 programming layer conventions
-% while most of the legay code is still as it was before. This make the code
+% while most of the legacy code is still as it was before. This make the code
% currently somewhat clattered, unfortunately. Eventually this will all move to L3
% programming layer but this will take time.
%
@@ -1345,7 +1359,7 @@ Bug reports can be opened (category \texttt{#1}) at\\%
% of \textsf{token} register $15$ instead of $1$ later on.
%
% The example above referred to an older version of =\save@decl= which
-% inserted a =\relex= inside the token register. This is now moved to
+% inserted a =\relax= inside the token register. This is now moved to
% the places where the actual token registers are inserted (look for
% =\the@toks=) because the old version would still make =@=
% expressions to moving arguments since after expanding the second
@@ -1386,33 +1400,112 @@ Bug reports can be opened (category \texttt{#1}) at\\%
% \begin{macrocode}
\UseTaggingSocket{tbl/cell/begin}%
% \end{macrocode}
-% Here, we assume that the \textsf{count} register
+% Next we have to insert the toks register holding the content of
+% \verb=>{...}=. Here, we assume that the \textsf{count} register
% =\@tempcnta= has saved the value $=\count@= - 1$.
%
-% To keep \TeX{} happy if there is a look ahead in the tabular preamble
-% which uses the Appendix~D trick (for example anything with a trailing
-% optional argument defined by \pkg{ltcmd}), we wrap everything here in
-% a protected version of \cs{@firstofone}.\footnote{The reason this
-% works is not really clear: almost certainly there is a bug in \TeX{}
-% here that we are simply avoiding, but as the master counter doesn't
-% show up in a trace, a full understanding likely means working through
-% the code that implements \cs{halign}!}
-% \TeX{} otherwise can get
+% To keep \TeX{} happy if there is a look ahead in the tabular
+% preamble, i.e., starting in \verb=>{...}=, which uses the
+% Appendix~D trick (for example, anything with a trailing optional
+% argument defined by \pkg{ltcmd}), we wrap everything here in a
+% protected version of \cs{@firstofone}. \TeX{} otherwise can get
% confused about the value of the master counter, and we get some
-% strange errors. (Quite possibly the underlying issue is a \TeX{}
-% bug, but rather than try to fix in 2024 we accept it's there and
-% work-around.) As an example, without this approach, something
-% like
+% strange errors. We suspected that there was an underlying issue
+% is the \TeX{} engine, but it turned out to be rather hard to get
+% to the bottom of it, because the master counter is not accessible
+% through \TeX{}'s tracing tools. Thus, all we could do was
+% producing various example documents, observing results, as well
+% as staring at a printout of the \TeX{} program. As an example,
+% without this approach, something like
% \begin{verbatim}
-%\NewDocumentCommand\foo{o}{x}
-%\begin{tabular}{>{\foo}l}
-% Foo
-%\end{tabular}
+% \NewDocumentCommand\foo{o}{x}
+% \begin{tabular}{>{\foo}l}
+% Foo
+% \end{tabular}
% \end{verbatim}
-% will fail; that can be fixed by adding a \cs{relax} after the \cs{@tempcnta},
-% but that then leads to issues if you are collecting whole cells (tagging code
-% or \\pkg{collcell}), where you can no longer alter the meaning of \cs{cr}
-% as the master counter goes wrong.
+% failed. That can be fixed by adding a \cs{relax} after the
+% \cs{@tempcnta}, but that then leads to issues if you are
+% collecting whole cells (tagging code or \pkg{collcell}), where
+% you can no longer alter the meaning of \cs{cr} as the master
+% counter goes wrong due to an obscure bug (or perhaps, say, an
+% undocumented feature of \TeX{}). Eventually, we were able to pin
+% down the root cause and really understand why
+% \cs{@protected@firstofone} solves the problem, even though it
+% looks like a nonsense addition to the code that does nothing
+% useful.\footnote{So it is a \TeX{} engine bug that was in there
+% from day one, or if you like, it is a hidden feature that is not
+% explained; neither in the \TeX{}book nor in the program code. We
+% don't really expect this to change in \TeX{} after such a long
+% time, other than perhaps documenting it as a feature, so this is
+% a proper solution to the problem and not just a workaround.}
+%
+% The problem is that \TeX{} tries to conserve stack space, and
+% when the last token of an existing token list is a macro, then
+% this token list is \emph{first} removed from memory (reducing the
+% stack) \emph{before} the macro replacement text (as a new
+% token list) is given to the parser adding a new stack level. This
+% is done using the routine \texttt{end\_token\_list} in the \TeX{}
+% program and ending the u-part of an \cs{halign} column with this
+% routine immediately sets the \emph{master counter} used by alignments to
+% zero (see chapter~22 and Appendix~D of the \TeX{}book). This
+% means that technically the expansion of the last token in the u-part (if it
+% is a macro) is not executed in the context of the u-part, but in
+% the context of the alignment entry in the document. That normally
+% doesn't make any difference whatsoever --- unless you play
+% around (as we sometimes have to) with tricks like those from
+% Appendix~D.
+%
+% To illustrate the issue we show a bit of strange low-level plain
+% \TeX{} code.\footnote{If all of this looks mighty strange to you,
+% don't worry. You will be unlikely to need to know about it. It is
+% just there so that programmers at some point in the future do not
+% have to wonder too much why there is this odd
+% \cs{@protected@firstofone} that apparently does nothing
+% useful. It took us several nights of head scratching to come up
+% with these minimal examples and then some more time to understand
+% what the heck is going on inside \TeX{}---thanks to Bruno for the
+% right ideas on the latter.} Below are two very special grouping
+% commands that are like \cs{bgroup} and \cs{egroup} but also
+% affect the alignment master counter when expanded (see
+% \TeX{}book p.385). If one of them is used as the
+% last macro in the u-part of a column, then you get strange errors
+% that you shouldn't get.
+% \begin{verbatim}
+% \def\bbgroup{{\ifnum0=`}\fi}
+% \def\eegroup{\ifnum0=`{\fi}}
+%
+% % Fails with an error message, but there should be none:
+% \halign{%
+% \message{u-part^^J}%
+% \bbgroup % <-- in the u-part
+% \eegroup % <-- in the u-part
+% #%
+% \message{v-part^^J}%
+% \hfill\cr
+% \message{body^^J}x
+% \cr
+% }
+%
+% % Fails but should work, the v-part is never reached:
+% \halign{%
+% \message{u-part^^J}%
+% \bbgroup % <-- in the u-part
+% #%
+% \message{v-part^^JJ}%
+% \eegroup % <-- in the v-part
+% \hfill\cr
+% \message{body^^J}x
+% \cr
+% }
+% \end{verbatim}
+%
+% So the trick we use now is making \cs{@protected@firstofone} the
+% last macro in the u-part, i.e., before the \cs{@sharp}. That way
+% its argument is always fully expanded as part of the alignment
+% entry and not as part of the u-part and this way we know exactly
+% what the master counter value is at this point, regardless of the content of
+% \verb=>{...}=.
+%
% \changes{v2.6f}{2024/09/13}{Stop parsing for optional argument (gh/1468)}
% \changes{v2.6g}{2024/10/12}{Further work to support optional args in preamble (gh/1468)}
% \begin{macrocode}
@@ -1429,7 +1522,7 @@ Bug reports can be opened (category \texttt{#1}) at\\%
% afterwards; in math mode, the latter is suppressed while the
% \cs{ignorespaces} makes no difference.
% \changes{v2.0e}{1991/02/07}{Added \{\} around \cs{@sharp} for new ftsel}
-% \changes{v2.0h}{1992/06/22}{Removed \{\} again in favour of
+% \changes{v2.0h}{1992/06/22}{Removed \{\} again in favor of
% \cs{d@llarbegin}}
% \changes{v2.6b}{2024/04/08}{Do not \cs{unskip} if in math mode (gh/1323)}
% \begin{macrocode}
@@ -1920,7 +2013,7 @@ Bug reports can be opened (category \texttt{#1}) at\\%
% For that reason the new implementation does the centering
% manually: First we check the height of the cell and if that is
% less or equal to =\ht\strutbox= we assume that this is a
-% single line cell. In that case we don't do any vertical maneuvre
+% single line cell. In that case we don't do any vertical maneuver
% and simply output the box, i.e., make it behave like a single
% line p-cell.
%
@@ -2363,7 +2456,7 @@ Bug reports can be opened (category \texttt{#1}) at\\%
\lineskip \z@
\baselineskip \z@
% \end{macrocode}
-% Don't use \cs{m@th} here as that signals to the math taggingg
+% Don't use \cs{m@th} here as that signals to the math tagging
% code that this is fake math that should not be tagged.
% \changes{v2.6a}{2023/12/11}{Support for tagged PDF}
% \begin{macrocode}
@@ -2489,7 +2582,7 @@ Bug reports can be opened (category \texttt{#1}) at\\%
%
% We then start a special brace which I have directly
% copied from the original definition. It is
-% necessary, because the =\futurlet= in =\@ifnextchar=
+% necessary, because the =\futurelet= in =\@ifnextchar=
% might
% expand a following =&= \textsf{token} in a construction like
% =\\ &=. This would otherwise end the alignment template at a
@@ -2502,7 +2595,7 @@ Bug reports can be opened (category \texttt{#1}) at\\%
% that a =&= will not be considered belonging to the current
% =\halign= while we are looking for a =*= or =[=.
% For further information see
-% \cite[Appendix D]{bk:knuth}.
+% \cite[Appendix~D]{bk:knuth}.
% \begin{macrocode}
\iffalse{\fi\ifnum 0=`}\fi
% \end{macrocode}
@@ -2687,7 +2780,7 @@ Bug reports can be opened (category \texttt{#1}) at\\%
% \section{The Environment Definitions}
%
% After these preparations we are able to define the environments. They
-% only differ in the initialisations of =\d@llar...=, =\col@sep=
+% only differ in the initializations of =\d@llar...=, =\col@sep=
% and =\@halignto=.
%
% \begin{macro}{\@halignto}
@@ -2702,7 +2795,7 @@ Bug reports can be opened (category \texttt{#1}) at\\%
% able overwrite the =\@halignto=
% setting of a tabular in the main text resulting in a very weird error.
% \changes{v2.4d}{2016/10/06}{\cs{@halignto} set locally (pr/4488)}
-% \changes{v2.0g}{1992/06/18}{`d@llarbegin defined on toplevel.}
+% \changes{v2.0g}{1992/06/18}{`d@llarbegin defined on top-level.}
% When the new font selection scheme is in force we have to
% we surround all =\halign= entries
% with braces. See remarks in TUGboat 10\#2. Actually we are going
@@ -2752,7 +2845,7 @@ Bug reports can be opened (category \texttt{#1}) at\\%
% \begin{macro}{\tabular}
% \begin{macro}{\tabular*}
% The environments \textsf{tabular} and \textsf{tabular$*$} differ
-% only in the initialisation of the command =\@halignto=. Therefore
+% only in the initialization of the command =\@halignto=. Therefore
% we define
% \changes{v2.4d}{2016/10/06}{\cs{@halignto} set locally (pr/4488)}
% \begin{macrocode}
@@ -3034,7 +3127,7 @@ Bug reports can be opened (category \texttt{#1}) at\\%
% rewrites (in the token register "\NC@list") will look like
% "\NC@do *" "\NC@do C" "\NC@do L".
% So we need to define "\NC@do" as a one argument macro which
-% initialises the rewriting of the specified column. Let us assume that
+% initializes the rewriting of the specified column. Let us assume that
% `C' is the argument.
% \begin{macrocode}
\def\NC@do#1{%
@@ -3102,7 +3195,7 @@ Bug reports can be opened (category \texttt{#1}) at\\%
% \end{macro}
%
% \subsection{The $*$--form}
-% We view the $*$-form as a slight generalisation of the system
+% We view the $*$-form as a slight generalization of the system
% described in the previous subsection. The idea is to define a $*$
% column by a command of the form:
% \begin{verbatim}
@@ -3540,7 +3633,7 @@ Bug reports can be opened (category \texttt{#1}) at\\%
% the cell content is too wide.
% \changes{v2.4f}{2017/11/07}{Column type added}
% \changes{v2.5a}{2020/04/06}{Use \cs{d@llarbegin} and \cs{d@llarend} so
-% that cell is typeset in mathmode inside \texttt{array} (gh/297)}
+% that cell is typeset in math mode inside \texttt{array} (gh/297)}
% \begin{macrocode}
\newcolumntype{W}[2]
{>{\begin{lrbox}\ar@cellbox\d@llarbegin}%
diff --git a/Master/texmf-dist/source/latex-dev/tools/longtable.dtx b/Master/texmf-dist/source/latex-dev/tools/longtable.dtx
index 439542a18c9..061d7b56102 100644
--- a/Master/texmf-dist/source/latex-dev/tools/longtable.dtx
+++ b/Master/texmf-dist/source/latex-dev/tools/longtable.dtx
@@ -38,7 +38,7 @@
%<driver> \ProvidesFile{longtable.drv}
% \fi
% \ProvidesFile{longtable.dtx}
- [2024-07-06 v4.21 Multi-page Table package (DPC)]
+ [2024-10-27 v4.22 Multi-page Table package (DPC)]
%
% \iffalse
%<*driver>
@@ -1639,15 +1639,20 @@
\LT@final@warn
\fi
% \end{macrocode}
-% Force one more go with the \env{longtable} output routine.
+% Force one more go with the \env{longtable} output routine.
+% Guard the special start of page value of "\pagegoal".
% \changes{v4.14}{2020/02/07}
% {Rearrange vertical space tests for tools/3512 (floats on same page)}
+% \changes{v4.22}{2024/10/27}
+% {Keep \cs{pagegoal} below \cs{maxdimen} gh1495}
% \begin{macrocode}
\endgraf\penalty -\LT@end@pen
\ifvoid\LT@foot\else
\global\advance\vsize\ht\LT@foot
\global\advance\@colroom\ht\LT@foot
- \dimen@\pagegoal\advance\dimen@\ht\LT@foot\pagegoal\dimen@
+ \ifdim\pagegoal<\maxdimen
+ \dimen@\pagegoal\advance\dimen@\ht\LT@foot\pagegoal\dimen@
+ \fi
\fi
% \end{macrocode}
% Now close the group to return to the standard routine.