summaryrefslogtreecommitdiff
path: root/macros/latex/required/latex-lab
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex/required/latex-lab')
-rw-r--r--macros/latex/required/latex-lab/README.md4
-rw-r--r--macros/latex/required/latex-lab/blocks-code.pdfbin886150 -> 881794 bytes
-rw-r--r--macros/latex/required/latex-lab/blocks-doc.pdfbin440234 -> 485663 bytes
-rw-r--r--macros/latex/required/latex-lab/changes.txt314
-rw-r--r--macros/latex/required/latex-lab/documentmetadata-support-code.pdfbin523380 -> 563214 bytes
-rw-r--r--macros/latex/required/latex-lab/documentmetadata-support-doc.pdfbin389003 -> 420933 bytes
-rw-r--r--macros/latex/required/latex-lab/documentmetadata-support.dtx155
-rw-r--r--macros/latex/required/latex-lab/latex-lab-amsmath.dtx124
-rw-r--r--macros/latex/required/latex-lab/latex-lab-amsmath.pdfbin357553 -> 382388 bytes
-rw-r--r--macros/latex/required/latex-lab/latex-lab-bib.dtx25
-rw-r--r--macros/latex/required/latex-lab/latex-lab-bib.pdfbin411092 -> 383673 bytes
-rw-r--r--macros/latex/required/latex-lab/latex-lab-block.dtx509
-rw-r--r--macros/latex/required/latex-lab/latex-lab-block.pdfbin886150 -> 881794 bytes
-rw-r--r--macros/latex/required/latex-lab/latex-lab-firstaid.dtx549
-rw-r--r--macros/latex/required/latex-lab/latex-lab-firstaid.pdfbin272864 -> 398544 bytes
-rw-r--r--macros/latex/required/latex-lab/latex-lab-float.dtx327
-rw-r--r--macros/latex/required/latex-lab/latex-lab-float.pdfbin444977 -> 444624 bytes
-rw-r--r--macros/latex/required/latex-lab/latex-lab-footnotes.dtx200
-rw-r--r--macros/latex/required/latex-lab/latex-lab-footnotes.pdfbin815656 -> 821496 bytes
-rw-r--r--macros/latex/required/latex-lab/latex-lab-graphic.dtx34
-rw-r--r--macros/latex/required/latex-lab/latex-lab-graphic.pdfbin496997 -> 517603 bytes
-rw-r--r--macros/latex/required/latex-lab/latex-lab-marginpar.dtx284
-rw-r--r--macros/latex/required/latex-lab/latex-lab-marginpar.pdfbin0 -> 414685 bytes
-rw-r--r--macros/latex/required/latex-lab/latex-lab-math.dtx2412
-rw-r--r--macros/latex/required/latex-lab/latex-lab-math.pdfbin612623 -> 797404 bytes
-rw-r--r--macros/latex/required/latex-lab/latex-lab-mathpkg.dtx35
-rw-r--r--macros/latex/required/latex-lab/latex-lab-mathpkg.pdfbin302371 -> 355758 bytes
-rw-r--r--macros/latex/required/latex-lab/latex-lab-mathtools.dtx29
-rw-r--r--macros/latex/required/latex-lab/latex-lab-mathtools.pdfbin357553 -> 372235 bytes
-rw-r--r--macros/latex/required/latex-lab/latex-lab-minipage.dtx59
-rw-r--r--macros/latex/required/latex-lab/latex-lab-minipage.pdfbin280811 -> 282259 bytes
-rw-r--r--macros/latex/required/latex-lab/latex-lab-namespace.dtx25
-rw-r--r--macros/latex/required/latex-lab/latex-lab-namespace.pdfbin234649 -> 235962 bytes
-rw-r--r--macros/latex/required/latex-lab/latex-lab-new-or-1.dtx2
-rw-r--r--macros/latex/required/latex-lab/latex-lab-new-or-1.pdfbin389721 -> 389721 bytes
-rw-r--r--macros/latex/required/latex-lab/latex-lab-new-or-2.dtx2
-rw-r--r--macros/latex/required/latex-lab/latex-lab-new-or-2.pdfbin632310 -> 632196 bytes
-rw-r--r--macros/latex/required/latex-lab/latex-lab-sec.dtx201
-rw-r--r--macros/latex/required/latex-lab/latex-lab-sec.pdfbin527916 -> 544929 bytes
-rw-r--r--macros/latex/required/latex-lab/latex-lab-table.dtx1709
-rw-r--r--macros/latex/required/latex-lab/latex-lab-table.pdfbin621929 -> 572577 bytes
-rw-r--r--macros/latex/required/latex-lab/latex-lab-testphase.dtx11
-rw-r--r--macros/latex/required/latex-lab/latex-lab-testphase.pdfbin298403 -> 298160 bytes
-rw-r--r--macros/latex/required/latex-lab/latex-lab-text.dtx10
-rw-r--r--macros/latex/required/latex-lab/latex-lab-text.pdfbin307812 -> 307847 bytes
-rw-r--r--macros/latex/required/latex-lab/latex-lab-title.dtx518
-rw-r--r--macros/latex/required/latex-lab/latex-lab-title.pdfbin0 -> 348117 bytes
-rw-r--r--macros/latex/required/latex-lab/latex-lab-toc-hyperref-changes.dtx2
-rw-r--r--macros/latex/required/latex-lab/latex-lab-toc-hyperref-changes.pdfbin296124 -> 296124 bytes
-rw-r--r--macros/latex/required/latex-lab/latex-lab-toc-kernel-changes.dtx178
-rw-r--r--macros/latex/required/latex-lab/latex-lab-toc-kernel-changes.pdfbin361084 -> 373186 bytes
-rw-r--r--macros/latex/required/latex-lab/latex-lab-toc.dtx185
-rw-r--r--macros/latex/required/latex-lab/latex-lab-toc.pdfbin396817 -> 406053 bytes
-rw-r--r--macros/latex/required/latex-lab/latex-lab.ins8
54 files changed, 5761 insertions, 2150 deletions
diff --git a/macros/latex/required/latex-lab/README.md b/macros/latex/required/latex-lab/README.md
index b27d0dc8fb..89d8d9f659 100644
--- a/macros/latex/required/latex-lab/README.md
+++ b/macros/latex/required/latex-lab/README.md
@@ -1,6 +1,6 @@
# LaTeX laboratory
-Release 2023-11-01
+Release 2024-11-01
## Overview
@@ -38,5 +38,5 @@ The license is LPPL 1.3c.
This README file is
-Copyright (C) 2021-2023
+Copyright (C) 2021-2024
The LaTeX Project
diff --git a/macros/latex/required/latex-lab/blocks-code.pdf b/macros/latex/required/latex-lab/blocks-code.pdf
index 91771be25c..6ed0532584 100644
--- a/macros/latex/required/latex-lab/blocks-code.pdf
+++ b/macros/latex/required/latex-lab/blocks-code.pdf
Binary files differ
diff --git a/macros/latex/required/latex-lab/blocks-doc.pdf b/macros/latex/required/latex-lab/blocks-doc.pdf
index 5f56e9052f..421ff15cd0 100644
--- a/macros/latex/required/latex-lab/blocks-doc.pdf
+++ b/macros/latex/required/latex-lab/blocks-doc.pdf
Binary files differ
diff --git a/macros/latex/required/latex-lab/changes.txt b/macros/latex/required/latex-lab/changes.txt
index 1a65830e8b..35c77075d6 100644
--- a/macros/latex/required/latex-lab/changes.txt
+++ b/macros/latex/required/latex-lab/changes.txt
@@ -1,12 +1,318 @@
+2024-10-25 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-math.dtx: reorganized luamml and mathml options
+ to support also structure elements and extended the documentation. Corrected
+ handling of alt-texts. Added examples for the various options.
+
+2024-10-16 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-firstaid.dtx: correct amsthm firstaid (tagging/733),
+ remove now unneeded code for cleveref.
+
+2024-10-12 Joseph Wright <Joseph.Wright@latex-project.org>
+ * latex-lab-math.dtx: Sync with protected-begin status
+
+2024-10-11 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-toc.dtx, latex-lab-sec.dtx, latex-lab-toc-kernel-changes: move target
+ handling (\MakeLinkTarget patches) into the kernel.
+
+2024-10-11 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * latex-lab-block.dtx (subsubsection{verse environment}):
+ Update \@itemlabel in \l_@@_legacy_env_params_tl and not at the start of
+ the environment (tagging/730)
+
+ Set the defaults for \@itemlabel, \@listctr and @nmbrlist early in the
+ block code before the setup code gets executed (tagging/730)
+
+ (subsubsection{Implementation of list templates ...):
+ Correct logic for setting up the list counter (tagging/730)
+
+2024-10-04 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-firstaid.dtx: add first support for fancyvrb environments.
+
+2024-10-04 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-sec.dtx (subsection{Sockets}):
+ add missing braces around optional arg (tagging/725)
+
+2024-10-03 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+ * latex-lab-block.dtx (subsubsection{Implementation of list templates ...}):
+ Pass user keys on list to \item for evaluation
+
+2024-10-02 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-math.dtx (subsection{Sockets}):
+ disable paratagging in inline math (tagging/711)
+
+2024-09-30 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-footnotes.dtx: remove unneeded NonStruct structure.
+
+2024-09-30 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+ * latex-lab-math.dtx (subsection{Content grabbing}):
+ Correct logic for inserting below skips after displays (tagging/721)
+
+2024-09-26 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-firstaid.dtx: add support for theorems declared with
+ amsthm, amsart, amsbook, amsproc.
+
+2024-09-24 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-sec.dtx,latex-lab-footnotes.dtx:
+ correct and improve footnotes in longtable
+
+2024-09-24 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-toc.dtx,latex-lab-footnotes.dtx: adapt Ref handling to tagpdf 0.99f
+
+2024-09-18 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-amsmath.dtx,latex-lab-graphic.dtc,
+ latex-lab-marginpar.dtx,latex-lab-math.dtx,latex-lab-mathtools.dtx,
+ latex-lab-minipage.dtx,latex-lab-sec.dtx,latex-lab-table.dtx,latex-lab-text.dtx:
+ switch to \tag_suspend:n and \tag_resume:n
+
+2024-09-17 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-float.dtx: switch to tagging sockets
+
+2024-09-13 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * documentmetadata-support.dtx: change warning to error if pdfstandard is unknown,
+ see https://github.com/latex3/pdfresources/issues/77#issuecomment-2329522654.
+
+2024-09-03 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * documentmetadata-support.dtx: switch to T1 encoding by default for non-Unicode
+ engines.
+
+2024-09-02 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+ * latex-lab-block.dtx (subsubsection{List tags}):
+ Do not close LI and LBody if they were never opened because of a
+ missing \item (issue tagging/641)
+
+ (subsubsection{Implementation of \cs{item} template(s)}):
+ Set @newlist to false after the first \item (issue tagging/36)
+
+ Call \@noitemerr in para/begin hook if hmode is started before
+ the first item
+
+ (subsubsection{Implementation of block templates \ldots}):
+ Drop \@noitemerr from \addvspace and \addpenalty
+
+2024-08-29 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-math.dtx: avoid loosing math if tagging is suspended,
+ tagging-project issue #661
+
+2024-08-22 Joseph Wright <Joseph.Wright@latex-project.org>
+ * latex-lab-math.dtx: correct handling of empty math processing
+
+2024-08-21 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-math.dtx: correct luamml patches for array,
+ allow to use luamml without unicode-math
+
+2024-08-14 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-math.dtx: add luamml support for automatic mathml generation
+
+2024-08-12 Joseph Wright <Joseph.Wright@latex-project.org>
+ * latex-lab-math.dtx: add support for math in tabulars
+
+2024-08-11 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-firstaid.dtx: amsproc support, discussion in PR #517
+
+2024-08-11 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-block.dtx: preset verbatim para-instance, issue #119
+
+2024-08-10 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-block.dtx, latex-lab-table.dtx: reset flattened level in para/restore, issue #544
+
+2024-08-08 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-minipage.dtx, latex-lab-table.dtx: improve support for minipage in tables.
+ handle issue #37
+
+2024-08-06 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-table.dtx: add support for header-columns
+ * latex-lab-table.dtx: add support for multirows
+ * latex-lab-table.dtx: handle issue #432
+ * latex-lab-marginpar.dtx: handle issue #444
+
+2024-07-11 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-footnote.dtx: restore paragraph defaults at the begin of the footnote
+ tagging-project#262
+
+2024-07-13 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * latex-lab-table.dtx (subsection{Tagging support sockets}):
+ add plugs for tbl/leaders/begin and /end
+ (subsection{Misc stuff}): drop unused socket
+
+2024-07-11 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-toc.dtx, latex-lab-toc-kernel-changes: switch from configuration points
+ to sockets.
+
+2024-05-25 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-table.dtx: disable table headers in presentation tables.
+
+2024-05-25 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-firstaid.dtx: add firstaid for booktabs cmidrules,
+ see tagging-issue 69.
+
+2024-04-18 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * documentmetadata-support.dtx: change handling of default language.
+ The code now tries to detect languages set by babel/polyglossia.
+
+2024-04-16 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-math.dtx: use tagging socket to disable math-writing if tagging
+ is suspended
+
+2024-03-24 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * latex-lab-namespace.xlsx:
+ File added (draft) replacing tagnames-commands.md
+
+2024-03-23 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * documentmetadata-support.dtx: keys for A4-E and A4-F
+
+2024-03-23 Yukai Chou <muzimuzhi@gmail.com>
+
+ * latex-lab-float.dtx (subsection{Patching}):
+ Fix missing underscore (_) in csname
+ Adjust white space before comment in \end@dblfloat
+
+2024-03-23 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-block.dtx: store main text-unit number for marginpars.
+
+2024-03-22 David Carlisle <David.Carlisle@latex-project.org>
+
+ * latex-lab-float.dtx (subsection{Patching}):
+ Adjust white space before comments
+
+2024-03-19 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * latex-lab-firstaid.dtx (subsection{verse}):
+ Added first aid for the verse package.
+
+ * latex-lab-block.dtx (subsection{Object and template interfaces}):
+ Change default for item-indent from 0pt to \itemindent. Otherwise, an
+ explicit setting for \itemindent in a legacy \list environment is
+ not picked up.
+
+2024-03-12 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * latex-lab-footnotes.dtx (section{Reimplementing the \pkg{footmisc} package}):
+ Typeset the footnote mark twice if the hang option is used. This means it can't
+ contain material that alter state, e.g., counters or labels.
+
+2024-03-11 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * latex-lab-footnotes.dtx (subsection{Debugging sockets and hooks}):
+ Added \DebugFNotesOn (and \DebugFNotesOff) not doing much for
+ now. Default is now to have debugging turned off (gh/58).
+
+ (subsubsection{Making documents use the new \cs{@makefntext}}):
+ Before attempting to patch old classes or packages check if the new
+ definition of \@makefntext is the one that was suppliedd by footmisc for
+ the hang option. (gh/12)
+
+ (subsubsection{Making documents use the new \cs{@makefntext}}):
+ Some classes/styles use \makebox rather than \hb@xt@, so try to patch
+ them too. Of course, none of this is very robust. By the end of the
+ day well need updating to the new standard solution.
+
+2024-02-23 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-amsmath.dtx, latex-lab-mathpkg.dtx: handle \pbm and poormans \bm
+ (luatex only)
+
+2024-02-23 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * update tagpdf and pdfmanagement
+
+2024-02-16 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-graphic.dtx: move end structure behind \fi, tagging-project#64
+
+2024-02-12 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-block.dtx: left align description labels.
+
+2024-02-07 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-table.dtx: change value layout to presentation (as in ARIA).
+
+2024-02-09 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-math.dtx: add keys to suppress AF-files locally
+
+2024-02-09 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-title.dtx: force DisplayDocTitle if UA-standard is detected
+
+2024-02-08 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-testphase.dtx: add marginpar tagging to phase-III
+
+2024-02-08 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-math.dtx, latex-lab-table.dtx: adapt tagpdfsetup keys
+
+2024-02-07 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-table.dtx: change key names from table-tagging to table/tagging
+
+2024-02-05 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-float.dtx: fix caption outside float error
+
+2024-02-05 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-toc-kernel-changes.dtx: fix spurious space, tagging-project#50
+
+2024-01-29 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-math.dtx: disable mathgrabbing in begindocument hook.
+
+2024-01-18 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-firstaid.dtx: add support for \authors from amsart.
+
+2024-01-18 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-title.dtx: make \@title and \@author robust to avoid errors
+ if they are not set.
+
+2024-01-18 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-table.dtx: add support for layout tables.
+
+2024-01-18 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-block.dtx: add support to set an attribute-class for para-main.
+
+2024-01-18 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-table.dtx: add option table-tagging=layout
+
+2024-01-17 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-math.dtx, latex-lab-amsmath.dtx, redefine \text to
+ avoid faulty structure and faulty PDF from \mathchoice.
+ Add statistic for mathml handling.
+
+2024-01-14 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-float.dtx, correct destination, see tagging issue #55
+
+2024-01-14 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-block.dtx, correct error message for environments,
+ see tagging issue #57
+
+2024-01-12 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-table.dtx: add some variables for tag names
+
+2024-01-08 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * move mathml-AF support into latex-lab-math.ltx
+
+2023-12-27 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * added latex-lab-title.dtx for maketitle/title and author tagging.
+
+2023-11-18 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-block.dtx, correct error message for items outside lists
+ see tagging issue #35
+
+2023-11-17 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-block.dtx, latex-lab-sec.dtx: use wrapper for para counter,
+ see tagging issue #34
+
+2023-11-12 Joseph Wright <Joseph.Wright@latex-project.org>
+ * latex-lab-math.dtx: tidy variant creation, switch to e-type expansion
+
+2023-11-05 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-math.dtx: remove processor in \(..\), see tagging issue #29
+
+2023-11-05 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
+ * latex-lab-math.dtx: handle also tabular*, see tagging issue #25
+ * latex-lab-table.dtx: use cmd hook for array, see tagging issue #28
+
2023-10-30 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
- * added latex-lab-table.dtx for basic table tagging.
+ * added latex-lab-table.dtx for basic table tagging.
2023-10-21 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
* latex-lab-minipage.dtx: use sockets to allow local changes
2023-10-13 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
- * latex-lab-toc.dtx, latex-lab-sec.dtx, latex-lab-toc-kernel-changes: extend
- \MakeLinkTarget to store the target-structure relationship too, see tagging issue #20
+ * latex-lab-toc.dtx, latex-lab-sec.dtx, latex-lab-toc-kernel-changes: extend
+ \MakeLinkTarget to store the target-structure relationship too, see tagging issue #20
2023-10-13 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
* latex-lab-graphic.dtx: fix handling of scale factor, tagging issue #16
@@ -21,7 +327,7 @@
2023-09-04 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
* label-lab-new-or-1.dtx latex-lab-new-or-2.dtx
fix position of kernel hook in \@makecol (tagpdf issue #58)
-
+
2023-09-04 Ulrike Fischer <Ulrike.Fischer@latex-project.org>
* documentmetadata-support.dtx: add debug key to load tagpdf-debug.
* new latex-lab-namespace.dtx with role mappings
diff --git a/macros/latex/required/latex-lab/documentmetadata-support-code.pdf b/macros/latex/required/latex-lab/documentmetadata-support-code.pdf
index d419630dff..5fec54a3cb 100644
--- a/macros/latex/required/latex-lab/documentmetadata-support-code.pdf
+++ b/macros/latex/required/latex-lab/documentmetadata-support-code.pdf
Binary files differ
diff --git a/macros/latex/required/latex-lab/documentmetadata-support-doc.pdf b/macros/latex/required/latex-lab/documentmetadata-support-doc.pdf
index a1c42b21f4..562f8d98bc 100644
--- a/macros/latex/required/latex-lab/documentmetadata-support-doc.pdf
+++ b/macros/latex/required/latex-lab/documentmetadata-support-doc.pdf
Binary files differ
diff --git a/macros/latex/required/latex-lab/documentmetadata-support.dtx b/macros/latex/required/latex-lab/documentmetadata-support.dtx
index b37ae6c9d7..6752e8098a 100644
--- a/macros/latex/required/latex-lab/documentmetadata-support.dtx
+++ b/macros/latex/required/latex-lab/documentmetadata-support.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
%% File: documentmetadata-support.dtx
-% Copyright (C) 2021-2023 The LaTeX Project
+% Copyright (C) 2021-2024 The LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -18,8 +18,8 @@
% for those people who are interested or want to report an issue.
%
% \begin{macrocode}
-\def\documentmetadatasupportversion{1.0f}
-\def\documentmetadatasupportdate{2023-09-01}
+\def\documentmetadatasupportversion{1.0j}
+\def\documentmetadatasupportdate{2024-09-13}
% \end{macrocode}
%
%
@@ -84,8 +84,17 @@
% features developed as part of the multi-year ``Tagged PDF''
% project~\cite{blueprint}.
%
-%
-%
+% \section{The \cs{DocumentMetadata} command}
+%
+% \begin{function}{\DocumentMetadata}
+% \begin{syntax}
+% \cs{DocumentMetadata}\Arg{key-value list}
+% \end{syntax}
+%
+% The command should be used as the first command in a document, before
+% \cs{documentclass}. It takes a key-value argument.
+% \end{function}
+
% \section{Currently supported key/values}
%
%
@@ -116,7 +125,8 @@
% e.g., \texttt{lang=de-DE}. If not given the default value used is |en-US|.
%
% \item[\texttt{pdfstandard}] Choice key to set the pdf standard.
-% Currently |A-1b|, |A-2a|, |A-2b|, |A-2u|, |A-3a|, |A-3b|, |A-3u| and |A-4| are accepted as
+% Currently |A-1b|, |A-2a|, |A-2b|, |A-2u|, |A-3a|, |A-3b|, |A-3u|, |A-4|, |A-4E|
+% and |A-4F| are accepted as
% values. The casing is irrelevant, |a-1b| works too.
% Note that using these
% key doesn't mean that the document actually follows the standard. \LaTeX{}
@@ -162,12 +172,12 @@
% \item[\texttt{phase-I}]
% This value loads code implementing the first phase of the project~\cite{blueprint}, i.e., it
% will load the tagpdf package. It will also activate tagging by issuing
-% |\tagpdfsetup{activate,interwordspace}|. This phase
+% |\tagpdfsetup{activate,activate/spaces}|. This phase
% is frozen.
% \item[\texttt{phase-II}]
% It differs from \texttt{phase-I} only in one point: It will
% additionally activate tagging of paragraphs with
-% |\tagpdfsetup{paratagging}|. In the upcoming months it will
+% |\tagpdfsetup{para/tagging}|. In the upcoming months it will
% also enable automatic tagging of other basic document elements.
% \item[\texttt{phase-III}]
% This is the current development phase.
@@ -179,7 +189,7 @@
% and it supports only a limited number of add-on packages.
% \end{description}
%
-% The various testphase modules can also be loaded individually (and least in theory,
+% The various testphase modules can also be loaded individually (at least in theory,
% there can be hidden dependencies). If loaded like this, the tagpdf package is not
% loaded and tagging is not activated! The list of modules will change over time.
% \begin{description}
@@ -213,8 +223,19 @@
% \item[\texttt{text}] This module adds tagging support to the \LaTeX{} logo and
% to the \cs{emph} command.
% This code is also loaded by the \texttt{phase-III} key.
+% \item[\texttt{marginpar}] This module adds tagging support to the \cs{marginpar}
+% command. This code is also loaded by the \texttt{phase-III} key.
+% \item[\texttt{title}] This module add tagging support to the \cs{maketitle}
+% command if a standard class is used. It also enhances the \cs{title}
+% and \cs{author} commands to fill the XMP-metadata and set the window title.
+% It is not compatible with packages and classes which redefine these commands
+% too. The module is currently not loaded by any \texttt{phase} key.
% \item[\texttt{math}] This adapts math for tagging. This is only a prototype.
% The module is currently not loaded by any \texttt{phase} key.
+% \item[\texttt{table}] This provides basic tagging for
+% \texttt{tabular}, \texttt{longtable} and similar table environments.
+% The module is currently not loaded by any \texttt{phase} key. Its use and
+% restrictions is documented in \texttt{latex-lab-table.pdf}.%
% \item[\texttt{firstaid}] This contains small adjustments to external packages.
% The module is currently not loaded by any \texttt{phase} key.
% \end{description}
@@ -274,8 +295,41 @@
\ExplSyntaxOn\makeatletter
% \end{macrocode}
+% \subsection{Variables}
+% These variable definitions are currently also done in ltdocinit.
+% They can be removed from there once latex-lab has been updated to
+% provide them too.
+% \begin{variable}{\g_@@_firstaidoff_clist}
+% A list to store the firstaid code which should be disabled
+% \begin{macrocode}
+\clist_if_exist:NF \g_@@_firstaidoff_clist
+ { \clist_new:N \g_@@_firstaidoff_clist }
+% \end{macrocode}
+% \end{variable}
+% \begin{variable}{\g_@@_testphase_tl}
+% a tl to store the testphase loading code so that we can load them at
+% the end of the command.
+% \begin{macrocode}
+\tl_if_exist:NF \g_@@_testphase_tl
+ { \tl_new:N \g_@@_testphase_tl }
+% \end{macrocode}
+% \end{variable}
+%
+% \subsection{Kernel changes with \cs{DocumentMetadata}}
+% \begin{macro}{\@kernel@before@DocumentMetadata}
+% \begin{macrocode}
+\cs_new_protected:Npn \@kernel@before@DocumentMetadata
+ {
+ \ifx\Umathcode\@undefined
+ \fontencoding{T1}
+ \renewcommand\encodingdefault{T1}
+ \fi
+ }
+% \end{macrocode}
+% \end{macro}
-
+% \subsection{\cs{DocumentMetadata}}
+%
% \begin{macro}{\DocumentMetadata}
%
% \cs{DocumentMetadata} should not be used after
@@ -289,6 +343,10 @@
{ \msg_error:nn { meta } { after-class } }
{
% \end{macrocode}
+% Load general format changes
+% \begin{macrocode}
+ \@kernel@before@DocumentMetadata
+% \end{macrocode}
%
% The wanted backend must be detected first, we read the init
% key and then force the loading of the backend.
@@ -309,14 +367,35 @@
\file_input:n {l3backend-testphase-\c_sys_backend_str.def}
\ExplSyntaxOff\makeatother
% \end{macrocode}
-% Set the default language (this requires that the backend has been loaded),
-% process the rest of the keys,
-% and setup the generic driver.
+%
+% Process the init keys and setup the generic driver.
% \begin{macrocode}
- \keys_set_filter:nnn { document / metadata } { init } { lang=en-US, #1 }
+ \keys_set_filter:nnn { document / metadata } { init } { #1 }
\bool_if:NT \g_@@_active_bool
{
\PassOptionsToPackage{customdriver=hgeneric-testphase}{hyperref}
+% \end{macrocode}
+% Finally we setup the language default.
+% This is done after the begindocument hook so that it can pick up settings
+% from babel. If the Catalog dictionary already contains a lang value we do nothing,
+% otherwise we use the value stored in \cs{BCPdata}, either the main language
+% (if its exists) or the fall back language.
+% Note: if babel is loaded without a language this gives the language \texttt{und}.
+% \begin{macrocode}
+ \g@addto@macro\@kernel@after@begindocument
+ {
+ \pdfdict_get:nnN {g__pdf_Core/Catalog}{Lang}\l_@@_tmpa_tl
+ \quark_if_no_value:NT\l_@@_tmpa_tl
+ {
+ \tl_if_empty:eTF { \BCPdata{main.language} }
+ { \tl_set:Ne \l_@@_tmpb_tl { \BCPdata{language} } }
+ { \tl_set:Ne \l_@@_tmpb_tl { \BCPdata{main.language} } }
+ \msg_warning:nne { meta } { lang-missing }{ \l_@@_tmpb_tl }
+ \exp_last_unbraced:Ne
+ \AddToDocumentProperties{[document]{lang}{\l_@@_tmpb_tl}}
+ \pdfmanagement_add:nne {Catalog} {Lang}{(\l_@@_tmpb_tl)}
+ }
+ }
}
% \end{macrocode}
% \cs{pdfmanagement_add:nnn} has collected values in this hook.
@@ -348,15 +427,8 @@
% \end{macrocode}
% \end{macro}
-
-
-
+%\subsection{\cs{DocumentMetadata} keys}
% \begin{macrocode}
-%FMi defined elsewhere
-%FMi
-%FMi \clist_new:N \g_@@_firstaidoff_clist
-%FMi \tl_new:N \g_@@_testphase_tl
-% UFi should the definition move to here?
\keys_define:nn { document / metadata }
{
backend .choices:nn =
@@ -388,7 +460,7 @@
% this uses internal command from pdfmeta, it should probably move there ...
,pdfstandard .code:n =
{
- \exp_args:Nnx
+ \exp_args:Nne
\keys_set:nn {document / metadata} {_pdfstandard=\str_uppercase:n{#1}}
}
,_pdfstandard .choices:nn =
@@ -400,9 +472,33 @@
}
\AddToDocumentProperties [document]{pdfstandard}{#1}
}
+ ,_pdfstandard / A-4F .code:n =
+ {
+ \prop_if_exist:cTF { g__pdfmeta_standard_pdf/A-4F_prop }
+ {
+ \prop_gset_eq:Nc \g__pdfmeta_standard_prop { g__pdfmeta_standard_pdf/A-4F_prop }
+ }
+ {
+ \prop_gset_eq:Nc \g__pdfmeta_standard_prop { g__pdfmeta_standard_pdf/A-4_prop }
+ \prop_gput:Nnn \g__pdfmeta_standard_prop{conformance}{F}
+ }
+ \AddToDocumentProperties [document]{pdfstandard}{A-4F}
+ }
+ ,_pdfstandard / A-4E .code:n =
+ {
+ \prop_if_exist:cTF { g__pdfmeta_standard_pdf/A-4E_prop }
+ {
+ \prop_gset_eq:Nc \g__pdfmeta_standard_prop { g__pdfmeta_standard_pdf/A-4E_prop }
+ }
+ {
+ \prop_gset_eq:Nc \g__pdfmeta_standard_prop { g__pdfmeta_standard_pdf/A-4_prop }
+ \prop_gput:Nnn \g__pdfmeta_standard_prop{conformance}{E}
+ }
+ \AddToDocumentProperties [document]{pdfstandard}{A-4E}
+ }
,_pdfstandard / unknown .code:n =
{
- \msg_warning:nnn{pdf}{unknown-standard}{#1}
+ \msg_error:nnn{pdf}{unknown-standard}{#1}
}
,testphase .multichoice:
,testphase / tagpdf .code:n =
@@ -413,7 +509,7 @@
{
\RequirePackage{tagpdf}
\AddToDocumentProperties [document]{testphase/tagpdf}{loaded}
- \tagpdfsetup{activate,paratagging,interwordspace}
+ \tagpdfsetup{activate,para/tagging,activate/spaces}
\AddToDocumentProperties [document]{tagging}{active}
\AddToDocumentProperties [document]{tagging/para}{active}
\AddToDocumentProperties [document]{tagging/interwordspace}{active}
@@ -450,7 +546,7 @@
package/tagpdf/after
}
{
- \tagpdfsetup{paratagging-show}
+ \tagpdfsetup{debug/show=para}
}
}
,debug / log .code:n =
@@ -460,7 +556,7 @@
package/tagpdf/after
}
{
- \tagpdfsetup{log=#1}
+ \tagpdfsetup{debug/log=#1}
}
}
,debug / tagpdf .code:n =
@@ -498,6 +594,11 @@
{
LaTeX-lab~package~'#1'~not~found.
}
+\msg_new:nnn { meta } { lang-missing }
+ {
+ The~language~has~not~been~set~in~\token_to_str:N
+ \DocumentMetadata.\\Setting~it~to~'#1'~as~fallback.
+ }
% \end{macrocode}
%
% \begin{macrocode}
diff --git a/macros/latex/required/latex-lab/latex-lab-amsmath.dtx b/macros/latex/required/latex-lab/latex-lab-amsmath.dtx
index e1f95730fa..8591b39b39 100644
--- a/macros/latex/required/latex-lab/latex-lab-amsmath.dtx
+++ b/macros/latex/required/latex-lab/latex-lab-amsmath.dtx
@@ -2,7 +2,7 @@
%
%% File: latex-lab-amsmath.dtx
%
-% Copyright (C) 2022,2023 The LaTeX Project
+% Copyright (C) 2022-2024 The LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -66,7 +66,7 @@
% \subsection{File declaration}
% \begin{macrocode}
\ProvidesFile{latex-lab-amsmath.ltx}
- [2023-01-05 v0.1a amsmath adaptions]
+ [2024-09-18 v0.1c amsmath adaptions]
% \end{macrocode}
% \subsection{Tagpdf support}
% To make the code independent from tagging being loaded and active
@@ -90,12 +90,16 @@
\def\intertext##1{%
\ifvmode\else\\\@empty\fi
\noalign{%
- \penalty\postdisplaypenalty\vskip\belowdisplayskip
+% \end{macrocode}
+% we have to flip the sign and use a negative \cs{belowdisplayskip}
+% as we flipped the sign at the outside.
+% \begin{macrocode}
+ \penalty\postdisplaypenalty\vskip-\belowdisplayskip
\vbox{
% \end{macrocode}
% Stop tagging when measuring:
% \begin{macrocode}
- \ifmeasuring@\tag_stop:\fi
+ \ifmeasuring@\tag_suspend:n{\measuring}\fi
\normalbaselines
\ifdim\linewidth=\columnwidth
\else \parshape\@ne \@totalleftmargin \linewidth
@@ -105,9 +109,13 @@
% \begin{macrocode}
\tag_mc_end_push:
% \end{macrocode}
-% We are already in a par so we change now to Span:
+% We are already in a par so we change now to text:
+% \begin{macrocode}
+ \tagpdfsetup{para/tag=P}%
+% \end{macrocode}
+% TODO why \cs{tagpdfparaOn} needed?
% \begin{macrocode}
- \tagpdfsetup{paratag=Span}%
+ \tagpdfparaOn
\noindent\ignorespaces##1\par
% \end{macrocode}
% Restart the MC
@@ -119,6 +127,110 @@
}
% \end{macrocode}
%
+% \subsection{\cs{text}}
+%
+% The \cs{text} command uses \cs{mathchoice} which \enquote{typesets} the argument
+% four times. This makes it quite problematic for tagging. Without precautions
+% structure objects would be created four times and would get MC-chunks as kids
+% that doesn't really exist. amsmath contains a switch that allows to execute code
+% only in the first (displaymath) branch, but that isn't usable here. At first because
+% we don't know if the first branch creates the same structure as the one that is
+% actually used. At second because the engines executes some commands like \cs{label}
+% and \cs{pdfannot} only at shipout from the branch that really was used. So we would
+% get structure data from one \cs{mathchoice}-branch and MC-labels and links from another
+% one and that gets very messy.
+%
+% We therefore have to avoid that tagging is active in unused branches. In pdflatex it
+% is not possible to detect the mathstyle before, so we use a label. With lualatex is
+% is possible to redefine \cs{text} not to use \cs{mathchoice}
+%
+% \begin{macrocode}
+\AddToHook{package/amstext/after}
+ {
+% \end{macrocode}
+% currently amsmath is loaded in a begindocument hook, so this
+% test is fine. If amstext is loaded earlier (in the kernel), this needs perhaps a change.
+% \begin{macrocode}
+ \tag_if_active:T
+ {
+ \sys_if_engine_luatex:TF
+ {
+ \def\text@#1{{%
+ \ifcase\mathstyle
+ \hbox{{#1}}\or
+ \hbox{{#1}}\or
+ \hbox{{#1}}\or
+ \hbox{{#1}}\or
+ \hbox{{\let\f@size\sf@size\selectfont#1}}\or
+ \hbox{{\let\f@size\sf@size\selectfont#1}}\or
+ \hbox{{\let\f@size\ssf@size\selectfont#1}}\or
+ \hbox{{\let\f@size\ssf@size\selectfont#1}}\or
+ \ERROR
+ \fi
+ \check@mathfonts
+ }}
+ }
+ {
+ \def\text@#1
+ {{
+ \int_gincr:N\g__math_mathchoice_int
+ \tag_suspend:n{\text@}
+ \mathchoice
+ {
+ \@@_tag_if_mathstyle:en{mathchoice-\int_use:N\g__math_mathchoice_int}{0}
+ \textdef@\displaystyle\f@size{#1}
+ }
+ {
+ \@@_tag_if_mathstyle:en{mathchoice-\int_use:N\g__math_mathchoice_int}{2}
+ \textdef@\textstyle\f@size{\firstchoice@false #1}
+ }
+ {
+ \@@_tag_if_mathstyle:en{mathchoice-\int_use:N\g__math_mathchoice_int}{4}
+ \textdef@\textstyle\sf@size{\firstchoice@false #1}
+ }
+ {
+ \@@_tag_if_mathstyle:en{mathchoice-\int_use:N\g__math_mathchoice_int}{6}
+ \textdef@\textstyle \ssf@size{\firstchoice@false #1}
+ }
+ \check@mathfonts
+ }}
+ }
+ }
+ }
+% \end{macrocode}
+%
+% \subsection{\cs{pmb}}
+% \cs{pmb} prints its argument three times. For tagging we must mark
+% two of occurrences as artifact.
+% For luatex the attributes in the box must be reset, for this
+% we switch to expl3-boxes.
+% \begin{macrocode}
+\AddToHook{package/amsbsy/after}
+ {
+ \def\pmb@@@@#1#2#3{\leavevmode\hbox_set:Nn\l_@@_tmpa_box{xxx#3}
+ \dimen@-\box_wd:N\l_@@_tmpa_box
+ \kern-.5\ex@\box_use:N\l_@@_tmpa_box
+ \tag_mc_end:\tag_mc_begin:n{artifact}
+ \tag_mc_reset_box:N\l_@@_tmpa_box
+ \kern\dimen@\kern.25\ex@\raise.4\ex@\box_use:N\l_@@_tmpa_box
+ \kern\dimen@\kern.25\ex@\box_use_drop:N\l_@@_tmpa_box
+ \tag_mc_end:\tag_mc_begin:n{}
+ }
+ \def\pmb@#1#2{\hbox_set:Nn\l_@@_tmpa_box{$\m@th#1{#2}$}
+ \setboxz@h{$\m@th#1\mkern.5mu$}\pmbraise@\wdz@
+ \binrel@{#2}
+ \dimen@-\box_wd:N\l_@@_tmpa_box
+ \binrel@@@@{
+ \mkern-.8mu\box_use:N\l_@@_tmpa_box
+ \tag_mc_end:\tag_mc_begin:n{artifact}
+ \tag_mc_reset_box:N\l_@@_tmpa_box
+ \kern\dimen@\mkern.4mu\raise\pmbraise@\box_use:N\l_@@_tmpa_box
+ \kern\dimen@\mkern.4mu\box_use_drop:N\l_@@_tmpa_box
+ \tag_mc_end:\tag_mc_begin:n{}
+ }
+ }
+ }
+% \end{macrocode}
% \begin{macrocode}
\ExplSyntaxOff
% \end{macrocode}
diff --git a/macros/latex/required/latex-lab/latex-lab-amsmath.pdf b/macros/latex/required/latex-lab/latex-lab-amsmath.pdf
index 54ffaaf99a..828677fe17 100644
--- a/macros/latex/required/latex-lab/latex-lab-amsmath.pdf
+++ b/macros/latex/required/latex-lab/latex-lab-amsmath.pdf
Binary files differ
diff --git a/macros/latex/required/latex-lab/latex-lab-bib.dtx b/macros/latex/required/latex-lab/latex-lab-bib.dtx
index a467bf3158..9d336aba20 100644
--- a/macros/latex/required/latex-lab/latex-lab-bib.dtx
+++ b/macros/latex/required/latex-lab/latex-lab-bib.dtx
@@ -16,8 +16,8 @@
%
% for those people who are interested or want to report an issue.
%
-\def\ltlabbibdate{2023-07-20}
-\def\ltlabbibversion{0.81a}
+\def\ltlabbibdate{2024-07-05}
+\def\ltlabbibversion{0.81b}
%<*driver>
\documentclass{l3doc}
\EnableCrossrefs
@@ -124,6 +124,17 @@
% but has to test if this anchor is already known.
% \end{description}
%
+% \section{Provided or redefined commands}
+%
+% \begin{function}{\@extra@binfo,\@extra@b@citeb}
+%
+% These are taken from hyperref, they are for chapterbib compatibility (and also
+% signal to chapterbib not to change the citation commands)
+% \end{function}
+%
+% \begin{function}{\@bibitem,\@lbibitem}
+% The internal item commands.
+% \end{function}
%
% \section{Implementation}
% \begin{macrocode}
@@ -146,7 +157,7 @@
% \end{macrocode}
% \begin{macro}{\@extra@binfo,\@extra@b@citeb}
-% These are taken from hyperref, they are for chapterbib compability (and also
+% These are taken from hyperref, they are for chapterbib compatibility (and also
% signal to chapterbib not to change the citation commands)
% \begin{macrocode}
\providecommand*\@extra@binfo{}%
@@ -259,12 +270,12 @@
% \end{macrocode}
% Now we add the tagging structure.
% TODO: with the next tagpdf version it should no longer be
-% needed to exand the ref key.
+% needed to expand the ref key.
% \begin{macrocode}
\AddToHookWithArguments{bibcite/before}
{
\tag_mc_end_push:
- \exp_args:Nx\tagstructbegin{tag=Reference,ref=cite.#1\@extra@b@citeb}
+ \exp_args:Ne\tagstructbegin{tag=Reference,ref=cite.#1\@extra@b@citeb}
\tagmcbegin{}
}
\AddToHookWithArguments{bibcite/after}[tag]
@@ -294,7 +305,7 @@
% We need in part different code for both systems:
% with biblatex we have to take care that only the first
% structure sets a label, and if
-% hyperref is not loaded (or deactived) we will need additional code
+% hyperref is not loaded (or deactivated) we will need additional code
% but this currently doesn't exist.
% We assume that no document loads both package -- that will probably break.
% \begin{macrocode}
@@ -318,7 +329,7 @@
{
\leavevmode
\tag_mc_end_push:
- \exp_args:Nx\tag_struct_begin:n{tag=Reference,ref=cite.#1\@extra@b@citeb}
+ \exp_args:Ne\tag_struct_begin:n{tag=Reference,ref=cite.#1\@extra@b@citeb}
\tag_mc_begin:n{}
}
\AddToHook{cmd/hyper@natlinkend/after}
diff --git a/macros/latex/required/latex-lab/latex-lab-bib.pdf b/macros/latex/required/latex-lab/latex-lab-bib.pdf
index fabcc7cfa3..507ada06ef 100644
--- a/macros/latex/required/latex-lab/latex-lab-bib.pdf
+++ b/macros/latex/required/latex-lab/latex-lab-bib.pdf
Binary files differ
diff --git a/macros/latex/required/latex-lab/latex-lab-block.dtx b/macros/latex/required/latex-lab/latex-lab-block.dtx
index e0a723ca87..74d68c495a 100644
--- a/macros/latex/required/latex-lab/latex-lab-block.dtx
+++ b/macros/latex/required/latex-lab/latex-lab-block.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-%% File: latex-lab-block.dtx (C) Copyright 2021-2023 LaTeX Project
+%% File: latex-lab-block.dtx (C) Copyright 2021-2024 LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -9,10 +9,10 @@
%
% https://www.latex-project.org/lppl.txt
%
-\def\ltlabblockdate{2023-09-01}
-\def\ltlabblockversion{0.8h}
+\def\ltlabblockdate{2024-10-11}
+\def\ltlabblockversion{0.8v}
%<*driver>
-\documentclass{l3doc}
+\documentclass[kernel]{l3doc}
\usepackage{amstext}
\EnableCrossrefs
\CodelineIndex
@@ -308,7 +308,7 @@
% \end{TemplateDescription}
%
% The maximum number of \xt{blockenv}s that can be nested into each
-% other is is restricted by the \LaTeX{} counter
+% other is restricted by the \LaTeX{} counter
% \texttt{maxblocklevels} with a default value of \texttt{6}. If this
% value is increased then it is necessary to provide additional
% instances, e.g., \texttt{displayblock-7}, etc. Decreasing is, of
@@ -331,6 +331,8 @@
% \TemplateKey{par-skip}{skip}{}{\cs{parsep}}
% \TemplateKey{end-skip}{skip}{}{\valuefrom{beginsep}}
% \TemplateKey{end-par-skip}{skip}{}{\valuefrom{begin-par-skip}}
+% \TemplateKey{item-skip}{skip}{The space in front of an item if the
+% block is a list; if not the setting has no effect}{\cs{itemsep}}
% \TemplateKey{beginpenalty}{integer}{}{\cs{@beginparpenalty}}
% \TemplateKey{endpenalty}{integer}{}{\cs{@endparpenalty}}
% \TemplateKey{leftmargin}{length}{}{\cs{leftmargin}}
@@ -341,7 +343,7 @@
%
% The idea of a \key{heading} key needs some further
% thoughts. Maybe instead the object type should accept a second
-% argument and receive input for such a headding from the document
+% argument and receive input for such a heading from the document
% level instead.
%
% The names of the keys need further thoughts and some
@@ -390,7 +392,7 @@
% {Instance of type \texttt{item} to be used to format
% the label string}{basic}
% \TemplateKey{item-skip}{skip}{The space in front of an item in the
-% list.\fmi{May need to be on a different template level}}{\cs{itemsep}}
+% list. If not specified the value specified in the block template instance is used}{}
% \TemplateKey{item-indent}{length}{Horizontal displacement of the item.}{0pt}
% \TemplateKey{item-penalty}{integer}
% {Penalty for breaking before an
@@ -474,7 +476,7 @@
% \>\>\> The paragraph text before the display element \ldots\\
% \>\> \struct{/text}\\
% \>\> \struct{display element structure}\\
-% \>\>\> Content of the display structure possiblly involving inner \struct{text-unit} tags\\
+% \>\>\> Content of the display structure possibly involving inner \struct{text-unit} tags\\
% \>\> \struct{/display element structure}\\
% \>\> \struct{text}\\
% \>\>\> \ldots{} continuing the outer paragraph text\\
@@ -646,11 +648,59 @@
%
% \end{description}
%
+% \section{Debugging}
+%
+% \begin{function}{\DebugBlocksOn,\DebugBlocksOff, \block_debug_on:, \block_debug_off:}
+%
+% These commands enable/disable debugging messages.
+%
+% \end{function}
%
+% \section{New and redefined kernel command}
+%
+% \begin{function}{\@doendpe}
+% The original \LaTeXe{} command is augmented to allow for tagging.
+% \end{function}
%
+% \begin{function}{\legacyverbatimsetup,\legacylistsetupcode}
+% \emph{to be documented}
+% \end{function}
+%
+% \begin{function}{\@setupverbinvisiblespace}
+% A counterpart definition to the kernel command \cs{@setupverbinvisiblespace},
+% needed as we need to handle real space chars in verbatim.
+% \end{function}
+%
+% \begin{function}{endblockenv,\g_block_nesting_depth_int}
+% \emph{to be documented}
+% \end{function}
+%
+% \begin{function}{\newtheorem,\@thm,\@begintheorem}
+% Redefined to make theorems tagging aware.
+% \end{function}
%
+% \begin{function}{\item,\@itemlabel}
+% The \cs{item} is redefined.
+% \end{function}
%
-%
+% \begin{function}{\c@maxblocklevels}
+% A counter to increase or decrease the number of supported
+% level. If increased, one needs to supply additional level instances.
+% \end{function}
+%
+% \begin{function}{\begin}
+% The \cs{begin} is slightly redefine to handle \cs{@doendpe} better.
+% TODO: move to kernel
+% \end{function}
+%
+% \begin{function}{\para_end:}
+% TODO: consider name, document
+% \end{function}
+%
+% \begin{function}{para/begin}
+% The para/begin hook is enhanced to support list ends
+% \end{function}
+%
% \end{documentation}
%
% \StopEventually{\setlength\IndexMin{200pt} \PrintIndex }
@@ -674,11 +724,7 @@
blockenv implementation]
% \end{macrocode}
%
-% We make use of templates:
-% \begin{macrocode}
-\RequirePackage{xtemplate}
-% \end{macrocode}
-% Generell kernel changes, also loaded by the sec and toc code.
+% General kernel changes, also loaded by the sec and toc code.
% \begin{macrocode}
\RequirePackage{latex-lab-kernel-changes}
% \end{macrocode}
@@ -691,7 +737,7 @@
\tl_new:N \l_@@_item_align_tl
\tl_new:N\l_@@_legacy_env_params_tl
% \end{macrocode}
-
+%
% \subsection{Handling \cs{par} after the end of the list}
%
% An empty line (or a \cs{par}) after a list has semantic meaning as
@@ -712,8 +758,9 @@
%
%
%
-% \begin{macro}{\@doendpe}
+% \begin{macro}{\@doendpe,\__kernel_displayblock_doendpe:}
% The original \LaTeXe{} command is augmented to allow for tagging.
+% TODO: use sockets for this and move to the kernel eventually.
% \begin{macrocode}
\def\@doendpe{\@endpetrue
\def\par
@@ -748,15 +795,10 @@
% \begin{macrocode}
\cs_new_eq:NN \__kernel_displayblock_doendpe: \prg_do_nothing:
% \end{macrocode}
-% The flag itself should be set globally not locally.\fmi{verify
-% that this claim is actually correct!}
-% \begin{macrocode}
-\def\@endpetrue {\global\let\if@endpe\iftrue}
-\def\@endpefalse{\global\let\if@endpe\iffalse}
-% \end{macrocode}
-% \end{macro}
%
%
+% \end{macro}
+%
%
% \subsection{Object and template interfaces}
%
@@ -767,11 +809,11 @@
% given use in the document. This section is devoted to template
% interfaces, and the template code is covered later.
% \begin{macrocode}
-\DeclareObjectType{blockenv}{1}
-\DeclareObjectType{block}{1}
-\DeclareObjectType{para}{1}
-\DeclareObjectType{list}{1}
-\DeclareObjectType{item}{1}
+\NewTemplateType{blockenv}{1}
+\NewTemplateType{block}{1}
+\NewTemplateType{para}{1}
+\NewTemplateType{list}{1}
+\NewTemplateType{item}{1}
% \end{macrocode}
% \end{objecttype}
%
@@ -803,6 +845,7 @@
%
% \begin{template}{block display}
%
+% \changes{v0.8s}{2024/10/03}{Offer item-skip key also on block templates}
% \begin{macrocode}
\DeclareTemplateInterface{block}{display}{1}
{
@@ -812,6 +855,7 @@
par-skip : skip = \parsep ,
end-skip : skip = \KeyValue{beginsep} , % conflict with name below
end-par-skip : skip = \KeyValue{begin-par-skip} ,
+ item-skip : skip = \itemsep ,
beginpenalty : integer = \UseName{@beginparpenalty} ,
endpenalty : integer = \UseName{@endparpenalty} ,
leftmargin : length = \leftmargin ,
@@ -854,7 +898,7 @@
item-instance : instance{item} = basic ,
item-skip : skip = \itemsep ,
item-penalty : integer = \UseName{@itempenalty} ,
- item-indent : length = 0pt , % was \itemindent
+ item-indent : length = \itemindent ,
label-width : length = \labelwidth ,
label-sep : length = \labelsep ,
legacy-support : boolean = false ,
@@ -893,8 +937,8 @@
% This section collects \pkg{expl3} commands that will be useful.
%
% \begin{macro}{\@@_skip_set_to_last:N,\@@_skip_remove_last:}
-% Set a skiip register to the value of an immediately preceding
-% skip or zero if there was none
+% Set a skip register to the value of an immediately preceding
+% skip or zero if there was none.
% \begin{macrocode}
\cs_new_protected:Npn \@@_skip_set_to_last:N #1 {
\skip_set:Nn #1 { \tex_lastskip:D }
@@ -907,12 +951,9 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\tl_if_novalue:nTF}
-%
% \begin{macrocode}
\cs_generate_variant:Nn \tl_if_novalue:nTF { o }
% \end{macrocode}
-% \end{macro}
%
%
% \subsubsection{Debugging}
@@ -1228,9 +1269,15 @@
% We do this by storing them away and then call the list
% instance. Inside this instance the \texttt{setup-code} key
% contains \cs{legacylistsetupcode}, which makes use of the stored values.
+% \changes{v0.8v}{2024/10/11}{Update \cs{@itemlabel} in
+% \cs{l_@@_legacy_env_params_tl} and not at the start of the
+% environment (tagging/730)}
% \begin{macrocode}
- \tl_set:Nn \@itemlabel {#2}
- \tl_set:Nn \l_@@_legacy_env_params_tl {#3}
+ \tl_set:Nn \l_@@_legacy_env_params_tl
+ {
+ \tl_set:Nn \@itemlabel {#2}
+ #3
+ }
% \end{macrocode}
%
% \begin{macrocode}
@@ -1244,14 +1291,6 @@
%
%
%
-% \begin{variable}{\l_@@_env_params_tl}
-% Declare the variable for the parameter argument; \cs{@itemlabel}
-% is already declared in \LaTeXe{}.
-% \begin{macrocode}
-\tl_new:N \l_@@_env_params_tl
-% \end{macrocode}
-% \end{variable}
-%
%
% \begin{macro}{\legacylistsetupcode}
%
@@ -1267,10 +1306,14 @@
\dim_zero:N \itemindent
% \end{macrocode}
%
-% By default a \env{list} environment is not numbered:
+% By default a \env{list} environment is not numbered, but this
+% happens already in the block template.
+% \changes{v0.8v}{2024/10/11}{Set the defaults for \cs{@itemlabel},
+% \cs{@listctr} and \texttt{@nmbrlist} early in the block code
+% before the setup code gets executed (tagging/730)}
% \begin{macrocode}
- \tl_set:Nn \@listctr {}
- \legacy_if_set_false:n { @nmbrlist } % needed if lists are nested
+% \tl_set:Nn \@listctr {}
+% \legacy_if_set_false:n { @nmbrlist } % needed if lists are nested
% \end{macrocode}
% By default there is a simple definition for \cs{makelabel}. It can be
% overwritten in the second mandatory argument to the list
@@ -1342,14 +1385,14 @@
\@definecounter {#2}
\IfNoValueTF {#4}
{ % @ynthm
- \tl_gset:cx { the #2 }
+ \tl_gset:ce { the #2 }
{
\@thmcounter{#2}
}
}
{ % @xnthm
\@newctr{#1}[#4]
- \tl_gset:cx { the #2 }
+ \tl_gset:ce { the #2 }
{
\expandafter\noexpand\csname the#4\endcsname
\@thmcountersep
@@ -1528,7 +1571,7 @@
% \end{macrocode}
% We need to know later if we have nested blockenvs inside
% a flattened environment. Whenever we start a new blockenv we
-% increment \cs{\l_@@_flattened_level_int} if it is already
+% increment \cs{l__tag_block_flattened_level_int} if it is already
% different from zero. If it is zero we increment it if flattening
% is requested.
% Thus a value of \texttt{0} means no flattening requested so far
@@ -1537,14 +1580,14 @@
% is surrounded by a \texttt{text-unit} tag, while for any value above
% \texttt{1} we have to omit the \texttt{text-unit}.
% \begin{macrocode}
- \int_compare:nNnTF \l_@@_flattened_level_int > 0
+ \int_compare:nNnTF \l__tag_block_flattened_level_int > 0
{
- \int_incr:N \l_@@_flattened_level_int
+ \int_incr:N \l__tag_block_flattened_level_int
}
{
\bool_if:NT \l__tag_para_flattened_bool
{
- \int_incr:N \l_@@_flattened_level_int
+ \int_incr:N \l__tag_block_flattened_level_int
}
}
%
@@ -1582,6 +1625,23 @@
% \begin{macrocode}
\tag_if_active:T { \use:c { @@_recipe_ \l_@@_tagging_recipe_tl : } }
% \end{macrocode}
+% The default for \env{list} environments is that they have an
+% empty label and are not numbered (something that is then
+% overwritting by the setup of a specific list). We ensure
+% this here even for non-lists, because we need a defined state
+% that then can be overwritting by the legacy setup code for
+% the \env{list} environment in \cs{l_@@_setup_code_tl}.
+% This is needed in case lists are nested as they otherwise would
+% inherit outer values (and suddenly an \env{itemize} would start
+% incrementing an outer \env{enumerate} counter, etc.
+% \changes{v0.8v}{2024/10/11}{Set the defaults for \cs{@itemlabel},
+% \cs{@listctr} and \texttt{@nmbrlist} early in the block code
+% before the setup code gets executed (tagging/730)}
+% \begin{macrocode}
+ \tl_clear:N \@itemlabel
+ \tl_clear:N \@listctr
+ \legacy_if_set_false:n { @nmbrlist }
+% \end{macrocode}
% Then run the setup code if any is given in the instance.
% \begin{macrocode}
\l_@@_setup_code_tl
@@ -1640,11 +1700,15 @@
% \end{template}
%
%
-% \begin{macro}{\l_@@_flattened_level_int}
+% \begin{macro}{\l__tag_block_flattened_level_int}
% Count the levels of nested blockenvs starting with the first that
-% is \enquote{flattened}.
+% is \enquote{flattened}. The counter is defined in lttagging.dtx,
+% but until the next release 11/24 we set it up here too
% \begin{macrocode}
-\int_new:N \l_@@_flattened_level_int
+\int_if_exist:NF \l__tag_block_flattened_level_int
+ {
+ \int_new:N \l__tag_block_flattened_level_int
+ }
% \end{macrocode}
% \end{macro}
%
@@ -1684,15 +1748,19 @@
\legacy_if_gset_false:n { @inlabel }
}
% \end{macrocode}
-% In a pure ``displayblock'' scenario \texttt{@newlist} will be
-% always false and the code bypassed, but we may have an outer list
-% followed immediately by a displayblock (with the \cs{item} missing)
+% If we are ending a list environment and we have not seen any
+% \cs{item}, i.e., \texttt{@newlist} is still true, we raise an
+% error. In basic a ``displayblock'' scenario \texttt{@newlist} will
+% always be false, but if such an environment appears inside an outer
+% list then \cs{noitemerr} could still be triggered and that is undesirable
+% (as the missing item will be detected at the wrong point and again later,
+% during the outer list processing). We
+% therefore run it only if the current environment is a list.
+% \changes{v0.8q}{2024/09/03}{Raise a \cs{@noitemerr} if appropriate}
+% \begin{macrocode}
+ \@@_if_list:T { \legacy_if:nT { @newlist } { \@noitemerr } }
+% \end{macrocode}
% \begin{macrocode}
- \legacy_if:nT { @newlist }
- {
- \@noitemerr
- \legacy_if_gset_false:n { @newlist }
- }
\mode_if_horizontal:TF
{ \@@_skip_remove_last: \@@_skip_remove_last: \par }
{ \@inmatherr{\end{\@currenvir}} }
@@ -1702,6 +1770,13 @@
% \begin{macrocode}
\__kernel_displayblock_end:
% \end{macrocode}
+% Resetting the \texttt{@newlist} switch is also only done if the
+% current enviornment is a list and not unconditionally.
+% \changes{v0.8q}{2024/09/03}{Setting \texttt{@newlist} to false
+% moved after tagging code if in a list}
+% \begin{macrocode}
+ \@@_if_list:T { \legacy_if_gset_false:n { @newlist } }
+% \end{macrocode}
% What to do in terms of vertical spacing in different situations
% is still somewhat open to debate, right now this is more or less
% implementing what \LaTeXe{} list environment have been
@@ -1748,6 +1823,19 @@
% \end{macro}
%
%
+% \begin{macro}{\@@_if_list:T}
+% The following code may need some redesigning, as there is no good test for \enquote{is
+% this environment a \enquote{list} that has \cs{item}s}. For now
+% this here does the trick well enough.\fmi{revisit}
+% \changes{v0.8q}{2024/09/03}{Provide a test for: Am I in a list?}
+% \begin{macrocode}
+\cs_new:Npn \@@_if_list:T
+ { \tl_if_eq:NnT \l_@@_block_instance_tl {list} }
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
% \begin{macro}{\__kernel_displayblock_end:}
% The kernel hook for tagging at the end of the block.
% \begin{macrocode}
@@ -1773,9 +1861,13 @@
% and should not inherit the setting from the outer environment.
% \begin{macrocode}
\socket_new_plug:nnn{tagsupport/block-endpe}{on}
- { \legacy_if_gset_true:n { @endpe } }
+% \end{macrocode}
+% We can't use \cs{legacy_if_gset_true:n} because this is now doing
+% more than setting the legacy switch
+% \begin{macrocode}
+ { \@endpetrue }
\socket_new_plug:nnn{tagsupport/block-endpe}{off}
- { \legacy_if_gset_false:n { @endpe } }
+ { \@endpefalse }
% \end{macrocode}
%
% \begin{macrocode}
@@ -1802,7 +1894,7 @@
fixed-word-spaces = \l__par_fixed_word_spaces_bool , % name??
final-hyphen-demerits = \finalhyphendemerits ,
cr-cmd = \\ ,
- para-class = \l_tag_para_attr_class_tl ,
+ para-class = \l__tag_para_attr_class_tl ,
}
{
\tl_if_empty:nF {#1} { \SetTemplateKeys{para}{std}{#1} }
@@ -1823,6 +1915,7 @@
%
% \begin{template}{block display}
%
+% \changes{v0.8s}{2024/10/03}{Offer item-skip key also on block templates}
% \begin{macrocode}
\DeclareTemplateCode{block}{display}{1}
{
@@ -1832,6 +1925,7 @@
par-skip = \parsep ,
end-skip = \l_@@_botsep_skip ,
end-par-skip = \l_@@_parbotsep_skip ,
+ item-skip = \itemsep ,
beginpenalty = \@beginparpenalty ,
endpenalty = \@endparpenalty ,
rightmargin = \rightmargin ,
@@ -1940,7 +2034,7 @@
% \cs{parskip} and some other housekeeping, unless this block is inside a list and the list
% \cs{item} has not yet placed. In that case the vertical
% space and penalty us suppressed. This
-% is controled through the legacy switches \texttt{@noparitem},
+% is controlled through the legacy switches \texttt{@noparitem},
% \texttt{minipage}, and \texttt{@nobreak}.
% \begin{macrocode}
\legacy_if:nTF { @noparitem }
@@ -1987,7 +2081,6 @@
% \end{template}
%
%
-%
% \begin{macro}{\__kernel_displayblock_begin:,
% \__kernel_displayblock_beginpar_hmode:w,
% \__kernel_displayblock_beginpar_vmode:}
@@ -2032,6 +2125,40 @@
%
%
%
+% \begin{macro}{\@@_evaluate_saved_user_keys:nn}
+% Keys set on individual list environments may be intended to alter
+% the behavior of the template instance that defines the \cs{item}
+% command. If meant to alter only a single \cs{item} command one
+% would specify them in the optional argument of the \cs{item}, but
+% if they should alter all items the right place would be the list
+% environment. For this reason we need to store the values and then
+% set them inside the \cs{item} template code using
+% \cs{SetTemplateKeys} in the appropriate context (template type
+% and template name). This is done in
+% \cs{@@_evaluate_saved_user_keys:nn}. The context is provided in
+% the two arguments (because different list environments may use
+% different \cs{item} instances based on different templates. By
+% default the command does
+% nothing because most environments do not have user key settings.
+% \changes{v0.8s}{2024/10/03}{Pass user keys on list to \cs{item} for
+% evaluation}
+% \begin{macrocode}
+\cs_new_eq:NN \@@_evaluate_saved_user_keys:nn \use_none:nn
+% \end{macrocode}
+% Maybe something like this should become a public function, but
+% for now this is a one-off for the \cs{item} command and therefore
+% coded inline and internal to the block code.
+% \begin{macrocode}
+%\cs_new:Npn \@@_save_user_keys:n #1 {
+% \tl_if_empty:nTF {#1}
+% { \cs_set_eq:NN \@@_evaluate_saved_user_keys:nn \use_none:nn }
+% {
+% \cs_set:Npe \@@_evaluate_saved_user_keys:nn ##1##2
+% { \SetTemplateKeys{##1}{##2}{ \exp_not:n{#1} } }
+% }
+%}
+% \end{macrocode}
+% \end{macro}
%
%
% \begin{template}{list std}
@@ -2057,36 +2184,48 @@
{
\@@_debug_typeout:n{template:list:std}
%
- \tl_if_empty:nF {#1} { \SetTemplateKeys{list}{std}{#1} }
+% \end{macrocode}
+% We start by looking at the user supplied keys in \texttt{\#1}. If
+% there aren't any we reset \cs{@@_evaluate_saved_user_keys:nn} to
+% do nothing. Otherwise we evaluate and set the keys in the contect
+% of the current list template. In addition we prepare
+% \cs{@@_evaluate_saved_user_keys:nn} for execution in the
+% template for \cs{item}.
+% \changes{v0.8s}{2024/10/03}{Prepare \cs{@@_evaluate_saved_user_keys:nn}
+% for use in \cs{item}}
+% \begin{macrocode}
+ \tl_if_empty:nTF {#1}
+ { \cs_set_eq:NN \@@_evaluate_saved_user_keys:nn \use_none:nn }
+ {
+ \SetTemplateKeys{list}{std}{#1}
+ \cs_set:Npe \@@_evaluate_saved_user_keys:nn ##1##2
+ { \SetTemplateKeys{##1}{##2}{ \exp_not:n{#1} } }
+ }
% \end{macrocode}
% Has this list a counter name defined in the instance?
% \begin{macrocode}
\tl_if_empty:NTF \l_@@_counter_tl
{
% \end{macrocode}
-% If not we check if \cs{@listctr} has a non-empty value to be used
-% for the list counter.
-%
-% We better test for blank not empty in case somebody had defined
-% \cs{@listctr} using \cs{renewcommand} or \cs{cs_set:Npn}.
+% If not we check if \cs{@nmbrlist} is true which may be the case
+% in legacy environments that used \cs{usecounter} in the argument
+% to the \env{list} environment.
+% \changes{v0.8v}{2024/10/11}{Correct logic for setting up the list
+% counter (tagging/730)}
% \begin{macrocode}
- \tl_if_blank:oF \@listctr
- {
+ \legacy_if:nT { @nmbrlist }
+ {
% \end{macrocode}
-% In that case \texttt{@nmbrlist} should have been set too, for
-% example, through \cs{usecounter}, so we do not set it
-% explicitly. However, we check if we should resume a previous list.
+% In that case we only check if we should resume a previous list
+% (\cs{@listctr} should be set in that case through the legacy
+% method as well so we should be able to use it).
% \begin{macrocode}
\bool_if:NF \l_@@_resume_bool
{
\int_gset:cn{ c@ \@listctr }
{ \l_@@_counter_start_int - 1 }
}
- }
-% \end{macrocode}
-% If \cs{@listctr} is not set then we have definitely an unnumbered list.
-% \begin{macrocode}
- { \@nmbrlistfalse }
+ }
}
% \end{macrocode}
% If a counter is set in the list instance we use that
@@ -2116,12 +2255,28 @@
\tl_set_eq:NN \@itemlabel \l_@@_item_label_tl
}
% \end{macrocode}
-% finally, we signal that we are at the start of a new list (which
-% effects how the first \cs{item} is handled and how \cs{par}
+% Finally, we signal that we are at the start of a new list (which
+% affects how the first \cs{item} is handled and how \cs{par}
% commands are interpreted.
% \begin{macrocode}
\legacy_if_gset_true:n { @newlist }
% \end{macrocode}
+% If we encounter horizontal material before the first \cs{item} we
+% do want a \cs{@noitemerr} straight away, because afterwards we
+% end up with tagging structure faults whose cause is the
+% missing \cs{item}. So we setup up \cs{@@_item_everypar:} to test
+% for this; when the first \cs{item} is encountered this will get
+% reset. This is only relevant for vertical lists, when dealing with
+% inline lists one would need to test for something else to
+% identify that there is horizontal material between the start of the list and
+% the first \cs{item} (maybe some \cs{spacefactor} trick could be
+% used then, or the material is boxed first and the width is
+% inspected as suggested by Joseph).\fmi{Think about a better
+% implementation at some point.}
+% \changes{v0.8q}{2024/09/02}{}
+% \begin{macrocode}
+ \cs_set_eq:NN \@@_item_everypar: \@@_item_everypar_first:
+% \end{macrocode}
%
% \begin{macrocode}
\@@_debug_typeout:n{template:list:std~end}
@@ -2210,8 +2365,19 @@
% was given.
% \begin{macrocode}
\tl_set_eq:NN \l_@@_label_given_tl \c_novalue_tl
+% \end{macrocode}
+% First we evaluate and set any keys specified on the list
+% environment by calling
+% \cs{@@_evaluate_saved_user_keys:nn}. Then we do the same
+% with all keys specified on this \cs{item} command (which may
+% overwrite one or the other setting just made).
+% \changes{v0.8s}{2024/10/03}{Use \cs{@@_evaluate_saved_user_keys:nn}
+% to make use of user keys on the list level}
+% \begin{macrocode}
+ \@@_evaluate_saved_user_keys:nn {item}{std}
\tl_if_empty:nF{#1}{ \SetTemplateKeys{item}{std}{#1} }
% \end{macrocode}
+%
% If no optional argument was given then \cs{l_@@_label_given_tl}
% is still equal to \cs{c_novalue_tl} and so we can distinuish
% that from \verb=\item[]=.
@@ -2260,6 +2426,9 @@
\exp_after:wN \use_ii:nn \l_@@_item_align_tl
}
}
+% \end{macrocode}
+% Add another box level to the label box:
+% \begin{macrocode}
\hbox_set:Nn \l_@@_one_label_box
{ \box_use_drop:N \l_@@_one_label_box }
}
@@ -2360,16 +2529,16 @@
%
%
%
-% \begin{macro}{\@@_item_everypar:, \@@_item_everypar_std:}
+% \begin{macro}{\@@_item_everypar:, \@@_item_everypar_std:, \@@_item_everypar_first:}
% The \cs{@@_item_everypar:} command is executed as part of \hook{para/begin}
% but most of the time does nothing, i.e., it has the following
-% default definition.
+% default definition outside of lists (and most of the time within lists).
% \begin{macrocode}
\cs_new_eq:NN \@@_item_everypar: \prg_do_nothing:
% \end{macrocode}
-%
+%
% \begin{macrocode}
-\AddToHook{para/begin}[lists]{\@@_item_everypar:}
+\AddToHook{para/begin}[items]{\@@_item_everypar:}
% \end{macrocode}
%
% Note that we have to make sure that the above code is executed
@@ -2377,9 +2546,9 @@
% \texttt{@inlabel} to make a decision.
%
% By the end of the day both should probably move into the kernel
-% hook instead!
+% hook instead or, better, into sockets.
% \begin{macrocode}
-\DeclareHookRule{para/begin}{lists}{after}{tagpdf}
+\DeclareHookRule{para/begin}{items}{after}{tagpdf}
% \end{macrocode}
%
%
@@ -2431,6 +2600,16 @@
}
% \end{macrocode}
%
+% This is the definition of \cs{@@_item_everypar:} before the first
+% \cs{item} is encountered.
+% \changes{v0.8q}{2024/09/02}{Call \cs{@noitemerr} if hmode is
+% started before the first item}
+% \begin{macrocode}
+\cs_new:Npn \@@_item_everypar_first: {
+ \legacy_if:nT { @newlist } { \@noitemerr }
+}
+% \end{macrocode}
+%
% \end{macro}
%
%
@@ -2476,7 +2655,7 @@
%
% \begin{macro}{\item}
% Here we already have all the building blocks. Complain in math
-% mode. Distingusih between first item (do necessary tagging) and
+% mode. Distinguish between first item (do necessary tagging) and
% later items \cs{@@_inter_item:} to
% cleanly close what's before, then call \cs{@@_item_instance:n} (which
% calls \cs{UseInstance}\{item\}\marg{instance}) to prepare the
@@ -2488,14 +2667,25 @@
{
\@inmatherr \item
% \end{macrocode}
-% TODO: Test for being outside of a list needs updating!
+% TODO: Check if test for being outside of a list is sensible
% \begin{macrocode}
- \tl_if_empty:oTF \@@_item_instance:n %%FMi?
- { \msg_error:nnn { @@ } { item-in-nonlist } { \item[{#1}] } }
+ \cs_if_free:NTF \@@_item_instance:n
+ {
+ \@latex@error{Lonely~\string\item--perhaps~a~missing~
+ list~environment}\@ehc
+ }
{
\legacy_if:nTF { @newlist }
- { \__kernel_list_item_begin: }
- { \@@_inter_item: }
+ {
+ \__kernel_list_item_begin:
+% \end{macrocode}
+% The first item of a list also has to change the \texttt{@newlist} switch.
+% \changes{v0.8q}{2024/09/02}{Set \texttt{@newlist} to false after
+% the first \cs{item}}
+% \begin{macrocode}
+ \legacy_if_gset_false:n { @newlist }
+ }
+ { \@@_inter_item: }
% \end{macrocode}
% To avoid unnecessary key/val processing we make a quick check if
% there was an optional argument.
@@ -2630,7 +2820,7 @@
%
% \item Then open an new (inner) structure (by default
% \texttt{Figure} but typically the one specified on the instance).
-% \item At the end of the block close the the inner structure
+% \item At the end of the block close the inner structure
% (\texttt{Figure} or explicit one)
% but leave the \texttt{text-unit} open to be either continued or closed due to a
% following \cs{par}.
@@ -2704,7 +2894,7 @@
\socket_assign_plug:nn{tagsupport/block-endpe}{on}
% \end{macrocode}
%
-% Handle the tag name and attribute classess using the key values
+% Handle the tag name and attribute classes using the key values
% from the current list instance.
% \begin{macrocode}
\tl_if_empty:NTF \l_@@_tag_name_tl
@@ -2947,6 +3137,7 @@
block-instance = verbatimblock ,
inner-instance = ,
final-code = \legacyverbatimsetup ,
+ para-instance = justify
}
% \end{macrocode}
% \end{instance}
@@ -3126,7 +3317,7 @@
% block quoteblock-4,
% block quoteblock-5,
% block quoteblock-6 }
-% Default layout is to indent equaly from both side.
+% Default layout is to indent equally from both sides.
% \begin{macrocode}
\DeclareInstance{block}{quoteblock-1}{display}
{ rightmargin = \KeyValue{leftmargin} }
@@ -3290,6 +3481,7 @@
\DeclareInstance{item}{description}{std}
{
label-format = \normalfont\bfseries #1 ,
+ label-align = left
}
% \end{macrocode}
% \end{instance}
@@ -3303,10 +3495,10 @@
{
\tagpdfsetup
{
- newattribute = {justify} {/O /Layout /TextAlign/Justify},
- newattribute = {center} {/O /Layout /TextAlign/Center},
- newattribute = {raggedright}{/O /Layout /TextAlign/Start},
- newattribute = {raggedleft} {/O /Layout /TextAlign/End},
+ role/new-attribute = {justify} {/O /Layout /TextAlign/Justify},
+ role/new-attribute = {center} {/O /Layout /TextAlign/Center},
+ role/new-attribute = {raggedright}{/O /Layout /TextAlign/Start},
+ role/new-attribute = {raggedleft} {/O /Layout /TextAlign/End},
}
}
% \end{macrocode}
@@ -3389,9 +3581,7 @@
%
% In this section we provide code to the various kernel hooks to support
% the tagging of the different displayblock environments.
-%
-%
-%
+%
% All of the following definitions should only be made if tagging
% is active!
% \begin{macrocode}
@@ -3422,10 +3612,15 @@
% then have to avoid adding another \texttt{text-unit}.
% \begin{macrocode}
{
- \int_compare:nNnT \l_@@_flattened_level_int < 2
+ \int_compare:nNnT \l__tag_block_flattened_level_int < 2
{
- \int_gincr:N \g__tag_para_main_begin_int
- \tagstructbegin{tag=\l__tag_para_main_tag_tl}
+ \__tag_gincr_para_main_begin_int:
+ \tag_struct_begin:n
+ {
+ tag=\l__tag_para_main_tag_tl,
+ attribute-class=\l__tag_para_main_attr_class_tl,
+ }
+ \__tag_para_main_store_struct:
}
}
}
@@ -3445,7 +3640,7 @@
\cs_set:Npn \@@_beginpar_hmode:N #1
{
\tag_mc_end:
- \int_gincr:N \g__tag_para_end_int
+ \__tag_gincr_para_end_int:
\@@_debug_typeout:n{increment~ /P \on@line }
\bool_if:NT \l__tag_para_show_bool
{ \tag_mc_begin:n{artifact}
@@ -3492,7 +3687,7 @@
{
\@@_debug_typeout:n{Structure-end~
\l__tag_para_main_tag_tl\space after~ displayblock \on@line }
- \int_gincr:N \g__tag_para_main_end_int
+ \__tag_gincr_para_main_end_int:
\tag_struct_end: %text-unit
}
}
@@ -3551,16 +3746,21 @@
{
\bool_if:NF \l__tag_para_flattened_bool
{
- \int_gincr:N \g__tag_para_main_begin_int
- \tag_struct_begin:n{tag=\l__tag_para_main_tag_tl}
+ \__tag_gincr_para_main_begin_int:
+ \tag_struct_begin:n
+ {
+ tag=\l__tag_para_main_tag_tl,
+ attribute-class=\l__tag_para_main_attr_class_tl,
+ }
+ \__tag_para_main_store_struct:
}
}
- \int_gincr:N \g__tag_para_begin_int
+ \__tag_gincr_para_begin_int:
\@@_debug_typeout:n{increment~ P \on@line }
\tag_struct_begin:n
{
tag=\l__tag_para_tag_tl
- ,attribute-class=\l_tag_para_attr_class_tl
+ ,attribute-class=\l__tag_para_attr_class_tl
}
\__tag_check_para_begin_show:nn {green}{#1}
\tag_mc_begin:n {}
@@ -3572,15 +3772,20 @@
\cs_new_protected:Npn \@@_start_para_structure_unconditionally:n #1 {
\bool_if:NF \l__tag_para_flattened_bool
{
- \int_gincr:N \g__tag_para_main_begin_int
- \tag_struct_begin:n{tag=\l__tag_para_main_tag_tl}
+ \__tag_gincr_para_main_begin_int:
+ \tag_struct_begin:n
+ {
+ tag=\l__tag_para_main_tag_tl,
+ attribute-class=\l__tag_para_main_attr_class_tl,
+ }
+ \__tag_para_main_store_struct:
}
- \int_gincr:N \g__tag_para_begin_int
+ \__tag_gincr_para_begin_int:
\@@_debug_typeout:n{increment~ P \on@line }
\tag_struct_begin:n
{
tag=\l__tag_para_tag_tl
- ,attribute-class=\l_tag_para_attr_class_tl
+ ,attribute-class=\l__tag_para_attr_class_tl
}
\__tag_check_para_begin_show:nn {green}{#1}
\tag_mc_begin:n {}
@@ -3594,14 +3799,14 @@
{
\bool_if:NT \l__tag_para_bool
{
- \int_gincr:N \g__tag_para_end_int
+ \__tag_gincr_para_end_int:
\@@_debug_typeout:n{increment~ /P \on@line }
\tag_mc_end:
\__tag_check_para_end_show:nn {red}{}
\tag_struct_end:
\bool_if:NF \l__tag_para_flattened_bool
{
- \int_gincr:N \g__tag_para_main_end_int
+ \__tag_gincr_para_main_end_int:
\tag_struct_end:
}
}
@@ -3657,7 +3862,7 @@
\DeclareRobustCommand*\begin[1]{%
\UseHook{env/#1/before}%
\@ifundefined{#1}%
- {\def\reserved@a{\@latex@error{Environment #1 undefined}\@eha}}%
+ {\def\reserved@a{\@latex@error{Environment~#1~undefined}\@eha}}%
{\def\reserved@a{\def\@currenvir{#1}%
\edef\@currenvline{\on@line}%
\@execute@begin@hook{#1}%
@@ -3680,7 +3885,7 @@
{
\bool_if:NF \l__tag_para_flattened_bool
{
- \int_gincr:N \g__tag_para_main_end_int
+ \__tag_gincr_para_main_end_int:
\tag_struct_end:
}
\@endpefalse
@@ -3722,7 +3927,7 @@
\@@_debug_typeout:n{block-end \on@line}
\legacy_if:nT { @endpe }
{
- \int_gincr:N \g__tag_para_main_end_int
+ \__tag_gincr_para_main_end_int:
\@@_debug_typeout:n{close~ /text-unit \on@line}
\tagstructend
}
@@ -3752,11 +3957,17 @@
{
\tagpdfsetup
{
+ role/new-attribute = {itemize}{/O /List /ListNumbering/Unordered},
+ role/new-attribute = {enumerate}{/O /List /ListNumbering/Ordered},
+ role/new-attribute = {description}{/O /List /ListNumbering/Description},
+% \end{macrocode}
+% Initially, we had \texttt{/None} for the basic \env{list}
+% environment, but that is not allowed in PDF/UA-2 if the list
+% contains any Lbl tags. So now we default to
+% \texttt{Unordered}.
+% \begin{macrocode}
% default if unknown
- newattribute = {list}{/O /List /ListNumbering/None},
- newattribute = {itemize}{/O /List /ListNumbering/Unordered},
- newattribute = {enumerate}{/O /List /ListNumbering/Ordered},
- newattribute = {description}{/O /List /ListNumbering/Description},
+ role/new-attribute = {list}{/O /List /ListNumbering/Unordered},
}
}
% \end{macrocode}
@@ -3792,7 +4003,7 @@
\cs_set:Npn \__kernel_list_label_begin: {
%
% FMi: this needs a different logic to decide when to make the label
-% an artifact (after cleaning up the the \item code ), therefore
+% an artifact (after cleaning up the \item code ), therefore
% disabled for now
% \tl_if_empty:oTF \@itemlabel
% {
@@ -3835,7 +4046,7 @@
\cs_set:Npn \@@_list_item_end: {
\legacy_if:nT { @endpe }
{
- \int_gincr:N \g__tag_para_main_end_int
+ \__tag_gincr_para_main_end_int:
\tagstructend % text-unit
% \@@_debug_typeout:n{Structure-end~ P~ at~ item-end \on@line }
}
@@ -3850,15 +4061,37 @@
% Finally, at the list end we have to close the open
% \texttt{LBody}, \texttt{LI}, \texttt{L}, and possibly a
% \struct{text} if the last item ends with a list.
+% However, if the user forgot to add an \cs{item} then there will be no
+% \texttt{LI} and \texttt{LBody} open, so we check for the status
+% of \texttt{@newlist}. The corresponding no-item error was
+% generated earlier outside the tagging code.
+%
+% One could argue that it doesn't matter if the tagging is wrong
+% after a \cs{@noitemerr} was issued. However, there is one case
+% where it isn't an error: In the \texttt{thebibliography}
+% environment (which is internally a list) it is often the case
+% that documents start out with an empty environment, not
+% containing any \cs{bibitem}s. For that reason \cs{@noitemerr} is
+% redefined inside that environment to only produce a warning;
+% hence we have to produce correct tag structures in that case.
+% \changes{v0.8q}{2024/09/02}{Do not close LI and LBody if they
+% never were opened.}
% \begin{macrocode}
\cs_set:Npn \@@_list_end: {
- \legacy_if:nT { @endpe }
+% \end{macrocode}
+% If \texttt{@newlist} is true (i.e., when we have an error or warning
+% situation) there is not much to close.
+% \begin{macrocode}
+ \legacy_if:nF { @newlist }
{
- \int_gincr:N \g__tag_para_main_end_int
- \tagstructend % text-unit
- \@@_debug_typeout:n{Structure-end~ P~ at~ list-end \on@line }
+ \legacy_if:nT { @endpe }
+ {
+ \__tag_gincr_para_main_end_int:
+ \tagstructend % text-unit
+ \@@_debug_typeout:n{Structure-end~ P~ at~ list-end \on@line }
+ }
+ \tagstructend\tagstructend % end LBody, LI
}
- \tagstructend\tagstructend % end LBody, LI
\tagstructend % end L
}
% \end{macrocode}
diff --git a/macros/latex/required/latex-lab/latex-lab-block.pdf b/macros/latex/required/latex-lab/latex-lab-block.pdf
index ad89aede81..4b0855a05d 100644
--- a/macros/latex/required/latex-lab/latex-lab-block.pdf
+++ b/macros/latex/required/latex-lab/latex-lab-block.pdf
Binary files differ
diff --git a/macros/latex/required/latex-lab/latex-lab-firstaid.dtx b/macros/latex/required/latex-lab/latex-lab-firstaid.dtx
index e2ee78b2ff..118baccd79 100644
--- a/macros/latex/required/latex-lab/latex-lab-firstaid.dtx
+++ b/macros/latex/required/latex-lab/latex-lab-firstaid.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-%% File: latex-lab-firstaid.dtx (C) Copyright 2023 LaTeX Project
+%% File: latex-lab-firstaid.dtx (C) Copyright 2023-2024 LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -16,8 +16,8 @@
%
% for those people who are interested or want to report an issue.
%
-\def\ltlabfirstaiddate{2023-07-20}
-\def\ltlabfirstaidversion{0.85a}
+\def\ltlabfirstaiddate{2024-10-16}
+\def\ltlabfirstaidversion{0.85h}
%<*driver>
\documentclass{l3doc}
\EnableCrossrefs
@@ -53,8 +53,11 @@
%
% Similar to the main firstaid package the goal is to remove the
% patches once the packages have been updated.
-
+%
+% \changes{v0.85g}{2024/10/04}{Removed firstaid for blindtext. No longer needed with new doenpe-code.}
+% \changes{v0.85g}{2024/10/04}{Added firstaid for fancyvrb.}
% \section{Implementation}
+%
% \begin{macrocode}
%<*package>
%<@@=tag>
@@ -64,51 +67,326 @@
\ltlabfirstaiddate\space v\ltlabfirstaiddate\space
Temporary patches to external packages needed for the tagging project]
% \end{macrocode}
+% \begin{macro}{\FirstAidNeededT}
+% This is a very simple help to ensure that we only apply first aid
+% to an unmodified package or class. It only works in the case the
+% file has already been loaded and the csname \cs{ver@\#1.\#2} got
+% defined (holding the current date, version, and short description
+% info). We then compare its content to a frozen string and make
+% the modification \verb=#3= only if both agree. If they differ we
+% assume that the package/class in question got updated by its
+% maintainer.
+% \begin{macrocode}
+\ExplSyntaxOn
+\providecommand\FirstAidNeededT[3]{
+ \exp_args:Ncx\str_if_eq:onF{ver@#1.#2}{#3}
+ { \typeout{==>~ First~ Aid~ for~ #1.#2~ no~ longer~ applied!^^J
+ \@spaces Expected:^^J
+ \@spaces\@spaces #3^^J
+ \@spaces but~ found:^^J
+ \@spaces\@spaces \use:c{ver@#1.#2}^^J
+ \@spaces so~ I'm~ assuming~ it~ got~ fixed.
+ } }
+ \exp_args:Ncx\str_if_eq:onT{ver@#1.#2}{#3}
+}
+% \end{macrocode}
+% \end{macro}
-% \subsection{blindtext}
-% The blindtext package generates lists with nested \cs{loop} command.
-% The inner loop introduces a group around the list which error when lists are tagged
-% as \cs{@doendpe} is lost.
-% \begin{macrocode}
-\AddToHook{file/blindtext.sty/after}[latex-lab-firstaid]{%
- \FirstAidNeededT{blindtext}{sty}{\blindfiledate\space\blindfileversion\space%
- blindtext-Package}%
+% \subsection{ams classes}
+% The amsart, amsbook and amsproc classes do not use \cs{@author} to store the author list
+% but a command \cs{authors}. To be able to nevertheless use the authors in the
+% xmp-metadata we map \cs{@author} to this new command.
+%
+% \begin{macrocode}
+\AddToHook{class/amsart/after}
+ {\def\@author{\authors}}
+\AddToHook{class/amsbook/after}
+ {\def\@author{\authors}}
+\AddToHook{class/amsproc/after}
+ {\def\@author{\authors}}
+% \end{macrocode}
+%
+% \subsection{ams classes and amsthm}
+% The amsart, amsbook and amsproc classes redefine the theorem code
+% and this breaks the tagging added by the block code. The following
+% reenables tagging. It does \emph{not} give a completly identical output
+% (similar to the new theorem code,
+% see \url{https://github.com/latex3/tagging-project/issues/715}).
+% The code also does not try to use sockets yet, as the theorem definitions
+% in the block code don't do that yet either.
+%
+% \begin{macrocode}
+\AddToHook{class/amsart/after}[latex-lab-testphase-firstaid/amsthm]
+ {\tag_if_active:T{\@@_firstaid_amsthm:}}
+\AddToHook{class/amsbook/after}[latex-lab-testphase-firstaid/amsthm]
+ {\tag_if_active:T{\@@_firstaid_amsthm:}}
+\AddToHook{class/amsproc/after}[latex-lab-testphase-firstaid/amsthm]
+ {\tag_if_active:T{\@@_firstaid_amsthm:}}
+\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:
+ {
+% \end{macrocode}
+% \cs{@endtheorem} must use the endblock code
+% \begin{macrocode}
+ \def\@endtheorem{\endblockenv}
+% \end{macrocode}
+% In \cs{@thm} we have to remove the \cs{trivlist}
+% \begin{macrocode}
+ \RenewDocumentCommand\@thm{mmmO{}}{%
+ \ifhmode\unskip\unskip\par\fi
+ \normalfont
+ \let\thmheadnl\relax
+ \let\thm@swap\@gobble
+ \thm@notefont{\fontseries\mddefault\upshape}%
+ \thm@headpunct{.}% add period after heading
+ \thm@headsep 5\p@ plus\p@ minus\p@\relax
+ \thm@space@setup
+ ##1% style overrides
+ \@topsep \thm@preskip % used by thm head
+ \@topsepadd \thm@postskip % used by \@endparenv
+% \end{macrocode}
+% We store the counter name so that the anchor can make use of it.
+% \begin{macrocode}
+ \tl_set:Nn \l__block_thm_current_counter_tl{##2}
+ \tl_if_empty:nTF{##2}
+ {
+ \@begintheorem{##3}{}[##4]
+ }
+ {
+ \@kernel@refstepcounter{##2}
+ \@begintheorem{##3}{\csname the##2\endcsname}[##4]
+ }
+ }
+% \end{macrocode}
+% \cs{@begintheorem} has a larger number of changes
+% \begin{macrocode}
+ \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}{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. 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}
+ \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
+ \@ifempty{##1}
+ {\let\thmname\@gobble}
+% \end{macrocode}
+% we insert the MC and the Lbl structure into \cs{thmname},
+% \cs{thmnumber} and \cs{thmnote}. This will also work
+% with new theorem style as long as they use these command.
+% \begin{macrocode}
+ {\def\thmname####1{\tag_mc_begin:n {}####1\tag_mc_end:}}%
+ \@ifempty{##2}
+ {\let\thmnumber\@gobble}
+ {\def\thmnumber####1
+ {\tag_struct_begin:n{tag=Lbl}\tag_mc_begin:n {}
+ ####1
+ \tag_mc_end:\tag_struct_end:}}%
+ \@ifempty{##3}
+ {\let\thmnote\@gobble}
+ {\def\thmnote####1{\tag_mc_begin:n{}####1\tag_mc_end:}}%
+ \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:
+% \end{macrocode}
+% Now we restart para tagging and start a paragraph. The socket
+% is currently defined in tagpdf, so the code should only
+% be used if tagging is active!
+% \begin{macrocode}
+ \tagpdfparaOn
+ \UseTaggingSocket{para/begin} %
+ \ignorespaces}
+% \end{macrocode}
+% This redefines the standard styles for the theorem heads.
+% \cs{thm@headpunct} has been moved into the head code
+% to make tagging more easier.
+% \begin{macrocode}
+ \def\thmhead@plain##1##2##3{%
+ \thmname{##1}
+ \thmnumber{
+ \@ifnotempty{##1}{~}\@upn{##2}
+ }%
+ \thmnote{\pdffakespace\space{\the\thm@notefont(##3)}}
+ }
+ \let\thmhead\thmhead@plain
+ \def\swappedhead##1##2##3{%
+ \thmnumber{##2}
+ \thmname{\@ifnotempty{##2}{\nobreakspace}##1}
+ \thmnote{\pdffakespace\space{\the\thm@notefont(##3)}}
+ }
+ \let\swappedhead@plain=\swappedhead
+% \end{macrocode}
+% At last some adjustments for the proof environment.
+% The qed symbols use a drawn box by default. We add an actualtext.
+% \begin{macrocode}
+ \renewcommand{\openbox}{\leavevmode
+ \hbox to.77778em{\pdf_bdc:nn{Span}{/ActualText<FEFF220E>}%
+ \pdffakespace\hfil\vrule
+ \vbox to.675em{\hrule width.6em\vfil\hrule}%
+ \vrule\hfil\pdf_emc:}}
+% \end{macrocode}
+% And redefine proof to no longer use a trivlist.
+% \begin{macrocode}
+ \renewenvironment{proof}[1][\proofname]{\par
+ \pushQED{\qed}%
+ \UseInstance{blockenv}{theorem}{beginsep=6\p@\@plus6\p@}
+ \normalfont
+ \tagpdfparaOff
+ \AddToHookNext{para/begin}
+ {\tag_struct_begin:n{tag=Caption}
+ \tag_mc_begin:n{}%
+ \textit{##1\@addpunct{.}}%
+ \tag_mc_end:
+ \tag_struct_end:
+ \tagpdfparaOn
+ \UseTaggingSocket{para/begin}
+ \pdffakespace\hspace{\labelsep}}
+ \ignorespaces
+ }{%
+ \popQED\endblockenv\par
+ }
+ }
+\ExplSyntaxOff
+% \end{macrocode}
+%
+% \subsection{verse}
+%
+% The \pkg{verse} package has its own definition of the
+% \env{verse} environment, which would tag correctly, except that
+% it is overwritten by the block code in the hook
+% \texttt{begindocument/before}. So the simplest way to make
+% tagging work is to reinstall the package version afterwards,
+% which is what we are doing here.
+% \begin{macrocode}
+\AddToHook{package/verse/after}[latex-lab-firstaid]{%
+ \FirstAidNeededT{verse}{sty}{2014/05/10 v2.4b verse typesetting}%
{%
- \renewcommand{\blind@items}{%
- \setcounter{blind@listcount}{1}%
- \loop
- \ifblind@optional
- \ifblind@long
- \item[\blindtext@countitem] \blindtext@text
- \else
- \item[\blindtext@count] \blindtext@item
- \fi
- \else % \blind@optionalfalse
- \ifblind@long
- \item \blindtext@text
- \else
- \item \blindtext@countitem
- \fi
- \fi % \ifblind@optional
- {%
- \loop
- \ifnum\value{blindlistlevel}>\value{blindlist@level}%
- \stepcounter{blind@levelcount}%
- \blind@list[\value{blindlist}]\relax
- \addtocounter{blind@levelcount}{-1}%
- \setcounter{blind@listcount}{1}%
- \repeat
- \expandafter}\if@endpe\@doendpe\fi % <----------changed
- \ifnum\value{blind@listcount}<\value{blindlist}%
- \stepcounter{blind@listcount}%
- \repeat
- }
+ \AtBeginDocument{%
+ \renewenvironment{verse}[1][\linewidth]{%
+ \stepcounter{verse@envctr}%
+ \setcounter{poemline}{0}\refstepcounter{poemline}%
+ \setcounter{vslineno}{1}%
+ \let\\=\@vscentercr
+ \list{}{\itemsep \z@
+ \itemindent -\vindent
+ \listparindent\itemindent
+ \parsep \stanzaskip
+ \ifdim #1 < \linewidth
+ \rightmargin \z@
+ \setlength{\leftmargin}{\linewidth}%
+ \addtolength{\leftmargin}{-#1}%
+ \addtolength{\leftmargin}{-0.5\leftmargin}%
+ \else
+ \rightmargin \leftmargin
+ \fi
+ \addtolength{\leftmargin}{\vindent}}%
+ \item[]%
+ }%
+ {\endlist}%
+ }%
}%
- }
+}
% \end{macrocode}
+% Of course, this means that the
+% optional argument of the environment then only accepts a length
+% value and not any more a key value list for altering the
+% environment settings.
+%
+% A more elabroate version could be something like this that allows
+% key/val and legacy interface. Or one could extend the list
+% template to support a \texttt{list-width} key.
+%\begin{verbatim}
+% \ExplSyntaxOn
+% \cs_new_protected:Npn \ExtractAndDropKey #1#2#3#4#5 {
+% \tl_set_eq:NN #4 \c_novalue_tl % or empty?
+% \keys_define:nn { #1 } { #2 .code:n = \tl_set:Nn #4{##1} }
+% \keys_set_known:nnN { #1 } { #3 } #5
+% }
+% \ExplSyntaxOff
+%
+% % Change the env definition for verse matching verse.sty
+% % This keeps the verse.sty interface as it is and only adjusts the
+% % main environment to use the basic list env with the verse.sty
+% % specific settings.
+% \makeatletter
+%
+% \AddToHook{package/verse/after}{%
+% \AtBeginDocument{%
+% \RenewDocumentEnvironment{verse}{={verse-width}!O{\linewidth}}%
+% {%
+% \stepcounter{verse@envctr}%
+% \setcounter{poemline}{0}\refstepcounter{poemline}%
+% \setcounter{vslineno}{1}%
+% \let\\=\@vscentercr
+% %
+% \ExtractAndDropKey{verse}{verse-width}{#1}\@vswidth\@vsremainingkvlist
+% % If other keys have been specified but not verse-width we have no
+% % default for \@vswidth and need to set it again
+% \ExpandArgs{o}\IfNoValueT \@vswidth
+% {\def\@vswidth{\linewidth}}%
+% %
+% % This is a bit ugly but we can't stick \cs{@vsremainingkvlist} into
+% % the instance argument as keys are expected to be visible on
+% % top-level not hidden inside a macro. The alternative is to push
+% % in \verb=#1= but then the key/value \verb/verse-width=.../ is
+% % passed into the instance which is not known there (not harmful as
+% % it will get ignored but noticeably more and unnecessary
+% % processing).
+% %
+% \def\next##1{%
+% \UseInstance{blockenv}{list}%
+% {%
+% item-indent =-\vindent,%
+% parindent =-\vindent,%
+% par-skip =\stanzaskip,%
+% item-skip =0pt,%
+% leftmargin = (\linewidth-\@vswidth)/2+\vindent,%
+% rightmargin = \ifdim\@vswidth<\linewidth 0pt
+% \else (\linewidth-\@vswidth)/2\fi,%
+% ##1%
+% }}%
+% \ExpandArgs{o}\next\@vsremainingkvlist
+% \item\relax
+% }{\endblockenv}%
+% }%
+% }
+% \makeatother
+%\end{verbatim}
+%
+%
% \subsection{cleveref}
+%
% The cleveref package redefines \cs{@makefntext} and this means that the patches in
-% the new footnote code fails. We use a hook instead
+% 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}
{
@@ -118,21 +396,188 @@
\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
+%
+% \subsection{booktabs}
+% In some cases booktabs inserts a
+% \cs{multispan} into the table (through the commands \cs{@cmidruleb}
+% and \cs{@cmidrulea} and this then errors
+% with the tagging code.
+% This affects both tabular and longtable
+% (but longtable more as booktabs handles lines in longtable differently).
+% See also issue \url{https://github.com/latex3/tagging-project/issues/69}
+%
+%
% \begin{macrocode}
- \RenewDocumentCommand\refstepcounter{om}{%
- \IfNoValueTF{#1}%
- {\refstepcounter@noarg{#2}}%
- {\refstepcounter@optarg[#1]{#2}}%
- }%
- }
+\ExplSyntaxOn
+\AddToHook{package/booktabs/after}
+ {
+ \def\@cmidrulea{
+ \multispan\@cmidla
+ &\multispan\@cmidlb
+ \unskip\hskip\cmrkern@l
+ {
+ \tag_mc_begin:n{artifact}
+ \CT@arc@\leaders\hrule \@height\@thisrulewidth\hfill\kern\z@}
+ \hskip\cmrkern@r
+ \tag_mc_end: \int_gdecr:N \g__tbl_row_int
+ \cr}
+
+ \def\@cmidruleb{%
+ \multispan\@cmidlb
+ \unskip\hskip \cmrkern@l%
+ {
+ \tag_mc_begin:n{artifact}
+ \CT@arc@\leaders\hrule \@height\@thisrulewidth\hfill\kern\z@}
+ \hskip\cmrkern@r
+ \tag_mc_end: \int_gdecr:N \g__tbl_row_int
+ \cr}
+ }
+\ExplSyntaxOff
% \end{macrocode}
+
+%
+% \subsection{fancyvrb}
+% The firstaid adds first partial tagging support to the environments
+% of fancyvrb (inline verbatim is untested).
+% This supports then also packages like minted which internally uses fancyvrb
+% and classes like l3doc (where currently the verbatim environment based on fancyvrb
+% is overwritten by the block code).
+% The environments are surrounded by a \texttt{verbatim} structure,
+% every line by a \texttt{codeline}
+% structure (this requires the block code, but firstaid should be used only with
+% phase-III anyway). Line numbers are tagged as Lbl, currently outside of the
+% \texttt{codeline} structure. The frame lines are marked as artifact.
+%
+% \begin{macro}{\FV@LeaveVMode}
+% If we are in vmode we have to open a text-unit structure, if we are
+% in hmode we have to set para mode to flattened before the fancyhdr code
+% issues the\cs{par}. The closing of the text-unit structure is handled by the
+% doendpe code in the block code.
+% \begin{macrocode}
+\ExplSyntaxOn
+\AddToHook{package/fancyvrb/after}
+{
+ \def\FV@LeaveVMode{%
+ \if@noskipsec
+ \leavevmode
+ \else
+ \if@FV@ResetMargins\if@inlabel\leavevmode\fi\fi
+ \fi
+ \ifvmode
+ \@noparlisttrue
+ \__tag_gincr_para_main_begin_int:
+ \tag_struct_begin:n{tag=\l__tag_para_main_tag_tl}
+ \else
+ \bool_set_true:N\l__tag_para_flattened_bool
+ \@noparlistfalse
+ \unskip\par
+ \fi
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\FV@List}
+% At the begin of the list code we have to tag the frame as artifact
+% and start the \texttt{verbatim} structure
+% \begin{macrocode}
+ \def\FV@List#1{%
+ \begingroup
+ \FV@UseKeyValues
+ \FV@LeaveVMode
+ \if@inlabel\else\setbox\@labels=\box\voidb@x\fi
+ \FV@ListNesting{#1}%
+ \FV@ListParameterHook
+ \FV@ListVSpace
+ \FV@SetLineWidth
+ \FV@InterLinePenalty
+ \let\FV@ProcessLine\FV@ListProcessLine@i
+ \FV@CatCodes
+ \FV@FormattingPrep
+ \FV@ObeyTabsInit
+ \cs_if_exist:NT \FV@BeginListFrame
+ {
+ \tag_mc_begin:n{artifact}
+ \FV@BeginListFrame
+ \tag_mc_end:
+ }
+ \tag_struct_begin:n{tag=verbatim}
+ }
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\FV@EndList}
+% At the end of the list code we close the \texttt{verbatim} structure and
+% tag the frame as artifact.
+% \begin{macrocode}
+ \def\FV@EndList{%
+ \FV@ListProcessLastLine
+ \tag_struct_end:
+ \cs_if_exist:NT \FV@EndListFrame
+ {
+ \tag_mc_begin:n{artifact}
+ \FV@EndListFrame
+ \tag_mc_end:
+ }
+ \@endparenv
+ \endgroup
+ \@endpetrue
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\FV@ListProcessLine}
+% At last the tagging of the code lines. Here we have to tag also
+% numbers and frame parts if they exist.
+% \begin{macrocode}
+ \def\FV@ListProcessLine#1{%
+ \hbox to \hsize{%
+ \kern\leftmargin
+ \hbox to \linewidth{%
+ \cs_if_exist:NT \FV@LeftListNumber
+ {
+ \tag_struct_begin:n{tag=Lbl}
+ \tag_mc_begin:n{}
+ \FV@LeftListNumber
+ \tag_mc_end:
+ \tag_struct_end:
+ }
+ \cs_if_exist:NT \FV@LeftListFrame
+ {
+ \tag_mc_begin:n{artifact}
+ \FV@LeftListFrame
+ \tag_mc_end:
+ }
+ \tag_struct_begin:n{tag=codeline}
+ \tag_mc_begin:n{}%
+ \FancyVerbFormatLine{#1}%
+ \tag_mc_end:
+ \tag_struct_end:\hss
+ \cs_if_exist:NT \FV@RightListFrame
+ {
+ \tag_mc_begin:n{artifact}
+ \FV@RightListFrame
+ \tag_mc_end:
+ }
+ \cs_if_exist:NT \FV@RightListNumber
+ {
+ \tag_struct_begin:n{tag=Lbl}
+ \tag_mc_begin:n{}
+ \FV@RightListNumber
+ \tag_mc_begin:n{}
+ \tag_struct_end:
+ }
+ }
+ \hss}}
+ }
+\ExplSyntaxOff
+% \end{macrocode}
+% \end{macro}
% \begin{macrocode}
%</package>
% \end{macrocode}
+%
+%
% \begin{macrocode}
%<*latex-lab>
\ProvidesFile{firstaid-latex-lab-testphase.ltx}
diff --git a/macros/latex/required/latex-lab/latex-lab-firstaid.pdf b/macros/latex/required/latex-lab/latex-lab-firstaid.pdf
index c2b3b49a43..a43b493f7d 100644
--- a/macros/latex/required/latex-lab/latex-lab-firstaid.pdf
+++ b/macros/latex/required/latex-lab/latex-lab-firstaid.pdf
Binary files differ
diff --git a/macros/latex/required/latex-lab/latex-lab-float.dtx b/macros/latex/required/latex-lab/latex-lab-float.dtx
index 3bd3483600..536aa09cfa 100644
--- a/macros/latex/required/latex-lab/latex-lab-float.dtx
+++ b/macros/latex/required/latex-lab/latex-lab-float.dtx
@@ -16,8 +16,8 @@
%
% for those people who are interested or want to report an issue.
%
-\def\ltlabfloatdate{2023-07-20}
-\def\ltlabfloatversion{0.81a}
+\def\ltlabfloatdate{2024-09-20}
+\def\ltlabfloatversion{0.81f}
%<*driver>
\documentclass{l3doc}
\EnableCrossrefs
@@ -43,6 +43,9 @@
% customizations}}
%
% \providecommand\hook[1]{\texttt{#1}}
+% \ProvideDocElement[printtype=\textit{plug},idxtype=plug,idxgroup=Plugs]{Plug}{plugdecl}
+% \ProvideDocElement[printtype=\textit{socket},idxtype=socket,idxgroup=Sockets]{Socket}{socketdecl}
+%
% \begin{documentation}
% \begin{abstract}
% The following code implements a first draft for the tagging of float
@@ -64,7 +67,7 @@
%
% A special type, called a H-float, (provided by the float package)
% is always placed in the main text stream and does not
-% necessarly preserve the order with normal floats of the same type: It is basically
+% necessarily preserve the order with normal floats of the same type: It is basically
% a minipage with a caption.
%
% Floats typically contain a figure (or a table, etc.) and a caption,
@@ -86,8 +89,8 @@
% In PDF~2.0 there is the suitable \texttt{Aside} tag which hopefully will
% be handled correctly regarding the reading order once processor actually support
% PDF~2.0. But in PDF~1.7 we rolemap it to \texttt{Note} and this doesn't lead to
-% a good reading order. The code therefore collect the float structures and moves
-% them to a \texttt{Sect} the end of the document or the chapter
+% a good reading order. The code therefore collects the float structures and moves
+% them to a \texttt{Sect} at the end of the document or the chapter
% (H-floats once they are handled will not be moved).
%
% To fulfill the requirement that a \texttt{Caption} should be at the begin or end, we always
@@ -106,6 +109,8 @@
%
% The code add two keys for the \cs{tagtool} command
%
+%
+% \begin{function}{flush-floats,split-float}
% \begin{description}
% \item[flush-floats] This will flush out the collected floats sofar (currently
% table and figure. The value is a sectioning level, e.g. \texttt{section} or \texttt{chapter},
@@ -117,9 +122,22 @@
% \item[split-float] This can be used inside a float if there are two captions.
% It will only work reasonably well if the content of the float parts are in a sensible order
% and can be separated by this command. More complex setups with tabulars will need more
-% thoughts
+% thoughts.
+% \end{description}
+% \end{function}
+%
+% \section{Kernel commands}
+% \begin{function}{\@current@float@struct}
+% This variable holds the number of the current float structure. With tagging
+% this is the structure number, without tagging a unique counter. A float
+% can contain more than one float structure (e.g. if there is more than one
+% caption).
+% \end{function}
%
-% \end{description}
+% \begin{function}{\@makecaption}
+% \cs{@makecaption} is defined by the classes so we overwrite it for now
+% at begin document.
+% \end{function}
%
%
% \begin{macrocode}
@@ -134,22 +152,28 @@
{Code related to the tagging of floats}
% \end{macrocode}
% \subsection{Variables}
-% We rolemap to float to Aside, and float sections to Sect.
+% We rolemap floats to Aside, and float sections to Sect.
%
% \begin{variable}{
% \g_@@_float_sect_prop,
% \g_@@_float_types_seq,
-% \@current@float@struct
+% \@current@float@struct,
+% \g_@@_float_int
% }
% These variables will hold the structure number for the float container
% and the list of float types. Currently only figure and table are supported
% TODO: interface to declare new float types.
+% To set the target for links we need also a unique counter.
+% With tagging we could use the structure number, but
+% the structure commands now are hidden inside tagging sockets
+% so we use a dedicated counter.
% \begin{macrocode}
\prop_new:N \g_@@_float_sect_prop
\seq_new:N \g_@@_float_types_seq
\seq_gput_right:Nn \g_@@_float_types_seq {figure}
\seq_gput_right:Nn \g_@@_float_types_seq {table}
\tl_new:N\@current@float@struct
+\int_new:N\g_@@_float_int
% \end{macrocode}
% \end{variable}
%
@@ -164,6 +188,19 @@
% \end{macrocode}
% \end{variable}
%
+% \begin{macro}{\@@_float_init:}
+% To be able to set unique targets for links, we
+% need a counter outside the tagging sockets.
+% TODO: check if this command should be public or
+% a socket or a hook.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_float_init:
+ {
+ \int_gincr:N \g_@@_float_int
+ \tl_set:Ne \@current@float@struct { \int_use:N \g_@@_float_int}
+ }
+% \end{macrocode}
+% \end{macro}
%
%\subsection{Moving float structures}
%
@@ -182,7 +219,7 @@
\seq_map_inline:Nn\g_@@_float_types_seq
{
\tag_struct_begin:n{tag=##1s,stash}
- \prop_gput:Nnx\g_@@_float_sect_prop {##1-struct}{\int_use:N\c@g__tag_struct_abs_int}
+ \prop_gput:Nne\g_@@_float_sect_prop {##1-struct}{\int_use:N\c@g__tag_struct_abs_int}
\tag_struct_end:
}
}
@@ -239,6 +276,7 @@
{\par\__tag_sec_end:n{-10}\@@_float_stop_sect:}
\DeclareHookRule{tagpdf/finish/before}{latex-lab/float}{before}{tagpdf}
% \end{macrocode}
+%
% \subsection{Splitting floats}
% \begin{macro}{split-float}
% TODO: check if the target affect spacing!!
@@ -247,15 +285,71 @@
{
split-float .code:n =
{
- \@@_float_end:
- \@@_float_begin:
- \MakeLinkTarget[tagstructure]{g__tag_struct_abs_int}
+ \UseTaggingSocket{float/end}
+ \@@_float_init:
+ \UseTaggingSocket{float/begin}
+ \MakeLinkTarget*{floatstructure.\@current@float@struct}
}
}
% \end{macrocode}
% \end{macro}
-
-% \subsection{Patching}
+%
+% \subsection{Tagging sockets}
+% For now we test if the sockets are already defined
+% \begin{macrocode}
+\str_if_exist:cF { l__socket_tagsupport/float/begin_plug_str }
+ {
+ \NewSocket{tagsupport/float/hmode/begin}{0}
+ \NewSocket{tagsupport/float/hmode/end}{0}
+ \NewSocket{tagsupport/float/begin}{0}
+ \NewSocket{tagsupport/float/end}{0}
+ }
+% \end{macrocode}
+%
+% \begin{plugdecl}{default (tagsupport/float/hmode/begin)}
+% This plug should be used if a float is called in hmode.
+% In then closes the MC-chunks and starts the structure.
+% \begin{macrocode}
+\NewSocketPlug {tagsupport/float/hmode/begin}{default}
+ {
+ \@@_float_stop_par:
+ }
+\AssignSocketPlug{tagsupport/float/hmode/begin}{default}
+% \end{macrocode}
+% \end{plugdecl}
+%
+% \begin{plugdecl}{default (tagsupport/float/hmode/end)}
+% This plug should be used if a float is called in hmode
+% and the end of the float it then restarts the MC.
+% \begin{macrocode}
+\NewSocketPlug{tagsupport/float/hmode/end}{default}
+ {
+ \@@_float_start_par:
+ }
+\AssignSocketPlug{tagsupport/float/hmode/end}{default}
+% \end{macrocode}
+% \end{plugdecl}
+%
+% \begin{plugdecl}{default (tagsupport/float/begin)}
+% \begin{macrocode}
+\NewSocketPlug{tagsupport/float/begin}{default}
+ {
+ \@@_float_begin:
+ }
+\AssignSocketPlug{tagsupport/float/begin}{default}
+% \end{macrocode}
+% \end{plugdecl}
+%
+% \begin{plugdecl}{default (tagsupport/float/end)}
+% \begin{macrocode}
+\NewSocketPlug{tagsupport/float/end}{default}
+ {
+ \@@_float_end:
+ }
+\AssignSocketPlug{tagsupport/float/end}{default}
+% \end{macrocode}
+% \end{plugdecl}
+%
% \begin{macro}{\@@_float_stop_par:,\@@_float_start_par:}
% if a float is in a par, we need commands to stop and restart the P-mc
% \begin{macrocode}
@@ -274,8 +368,7 @@
\tag_struct_begin:n{tag=text}%
}
\tag_mc_begin:n{tag=P}
- }
-
+ }
% \end{macrocode}
% \end{macro}
% These commands are the main commands to start and end the float tagging.
@@ -290,18 +383,19 @@
{
\exp_args:Ne
\tag_struct_begin:n{tag=float,parent=0\prop_item:No\g_@@_float_sect_prop{\@captype-struct}}%
- \prop_gput:Nxx \g_@@_float_sect_prop {\@captype-used}{true}
+ \prop_gput:Nee \g_@@_float_sect_prop {\@captype-used}{true}
}
{
\tag_struct_begin:n{tag=float}
}
- \tl_set:Nx\@current@float@struct{\tag_get:n{struct_num}}%
+ \tl_set:Ne\@current@float@struct{\tag_get:n{struct_num}}%
\typeout{Float structure: \@current@float@struct}
}
\cs_new_protected:Npn\@@_float_end:{\tag_struct_end:} %end Aside
% \end{macrocode}
+% \subsection{Patching}
% This patches the main command \cs{@xfloat}.
% There is a : in the code, so we disable expl3 syntax
% \begin{macrocode}
@@ -324,7 +418,7 @@
% \end{macrocode}
% If the float is in hmode we have to interrupt the P
% \begin{macrocode}
- \@nameuse{@@_float_stoppar:} %<---end P
+ \UseTaggingSocket{float/hmode/begin}%
\@floatpenalty -\@Mii
\else
\@floatpenalty-\@Miii
@@ -370,7 +464,8 @@
% \end{macrocode}
% This starts the structure for the float.
% \begin{macrocode}
- \@nameuse{@@_float_begin:}%
+ \csname @@_float_init:\endcsname
+ \UseTaggingSocket{float/begin}%
\global \setbox\@currbox
\color@vbox
\normalcolor
@@ -381,14 +476,14 @@
% \end{macrocode}
% We add a target for links. TODO: check that it doesn't affect spacing!!
% \begin{macrocode}
- \MakeLinkTarget[tagstructure]{g__tag_struct_abs_int}%
+ \MakeLinkTarget*{\@captype.struct.\@current@float@struct}%
}%
% \end{macrocode}
% The end code of the float ...
% \begin{macrocode}
\def\end@float{%
\@endfloatbox
- \@nameuse{@@_float_end:}%
+ \UseTaggingSocket{float/end}%
\ifnum\@floatpenalty <\z@
\@largefloatcheck
\@cons\@currlist\@currbox
@@ -400,7 +495,7 @@
\penalty\@floatpenalty
\else
\vadjust{\penalty -\@Miv \vbox{}\penalty\@floatpenalty}\@Esphack
- \@nameuse{@@_float_start_par:} %restart P safe here??
+ \UseTaggingSocket{float/hmode/end}%
\fi
\fi
}
@@ -410,7 +505,7 @@
\def\end@dblfloat{%
\if@twocolumn
\@endfloatbox
- \@nameuse{@@_float_end:}%
+ \UseTaggingSocket{float/end}%
\ifnum\@floatpenalty <\z@
\@largefloatcheck
\global\dp\@currbox1sp %
@@ -423,7 +518,7 @@
\penalty\@floatpenalty
\else
\vadjust{\penalty -\@Miv \vbox{}\penalty\@floatpenalty}\@Esphack
- \@nameuse{@@_float_start_par:} %restart P safe here??
+ \UseTaggingSocket{float/hmode/end}%
\fi
\fi
\else
@@ -440,29 +535,140 @@
\def\hyper@nopatch@caption{}
% \end{macrocode}
%
+% \subsubsection{(Tagging) sockets}
+%
+% First some temporary sockets.
+% These sockets are in lttagging.
+% \begin{macrocode}
+\str_if_exist:cF { l__socket_tagsupport/caption/begin_plug_str }
+ {
+ \NewSocket{tagsupport/caption/begin}{1}
+ \NewSocket{tagsupport/caption/end}{0}
+ \NewSocket{tagsupport/caption/label/begin}{0}
+ \NewSocket{tagsupport/caption/label/end}{0}
+ }
+% \end{macrocode}
+% These socket are currently defined in tagpdf.
+% \begin{macrocode}
+\str_if_exist:cF { l__socket_tagsupport/para/begin_plug_str }
+ {
+ \NewSocket{tagsupport/para/begin}
+ \NewSocket{tagsupport/para/end}
+ }
+% \end{macrocode}
+%
+% \begin{socketdecl}{caption/label}
+% This socket is a lightweight start for
+% some interface to format the label or add a font command.
+% The argument is the label text.
+% The default plug \texttt{kernel} adds a colon
+% and a space.
+% TODO: revisit after checking float and caption packages
+% to identify which sockets and hooks are needed.
+% \begin{macrocode}
+\NewSocket{caption/label}{1}
+% \end{macrocode}
+% \end{socketdecl}
+%
+% \begin{plugdecl}{kernel (caption/label)}
+% The standard label formatting from the kernel.
+% \begin{macrocode}
+\NewSocketPlug{caption/label}{kernel}
+ {
+ #1:~
+ }
+\AssignSocketPlug{caption/label}{kernel}
+% \end{macrocode}
+% \end{plugdecl}
+% \begin{plugdecl}{default}
+% The caption begin socket takes an argument: the structure number of
+% the parent float. If the argument is empty, the current structure is used.
+% TODO: a tagpdf key that moves a structure to the begin of the parent.
+% The caption is moved to the first position with the firstkid option.
+% \begin{macrocode}
+\NewSocketPlug {tagsupport/caption/begin}{default}
+ {
+ \tl_if_empty:eTF {#1}
+ {
+ \tag_struct_begin:n{tag=Caption,firstkid}
+ }
+ {
+ \tag_struct_begin:n{tag=Caption,parent=#1,firstkid}
+ }
+ \bool_set_true:N \l__tag_para_flattened_bool
+ }
+\AssignSocketPlug{tagsupport/caption/begin}{default}
+% \end{macrocode}
+% \end{plugdecl}
+% \begin{plugdecl}{default}
+% \begin{macrocode}
+\NewSocketPlug {tagsupport/caption/end}{default}
+ {
+ \tag_struct_end:
+ }
+\AssignSocketPlug{tagsupport/caption/end}{default}
+% \end{macrocode}
+% \end{plugdecl}
+%
+% \begin{plugdecl}{default (tagsupport/caption/label/begin)}
+% \begin{macrocode}
+\NewSocketPlug {tagsupport/caption/label/begin}{default}
+ {
+% \end{macrocode}
+% suppress para tagging at the begin.
+% \begin{macrocode}
+ \tagpdfparaOff
+ \tag_struct_begin:n{tag=Lbl}
+ \tag_mc_begin:n{}
+ }
+\AssignSocketPlug{tagsupport/caption/label/begin}{default}
+% \end{macrocode}
+% \end{plugdecl}
+%
+% \begin{plugdecl}{default (tagsupport/caption/label/end)}
+% \begin{macrocode}
+\NewSocketPlug {tagsupport/caption/label/end}{default}
+ {
+ \tag_mc_end:
+ \tag_struct_end:
+ \tagpdfparaOn
+ }
+\AssignSocketPlug{tagsupport/caption/label/end}{default}
+% \end{macrocode}
+% \end{plugdecl}
+%
+% \subsubsection{Redefinitions}
+%
% With hyperref that means that the \cs{refstepcounter} now can affect spacing so we
% change that to the kernel refstepcounter:
% \begin{macrocode}
-\let\@kernel@refstepcounter\refstepcounter %as long it is not in the kernel
\def\caption{%
\ifx\@captype\@undefined
- \@latex@error{\noexpand\caption outside float}\@ehd
+ \@latex@error{\noexpand\caption\c_space_tl outside~float}\@ehd
\expandafter\@gobble
- \else
- \@kernel@refstepcounter\@captype
+ \else
+% \end{macrocode}
+% if a caption is used outside a float no
+% target has been set and \cs{@current@float@struct} is empty
+% \begin{macrocode}
+ \tl_if_empty:NTF\@current@float@struct
+ {
+ \refstepcounter\@captype
+ }
+ {
+ \@kernel@refstepcounter\@captype
+% \end{macrocode}
+% we need to reset the target for \cs{addcontentsline}.
+% We use \cs{@captype} to support autoref.
+% \begin{macrocode}
+ \xdef\@currentHref{\@captype.struct.\@current@float@struct}%
+ }
\expandafter\@firstofone
\fi
{\@dblarg{\@caption\@captype}}%
}
% \end{macrocode}
-% As we will use the structure number in the target, we need to provide a
-% theH-representation. (Once the kernel will create
-% theH-representation generally this will be provided automatically, as tagpdf uses
-% \cs{newcounter})
-% \begin{macrocode}
-\providecommand\theHg__tag_struct_abs_int{\int_use:N\c@g__tag_struct_abs_int}
-% \end{macrocode}
-
+%
% \begin{macro}{\@makecaption}
% \cs{@makecaption} is defined by the classes so we overwrite it for now
% at begin document.
@@ -471,48 +677,39 @@
{
\long\def\@makecaption#1#2{%
\vskip\abovecaptionskip
- \xdef\@currentHref{tagstructure.\@current@float@struct}%
% \end{macrocode}
% we don't want tagging when storing the caption for the singleline check
% \begin{macrocode}
- \tag_stop:n{caption}
+ \SuspendTagging{\@makecaption}
\sbox\@tempboxa{#1:~#2}%
- \tag_start:n{caption}
+ \ResumeTagging{\@makecaption}
% \end{macrocode}
-% we stop paratagging. TODO: check
+% We pass \cs{@current@float@struct} as parent structure
+% number. If that is empty the socket will use the parent structure and hope ...
% \begin{macrocode}
- \tagtool{para=false}
- \tag_struct_begin:n{tag=Caption,parent=\@current@float@struct}
-% \end{macrocode}
-% move the caption to the begin of the float structure:
-% \begin{macrocode}
- \seq_gpop_right:cN {g__tag_struct_kids_\@current@float@struct _seq}\l_@@_tmpa_tl
- \seq_gput_left:cV {g__tag_struct_kids_\@current@float@struct _seq}\l_@@_tmpa_tl
+ \UseTaggingSocket{caption/begin}{\@current@float@struct}
\ifdim \wd\@tempboxa >\hsize
- \tag_struct_begin:n{tag=Lbl}
- \tag_mc_begin:n{}
- #1:~
- \tag_mc_end:
- \tag_struct_end:
- \tag_mc_begin:n{}
- #2\par
- \tag_mc_end:
+ \UseTaggingSocket{caption/label/begin}
+ \UseSocket{caption/label}{#1}
+ \UseTaggingSocket{caption/label/end}
+ \UseTaggingSocket{para/begin}
+ #2
+ \par
\else
% \end{macrocode}
% we don't reuse the box as it doesn't contain tagging, but set the text explicitly.
% \begin{macrocode}
\global \@minipagefalse
\hb@xt@\hsize{\hfil
- \tag_struct_begin:n{tag=Lbl}
- \tag_mc_begin:n{}
- #1:~
- \tag_mc_end:
- \tag_struct_end:
- \tag_mc_begin:n{}
+ \UseTaggingSocket{caption/label/begin}
+ \UseSocket{caption/label}{#1}
+ \UseTaggingSocket{caption/label/end}
+ \UseTaggingSocket{para/begin}
#2
- \tag_mc_end:\hfil}%
+ \UseTaggingSocket{para/end}
+ \hfil}%
\fi
- \tag_struct_end: %caption
+ \UseTaggingSocket{caption/end}
\vskip\belowcaptionskip}
}
% \end{macrocode}
diff --git a/macros/latex/required/latex-lab/latex-lab-float.pdf b/macros/latex/required/latex-lab/latex-lab-float.pdf
index 8655d7309f..3915910cc0 100644
--- a/macros/latex/required/latex-lab/latex-lab-float.pdf
+++ b/macros/latex/required/latex-lab/latex-lab-float.pdf
Binary files differ
diff --git a/macros/latex/required/latex-lab/latex-lab-footnotes.dtx b/macros/latex/required/latex-lab/latex-lab-footnotes.dtx
index 2389906c5a..f4ad7edd9d 100644
--- a/macros/latex/required/latex-lab/latex-lab-footnotes.dtx
+++ b/macros/latex/required/latex-lab/latex-lab-footnotes.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
%% File: latex-lab-footnotes.dtx
-% Copyright (C) 2022-2023 The LaTeX Project
+% Copyright (C) 2022-2024 The LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -17,8 +17,8 @@
%
% for those people who are interested or want to report an issue.
%
-\def\ltlabfootnotedate{2023-09-04}
-\def\ltlabfootnoteversion{0.8c}
+\def\ltlabfootnotedate{2024-09-30}
+\def\ltlabfootnoteversion{0.8g}
%<*driver>
\documentclass{l3doc}
@@ -228,7 +228,8 @@
%
% To cater for different layout configurations there are four
% sockets that can be set by a package or
-% class but there should be only one per document setting them, i.e., if two packages/classes set them they are mutually
+% class but there should be only one per document setting them,
+% i.e., if two packages/classes set them they are mutually
% incompatible (or rather the last one wins most likely).
% These are:
% \begin{description}
@@ -454,6 +455,14 @@
% option.
% \end{itemize}
%
+% \subsection{Debugging sockets and hooks}
+%
+% For some rudimentary debugging we currently have \cs{DebugFNotesOn}
+% (and \cs{DebugFNotesOff}). At the moment \cs{DebugFNotesOn} only
+% shows the current settings for hooks and sockets related to the
+% footnote code and then
+% automatically turns itself off again.
+%
%
% \section{Tagging and hyperlinking support}
%
@@ -483,11 +492,21 @@
% \subsection{Technical details for the tagging}
%
% The following sockets are set up for kernel use, when doing tagging:
+% There name and/or function will probably change as they currently
+% mix tagging with the link support.
+%
+% TODO: review this sockets
% \begin{description}
% \item[\socket{tagsupport/fnmark} (1 argument)]
%
% \DescribeSocket[noprint]{tagsupport/fnmark}
-%
+%
+% The socket is used in \cs{@footnotemark}/\cs{fnote_footnotemark:}
+% and takes \cs{@makefnmark} as argument. It prints the mark in the text
+% and surrounds it with a tagging structure and a link. As such it is
+% not solely for tagging and so should not be used with \cs{UseTaggingSocket}
+% as this would swallow the argument and loose the link support.
+%
% \fmi{describe and decide on names}
%
%
@@ -495,31 +514,45 @@
%
% \DescribeSocket[noprint]{tagsupport/fntext/begin}
%
+% This socket is used before the main processing socket
+% (so before the \cs{insert} command). It opens the FEnote structure.
+% As it sets also the tl-var for the current structure and this is used
+% in destinations it should not use as tagging socket.
+%
%
% \item[\socket{tagsupport/fntext/end} (no argument)]
%
% \DescribeSocket[noprint]{tagsupport/fntext/end}
%
+% This socket is used after the main processing socket
+% (so after the \cs{insert} command). It closes the FEnote structure.
%
% \item[\socket{tagsupport/fntext/mark} (1 argument)]
%
% \DescribeSocket[noprint]{tagsupport/fntext/mark}
-%
+%
+% This socket is used around the mark in the footnote text.
+% It adds tagging support but also link support, so like the other
+% tagsupport sockets it should be always active.
%
% \item[\socket{tagsupport/fntext/text} (1 argument)]
%
% \DescribeSocket[noprint]{tagsupport/fntext/text}
%
+% This socket handles mc-chunks around the text of the footnote. As it
+% takes an argument (the text) is should not be use as tagging socket either.
%
% \end{description}
%
%
% The \emph{footnotemark} should create a \texttt{/Lbl} structure\footnote{to make it easier
-% to identify the role we use \texttt{/footnotemark} which we rolemap to \texttt{/Lbl}} that should contain a \texttt{/Ref} entry pointing
+% to identify the role we use \texttt{/footnotemark} which we rolemap to \texttt{/Lbl}}
+% that should contain a \texttt{/Ref} entry pointing
% to the structure of the \emph{footnotetext}.
%
-% The \emph{footnotetext} should create a \texttt{/FENote}\footnote{We tag it as \texttt{/footnote} and role map it.}
-% structure with a \texttt{/Ref}
+% The \emph{footnotetext} should create a \texttt{/FENote}%
+% \footnote{We tag it as \texttt{/footnote} and role map it.}
+% structure with a \texttt{/Ref}
% entry pointing to the structures of \emph{all} marks related to the note.
% The mark at the begin of the
% note is in a \texttt{/Lbl}\footnote{We tag it as \texttt{/footnotelabel}.}
@@ -574,8 +607,8 @@
% with their own structure number as a key in a property.
%
% A following \cs{footnotetext} compares its own \cs{@thefnmark} with the values in
-% the prop. If there is a match it stores the structure numbers and removes the entries
-% from the properties (so in a normal document the property will never contain more than
+% the prop. If there is one or more match it stores the structure numbers and removes the entries
+% from the property (so in a normal document the property will never contain more than
% a few entries).
%
% This works well as long as the \cs{footnotemark} commands are issued before the \cs{footnotetext} and
@@ -618,9 +651,9 @@
%
% \subsubsection{\cs{footref}}
%
-% \cs{footref} use internally the same command to set the mark as \cs{footnotemark}, it only
+% \cs{footref} uses internally the same command to set the mark as \cs{footnotemark}, it only
% defines \cs{@thefnmark} differently. This \cs{@thefnmark} is not suitable for the method described
-% above, as it contains a reference command it can't be used to match a note, also \cs{footref} can
+% above: as it contains a reference command it can't be used to match a note, also \cs{footref} can
% be used after the note has already been set. \cs{footref} disables therefore the automatic detection.
%
% Instead the \cs{label} command is
@@ -628,7 +661,7 @@
% number to setup the reference and the link.
%
% The structure related to the \cs{footref} is added to the end of the \texttt{/Ref} array of the note and so the
-% \texttt{/Ref} array doesn't necessarly reflect the order of the marks in the document. It would probably
+% \texttt{/Ref} array doesn't necessarily reflect the order of the marks in the document. It would probably
% be possible to change this, but it is not clear if it actually matters and so it worth the additional coding
% and processing.
%
@@ -664,7 +697,7 @@
%
% A \cs{footnotetext} creates a bunch of destinations (in most cases this sums up to
% two destinations): one for every structure number in the \texttt{/Ref} (used as target
-% by the mark commands) and one for the structure number of the footnotetest itself
+% by the mark commands) and one for the structure number of the footnotetext itself
% (used as target by \cs{footref}s commands).
%
% \subsection{Implementation details regarding tagging}
@@ -891,8 +924,8 @@
% This is used to pass the structure number of the note around, e.g.
% to a label inside the note.
% \begin{macrocode}
-\tl_new:N \l_@@_currentstruct_tl
-\tl_set:Nn \l_@@_currentstruct_tl {1}
+\tl_new:N \l_@@_currentstruct_tl
+\tl_set:Nn \l_@@_currentstruct_tl {2}
% \end{macrocode}
%
%
@@ -978,13 +1011,22 @@
% \end{hookdecl}
%
% \subsection{Debugging code}
-% the debugging code is just temporary
+% The debugging code is just temporary
%
-% For now we have debugging turned on by default
% \begin{macrocode}
\bool_new:N \g_fnote_debug_bool
-\bool_gset_true:N \g_fnote_debug_bool
% \end{macrocode}
+
+% \begin{macro}{\DebugFNotesOn,\DebugFNotesOff}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \DebugFNotesOn { \bool_gset_true:N \g_fnote_debug_bool }
+\cs_new_protected:Npn \DebugFNotesOff { \bool_gset_false:N \g_fnote_debug_bool }
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
% We log the hooks in the footnote mark command, but only once
% \begin{macrocode}
\cs_new_protected:Npn \@@_debug_footnotemark:
@@ -1133,6 +1175,21 @@
%
%
% \begin{macro}{\fnote_footnotetext:n}
+% We temporarily test for the tagging socket until it is in the next release:
+% \begin{macrocode}
+\str_if_exist:cF { l__socket_tagsupport/para/restore_plug_str }
+ {
+ \NewSocket{tagsupport/para/restore}{0}
+ \NewSocketPlug{tagsupport/para/restore}{default}
+ {
+ \tl_set:Nn \l__tag_para_main_tag_tl {text-unit}
+ \tl_set_eq:NN \l__tag_para_tag_tl\l__tag_para_tag_default_tl
+ \bool_set_false:N\l__tag_para_flattened_bool
+ }
+ \AssignSocketPlug{tagsupport/para/restore}{default}
+ }
+% \end{macrocode}
+%
% \begin{macrocode}
\cs_new_protected:Npn \fnote_footnotetext:n #1 {
\@@_debug_footnotetext:
@@ -1174,6 +1231,7 @@
\floatingpenalty \@MM
\hsize\columnwidth
\@parboxrestore
+ \UseTaggingSocket{para/restore}
\parindent 1em % typical default used in \@makefntext moved up here
\def\@currentcounter{footnote}
\protected@edef \@currentlabel { \p@footnote \@thefnmark }
@@ -1485,10 +1543,18 @@
\tl_if_in:NnTF \l_@@_patch_tl { \hb@xt@ }
{ \cs_set_eq:NN \@@_tmp:w \@@_patch_hb@xt@:w }
{
- \tl_if_in:NnTF \l_@@_patch_tl { \@makefnmark }
- { \cs_set_eq:NN \@@_tmp:w \@@_patch_@makefnmark:w }
- { \ERROR
- \cs_set_eq:NN \@@_tmp:w \exp_stop_f: }
+% \end{macrocode}
+% Some styles/classes use \verb=\makebox[...][...]= instead of \cs{hb@xt@}
+% so try to patch those too.
+% \begin{macrocode}
+ \tl_if_in:NnTF \l_@@_patch_tl { \makebox }
+ { \cs_set_eq:NN \@@_tmp:w \@@_patch_makebox:w }
+ {
+ \tl_if_in:NnTF \l_@@_patch_tl { \@makefnmark }
+ { \cs_set_eq:NN \@@_tmp:w \@@_patch_@makefnmark:w }
+ { \ERROR
+ \cs_set_eq:NN \@@_tmp:w \exp_stop_f: }
+ }
}
}
\tl_set:Nf \l_@@_patch_tl
@@ -1512,6 +1578,17 @@
% \begin{macrocode}
\cs_new:Npn \@@_patch_hb@xt@:w #1 \hb@xt@ #2 #
{ \exp_stop_f: #1 \@makefntext@processX { \hb@xt@ #2 } }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new:Npn \@@_patch_makebox:w #1 \makebox #2 #
+ { \exp_stop_f: #1 \@makefntext@processX { \makebox #2 } }
+% \end{macrocode}
+%
+% If the definition contains neither \cs{hbox}, \cs{hb@xt@} nor \cs{makebox},
+% we see if it contains \cs{@makefnmark} and if so put the socket
+% before that.
+% \begin{macrocode}
\cs_new:Npn \@@_patch_@makefnmark:w #1 \@makefnmark
{ \exp_stop_f: #1 \@makefntext@processX { \use:n } { \@makefnmark } }
% \end{macrocode}
@@ -1539,7 +1616,12 @@
\cs_set_eq:NN \@makefntext \fnote_makefntext:n
}
{
- \@@_patch:
+% \end{macrocode}
+% If \cs{@makefntext} contains the definition from \pkg{footmisc}
+% we do nothing, otherwise we try to patch.
+% \begin{macrocode}
+ \cs_if_eq:NNF \@makefntext \footmisc@hang@makefntext
+ { \@@_patch: }
}
}
@@ -1632,7 +1714,7 @@
%
% \subsubsection{\pkg{memoir}}
% The \pkg{memoir} class redefines various internal commands to inject its
-% hooks and addtional code. The following reinstates the kernel command and
+% hooks and additional code. The following reinstates the kernel command and
% so probably breaks various options of \pkg{memoir}, but without the
% changes it errors anyway. The \pkg{footmisc} package should be used to change
% for example to para footnotes.
@@ -1896,10 +1978,7 @@
% \begin{macrocode}
\cs_new_protected:Npn \@@_gput_ref:nn #1 #2 %#1 the structure number receiving the ref #2
{
- \tag_if_active:T
- {
- \tag_struct_gput:nne {#1}{ref}{\tag_struct_object_ref:e { #2 }}
- }
+ \tag_struct_gput:nnn {#1}{ref_num}{#2}
}
\cs_new_protected:Npn \fnote_gput_refs:nn #1 #2 % pair of numbers
{
@@ -1910,11 +1989,7 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macrocode}
-\tl_new:N \l_@@_dflt_struct_tl
-\tl_set:Nn \l_@@_dflt_struct_tl {1}
-% \end{macrocode}
-% kernel hooks for taggin
+% kernel hooks for tagging
% this sets the structure around the whole text
%
%
@@ -1924,25 +1999,30 @@
{
\tag_mc_end_push:
% \end{macrocode}
-% test if a footnote is allowed, if not move up to the document structure.
+% test if a footnote is allowed, if not move up to the next sect or
+% the document structure.
% \begin{macrocode}
\tag_check_child:nnTF {FENote}{pdf2}
{
\tag_struct_begin:n { tag=footnote }
}
{
- \tag_struct_begin:n { tag=footnote,parent=\l_@@_dflt_struct_tl }
+ \tag_struct_begin:n
+ {
+ tag=footnote,
+% \end{macrocode}
+% We add 0 for now to ensure to get a number even if the sec code is not loaded
+% or if the seq is empty (which it shouldn't unless there is an coding error)
+% \begin{macrocode}
+ parent=\int_max:nn{2}{\tag_get:n{current_Sect}+0}
+ }
}
% \end{macrocode}
% Store the current structure number for labels.
% \begin{macrocode}
\tl_set:Ne \l_@@_currentstruct_tl { \tag_get:n{struct_num} }
% \end{macrocode}
-% We want to move the label structure here. So we provide a container
-% It number is |\l__fnote_currentstruct_tl| plus 1.
-% \begin{macrocode}
- \tag_struct_begin:n { tag=footnotelabel }\tag_struct_end:
-% \end{macrocode}
+%
% after we have opened the structure we can use the structure number to
% try to detect the connected marks. As with the marks we assume that sometimes
% no auto detection is done.
@@ -2025,12 +2105,9 @@
\MakeLinkTarget*{footnote*.\l_@@_currentstruct_tl}
% \end{macrocode}
% Now we add the tagging commands. We move the structure of the label to
-% to the container at the begin of the note.
-% \begin{NOTE}{UF}
-% Check if the NonStruct is really needed. Perhaps we can simply move the mc.
-% \end{NOTE}
+% the begin of the footnote structure.
% \begin{macrocode}
- \tag_struct_begin:n { tag=NonStruct,parent=\l_@@_currentstruct_tl +1 }
+ \tag_struct_begin:n { tag=footnotelabel,parent=\l_@@_currentstruct_tl,firstkid }
\tag_mc_begin:n { tag=Lbl }
#1
\tag_mc_end:
@@ -2405,7 +2482,7 @@
% This can use the default interface, except that a negative value for
% \footnotemargin makes little sense, so we test for this and warn if
-% necessary. But -\maxdimen is ok again, so would need to be a litte bit more elaborate.
+% necessary. But -\maxdimen is ok again, so would need to be a little bit more elaborate.
%
%\AddToHook{fntext/para}{
@@ -2421,8 +2498,9 @@
\else
\ifFN@hangfoot
- \long\def\@makefntext#1{%
+ \long\def\footmisc@hang@makefntext#1{%
\bgroup
+ \SuspendTagging{footmisc}%
\setbox\@tempboxa\hbox{%
\ifdim\footnotemargin>\z@
\hb@xt@\footnotemargin{\@makefnmark\hss}%
@@ -2437,14 +2515,33 @@
\parshape \@ne \leftmargin \linewidth
\footnotesize
\@setpar{{\@@par}}%
+ \ResumeTagging{footmisc}%
\leavevmode
- \llap{\box\@tempboxa}%
+% \end{macrocode}
+% Typesetting the mark twice means that one can't have any material
+% inside that gets unhappy in that case. That shouldn't be a
+% problem, but perhaps we have to come up with a more elaborate
+% solution in the end.
+% \begin{macrocode}
+ \UseSocket{tagsupport/fntext/mark}%
+ {\llap{%
+ \ifdim\footnotemargin>\z@
+ \hb@xt@\footnotemargin{\@makefnmark\hss}%
+ \else
+ \@makefnmark
+ \fi
+ }}%
\parskip\hangfootparskip\relax
\parindent\hangfootparindent\relax
\footnotelayout#1%
\par
\egroup
}
+% \end{macrocode}
+% Defined in a roundabout way so that we can test for it when
+% patching classes that are not updated.
+% \begin{macrocode}
+ \let \@makefntext \footmisc@hang@makefntext
\else
@@ -2723,9 +2820,8 @@
\@footnotemark
}
% \end{macrocode}
-% TEMP PATCHES FOR TESTING
+%
% \begin{macrocode}
-
\endinput
%</footmisc>
% \end{macrocode}
diff --git a/macros/latex/required/latex-lab/latex-lab-footnotes.pdf b/macros/latex/required/latex-lab/latex-lab-footnotes.pdf
index 8f55486a67..c928060b5f 100644
--- a/macros/latex/required/latex-lab/latex-lab-footnotes.pdf
+++ b/macros/latex/required/latex-lab/latex-lab-footnotes.pdf
Binary files differ
diff --git a/macros/latex/required/latex-lab/latex-lab-graphic.dtx b/macros/latex/required/latex-lab/latex-lab-graphic.dtx
index 158b0d2a9c..b3ee3eb6c6 100644
--- a/macros/latex/required/latex-lab/latex-lab-graphic.dtx
+++ b/macros/latex/required/latex-lab/latex-lab-graphic.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-%% File: latex-lab-graphic.dtx (C) Copyright 2022-2023 LaTeX Project
+%% File: latex-lab-graphic.dtx (C) Copyright 2022-2024 LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -15,8 +15,8 @@
% https://github.com/latex3/latex2e/required/latex-lab
%
% for those people who are interested or want to report an issue.
-\def\ltlabgraphicdate{2023-10-13}
-\def\ltlabgraphicversion{0.80b}
+\def\ltlabgraphicdate{2024-09-18}
+\def\ltlabgraphicversion{0.80e}
%
%<*driver>
\documentclass{l3doc}
@@ -78,7 +78,7 @@
% The value of a \texttt{BBox} is an array of four numbers that gives the
% coordinates of the left, bottom, right, and top edges
% of the structure element’s bounding box. That is the rectangle that completely encloses
-% its \emph{visible} content so not necessarly the TeX bounding box:
+% its \emph{visible} content so not necessarily the TeX bounding box:
% if \texttt{viewport} or \texttt{trim} is used and the
% graphic is not clipped, the visible content can be larger.
%
@@ -146,8 +146,8 @@
% \item[\texttt{artifact}] When used the graphic will be tagged as artifact. This doesn't
% require a \texttt{BBox} and so works also in some of the not yet supported cases described
% above.
-% \item[\texttt{false}] When used tagging will be stopped completly. It is then the
-% responsability of the surrounding code to add appropriate tagging commands.
+% \item[\texttt{false}] When used tagging will be stopped completely. It is then the
+% responsibility of the surrounding code to add appropriate tagging commands.
% \item[\meta{name}] Other values will be used as tag names in the structure. If the tag is not
% known as a structure tag you will get an warning from tagpdf. The default name is currently
% \texttt{Figure}
@@ -184,7 +184,10 @@
\RequirePackage{l3opacity}
% \end{macrocode}
%
-%
+% Needed during switch to e-type:
+% \begin{macrocode}
+\cs_generate_variant:Nn \@@_prop_gput:Nnn {cne}
+% \end{macrocode}
% \begin{macro}{\@@_graphic_savepos:n}
% this is the command which stores the position. Similar to
% zref-savepos it uses two savepos commands
@@ -288,7 +291,7 @@
% ,\l_@@_graphic_trim_uy_fp
% }
% A bunch of fp-variables (we don't use tl-vars,
-% to avoid to have to take care about minus signs everwhere)
+% to avoid to have to take care about minus signs everywhere)
% \begin{macrocode}
\fp_new:N\l_@@_graphic_sin_fp
\fp_new:N\l_@@_graphic_cos_fp
@@ -323,7 +326,7 @@
\msg_new:nnn {tag}{alt-text-missing}
{
Alternative~text~for~graphic~is~missing.\\
- Using~'#1'~instead
+ Using~the~file~name~'#1'~instead.
}
\cs_new_protected:Npn\Gin@tag@struct@begin
{
@@ -449,8 +452,9 @@
% \end{macrocode}
% and here the tagging stops.
% \begin{macrocode}
+ \fi
\Gin@tag@struct@end %new
- \fi}
+ }
}
% \end{macrocode}
%
@@ -485,7 +489,7 @@
\bool_set_true:N \l_@@_graphic_artifact_bool
\bool_set_false:N \l_@@_graphic_BBox_bool
}
- {false}{\tag_stop:}
+ {false}{\tag_suspend:n{Gin}}
}
{\tl_set:Nn\l_@@_graphic_struct_tl{#1}}
}
@@ -524,7 +528,7 @@
\bool_set_true:N \l_@@_graphic_artifact_bool
\bool_set_false:N \l_@@_graphic_BBox_bool
}
- {false}{\tag_stop:}
+ {false}{\tag_suspend:n{picture}}
}
{\tl_set:Nn\l_@@_graphic_struct_tl{#1}}
}
@@ -894,7 +898,7 @@
% The structure and the mc must be open earlier, before the \cs{setbox} (at least
% for luatex it has to). TODO: think about interface if more attributes are needed.
% \begin{macrocode}
- \@@_prop_gput:cnx
+ \@@_prop_gput:cne
{ g_@@_struct_\int_eval:n {\c@g_@@_struct_abs_int}_prop }
{ A }
{
@@ -970,7 +974,7 @@
{red}
{\int_use:N\g_@@_graphic_int}
}
- \@@_prop_gput:cnx
+ \@@_prop_gput:cne
{ g_@@_struct_\int_eval:n {\c@g_@@_struct_abs_int}_prop }
{ A }
{
@@ -1008,7 +1012,7 @@
\@defaultunitsset\@tempdimc{#1}\unitlength
\Gin@tag@struct@begin
\setbox\@picbox\hb@xt@\@tempdimc\bgroup
- \tag_stop: %do not tag inside the picture box
+ \tag_suspend:n{\@picture} %do not tag inside the picture box
\@defaultunitsset\@tempdimc{#3}\unitlength
\hskip -\@tempdimc
\@defaultunitsset\@tempdimc{#4}\unitlength
diff --git a/macros/latex/required/latex-lab/latex-lab-graphic.pdf b/macros/latex/required/latex-lab/latex-lab-graphic.pdf
index a8570de484..48065014f2 100644
--- a/macros/latex/required/latex-lab/latex-lab-graphic.pdf
+++ b/macros/latex/required/latex-lab/latex-lab-graphic.pdf
Binary files differ
diff --git a/macros/latex/required/latex-lab/latex-lab-marginpar.dtx b/macros/latex/required/latex-lab/latex-lab-marginpar.dtx
new file mode 100644
index 0000000000..2f293ee492
--- /dev/null
+++ b/macros/latex/required/latex-lab/latex-lab-marginpar.dtx
@@ -0,0 +1,284 @@
+% \iffalse meta-comment
+%
+%% File: latex-lab-marginpar.dtx
+%%
+% Copyright (C) 2024 LaTeX Project
+%
+% It may be distributed and/or modified under the conditions of the
+% LaTeX Project Public License (LPPL), either version 1.3c of this
+% license or (at your option) any later version. The latest version
+% of this license is in the file
+%
+% https://www.latex-project.org/lppl.txt
+%
+%
+% The development version of the bundle can be found below
+%
+% https://github.com/latex3/latex2e/required/latex-lab
+%
+% for those people who are interested or want to report an issue.
+%
+\def\ltlabmarginpardate{2024-09-18}
+\def\ltlabmarginparversion{0.85d}
+
+%<*driver>
+\documentclass[kernel]{l3doc}
+\EnableCrossrefs
+\CodelineIndex
+\begin{document}
+ \DocInput{latex-lab-marginpar.dtx}
+\end{document}
+%</driver>
+%
+% \fi
+%
+% \title{The \textsf{latex-lab-marginpar} package\\
+% Changes related to the tagging of margin notes}
+% \author{\LaTeX{} Project\thanks{Initial implementation done by Ulrike Fischer}}
+% \date{v\ltlabmarginparversion\ \ltlabmarginpardate}
+%
+% \maketitle
+%
+% \newcommand{\xt}[1]{\textsl{\textsf{#1}}}
+% \newcommand{\TODO}[1]{\textbf{[TODO:} #1\textbf{]}}
+% \newcommand{\docclass}{document class \marginpar{\raggedright document class
+% customizations}}
+%
+% \providecommand\hook[1]{\texttt{#1\DescribeHook[noprint]{#1}}}
+% \providecommand\socket[1]{\texttt{#1\DescribeSocket[noprint]{#1}}}
+% \providecommand\plug[1]{\texttt{#1\DescribePlug[noprint]{#1}}}
+%
+% \NewDocElement[printtype=\textit{socket},idxtype=socket,idxgroup=Sockets]{Socket}{socketdecl}
+% \NewDocElement[printtype=\textit{hook},idxtype=hook,idxgroup=Hooks]{Hook}{hookdecl}
+% \NewDocElement[printtype=\textit{plug},idxtype=plug,idxgroup=Plugs]{Plug}{plugdecl}
+%
+% \begin{abstract}
+% \end{abstract}
+%
+% \section{Introduction}
+%
+% This module contains changes to improve the tagging (in the standard classes) of
+% margin notes created with the \cs{marginpar} command.
+%
+% Such margin notes are rather small but nevertheless tagging is not trivial and poses
+% a number of interesting problems both regarding the structure and the implementation.
+%
+% \subsection{Structure}
+% \cs{marginpar} creates small boxes in the margin of a page.
+% While they are technically floats they also typically
+% relate to the paragraph beside them, so their structure element should be placed near
+% such a paragraph.
+%
+% They can be tagged either as artifacts (if they are merely distracting decoration),
+% as small headings before the paragraph, or as |Aside|. Unlike the PDF 1.7 fallback |Note|
+% the structure |Aside| is not allowed inside |P|,
+% so if |Aside| is used, it must be placed before or after the current |P| in the surrounding |text-unit|,
+% or it must split the |P|. Splitting is probably not so good as
+% |\marginpar| is often used somewhere in the middle of sentence.
+% The best default is probably to use |Aside|, find the parent |text-unit| and add it there.
+%
+% \subsection{Implementation}
+%
+% |marginpar| has an optional argument which allows to define a different content
+% on left/right margins for odd/even pages (depending on twoside and \cs{reversemarginpar}).
+%
+% The current implementation stores *both* arguments in boxes and
+% decides in the output routine which
+% one to use. This is quite problematic for tagging, as the unused box produces
+% structure objects, literals, labels, MCID numbers,
+% and perhaps OBJR-objects from links
+% which must be later thrown away again (or are thrown away by the engine).
+% While it is theoretically not impossible to create
+% both boxes while taging is active but to keep everything on hold and insert
+% the real structure only when the box is used it is in practice quite difficult,
+% slow and error prone.
+%
+% There are a number of options to avoid this hassle.
+%
+% \begin{description}
+% \item[Minimal tagging] One option is to disable tagging when the boxes
+% are built and when the box is used to surround them with a simple Aside.
+%
+% \begin{description}
+% \item[Pro:] easy to implement
+% \item[Contra:]
+% Content that perhaps needed tagging (|\LaTeX| logo with /ActualText, images, links) is not tagged.
+% \end{description}
+%
+% \item[Remaking the box]
+% Tagging is deactivated when the boxes are created.
+% The arguments are stored and when the box should be used in the output routine
+% (and when it is known which one will be used) the box is (re)created, now with proper tagging.
+%
+% Contra: The content can change e.g. if it uses counters or macros that are redefine later before the
+% output routine is called. As tagging is done later, it is not trivial to insert the
+% |Aside| in the right place in the paragraph structure.
+%
+% \item[Two pass compilation]
+% A label is used to detect which argument/boxed is used and
+% tagging is activated only for this one.
+%
+% Contra: costs a |label| and requires a two pass compilation (which is needed anyway).
+% This should be ok. |\marginnote| uses a label too, and the same
+% label could also be used to resolve problems if a margin note
+% moves to a new page (and so replace the mparhack package).
+% \end{description}
+%
+% The last option seems the best and is therefore implemented.
+%
+%
+% \section{Implementation}
+% \begin{macrocode}
+%<*package>
+%<@@=tag>
+% \end{macrocode}
+% \begin{macrocode}
+\ProvidesExplPackage {latex-lab-testphase-marginpar} {\ltlabmarginpardate} {\ltlabmarginparversion}
+ {Changes related to the tagging of the margin notes}
+% \end{macrocode}
+% \subsection{Variables}
+% We need a variable to make the label unique.
+% Todo: Not sure about the name.
+% \begin{macro}{\g__kernel_marginpar_int}
+% \begin{macrocode}
+\int_new:N \g__kernel_marginpar_int
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Tagging sockets}
+%
+% \begin{socketdecl}{tagsupport/marginpar/begin,tagsupport/marginpar/end}
+% \begin{macrocode}
+\socket_new:nn {tagsupport/marginpar/begin}{0}
+\socket_new:nn {tagsupport/marginpar/end}{0}
+% \end{macrocode}
+% \end{socketdecl}
+%
+% \begin{macro}{\@@_get_marginpar_parent:N,\@@_get_marginpar_parent_aux:nn}
+% In a paragraph we must retrieve
+% the structure number of the surrounding Part structure
+% TODO: if this is needed in more places this should
+% go into tagpdf.
+% \begin{macrocode}
+\cs_new_protected:Npn\@@_get_marginpar_parent_aux:nn #1 #2
+ {
+ \str_if_eq:eeT{\use_ii:nn #1}{Part}{\seq_put_right:Nn\l_@@_tmpa_seq {#2}}
+ }
+\cs_new_protected:Npn \@@_get_marginpar_parent:N #1
+ {
+ \seq_clear:N\l_@@_tmpa_seq
+ \seq_map_pairwise_function:NNN
+ \g_@@_struct_tag_stack_seq
+ \g_@@_struct_stack_seq
+ \@@_get_marginpar_parent_aux:nn
+ \seq_put_right:Nn\l_@@_tmpa_seq {2}
+ \seq_get_left:NN \l_@@_tmpa_seq #1
+ }
+\cs_generate_variant:Nn \tag_struct_begin:n {e}
+% \end{macrocode}
+% \end{macro}
+% \begin{plugdecl}{tagsupport/marginpar/begin,tagsupport/marginpar/end}
+% \begin{macrocode}
+\socket_new_plug:nnn {tagsupport/marginpar/begin}{default}
+ {
+ \if_mode_horizontal:
+ \tag_mc_end:
+ \@@_get_marginpar_parent:N \l_@@_tmpa_tl
+ \tag_struct_begin:e{tag=Aside,parent=\l_@@_tmpa_tl}%
+ \else:
+ \tag_struct_begin:n{tag=Aside}%
+ \fi:
+ }
+\socket_new_plug:nnn {tagsupport/marginpar/end}{default}
+ {
+ \tag_struct_end:
+ \if_mode_horizontal: \tag_mc_begin:n{} \fi:
+ }
+\socket_assign_plug:nn {tagsupport/marginpar/begin}{default}
+\socket_assign_plug:nn {tagsupport/marginpar/end}{default}
+% \end{macrocode}
+% \end{plugdecl}
+
+% \subsection{Kernel command changes}
+% \begin{macro}{\@savemarbox }
+% We add sockets that add a tagging structure Aside:
+% \begin{macrocode}
+\long\def \@savemarbox #1#2{%
+ \UseTaggingSocket{marginpar/begin}
+ \global\setbox #1%
+ \color@vbox
+ \vtop{%
+ \hsize\marginparwidth
+ \@parboxrestore
+ \@marginparreset
+ #2\par
+ \@minipagefalse
+ \outer@nobreak
+ }%
+ \color@endbox
+ \UseTaggingSocket{marginpar/end}
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@ympar}
+% We must avoid that \cs{@xympar} creates tagging structure:
+% \begin{macrocode}
+\long\def\@ympar#1{%
+ \@savemarbox\@marbox{#1}%
+ \global\setbox\@currbox\copy\@marbox
+ \tag_suspend:n{\@ympar}
+ \@xympar
+ \tag_resume:n{\@ympar}}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@xmpar}
+% \cs{@xmpar} is the command used if an optional argument is present.
+% In this case we must stop tagging for \cs{@xympar} as above
+% but also decide which of the two @savemarbox should have tagging active.
+% We add a label to \cs{@marbox}. If that exist tagging is activated for this
+% box else for the other one.
+% \begin{macrocode}
+\long\def\@xmpar[#1]#2{%
+ \int_gincr:N\g__kernel_marginpar_int
+ \property_if_recorded:eTF { tag_marginpar-opt-\int_use:N\g__kernel_marginpar_int }
+ {
+ \@savemarbox\@marbox {#1
+ \property_record:ee
+ { tag_marginpar-opt-\int_use:N\g__kernel_marginpar_int }{page}
+ }%
+ \tag_suspend:n{\@xmpar}
+ \@savemarbox\@currbox{#2}%
+ \tag_resume:n{\@xmpar}
+ }
+% \end{macrocode}
+% order matters! the tagged box should be first so that it can pick up
+% the correct text-unit number.
+% \begin{macrocode}
+ {
+ \@savemarbox\@currbox{#2}%
+ \tag_suspend:n{\@xmpar}
+ \@savemarbox\@marbox{#1
+ \property_record:ee
+ { tag_marginpar-opt-\int_use:N\g__kernel_marginpar_int }{page}}
+ \tag_resume:n{\@xmpar}
+ }
+ \tag_suspend:n{\@xmpar}
+ \@xympar
+ \tag_resume:n{\@xmpar}
+ }
+%</package>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%<*latex-lab>
+\ProvidesFile{marginpar-latex-lab-testphase.ltx}
+ [\ltlabmarginpardate\space v\ltlabmarginparversion\space
+ Changes related to the tagging of the margin notes]
+
+\RequirePackage{latex-lab-testphase-marginpar}
+
+%</latex-lab>
+% \end{macrocode}
diff --git a/macros/latex/required/latex-lab/latex-lab-marginpar.pdf b/macros/latex/required/latex-lab/latex-lab-marginpar.pdf
new file mode 100644
index 0000000000..9db1bd0b70
--- /dev/null
+++ b/macros/latex/required/latex-lab/latex-lab-marginpar.pdf
Binary files differ
diff --git a/macros/latex/required/latex-lab/latex-lab-math.dtx b/macros/latex/required/latex-lab/latex-lab-math.dtx
index 285471addc..94d31c817b 100644
--- a/macros/latex/required/latex-lab/latex-lab-math.dtx
+++ b/macros/latex/required/latex-lab/latex-lab-math.dtx
@@ -2,7 +2,7 @@
%
%% File: latex-lab-math.dtx
%
-% Copyright (C) 2022-2023 The LaTeX Project
+% Copyright (C) 2022-2024 The LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -19,13 +19,13 @@
% for those people who are interested or want to report an issue.
%
%
-\def\ltlabmathdate{2023-09-11}
-\def\ltlabmathversion{0.5c}
+\def\ltlabmathdate{2024-10-25}
+\def\ltlabmathversion{0.6i}
%
%<*driver>
\documentclass{l3doc}
\EnableCrossrefs
-\CodelineIndex
+\CodelineIndex
\usepackage{todonotes}
@@ -40,13 +40,20 @@
% \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}}}
% \providecommand\class[1]{\texttt{#1.cls}}
% \providecommand\pkg[1]{\texttt{#1}}
-% \providecommand\hook[1]{\texttt{#1}}
+%
+% \providecommand\hook[1]{\texttt{#1\DescribeHook[noprint]{#1}}}
+% \providecommand\socket[1]{\texttt{#1\DescribeSocket[noprint]{#1}}}
+% \providecommand\plug[1]{\texttt{#1\DescribePlug[noprint]{#1}}}
+%
+% \NewDocElement[printtype=\textit{socket},idxtype=socket,idxgroup=Sockets]{Socket}{socketdecl}
+% \NewDocElement[printtype=\textit{hook},idxtype=hook,idxgroup=Hooks]{Hook}{hookdecl}
+% \NewDocElement[printtype=\textit{plug},idxtype=plug,idxgroup=Plugs]{Plug}{plugdecl}
%
% ^^A \car {...} for marginal comments
% ^^A \car*{...} for longer inline comments
@@ -59,8 +66,6 @@
% {\IfBooleanTF{#1}{\todo[inline,#2]{#3}}^^A
% {\todo[#2]{#3}}}
%
-%
-%
% \begin{abstract}
% This is an experimental prototype. It captures math material
% (basically okay, but the interfaces for packages aren't yet
@@ -72,9 +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.
+% \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.
+% \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
@@ -85,6 +102,23 @@
% 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
+% \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
+% regardless of the state of the boolean. For
+% |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}
+%
% \subsection{Code level interfaces}
%
% \begin{function}{\math_register_env:n, \math_register_env:nn}
@@ -109,7 +143,8 @@
% \end{syntax}
% Declares that the captured math content should be passed to the
% \meta{tokens}, which will receive the environment type as |#1| and
-% the content as |#2|.
+% the content as |#2|. The processing is done before the typesetting. It is not
+% applied if \cs{ifmeasuring@} is true.
% \end{function}
%
% \subsection{Document level interfaces}
@@ -128,51 +163,463 @@
% material.
% \end{itemize}
% \end{function}
-%
+%
+% \section{Math tagging}
+%
+% \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 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 the /Alt key
+% \item setup content for the /ActualText key
+% \item setup attributes
+% \item add associated files
+% \item add a Formula structure
+% \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
+% (currently only luatex with luamml)
+% \end{itemize}
+% \end{itemize}
+%
+% \subsection{Inline math}
+%
+% The embedding code is added through
+% the sockets
+% \begin{itemize}
+% \item |tagsupport/math/inline/begin|
+% \item |tagsupport/math/inline/end|
+% \end{itemize}
+% The sockets simply push and pop the MC currently. Without
+% 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.
+% It is not \emph{used} as a tagging socket as the math argument should
+% 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:
+% \begin{itemize}
+% \item |tagsupport/math/content| This should set up the various
+% content variables (empty variables are ignored by the structure code
+% and so can be used to suppress a setting).
+% \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??
+% \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|
+% \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.
+% Technically both can be attached---AF is an array
+% 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.
+% 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.
+% If the files contain more than one suitable snippet (as identified by the hash)
+% 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.
+%
+% 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
+% 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.
+% 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
+% 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>| \\
+% | <h2>\mml| \meta{key}|</h2>|\\
+% | <p>|\meta{source}|</p>| \\
+% | <p>|\meta{hash}|</p>| \\
+% | <math | \meta{attributes} |>|\\
+% \meta{mathml}\\
+% | </math>|\\
+% |</div>|
+% \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
+% 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.
+% 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
+% |math/mathml/AF=false|, or
+% 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
+% 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).
+%
+%
+% \subsection{Automatic mathml creation with luamml}\label{sec:luamml}
+%
+% 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.
+% 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|.
+%
+% 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}/''.
+% This can be avoided by an additional brace group:
+% \begin{verbatim}
+% $a{\begin{minipage}{1cm}$b$\end{minipage}}$
+% \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
-% \end{enumerate}
+% 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).
+%
+% \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
+% a grabbing environment.
+%
+% \item The behaviour of |\[...\]| is faulty. See above.
+% \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}.
+%
+% 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
+% \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.
+%
+% 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.
+%
+% \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.
+% 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}
+%
+% \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.,
+% 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.
+%
+% \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.
+% 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
-% 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,
+%
+% \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,
% \emph{even when the math is genuine} (and hence needs to be collected).
-% \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{DeclareMathEnviornment},
+% 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
+% \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.
% \end{enumerate}
%
%
@@ -218,37 +665,1216 @@
% have conditional definitions and deals with how to define \cs{[}/\cs{]}
% neatly.
% \begin{macrocode}
-\tl_gput_right:Nn \@kernel@before@begindocument
- { \RequirePackage { amsmath } }
-% \end{macrocode}
+\AddToHook{begindocument/before}{ \RequirePackage { amsmath } }
+% \end{macrocode}
%
%
% \subsection{Data structures}
%
-%
-%
-% \begin{variable}{\l_@@_collected_bool}
+% \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.
+% See \ref{sec:mathcapture} for details.
+% \begin{macrocode}
+\bool_new:N \l_@@_collected_bool
+% \end{macrocode}
+% \end{variable}
%
+% \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
+% grabbed contents contains the \cs{m@th} token.
%
% \begin{macrocode}
-\bool_new:N \l_@@_collected_bool
+\bool_new:N \l_@@_fakemath_bool
% \end{macrocode}
% \end{variable}
-%
+%
+%
% \car{Change first tl name below: `env' $=>$ `info'?\\
% Or do we need an extra storage tl?}
%
% \begin{variable}{\g_@@_grabbed_env_tl, \g_@@_grabbed_math_tl}
-% \cs{g_@@_grabbed_env_tl} contains the name of the math environment (\texttt{math} in the case
-% of inline math, \cs{g_@@_grabbed_math_tl} the math content.
+% \cs{g_@@_grabbed_env_tl} contains the name of the math environment
+% (\texttt{math} in the case of inline math,
+% \cs{g_@@_grabbed_math_tl} the math content.
% \begin{macrocode}
\tl_new:N \g_@@_grabbed_env_tl
\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}
+\tl_new:N \l_@@_tmpa_tl
+\skip_new:N \l_@@_tmpa_skip
+\str_new:N \l_@@_tmpa_str
+% \end{macrocode}
+% \end{variable}
+%
+% \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.
+% \begin{macrocode}
+\tl_new:N \l_@@_content_alt_tl
+\tl_new:N \l_@@_content_actual_tl
+\tl_new:N \l_@@_content_AF_source_tl
+\tl_new:N \l_@@_content_AF_source_tmpa_tl
+\tl_new:N \l_@@_content_AF_mathml_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \subsection{Tagging tools}
+% 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:
+ {
+ \tag_if_active:T
+ {
+ \tag_mc_end: %end P-chunk, should perhaps be \tag_mc_end_push: ...
+ \__tag_gincr_para_end_int:
+ \__tag_check_para_end_show:nn{red}{} %debug: show para
+ \tag_struct_end:
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% 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}
+% Booleans to handle the options.
+% \begin{variable}{
+% \l__tag_math_texsource_AF_bool,
+% \l__tag_math_texsource_pane_bool,
+% \l__tag_math_mathml_AF_bool,
+% \g__tag_math_mathml_AF_bool,
+% \l__tag_math_mathml_pane_bool,
+% \l__tag_math_alt_bool,
+% \g__tag_math_luamml_tl,
+% }
+% The variable \cs{g__tag_math_luamml_tl} is initially 0 and
+% the user key can set it to -1 or 1. This allows to distinguish
+% the unset case from a value set by the user.
+% \begin{macrocode}
+\bool_new:N\l__tag_math_texsource_AF_bool
+\bool_new:N\l__tag_math_texsource_pane_bool
+\bool_new:N\l__tag_math_mathml_AF_bool
+\bool_new:N\g__tag_math_mathml_AF_bool
+\bool_new:N\l__tag_math_mathml_pane_bool
+\bool_new:N\l__tag_math_alt_bool
+\tl_new:N\g__tag_math_luamml_tl
+\tl_gset:Nn\g__tag_math_luamml_tl {0}
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{
+% \g_@@_mathml_total_int,
+% \g_@@_mathml_int,
+% \g_@@_math_total_int,
+% \g_@@_mathml_AF_found_int,
+% \g_@@_mathml_AF_attached_int,
+% }
+% \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_found_int} records the number of math structures for which a fitting
+% 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
+\int_new:N\g_@@_math_total_int
+\int_new:N\g_@@_mathml_AF_found_int
+\int_new:N\g_@@_mathml_AF_attached_int
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l__tag_math_mathml_files_clist}
+% A sequence to store the file list for the mathml.
+% 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
+ {\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.
+% \begin{macro}{\@@_AF_mml:nnnn}
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_AF_mml:nnnn #1 #2 #3 #4
+%#1 number, #2 tex source for debugging, #3 hash, #4 mathml
+ {
+ \int_gincr:N \g_@@_mathml_total_int
+% \end{macrocode}
+% mathml with the same hash should be included only once:
+% \begin{macrocode}
+ \tl_if_exist:cF { g_@@_mathml_#3_tl }
+ {
+ \int_gincr:N \g_@@_mathml_int
+% \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)}
+ \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
+% \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
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% 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
+ \char_set_catcode_other:N\{
+ \char_set_catcode_other:N\}
+ \char_set_catcode_other:N\#
+ \char_set_catcode_other:N\%
+ \@@_AF_html_reader_verb:w{#1}{#3}{#5}<math
+}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new_protected:Npn\@@_AF_html_reader_verb:w#1#2#3#4~</div>{
+ \endgroup
+ \@@_AF_mml:nnnn{#1}{#2}{#3}{#4}
+ }
+% \end{macrocode}
+%
+% 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}
+% \begin{macrocode}
+\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
+ {
+ \iow_newline:
+ </div>
+ \iow_newline:
+ }
+\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
+% that both the dummy and luamml can make use of it.
+% \begin{macrocode}
+\socket_new:nn {tagsupport/math/mathml/write/prepare}{0}
+% \end{macrocode}
+% \end{socketdecl}
+%
+% \begin{plugdecl}{On}
+% \begin{macrocode}
+\socket_new_plug:nnn{tagsupport/math/mathml/write/prepare}{On}
+ {
+ \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
+ {
+ <div>
+ \iow_newline:
+ <h2>\c_backslash_str mml\c_space_tl \int_use:N \g_@@_math_total_int </h2>
+ \iow_newline:
+ <p>\l_@@_tmpa_str</p>
+ \iow_newline:
+ <p>\l_@@_content_hash_tl </p>
+ \iow_newline:
+ }
+ }
+% \end{macrocode}
+% \end{plugdecl}
+%
+% 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}
+\cs_new_protected:Npn\@@_provide_luamml_commands:
+ {
+ \providecommand\luamml_flag_structelem:{}
+ \cs_if_free:NT \luamml_structelem:
+ {
+ \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
+% \begin{macrocode}
+ \cs_new_protected:Npn \@@_correct_luamml_array_patches:
+ {
+ \AddToHook{package/array/after}
+ {
+ \cs_set:Npn \endarray
+ {
+ \tbl_crcr:n{endarray}
+ \__luamml_array_save_array:
+ \egroup
+ \UseTaggingSocket{tbl/finalize}
+ \tbl_restore_outer_cell_data:
+ \egroup
+ \mode_if_math:T { \__luamml_array_finalize_array: }
+ \@arrayright
+ \gdef \@preamble {}
+ }
+ \cs_set:Npn \@classz
+ {
+ \@classx
+ \@tempcnta \count@
+ \prepnext@tok
+ \@addtopreamble {
+ \ifcase \@chnum
+ \hfil
+ \hskip 1sp
+ \d@llarbegin
+ \cs_if_eq:NNTF \d@llarbegin \begingroup {
+ \insert@column
+ \d@llarend
+ } {
+ \__luamml_array_init_col:
+ \insert@column
+ \luamml_flag_save:nn {} {mtd}
+ \d@llarend
+ \__luamml_array_finalize_col:w 0~
+ }
+ \do@row@strut
+ \hfil
+ \or
+ \hskip 1sp
+ \d@llarbegin
+ \cs_if_eq:NNTF \d@llarbegin \begingroup {
+ \insert@column
+ \d@llarend
+ } {
+ \__luamml_array_init_col:
+ \insert@column
+ \luamml_flag_save:nn {} {mtd}
+ \d@llarend
+ \__luamml_array_finalize_col:w 1~
+ }
+ \do@row@strut
+ \hfil
+ \or
+ \hfil
+ \hskip 1sp
+ \d@llarbegin
+ \cs_if_eq:NNTF \d@llarbegin \begingroup {
+ \insert@column
+ \d@llarend
+ } {
+ \__luamml_array_init_col:
+ \insert@column
+ \luamml_flag_save:nn {} {mtd}
+ \d@llarend
+ \__luamml_array_finalize_col:w 2~
+ }
+ \do@row@strut
+ \or
+ \setbox \ar@mcellbox \vbox \@startpbox { \@nextchar }
+ \insert@pcolumn
+ \@endpbox
+ \ar@align@mcell
+ \do@row@strut
+ \or
+ \vtop \@startpbox { \@nextchar }
+ \insert@pcolumn
+ \@endpbox
+ \do@row@strut
+ \or
+ \vbox \@startpbox { \@nextchar }
+ \insert@pcolumn
+ \@endpbox
+ \do@row@strut
+ \fi
+ }
+ \prepnext@tok
+ }
+ }
+ }
+% \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 } }
+ }
+ }
+ \@@_provide_luamml_commands:
+ }
+ }
+ {
+ \@@_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 }
+ {
+ 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/load=false}}\\
+ or~force~luamml~with~\\
+ \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}{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 }
+ }
+ }
+% \end{macrocode}
+% 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}
+\tl_new:N \g_@@_luamml_load_tl
+\tl_gset:Nn \g_@@_luamml_load_tl {0}
+% \end{macrocode}
+% \end{variable}
+% \begin{variable}{\g_@@_luamml_write_bool}
+% This variable decides if luamml writes a mathml
+% altogether.
+% \begin{macrocode}
+\bool_new:N \g_@@_luamml_write_bool
+\bool_gset_true:N \g_@@_luamml_write_bool
+% \end{macrocode}
+% \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 }
+ {
+% \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
+ {
+ \l_@@_mathml_write_before_tl
+ <math></math>
+ \c_@@_mathml_write_after_tl
+ }
+ }
+% \end{macrocode}
+% \end{plugdecl}
+% And now a key to activate the socket.
+% \begin{macrocode}
+
+\keys_define:nn { __tag / setup }
+ {
+ math/mathml/write-dummy .code:n =
+ {
+ \bool_gset_true:N \g__tag_math_mathml_AF_bool
+ \tl_if_exist:NF\g_@@_writedummy_iow
+ {
+ \iow_new:N \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}{On}
+ \AddToHook{enddocument/afterlastpage}
+ {
+ \iow_now:Ne \g_@@_writedummy_iow
+ { \c_@@_mathml_write_final_tl }
+ \iow_close:N \g_@@_writedummy_iow
+ }
+ }
+ },
+ math/mathml/write-dummy .usage:n=preamble
+ }
+% \end{macrocode}
+%
+% \begin{macro}{\@@_AF_process_mathml_files:}
+% \begin{macrocode}
+\box_new:N\l_@@_tmpa_box
+\cs_new_protected:Npn \@@_AF_process_mathml_files:
+ {
+ \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} }
+ \char_set_catcode_other:N \#
+ \cs_set_eq:NN\mml \@@_AF_html_reader:w
+ \clist_map_inline:Nn \l__tag_math_mathml_files_clist
+ {
+ \file_if_exist:nTF {##1.html}
+ {
+ \typeout{Info:~reading~mathml~file~##1}
+ \file_input:n {##1.html}
+ \bool_gset_true:N\g__tag_math_mathml_AF_bool
+ }
+ {
+ \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}{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}
+ \AssignSocketPlug{tagsupport/math/substruct/begin}{single}
+ \AssignSocketPlug{tagsupport/math/substruct/end}{single}
+ \AddToHook{enddocument/info}
+ {
+ \iow_term:n{MathML~statistic}
+ \iow_term:n{================}
+ \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
+ different~MathML~fragments}
+ \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
+ fitting~MathML~AF~found}
+ \iow_term:e{==>~\int_use:N\g_@@_mathml_AF_attached_int\c_space_tl
+ MathML~AF~attached}
+ }
+ }
+ }
+\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.
+% 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
+\int_new:N \g_@@_mathchoice_int
+\property_new:nnnn{mathstyle}{now}{-1}{\int_use:N \l_@@_mathstyle_int }
+% \end{macrocode}
+%\end{macro}
+% 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
+% then used.
+% \begin{macro}{\@@_tag_if_mathstyle:nn}
+% \begin{macrocode}
+\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)
+ {
+ \int_set:Nn \l_@@_mathstyle_int {#2}
+ \property_record:nn {#1} { mathstyle }
+ \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}
+% \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,
+ 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,
+ 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,
+% tagsupport/math/inline/end,
+% tagsupport/math/inline/formula/begin,
+% 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.
+% 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!
+% \begin{macrocode}
+\socket_new:nn {tagsupport/math/inline/begin}{0}
+\socket_new:nn {tagsupport/math/inline/end}{0}
+\socket_new:nn {tagsupport/math/inline/formula/begin}{1} %
+\socket_new:nn {tagsupport/math/inline/formula/end}{0}
+% \end{macrocode}
+%\end{socketdecl}
+%
+%
+% \begin{plugdecl}{MC}
+% \begin{macrocode}
+\socket_new_plug:nnn
+ {tagsupport/math/inline/begin}
+ {MC}
+ {\tag_mc_end_push:}
+\socket_new_plug:nnn
+ {tagsupport/math/inline/end}
+ {MC}
+ {\tag_mc_begin_pop:n{}}
+% \end{macrocode}
+% \end{plugdecl}
+%
+% We probably will want to test different tagging recipes.
+% \begin{plugdecl}{default}
+% \begin{macrocode}
+\socket_new_plug:nnn
+ {tagsupport/math/inline/formula/begin}
+ {default}
+% \end{macrocode}
+% \changes{v0.6g}{2024-10-02}{disable paratagging, issue \#711}
+% \begin{macrocode}
+ { \tagpdfparaOff
+ \tag_socket_use:n{math/content}
+ \tag_socket_use:n{math/struct/begin}
+% \end{macrocode}
+% TODO: does inline math need subformula handling?
+% \begin{macrocode}
+ % inner formula if multiple parts (not really implemented yet)
+ \tag_socket_use:n{math/substruct/begin}
+ #1
+ \tag_socket_use:n{math/end}
+ }
+\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,
+% tagsupport/math/display/end,
+% tagsupport/math/display/formula/begin,
+% 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
+% P-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 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.
+% \begin{macrocode}
+\socket_new:nn {tagsupport/math/display/begin}{0}
+\socket_new:nn {tagsupport/math/display/end}{0}
+\socket_new:nn {tagsupport/math/display/formula/begin}{1} %
+\socket_new:nn {tagsupport/math/display/formula/end}{0}
+% \end{macrocode}
+%\end{socketdecl}
+
+% \begin{plugdecl}{default}
+% \begin{macrocode}
+\socket_new_plug:nnn
+ {tagsupport/math/display/begin}
+ {default}
+ { \__tag_tool_close_P: }
+\socket_new_plug:nnn
+ {tagsupport/math/display/end}
+ {default}
+ {
+ }
+% \end{macrocode}
+% \end{plugdecl}
+
+
+% \begin{plugdecl}{default}
+% \begin{macrocode}
+\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
+ \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}
+\tl_new:N\l_@@_content_template_tl
+\tl_set:Nn \l_@@_content_template_tl
+ {
+ LaTeX~ formula~ starts~
+ \exp_not:N\begin{\g_@@_grabbed_env_tl}
+ \c_space_tl
+ \exp_not:V\g_@@_grabbed_math_tl
+ \c_space_tl
+ \exp_not:N\end{\g_@@_grabbed_env_tl}
+ \c_space_tl LaTeX~ formula~ ends~
+ }
+% \end{macrocode}
+% \end{variable}
+
+% \begin{variable}{\l_@@_texsource_template_tl}
+% The default text used as texsource
+% \begin{macrocode}
+\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
+ {
+ $
+ \exp_not:V\g_@@_grabbed_math_tl
+ $
+ }
+ {
+ \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
+% 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
+% \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 how this should organized so that one
+% has options to change from the outside and so that
+% there are less repetitions.
+% \begin{plugdecl}{actual+source}
+% \begin{macrocode}
+\socket_new_plug:nnn
+ {tagsupport/math/content}
+ {actual+source}
+ {
+ \tl_set:Ne\l_@@_content_actual_tl
+ {
+ \l_@@_content_template_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}
+%
+% \begin{plugdecl}{alt+source}
+% \begin{macrocode}
+\socket_new_plug:nnn
+ {tagsupport/math/content}
+ {alt+source}
+ {
+ \tl_set:Ne\l_@@_content_alt_tl
+ {
+ \l_@@_content_template_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}
+% \end{macrocode}
+%
+% \begin{socketdecl}{tagsupport/math/struct/begin,
+% tagsupport/math/struct/end}
+% 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}
+\socket_new:nn {tagsupport/math/struct/end}{0}
+% \end{macrocode}
+% \end{socketdecl}
+%
+% \begin{plugdecl}{default}
+% TODO: think about some naming convention ...
+% \begin{macrocode}
+\socket_new_plug:nnn
+ {tagsupport/math/struct/begin}
+ {default}
+ {
+ \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,
+ alt = \l_@@_content_alt_tl
+ }
+ }
+\socket_new_plug:nnn
+ {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}{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
+% \end{macrocode}
+% we need to save the grabbed math:
+% \begin{macrocode}
+\tl_new:N\l_@@_grabbed_math_tl
+% \end{macrocode}
+% the socket definition
+% \begin{macrocode}
+\socket_new_plug:nnn
+ {tagsupport/math/struct/begin}
+ {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{display}
+ }
+ \bool_if:NF\l__tag_math_alt_bool
+ { \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}
+ }
+ }
+ {
+ \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 }
+ \tag_struct_begin:n
+ {
+ tag=Formula,
+ attribute-class=\l_@@_attribute_class_tl, %
+ AFref =
+ \bool_if:NT\l__tag_math_mathml_AF_bool
+ {
+ \cs_if_exist_use:c {g_@@_mathml_ \l_@@_content_hash_tl _tl}
+ },
+ texsource = \l_@@_content_AF_source_tmpa_tl, % should be after mathml AF!
+ title-o = \g_@@_grabbed_env_tl, %
+ alt = \l_@@_content_alt_tl
+ }
+ }
+% \end{macrocode}
+% not really needed but looks more symmetric:
+% \begin{macrocode}
+\socket_new_plug:nnn
+ {tagsupport/math/struct/end}
+ {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.
+% \begin{macrocode}
+\socket_new:nn {tagsupport/math/substruct/begin}{0}
+\socket_new:nn {tagsupport/math/substruct/end}{0}
+% \end{macrocode}
+% \end{socketdecl}
+%
+% \begin{plugdecl}{default}
+% \begin{macrocode}
+\socket_new_plug:nnn
+ {tagsupport/math/substruct/begin}
+ {default}
+ { \grabaformulapartandstart }
+\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}
+
+% \begin{plugdecl}{single}
+% We need an option to disable subparts as it is unclear
+% if consumers can handle them:
+% \begin{macrocode}
+\socket_new_plug:nnn
+ {tagsupport/math/substruct/begin}
+ {single}
+ {
+ \typeout{====>subpart~splitting~deactivated}
+ \typeout{====>grabbed~math=\meaning\g_@@_grabbed_math_tl}
+ \tag_mc_begin:n{}
+ }
+\socket_new_plug:nnn
+ {tagsupport/math/substruct/end}
+ {single}
+ { \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.
+% \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:
+ {
+ \socket_assign_plug:nn {tagsupport/math/inline/begin}{noop}
+ \socket_assign_plug:nn {tagsupport/math/inline/end}{noop}
+ \socket_assign_plug:nn {tagsupport/math/inline/formula/begin}{identity}
+ \socket_assign_plug:nn {tagsupport/math/inline/formula/end}{noop}
+ \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}
+ }
+% \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:
+ {
+ \socket_assign_plug:nn {tagsupport/math/inline/begin}{MC}
+ \socket_assign_plug:nn {tagsupport/math/inline/end}{MC}
+ \socket_assign_plug:nn {tagsupport/math/inline/formula/begin}{default}
+ \socket_assign_plug:nn {tagsupport/math/inline/formula/end}{default}
+ \socket_assign_plug:nn {tagsupport/math/display/begin}{default}
+ \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:
+% \begin{macrocode}
+\AtBeginDocument{\tag_if_active:T{\__tag_math_enable: }}
+% \end{macrocode}
+%
% \subsection{Interface commands}
%
% \begin{macro}
@@ -260,7 +1886,8 @@
{
\legacy_if:nF { measuring@ }
{
- \tl_if_in:nnF {#2} { \m@th }
+ \tl_if_in:nnTF {#2} { \m@th }
+ { \bool_set_true:N\l_@@_fakemath_bool }
{ \tl_trim_spaces_apply:nN {#2} \@@_process_auxi:nn {#1} }
}
}
@@ -286,115 +1913,117 @@
% \subsection{Content grabbing}
%
% \begin{macro}{\@@_grab_dollar:w}
-% Grab up to a single |$|, for inline math mode, suppressing
-% any processing if the first token is \tn{m@th}.
-%
-% \fmi{what's that test doing?}
-%
-% \car{It is some kind of fix, to avoid the remote
-% possibility that the math is empty, making the code
-% produce an unwanted \texttt{\$\$}.}
-%
-%\car{cf.~the code for this in \cs{@ensuredmath}}
-%
-%\car{It is harmless but unnecessary in the dollardollar grabbing below.}
-%
+% \begin{macro}{\@@_grab_dollar:n}
+% \changes{v0.6c}{2024-08-22}{Correct handling of empty math segments}
+% Top-level function to handle grabbing of inline math mode delimited by
+% |$| tokens. We provide two different ways to do that: a token-by-token
+% one that can be used everywhere, and a fast delimited one that does not
+% work anywhere that the end |$| token may be hidden, most obviously in
+% tabulars. The function here is therefore set up as a variable starting
+% point.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_grab_dollar:w { \@@_grab_dollar_delim:w }
+% \end{macrocode}
+% After grabbing inline math material, there is again common processing
+% independent of mechanism of collection.
% \begin{macrocode}
-\cs_new_protected:Npn \@@_grab_dollar:w % $
- #1 $
+\cs_new_protected:Npn \@@_grab_dollar:n #1
{
% \end{macrocode}
-% \fmi{what's that test doing?}
+% We need to do processing first as this picks up \enquote{fake} math mode:
+% that information is needed below.
% \begin{macrocode}
- \tl_if_blank:nF {#1}
- {
- \@@_process:nn { math } {#1} % $
-% fairly simple this one
+ \@@_process:nn { math } {#1}
% \end{macrocode}
-% We do not want math tagging in fakemath or when measuring,
-% so we imitate the test inside \cs{@@_process:nn} for now,
-% see https://github.com/latex3/tagging-project/issues/5
-% TODO: use socket to get more control about typesetting variants (tagged, drop etc)?
+% 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}
- \legacy_if:nTF { measuring@ }
- { #1 $ }
- {
- \tl_if_in:nnTF {#1} { \m@th }
- { #1 $ }
- {
- \tagmcend %end P-chunk, in code: \tag_mc_end_push:
- \@kernel@math@begin
- #1 $
- \@kernel@math@end
- \tagmcbegin{} % restart P-chunk (whatsits in pdftex)
- }
- }
- }
+ \bool_lazy_any:nTF
+ {
+ {\legacy_if_p:n { measuring@ }}
+ { \l_@@_fakemath_bool }
+ { \tl_if_blank_p:n {#1} }
+ }
+ {
+ #1 $ % $
+ }
+ {
+ \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.
+% \begin{macrocode}
+ \socket_use:nn {tagsupport/math/inline/formula/begin}{#1}
+ $ % $
+ \tag_socket_use:n {math/inline/formula/end}
+ \tag_socket_use:n {math/inline/end} % restart P-MC
+ }
}
% \end{macrocode}
% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_grab_dollar_delim:w}
+% Grab up to a single |$|, for inline math mode, suppressing
+% any processing if the token is \tn{m@th} found in the content.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_grab_dollar_delim:w #1 $ % $
+ { \@@_grab_dollar:n {#1} }
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}{\@@_grab_dollardollar:w}
% And for the classical \TeX{} display structure.
% \begin{macrocode}
-
-\skip_new:N \l_@@_tmpa_skip
-
\cs_new_protected:Npn \@@_grab_dollardollar:w % $$
#1 $$
{
\tl_if_blank:nF {#1}
{
- \@@_tag_dollardollar_display:nn { equation* }{#1}
- #1
- $$
+ \@@_process:nn { equation* } {#1}
+ \tag_socket_use:n {math/display/begin}
+ \socket_use:nn{tagsupport/math/display/formula/begin}{#1}
}
+ $$
}
% \end{macrocode}
-% To allow to use the code without tagging we guard. But probably tagpdf should
-% provide some tools for such manual para-ends.
+%
+% The end code is added through a \cs{aftergroup} so we
+% store it inside a command.
% \begin{macrocode}
-\cs_new_protected:Npn \@kernel@close@P {
- \tag_if_active:T
- {
- \tagmcend %end P-chunk, should perhaps be \tag_mc_end_push: ...
- \int_gincr:N \g__tag_para_end_int
- \bool_if:NT \l__tag_para_show_bool
- { \tag_mc_begin:n{artifact}
- \rlap{\color_select:n{red}\tiny\ \int_use:N\g__tag_para_end_int}
- \tag_mc_end:
- }
- \tag_struct_end:
- }
-}
-
-
-
-\cs_new_protected:Npn \@@_tag_dollardollar_display:nn #1#2 {
- \@@_process:nn {#1} {#2}
- \@kernel@close@P
- \@kernel@math@begin
-% \skip_set:Nn \belowdisplayskip {-\belowdisplayskip}
-% \skip_set:Nn \belowdisplayshortskip {-\belowdisplayshortskip}
-% \int_set:Nn \postdisplaypenalty {10000}
-%%
-% \group_insert_after:N \@@_tag_dollardollar_display_end:
-}
-
-\cs_new_protected:Npn \@@_tag_dollardollar_display_end: {
-% \typeout{== tag dollarldollar display end}
-% \ShowTagging{struct-stack}
- \tagpdfparaOff
- \para_raw_end:
- \tagpdfparaOn
- \l_@@_tmpa_skip \lastskip
- \@kernel@math@end
- \penalty \postdisplaypenalty
+\cs_new_protected:Npn \@@_tag_dollardollar_display_end:
+ {
+ % \typeout{== tag dollarldollar display end}
+ % \ShowTagging{struct-stack}
+ \para_raw_end:
% \end{macrocode}
-% This reinserts the below display skips. It must be doubled to
-% get the right amount:
+% TODO why is that needed? where is para-tagging disabled?
% \begin{macrocode}
- \skip_vertical:n { -\l_@@_tmpa_skip * 2 }
-%
+ \tagpdfparaOn
+% \end{macrocode}
+% The \cs{postdisplaypenalty} was temporarily set to 10000 inside
+% the display and the \cs{belowdisplayskip} and the
+% \cs{belowdisplayshortskip} was negated, so whatever was inserted
+% it should have been a negative skip. Whatever skip was added we
+% pick it ups value up here, so that we can correct the spacing
+% after the tagging code was inserted.
+% \begin{macrocode}
+ \l_@@_tmpa_skip \lastskip
+ \tag_socket_use:n{math/display/formula/end}
+% \end{macrocode}
+% Now we add a skip without indroducing a page break possibility,
+% that should bring the current vertical position back to the point
+% where \TeX{} would add the penalty and the \enquote{below skip}.
+% \changes{v0.6f}{2024-09-30}{Correct logic for inserting below skips
+% after displays (tagging/721)}
+% \begin{macrocode}
+ \nobreak
+ \skip_vertical:n { -\l__math_tmpa_skip } % remove the negative belowdisplayskip
+% \end{macrocode}
+% Then we finally add the real stuff:
+% \begin{macrocode}
+ \penalty \postdisplaypenalty
+ \skip_vertical:n { -\l__math_tmpa_skip } % insert the correct skip
\@doendpe % this has no \end{...} to take care of it
}
@@ -410,13 +2039,13 @@
{
\tl_if_blank:nF {#1}
{
- \@@_process:nn { math } {#1}
$ #1 $
}
\bool_set_false:N \l_@@_collected_bool
}
% \end{macrocode}
% \end{macro}
+%
% \begin{macro}{\@@_grab_eqn:w}
% For the most common use of \cs{[}/\cs{]}: turn into an environment.
% \begin{macrocode}
@@ -429,6 +2058,164 @@
% \end{macrocode}
% \end{macro}
%
+% \subsection{Token-by-token inline grabbing}
+%
+% Grabbing inline math token-by-token is more involved. The mechanism here
+% is essentially a simplified version of that originally seen in
+% \pkg{collcell} and refined in \pkg{siunitx}. We make use of the fact that
+% in math mode spaces are ignored, so we have to deal with only \texttt{N}-type
+% tokens and groups. Furthermore, there is no need to look inside groups, so
+% the only special cases are a small selection of \texttt{N}-type tokens.
+%
+% \begin{variable}{\l_@@_grabbed_tl}
+% For collection of the material piecewise.
+% \begin{macrocode}
+\tl_new:N \l_@@_grabbed_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_grab_env_int}
+% Needed to count up the number of nested environments encountered.
+% \begin{macrocode}
+\int_new:N \l_@@_grab_env_int
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\@@_grab_dollar_loop:}
+% \begin{macro}{\@@_grab_loop:}
+% The lead-off here establishes a group: we need that as we will have to
+% be careful in the way \tn{cr} is handled and ensure this is only
+% manipulated whilst grabbing. The main loop is then started.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_grab_dollar_loop:
+ {
+ \group_begin:
+ \tl_clear:N \l_@@_grabbed_tl
+ \@@_grab_loop:
+ }
+\cs_new_protected:Npn \@@_grab_loop:
+ {
+ \peek_remove_spaces:n
+ {
+ \peek_meaning:NTF \c_group_begin_token
+ { \@@_grab_loop_group:n }
+ { \@@_grab_loop_token:N }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_grab_loop_group:n}
+% \begin{macro}{\@@_grab_loop_store:n}
+% Handling of grabbed groups is pretty easy.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_grab_loop_group:n #1
+ { \@@_grab_loop_store:n { {#1} } }
+\cs_new_protected:Npn \@@_grab_loop_store:n #1
+ {
+ \tl_put_right:Nn \l_@@_grabbed_tl {#1}
+ \@@_grab_loop:
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_grab_loop_token:N}
+% \begin{macro}
+% {
+% \@@_grab_loop_$: ,
+% \@@_grab_loop_\\: ,
+% \@@_grab_loop_\begin: ,
+% \@@_grab_loop_\end: ,
+% \@@_grab_loop_\ignorespaces: ,
+% \@@_grab_loop_\unskip: ,
+% \@@_grab_loop_\textonly@unskip:
+% }
+% Filter out the special cases: for performance reasons, use a hash table
+% approach rather than a loop (\emph{cf.}~\pkg{collcell}).
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_grab_loop_token:N #1
+ {
+ \cs_if_exist_use:cF
+ { @@_grab_loop_ \token_to_str:N #1 : }
+ { \@@_grab_loop_store:n {#1} }
+ }
+\cs_new_protected:cpn { @@_grab_loop_ \token_to_str:N $ : }
+ { \@@_grab_loop_end: }
+\cs_new_protected:cpn { @@_grab_loop_ \token_to_str:N \\ : }
+ {
+ \int_compare:nNnTF \l_@@_grab_env_int = 0
+ { \@@_grab_loop_newline: }
+ { \@@_grab_loop_store:n { \\ } }
+ }
+% \end{macrocode}
+% In contrast to \pkg{collcell}, nesting is tracked by counting
+% \cs{begin}/\cs{end} pairs: this is needed in case there is a tabular-like
+% construct containing |\\| inside a cell. As a result, the end-of-tabular
+% can be detected without checking the name argument: if \cs{end} is
+% encountered at nesting level~0, we've hit the end of a cell. In that case,
+% end the row and leave the environment to clean up.
+% \begin{macrocode}
+\cs_new_protected:cpn { @@_grab_loop_ \token_to_str:N \begin : }
+ {
+ \int_incr:N \l_@@_grab_env_int
+ \@@_grab_loop_store:n { \begin }
+ }
+\cs_new_protected:cpn { @@_grab_loop_ \token_to_str:N \end : }
+ {
+ \int_compare:nNnTF \l_@@_grab_env_int = 0
+ {
+ \@@_grab_loop_newline:
+ \end
+ }
+ {
+ \int_decr:N \l_@@_grab_env_int
+ \@@_grab_loop_store:n { \end }
+ }
+ }
+\tl_map_inline:nn { \ignorespaces \unskip \textonly@unskip }
+ {
+ \cs_new_protected:cpn { @@_grab_loop_ \token_to_str:N #1 : }
+ { \@@_grab_loop: }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_grab_loop_newline:}
+% To allow collection of tokens in the part of the \tn{halign} template after
+% |#|, we need \TeX{} to see the primitive with the loop token in the right
+% place. That is done by re-defining \tn{cr} at present. Ideally there would
+% be a socket in the definition of \texttt{tabular}, etc., to handle this:
+% there is also the need to examine in interaction with \pkg{longtable}, which
+% also redefines \tn{cr}.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_grab_loop_newline:
+ {
+ \if_false: { \fi:
+ \cs_set_protected:Npn \cr
+ {
+ \@@_grab_loop:
+ \tex_cr:D
+ }
+ \if_false: } \fi:
+ \\
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_grab_loop_end:}
+% Clean up and pass on.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_grab_loop_end:
+ {
+ \exp_args:NNV \group_end:
+ \@@_grab_dollar:n \l_@@_grabbed_tl
+ }
+% \end{macrocode}
+% \end{macro}
+%
% \subsection{Marking math environments}
%
% A general mechanism for math mode environments that do not grab their
@@ -463,7 +2250,7 @@
% \begin{macro}{\math_register_env:n}
% \begin{macro}{\RegisterMathEnvironment}
% Set up to capture environment content and make available.
-%
+%
% \begin{macrocode}
\cs_new_protected:Npn \math_register_env:nn #1#2
{
@@ -472,15 +2259,8 @@
\cs_gset_eq:cc { @@_env_ #1 _begin: } {#1}
\cs_gset_eq:cc { @@_env_ #1 _end: } { end #1 }
%
- \ExpandArgs { nnx } \RenewDocumentEnvironment {#1} { b }
+ \ExpandArgs { nne } \RenewDocumentEnvironment {#1} { b }
{
-% \bool_set_true:N \exp_not:N \l_@@_collected_bool
-% \cs_if_exist:cTF { @@_env #1 _aux: }
-% {
-% \exp_not:c { @@_env #1 _aux: }
-% ####1 \exp_not:N \@@_env_end: {#1}
-% }
-% { \exp_not:N \@@_process:nn {#1} {####1} }
\exp_not:N \bool_if:NTF \exp_not:N \l_@@_collected_bool
{
% \typeout{===>B1}
@@ -490,34 +2270,22 @@
\cs_if_exist:cTF { @@_env #1 _aux: }
{
\exp_not:c { @@_env #1 _aux: }
- ####1 \exp_not:N \@@_env_end: {#1}
+ ##1 \exp_not:N \@@_env_end: {#1}
}
- { \exp_not:N \@@_process:nn {#1} {####1} }
+ { \exp_not:N \@@_process:nn {#1} {##1} }
\exp_not:n { \@kernel@math@registered@begin }
\bool_set_true:N \exp_not:N \l_@@_collected_bool
}
-% \exp_not:N \tracingall
+% \exp_not:N \tracingall
\exp_not:c { @@_env_ #1 _begin: }
- ####1
+ ##1
\exp_not:c { @@_env_ #1 _end: }
-% \exp_not:c { @@_env_ #1 _end: }
% \exp_not:N \tracingnone
-% \exp_not:n { \@kernel@math@registered@end }
}
- {
- }
+ {
+ }
}
-\cs_set_protected:Npn \__cs_tmp:w #1
- {
- \group_begin:
- \exp_args:No \__cs_generate_internal_variant:n
- { \tl_to_str:n {#1} }
- \group_end:
- }
-\__cs_tmp:w { nnxx }
-
-
\cs_new_protected:Npn \math_register_halign_env:nn #1#2
{
\tl_set:Nn \l_@@_env_name_tl {#1}
@@ -525,15 +2293,8 @@
\cs_gset_eq:cc { @@_env_ #1 _begin: } {#1}
\cs_gset_eq:cc { @@_env_ #1 _end: } { end #1 }
%
- \ExpandArgs { nnxx } \RenewDocumentEnvironment {#1} { b }
+ \ExpandArgs { nnee } \RenewDocumentEnvironment {#1} { b }
{
-% \bool_set_true:N \exp_not:N \l_@@_collected_bool
-% \cs_if_exist:cTF { @@_env #1 _aux: }
-% {
-% \exp_not:c { @@_env #1 _aux: }
-% ####1 \exp_not:N \@@_env_end: {#1}
-% }
-% { \exp_not:N \@@_process:nn {#1} {####1} }
\exp_not:N \bool_if:NTF \exp_not:N \l_@@_collected_bool
{
% \typeout{===>B1}
@@ -543,23 +2304,24 @@
\cs_if_exist:cTF { @@_env #1 _aux: }
{
\exp_not:c { @@_env #1 _aux: }
- ####1 \exp_not:N \@@_env_end: {#1}
+ ##1 \exp_not:N \@@_env_end: {#1}
}
- { \exp_not:N \@@_process:nn {#1} {####1} }
+ { \exp_not:N \@@_process:nn {#1} {##1} }
\exp_not:n { \@kernel@math@registered@begin }
\bool_set_true:N \exp_not:N \l_@@_collected_bool
}
-% \exp_not:N \tracingall
+% \exp_not:N \tracingall
\exp_not:c { @@_env_ #1 _begin: }
- ####1
-% \exp_not:c { @@_env_ #1 _end: }
+ ##1
% \exp_not:N \tracingnone
}
- {
- \exp_not:c { @@_env_ #1 _end: }
- }
+ {
+ \exp_not:c { @@_env_ #1 _end: }
+ }
}
-
+% \end{macrocode}
+% TODO: the following command is neither documented nor used. Is is needed?
+% \begin{macrocode}
\cs_new_protected:Npn \math_register_odd_env:nn #1#2
{
\tl_set:Nn \l_@@_env_name_tl {#1}
@@ -567,7 +2329,7 @@
\cs_gset_eq:cc { @@_env_ #1 _begin: } {#1}
\cs_gset_eq:cc { @@_env_ #1 _end: } { end #1 }
%
- \ExpandArgs { nnxx } \RenewDocumentEnvironment {#1} { b }
+ \ExpandArgs { nnee } \RenewDocumentEnvironment {#1} { b }
{
\exp_not:N \bool_if:NTF \exp_not:N \l_@@_collected_bool
{
@@ -578,19 +2340,19 @@
\cs_if_exist:cTF { @@_env #1 _aux: }
{
\exp_not:c { @@_env #1 _aux: }
- ####1 \exp_not:N \@@_env_end: {#1}
+ ##1 \exp_not:N \@@_env_end: {#1}
}
- { \exp_not:N \@@_process:nn {#1} {####1} }
+ { \exp_not:N \@@_process:nn {#1} {##1} }
\exp_not:n { \@kernel@math@registered@begin }
\bool_set_true:N \exp_not:N \l_@@_collected_bool
}
-% \exp_not:N \tracingall
+% \exp_not:N \tracingall
\exp_not:c { @@_env_ #1 _begin: }
- ####1
+ ##1
}
{
\exp_not:c { @@_env_ #1 _end: }
-% needed if we don't have $$...$$
+% needed if we don't have $$...$$
% \exp_not:n { \typeout{---> @kernel@math@registered@end }}
\exp_not:n { \@kernel@math@registered@end }
}
@@ -614,7 +2376,7 @@
\cs_new:Npn \@kernel@math@registered@begin {
-% \ShowTagging{struct-stack}
+% \ShowTagging{struct-stack}
%\typeout{==>A1}\ShowTagging{struct-stack,mc-current}
\mode_if_vertical:TF
{
@@ -623,19 +2385,21 @@
% { \__block_list_beginpar_vmode: }
%
% \typeout{==>~ at:~ \g__tag_struct_tag_tl}
-%
- \exp_args:Noo\str_if_eq:nnF \g__tag_struct_tag_tl { \l__tag_para_main_tag_tl } % needs correction!
+%
+ \tag_if_active:T
+ {
+ \exp_args:Noo\str_if_eq:nnF \g__tag_struct_tag_tl { \l__tag_para_main_tag_tl } % needs correction!
{
% \typeout{==>A2}
\__block_beginpar_vmode:
} % needs correction!
+ }
}
{
% \typeout{==>A3}
- \@kernel@close@P
-% \tagmcend % needs correction!
+ \__tag_tool_close_P:
}
- \@kernel@math@begin
+ \socket_use:nn{tagsupport/math/display/formula/begin}{}
\tagpdfparaOff
% \typeout{==>MC1}\ShowTagging{mc-current}
}
@@ -644,13 +2408,14 @@
% \typeout{==>MC2}\ShowTagging{mc-current}
\para_raw_end:
\tagpdfparaOn
- \@kernel@math@end
+ \socket_use:n{tagsupport/math/display/formula/end}
% \typeout{==>MC3}\ShowTagging{mc-current}
\@endpetrue
}
-
+
\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}
@@ -660,12 +2425,12 @@
%
% \begin{macro}{\@@_env_forward:w}
% \begin{macrocode}
-\cs_new_protected:Npn \@@_env_forward:w #1 \@@_env_end: #2
+\cs_new_protected:Npn \@@_env_forward:w #1 \@@_env_end: #2
{ \@@_process:nn {#2} {#1} }
% \end{macrocode}
% \end{macro}
-%
-% \subsection{Document commands}
+%
+% \subsection{Document commands}
%
% \car*{Add one more here: \texttt{displaymath}, which
% is equivalent to \cs{[} , \cs{]}\\
@@ -692,9 +2457,9 @@
% at the moment register_env can only do display math
% \math_register_env:n { math }
\RenewDocumentEnvironment{math} {b}{$#1$}{}
-% and this one doesn't work either
+% and this one doesn't work either
% \math_register_env:n { displaymath }
- \RenewDocumentEnvironment{displaymath} {b}{\[#1\]}{}
+ \RenewDocumentEnvironment{displaymath} {b}{\[#1\]}{}
}
% \end{macrocode}
% \end{macro}
@@ -737,29 +2502,31 @@
{
\cs_gset_protected:Npn \[ % \]
{
- \bool_if:NTF \l_@@_collected_bool
- { \begin { equation* } }
- { \@@_grab_eqn:w }
+ \@@_grab_eqn:w
+ % \bool_if:NTF \l_@@_collected_bool
+% { \begin { equation* } }
+% { \@@_grab_eqn:w }
} % \[
\cs_gset_protected:Npn \]
{
- \bool_if:NTF \l_@@_collected_bool
- { \end{ equation* } }
- { \@badmath }
+ \@badmath
+% \bool_if:NTF \l_@@_collected_bool
+% { \end{ equation* } }
+% { \@badmath }
}
}
% \end{macrocode}
% \end{macro}
-%
+%
%
% \begin{macro}{\ensuremath}
% A bit of nesting fun to make sure we collect only if required.
% \fmi{why does ensuremath need handling at all?}
-%
-% \car{Indeed! Currently, this is setup to process the math that
-% it has anyways already captured as its argument; thus it is more
+%
+% \car{Indeed! Currently, this is setup to process the math that
+% it has anyways already captured as its argument; thus it is more
% efficient than leaving the capture to be repeated by the \cs{everymath}}
-%
+%
% \begin{macrocode}
%\cs_gset_protected:Npn \ensuremath #1
% {
@@ -786,47 +2553,6 @@
% have macro control.
% \begin{macrocode}
-\tl_new:N\tmpmathcontent
-
-
-\def\@kernel@math@begin {
-% \typeout{==>~math~begin}
-% needs different handling if we support nesting
- \tl_gset:Nx\tmpmathcontent
- {
- LaTeX~ formula~ starts~
- \exp_not:N\begin{\g_@@_grabbed_env_tl}
- \space
- \exp_not:V\g_@@_grabbed_math_tl
- \space
- \exp_not:N\end{\g_@@_grabbed_env_tl}
- \space LaTeX~ formula~ ends~
- }
- \tagstructbegin{tag=Formula,
- AFinline-o=\tmpmathcontent,
- title-o=\g_@@_grabbed_env_tl,
- actualtext=\tmpmathcontent
-% alt=\tmpmathcontent
- }
-% inner formula if multiple parts (not really implemented yet)
- \grabaformulapartandstart
-% the above does:
-% \tagstructbegin{tag=Formula}\tagmcbegin{}
-% or just
-% \tagmcbegin{}
-}
-\def\@kernel@math@end {
-% \typeout{==>~math~end}
-% \ShowTagging{struct-stack}
- \tagmcend
- \if@subformulas
- \tagstructend
- \else
- \fi
- \tagstructend
-% \ShowTagging{struct-stack}
-}
-
\exp_args:No \tex_everymath:D
{
\tex_the:D \tex_everymath:D
@@ -841,24 +2567,21 @@
{
\tex_the:D \tex_everydisplay:D
\iftrue % this may have to be a settable flag!
-% {
% \typeout{==>~ in~ everydisplay}
% \end{macrocode}
-% flipping the \cs{belowdisplay} values is done so that we get (assumption)
-% a negative skip and not make the page bigger then we take that out,
-% then we add the tagging code (in \cs{@@_tag_dollardollar_display_end} ) and
-% then we put a real \cs{postdisplaypenalty} in and
-% the right skip (of which we don't know if it is short or a
-% normal \cs{belowdisplayskip}). This might need some refinement if that skip
-% is actually negative from the start
+% flipping the \cs{belowdisplay} values is done so that we get (assumption)
+% a negative skip and not make the page bigger then we take that out,
+% then we add the tagging code (in \cs{@@_tag_dollardollar_display_end} ) and
+% then we put a real \cs{postdisplaypenalty} in and
+% the right skip (of which we don't know if it is short or a
+% normal \cs{belowdisplayskip}). This might need some refinement if that skip
+% is actually negative from the start
% (not sure it ever is and is worth bothering about)
% \begin{macrocode}
\skip_set:Nn \belowdisplayskip {-\belowdisplayskip}
\skip_set:Nn \belowdisplayshortskip {-\belowdisplayshortskip}
\int_set:Nn \postdisplaypenalty {10000}
-%
\group_insert_after:N \@@_tag_dollardollar_display_end:
-% }
\fi
\bool_if:NF \l_@@_collected_bool
{
@@ -876,14 +2599,27 @@
\math_register_env:n { eqnarray* }
% \end{macrocode}
%
-% Places where math mode is (ab)used.
+% Tabulars currently contain a \$ that shouldn't trigger math
+% tagging.
% \begin{macrocode}
-\clist_map_inline:nn
- { tabular }
- {
- \AddToHook{ env / #1 / begin }
- { \bool_set_true:N \l_@@_collected_bool }
- }
+\RequirePackage{array}
+\tl_if_in:NnT\@tabular{$}
+ {
+ \def\@tabular{%
+ \leavevmode
+ \UseTaggingSocket{tbl/hmode/begin}%
+ \hbox \bgroup
+ \bool_set_true:N \l_@@_collected_bool
+ $
+ \bool_set_false:N \l_@@_collected_bool
+ \col@sep\tabcolsep \let\d@llarbegin\begingroup
+ \let\d@llarend\endgroup
+% \end{macrocode}
+% A proper switching mechanism is needed: for the present, do directly.
+% \begin{macrocode}
+ \cs_set_protected:Npn \@@_grab_dollar:w { \@@_grab_dollar_loop: }
+ \@tabarray}
+ }
% \end{macrocode}
%
% \begin{macro}{\@@_m@th:, \m@th}
@@ -899,6 +2635,20 @@
% \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
+ {
+ \bool_set_true:N\l_@@_collected_bool
+ }
+\tl_gput_right:Nn\@kernel@after@begindocument
+ {
+ \bool_set_false:N\l_@@_collected_bool
+ }
+% \end{macrocode}
+%
% \subsection{Modifying \pkg{amsmath}}
%
% \begin{macro}{\@@_amsmath_align@:nn}
@@ -934,7 +2684,7 @@
$$\ignorespacesafterend
}
% \end{macrocode}
-%
+%
% \begin{macrocode}
\def\common@align@ending {
\math@cr \black@\totwidth@
@@ -1003,13 +2753,15 @@
% \end{macrocode}
% Also for "false?"
% \begin{macrocode}
-\def\measuring@true{\let\ifmeasuring@\iftrue\tag_stop:}
+\def\measuring@true{\let\ifmeasuring@\iftrue\tag_suspend:n{\measuring}}
% \end{macrocode}
%
% \begin{macrocode}
-%
+%
\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 {flalign}{}
\math_register_halign_env:nn {flalign*}{}
\math_register_halign_env:nn {gather}{}
@@ -1032,44 +2784,8 @@
\fi
}
% \end{macrocode}
-%
-% \begin{macrocode}
- \def\intertext@{%
- \def\intertext##1{%
- \ifvmode\else\\\@empty\fi
- \noalign{%
-% we have to flip the sign on the skip because we flipped it on the outside
- \penalty\postdisplaypenalty\vskip-\belowdisplayskip
- \vbox{
-% \end{macrocode}
-% Stop tagging when measuring:
-% \begin{macrocode}
- \ifmeasuring@\tag_stop:\fi
- \normalbaselines
- \ifdim\linewidth=\columnwidth
- \else \parshape\@ne \@totalleftmargin \linewidth
- \fi
-% \end{macrocode}
-% End the previous mc:\fmi{if we use 2 levels of formulas this would
-% need changing}
-% \begin{macrocode}
- \tag_mc_end_push:
-% \end{macrocode}
-% We are already in a par so we change now to Span:\fmi{not true any longer}
-% \begin{macrocode}
- \tagpdfsetup{paratag=P}%
- \tagpdfparaOn
- \noindent\ignorespaces##1\par
-% \end{macrocode}
-% Restart the MC
-% \begin{macrocode}
- \tag_mc_begin_pop:n{}}%
- \penalty\predisplaypenalty\vskip\abovedisplayskip%
- }%
- }
- }
-% \end{macrocode}
-%
+%
+%
% \begin{macrocode}
\@namedef{math@cr @ @ @ gather}{%
\ifst@rred\nonumber\fi
@@ -1083,7 +2799,7 @@
\cr
}
% \end{macrocode}
-%
+%
% \begin{macrocode}
\@namedef{math@cr @ @ @ align}{%
\ifst@rred\nonumber\fi
@@ -1104,7 +2820,7 @@
\cr
}
% \end{macrocode}
-%
+%
% \begin{macrocode}
\def\restore@math@cr{\@namedef{math@cr @ @ @}{
%
@@ -1113,7 +2829,7 @@
\cr}}
\restore@math@cr
% \end{macrocode}
-%
+%
% \begin{macrocode}
}
% \end{macrocode}
@@ -1125,8 +2841,17 @@
%
%
-% \begin{macro}{}
-%
+% \begin{macro}{\@@_split_at_nl:NN}
+% This splits grabbed math at newlines.
+%
+% \begin{macrocode}
+\cs_new:Npn \@@_split_at_nl:NN #1#2 {
+ \tl_set:Nf \l_@@_tmpa_tl {
+ \exp_after:wN \@@_split_at_nl_first:w #1 \\ \q_nil \\ \s_stop }
+ \exp_after:wN \@@_split_at_nl_aux:nnNN \l_@@_tmpa_tl #1 #2
+}
+% \end{macrocode}
+% and the auxiliary commands
% \begin{macrocode}
\cs_new:Npn \@@_split_at_nl_first:w #1 \\ #2 \\ #3 \s_stop
{
@@ -1137,8 +2862,15 @@
#2 \\ #3 \s_stop
}
}
-\cs_new:Npn \@@_split_chk_if_begin:ww #1 \begin #2 #3 \s_mark
- #4 \\ \q_nil \\ \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
+ #1 \begin #2 #3 \s_mark #4 \\ \q_nil \\ \s_stop
{
\quark_if_nil:nTF {#2}
{ {#1} {#4} }
@@ -1148,7 +2880,9 @@
{ } { 1 }
}
}
+
\cs_new:Npn \@@_split_cleanup_begin_q_nil:w #1 \begin \q_nil {#1}
+
\cs_new:Npn \@@_split_collect_one_end:w #1 \end #2 #3 \s_stop #4 #5
{
\exp_args:Nf \@@_split_check_count_begins:nnnn
@@ -1157,14 +2891,16 @@
}
\cs_new:Npn \@@_split_count_begins:n #1
{ \int_eval:n { 0 \@@_split_count_begins:w #1 \begin \q_nil } }
+
\cs_new:Npn \@@_split_count_begins:w #1 \begin #2
{ \quark_if_nil:nF {#2} { +1 \@@_split_count_begins:w } }
+
\cs_new:Npn \@@_split_check_count_begins:nnnn #1 #2 #3 #4
{
\int_compare:nNnTF {#1} = {#2}
{
\exp_last_unbraced:Nf \@@_split_final_cleanup:nn
- { \split:n { \@@_split_guard:n {#3} #4 } }
+ { \@@_split:n { \@@_split_guard:n {#3} #4 } }
}
{
\exp_args:No \use_ii_i:nn
@@ -1184,40 +2920,28 @@
{ \exp_end: { #4 #1 } }
{ \@@_split_final_cleanup:w #3 \s_mark { #4 #1 #2 } }
}
-\NewDocumentCommand \splitnl { mm +m }
- {
- \tl_set:Nf \l_tmpa_tl { \split:n {#3} }
- \show \l_tmpa_tl
- \exp_after:wN \__splitnl_aux:nnNN \l_tmpa_tl #1 #2
- }
-
-\cs_new:Npn \split:n #1 {
+\cs_new:Npn \@@_split:n #1 {
\@@_split_at_nl_first:w #1 \\ \q_nil \\ \s_stop }
-\cs_new:Npn \@@_split_at_nl:NN #1#2 {
- \tl_set:Nf \l_tmpa_tl {
- \exp_after:wN \@@_split_at_nl_first:w #1 \\ \q_nil \\ \s_stop }
- \exp_after:wN \@@_split_at_nl_aux:nnNN \l_tmpa_tl #1 #2
-}
-
-\cs_new_protected:Npn \@@_split_at_nl_aux:nnNN #1 #2 #3 #4
- {
- \tl_gset:Nn #4 {#1}
- \tl_gset:Nn #3 {#2}
-}
-
+% this looks unused.
+%\NewDocumentCommand \splitnl { mm +m }
+% {
+% \tl_set:Nf \l_@@_tmpa_tl { \split:n {#3} }
+% \show \l_@@_tmpa_tl
+% \exp_after:wN \__splitnl_aux:nnNN \l_@@_tmpa_tl #1 #2
+% }
% \end{macrocode}
% \end{macro}
%
%
% \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}
@@ -1233,9 +2957,11 @@
\edef\resulttitle{\g_@@_grabbed_env_tl\space (part)}
\tagstructbegin{tag=Formula,
% \end{macrocode}
-% For now we don't put anything in /alt or /ActualText on subformulas
+% For now we don't put real content in /alt or /ActualText on subformulas
+% but we add a short text to satisfy the pdf/ua-2 validator
% \begin{macrocode}
% alt=\result,
+ alt = subformula,
title-o=\resulttitle
}
}
@@ -1273,7 +2999,7 @@
%
\tl_if_empty:NF \g_@@_grabbed_math_tl
{
- \tagmcend
+ \tagmcend
\tagstructend
\grabaformulapartandmayberestart
}
@@ -1289,20 +3015,16 @@
% \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}
-%
-% \end{macrocode}
%
% \begin{macrocode}
%</kernel>
@@ -1310,4 +3032,4 @@
%
% \Finale
%
-%
+%
diff --git a/macros/latex/required/latex-lab/latex-lab-math.pdf b/macros/latex/required/latex-lab/latex-lab-math.pdf
index e65f6cd1bb..fb2a43437f 100644
--- a/macros/latex/required/latex-lab/latex-lab-math.pdf
+++ b/macros/latex/required/latex-lab/latex-lab-math.pdf
Binary files differ
diff --git a/macros/latex/required/latex-lab/latex-lab-mathpkg.dtx b/macros/latex/required/latex-lab/latex-lab-mathpkg.dtx
index 14d8e94362..31e7d31ef6 100644
--- a/macros/latex/required/latex-lab/latex-lab-mathpkg.dtx
+++ b/macros/latex/required/latex-lab/latex-lab-mathpkg.dtx
@@ -2,7 +2,7 @@
%
%% File: latex-lab-mathpkg.dtx
%
-% Copyright (C) 2022,2023 The LaTeX Project
+% Copyright (C) 2022-2024 The LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -68,15 +68,8 @@
\ProvidesFile{latex-lab-mathpkg.ltx}
[2023-01-05 v0.1a mathpkg adaptions]
% \end{macrocode}
-% \subsection{Tagpdf support}
-% To make the code independent from tagging being loaded and active
-% we load the \pkg{tagpdf-base} package:
-%
-% \begin{macrocode}
-\RequirePackage{tagpdf-base}
-% \end{macrocode}
-%
%
+% \subsection{breqn}
% \begin{macrocode}
\AddToHook{package/breqn/after}{
\RegisterMathEnvironment{dmath}
@@ -86,6 +79,7 @@
}
% \end{macrocode}
%
+% \subsection{cases}
% Force loading of \pkg{amsmath} before \pkg{cases}.
% \begin{macrocode}
\AddToHook {package/cases/before}{\RequirePackage{amsmath}}
@@ -94,6 +88,29 @@
}
% \end{macrocode}
%
+% \subsection{bm}
+% Similar to the amsbsy code in latex-lab-amsmath for \cs{pmb} we need to mark up
+% copies as artifact:
+%
+% \begin{macrocode}
+\ExplSyntaxOn
+\AddToHook{package/bm/after}
+ {
+ \def\bm@pmb@@@@#1#2#3{{%
+ \hbox_set:Nn\l_@@_tmpa_box{$\m@th#1#3$}%
+ \dimen@#2\wd\tw@
+ \rlap{\box_use:N\l_@@_tmpa_box}%
+ \tag_mc_end:\tag_mc_begin:n{artifact}
+ \tag_mc_reset_box:N\l_@@_tmpa_box
+ \kern\dimen@
+ \raise1.5\dimen@\rlap{\box_use:N\l_@@_tmpa_box}%
+ \kern\dimen@
+ \box_use_drop:N\l_@@_tmpa_box
+ \tag_mc_end:\tag_mc_begin:n{}%
+ }}
+ }
+\ExplSyntaxOff
+% \end{macrocode}
% \begin{macrocode}
%</kernel>
% \end{macrocode}
diff --git a/macros/latex/required/latex-lab/latex-lab-mathpkg.pdf b/macros/latex/required/latex-lab/latex-lab-mathpkg.pdf
index 6669de2eb6..d16a507e01 100644
--- a/macros/latex/required/latex-lab/latex-lab-mathpkg.pdf
+++ b/macros/latex/required/latex-lab/latex-lab-mathpkg.pdf
Binary files differ
diff --git a/macros/latex/required/latex-lab/latex-lab-mathtools.dtx b/macros/latex/required/latex-lab/latex-lab-mathtools.dtx
index c3f43243b1..ed8b6e467e 100644
--- a/macros/latex/required/latex-lab/latex-lab-mathtools.dtx
+++ b/macros/latex/required/latex-lab/latex-lab-mathtools.dtx
@@ -2,7 +2,7 @@
%
%% File: latex-lab-mathtools.dtx
%
-% Copyright (C) 2022,2023 The LaTeX Project
+% Copyright (C) 2022-2024 The LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -18,12 +18,14 @@
%
% for those people who are interested or want to report an issue.
%
+\def\ltlabmathtoolsdate{2024-09-18}
+\def\ltlabmathtoolsversion{0.80a}
%<*driver>
\documentclass{l3doc}
\EnableCrossrefs
\CodelineIndex
\begin{document}
- \DocInput{latex-lab-amsmath.dtx}
+ \DocInput{latex-lab-mathtools.dtx}
\end{document}
%</driver>
%
@@ -32,7 +34,7 @@
%
% \title{The \texttt{latex-lab-mathtools} code\thanks{}}
% \author{\LaTeX{} Project}
-%
+% \date{v\ltlabmathtoolsversion\ \ltlabmathtoolsdate}
% \maketitle
%
% \newcommand\fmi[1]{\begin{quote} TODO: \itshape #1\end{quote}}
@@ -66,7 +68,7 @@
% \subsection{File declaration}
% \begin{macrocode}
\ProvidesFile{latex-lab-mathtools.ltx}
- [2023-01-05 v0.1a mathtools adaptions]
+ [2024-07-13 v0.1a mathtools adaptions]
% \end{macrocode}
% \subsection{Tagpdf support}
% To make the code independent from tagging being loaded and active
@@ -109,7 +111,7 @@
\def\intertext##1{%
\ifvmode\else\\\@empty\fi
\noalign{%
- \penalty\postdisplaypenalty\vskip\belowdisplayskip
+ \penalty\postdisplaypenalty\vskip-\belowdisplayskip
\vskip-\lineskiplimit % CCS
\vskip\normallineskiplimit % CCS
\vskip\l_MT_above_intertext_sep
@@ -117,7 +119,7 @@
% \end{macrocode}
% Stop tagging when measuring:
% \begin{macrocode}
- \ifmeasuring@\tag_stop:\fi
+ \ifmeasuring@\tag_suspend:n{\measuring}\fi
\normalbaselines
\ifdim
\ifdim\@totalleftmargin=\z@
@@ -135,7 +137,7 @@
% \end{macrocode}
% We are already in a par so we change now to Span:
% \begin{macrocode}
- \tagpdfsetup{paratag=Span}
+ \tagpdfsetup{para/tag=Span}
\noindent\ignorespaces##1\par
% \end{macrocode}
% Restart the MC
@@ -156,7 +158,7 @@
\noalign{%
\penalty\postdisplaypenalty\vskip\abovedisplayshortskip
\vbox{%
- \ifmeasuring@\tag_stop:\fi
+ \ifmeasuring@\tag_suspend:n{\measuring}\fi
\normalbaselines
\MH_if_dim:w
\MH_if_dim:w \@totalleftmargin=\z@
@@ -169,7 +171,8 @@
\parshape\@ne \@totalleftmargin \linewidth
\MH_fi:
\tag_mc_end_push:
- \tagpdfsetup{paratag=Span}
+ \tagpdfsetup{para/tag=Span}
+ \tagpdfparaOn
\noindent\ignorespaces#1\par
\tag_mc_begin_pop:n{}}
\penalty\predisplaypenalty\vskip\abovedisplayshortskip%
@@ -184,7 +187,7 @@
\vskip\normallineskiplimit
\vskip\l_MT_above_shortintertext_sep
\vbox{%
- \ifmeasuring@\tag_stop:\fi
+ \ifmeasuring@\tag_suspend:n{\measuring}\fi
\normalbaselines
\MH_if_dim:w
\MH_if_dim:w \@totalleftmargin=\z@
@@ -197,7 +200,11 @@
\parshape\@ne \@totalleftmargin \linewidth
\MH_fi:
\tag_mc_end_push:
- \tagpdfsetup{paratag=Span}
+ \tagpdfsetup{para/tag=P}
+% \end{macrocode}
+% Why is it needed to enable paratagging??
+% \begin{macrocode}
+ \tagpdfparaOn
\noindent\ignorespaces#1\par
\tag_mc_begin_pop:n{}}%
\penalty\predisplaypenalty\vskip\abovedisplayshortskip%
diff --git a/macros/latex/required/latex-lab/latex-lab-mathtools.pdf b/macros/latex/required/latex-lab/latex-lab-mathtools.pdf
index e079d79d48..3eb43692cb 100644
--- a/macros/latex/required/latex-lab/latex-lab-mathtools.pdf
+++ b/macros/latex/required/latex-lab/latex-lab-mathtools.pdf
Binary files differ
diff --git a/macros/latex/required/latex-lab/latex-lab-minipage.dtx b/macros/latex/required/latex-lab/latex-lab-minipage.dtx
index 1d3ee828aa..eed595a531 100644
--- a/macros/latex/required/latex-lab/latex-lab-minipage.dtx
+++ b/macros/latex/required/latex-lab/latex-lab-minipage.dtx
@@ -1,6 +1,8 @@
% \iffalse meta-comment
%
-%% File: latex-lab-minipage.dtx (C) Copyright 2023 LaTeX Project
+%% File: latex-lab-minipage.dtx
+%%
+% Copyright (C) 2023-2024 LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -16,8 +18,8 @@
%
% for those people who are interested or want to report an issue.
%
-\def\ltlabminipagedate{2023-10-30}
-\def\ltlabminipageversion{0.81c}
+\def\ltlabminipagedate{2024-09-18}
+\def\ltlabminipageversion{0.81e}
%<*driver>
\documentclass{l3doc}
\EnableCrossrefs
@@ -118,12 +120,18 @@
% \end{macrocode}
% insert the socket
% \begin{macrocode}
- \socket_use:n{tagsupport/minipage/before}% new
+ \UseTaggingSocket{minipage/before}% new
\setbox\@tempboxa\vbox\bgroup
\color@begingroup
\hsize\@tempdima
\textwidth\hsize \columnwidth\hsize
\@parboxrestore
+% \end{macrocode}
+% minipages are perhaps used in environments where the tagging of paragraphs
+% has been altered. So we try to restore this. TODO: this should
+% perhaps be done in \cs{@parboxrestore} directly.
+% \begin{macrocode}
+ \UseTaggingSocket{para/restore}
\def\@mpfn{mpfootnote}\def\thempfn{\thempfootnote}\c@mpfootnote\z@
\socket_assign_plug:nn{fntext/process}{mp}%
\let\@listdepth\@mplistdepth \@mplistdepth\z@
@@ -148,10 +156,10 @@
% As the parbox command is called, we must prevent that it adds its
% additional tagging commands:
% \begin{macrocode}
- \tag_stop:n{minipage}
+ \tag_suspend:n{minipage}
\expandafter\@iiiparbox\@mpargs{\unvbox\@tempboxa}%
- \tag_start:n{minipage}
- \socket_use:n{tagsupport/minipage/after} %new end ...
+ \tag_resume:n{minipage}
+ \UseTaggingSocket{minipage/after} %new end ...
}
% \end{macrocode}
%
@@ -162,8 +170,15 @@
\leavevmode
\@pboxswfalse
\setlength\@tempdima{#4}%
- \socket_use:n{tagsupport/parbox/before}
- \@begin@tempboxa\vbox{\hsize\@tempdima\@parboxrestore#5\@@par}%
+ \UseTaggingSocket{parbox/before}
+ \@begin@tempboxa\vbox{\hsize\@tempdima\@parboxrestore
+% \end{macrocode}
+% parbox are perhaps used in environments where the tagging of paragraphs
+% has been altered. So we try to restore this. TODO: this should
+% perhaps be done in \cs{@parboxrestore} directly.
+% \begin{macrocode}
+ \UseTaggingSocket{para/restore}
+ #5\@@par}%
\ifx\relax#2\else
\setlength\@tempdimb{#2}%
\edef\@parboxto{to\the\@tempdimb}%
@@ -177,7 +192,7 @@
\csname bm@#3\endcsname}%
\if@pboxsw \m@th$\fi
\@end@tempboxa%
- \socket_use:n{tagsupport/parbox/after}
+ \UseTaggingSocket{parbox/after}
}
% \end{macrocode}
%
@@ -189,9 +204,11 @@
\socket_new_plug:nnn{tagsupport/minipage/before}{tag/dflt}
{
% \end{macrocode}
-% As there was a \cs{leavevmode} before that is a P/text open that we have to close.
+% As there was a \cs{leavevmode} before that is a P/text open that we have to close
+% if para tagging is active:
% \begin{macrocode}
- \tag_mc_end_push:\tag_struct_end:
+ \tag_mc_end_push:
+ \bool_if:NT \l__tag_para_bool {\tag_struct_end:}
% \end{macrocode}
% TODO: the P can be further up, we need a proper method to test and handle this.
% \begin{macrocode}
@@ -201,13 +218,25 @@
% similar for the other sockets:
% \begin{macrocode}
\socket_new_plug:nnn{tagsupport/minipage/after}{tag/dflt}
- {\tag_struct_end:\tag_struct_begin:n{tag=\l__tag_para_tag_tl}\tag_mc_begin_pop:n{}}
+ {
+ \tag_struct_end:
+ \bool_if:NT \l__tag_para_bool {\tag_struct_begin:n{tag=\l__tag_para_tag_tl}}
+ \tag_mc_begin_pop:n{}
+ }
\socket_new_plug:nnn{tagsupport/parbox/before}{tag/dflt}
- {\tag_mc_end_push:\tag_struct_end:\tag_struct_begin:n{tag=\l__ltboxes_tag_tl}}
+ {
+ \tag_mc_end_push:
+ \bool_if:NT \l__tag_para_bool {\tag_struct_end:}
+ \tag_struct_begin:n{tag=\l__ltboxes_tag_tl}
+ }
\socket_new_plug:nnn{tagsupport/parbox/after}{tag/dflt}
- {\tag_struct_end:\tag_struct_begin:n{tag=\l__tag_para_tag_tl}\tag_mc_begin_pop:n{}}
+ {
+ \tag_struct_end:
+ \bool_if:NT \l__tag_para_bool {\tag_struct_begin:n{tag=\l__tag_para_tag_tl}}
+ \tag_mc_begin_pop:n{}
+ }
% \end{macrocode}
% Activate the default tagging plug
% \begin{macrocode}
diff --git a/macros/latex/required/latex-lab/latex-lab-minipage.pdf b/macros/latex/required/latex-lab/latex-lab-minipage.pdf
index 3ee22bfc51..7878bcfd34 100644
--- a/macros/latex/required/latex-lab/latex-lab-minipage.pdf
+++ b/macros/latex/required/latex-lab/latex-lab-minipage.pdf
Binary files differ
diff --git a/macros/latex/required/latex-lab/latex-lab-namespace.dtx b/macros/latex/required/latex-lab/latex-lab-namespace.dtx
index 2ec9b0584b..d76dd8d489 100644
--- a/macros/latex/required/latex-lab/latex-lab-namespace.dtx
+++ b/macros/latex/required/latex-lab/latex-lab-namespace.dtx
@@ -1,6 +1,8 @@
% \iffalse meta-comment
%
-%% File: latex-lab-namespace.dtx (C) Copyright 2023 LaTeX Project
+%% File: latex-lab-namespace.dtx
+%%
+% Copyright (C) 2023-2024 LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -24,7 +26,7 @@
% \fi
% \title{Prototype reimplementation of \LaTeXe{}'s role mapping}
% \author{\LaTeX{} Project, initial implementation Ulrike Fischer}
-% \date{v0.8 2023-09-04}
+% \date{v0.8b 2024-07-05}
%
% \maketitle
%
@@ -35,7 +37,7 @@
% \section{Introduction}
%
% This short file collects tag names from the \LaTeX{} namespace and their role mapping used
-% in the latex-lab files. The names and the roles are not necessarly the final ones!
+% in the latex-lab files. The names and the roles are not necessarily the final ones!
%
% Later settings of the same tag overwrite previous settings.
% The syntax of a line is a list of three strings ending with commas:
@@ -60,18 +62,33 @@
% \begin{macrocode}
title, Title, pdf2,
part, Title, pdf2,
+% \end{macrocode}
+% Headings differ in article and book class. This here is for article:
+% \begin{macrocode}
section, H1, pdf2,
subsection, H2, pdf2,
subsubsection,H3, pdf2,
paragraph, H4, pdf2,
subparagraph, H5, pdf2,
+% \end{macrocode}
+% And this here is used in book:
+% \begin{macrocode}
+%chapter, H1, pdf2,
+%section, H2, pdf2,
+%subsection, H3, pdf2,
+%subsubsection, H4, pdf2,
+%paragraph, H5, pdf2,
+%subparagraph, H6, pdf2,
+% \end{macrocode}
+%
+% \begin{macrocode}
list, L, pdf2,
itemize, L, pdf2,
enumerate, L, pdf2,
description, L, pdf2,
quote, BlockQuote,pdf,
quotation, BlockQuote,pdf,
-verbatim, Div, pdf2,
+verbatim, Div, pdf2, % overwritten by block
item, LI, pdf2,
itemlabel, Lbl, pdf2,
itembody, LBody, pdf2,
diff --git a/macros/latex/required/latex-lab/latex-lab-namespace.pdf b/macros/latex/required/latex-lab/latex-lab-namespace.pdf
index d8c4cba427..3792133f44 100644
--- a/macros/latex/required/latex-lab/latex-lab-namespace.pdf
+++ b/macros/latex/required/latex-lab/latex-lab-namespace.pdf
Binary files differ
diff --git a/macros/latex/required/latex-lab/latex-lab-new-or-1.dtx b/macros/latex/required/latex-lab/latex-lab-new-or-1.dtx
index cc60f50de0..9994b15cb8 100644
--- a/macros/latex/required/latex-lab/latex-lab-new-or-1.dtx
+++ b/macros/latex/required/latex-lab/latex-lab-new-or-1.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-%% File: latex-lab-new-or-1.dtx (C) Copyright 2020-2023 Frank Mittelbach
+%% File: latex-lab-new-or-1.dtx (C) Copyright 2020-2024 Frank Mittelbach
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
diff --git a/macros/latex/required/latex-lab/latex-lab-new-or-1.pdf b/macros/latex/required/latex-lab/latex-lab-new-or-1.pdf
index 501f7ac3d2..b80a1c4b15 100644
--- a/macros/latex/required/latex-lab/latex-lab-new-or-1.pdf
+++ b/macros/latex/required/latex-lab/latex-lab-new-or-1.pdf
Binary files differ
diff --git a/macros/latex/required/latex-lab/latex-lab-new-or-2.dtx b/macros/latex/required/latex-lab/latex-lab-new-or-2.dtx
index d2011256b1..ee20331a8f 100644
--- a/macros/latex/required/latex-lab/latex-lab-new-or-2.dtx
+++ b/macros/latex/required/latex-lab/latex-lab-new-or-2.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
%% File: latex-lab-new-or-2.dtx
-% Copyright (C) 2022-2023 The LaTeX Project
+% Copyright (C) 2022-2024 The LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
diff --git a/macros/latex/required/latex-lab/latex-lab-new-or-2.pdf b/macros/latex/required/latex-lab/latex-lab-new-or-2.pdf
index e15dd5abd0..24491f9568 100644
--- a/macros/latex/required/latex-lab/latex-lab-new-or-2.pdf
+++ b/macros/latex/required/latex-lab/latex-lab-new-or-2.pdf
Binary files differ
diff --git a/macros/latex/required/latex-lab/latex-lab-sec.dtx b/macros/latex/required/latex-lab/latex-lab-sec.dtx
index ae7a0b85c3..936eee9ed2 100644
--- a/macros/latex/required/latex-lab/latex-lab-sec.dtx
+++ b/macros/latex/required/latex-lab/latex-lab-sec.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-%% File: latex-lab-sec.dtx (C) Copyright 2022-2023 LaTeX Project
+%% File: latex-lab-sec.dtx (C) Copyright 2022-2024 LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -16,10 +16,10 @@
%
% for those people who are interested or want to report an issue.
%
-\def\ltlabsecdate{2023-10-16}
-\def\ltlabsecversion{0.84b}
+\def\ltlabsecdate{2024-10-04}
+\def\ltlabsecversion{0.84f}
%<*driver>
-\documentclass{l3doc}
+\documentclass[kernel]{l3doc}
\EnableCrossrefs
\CodelineIndex
\begin{document}
@@ -121,7 +121,7 @@
% commands must be at the right grouping level.
% \end{itemize}
%
-% \subsection{Funktions and keys}
+% \subsection{Functions and keys}
%
% \begin{function}{\tag_tool:n,\tagtool}
%
@@ -138,7 +138,7 @@
% to allow e.g. to put an epigraph or similar in front.
%
% \item The number in \cs{part} and \cs{chapter} is currently not correctly
-% tagged as a \texttt{Lbl} as this requires to redefine the internal (class dependant)
+% tagged as a \texttt{Lbl} as this requires to redefine the internal (class dependent)
% commands too.
%
% \end{itemize}
@@ -198,28 +198,31 @@
% We must ensure that manual targets (e.g. in unnumbered sections)
% correctly update \cs{@currentHref}. For this we extend the kernel definition of
% \cs{MakeLinkTarget}
-%
+% TODO: remove after release 2024/11
% \begin{macrocode}
%<*kernelchange>
\ExplSyntaxOn
-\int_new:N\g__kernel_target_int
-\RenewDocumentCommand\MakeLinkTarget{sO{}m}
- {%
- \ifvmode
- \special{}%
- \else
- \@savsf\spacefactor
- \smash{}%
- \spacefactor\@savsf
- \fi
- \IfBooleanTF {#1}
- {
- \tl_gset:Nx \@currentHref {#3}
+\str_if_exist:cF { l__socket_tagsupport/recordtarget_plug_str }
+ {
+ \int_new:N\g__kernel_target_int
+ \RenewDocumentCommand\MakeLinkTarget{sO{}m}
+ {%
+ \ifvmode
+ \special{}%
+ \else
+ \@savsf\spacefactor
+ \smash{}%
+ \spacefactor\@savsf
+ \fi
+ \IfBooleanTF {#1}
+ {
+ \tl_gset:Ne \@currentHref {#3}
+ }
+ {
+ \int_gincr:N\g__kernel_target_int
+ \tl_gset:Ne \@currentHref {target*.\int_use:N\g__kernel_target_int}
+ }
}
- {
- \int_gincr:N\g__kernel_target_int
- \tl_gset:Nx \@currentHref {target*.\int_use:N\g__kernel_target_int}
- }
}
\ExplSyntaxOff
%</kernelchange>
@@ -227,45 +230,56 @@
%
% \begin{macrocode}
%<*package>
+%<@@=tag>
% \end{macrocode}
% \subsubsection{Tagging commands}
%
%
-% \begin{variable}{\g__tag_sec_stack_seq}
-% The stack holds the tag and the level.
+% \begin{variable}{\g_@@_sec_stack_seq}
+% The stack holds the tag, the level and the structure number.
% \begin{macrocode}
-\seq_new:N \g__tag_sec_stack_seq
-\seq_gpush:Nn\g__tag_sec_stack_seq {{Document}{-100}}
+\seq_new:N \g_@@_sec_stack_seq
+\seq_gpush:Nn\g_@@_sec_stack_seq {{Document}{-100}{2}}
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\l__tag_sec_Sect_bool}
+% \begin{macro}{\@@_get_data_current_Sect:}
+% This allows to retrieve the number of the current Sect structure (or
+% Document if we are outside any Sect) with |\tag_get:n{current_Sect}|
+% \begin{macrocode}
+\cs_new:Npn \@@_get_data_current_Sect:
+ {
+ \exp_last_unbraced:Ne\use_iii:nnn{\seq_item:Nn\g_@@_sec_stack_seq{1}}
+ }
+% \end{macrocode}
+% \end{macro}
+% \begin{variable}{\l_@@_sec_Sect_bool}
% This boolean controls if a Sect structure is opened.
% \begin{macrocode}
-\bool_new:N \l__tag_sec_Sect_bool
-\bool_set_true:N\l__tag_sec_Sect_bool
+\bool_new:N \l_@@_sec_Sect_bool
+\bool_set_true:N\l_@@_sec_Sect_bool
% \end{macrocode}
% \end{variable}
-
-%
-% \begin{macro}{\__tag_sec_begin:nn}
+%
+% \begin{macro}{\@@_sec_begin:nn}
% This starts a sectioning structure.
% Currently the tag is fix, either Sect or Part, depending on the level,
% but this will perhaps change. The second argument is currently unused.
% \begin{macrocode}
-\cs_new_protected:Npn\__tag_sec_begin:nn #1 #2 %#1 level #2 keyval
+\cs_new_protected:Npn\@@_sec_begin:nn #1 #2 %#1 level #2 keyval
{
\tag_struct_begin:n
{
tag= {\int_compare:nNnTF {#1}={-1}{Part}{Sect}}
,#2
}
- \seq_gpush:Nx \g__tag_sec_stack_seq {{\g__tag_struct_tag_tl}{\int_eval:n{#1}}}
+ \seq_gpush:Ne \g_@@_sec_stack_seq
+ {{\g_@@_struct_tag_tl}{\int_eval:n{#1}}{\g_@@_struct_stack_current_tl}}
}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\__tag_sec_end:n}
+% \begin{macro}{\@@_sec_end:n}
% \begin{macrocode}
\msg_new:nnn { tag } {wrong-sect-nesting}
{
@@ -273,65 +287,65 @@
It~is~not~equal~to~the~current~structure~#2~on~the~main~stack
}
-\cs_new_protected:Npn\__tag_sec_end:n #1 % #1 level
+\cs_new_protected:Npn\@@_sec_end:n #1 % #1 level
{
- \seq_get:NN \g__tag_sec_stack_seq \l__tag_tmpa_tl
- \int_compare:nNnT {#1}<{\exp_last_unbraced:NV\use_ii:nn\l__tag_tmpa_tl+1}
+ \seq_get:NN \g_@@_sec_stack_seq \l_@@_tmpa_tl
+ \int_compare:nNnT {#1}<{\exp_last_unbraced:NV\use_ii:nnn\l_@@_tmpa_tl+1}
{
- \seq_get:NN\g__tag_struct_tag_stack_seq \l__tag_tmpb_tl
+ \seq_get:NN\g_@@_struct_tag_stack_seq \l_@@_tmpb_tl
\exp_args:Nee
\tl_if_eq:nnTF
- {\exp_last_unbraced:NV\use_i:nn\l__tag_tmpa_tl}
- {\exp_last_unbraced:NV\use_i:nn\l__tag_tmpb_tl}
+ {\exp_last_unbraced:NV\use_i:nnn\l_@@_tmpa_tl}
+ {\exp_last_unbraced:NV\use_i:nn\l_@@_tmpb_tl}
{
- \seq_gpop:NN \g__tag_sec_stack_seq \l__tag_tmpa_tl
+ \seq_gpop:NN \g_@@_sec_stack_seq \l_@@_tmpa_tl
\tag_struct_end:
- \__tag_sec_end:n {#1}
+ \@@_sec_end:n {#1}
}
{
- \msg_warning:nnxx {tag}{wrong-sect-nesting}
- { \exp_last_unbraced:NV\use_i:nn \l__tag_tmpa_tl }
- { \exp_last_unbraced:NV\use_i:nn \l__tag_tmpb_tl }
+ \msg_warning:nnee {tag}{wrong-sect-nesting}
+ { \exp_last_unbraced:NV\use_i:nnn \l_@@_tmpa_tl }
+ { \exp_last_unbraced:NV\use_i:nn \l_@@_tmpb_tl }
}
}
}
% \end{macrocode}
% \end{macro}
-% \begin{macro}{\__tag_tool_para_split:}
+% \begin{macro}{\@@_tool_para_split:}
% Runin-sectioning command must separate the heading from the following text.
%
% \begin{macrocode}
-\cs_new_protected:Npn \__tag_tool_para_split:
+\cs_new_protected:Npn \@@_tool_para_split:
{
\tag_mc_end:
\tag_struct_end:
- \tag_struct_begin:n{tag=\l__tag_para_tag_default_tl}
+ \tag_struct_begin:n{tag=\l_@@_para_tag_default_tl}
\tag_mc_begin:n{}
- \__tag_setup_restore_para_default:
+ \@@_setup_restore_para_default:
}
% \end{macrocode}
% \end{macro}
-% \begin{macro}{\__tag_setup_restore_para_default:}
+% \begin{macro}{\@@_setup_restore_para_default:}
% We change the para tagging in the sectioning code.
% This here restores the default. Currently it only resets the
% the tag, but perhaps more will be needed later.
% \begin{macrocode}
-\cs_new_protected:Npn \__tag_setup_restore_para_default:
+\cs_new_protected:Npn \@@_setup_restore_para_default:
{
- \tl_set:Nn \l__tag_para_main_tag_tl {text-unit}
- \tl_set_eq:NN\l__tag_para_tag_tl\l__tag_para_tag_default_tl
+ \tl_set:Nn \l_@@_para_main_tag_tl {text-unit}
+ \tl_set_eq:NN\l_@@_para_tag_tl\l_@@_para_tag_default_tl
}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\__tag_sec_end_display:}
+% \begin{macro}{\@@_sec_end_display:}
% \begin{macrocode}
-\cs_new_protected:Npn \__tag_sec_end_display:
+\cs_new_protected:Npn \@@_sec_end_display:
{
\tag_struct_end: %P = Hn
- \__tag_setup_restore_para_default:
+ \@@_setup_restore_para_default:
}
% \end{macrocode}
% \end{macro}
@@ -339,17 +353,17 @@
% Open sec structures should be closed at the end of the document. This should
% be done before tagpdf closes the Document structure.
% \begin{macrocode}
-\hook_gput_code:nnn{tagpdf/finish/before}{tagpdf/sec}{\__tag_sec_end:n{-10}}
+\hook_gput_code:nnn{tagpdf/finish/before}{tagpdf/sec}{\@@_sec_end:n{-10}}
\hook_gset_rule:nnnn {tagpdf/finish/before}{tagpdf/sec}{before}{tagpdf}
% \end{macrocode}
%
% The commands \cs{mainmatter}, \cs{backmatter}, \cs{frontmatter} and
% \cs{appendix} close all \texttt{Sect} and \texttt{Part} structures.
% \begin{macrocode}
-\AddToHook{cmd/frontmatter/before}{\__tag_sec_end:n{-10}}
-\AddToHook{cmd/mainmatter/before} {\__tag_sec_end:n{-10}}
-\AddToHook{cmd/backmatter/before} {\__tag_sec_end:n{-10}}
-\AddToHook{cmd/appendix/before} {\__tag_sec_end:n{-10}}
+\AddToHook{cmd/frontmatter/before}{\@@_sec_end:n{-10}}
+\AddToHook{cmd/mainmatter/before} {\@@_sec_end:n{-10}}
+\AddToHook{cmd/backmatter/before} {\@@_sec_end:n{-10}}
+\AddToHook{cmd/appendix/before} {\@@_sec_end:n{-10}}
% \end{macrocode}
%
% \subsection{Tagging tools}
@@ -368,57 +382,57 @@
{
,sec-start-part .code:n =
{
- \bool_if:NT\l__tag_sec_Sect_bool
+ \bool_if:NT\l_@@_sec_Sect_bool
{
- \__tag_sec_end:n {-1}
- \__tag_sec_begin:nn{-1}{tag=Part}
+ \@@_sec_end:n {-1}
+ \@@_sec_begin:nn{-1}{tag=Part}
}
\tag_struct_begin:n{tag=part,title=#1}
% \end{macrocode}
% We remap here the text-unit from the paragraph to NonStruct.
-% It would be better to suppress it completly as with the other
+% It would be better to suppress it completely as with the other
% sectioning commands, but this would require to redefine \cs{@spart}
% and \cs{@part}, as there is the grouping, and these commands are
% all slightly different in the standard classes. So this is delayed
% to the time when sectioning commands are redefined with templates.
% \begin{macrocode}
- \tl_set:Nn\l__tag_para_main_tag_tl {NonStruct}
- \tl_set:Nn\l__tag_para_tag_tl {Span}
+ \tl_set:Nn\l_@@_para_main_tag_tl {NonStruct}
+ \tl_set:Nn\l_@@_para_tag_tl {Span}
}
- ,sec-stop-part .code:n = {\__tag_sec_end_display:}
+ ,sec-stop-part .code:n = {\@@_sec_end_display:}
,sec-start-chapter .code:n =
{
- \bool_if:NT\l__tag_sec_Sect_bool
+ \bool_if:NT\l_@@_sec_Sect_bool
{
- \__tag_sec_end:n {0}
- \__tag_sec_begin:nn{0}{tag=Sect}
+ \@@_sec_end:n {0}
+ \@@_sec_begin:nn{0}{tag=Sect}
}
\tag_struct_begin:n{tag=chapter,title=#1}
% \end{macrocode}
% similar to part we remap to NonStruct for now ...
% \begin{macrocode}
- \tl_set:Nn\l__tag_para_main_tag_tl {NonStruct}
- \tl_set:Nn\l__tag_para_tag_tl {Span}
+ \tl_set:Nn\l_@@_para_main_tag_tl {NonStruct}
+ \tl_set:Nn\l_@@_para_tag_tl {Span}
}
,sec-stop-chapter .meta:n = { sec-stop-part}
,sec-start .code:n = % #1 is a name like "section"
{
- \bool_if:NT\l__tag_sec_Sect_bool
+ \bool_if:NT\l_@@_sec_Sect_bool
{
- \__tag_sec_end:n {\cs_if_exist_use:c{toclevel@#1}+0}
- \__tag_sec_begin:nn {\cs_if_exist_use:c{toclevel@#1}+0}{tag=Sect}
+ \@@_sec_end:n {\cs_if_exist_use:c{toclevel@#1}+0}
+ \@@_sec_begin:nn {\cs_if_exist_use:c{toclevel@#1}+0}{tag=Sect}
}
- \tl_set:Nn\l__tag_para_tag_tl{#1}
+ \tl_set:Nn\l_@@_para_tag_tl{#1}
}
,sec-start .value_required:n = true
- ,sec-split-para .code:n = {\__tag_tool_para_split:}
- ,restore-para .code:n = {\__tag_setup_restore_para_default:}
+ ,sec-split-para .code:n = {\@@_tool_para_split:}
+ ,restore-para .code:n = {\@@_setup_restore_para_default:}
,sec-stop .code:n =
{
- \par\__tag_sec_end:n {\cs_if_exist_use:c{toclevel@#1}+0}
+ \par\@@_sec_end:n {\cs_if_exist_use:c{toclevel@#1}+0}
}
,sec-stop .value_required:n = true
- ,sec-add-grouping .bool_set:N = \l__tag_sec_Sect_bool
+ ,sec-add-grouping .bool_set:N = \l_@@_sec_Sect_bool
}
% \end{macrocode}
%
@@ -433,6 +447,7 @@
% The tagging inside relies on the para tagging.
% We do not yet use keyval in the optional argument, as this requires latex-dev
% and the naming of the keys and their key family is unclear.
+% \changes{v0.84f}{2024/10/04}{Added braces around optional arg (tagging/725)}
% \begin{macrocode}
\AddToHook{class/after}
{
@@ -476,7 +491,7 @@
\IfBooleanTF
{#1}
{ \@spart {#3} }
- { \@part [#2]{#3} }
+ { \@part [{#2}]{#3} }
% \end{macrocode}
% and now the closing command for the tagging of the title.
% \begin{macrocode}
@@ -528,7 +543,7 @@
\IfBooleanTF
{#1}
{ \@schapter {#3} }
- { \@chapter [#2]{#3} }
+ { \@chapter [{#2}]{#3} }
% \end{macrocode}
% and now the closing command for the tagging of the title.
% \begin{macrocode}
@@ -583,7 +598,7 @@
\IfBooleanTF
{#1}
{ \@spart {#3} }
- { \@part [#2]{#3} }
+ { \@part [{#2}]{#3} }
% \end{macrocode}
% and now the closing command for the tagging of the title.
% \begin{macrocode}
@@ -669,7 +684,8 @@
% \begin{macrocode}
\cs_new_protected:Npn \@kernel@tag@hangfrom #1
{
- \tagstructbegin{tag=\l__tag_para_tag_tl}
+ \tagstructbegin{tag=\l_@@_para_tag_tl}
+ \cs_if_exist_use:N \@@_gincr_para_begin_int:
\tagstructbegin{tag=Lbl}
\setbox\@tempboxa
\hbox
@@ -679,7 +695,7 @@
% \begin{macrocode}
\bool_lazy_and:nnT
{\tag_if_active_p:}
- {\g__tag_mode_lua_bool}
+ {\g_@@_mode_lua_bool}
{\tagmcbegin{tag=Lbl}}
{#1}
}
@@ -688,12 +704,12 @@
% the paratagging. We do not disable paratagging completely, to
% avoid that the numbering goes wrong.
% \begin{macrocode}
- \tag_stop:n{hangfrom}
+ \tag_suspend:n{hangfrom}
\hangindent \wd\@tempboxa\noindent
% \end{macrocode}
% Restart tagging and insert the box.
% \begin{macrocode}
- \tag_start:n{hangfrom}
+ \tag_resume:n{hangfrom}
\tagmcbegin{}\box\@tempboxa\tagmcend\tagstructend\tagmcbegin{}}
% \end{macrocode}
% This command is used to tag the numbers of runin. We do not try
@@ -714,6 +730,7 @@
% \cs{@sect} is only changed to replace the hyperref patches
% and to use the new \cs{@kernel@tag@hangfrom} and \cs{@kernel@tag@svsec}
% \begin{macrocode}
+%<@@=>
\def\@sect#1#2#3#4#5#6[#7]#8{%
\ifnum #2>\c@secnumdepth
\def\@svsec{\@hyp@section@target@nnn{[section]}{}{#3}}
@@ -726,7 +743,7 @@
\@tempskipa #5\relax
\ifdim \@tempskipa>\z@
\begingroup
- \tagtool{para-flattened=true} % or \bool_set_true\l__tag_para_flattened_bool
+ \tagtool{para-flattened=true} % or \bool_set_true\l_@@_para_flattened_bool
#6{%
\ifnum #2>\c@secnumdepth
\@hangfrom {\hskip #3\relax\@svsec}%
diff --git a/macros/latex/required/latex-lab/latex-lab-sec.pdf b/macros/latex/required/latex-lab/latex-lab-sec.pdf
index d470f9bbfb..22a509f3ec 100644
--- a/macros/latex/required/latex-lab/latex-lab-sec.pdf
+++ b/macros/latex/required/latex-lab/latex-lab-sec.pdf
Binary files differ
diff --git a/macros/latex/required/latex-lab/latex-lab-table.dtx b/macros/latex/required/latex-lab/latex-lab-table.dtx
index 700d4ce6c1..c65667e8ed 100644
--- a/macros/latex/required/latex-lab/latex-lab-table.dtx
+++ b/macros/latex/required/latex-lab/latex-lab-table.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-%% File: latex-lab-table.dtx (C) Copyright 2023 LaTeX Project
+%% File: latex-lab-table.dtx (C) Copyright 2023-2024 LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -16,8 +16,8 @@
%
% for those people who are interested or want to report an issue.
%
-\def\ltlabtbldate{2023-10-30}
-\def\ltlabtblversion{0.85d}
+\def\ltlabtbldate{2024-09-18}
+\def\ltlabtblversion{0.85n}
%<*driver>
\documentclass{l3doc}
\EnableCrossrefs
@@ -100,6 +100,7 @@
% support for the tagging of tables. A list of the known limitations
% is shown below.
%
+% \subsection{Loading}
% The module is not loaded automatically (i.e., not yet integrated
% into any \texttt{phase-XX}) and by itself it doesn't activate
% tagging. For experimenting with table tagging it is therefore best
@@ -113,34 +114,13 @@
% It will then automatically tag all table environments it already supports with
% the exception of tables in the header and footer of the page (where tagging is disabled).
% Such tables can be nested.
-%
-% If a table should not be tagged as table, for example because it is merely used
-% to produce a layout or because it is a not yet (fully) supported table structure,
-% the tagging can be disabled with
-% \verb|\tagpdfsetup{table-tagging=false}|.
-%
+%
% Inside cells the automatic tagging of paragraphs is disabled with the exception of
% p/m/b-type cells.
%
% Rows do not need to contain a full number of \&, missing cells are automatically
% added with an empty TD-structure.
-%
-% There is some basic support\footnote{This is not meant to be the
-% final interface, though.} for headers. With
-% \begin{quote}
-% \verb|\tagpdfsetup{table-header-rows={|\meta{list of row numbers}\verb|}|
-% \end{quote}
-% you can
-% declare which (absolute) row numbers should be tagged as header rows.
-% It applies to all tables until it is changed to a different list of row numbers or undone by setting
-% the key to \meta{empty}.
-% A row number can be
-% negative, then the counting starts from the end of the table. There is no support
-% for header columns yet. In a \env{longtable} the code will currently use the \cs{endhead} or
-% \cs{endfirsthead} rows as header if one of these commands has been
-% used and in that case the code
-% ignores a \texttt{table-header-rows} setting.
-%
+%
% You should not insert meaningful text with \verb+!{...}+ or \verb+@{...}+ or \cs{noalign}
% between the rows or columns of the table.
% With pdflatex such text will be unmarked, with lualatex it will be marked as artifact.
@@ -149,10 +129,64 @@
% to collect such text and move it into a structure it would require manual markup
% from the author to clarify where this text belongs too.}
%
-% As mentioned below the \pkg{colortbl} doesn't yet work properly with the tagging,
-% but once it does, then colors inside the table will probably be
-% simply ignored (at least initially). If such a color
+% As mentioned below the \pkg{colortbl} doesn't work fully with the tagging,
+% but when it does, colors inside the table are currently ignored. If such a color
% has a semantic meaning (like \enquote{important value}) this meaning will be lost.
+%
+% \subsection{Untagged and presentation tables}
+% If a table should not be tagged as table, for example because it is merely used
+% as a layout to ensure that the content is properly aligned
+% or because it is a not yet (fully) supported table structure,
+% the tagging can be disabled with
+% \verb|\tagpdfsetup{table/tagging=false}| or with \verb|\tagpdfsetup{table/tagging=presentation}|%
+% \footnote{The key has been renamed. The old name `table-tagging` still works but is
+% deprecated. The value \texttt{presentation} refers to the ARIA role \enquote{presentation}.}
+% The first option disables the table tagging code and the content of the tabular
+% is then treated more or less like running text. This works ok for simple tables using
+% only hmode-cells (l/c/r) with normal text content, but fails if the table uses vmode-cells
+% (p/m/b). In such cases the second option works better: it keeps the tagging code active
+% but changes the tag names to \texttt{Div} and the grouping structure \texttt{NonStruct}. It also
+% (re)sets the \texttt{table/header-rows} key to empty.
+% The key should currently only be used in a group as there is no key (yet) to reset to the default
+% tag names.
+%
+% \subsection{Header rows and columns}
+% There is some basic support\footnote{This is not meant to be the
+% final interface, though.} for headers. With\footnote{The old key name \texttt{table-header-rows} still
+% works but is deprecated.}
+% \begin{quote}
+% \verb|\tagpdfsetup{table/header-rows={|\meta{list of row numbers}\verb|}|
+% \verb|\tagpdfsetup{table/header-columns={|\meta{list of column numbers}\verb|}|
+% \end{quote}
+% you can
+% declare which (absolute) row and column numbers should be tagged as header rows and header columns.
+% It applies to all tables until it is changed to a different list of row or
+% columns numbers or undone by setting
+% the keys to \meta{empty}.
+% A row or column number can be
+% negative, then the counting starts from the end of the table.
+% In a \env{longtable} the code will currently use the \cs{endhead} or
+% \cs{endfirsthead} rows as header if one of these commands has been
+% used and in that case the code
+% ignores a \texttt{table/header-rows} setting.
+%
+% \subsection{Spanning of cells}
+%
+% \cs{multicolumn} is supported out of the box and will create a structure with a
+% suitable \texttt{ColSpan} attribute\footnote{The code uses actually an attribute \emph{class}.
+% The validator PAC doesn't handle this correctly currently and complains about a missing attribute.}
+%
+% For cells spanning rows some preliminary support exists\footnote{The interface is bound to change!}:
+% If you add
+% \begin{quote}
+% \verb|\tagpdfsetup{table/multirow={|\meta{number of rows}\verb|}|
+% \end{quote}
+% to a cell the code will add the suitable \texttt{RowSpan} attribute and suppress the tagging of affected
+% cells in the following rows. This will also work if the current cell is a \cs{multicolumn}, then
+% the cell will span both rows and columns. It is the duty of the author to
+% ensure that all cells below and covered by a \texttt{RowSpan} are empty!
+% The code neither checks that nor does
+% it tries to suppress content.
%
% Feedback and problems with the code can be reported at
% \url{https://github.com/latex3/tagging-project} either in form of
@@ -171,19 +205,19 @@
% \item the \env{array} environment is assumed to be part of math and tagging as a table is disabled for
% it.
%
-% \item Row spans are not yet supported (and the \pkg{multirow} package is untested).
+% \item Row spans can only be added manually (the \pkg{multirow} package is untested).
%
-% \item The \pkg{colortbl} package breaks tagging if there are nested tables. It also breaks
-% the filling up of incomplete rows.
+% \item The \pkg{colortbl} package breaks tagging if there are nested tables.
%
% \item The \pkg{tabularray} package use a completed different
% method to create tables and will not be supported by this code.
%
% \item The \pkg{nicematrix} package is currently incompatible.
%
-% \item Most other packages related to tables in \LaTeX{} are not yet tested,
+% \item Most other packages related to tables in \LaTeX{} are not fully tested,
% that includes packages that change rules like \pkg{booktabs}, \pkg{hhline},
-% \pkg{arydshln}, \pkg{hvdashln}.
+% \pkg{arydshln}, \pkg{hvdashln}. Some problems have been resolved, either
+% in the packages or through a firstaid which can be loaded the \verb+testphase=firstaid+.
%
% \item \env{longtable} currently only works with lualatex.
% With other engines it breaks as its output
@@ -193,11 +227,12 @@
%
% \item Not every table should be tagged as a Table structure, often they are
% only used as layout help, e.g. to align authors in a title pages. In such uses
-% the tagging of the table must be deactivated with \verb|\tagpdfsetup{table-tagging=false}|.
+% the tagging of the table must be deactivated with \verb|\tagpdfsetup{table/tagging=false}|
+% or \verb|\tagpdfsetup{table/tagging=presentation}|.
%
-% \item Only simple header rows are currently supported. Columns and complex headers with
+% \item Only simple header rows and columns are currently supported. Complex headers with
% subheaders will be handled later as that needs some syntax changes. Tables
-% with more than one header row are probably not pdf/UA as the headers array in
+% with more than one header row or column are probably not pdf/UA as the headers array in
% the cells is missing.
%
% \item A \pkg{longtable} \cs{caption} is currently simply formatted as a multicolumn and
@@ -210,6 +245,8 @@
%
% \item The \env{longtable} environment supports footnotes in p-type columns, but it hasn't been
% tested yet if this works also with the tagging code.
+%
+% \item Vertical boxes (\cs{parbox}, \texttt{minipage}, \ldots) inside cells can be problematic.
%
% \item The code is quite noisy and fills the log with lots of
% messages.\footnote{Helpful for us at this stage.}
@@ -244,9 +281,6 @@
%
% \item Longtable captions should be properly supported.
%
-% \item Handle p-cells better. para-tagging should probably be enabled,
-% but Part can't be a child of TD, so this should probably be changed to Div here.
-% Also there is a stray MC somewhere.
%
% \item More packages must be tested.
% \end{itemize}
@@ -271,24 +305,32 @@
% \begin{macro}
% {
% \l_@@_celltag_tl
+% \l_@@_pcelltag_tl
% ,\l_@@_rowtag_tl
+% ,\l_@@_table_tl
% ,\l_@@_cellattribute_tl
% ,\l_@@_rowattribute_tl
-% ,\g_@@_missingcells_int
% ,\l_@@_tmpa_clist
-% ,\l_@@_tmpa_seq
% ,\l_@@_tmpa_tl
+% ,\l_@@_tmpa_str
% }
% This is for the celltag, e.g. TD or TH:
% \begin{macrocode}
\tl_new:N \l_@@_celltag_tl
\tl_set:Nn \l_@@_celltag_tl {TD}
+\tl_new:N \l_@@_pcelltag_tl
+\tl_set:Nn \l_@@_pcelltag_tl {TD}
% \end{macrocode}
% For the rowtag, probably always TR:
% \begin{macrocode}
\tl_new:N \l_@@_rowtag_tl
\tl_set:Nn \l_@@_rowtag_tl {TR}
% \end{macrocode}
+% For the tabletag, probably always Table:
+% \begin{macrocode}
+\tl_new:N \l_@@_tabletag_tl
+\tl_set:Nn \l_@@_tabletag_tl {Table}
+% \end{macrocode}
% And here cell and row attributes:
% \begin{macrocode}
\tl_new:N \l_@@_cellattribute_tl
@@ -296,158 +338,170 @@
\tl_new:N \l_@@_rowattribute_tl
\tl_set:Nn \l_@@_rowattribute_tl {}
% \end{macrocode}
-% This will contain the number of missing cells used:
+% Variable to store cell info like which cell must be skipped when tagging multirows.
% \begin{macrocode}
-\int_new:N \g_@@_missing_cells_int
+\prop_new:N\g_@@_untagged_cells_prop
+\prop_new:N\l_@@_saved_untagged_cells_prop
% \end{macrocode}
% Temp variables
% \begin{macrocode}
\clist_new:N \l_@@_tmpa_clist
-\seq_new:N \l_@@_tmpa_seq
\tl_new:N \l_@@_tmpa_tl
+\str_new:N \l_@@_tmpa_str
% \end{macrocode}
% \end{macro}
%
-% \subsection{Sockets}
+% \subsection{Tagging support sockets}
%
-% 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 At first sockets for the begin and
-% end of cells and rows
%
-% \begin{socketdecl}{tagsupport/tblcell/begin,
-% tagsupport/tblcell/end,
-% tagsupport/tblrow/begin,
-% tagsupport/tblrow/end,
-% }
+% This are the standard plugs for tagging of cells and rows.
+%
+% The following two sockets are defined in lttagging, but we check
+% for their existence until the release 11/2024.
% \begin{macrocode}
-\NewSocket{tagsupport/tblcell/begin}{0}
-\NewSocket{tagsupport/tblcell/end}{0}
-\NewSocket{tagsupport/tblrow/begin}{0}
-\NewSocket{tagsupport/tblrow/end}{0}
+\str_if_exist:cF { l__socket_tagsupport/tbl/init/celldata_plug_str }
+ {
+ \NewSocket{tagsupport/tbl/init/celldata}{0}
+ \NewSocket{tagsupport/tbl/restore/celldata}{0}
+ }
% \end{macrocode}
-% \end{socketdecl}
-%
-% \begin{socketdecl}{tagsupport/tbl/init}
-% This socket should be at the begin of the table, inside a group.
-% It is meant for settings like disabling paratagging. This socket
-% can perhaps be merged later into the begin-sockets when they are
-% no longer added as hooks but in the environment definitions.
+% \begin{plugdecl}{default}
+% This socket is used inside \cs{tbl_init_cell_data_for_table} for the
+% case that this a nested table in a cell.
% \begin{macrocode}
-\NewSocket{tagsupport/tbl/init}{0}
+\NewSocketPlug{tagsupport/tbl/init/celldata}{default}
+ {
+ \prop_set_eq:NN\l_@@_saved_untagged_cells_prop \g_@@_untagged_cells_prop
+ \prop_gclear:N \g_@@_untagged_cells_prop
+ }
+\AssignSocketPlug{tagsupport/tbl/init/celldata}{default}
% \end{macrocode}
-% \end{socketdecl}
-%
-%
-% \begin{socketdecl}{tagsupport/tbl/finalize}
-% To fine tune the structure (change cells to header cells, remove
-% unwanted structures, move a foot to the end, etc.) we also need a
-% socket that is executed at the end of the table but \emph{before}
-% all the variables are restored to the outer or default values.
-% The code in the socket can make assignments, but probably
-% shouldn't do typesetting and not write whatsits.
+% \end{plugdecl}
+
+% \begin{plugdecl}{default}
+% This socket is used inside \cs{tbl_restore_outer_cell_data:} and restores
+% values when a nested table is ended.
% \begin{macrocode}
-\NewSocket{tagsupport/tbl/finalize}{0}
+\NewSocketPlug{tagsupport/tbl/restore/celldata}{default}
+ {
+ \prop_gset_eq:NN\g_@@_untagged_cells_prop \l_@@_saved_untagged_cells_prop
+ }
+\AssignSocketPlug{tagsupport/tbl/restore/celldata}{default}
% \end{macrocode}
-% \end{socketdecl}
-%
-% \begin{socketdecl}{tagsupport/tbl/finalize/longtable}
-% \env{longtable} needs its own socket to fine tune the structure.
-% Simply switching the plug in the previous socket interferes with
-% enabling/disabling the tagging.
+% \end{plugdecl}
+%
+% \begin{plugdecl}{TD}
% \begin{macrocode}
-\NewSocket{tagsupport/tbl/finalize/longtable}{0}
+\NewSocketPlug{tagsupport/tbl/cell/begin}{TD}
+ {
% \end{macrocode}
-% \end{socketdecl}
-%
-% \begin{socketdecl}{tagsupport/tblhmode/begin,
-% tagsupport/tblhmode/end,
-% tagsupport/tblvmode/begin,
-% tagsupport/tblvmode/end
-% }
-%
-% These sockets are used in the begin and end code of environments,
-% to allow a fast enabling and disabling of the tagging. We
-% distinguish between tables that can be used inside paragraphs and
-% standalone tables like longtable.
+% Next line was previously outside of the plug, so if we want to execute it
+% always even if the noop plug is in force this needs a different solution.
% \begin{macrocode}
-\NewSocket{tagsupport/tblhmode/begin}{0}
-\NewSocket{tagsupport/tblhmode/end}{0}
-\NewSocket{tagsupport/tblvmode/begin}{0}
-\NewSocket{tagsupport/tblvmode/end}{0}
+ \@@_show_curr_cell_data:
% \end{macrocode}
-% \end{socketdecl}
-%
-% This are the standard plugs for tagging of cells and rows.
-%
-% \begin{plugdecl}{TD}
+% We test if the cell should be tagged at all.
% \begin{macrocode}
-\NewSocketPlug{tagsupport/tblcell/begin}{TD}
- {
- \tag_struct_begin:n
+ \@@_if_tag_cell:nnT {\g_@@_row_int } { \g_@@_col_int }
{
- tag =\l_@@_celltag_tl,
- attribute-class =\l_@@_cellattribute_tl
- }
- \seq_gput_right:Ne \g_@@_struct_cur_seq { \tag_get:n {struct_num} }
+% \end{macrocode}
+% this sets row headers
+% \begin{macrocode}
+ \clist_if_in:NVT \l_@@_header_columns_clist\g_@@_col_int
+ {
+ \tl_set:Nn \l_@@_celltag_tl {TH}
+ \tl_set:Ne \l_@@_cellattribute_tl {\l_@@_cellattribute_tl,TH-row}
+ }
+% \end{macrocode}
+% Here we handle negative value for row headers:
+% \begin{macrocode}
+ \tl_set:Ne \l_@@_tmpa_tl {\int_eval:n { \g_@@_col_int - 1 - \g_@@_table_cols_tl }}
+ \clist_if_in:NoT \l_@@_header_columns_clist { \l_@@_tmpa_tl }
+ {
+ \tl_set:Nn \l_@@_celltag_tl {TH}
+ \tl_set:Ne \l_@@_cellattribute_tl {\l_@@_cellattribute_tl,TH-row}
+ }
+ \tag_struct_begin:n
+ {
+ tag =\l_@@_celltag_tl,
+ attribute-class ={\l_@@_cellattribute_tl}
+ }
+ \seq_gput_right:Ne \g_@@_struct_cur_seq { \tag_get:n {struct_num} }
% \end{macrocode}
% we store the cells of multicolumns as negative number. This allow to skip them
% or to use them as needed.
% \begin{macrocode}
- \int_step_inline:nn { \g_@@_span_tl - 1 }
- {
- \seq_gput_right:Ne \g_@@_struct_cur_seq { -\tag_get:n {struct_num} }
- }
- \tag_mc_begin:n{}
+ \int_step_inline:nn { \g_@@_span_tl - 1 }
+ {
+ \seq_gput_right:Ne \g_@@_struct_cur_seq { -\tag_get:n {struct_num} }
+ }
+ \tag_mc_begin:n{}
+ }
}
% \end{macrocode}
% \end{plugdecl}
%
% \begin{plugdecl}{TD}
% \begin{macrocode}
-\NewSocketPlug{tagsupport/tblcell/end}{TD}
+\NewSocketPlug{tagsupport/tbl/cell/end}{TD}
{
- \tag_mc_end:
- \tag_struct_end:
+ \@@_if_tag_cell:nnT {\g__tbl_row_int } { \g__tbl_col_int }
+ {
+ \tag_mc_end:
+ \tag_struct_end:
+ }
}
% \end{macrocode}
% \end{plugdecl}
%
% In p-columns we need a slightly different plug which reactivates the
% paragraph tagging.
-% tagging
-% \begin{plugdecl}{TD}
+% \begin{plugdecl}{TDpbox}
% \begin{macrocode}
-\NewSocketPlug{tagsupport/tblcell/begin}{TDpbox}
+\NewSocketPlug{tagsupport/tbl/pcell/begin}{TDpbox}
{
- \tag_struct_begin:n
+ \@@_show_curr_cell_data:
+ \@@_if_tag_cell:nnT {\g__tbl_row_int } { \g__tbl_col_int }
{
- tag =\l__tbl_celltag_tl,
- attribute-class =\l__tbl_cellattribute_tl
- }
- \seq_gput_right:Ne \g__tbl_struct_cur_seq { \tag_get:n {struct_num} }
- \int_step_inline:nn { \g__tbl_span_tl - 1 }
- {
- \seq_gput_right:Ne \g__tbl_struct_cur_seq { -\tag_get:n {struct_num} }
- }
- \tagpdfparaOn
- \tl_set:Nn \l__tag_para_main_tag_tl {Div}
+ \clist_if_in:NVT \l_@@_header_columns_clist\g_@@_col_int
+ {
+ \tl_set:Nn \l_@@_celltag_tl {TH}
+ \tl_set:Ne \l_@@_cellattribute_tl {\l_@@_cellattribute_tl,TH-row}
+ }
+ \tag_struct_begin:n
+ {
+ tag =\l_@@_pcelltag_tl,
+ attribute-class ={\l_@@_cellattribute_tl}
+ }
+ \seq_gput_right:Ne \g_@@_struct_cur_seq { \tag_get:n {struct_num} }
+ \int_step_inline:nn { \g_@@_span_tl - 1 }
+ {
+ \seq_gput_right:Ne \g_@@_struct_cur_seq { -\tag_get:n {struct_num} }
+ }
+ \tagpdfparaOn
+ \tl_set:Nn \l__tag_para_main_tag_tl {Div}
+ }
}
% \end{macrocode}
% \end{plugdecl}
%
-% \begin{plugdecl}{TD}
+% \begin{plugdecl}{TDpbox}
% \begin{macrocode}
-\NewSocketPlug{tagsupport/tblcell/end}{TDpbox}
+\NewSocketPlug{tagsupport/tbl/pcell/end}{TDpbox}
{
- \tag_struct_end:
+ \@@_if_tag_cell:nnT {\g_@@_row_int } { \g_@@_col_int }
+ {
+ \tag_struct_end:
+ \legacy_if:nT {@endpe}{\par}
+ \mode_if_vertical:T{ \tagpdfparaOff }
+ }
}
% \end{macrocode}
% \end{plugdecl}
%
% \begin{plugdecl}{TR}
% \begin{macrocode}
-\NewSocketPlug{tagsupport/tblrow/begin}{TR}
+\NewSocketPlug{tagsupport/tbl/row/begin}{TR}
{
\seq_gclear:N \g_@@_struct_cur_seq
\tag_struct_begin:n
@@ -462,24 +516,28 @@
%
% \begin{plugdecl}{TR}
% \begin{macrocode}
-\NewSocketPlug{tagsupport/tblrow/end}{TR}
+\NewSocketPlug{tagsupport/tbl/row/end}{TR}
{
- \__tag_tbl_add_missing_cells:n { \g_@@_missing_cells_int }
+ \tag_if_active:T
+ {
+ \@@_add_missing_cells:
\seq_gput_right:Ne \g_@@_struct_cells_seq
{
\seq_use:Nn \g_@@_struct_cur_seq {,}
}
- \int_compare:nNnTF { \g_@@_row_int } = { \seq_count:N\g_@@_struct_cells_seq }
+ \int_compare:nNnTF { \g_@@_row_int } =
+ { \seq_count:N \g_@@_struct_cells_seq }
{
- \typeout
+ \@@_trace:n
{==>~
- stucture~stored~for~row~\int_use:N\g_@@_row_int :~
+ structure~stored~for~row~\int_use:N\g_@@_row_int :~
\seq_use:Nn \g_@@_struct_cur_seq {,}
}
}
- { \ERROR } % should not happen ...
+ { \ERRORtbl/row } % should not happen ...
\tag_struct_end:
}
+ }
% \end{macrocode}
% \end{plugdecl}
%
@@ -487,17 +545,49 @@
% normal tables which can also be used inline and nested and
% \enquote{vmode} tables like longtable.
%
+% \begin{macro}{\l__tag_block_flattened_level_int}
+% Count the levels of nested blockenvs starting with the first that
+% is \enquote{flattened}. The counter is defined in lttagging.dtx,
+% but until the next release 11/24 we set it up here too so that we can
+% use it in the following socket
+% \begin{macrocode}
+\int_if_exist:NF \l__tag_block_flattened_level_int
+ {
+ \int_new:N \l__tag_block_flattened_level_int
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{plugdecl}{Table}
+% Inside a TD or TR Part is not allowed as child. For structures that restore
+% paragraph settings we therefore need a special plug that adjust the settings.
+% Currently we set the para main tag to Div. This leads to double Div-structures
+% but flattening the paragraph doesn't work, it errors if there is a list inside.
+% \begin{macrocode}
+\NewSocketPlug{tagsupport/para/restore}{Table}
+ {
+ \tl_set:Nn \l__tag_para_main_tag_tl {Div}
+ \tl_set_eq:NN \l__tag_para_tag_tl\l__tag_para_tag_default_tl
+ \bool_set_true:N \l__tag_para_bool
+ \bool_set_false:N \l__tag_para_flattened_bool
+ \int_zero:N \l__tag_block_flattened_level_int
+ }
+% \end{macrocode}
+% \end{plugdecl}
+%
% \begin{plugdecl}{Table}
% Inside a table we currently only disable paratagging. We assume
-% that these sockets are in an environment group, so there is no
+% that these sockets are called in a group, so there is no
% need to reenable paratagging.
% \begin{macrocode}
\NewSocketPlug{tagsupport/tbl/init}{Table}
{
- \tag_if_active:T
- {
- \bool_set_false:N \l__tag_para_bool
- }
+ \bool_set_false:N \l__tag_para_bool
+ \AssignSocketPlug{tagsupport/para/restore}{Table}
+% \end{macrocode}
+% We also initialize the structure data variables a this point.
+% \begin{macrocode}
+ \@@_init_struct_data:
}
% \end{macrocode}
% \end{plugdecl}
@@ -509,14 +599,41 @@
\NewSocketPlug{tagsupport/tbl/finalize}{Table}
{
\@@_set_header_rows:
+% \end{macrocode}
+% Similarly, we restore the outer values of the structure data when
+% we leave the table.
+% \begin{macrocode}
+ \@@_restore_struct_data:
}
% \end{macrocode}
% \end{plugdecl}
%
+%
+%
+%
% \begin{plugdecl}{Table}
-% This plug will fine tune the structure of longtable.
+% This plug will initialize the structure in longtable.
% \begin{macrocode}
-\NewSocketPlug{tagsupport/tbl/finalize/longtable}{Table}
+\NewSocketPlug{tagsupport/tbl/longtable/init}{Table}
+ {
+ \seq_gclear:N\g_@@_struct_rows_seq
+ \seq_gclear:N\g_@@_struct_cells_seq
+ \seq_gclear:N\g_@@_struct_cur_seq
+ \seq_gclear:N\g_@@_LT@firsthead_rows_seq
+ \seq_gclear:N\g_@@_LT@head_rows_seq
+ \seq_gclear:N\g_@@_LT@lastfoot_rows_seq
+ \seq_gclear:N\g_@@_LT@foot_rows_seq
+ }
+% \end{macrocode}
+% \end{plugdecl}
+%
+%
+
+
+% \begin{plugdecl}{Table}
+% This plug will fine tune the structure in longtable.
+% \begin{macrocode}
+\NewSocketPlug{tagsupport/tbl/longtable/finalize}{Table}
{
% \end{macrocode}
% If neither \cs{endhead} nor \cs{endfirsthead} has been used
@@ -582,7 +699,7 @@
\prop_if_exist:cT
{ g__tag_struct_ \l_@@_tmpa_tl _prop }
{
- \@@_struct_prop_gput:Vnn \l_@@_tmpa_tl {S}{/Artifact}
+ \__tag_struct_prop_gput:onn { \l_@@_tmpa_tl } {S}{/Artifact}
}
}
}
@@ -673,7 +790,7 @@
\prop_if_exist:cT
{ g__tag_struct_ \l_@@_tmpa_tl _prop }
{
- \@@_struct_prop_gput:Vnn \l_@@_tmpa_tl {S}{/Artifact}
+ \__tag_struct_prop_gput:onn {\l_@@_tmpa_tl} {S}{/Artifact}
}
}
}
@@ -683,20 +800,49 @@
% \end{macrocode}
% \end{plugdecl}
%
+%
+%
+% \begin{plugdecl}{Table}
+%
+% We must avoid that the reuse of the header foot box leads to duplicated
+% content, thus reset attribute of the box:
+% \begin{macrocode}
+\NewSocketPlug{tagsupport/tbl/longtable/head}{Table}
+ {
+ \tagmcbegin{artifact}
+ \tag_mc_reset_box:N\LT@head
+ \tagmcend
+ }
+% \end{macrocode}
+% \end{plugdecl}
+%
% \begin{plugdecl}{Table}
% \begin{macrocode}
-\NewSocketPlug{tagsupport/tblhmode/begin}{Table}
+\NewSocketPlug{tagsupport/tbl/longtable/foot}{Table}
+ {
+ \tagmcbegin{artifact}
+ \tag_mc_reset_box:N \LT@foot
+ \tagmcend
+ }
+% \end{macrocode}
+% \end{plugdecl}
+%
+%
+%
+%
+% \begin{plugdecl}{Table}
+% \begin{macrocode}
+\NewSocketPlug{tagsupport/tbl/hmode/begin}{Table}
{
- \mode_leave_vertical:
\tag_mc_end_push:
% \end{macrocode}
% Close the P-chunk. This assumes that para-tagging is active.
-% For nested tables that is not necessarly true, so we test for it.
+% For nested tables that is not necessarily true, so we test for it.
% \begin{macrocode}
\bool_lazy_and:nnT
{ \bool_if_exist_p:N \l__tag_para_bool } { \l__tag_para_bool }
{ \tag_struct_end:n { text } }
- \tag_struct_begin:n {tag=Table}
+ \tag_struct_begin:n {tag=\l_@@_tabletag_tl}
\tl_gset:Ne \g_@@_struct_table_tl { \tag_get:n {struct_num} }
}
% \end{macrocode}
@@ -704,12 +850,12 @@
%
% \begin{plugdecl}{Table}
% \begin{macrocode}
-\NewSocketPlug{tagsupport/tblhmode/end}{Table}
+\NewSocketPlug{tagsupport/tbl/hmode/end}{Table}
{
\tag_struct_end:
% \end{macrocode}
% reopen the P-chunk. This assumes that para-tagging is active.
-% For nested tables that is not necessarly true, so we test for it.
+% For nested tables that is not necessarily true, so we test for it.
% \begin{macrocode}
\bool_lazy_and:nnT
{ \bool_if_exist_p:N \l__tag_para_bool } { \l__tag_para_bool }
@@ -721,9 +867,9 @@
%
% \begin{plugdecl}{Table}
% \begin{macrocode}
-\NewSocketPlug{tagsupport/tblvmode/begin}{Table}
+\NewSocketPlug{tagsupport/tbl/vmode/begin}{Table}
{
- \tag_struct_begin:n {tag=Table}
+ \tag_struct_begin:n {tag=\l_@@_tabletag_tl}
\tl_gset:Ne \g_@@_struct_table_tl { \tag_get:n {struct_num} }
}
% \end{macrocode}
@@ -731,7 +877,7 @@
%
% \begin{plugdecl}{Table}
% \begin{macrocode}
-\NewSocketPlug{tagsupport/tblvmode/end}{Table}
+\NewSocketPlug{tagsupport/tbl/vmode/end}{Table}
{
\tag_struct_end:
\par
@@ -740,66 +886,74 @@
% \end{plugdecl}
%
%
+% \begin{plugdecl}{code}
+% This socket takes a number, checks if is larger than one,
+% checks if the colspan attribute already exists (we can't predefine an
+% arbitrary number), and updates \cs{l_@@_cellattribute_tl}.
+% \begin{macrocode}
+\NewSocketPlug{tagsupport/tbl/colspan}{code}
+ {
+ \int_compare:nNnT {#1}>{1}
+ {
+ \prop_get:NeNF \g__tag_attr_entries_prop
+ {colspan-\int_eval:n{#1}}
+ \l_@@_tmpa_tl
+ {
+ \__tag_attr_new_entry:ee
+ {colspan-\int_eval:n{#1}}
+ {/O /Table /ColSpan~\int_eval:n{#1}}
+ }
+ \tl_set:Ne \l_@@_cellattribute_tl
+ {\l_@@_cellattribute_tl,colspan-\int_eval:n{#1}}
+ }
+ }
+% \end{macrocode}
+% \end{plugdecl}
%
%
%
-%\subsection{Environments}
%
-% Currently only tabular, tabular*, tabularx and longtable.
-% We must use the \texttt{before} and \texttt{after} hooks as the \texttt{end}
-% hook is executed before the end of the last row and then MC are messed up.
-% This means that this sockets should only contain code that doesn't needs to be
-% grouped!
+% \begin{plugdecl}{code}
+% The sockets will be in lttagging.dtx, but that may only happen in
+% the next main release, so for now we test if they are in the
+% format and if not define them now.
% \begin{macrocode}
-\AddToHook{env/tabular/before} {\UseSocket{tagsupport/tblhmode/begin}}
-\AddToHook{env/tabular/after} {\UseSocket{tagsupport/tblhmode/end}}
-\AddToHook{env/tabular*/before} {\UseSocket{tagsupport/tblhmode/begin}}
-\AddToHook{env/tabular*/after} {\UseSocket{tagsupport/tblhmode/end}}
-\AddToHook{env/tabularx/before} {\UseSocket{tagsupport/tblhmode/begin}}
-\AddToHook{env/tabularx/after} {\UseSocket{tagsupport/tblhmode/end}}
-\AddToHook{env/longtable/before}{\UseSocket{tagsupport/tblvmode/begin}}
-\AddToHook{env/longtable/after} {\UseSocket{tagsupport/tblvmode/end}}
+\str_if_exist:cF { l__socket_tagsupport/tbl/leaders/end_plug_str }
+ {
+ \NewSocket{tagsupport/tbl/leaders/begin}{0}
+ \NewSocket{tagsupport/tbl/leaders/end}{0}
+ }
% \end{macrocode}
-%
-% The \env{array} environment is math. So we disable table tagging for now.
+%
% \begin{macrocode}
-\AddToHook{env/array/begin} {\__tag_tbl_disable:}
+\NewSocketPlug{tagsupport/tbl/leaders/begin}{code}
+ { \tag_mc_begin:n{artifact} }
+\NewSocketPlug{tagsupport/tbl/leaders/end}{code}
+ { \tag_mc_end: }
% \end{macrocode}
+% \end{plugdecl}
%
%
-% \subsection{Interfaces to tagging}
%
-% \subsubsection{Tagging helper commands}
+%\subsection{Environments}
%
-% \begin{macro}{\@@_set_colspan:n}
-% This commands takes a number, checks if is larger than one,
-% checks if the colspan attribute exists (we can't predefine an
-% arbitrary number), and updates \cs{l_@@_cellattribute_tl}.
+% Currently we support only tabular, tabular*, tabularx and longtable
+% (and possibly environments build directly on top of them).
+%
+% The \env{array} environment is math. So we disable table tagging for now.
+% We use the command hook to catch also cases where \cs{array} is used directly
+% in other environments like matrix environments.
+% Perhaps table tagging should be disable for math generally, but then
+% we have to handle text insertions.
% \begin{macrocode}
-\tag_if_active:T
- { \cs_generate_variant:Nn \__tag_attr_new_entry:nn {ee} }
-\cs_new_protected:Npn \@@_set_colspan:n #1
- {
- \tag_if_active:T
- {
- \int_compare:nNnT {#1}>{1}
- {
- \prop_get:NeNF \g__tag_attr_entries_prop
- {colspan-\int_eval:n{#1}}
- \l_@@_tmpa_tl
- {
- \__tag_attr_new_entry:ee
- {colspan-\int_eval:n{#1}}
- {/O /Table /ColSpan~\int_eval:n{#1}}
- }
- \tl_set:Ne \l_@@_cellattribute_tl
- {colspan-\int_eval:n{#1}}
- }
- }
- }
+\AddToHook{cmd/array/before}{\__tag_tbl_disable:}
% \end{macrocode}
-% \end{macro}
%
+%
+% \subsection{Interfaces to tagging}
+%
+% \subsubsection{Tagging helper commands}
+
% \subsubsection{Disabling/enabling}
%
% For now we have only the option true/false but this will probably be extended
@@ -810,17 +964,25 @@
% \begin{macrocode}
\cs_new_protected:Npn \__tag_tbl_disable:
{
- \AssignSocketPlug{tagsupport/tblcell/begin}{noop}
- \AssignSocketPlug{tagsupport/tblcell/end}{noop}
- \AssignSocketPlug{tagsupport/tblrow/begin}{noop}
- \AssignSocketPlug{tagsupport/tblrow/end}{noop}
+ \AssignSocketPlug{tagsupport/tbl/cell/begin}{noop}
+ \AssignSocketPlug{tagsupport/tbl/cell/end}{noop}
+ \AssignSocketPlug{tagsupport/tbl/pcell/begin}{noop}
+ \AssignSocketPlug{tagsupport/tbl/pcell/end}{noop}
+ \AssignSocketPlug{tagsupport/tbl/row/begin}{noop}
+ \AssignSocketPlug{tagsupport/tbl/row/end}{noop}
\AssignSocketPlug{tagsupport/tbl/init}{noop}
\AssignSocketPlug{tagsupport/tbl/finalize}{noop}
- \AssignSocketPlug{tagsupport/tbl/finalize/longtable}{noop}
- \AssignSocketPlug{tagsupport/tblhmode/begin}{noop}
- \AssignSocketPlug{tagsupport/tblhmode/end}{noop}
- \AssignSocketPlug{tagsupport/tblvmode/begin}{noop}
- \AssignSocketPlug{tagsupport/tblvmode/end}{noop}
+ \AssignSocketPlug{tagsupport/tbl/longtable/init}{noop}
+ \AssignSocketPlug{tagsupport/tbl/longtable/head}{noop}
+ \AssignSocketPlug{tagsupport/tbl/longtable/foot}{noop}
+ \AssignSocketPlug{tagsupport/tbl/longtable/finalize}{noop}
+ \AssignSocketPlug{tagsupport/tbl/hmode/begin}{noop}
+ \AssignSocketPlug{tagsupport/tbl/hmode/end}{noop}
+ \AssignSocketPlug{tagsupport/tbl/vmode/begin}{noop}
+ \AssignSocketPlug{tagsupport/tbl/vmode/end}{noop}
+ \AssignSocketPlug{tagsupport/tbl/colspan}{noop}
+ \AssignSocketPlug{tagsupport/tbl/leaders/begin}{noop}
+ \AssignSocketPlug{tagsupport/tbl/leaders/end}{noop}
}
% \end{macrocode}
% \end{macro}
@@ -831,46 +993,62 @@
% \begin{macrocode}
\cs_new_protected:Npn \__tag_tbl_enable:
{
- \AssignSocketPlug{tagsupport/tblcell/begin}{TD}
- \AssignSocketPlug{tagsupport/tblcell/end}{TD}
- \AssignSocketPlug{tagsupport/tblrow/begin}{TR}
- \AssignSocketPlug{tagsupport/tblrow/end}{TR}
+ \AssignSocketPlug{tagsupport/tbl/cell/begin}{TD}
+ \AssignSocketPlug{tagsupport/tbl/cell/end}{TD}
+ \AssignSocketPlug{tagsupport/tbl/pcell/begin}{TDpbox}
+ \AssignSocketPlug{tagsupport/tbl/pcell/end}{TDpbox}
+ \AssignSocketPlug{tagsupport/tbl/row/begin}{TR}
+ \AssignSocketPlug{tagsupport/tbl/row/end}{TR}
\AssignSocketPlug{tagsupport/tbl/init}{Table}
\AssignSocketPlug{tagsupport/tbl/finalize}{Table}
- \AssignSocketPlug{tagsupport/tbl/finalize/longtable}{Table}
- \AssignSocketPlug{tagsupport/tblhmode/begin}{Table}
- \AssignSocketPlug{tagsupport/tblhmode/end}{Table}
- \AssignSocketPlug{tagsupport/tblvmode/begin}{Table}
- \AssignSocketPlug{tagsupport/tblvmode/end}{Table}
+ \AssignSocketPlug{tagsupport/tbl/longtable/head}{Table}
+ \AssignSocketPlug{tagsupport/tbl/longtable/foot}{Table}
+ \AssignSocketPlug{tagsupport/tbl/longtable/init}{Table}
+ \AssignSocketPlug{tagsupport/tbl/longtable/finalize}{Table}
+ \AssignSocketPlug{tagsupport/tbl/hmode/begin}{Table}
+ \AssignSocketPlug{tagsupport/tbl/hmode/end}{Table}
+ \AssignSocketPlug{tagsupport/tbl/vmode/begin}{Table}
+ \AssignSocketPlug{tagsupport/tbl/vmode/end}{Table}
+ \AssignSocketPlug{tagsupport/tbl/colspan}{code}
+ \AssignSocketPlug{tagsupport/tbl/leaders/begin}{code}
+ \AssignSocketPlug{tagsupport/tbl/leaders/end}{code}
}
% \end{macrocode}
% \end{macro}
% \begin{macrocode}
-% TODO decide about key name
+% See tagpdfsetup-keys.md in tagpdf/doc for the naming scheme.
\keys_define:nn { __tag / setup }
{
- table-tagging .choices:nn = { true, on }
+ table/tagging .choices:nn = { true, on }
{ \__tag_tbl_enable: },
- table-tagging .choices:nn = { false, off }
+ table/tagging .choices:nn = { false, off }
{ \__tag_tbl_disable: },
- table-tagging .default:n = true,
- table-tagging .initial:n = true
+ table/tagging .choice:,
+ table/tagging / presentation .code:n =
+ {
+ \__tag_tbl_enable:
+ \tl_set:Nn\l_@@_rowtag_tl {NonStruct}
+ \tl_set:Nn\l_@@_pcelltag_tl {NonStruct}
+ \tl_set:Nn\l_@@_celltag_tl {text}
+ \tl_set:Nn\l_@@_tabletag_tl {Div}
+ \clist_clear:N \l_@@_header_rows_clist
+ \clist_clear:N \l_@@_header_columns_clist
+ },
+ table/tagging .default:n = true,
+ table/tagging .initial:n = true
}
% \end{macrocode}
-%
-% Table tagging should be disabled in the head and foot.
+% This are the old key names kept for now for
+% compatibility. They will got at some time.
% \begin{macrocode}
-\AddToHook{begindocument}
- {
- \cs_if_exist:NT \@kernel@before@head
- {
- \tl_put_right:Nn \@kernel@before@head {\__tag_tbl_disable:}
- \tl_put_right:Nn \@kernel@before@foot {\__tag_tbl_disable:}
- }
- }
+\keys_define:nn { __tag / setup }
+ {
+ table-tagging .meta:n = {table/tagging={#1}}
+ }
% \end{macrocode}
%
+%
% \subsubsection{Header support}
%
% Accessible table must have header cells declaring the meaning of the
@@ -900,17 +1078,17 @@
{
\tagpdfsetup
{
- newattribute =
+ role/new-attribute =
{TH-col}{/O /Table /Scope /Column},
- newattribute =
+ role/new-attribute =
{TH-row}{/O /Table /Scope /Row},
- newattribute =
+ role/new-attribute =
{TH-both}{/O /Table /Scope /Both},
}
% \end{macrocode}
%
% And we put all three into the class map (perhaps the next tagpdf
-% should do that directly with newattribute):
+% should do that directly with role/new-attribute):
%
% \begin{macrocode}
\seq_gput_left:Ne\g__tag_attr_class_used_seq
@@ -924,30 +1102,16 @@
% \end{macrocode}
%
-% \begin{variable}{\l_@@_header_rows_clist}
-% This holds the numbers of the header rows. Negative numbers are
-% possible and count from the back.
+% \begin{variable}{\l_@@_header_rows_clist,\l_@@_header_columns_clist}
+% This holds the numbers of the header rows and columns. Negative numbers are
+% possible and count from the last column backwards.
% \begin{macrocode}
\clist_new:N \l_@@_header_rows_clist
+\clist_new:N \l_@@_header_columns_clist
% \end{macrocode}
% \end{variable}
%
% \begin{macro}{\@@_set_header_rows:}
-% TEMP: Next tagpdf will have the right command which also updates
-% the debug info.
-% For now a temporary command:
-% \begin{macrocode}
-\cs_if_free:NTF \__tag_struct_prop_gput:nnn
- {
- \cs_new_protected:Npn \@@_struct_prop_gput:nnn #1#2#3
- { \prop_gput:cnn { g__tag_struct_#1_prop }{#2}{#3} }
- }
- { \cs_new_protected:Npn \@@_struct_prop_gput:nnn #1#2#3
- { \__tag_struct_prop_gput:nnn {#1}{#2}{#3} }
- }
-\cs_generate_variant:Nn \@@_struct_prop_gput:nnn {nne,Vnn}
-% \end{macrocode}
-%
% \begin{macrocode}
\cs_new_protected:Npn \@@_set_header_rows:
{
@@ -964,17 +1128,29 @@
% \begin{macrocode}
\prop_if_exist:cT { g__tag_struct_####1_prop }
{
- \@@_struct_prop_gput:nnn{ ####1 }{S}{/TH}
+ \__tag_struct_prop_gput:nnn{ ####1 }{S}{/TH}
% \end{macrocode}
-% This need refinement once row headers (and perhaps other attributes)
-% are used too, but for now it should be ok.
+% This sets the scope class. If the header has already a row attribute
+% we replace by TH-both.
% \begin{macrocode}
\prop_get:cnNTF
{ g__tag_struct_####1_prop }
{ C }
\l_@@_tmpa_tl
- {\@@_struct_prop_gput:nne{ ####1 }{C}{[/TH-col~\l_@@_tmpa_tl]} }
- {\@@_struct_prop_gput:nnn{ ####1 }{C}{/TH-col}}
+ {
+ \str_set:Ne \l_@@_tmpa_str {\l_@@_tmpa_tl}
+ \str_remove_once:Nn \l_@@_tmpa_str {[}
+ \str_remove_once:Nn \l_@@_tmpa_str {]}
+ \str_if_in:NnTF\l_@@_tmpa_str{/TH-row}
+ {
+ \str_replace_once:Nnn \l_@@_tmpa_str {/TH-row}{/TH-both}
+ \__tag_struct_prop_gput:nne{ ####1 }{C}{[\l_@@_tmpa_str]}
+ }
+ {
+ \__tag_struct_prop_gput:nne{ ####1 }{C}{[/TH-col~\l_@@_tmpa_str]}
+ }
+ }
+ {\__tag_struct_prop_gput:nnn{ ####1 }{C}{/TH-col}}
}
}
}
@@ -983,261 +1159,169 @@
% \end{macro}
%
% And some key support:
+% (See tagpdfsetup-keys.md for the naming scheme.)
% \begin{macrocode}
-% TODO decide about key name
\keys_define:nn { __tag / setup }
{
- table-header-rows .clist_set:N = \l_@@_header_rows_clist
- }
+ table/header-rows .clist_set:N = \l_@@_header_rows_clist,
+ table/header-columns .clist_set:N = \l_@@_header_columns_clist,
% \end{macrocode}
-%
-% \subsection{Changes to \pkg{array} commands}
-%
-%
-%
-% \begin{macro}{\@@_show_curr_cell_data:}
-% Show the row/column index and span count for current table cell
-% for debugging.
-% \begin{macrocode}
-\cs_new_protected:Npn \@@_show_curr_cell_data: {
- \typeout { ==>~ current~cell~data:~
- \int_use:N \g_@@_row_int ,
- \int_use:N \g_@@_col_int ,
- \g_@@_span_tl
- }
-}
-% \end{macrocode}
-% \end{macro}
-%
-%
-%
-%
-% \begin{macro}{\insert@column}
-% \cs{insert@column} is defined in \pkg{array}, here only the two
-% sockets are inserted.
-% \begin{macrocode}
-\def\insert@column{%
- \@@_show_curr_cell_data:
- \UseSocket{tagsupport/tblcell/begin}%
- \the@toks \the \@tempcnta
- \ignorespaces \@sharp \unskip
- \the@toks \the \count@ \relax
- \UseSocket{tagsupport/tblcell/end}%
-}
-% \end{macrocode}
-% \end{macro}
-%
-%
-% \begin{macro}{\@classz}
-% \begin{macrocode}
-\def\@classz{\@classx
- \@tempcnta \count@
- \prepnext@tok
- \@addtopreamble{\ifcase \@chnum
- \hfil
- \hskip1sp%
- \d@llarbegin
- \insert@column
- \d@llarend \do@row@strut \hfil \or
- \hskip1sp\d@llarbegin \insert@column \d@llarend \do@row@strut \hfil \or
- \hfil\hskip1sp\d@llarbegin \insert@column \d@llarend \do@row@strut \or
- \setbox\ar@mcellbox\vbox
- \@startpbox{\@nextchar}
- \AssignSocketPlug{tagsupport/tblcell/begin}{TDpbox}
- \AssignSocketPlug{tagsupport/tblcell/end}{TDpbox}
- \insert@column \@endpbox
- \ar@align@mcell
- \do@row@strut \or
- \vtop \@startpbox{\@nextchar}
- \AssignSocketPlug{tagsupport/tblcell/begin}{TDpbox}
- \AssignSocketPlug{tagsupport/tblcell/end}{TDpbox}
- \insert@column \@endpbox\do@row@strut \or
- \vbox \@startpbox{\@nextchar}
- \AssignSocketPlug{tagsupport/tblcell/begin}{TDpbox}
- \AssignSocketPlug{tagsupport/tblcell/end}{TDpbox}
- \insert@column \@endpbox\do@row@strut
- \fi}\prepnext@tok}
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\@array,\@@@@array}
-% We modificate the \cs{@array} from \pkg{array}.
-% \begin{macrocode}
-\def\@array[#1]#2{%
- \@tempdima \ht \strutbox
- \advance \@tempdima by\extrarowheight
- \setbox \@arstrutbox \hbox{\vrule
- \@height \arraystretch \@tempdima
- \@depth \arraystretch \dp \strutbox
- \@width \z@}%
-% \end{macrocode}
-% The total number of table columns of the current table is
-% determined in \cs{@@_determine_table_cols:} but this is called in
-% a group, so local settings do not survive. Thus, to save away the
-% outer value of \cs{g_@@_table_cols_tl} we do it before the group.
+% obsolete older name:
% \begin{macrocode}
- \tl_set_eq:NN \l_@@_saved_table_cols_tl \g_@@_table_cols_tl
+ table-header-rows .meta:n = {table/header-rows={#1}}
+ }
% \end{macrocode}
%
-% \begin{macrocode}
- \begingroup
- \@mkpream{#2}
-% \end{macrocode}
-% Next call has to happen immediately after \cs{@mkpream} because
-% it uses implementation details from that.
-% \begin{macrocode}
- \@@_determine_table_cols:
+% \subsection{Multirow support}
+%
+% \begin{macro}{\@@_multirow:n}
+% This command makes the current cell into a multirow cell:
+% it creates, if needed, an RowSpan-attribute, adds it to the attributes
+% of the cell structure, and marks all following cells spanned by the multirow
+% as cells that should not be tagged. The argument is the number of spanned row
+% (including the current row).
+% \begin{macrocode}
+\cs_if_exist:NT \__tag_struct_prop_gput:nnn
+ {
+ \cs_generate_variant:Nn \__tag_struct_prop_gput:nnn {one}
+ }
+\cs_new_protected:Npn \@@_multirow:n #1
+ {
% \end{macrocode}
-%
+% Create an attribute if needed:
% \begin{macrocode}
- \xdef\@preamble{%
- \noexpand
+ \prop_get:NeNF \g__tag_attr_entries_prop
+ {rowspan-\int_eval:n{#1}}
+ \l_@@_tmpa_tl
+ {
+ \__tag_attr_new_entry:ee
+ {rowspan-\int_eval:n{#1}}
+ {/O /Table /RowSpan~\int_eval:n{#1}}
+ }
% \end{macrocode}
-% \cs{ialign} in the original definition is replaced by
-% \cs{ar@ialign} defined below.
+% ensure that the attribute is marked as used:
% \begin{macrocode}
- \ar@ialign
- \@halignto
- \bgroup \@arstrut
+ \seq_gput_left:Ne\g__tag_attr_class_used_seq
+ {\pdf_name_from_unicode_e:n{rowspan-\int_eval:n{#1}}}
% \end{macrocode}
-% A socket is inserted
+% Get the structure number of the current cell
% \begin{macrocode}
- \UseSocket{tagsupport/tblrow/begin}%
+ \seq_get_right:NN\g_@@_struct_cur_seq \l_@@_tmpb_tl
% \end{macrocode}
-% At the start of the preamble for the first column we set
-% \cs{g_@@_col_int} to \texttt{1} as we are no longer "at" but "in"
-% the first column. This is done in \cs{@@_init_cell_data:}. In
-% later columns this data is updated via \cs{@@_update_cell_data:}.
+% If we are in a multicolumn the number can be negative and
+% this must be changed
% \begin{macrocode}
- \@@_init_cell_data:
- \@preamble
- \tabskip \z@ \cr}%
- \endgroup
- \@arrayleft
+ \tl_set:Ne \l_@@_tmpb_tl { \int_abs:n{\l_@@_tmpb_tl} }
% \end{macrocode}
-% Another socket for tagging. TODO: what about \cs{arrayleft}?
+% no we must update an existing attribute.
+% TODO: simplify this ... (see also colspan handling).
% \begin{macrocode}
- \UseSocket{tagsupport/tbl/init}
- \if #1t\vtop \else \if#1b\vbox \else \vcenter \fi \fi
- \bgroup
- \let \@sharp ##\let \protect \relax
- \lineskip \z@
- \baselineskip \z@
- \m@th
- \let\\\@arraycr \let\tabularnewline\\\let\par\@empty
-%\show\@preamble
- \@preamble}
+ \prop_get:cnNTF
+ { g__tag_struct_\l_@@_tmpb_tl _prop }
+ { C }
+ \l_@@_tmpa_tl
+ {
+ \tl_remove_once:Nn \l_@@_tmpa_tl {[}
+ \tl_remove_once:Nn \l_@@_tmpa_tl {]}
+ \__tag_struct_prop_gput:one{ \l_@@_tmpb_tl }
+ {C}
+ {[/rowspan-\int_eval:n{#1}~\l_@@_tmpa_tl]}
+ }
+ {
+ \__tag_struct_prop_gput:one{ \l_@@_tmpb_tl }
+ {C}
+ {[/rowspan-\int_eval:n{#1}]}
+ }
% \end{macrocode}
-% Finally, also set \cs{@@@@array} to the new definition:
+% Now mark the spanned cells that should be ignored.
% \begin{macrocode}
-\let\@@@@array\@array
+ \@@_gset_untagged_row_cells:nn {#1-1}{\g_@@_span_tl}
+ }
% \end{macrocode}
% \end{macro}
%
-%
-% \begin{macro}{\@@_init_cell_data:}
-%
% \begin{macrocode}
-\cs_new_protected:Npn \@@_init_cell_data: {
- \int_gset:Nn \g_@@_col_int {1}
- \tl_gset:Nn \g_@@_span_tl {1}
-}
+\keys_define:nn{ __tag / setup }
+ { table/multirow .code:n = {\@@_multirow:n {#1} }
+ ,table/multirow .default:n = 1
+ }
% \end{macrocode}
-% \end{macro}
%
-% \begin{macro}{\@@_update_cell_data:}
-% Updating cell data in columns after the first means we have to
-% increment the \cs{g_@@_col_int} by the span count of the previous
-% cell (in case it was a \cs{multicolumn} and then reset the
-% \cs{g_@@_span_tl} to one (as the default).
+% \begin{macro}{\@@_gset_untagged_row_cells:nn}
+% This command stores the row and column numbers of the cells in the following row(s)
+% that should not be tagged as they are a part of a rowspan.
% \begin{macrocode}
-\cs_new_protected:Npn \@@_update_cell_data: {
- \int_gadd:Nn \g_@@_col_int { \g_@@_span_tl }
- \tl_gset:Nn \g_@@_span_tl {1}
-}
+\cs_new_protected:Npn \@@_gset_untagged_row_cells:nn #1 #2 % #1 number of rows, #2 number of columns
+ {
+ \int_step_inline:nn {#1}
+ {
+ \int_step_inline:nn {#2}
+ {
+ \prop_gput:Nee \g_@@_untagged_cells_prop
+ { \int_eval:n {\g_@@_row_int + ##1},\int_eval:n{\g_@@_col_int + ####1 -1 } }{}
+ }
+ }
+ }
% \end{macrocode}
-% \end{macro}
-%
-%
-%
-% \begin{macro}{\@@_determine_table_cols:}
-% Current implementation of \cs{@mkpream} uses the scratch counter
-% \cs{count@} to keep track of the number of toks registers it needs
-% (2 per column), but this can't be used as it counts also
-% insertings made with \verb+!{}+ and \verb+@{}+.
-% So similar as does longtable for \cs{LT@cols} we count the
-% numbers of ambersands instead.
+% \end{macro}
+%
+% \begin{macro}{\@@_if_tag_cell:nn}
+% We must be able to detect if a cell should be tagged. For this
+% we define a conditional --- if more options are needed it can be extended.
% \begin{macrocode}
-\cs_new:Npn \@@_determine_table_cols: {
- \seq_set_split:NnV\l_@@_tmpa_seq {&}\@preamble
- \tl_gset:Ne \g_@@_table_cols_tl { \seq_count:N \l_@@_tmpa_seq }
- \typeout{ ==>~ Table~ has~ \g_@@_table_cols_tl \space columns }
-}
+\prg_new_protected_conditional:Npnn\@@_if_tag_cell:nn #1 #2 %#1 row, #2 col
+ { T,TF }
+ {
+ \prop_get:NeNTF \g_@@_untagged_cells_prop
+ {\int_eval:n{#1},\int_eval:n{#2}}\l__tbl_tmpa_tl
+ { \prg_return_false:}
+ { \prg_return_true: }
+ }
% \end{macrocode}
-% \end{macro}
-%
+% \end{macro}
+%
+% \subsection{Misc stuff}
%
-% \begin{macro}{\@arraycr}
-% Add code that figures out if the current table row is incomplete
-% (not enough \verb=&=s). It can then do extra actions, such as
-% inserting missing cell tags.
+% \begin{macro}{\@@_show_curr_cell_data:}
+% Show the row/column index and span count for current table cell
+% for debugging.
% \begin{macrocode}
-\protected\def\@arraycr{
- \relax
- \@@_store_missing_cells:n{@arraycr}
- %
- \iffalse{\fi\ifnum 0=`}\fi
- \@ifstar \@xarraycr \@xarraycr}
+\cs_new_protected:Npn \@@_show_curr_cell_data: {
+ \@@_trace:n { ==>~ current~cell~data:~
+ \int_use:N \g_@@_row_int ,
+ \int_use:N \g_@@_col_int ,
+ \g_@@_span_tl
+ }
+}
% \end{macrocode}
% \end{macro}
%
%
%
-% \begin{macro}{\@@_store_missing_cells:n,
-% \__tag_tbl_add_missing_cells:n}
-% The storing and use of the number of missing cells
-% must happen at different places as the testing happens at
-% the end of the last cell of a row, but
-% still inside that cell, so we use two commands. The second is used in
-% the endrow socket.
+% \begin{macro}{\@@_add_missing_cells:}
+% The storing and use of the number of missing cells must happen at
+% different places as the testing happens at the end of the last
+% cell of a row, but still inside that cell, so we use two
+% commands. The one adding is used in the row/end socket.
% \begin{macrocode}
-\cs_new:Npn \@@_store_missing_cells:n #1 {
- \int_compare:nNnT \g_@@_col_int > 0
- {
- \int_gset:Nn \g_@@_missing_cells_int
- {
- \g_@@_table_cols_tl
- - \g_@@_col_int
- - \g_@@_span_tl
- + 1
- }
- \int_compare:nNnT \g_@@_missing_cells_int < 0 \ERROR % should not happen
- \typeout{==>~
- (#1)~
- This~ row~ needs~
- \int_use:N \g_@@_missing_cells_int \space
- additional~ cell(s)
- }
- }
-}
-% \end{macrocode}
-%
-% \begin{macrocode}
-\cs_new:Npn \__tag_tbl_add_missing_cells:n #1
+\cs_new:Npn \@@_add_missing_cells:
{
% \end{macrocode}
-% The TD-socket messages are issued after the message about the end-row socket,
-% but the structure is ok, so better issue a message for now to avoid confusion:
+% The TD-socket messages are issued after the message about the
+% end-row socket, but the structure is ok, so better issue a
+% message for now to avoid confusion:
% \begin{macrocode}
- \int_compare:nNnT {#1}>{0}
- {
- \typeout{==>~
- ~Inserting~\int_eval:n{#1}~additional~cell(s)~into~previous~row:}
- }
- \int_step_inline:nn { #1 }
+ \int_compare:nNnT \g_@@_missing_cells_int > 0
{
- \UseSocket{tagsupport/tblcell/begin}
- \UseSocket{tagsupport/tblcell/end}
+ \@@_trace:n {==>~
+ ~Inserting~\int_use:N \g_@@_missing_cells_int \space
+ additional~cell(s)~into~previous~row:}
+ \int_step_inline:nn { \g_@@_missing_cells_int }
+ {
+ \int_gincr:N\g_@@_col_int
+ \UseTaggingSocket{tbl/cell/begin}
+ \UseTaggingSocket{tbl/cell/end}
+ }
}
}
% \end{macrocode}
@@ -1245,119 +1329,8 @@
%
%
%
-% \begin{macro}{\endarray}
-% If tables are nested into another then it is necessary to
-% restore information about the cell the inner table started
-% in. Otherwise, \cs{g_@@_row_int}, \cs{g_@@_col_int}, and
-% \cs{g_@@_span_tl} reflect the status in the outer table as they
-% are globally manipulated. We restore in all cases even if we are
-% not in a nesting situation as that makes the code simpler (and
-% probably faster).
-%
-% \cs{endtabular} and \cs{endtabular*} inherit from \cs{endarray}
-% so we only need to change that. \texttt{tabularx} is handled
-% below.
-% \begin{macrocode}
-\def\endarray{
- \@@_store_missing_cells:n{endarray}
- \crcr \egroup
- \UseSocket{tagsupport/tbl/finalize}
- \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
- \tl_gset_eq:NN \g_@@_struct_table_tl \l_@@_saved_struct_table_tl
- \seq_gset_eq:NN \g_@@_struct_rows_seq \l_@@_saved_struct_rows_seq
- \seq_gset_eq:NN \g_@@_struct_cells_seq\l_@@_saved_struct_cells_seq
- \seq_gset_eq:NN \g_@@_struct_cur_seq \l_@@_saved_struct_cur_seq
- \typeout{==>~ restored~cell~data:~
- \int_use:N \g_@@_row_int,
- \int_use:N \g_@@_col_int,
- \l_@@_saved_span_tl \space
- (
- \int_compare:nNnTF \g_@@_table_cols_tl = 0
- { outer~ level }
- { max:~ \g_@@_table_cols_tl }
- )
- }
- \egroup
- \@arrayright \gdef\@preamble{}%
-}
-% \end{macrocode}
-% \end{macro}
-%
-%
-% \begin{macro}{\@addamp}
-% If we are after the first column we have to insert a \verb=&= and
-% also update the cell data.
-% \begin{macrocode}
-\def\@addamp {
- \if@firstamp
- \@firstampfalse
- \else
- \edef\@preamble{\@preamble &
- \@@_update_cell_data:
- }
- \fi
-}
-% \end{macrocode}
-% \end{macro}
-%
-%
-%
-% \begin{macro}{
-% \g_@@_col_int,
-% \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. It
-% is incremented by every \cs{cr} including the one ending the
-% table preamble.
-%
-% \cs{g_@@_col_int} holds the current column number. The value
-% \texttt{0} means we have not yet started the table or just finished a table row
-% (with \verb=\\= typically); any other positive value means we
-% are currently typesetting a cell in that column in some row
-% (denoted by the \cs{g_@@_row_int}.
-%
-% In a \cs{multicolumn} it holds the column number of the first
-% spanned column and \cs{g_@@_span_tl} the info how many cells are
-% spanned.
-%
-% \cs{g_@@_span_tl} is normally \texttt{1} except in a
-% \cs{multicolumn} cell.
-% \begin{macrocode}
-\int_new:N \g_@@_col_int
-\int_new:N \g_@@_row_int
-\tl_new:N \g_@@_span_tl
-\tl_new:N \g_@@_table_cols_tl
-
-\tl_gset:Nn \g_@@_span_tl {1}
-\tl_gset:Nn \g_@@_table_cols_tl {0} % indicates outer level
-% \end{macrocode}
-% \end{macro}
%
%
-% \begin{macro}{\l_@@_saved_col_tl,\l_@@_saved_row_tl,
-% \l_@@_saved_span_tl,\l_@@_saved_table_cols_tl}
-%
-% Saving the outer values if we are nesting tables is necessary (as
-% the above variables are globally altered. For this we use always
-% token lists because they don't change and we do not need to blow
-% additional integer registers.
-% \begin{macrocode}
-\tl_new:N \l_@@_saved_col_tl
-\tl_new:N \l_@@_saved_row_tl
-\tl_new:N \l_@@_saved_span_tl
-\tl_new:N \l_@@_saved_table_cols_tl
-
-\tl_set:Nn \l_@@_saved_col_tl{0}
-\tl_set:Nn \l_@@_saved_row_tl{0}
-\tl_set:Nn \l_@@_saved_span_tl{1}
-\tl_set:Nn \l_@@_saved_table_cols_tl{0} % indicates outer level
-% \end{macrocode}
-% \end{macro}
%
% \begin{macro}
% {
@@ -1390,475 +1363,54 @@
\seq_new:N \l_@@_saved_struct_cur_seq
% \end{macrocode}
% \end{macro}
+
+
+
+% \begin{macro}{\@@_init_struct_data:}
+% Save the global structure data variables locally so the we can
+% restore them when the table ends (important in case of nested
+% tables).
%
-% \begin{macro}{\ar@ialign}
-% A new command that replaces \cs{ialign} above. \cs{everycr} is
-% also applied to the \cs{cr} ending the preamble so we have to
-% program around that.
+% This is also the right point to initialize
+% them. \cs{g_@@_struct_table_tl} is set elsewhere.
% \begin{macrocode}
-\def\ar@ialign{%
-% \end{macrocode}
-% Before starting a table we locally stored the information related
-% to the current cell (if any) so that we can restore it once the
-% table is finished.
-% \begin{macrocode}
- \tl_set:No \l_@@_saved_col_tl {\int_use:N \g_@@_col_int }
- \tl_set:No \l_@@_saved_row_tl {\int_use:N \g_@@_row_int }
- \tl_set_eq:NN \l_@@_saved_span_tl \g_@@_span_tl
+\cs_new_protected:Npn \@@_init_struct_data: {
\tl_set_eq:NN \l_@@_saved_struct_table_tl \g_@@_struct_table_tl
\seq_set_eq:NN \l_@@_saved_struct_rows_seq \g_@@_struct_rows_seq
\seq_set_eq:NN \l_@@_saved_struct_cells_seq \g_@@_struct_cells_seq
\seq_set_eq:NN \l_@@_saved_struct_cur_seq \g_@@_struct_cur_seq
%
- \typeout{==>~ saved~cell~data:~
- \l_@@_saved_row_tl,
- \l_@@_saved_col_tl,
- \l_@@_saved_span_tl \space
- (
- \int_compare:nNnTF \l_@@_saved_table_cols_tl = 0
- { outer~ level }
- { max:~ \l_@@_saved_table_cols_tl }
- )
- }
-% \end{macrocode}
-% These are the initial values when starting a table:
-% \begin{macrocode}
- \int_gzero:N \g_@@_row_int
- \int_gzero:N \g_@@_col_int
- \tl_gset:Nn \g_@@_span_tl {1}
\seq_gclear:N\g_@@_struct_rows_seq
\seq_gclear:N\g_@@_struct_cells_seq
\seq_gclear:N\g_@@_struct_cur_seq
+}
% \end{macrocode}
-%
-% \begin{macrocode}
- \everycr{%
- \noalign{%
-% \end{macrocode}
-% We use \cs{g_@@_col_int} equal zero to indicate that we are just
-% after a TR (or at the very beginning of the table). Using the row
-% count is not so good as longtable may split the table in chunks.
-% \begin{macrocode}
- \int_compare:nNnT \g_@@_col_int > 0
- { \UseSocket{tagsupport/tblrow/end} }
- \int_gincr:N \g_@@_row_int % this row about to start
- \int_gzero:N \g_@@_col_int % we are before first col
- }%
- }%
- \tabskip\z@skip\halign}
-% \end{macrocode}
-% \end{macro}
-%
-%
-% \begin{macro}{\multicolumn}
-%
-% \cs{multicolumn} is also defined in \pkg{array}. The redefinition
-% has to solve two problems: it must handle the row begin if it is
-% used there, and it must save the numbers of cells it spans so
-% that we can add a suitable ColSpan attribute.\footnote{FMi: This can
-% now perhaps cleaned up somewhat}
-% \begin{macrocode}
-\long\def\multicolumn#1#2#3{%
- % alternative: determine first col with vmode test ...
- % \ifvmode
- % \multispan{#1}\typeout{A==> vmode}%
- % \else
- % \multispan{#1}\typeout{A==> not vmode}
- % \fi
- % but this makes the \crcr handling really complicated which would
- % then need to become something like
- % \ifvmode \expandafter \@gobble
- % \else \expandafter \@iden \fi {\cr\noalign{do something}}%
- % so not used.
- % Instead:
- \multispan{#1}\begingroup
-% \end{macrocode}
-% Insert rowbegin socket only if this multicolumn
-% replaces the preamble of the first column. In that case we have
-% to set \cs{g_@@_col_int} to 1 since this is no longer done in the
-% preamble for the cell.
-% \begin{macrocode}
- \int_compare:nNnTF \g_@@_col_int = 0
- {
- \UseSocket{tagsupport/tblrow/begin}
- \int_gset:Nn \g_@@_col_int {1}
- }
-% \end{macrocode}
-% If we are in a later column we use \cs{g_@@_span_tl} from the
-% previous column to update.
-% \begin{macrocode}
- {
- \int_gadd:Nn \g_@@_col_int { \g_@@_span_tl }
- }
-% \end{macrocode}
-% Then we set the span value so that it can be use in the next column.
+% \end{macro}
+
+
+
+
+% \begin{macro}{\@@_restore_struct_data:}
+%
% \begin{macrocode}
- \tl_gset:Nn \g_@@_span_tl {#1}
+\cs_new_protected:Npn \@@_restore_struct_data: {
+ \tl_gset_eq:NN \g_@@_struct_table_tl \l_@@_saved_struct_table_tl
+ \seq_gset_eq:NN \g_@@_struct_rows_seq \l_@@_saved_struct_rows_seq
+ \seq_gset_eq:NN \g_@@_struct_cells_seq\l_@@_saved_struct_cells_seq
+ \seq_gset_eq:NN \g_@@_struct_cur_seq \l_@@_saved_struct_cur_seq
+}
% \end{macrocode}
+% \end{macro}
+
+
%
-% \begin{macrocode}
- \def\@addamp{\if@firstamp\@firstampfalse \else
- \@preamerr 5\fi}%
- \@mkpream{#2}\@addtopreamble\@empty
- \endgroup
-% \end{macrocode}
-% Now we update the colspan attribute. This needs setting after
-% the group as it is hidden inside the plug in \cs{insert@column}.
-% \begin{macrocode}
- \@@_set_colspan:n {#1}
-% \end{macrocode}
-% \begin{macrocode}
- \def\@sharp{#3}%
- \@arstrut \@preamble
- \null
- \ignorespaces}
-% \end{macrocode}
-% \end{macro}
%
% \subsection{longtable}
%
-% Longtable is complicated. When at the begin the \cs{endhead},
-% \cs{endfirsthead}, \cs{endfoot} and \cs{endlastfoot} are used to
-% setup head and foot they create each a structure subtree with one or
-% more rows. From this structures we want to keep at most two (head
-% and foot) and move the foot to the end of the table. When the head
-% and foot boxes are (re)inserted on following pages we want to mark
-% them up as artifact with the exception of the head at the begin and
-% the foot box at the end.
-%
-% TODO: When a line is killed the structure subtree is there already
-% too and must be removed.
-%
-% Hyperref patches longtable. This must be disabled and replace with
-% genuine code
-% \begin{macrocode}
-\let\@kernel@refstepcounter\refstepcounter
-\def\hyper@nopatch@longtable{}
-% \end{macrocode}
-% \begin{macrocode}
-\def\@@_patch_LT@array[#1]#2{%
-% \end{macrocode}
-% \cs{LT@array} is executed in a group, so we can disable para-tagging here.
-% \begin{macrocode}
- \UseSocket{tagsupport/tbl/init}%
- \@kernel@refstepcounter{table}\stepcounter{LT@tables}%
-% \end{macrocode}
-% The target is created rather late and a \cs{label} can come earlier,
-% so we have to define \cs{@currentHref} explicitly. We can't currently
-% assume that \cs{theHtable} is defined always.
-% \begin{macrocode}
- \tl_gset:Ne \@currentHref {table.\cs_if_exist_use:N\theHtable}
- \int_gzero:N \g_@@_row_int
- \seq_gclear:N\g_@@_struct_rows_seq
- \seq_gclear:N\g_@@_struct_cells_seq
- \seq_gclear:N\g_@@_struct_cur_seq
- \seq_gclear:N\g_@@_LT@firsthead_rows_seq
- \seq_gclear:N\g_@@_LT@head_rows_seq
- \seq_gclear:N\g_@@_LT@lastfoot_rows_seq
- \seq_gclear:N\g_@@_LT@foot_rows_seq
- \if l#1%
- \LTleft\z@ \LTright\fill
- \else\if r#1%
- \LTleft\fill \LTright\z@
- \else\if c#1%
- \LTleft\fill \LTright\fill
- \fi\fi\fi
- \let\LT@mcol\multicolumn
- \let\LT@@@@tabarray\@tabarray
- \let\LT@@@@hl\hline
- \def\@tabarray{%
- \let\hline\LT@@@@hl
- \LT@@@@tabarray}%
- \let\\\LT@tabularcr
- \let\tabularnewline\\%
- \def\newpage{\noalign{\break}}%
- \def\pagebreak{\noalign{\ifnum`}=0\fi\@testopt{\LT@no@pgbk-}4}%
- \def\nopagebreak{\noalign{\ifnum`}=0\fi\@testopt\LT@no@pgbk4}%
- \let\hline\LT@hline \let\kill\LT@kill\let\caption\LT@caption
- \@tempdima\ht\strutbox
- \let\@endpbox\LT@endpbox
- \ifx\extrarowheight\@undefined
- \let\@acol\@tabacol
- \let\@classz\@tabclassz \let\@classiv\@tabclassiv
- \def\@startpbox{\vtop\LT@startpbox}%
- \let\@@@@startpbox\@startpbox
- \let\@@@@endpbox\@endpbox
- \let\LT@LL@FM@cr\@tabularcr
- \else
- \advance\@tempdima\extrarowheight
- \col@sep\tabcolsep
- \let\@startpbox\LT@startpbox\let\LT@LL@FM@cr\@arraycr
- \fi
- \setbox\@arstrutbox\hbox{\vrule
- \@height \arraystretch \@tempdima
- \@depth \arraystretch \dp \strutbox
- \@width \z@}%
- \let\@sharp##\let\protect\relax
- \begingroup
- \@mkpream{#2}%
- \@@_determine_table_cols:
- \xdef\LT@bchunk{%
-% \end{macrocode}
-% At the start of a chunk we set \cs{g_@@_col_int} to zero to make
-% sure that we aren't generating /TR with the \cs{cr} ending the
-% chunk preamble.
-% \begin{macrocode}
- \int_gzero:N \g_@@_col_int
- \global\advance\c@LT@chunks\@ne
- \global\LT@rows\z@\setbox\z@\vbox\bgroup
- \LT@setprevdepth
- \tabskip\LTleft \noexpand\halign to\hsize\bgroup
- \tabskip\z@ \@arstrut
-% \end{macrocode}
-% Insert the socket and the setting of the conditional
-% \begin{macrocode}
- \UseSocket{tagsupport/tblrow/begin}%
- \@@_init_cell_data:
-% \end{macrocode}
-% \begin{macrocode}
- \@preamble \tabskip\LTright \cr}%
- \endgroup
- \expandafter\LT@nofcols\LT@bchunk&\LT@nofcols
- \LT@make@row
- \m@th\let\par\@empty
-% \end{macrocode}
-% Socket and conditional
-% \begin{macrocode}
- \everycr{%
- \noalign{%
-% \end{macrocode}
-% In \pkg{longtable} we have a bunch of extra \cs{cr}s that are
-% executed whenever a chunk ends. In that case they should not
-% increment the main row counter, sigh.
-% \begin{macrocode}
- \typeout{--longtable-->~chunk~row:~ \the\LT@rows \space
- row:~ \the\g_@@_row_int \space
- column:~ \the\g_@@_col_int
- }
- \int_compare:nNnT \g_@@_col_int > 0
- {
- \UseSocket{tagsupport/tblrow/end}
- }
-% \end{macrocode}
-% This prevents any of the additional \cs{cr}s at the end of the
-% chunk to add another /TR. Then once we really start a new chunk
-% it gets incremented so\ldots
-% \begin{macrocode}
- \int_gzero:N \g_@@_col_int % before first col
-% \end{macrocode}
-% And for the same reason such \cs{cr}s should not increment the
-% main row counter (but it has to be incremented after the preamble
-% of a chunk), so here we test against \cs{LT@rows} which is
-% \cs{LTchunksize} at the end of a chunk.
-% \begin{macrocode}
- \int_compare:nNnT \LT@rows < \LTchunksize
- { \int_gincr:N \g_@@_row_int } % this row about to start
- }%
- }%
-% \end{macrocode}
-% \begin{macrocode}
- \lineskip\z@\baselineskip\z@
- \LT@bchunk}
-% \end{macrocode}
-% The end code most stop to insert the endrow too.
-% \begin{macrocode}
-\def\@@_patch_endlongtable{%
- \@@_store_missing_cells:n{endlongtable}
- \crcr
- \noalign{%
- \UseSocket{tagsupport/tbl/finalize/longtable}
- \int_gzero:N \g_@@_row_int % this prevents considering the next
- % \crcr as another row end.
- \let\LT@entry\LT@entry@chop
- \xdef\LT@save@row{\LT@save@row}}%
- \LT@echunk
- \LT@start
- \unvbox\z@
- \LT@get@widths
- \if@filesw
- {\let\LT@entry\LT@entry@write\immediate\write\@auxout{%
- \gdef\expandafter\noexpand
- \csname LT@\romannumeral\c@LT@tables\endcsname
- {\LT@save@row}}}%
- \fi
- \ifx\LT@save@row\LT@@@@save@row
- \else
- \LT@warn{Column~\@width s~have~changed\MessageBreak
- in~table~\thetable}%
- \LT@final@warn
- \fi
- \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@
- \fi
- \endgroup
- \global\@mparbottom\z@
- \endgraf\penalty\z@\addvspace\LTpost
- \ifvoid\footins\else\insert\footins{}\fi}
-% \end{macrocode}
-%
-%
-%
-% \begin{macro}{\@@_patch_LT@t@bularcr}
-%
-% \begin{macrocode}
-\def\@@_patch_LT@t@bularcr{%
- \global\advance\LT@rows\@ne
- \ifnum\LT@rows=\LTchunksize
-% \end{macrocode}
-% At the end of the chunk \verb=\\= is doing something special and
-% so we loose \cs{@@_store_missing_cells:n}. Below is about the
-% right place to add it do this code branch.
-% \begin{macrocode}
- \@@_store_missing_cells:n{echunk}
- \gdef\LT@setprevdepth{%
- \prevdepth\z@
- \global\let\LT@setprevdepth\relax}%
- \expandafter\LT@xtabularcr
- \else
- \ifnum0=`{}\fi
- \expandafter\LT@LL@FM@cr
- \fi}
-
-% \end{macrocode}
-% \end{macro}
-%
%
%
-% \begin{macro}{\@@_patch_LT@end@hd@ft}
-% This command is used to store the head and foot boxes.
-% We need to retrieve and store the row so that we can clean
-% up the structure in the finalize code.
-% \begin{macrocode}
-\def\@@_patch_LT@end@hd@ft#1{%
-% \end{macrocode}
-% To handle missing columns in the header we need this:
-% \begin{macrocode}
- \__tbl_store_missing_cells:n{head/foot}
- \int_step_inline:nn
- { \LT@rows + 1 }
- {
- \seq_gput_left:ce
- {g_@@_\cs_to_str:N #1 _rows_seq }
- { \int_eval:n {\g_@@_row_int + 1 - ##1 } }
- }
-% \end{macrocode}
-% We also have to set the chunk rows to its max value before
-% calling \cs{LTechunk} so that we don't get extra increments of
-% the main row counter due to \cs{everycr}.
-% \begin{macrocode}
- \int_gset:Nn \LT@rows { \LTchunksize }
- \LT@echunk
- \ifx\LT@start\endgraf
- \LT@err
- {Longtable head or foot not at start of table}%
- {Increase LTchunksize}%
- \fi
- \setbox#1\box\z@
- \LT@get@widths
- \LT@bchunk}
-% \end{macrocode}
-% \end{macro}
-
-% \begin{macro}{\@@_patch_LT@start}
-% \begin{macrocode}
-\def\@@_patch_LT@start{%
- \let\LT@start\endgraf
- \endgraf\penalty\z@\vskip\LTpre\endgraf
- \ifdim \pagetotal<\pagegoal \else
- \dimen@=\pageshrink
- \advance \dimen@ 1sp %
- \kern\dimen@\penalty 9999\endgraf \kern-\dimen@
- \fi
- \dimen@\pagetotal
- \advance\dimen@ \ht\ifvoid\LT@firsthead\LT@head\else\LT@firsthead\fi
- \advance\dimen@ \dp\ifvoid\LT@firsthead\LT@head\else\LT@firsthead\fi
- \advance\dimen@ \ht\LT@foot
- \edef\LT@reset@vfuzz{\vfuzz\the\vfuzz\vbadness\the\vbadness\relax}%
- \vfuzz\maxdimen
- \vbadness\@M
- \setbox\tw@\copy\z@
- \setbox\tw@\vsplit\tw@ to \ht\@arstrutbox
- \setbox\tw@\vbox{\unvbox\tw@}%
- \LT@reset@vfuzz
- \advance\dimen@ \ht
- \ifdim\ht\@arstrutbox>\ht\tw@\@arstrutbox\else\tw@\fi
- \advance\dimen@\dp
- \ifdim\dp\@arstrutbox>\dp\tw@\@arstrutbox\else\tw@\fi
- \advance\dimen@ -\pagegoal
- \ifdim \dimen@>\z@
- \vfil\break
- \else
- \ifdim\pageshrink>\z@\pageshrink\z@\fi
- \fi
- \global\@colroom\@colht
- \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@
- \maxdepth\z@
- \fi
- \MakeLinkTarget{table}
- \ifvoid\LT@firsthead\copy\LT@head\else\box\LT@firsthead\fi\nobreak
-% \end{macrocode}
-% Avoid that following uses of the box add content:
-% \begin{macrocode}
- \tagmcbegin{artifact}
- \tag_mc_reset_box:N\LT@head
- \tagmcend
- \output{\LT@output}}
-% \end{macrocode}
-% \end{macro}
%
%
-% \begin{macro}{\@@_patch_LT@output}
-% We must also avoid that the reuse of the foot box leads to
-% duplicated content:
-% \begin{macrocode}
-\def\@@_patch_LT@output{%
- \ifnum\outputpenalty <-\@Mi
- \ifnum\outputpenalty > -\LT@end@pen
- \LT@err{floats and marginpars not allowed in a longtable}\@ehc
- \else
- \setbox\z@\vbox{\unvbox\@cclv}%
- \ifdim \ht\LT@lastfoot>\ht\LT@foot
- \dimen@\pagegoal
- \advance\dimen@\ht\LT@foot
- \advance\dimen@-\ht\LT@lastfoot
- \ifdim\dimen@<\ht\z@
- \setbox\@cclv\vbox{\unvbox\z@\copy\LT@foot\vss}%
- \@makecol
- \@outputpage
- \global\vsize\@colroom
- \setbox\z@\vbox{\box\LT@head}%
- \fi
- \fi
- \unvbox\z@\box\ifvoid\LT@lastfoot\LT@foot\else\LT@lastfoot\fi
-% \end{macrocode}
-% Reset attribute of foot box:
-% \begin{macrocode}
- \tagmcbegin{artifact}
- \tag_mc_reset_box:N \LT@foot
- \tagmcend
- \fi
- \else
- \setbox\@cclv\vbox{\unvbox\@cclv\copy\LT@foot\vss}%
-% \end{macrocode}
-% Reset attribute of foot box:
-% \begin{macrocode}
- \tagmcbegin{artifact}
- \tag_mc_reset_box:N \LT@foot
- \tagmcend
- \@makecol
- \@outputpage
- \global\vsize\@colroom
- \copy\LT@head\nobreak
- \fi}
-% \end{macrocode}
-% \end{macro}
-%
% \begin{macro}{\@@_patch_\LT@makecaption}
% This patch is quite similar to the one for LaTeX's \cs{@makecaption}
% we also have to change the parbox sockets.
@@ -1873,9 +1425,9 @@
}
\hbox to\z@{\hss\parbox[t]\LTcapwidth{%
\reset@font
- \tag_stop:n{caption}
+ \tag_suspend:n{caption}
\sbox\@tempboxa{#1{#2:~}#3}%
- \tag_start:n{caption}
+ \tag_resume:n{caption}
\ifdim\wd\@tempboxa>\hsize
#1{#2:~}#3%
\else
@@ -1893,74 +1445,11 @@
% \begin{macrocode}
\AddToHook{package/longtable/after}
{
- \seq_new:N \g_@@_LT@firsthead_rows_seq
- \seq_new:N \g_@@_LT@head_rows_seq
- \seq_new:N \g_@@_LT@lastfoot_rows_seq
- \seq_new:N \g_@@_LT@foot_rows_seq
- \cs_set_eq:NN \LT@array\@@_patch_LT@array
- \cs_set_eq:NN \endlongtable\@@_patch_endlongtable
- \cs_set_eq:NN \LT@start\@@_patch_LT@start
- \cs_set_eq:NN \LT@output\@@_patch_LT@output
- \cs_set_eq:NN \LT@t@bularcr\@@_patch_LT@t@bularcr
- \cs_set_eq:NN \LT@end@hd@ft\@@_patch_LT@end@hd@ft
\cs_set_eq:NN \LT@makecaption\@@_patch_LT@makecaption
}
% \end{macrocode}
-
-
-
-% \subsection{tabularx}
-%
-% In tabularx we mainly need to ensure that no tagging is done during
-% the trial.
-%
-% \begin{macrocode}
-\def\@@_patch_TX@endtabularx{%
- \expandafter\expandafter\expandafter
- \TX@find@endtabularxa\csname end\TX@\endcsname
- \endtabularx\TX@\endtabularx\TX@find@endtabularxa
- \expandafter\TX@newcol\expandafter{\tabularxcolumn{\TX@col@width}}%
- \let\verb\TX@verb
- \def\@elt##1{\global\value{##1}\the\value{##1}\relax}%
- \edef\TX@ckpt{\cl@@@@ckpt}%
- \let\@elt\relax
- \TX@old@table\maxdimen
- \TX@col@width\TX@target
- \global\TX@cols\@ne
- \TX@typeout@
- {\@spaces Table Width\@spaces Column Width\@spaces X Columns}%
-% \end{macrocode}
-% Here we stop tagging:
-% \begin{macrocode}
- \tag_stop:n{tabularx}
- \TX@trial{\def\NC@rewrite@X{%
- \global\advance\TX@cols\@ne\NC@find p{\TX@col@width}}}%
- \loop
- \TX@arith
- \ifTX@
- \TX@trial{}%
- \repeat
-% \end{macrocode}
-% And now we restart it again.
-% \begin{macrocode}
- \tag_start:n{tabularx}
- {\let\@footnotetext\TX@ftntext\let\@xfootnotenext\TX@xftntext
- \csname tabular*\expandafter\endcsname\expandafter\TX@target
- \the\toks@
- \csname endtabular*\endcsname}%
- \global\TX@ftn\expandafter{\expandafter}\the\TX@ftn
- \ifnum0=`{\fi}%
- \expandafter\expandafter\expandafter
- \TX@find@endtabularxbb
- \expandafter\end\expandafter{\TX@}%
- \endtabularx\TX@\endtabularx\TX@find@endtabularxb
-}
-
-\AddToHook{package/tabularx/after}
- {\cs_set_eq:NN \TX@endtabularx\@@_patch_TX@endtabularx }
-% \end{macrocode}
% \begin{macrocode}
%</package>
% \end{macrocode}
@@ -1973,3 +1462,11 @@
\RequirePackage{latex-lab-testphase-table}
%</latex-lab>
% \end{macrocode}
+
+% \begin{macrocode}
+%<*latex-lab-alias>
+\ProvidesFile{tabular-latex-lab-testphase.ltx}
+ [\ltlabtbldate\space v\ltlabtblversion\space latex-lab wrapper tabular]
+\RequirePackage{latex-lab-testphase-table}
+%</latex-lab-alias>
+% \end{macrocode}
diff --git a/macros/latex/required/latex-lab/latex-lab-table.pdf b/macros/latex/required/latex-lab/latex-lab-table.pdf
index 555b839e75..8476deafbd 100644
--- a/macros/latex/required/latex-lab/latex-lab-table.pdf
+++ b/macros/latex/required/latex-lab/latex-lab-table.pdf
Binary files differ
diff --git a/macros/latex/required/latex-lab/latex-lab-testphase.dtx b/macros/latex/required/latex-lab/latex-lab-testphase.dtx
index b2ed5ecf8a..1134654cd6 100644
--- a/macros/latex/required/latex-lab/latex-lab-testphase.dtx
+++ b/macros/latex/required/latex-lab/latex-lab-testphase.dtx
@@ -1,7 +1,7 @@
% \iffalse meta-comment
%
%% File: latex-lab-testphase.dtx
-% Copyright (C) 2021-2023 The LaTeX Project
+% Copyright (C) 2021-2024 The LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -47,7 +47,7 @@
%
% Currently the values |phase-I|, |phase-II|, |phase-III| and |new-or| (bundles |new-or-1|
% and |new-or-2|) are provided.
-% |tagpdf| is an undocumented alias for |phase-II| which is kept for compability.
+% |tagpdf| is an undocumented alias for |phase-II| which is kept for compatibility.
% The value |math| combines various math related files.
%
% \StopEventually{\setlength\IndexMin{200pt} \PrintIndex }
@@ -79,7 +79,7 @@
% \begin{macrocode}
%<*phase-III>
\ProvidesFile{phase-III-latex-lab-testphase.ltx}
- [2023-07-20 v0.1b latex-lab wrapper phase-III]
+ [2024-02-12 v0.1c latex-lab wrapper phase-III]
\input{phase-II-latex-lab-testphase.ltx}
\IfFormatAtLeastTF{2023-06-01}
{
@@ -91,6 +91,7 @@
\RequirePackage{latex-lab-testphase-float}
\RequirePackage{latex-lab-testphase-bib}
\RequirePackage{latex-lab-testphase-text}
+ \RequirePackage{latex-lab-testphase-marginpar}
}
{\PackageWarning{latex-lab}{Testphase III needs newer format}{}}
%</phase-III>
@@ -122,9 +123,9 @@
\RequirePackage{tagpdf}
\AddToDocumentProperties [document]{testphase/tagpdf}{loaded}
%</tagpdf|phase-I|phase-II>
-%<tagpdf|phase-II>\tagpdfsetup{activate,paratagging,interwordspace}
+%<tagpdf|phase-II>\tagpdfsetup{activate,para/tagging,activate/spaces}
%<tagpdf|phase-II>\AddToDocumentProperties [document]{tagging/para}{active}
-%<phase-I>\tagpdfsetup{activate,interwordspace}
+%<phase-I>\tagpdfsetup{activate,activate/spaces}
%<*tagpdf|phase-I|phase-II>
\AddToDocumentProperties [document]{tagging}{active}
\AddToDocumentProperties [document]{tagging/interwordspace}{active}
diff --git a/macros/latex/required/latex-lab/latex-lab-testphase.pdf b/macros/latex/required/latex-lab/latex-lab-testphase.pdf
index f91a78d85a..cd840f015f 100644
--- a/macros/latex/required/latex-lab/latex-lab-testphase.pdf
+++ b/macros/latex/required/latex-lab/latex-lab-testphase.pdf
Binary files differ
diff --git a/macros/latex/required/latex-lab/latex-lab-text.dtx b/macros/latex/required/latex-lab/latex-lab-text.dtx
index 4041336ecb..7ca99191dc 100644
--- a/macros/latex/required/latex-lab/latex-lab-text.dtx
+++ b/macros/latex/required/latex-lab/latex-lab-text.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-%% File: latex-lab-text.dtx (C) Copyright 2023 LaTeX Project
+%% File: latex-lab-text.dtx (C) Copyright 2023-2024 LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -16,8 +16,8 @@
%
% for those people who are interested or want to report an issue.
%
-\def\ltlabtextdate{2023-07-20}
-\def\ltlabtextversion{0.85a}
+\def\ltlabtextdate{2024-09-18}
+\def\ltlabtextversion{0.85b}
%<*driver>
\documentclass{l3doc}
@@ -78,11 +78,11 @@
\tag_mc_end_push:
\tag_struct_begin:n{tag=Span,actualtext=LaTeX}
\tag_mc_begin:n{}
- \tag_stop:n{LaTeX}
+ \tag_suspend:n{LaTeX}
}
\AddToHook{cmd/LaTeX/after}
{
- \tag_start:n{LaTeX}
+ \tag_resume:n{LaTeX}
\tag_mc_end:
\tag_struct_end:
\tag_mc_begin_pop:n{}
diff --git a/macros/latex/required/latex-lab/latex-lab-text.pdf b/macros/latex/required/latex-lab/latex-lab-text.pdf
index b4e291df01..fc808ba24f 100644
--- a/macros/latex/required/latex-lab/latex-lab-text.pdf
+++ b/macros/latex/required/latex-lab/latex-lab-text.pdf
Binary files differ
diff --git a/macros/latex/required/latex-lab/latex-lab-title.dtx b/macros/latex/required/latex-lab/latex-lab-title.dtx
new file mode 100644
index 0000000000..757bb284a4
--- /dev/null
+++ b/macros/latex/required/latex-lab/latex-lab-title.dtx
@@ -0,0 +1,518 @@
+% \iffalse meta-comment
+%
+%% File: latex-lab-title.dtx (C) Copyright 2023-2024 LaTeX Project
+%
+% It may be distributed and/or modified under the conditions of the
+% LaTeX Project Public License (LPPL), either version 1.3c of this
+% license or (at your option) any later version. The latest version
+% of this license is in the file
+%
+% https://www.latex-project.org/lppl.txt
+%
+%
+% The development version of the bundle can be found below
+%
+% https://github.com/latex3/latex2e/required/latex-lab
+%
+% for those people who are interested or want to report an issue.
+%
+\def\ltlabtitledate{2024-02-09}
+\def\ltlabtitleversion{0.85c}
+
+%<*driver>
+\documentclass{l3doc}
+\EnableCrossrefs
+\CodelineIndex
+\begin{document}
+ \DocInput{latex-lab-title.dtx}
+\end{document}
+%</driver>
+%
+% \fi
+%
+% \title{The \textsf{latex-lab-title} package\\
+% Changes related to the tagging of the title}
+% \author{\LaTeX{} Project\thanks{Initial implementation done by Ulrike Fischer}}
+% \date{v\ltlabtitleversion\ \ltlabtitledate}
+%
+% \maketitle
+%
+% \newcommand{\xt}[1]{\textsl{\textsf{#1}}}
+% \newcommand{\TODO}[1]{\textbf{[TODO:} #1\textbf{]}}
+% \newcommand{\docclass}{document class \marginpar{\raggedright document class
+% customizations}}
+%
+% \providecommand\hook[1]{\texttt{#1}}
+%
+% \begin{abstract}
+% \end{abstract}
+%
+% \section{Introduction}
+%
+% This module contains changes to improve the tagging (in the standard classes) of
+% the title created with the \cs{maketitle} command. It also improves the
+% setting of the metadata related to the title and the author.
+%
+% For basic tagging of the printed title there are basically three things to do:
+%
+% \begin{itemize}
+% \item The actual title should be tagged with the \texttt{Title} tag.
+% \item The tabular used to format the author list should \emph{not} be tagged as a tabular.
+% \item \cs{maketitle} redefines footnote internals. These must be made tagging aware.
+% \end{itemize}
+%
+% A second task related to title is to store the authors and the title text
+% (or a shorter version) inside the XMP-metadata and (in PDF 1.7 or lower) in
+% the Info dictionary. Currently this can only be set if hyperref
+% is loaded and requires the use of the \texttt{pdftitle} and \texttt{pdfauthor} keys.
+% The new code therefore extends the \cs{title} and \cs{author} commands: They
+% stores their argument and use them at the end of the document
+% for the PDF metadata if the data hasn't been given in another way.
+% The code also gives \cs{title} and \cs{author}
+% an optional argument where the PDF title or author can be given with
+% in a key-value syntax. As with hyperref it is possible to store titles
+% in more than one language:
+%
+% \begin{verbatim}
+% \title
+% [pdftitle =
+% {[en]English Title,[de] Deutscher Titel,[fr]{titre français, avec comma}}]
+% {Document title}
+% \end{verbatim}
+%
+% It is also possible to set a subtitle which is then stored in the XMP-metadata:
+%
+% \begin{verbatim}
+% \title
+% [pdfsubtitle =
+% {[en]English Subtitle,[de] Deutscher Subtitel,[fr]{subtitre français, avec comma}}]
+% {Document title}
+% \end{verbatim}
+
+%
+% If using the \texttt{pdfauthor} key authors should be separated
+% by commas, and to hide commas in a name inside braces if needed:
+%
+% \begin{verbatim}
+% \author[pdfauthor = {Bär, Peter Anteater, {Riley, the sloth}}]{\ldots}
+% \end{verbatim}
+%
+% If hyperref is loaded there is no difference to the \texttt{pdftitle} and
+% \texttt{pdfauthor} key used in \cs{hypersetup}. Both can be used (and the last
+% key used will win).
+%
+% \subsection{Open questions and TODOs}
+%
+% \begin{itemize}
+% \item Writing into the Info dictionary needs to convert the input into a PDF string.
+% This is here done with a simple version of hyperref's \cs{pdfstringdef}, similar code
+% exist also in in the generic hyperref driver. This should be moved into a better place
+% module.
+%
+% \item Is it sensible to enhance \cs{author} and \cs{title} with an optional argument as done here?
+% An advantage is that it is rather light-weight and
+% doesn't require to decide how this values should be set in \cs{DocumentMetadata} (and would also work
+% without \cs{DocumentMetadata}. But a problem could be that various classes and packages already
+% extend this commands with other optional arguments.
+%
+% \item Some of the definitions related to metadata should perhaps be moved into l3pdfmeta.
+%
+% \item Are the names \texttt{pdftitle} and \texttt{pdfauthor} ok?
+%
+% \item The patch for \cs{thanks} to get a rlap-footnotemarker looks wrong. This
+% probably means that some configuration option is missing in the footnote code.
+% \end{itemize}
+%
+%
+%
+% \section{Implementation}
+% \begin{macrocode}
+%<*package>
+%<@@=tag>
+% \end{macrocode}
+% \begin{macrocode}
+\ProvidesExplPackage {latex-lab-testphase-title} {\ltlabtitledate} {\ltlabtitleversion}
+ {Changes related to the tagging of the title}
+% \end{macrocode}
+%
+% \subsection{\cs{maketitle} in article class}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_patch_thanks:n #1
+ {
+ \rlap{\footnotemark}
+ \protected@xdef\@thanks{\@thanks
+ \protect\footnotetext[\the\c@footnote]{#1}}
+ }
+% \end{macrocode}
+% The no-titlepage version of article, report and book
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_patch_maketitle:
+ {
+ \par
+ \begingroup
+% \end{macrocode}
+% Disable table tagging
+% \begin{macrocode}
+ \cs_if_exist_use:N\__tag_tbl_disable:
+ \renewcommand\thefootnote{\@fnsymbol\c@footnote}%
+% \end{macrocode}
+% the original definition redefines \cs{@makefnmark} and
+% \cs{@makefntext} to get an rlap-mark in the text without
+% affecting the mark in the note (which gives by the way
+% a wrong link area with hyperref). There seem to be currently
+% no good way in the footnote to configure this, so we redefine
+% \cs{thanks} instead
+% \begin{macrocode}
+ \cs_set_eq:NN \thanks \@@_patch_thanks:n
+ \if@twocolumn
+ \ifnum \col@number=\@ne
+ \@maketitle
+ \else
+ \twocolumn[\@maketitle]%
+ \fi
+ \else
+ \newpage
+ \global\@topnum\z@ % Prevents figures from going at top of page.
+ \@maketitle
+ \fi
+ \thispagestyle{plain}\@thanks
+ \endgroup
+ \setcounter{footnote}{0}%
+ \global\let\thanks\relax
+ \global\let\maketitle\relax
+ \global\let\@maketitle\relax
+ \global\let\@thanks\@empty
+ \global\let\@author\@empty
+ \global\let\@date\@empty
+ \global\let\@title\@empty
+ \global\let\title\relax
+ \global\let\author\relax
+ \global\let\date\relax
+ \global\let\and\relax
+ }
+% \end{macrocode}
+% We must also change \cs{@maketitle} to insert a Title tag
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_patch_@maketitle:
+ {
+ \newpage
+ \null
+ \vskip 2em%
+ \begin{center}%
+ \let \footnote \thanks
+% \end{macrocode}
+% use Title around the title. As in PDF 1.7 this is
+% rolemapped to P we change the text-unit tag there.
+% \begin{macrocode}
+ \pdf_version_compare:NnTF > {1.7}
+ {{\LARGE \tag_struct_begin:n{tag=Title}\@title \par\tag_struct_end:}}
+ {{\LARGE \tagtool{paratag=Title}\@title \par}}%
+ \vskip 1.5em%
+ {\large
+ \lineskip .5em%
+ \begin{tabular}[t]{c}%
+ \@author
+ \end{tabular}\par}%
+ \vskip 1em%
+ {\large \@date}%
+ \end{center}%
+ \par
+ \vskip 1.5em
+ }
+
+% \end{macrocode}
+% The titlepage variant
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_patch_maketitle_page:
+ {\begin{titlepage}%
+% \end{macrocode}
+% disable table tagging
+% \begin{macrocode}
+ \cs_if_exist_use:N\__tag_tbl_disable:
+ \let\footnotesize\small
+ \let\footnoterule\relax
+ \let \footnote \thanks
+ \null\vfil
+ \vskip 60\p@
+% \end{macrocode}
+% use Title around the title. As in PDF 1.7 this is
+% rolemapped to P we change the text-unit tag there.
+% \begin{macrocode}
+ \begin{center}%
+ \pdf_version_compare:NnTF > {1.7}
+ {{\LARGE \tag_struct_begin:n{tag=Title}\@title \par\tag_struct_end:}}
+ {{\LARGE \tagtool{paratag=Title}\@title \par}}%
+ \vskip 3em%
+ {\large
+ \lineskip .75em%
+ \begin{tabular}[t]{c}%
+ \@author
+ \end{tabular}\par}%
+ \vskip 1.5em%
+ {\large \@date \par}% % Set date in \large size.
+ \end{center}\par
+ \@thanks
+ \vfil\null
+ \end{titlepage}%
+ \setcounter{footnote}{0}%
+ \global\let\thanks\relax
+ \global\let\maketitle\relax
+ \global\let\@thanks\@empty
+ \global\let\@author\@empty
+ \global\let\@date\@empty
+ \global\let\@title\@empty
+ \global\let\title\relax
+ \global\let\author\relax
+ \global\let\date\relax
+ \global\let\and\relax
+ }
+
+% \end{macrocode}
+% Map the new commands onto \cs{maketitle}:
+% \begin{macrocode}
+\AddToHook{class/article/after}
+ {
+ \if@titlepage
+ \cs_set_eq:NN \maketitle \@@_patch_maketitle_page:
+ \else
+ \cs_set_eq:NN \maketitle \@@_patch_maketitle:
+ \cs_set_eq:NN \@maketitle \@@_patch_@maketitle:
+ \fi
+ }
+\AddToHook{class/report/after}
+ {
+ \if@titlepage
+ \cs_set_eq:NN \maketitle \@@_patch_maketitle_page:
+ \else
+ \cs_set_eq:NN \maketitle \@@_patch_maketitle:
+ \cs_set_eq:NN \@maketitle \@@_patch_@maketitle:
+ \fi
+ }
+\AddToHook{class/book/after}
+ {
+ \if@titlepage
+ \cs_set_eq:NN \maketitle \@@_patch_maketitle_page:
+ \else
+ \cs_set_eq:NN \maketitle \@@_patch_maketitle:
+ \cs_set_eq:NN \@maketitle \@@_patch_@maketitle:
+ \fi
+ }
+% \end{macrocode}
+%
+% \subsection{Helper commands to set metadata}
+%
+% Some temp variables
+% \begin{macrocode}
+\str_new:N \g_@@_title_tmpa_str
+\str_new:N \l_@@_title_tmpa_str
+\tl_new:N \l_@@_title_tmpa_tl
+\seq_new:N \l_@@_title_tmpa_seq
+% \end{macrocode}
+% Support for \cs{texorpdfstring}
+% \begin{macrocode}
+\providecommand\texorpdfstring[2]{#1}%
+% \end{macrocode}
+%
+% A helper command to convert the title into a pdfstring similar to
+% \cs{pdfstringdef}.
+% As we use \cs{text_purify} we must ensure that the default definitions
+% of \cs{@title} and \cs{@author} are robust:
+% \begin{macrocode}
+\protected\def\@title{\@latex@error{No \noexpand\title given}\@ehc}
+\protected\def\@author{\@latex@warning@no@line{No \noexpand\author given}}
+% \end{macrocode}
+% TODO: This should be improved and moved into the pdf module so that
+% it is generally available.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_title_pdfstring:nnN #1 #2 #3 % #1 text, #2 e.g. utf16/hex
+ {
+ \group_begin:
+% \end{macrocode}
+% TODO: we need probably a common boolean to handle
+% \cs{texorpdfstring} also without hyperref.
+% \begin{macrocode}
+ \cs_set_eq:NN\texorpdfstring\use_ii:nn
+ \str_set:Ne \l_@@_title_tmpa_str {\text_purify:n { #1 } }
+ \pdf_string_from_unicode:nVN { #2 } \l_@@_title_tmpa_str \l_@@_title_tmpa_str
+ \str_gset_eq:NN \g_@@_title_tmpa_str\l_@@_title_tmpa_str
+ \group_end:
+ \str_set_eq:NN #3 \g_@@_title_tmpa_str
+ }
+\cs_generate_variant:Nn\@@_title_pdfstring:nnN {e}
+% \end{macrocode}
+
+% \subsection{Extend title to set metadata}
+% At first a variable to store the title, as \cs{@title} is emptied by \LaTeX.
+% \begin{macrocode}
+\tl_new:N \g_@@_title_title_tl
+% \end{macrocode}
+% Now we redefine \cs{title} so that it stores the title, and processes
+% keys in the optional argument. We use \texttt{hyp} as module
+% name for the key as this means that if hyperref is loaded its definition
+% of \texttt{pdftitle} will be used -- at some time probably this
+% should be moved out of hyperref so that we have only one definition.
+%
+% \begin{macrocode}
+\RenewDocumentCommand\title{O{}m}
+ {
+ \gdef\@title{#2}
+ \tl_gset_eq:NN\g_@@_title_title_tl\@title
+ \keys_set:nn {hyp}{#1}
+ }
+% \end{macrocode}
+% Now we define the \texttt{pdftitle} key. This is more or less
+% the same definition as in the generic hyperref driver.
+% \begin{macrocode}
+\regex_new:N\l_@@_title_optlang_regex
+\regex_set:Nn\l_@@_title_optlang_regex {\A\[([A-Za-z\-]+)\](.*)}
+\cs_generate_variant:Nn \regex_extract_once:NnN{NVN}
+\cs_generate_variant:Nn \clist_item:nn {on}
+% \end{macrocode}
+% and now the keys.
+% \begin{macrocode}
+\keys_define:nn { hyp }
+ {
+ pdftitle .code:n =
+ {
+ \tl_if_blank:nTF {#1}
+ {
+ \pdfmanagement_remove:nn {Info}{Title}
+ }
+ {
+ \tl_set:Ne\l_@@_title_tmpa_tl {\clist_item:on{#1}{1}}
+ \regex_extract_once:NVN
+ \l_@@_title_optlang_regex
+ \l_@@_title_tmpa_tl
+ \l_@@_title_tmpa_seq
+ \seq_if_empty:NTF\l_@@_title_tmpa_seq
+ {
+ \@@_title_pdfstring:nnN {#1}{utf16/hex}\l_@@_title_tmpa_str
+ }
+ {
+ \@@_title_pdfstring:enN
+ {\seq_item:Nn \l_@@_title_tmpa_seq{3}}{utf16/hex}\l_@@_title_tmpa_str
+ }
+ \str_if_eq:VnF\l_@@_title_tmpa_str{<FEFF>}
+ {
+ \pdfmanagement_add:nne {Info}{Title}{\l_@@_title_tmpa_str}
+ }
+ }
+ \AddToDocumentProperties[hyperref]{pdftitle}{#1}
+ }
+ ,pdfsubtitle .code:n = { \AddToDocumentProperties[hyperref]{pdfsubtitle}{#1} }
+ }
+% \end{macrocode}
+%
+% \subsection{Extend \cs{author} to set metadata}
+%
+% At first a variable to store the authors, as \cs{@author} is emptied by \LaTeX.
+% \begin{macrocode}
+\tl_new:N \g_@@_title_author_tl
+% \end{macrocode}
+% Now we redefine \cs{author} so that it stores the authors, and processes
+% keys in the optional argument. We use \texttt{hyp} as module
+% name for the key as this means that if hyperref is loaded its definition
+% of \texttt{pdfauthor} will be used -- at some time probably this
+% should be moved out of hyperref so that we have only one definition.
+%
+% \begin{macrocode}
+\RenewDocumentCommand\author{O{}m}
+ {
+ \gdef\@author{#2}
+ \tl_gset_eq:NN\g_@@_title_author_tl\@author
+ \keys_set:nn {hyp}{#1}
+ }
+% \end{macrocode}
+%
+% Now we define the \texttt{pdfauthor} key. This is more or less
+% the same definition as in the generic hyperref driver.
+
+% \begin{macrocode}
+\keys_define:nn { hyp }
+ {
+ pdfauthor .code:n =
+ {
+ \tl_if_blank:nTF {#1}
+ {
+ \pdfmanagement_remove:nn {Info}{Author}
+ }
+ {
+ \tl_set:Ne\l_@@_title_tmpa_tl {\clist_item:on{#1}{1}}
+ \regex_extract_once:NVN
+ \l_@@_title_optlang_regex
+ \l_@@_title_tmpa_tl
+ \l_@@_title_tmpa_seq
+ \seq_if_empty:NTF\l_@@_title_tmpa_seq
+ {
+ \@@_title_pdfstring:nnN {#1}{utf16/hex}\l_@@_title_tmpa_str
+ }
+ {
+ \@@_title_pdfstring:enN
+ {\seq_item:Nn \l_@@_title_tmpa_seq{3}}{utf16/hex}\l_@@_title_tmpa_str
+ }
+ \str_if_eq:VnF\l_@@_title_tmpa_str{<FEFF>}
+ {
+ \pdfmanagement_add:nne {Info}{Author}{\l_@@_title_tmpa_str}
+ }
+ }
+ \AddToDocumentProperties[hyperref]{pdfauthor}{#1}
+ }
+ }
+% \end{macrocode}
+% \subsection{Fallback for classes and packages that redefine \cs{title} or \cs{author}}
+% If a class redefines \cs{author} and \cs{title} again, we try to retrieve at
+% least the values.
+% \begin{macrocode}
+\AddToHook{cmd/maketitle/before}
+ {
+ \tl_gset_eq:NN \g_@@_title_author_tl\@author
+ \tl_gset_eq:NN \g_@@_title_title_tl\@title
+ }
+% \end{macrocode}
+%
+% \subsection{Finalize document}
+% At last we set the title and the author at the end of document
+% if that hasn't happened yet:
+% \begin{macrocode}
+\AddToHook{shipout/lastpage}
+ {
+ \tl_if_empty:eT{\GetDocumentProperties{hyperref/pdftitle}}
+ {
+ \group_begin:
+ \cs_set_eq:NN\thanks \use_none:n
+ \str_set:Ne \l_@@_title_tmpa_str {\text_purify:n { \g_@@_title_title_tl } }
+ \keys_set:ne{hyp}{pdftitle={\exp_not:V\l_@@_title_tmpa_str}}
+ \group_end:
+ }
+ \tl_if_empty:eT{\GetDocumentProperties{hyperref/pdfauthor}}
+ {
+ \group_begin:
+ \cs_set_eq:NN\thanks \use_none:n
+ \cs_set:Npn \and {,}
+ \str_set:Ne \l_@@_title_tmpa_str {\text_purify:n { \g_@@_title_author_tl } }
+ \keys_set:ne{hyp}{pdfauthor={\exp_not:V\l_@@_title_tmpa_str}}
+ \group_end:
+ }
+% \end{macrocode}
+% force display title, if an UA-standard is detected.
+% \begin{macrocode}
+ \tl_if_empty:eF{\GetDocumentProperties{document/pdfstandard-UA}}
+ {
+ \pdfmanagement_add:nnn {Catalog / ViewerPreferences } { DisplayDocTitle } { true }
+ }
+ }
+\DeclareHookRule{shipout/lastpage}{latex-lab-testphase-title}{before}{pdfmanagement-testphase}
+%</package>
+% \end{macrocode}
+
+% \begin{macrocode}
+%<*latex-lab>
+\ProvidesFile{title-latex-lab-testphase.ltx}
+ [\ltlabtitledate\space v\ltlabtitleversion\space
+ Changes related to the tagging of the title]
+
+\RequirePackage{latex-lab-testphase-title}
+
+%</latex-lab>
+% \end{macrocode}
diff --git a/macros/latex/required/latex-lab/latex-lab-title.pdf b/macros/latex/required/latex-lab/latex-lab-title.pdf
new file mode 100644
index 0000000000..c81bcd9eb8
--- /dev/null
+++ b/macros/latex/required/latex-lab/latex-lab-title.pdf
Binary files differ
diff --git a/macros/latex/required/latex-lab/latex-lab-toc-hyperref-changes.dtx b/macros/latex/required/latex-lab/latex-lab-toc-hyperref-changes.dtx
index 2f00b83c05..ff9dd950b7 100644
--- a/macros/latex/required/latex-lab/latex-lab-toc-hyperref-changes.dtx
+++ b/macros/latex/required/latex-lab/latex-lab-toc-hyperref-changes.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-%% File: latex-lab-toc-hyperref-changes.dtx (C) Copyright 2022-2023 LaTeX Project
+%% File: latex-lab-toc-hyperref-changes.dtx (C) Copyright 2022-2024 LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
diff --git a/macros/latex/required/latex-lab/latex-lab-toc-hyperref-changes.pdf b/macros/latex/required/latex-lab/latex-lab-toc-hyperref-changes.pdf
index 8662c9c37c..329c0beb36 100644
--- a/macros/latex/required/latex-lab/latex-lab-toc-hyperref-changes.pdf
+++ b/macros/latex/required/latex-lab/latex-lab-toc-hyperref-changes.pdf
Binary files differ
diff --git a/macros/latex/required/latex-lab/latex-lab-toc-kernel-changes.dtx b/macros/latex/required/latex-lab/latex-lab-toc-kernel-changes.dtx
index 81c9edfe4d..2934a26168 100644
--- a/macros/latex/required/latex-lab/latex-lab-toc-kernel-changes.dtx
+++ b/macros/latex/required/latex-lab/latex-lab-toc-kernel-changes.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-%% File: latex-lab-toc-kernel-changes.dtx (C) Copyright 2022-2023 LaTeX Project
+%% File: latex-lab-toc-kernel-changes.dtx (C) Copyright 2022-2024 LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -17,8 +17,8 @@
% for those people who are interested or want to report an issue.
%
% dates for latex-lab-kernel-changes.sty (pulled from various sources, see ins)
-\def\ltlabkerneldate{2023-10-16}
-\def\ltlabkernelversion{0.85b}
+\def\ltlabkerneldate{2024-07-11}
+\def\ltlabkernelversion{0.85d}
%<*driver>
\documentclass{l3doc}
\EnableCrossrefs
@@ -44,6 +44,11 @@
%
% \providecommand\hook[1]{\texttt{#1}}
%
+%
+% \ProvideDocElement[printtype=\textit{socket},idxtype=socket,idxgroup=Sockets]{Socket}{socketdecl}
+% \ProvideDocElement[printtype=\textit{hook},idxtype=hook,idxgroup=Hooks]{Hook}{hookdecl}
+% \ProvideDocElement[printtype=\textit{plug},idxtype=plug,idxgroup=Plugs]{Plug}{plugdecl}
+%
% \begin{abstract}
% \end{abstract}
%
@@ -68,67 +73,14 @@
% \end{macrocode}
%
% \subsection{Providing the counter representation \cs{theHxx} generally}
-% [kernel?]
-%
-% The \cs{theHxx} representation allows to create a unique representation of a counter
-% that is for example used to create destination names. It will also be needed
-% to add |/Ref| keys to various tagging structures. It makes therefore sense
-% to provide it by default as soon as a counter is created. The |\@addtoreset| change
-% (taken also from hyperref) tries to ensure the counter stays unique if it is reset.
-%
-% At first we suppress the patches from hyperref:
+%
+% This has been moved to base.
+%
+% We still suppress the patches from hyperref:
% \begin{macrocode}
\def\hyper@nopatch@counter{}
% \end{macrocode}
-%
-% \begin{macrocode}
-\def\@definecounter#1{\expandafter\newcount\csname c@#1\endcsname
- \setcounter{#1}\z@
- \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}}%new
- \expandafter
- \gdef\csname the#1\expandafter\endcsname\expandafter
- {\expandafter\@arabic\csname c@#1\endcsname}}
-\def\@addtoreset#1#2{\expandafter\@cons\csname cl@#2\endcsname {{#1}}%
- \expandafter\gdef\csname theH#1\endcsname{\csname theH#2\endcsname.\the\value{#1}}%
-}
-% \end{macrocode}
-% The following counters are defined in the kernel
-% \begin{macrocode}
-\gdef\theHenumi{\the\value{enumi}}
-\gdef\theHenumii{\the\value{enumii}}
-\gdef\theHenumiii{\the\value{enumiii}}
-\gdef\theHenumiv{\the\value{enumiv}}
-\gdef\theHequation{\the\value{equation}}
-\gdef\theHfootnote{\the\value{footnote}}
-\gdef\theHmpfootnote{\the\value{mpfootnote}}
-% \end{macrocode}
-%
-% \subsection{Providing and updating \cs{@currentHref}}
-% [kernel?]
-%
-% \cs{@currentHref} contains the current unique representation of a counter.
-% It is useful also without hyperref as it allows to connect with a |/Ref|
-% key a toc entry with the heading it refers too. So \cs{refstepcounter}
-% is extended to update the command. This is done at the begin so that the
-% hyperref code can still adapt it later (using the cmd/refstepcounter/after hook
-% would be too late, and could also break with cleverref.)
-%
-% We also provide a kernel version that hyperref doesn't touch and so will never
-% set a target.
-% \begin{macrocode}
-\def\@currentHref{}
-\def\refstepcounter#1{\stepcounter{#1}%
- \edef\@currentcounter{#1}%
- \xdef\@currentHref {#1.\csname theH#1\endcsname}%
- \protected@edef\@currentlabel
- {\csname p@#1\expandafter\endcsname\csname the#1\endcsname}%
-}
-\let\@kernel@refstepcounter\refstepcounter
-% \end{macrocode}
-%
+
% \subsection{Assigning the headings level numbers}
% [kernel?]
%
@@ -160,17 +112,21 @@
% catch as much as possible, see also tagging issue \#20. This should work also
% without hyperref. The property is defined in tagpdf-base, so the code would
% work also without tagging but we add a test anyway, this is probably faster.
+% TODO: remove
% \begin{macrocode}
\ExplSyntaxOn
-\AddToHookWithArguments{cmd/MakeLinkTarget/after}
- {
- \tag_if_active:T
- {
- \tl_if_blank:VF \@currentHref
- {
- \prop_gput:Nee \g__tag_struct_dest_num_prop {\@currentHref}{\tag_get:n{struct_num}}
- }
- }
+\str_if_exist:cF { l__socket_tagsupport/recordtarget_str }
+ {
+ \AddToHookWithArguments{cmd/MakeLinkTarget/after}
+ {
+ \tag_if_active:T
+ {
+ \tl_if_blank:VF \@currentHref
+ {
+ \prop_gput:Nee \g__tag_struct_dest_num_prop {\@currentHref}{\tag_get:n{struct_num}}
+ }
+ }
+ }
}
\ExplSyntaxOff
% \end{macrocode}
@@ -187,12 +143,24 @@
% \subsection{\cs{contentsline} extension}
% [latex-lab]
% The tagging code must add code at the begin and end of \cs{contentsline}.
-% This code must have access to the arguments. We set it up as config point
-% for now.
+% This code must have access to the arguments. They are passed
+% together in tagging socket.
+% \begin{socketdecl}{tagsupport/toc/contentsline/before,
+% tagsupport/toc/contentsline/after}
+% Tagging sockets at the begin and end of contentsline.
+% They receive \emph{all} contentsline arguments as one argument
+% in four brace groups. The socket code should then use the parts it needs.
+% The sockets will be in lttagging.dtx, but that may only happen in
+% the next main release, so for now we test if they are in the
+% format and if not define them now.
% \begin{macrocode}
-\def\@contentsline@cfgpoint@before#1#2#3#4{}
-\def\@contentsline@cfgpoint@after#1#2#3#4{}
+\str_if_exist:cF { l__socket_tagsupport/toc/contentsline/before_plug_str }
+ {
+ \NewSocket{tagsupport/toc/contentsline/before}{1}
+ \NewSocket{tagsupport/toc/contentsline/after}{1}
+ }
% \end{macrocode}
+% \end{socketdecl}
% for the hooks we need that the \cs{l@XX} pass also the destination and
% that \cs{l@XX} takes three arguments.
% TODO: test that, if there are two many problems we should pass the
@@ -200,10 +168,10 @@
% \begin{macrocode}
\def\contentsline#1#2#3#4%
{%
- \@contentsline@cfgpoint@before{#1}{#2}{#3}{#4}%
+ \UseTaggingSocket{toc/contentsline/before}{{#1}{#2}{#3}{#4}}%
\gdef\@contentsline@destination{#4}%
\csname l@#1\endcsname{#2}{#3}%
- \@contentsline@cfgpoint@after{#1}{#2}{#3}{#4}%
+ \UseTaggingSocket{toc/contentsline/after}{{#1}{#2}{#3}{#4}}%
}
% \end{macrocode}
%
@@ -225,17 +193,33 @@
% \subsection{\cs{@starttoc}}
% [kernel?]
%
-% We add a configuration point before and after reading the file
+% We add a tagging socket before and after reading the file
% for the tagging.
+% \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.
+% The sockets will be in lttagging.dtx, but that may only happen in
+% the next main release, so for now we test if they are in the
+% format and if not define them now.
+% \begin{macrocode}
+\str_if_exist:cF { l__socket_tagsupport/toc/starttoc/before_plug_str }
+ {
+ \NewSocket{tagsupport/toc/starttoc/before}{1}
+ \NewSocket{tagsupport/toc/starttoc/after}{1}
+ }
+% \end{macrocode}
+% \begin{macrocode}
+% \end{macrocode}
+% \end{socketdecl}
+%
% \begin{macrocode}
-\def\@starttoc@cfgpoint@before#1{}
-\def\@starttoc@cfgpoint@after#1{}
\def\@starttoc#1{%
\begingroup
\makeatletter
- \@starttoc@cfgpoint@before{#1}%
+ \UseTaggingSocket{toc/starttoc/before}{#1}%
\@input{\jobname.#1}%
- \@starttoc@cfgpoint@after{#1}
+ \UseTaggingSocket{toc/starttoc/after}{#1}%
\if@filesw
\expandafter\newwrite\csname tf@#1\endcsname
\immediate\openout \csname tf@#1\endcsname \jobname.#1\relax
@@ -269,15 +253,32 @@
\NewMirroredHookPairWithArguments{contentsline/page/before}{contentsline/page/after}{4}%
% \end{macrocode}
%
-% The dot in the leader must be set as artifact.
+% The dots in the leader must be set as artifact.
% But luatex requires that the mc are set outside the leaders.
-% So we need a config point.
+% So we need sockets.
%
% \cs{@dottedtocline} needs hooks and formatting commands.
-% We add a sixth argument so that it can grab the destination too.
+% To make the leaders into artifact we use tagging sockets.
+% The declaration should perhaps be moved into lttagging so that
+% it can be used also by external packages even if the tagging code is not
+% loaded?
+% \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.
+% The sockets will be in lttagging.dtx, but that may only happen in
+% the next main release, so for now we test if they are in the
+% format and if not define them now.
+% \begin{macrocode}
+\str_if_exist:cF { l__socket_tagsupport/toc/leaders/before_plug_str }
+ {
+ \NewSocket{tagsupport/toc/leaders/before}{0}
+ \NewSocket{tagsupport/toc/leaders/after}{0}
+ }
+% \end{macrocode}
+% \end{socketdecl}
+% The destination is accessed through \cs{@contentsline@destination}.
% \begin{macrocode}
-\def\@dottedtocline@cfgpoint@leaders#1{#1}
-
\def\@dottedtocline#1#2#3#4#5{%
\ifnum #1>\c@tocdepth \else
\vskip \z@ \@plus.2\p@
@@ -291,10 +292,11 @@
\csname contentsline@text@#1@format\endcsname{#4}%
\UseHookWithArguments{contentsline/text/after}{4}{#1}{#4}{#5}{\@contentsline@destination}%
\nobreak
- \@dottedtocline@cfgpoint@leaders{%
+ \UseTaggingSocket{toc/leaders/before}\SuspendTagging{toc/leaders}%
\leaders\hbox{$\m@th
\mkern \@dotsep mu\hbox{.}\mkern \@dotsep
- mu$}\hfill}%
+ mu$}\hfill
+ \ResumeTagging{toc/leaders}\UseTaggingSocket{toc/leaders/after}%
\nobreak
\hb@xt@\@pnumwidth{\hfil\normalfont \normalcolor
\UseHookWithArguments{contentsline/page/before}{4}{#1}{#4}{#5}{\@contentsline@destination}%
diff --git a/macros/latex/required/latex-lab/latex-lab-toc-kernel-changes.pdf b/macros/latex/required/latex-lab/latex-lab-toc-kernel-changes.pdf
index b559fb59e6..2c3d82f7fe 100644
--- a/macros/latex/required/latex-lab/latex-lab-toc-kernel-changes.pdf
+++ b/macros/latex/required/latex-lab/latex-lab-toc-kernel-changes.pdf
Binary files differ
diff --git a/macros/latex/required/latex-lab/latex-lab-toc.dtx b/macros/latex/required/latex-lab/latex-lab-toc.dtx
index 6def505e11..15dd403bdf 100644
--- a/macros/latex/required/latex-lab/latex-lab-toc.dtx
+++ b/macros/latex/required/latex-lab/latex-lab-toc.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-%% File: latex-lab-toc.dtx (C) Copyright 2022-2023 LaTeX Project
+%% File: latex-lab-toc.dtx (C) Copyright 2022-2024 LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -16,8 +16,8 @@
%
% for those people who are interested or want to report an issue.
%
-\def\ltlabtocdate{2023-10-16}
-\def\ltlabtocversion{0.85b}
+\def\ltlabtocdate{2024-09-26}
+\def\ltlabtocversion{0.85e}
%<*driver>
\documentclass{l3doc}
\EnableCrossrefs
@@ -42,7 +42,10 @@
% \newcommand{\docclass}{document class \marginpar{\raggedright document class
% customizations}}
%
-% \providecommand\hook[1]{\texttt{#1}}
+%
+% \ProvideDocElement[printtype=\textit{socket},idxtype=socket,idxgroup=Sockets]{Socket}{socketdecl}
+% \ProvideDocElement[printtype=\textit{hook},idxtype=hook,idxgroup=Hooks]{Hook}{hookdecl}
+% \ProvideDocElement[printtype=\textit{plug},idxtype=plug,idxgroup=Plugs]{Plug}{plugdecl}
%
% \begin{abstract}
% \end{abstract}
@@ -111,66 +114,32 @@
% Defined by tagpdf.
% \end{variable}
%
-% \cs{refstepcounter} doesn't use \cs{MakeLinkTarget} (yet) so
-% we have to patch it too to store the relation between
-% destination names/\cs{@currentHref} and structure numbers
+% We have to to store the relation between
+% destination names/\cs{@currentHref} and structure numbers.
+% With a current kernel this is done in \cs{refstepcounter}
+% through the |recordtarget| socket. If that doesn't exist yet
+% we patch:
%
-% The property is set up in tagpdf-test so that one
-% doesn't has to check if the prop exists or not.
+% TODO remove after release 2024/11
% \begin{macrocode}
-\AddToHook{cmd/refstepcounter/after}
- {
- \tl_if_blank:VF \@currentHref
- {
- \prop_gput:Nee \g_@@_struct_dest_num_prop {\@currentHref}{\tag_get:n{struct_num}}
- }
- }
-\AddToHook{cmd/H@refstepcounter/after}
- {
- \tl_if_blank:VF \@currentHref
- {
- \prop_gput:Nee \g_@@_struct_dest_num_prop {\@currentHref}{\tag_get:n{struct_num}}
- }
- }
-% \end{macrocode}
-% \begin{variable}{\g_@@_struct_ref_by_dest_prop}
-% This variable contains structures whose Ref key should be updated
-% at the end to point to structured related with this destination.
-% As this is probably need in other places too, it is not only a toc-variable.
-% Moved into tagpdf!
-% \end{variable}
-%
-% \begin{macro}{\g_@@_struct_ref_by_dest:}
-% This command is executed and update the Ref keys
-% of the structures listed in |\g_@@_struct_ref_by_dest_prop|.
-% It is currently only relevant for the |TOCI|. But other structures
-% could need that later too.
-% The command is executed in the |tagpdf/finish/before| hook.
-% \begin{macrocode}
-\msg_new:nnn { tag } {struct-dest-unknown}
- {
- Destination~#1~has~no~related~structure.\\
- /Ref~for~structure~#2~not~updated
- }
-
-\cs_new_protected:Npn \g_@@_struct_ref_by_dest:
+\str_if_exist:cF { l__socket_tagsupport/recordtarget_plug_str }
{
- \prop_map_inline:Nn\g_@@_struct_ref_by_dest_prop
- {
- \prop_get:NnNTF \g_@@_struct_dest_num_prop {##2} \l_@@_tmpa_tl
- {
- \@@_struct_gput_data_ref:ee
- { ##1 }
- { \tag_struct_object_ref:e{ \l_@@_tmpa_tl }}
- }
- {
- \msg_warning:nnnn {tag}{struct-dest-unknown}{##2}{ ##1}
- }
- }
- }
-\hook_gput_code:nnn {tagpdf/finish/before}{tagpdf/struct/Ref}{\g_@@_struct_ref_by_dest:}
+ \AddToHook{cmd/refstepcounter/after}
+ {
+ \tl_if_blank:VF \@currentHref
+ {
+ \prop_gput:Nee \g_@@_struct_dest_num_prop {\@currentHref}{\tag_get:n{struct_num}}
+ }
+ }
+ \AddToHook{cmd/H@refstepcounter/after}
+ {
+ \tl_if_blank:VF \@currentHref
+ {
+ \prop_gput:Nee \g_@@_struct_dest_num_prop {\@currentHref}{\tag_get:n{struct_num}}
+ }
+ }
+ }
% \end{macrocode}
-% \end{macro}
%
% \section{Toc code}
% \begin{variable}{\g_@@_toc_level_int,\g_@@_toc_stack_seq}
@@ -196,14 +165,17 @@
\tag_struct_begin:n{tag=TOC,title=#1}
}
% \end{macrocode}
-% Now map it into the config point:
+% \end{macro}
+% Now define the tagging plug and assign it to the socket.
+% \begin{plugdecl}{default}
% \begin{macrocode}
-\cs_set_protected:Npn\@starttoc@cfgpoint@before#1
- {
- \@@_toc_starttoc_init:n{#1}
- }
+\NewSocketPlug{tagsupport/toc/starttoc/before}{default}
+ {
+ \@@_toc_starttoc_init:n{#1}
+ }
+\AssignSocketPlug{tagsupport/toc/starttoc/before}{default}
% \end{macrocode}
-% \end{macro}
+% \end{plugdecl}
% \begin{macro}{\@@_toc_starttoc_finalize:}
% \begin{macrocode}
\cs_new_protected:Npn \@@_toc_starttoc_finalize:
@@ -215,15 +187,18 @@
\seq_gclear:N \g_@@_toc_stack_seq
}
% \end{macrocode}
-% Now map it into the config point:
+% \end{macro}
+% Now define the tagging plug and assign it to the socket.
+% \begin{plugdecl}{default}
% \begin{macrocode}
-\cs_set_protected:Npn\@starttoc@cfgpoint@after#1
- {
- \@@_toc_starttoc_finalize:
- }
+\NewSocketPlug{tagsupport/toc/starttoc/after}{default}
+ {
+ \@@_toc_starttoc_finalize:
+ }
+\AssignSocketPlug{tagsupport/toc/starttoc/after}{default}
% \end{macrocode}
-% \end{macro}
-
+% \end{plugdecl}
+%
% \begin{macro}{\@@_toc_end:n}
% This commands ends all TOC on the stack with a level higher than the argument
% \begin{macrocode}
@@ -249,10 +224,11 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\@@_toc_contentsline_begin:nnn}
+% \begin{macro}{\@@_toc_contentsline_begin:nnnn}
% This is main command executed at the begin of a |\contentsline|.
% \begin{macrocode}
-\cs_new_protected:Npn \@@_toc_contentsline_begin:nnn #1 #2 #3 %#1 level, #2 content, #3 destination
+\cs_new_protected:Npn \@@_toc_contentsline_begin:nnnn #1 #2 #3 #4
+ %#1 level, #2 content, #3 page number (unused) #4 destination
{
\tag_if_active:T
{
@@ -271,7 +247,7 @@
{ \int_compare_p:nNn { \g_@@_toc_level_int } > {-100} }
{ \int_compare_p:nNn { \use:c{toclevel@#1} } > { \g_@@_toc_level_int } }
{
- \seq_gpush:Nx \g_@@_toc_stack_seq {{TOC}\use:c{toclevel@#1}}
+ \seq_gpush:Ne \g_@@_toc_stack_seq {{TOC}\use:c{toclevel@#1}}
\tag_struct_begin:n{tag=TOC}
}
% \end{macrocode}
@@ -298,40 +274,44 @@
% \begin{macrocode}
\group_begin:
\text_declare_expand_equivalent:Nn \numberline \use_none:n
- \exp_args:Nx \tag_struct_begin:n{tag=TOCI,title={\text_purify:n {#2}}}
+ \exp_args:Ne
+ \tag_struct_begin:n{tag=TOCI,title={\text_purify:n {#2}}}
% \end{macrocode}
-% The TOCI structure should get a /Ref, so we put a request with its destination
-% name into the prop.
+% The TOCI structure should get a /Ref, we use a destination
+% to retrieve it.
% \begin{NOTE}{UF}
% This only works with hyperref currently. Without hyperref we
% need to store fake names.
% \end{NOTE}
% \begin{macrocode}
- \prop_gput:Nxx \g_@@_struct_ref_by_dest_prop
- { \tag_get:n {struct_num} }{#3}
- \seq_gpush:Nx \g_@@_toc_stack_seq {{TOCI}\use:c{toclevel@#1}}
+ \tag_struct_gput:nnn { \tag_get:n {struct_num} }{ref_dest}{#4}
+ \seq_gpush:Ne \g_@@_toc_stack_seq {{TOCI}\use:c{toclevel@#1}}
\group_end:
}
}
}
% \end{macrocode}
-% Now map it into the config point:
+% \end{macro}
+% Now define the tagging plug and assign it to the socket.
+% \begin{plugdecl}{default}
% \begin{macrocode}
-\cs_set_protected:Npn\@contentsline@cfgpoint@before#1#2#3#4
+\NewSocketPlug{tagsupport/toc/contentsline/before}{default}
{
- \@@_toc_contentsline_begin:nnn {#1}{#2}{#4}
- }
+ \@@_toc_contentsline_begin:nnnn #1
+ }
+\AssignSocketPlug{tagsupport/toc/contentsline/before}{default}
% \end{macrocode}
-% \end{macro}
+% \end{plugdecl}
%
-% \begin{macro}{\@@_toc_contentsline_end:n}
+% \begin{macro}{\@@_toc_contentsline_end:nnnn}
% This is the closing code of a |\contentsline|.
% If the contentsline was actually printed, the code has to
% close the TOCI structure and to update the stack.
% \begin{macrocode}
\msg_new:nnn {tag}{toc-no-TOCI}{Missing~TOCI~structure~on~toc~stack}
-\cs_new_protected:Npn \@@_toc_contentsline_end:n #1 %#1 level name
+\cs_new_protected:Npn \@@_toc_contentsline_end:nnnn #1 #2 #3 #4
+% #1 level, #2 content (unused), #3 page number (unused) #4 destination (unused)
{
\int_compare:nNnF { \use:c{toclevel@#1} } > {\use:c{c@tocdepth}}
{
@@ -348,14 +328,17 @@
}
}
% \end{macrocode}
-% Now we map it to the config point
+% \end{macro}
+% Now define the tagging plug and assign it to the socket.
+% \begin{plugdecl}{default}
% \begin{macrocode}
-\cs_set_protected:Npn \@contentsline@cfgpoint@after #1#2#3#4
- {
- \@@_toc_contentsline_end:n {#1}
- }
+\NewSocketPlug{tagsupport/toc/contentsline/after}{default}
+ {
+ \@@_toc_contentsline_end:nnnn #1
+ }
+\AssignSocketPlug{tagsupport/toc/contentsline/after}{default}
% \end{macrocode}
-% \end{macro}
+% \end{plugdecl}
%
% \subsection{Tagging of the content}
% This need discussion.
@@ -380,12 +363,16 @@
\tag_struct_end:
\tag_mc_begin:n{tag=Reference}}
% \end{macrocode}
-%
+% \begin{plugdecl}{artifact}
% \begin{macrocode}
-\def\@dottedtocline@cfgpoint@leaders#1{%
- \tag_mc_begin:n{artifact}\tag_stop:n{leaders}\nobreak#1\nobreak\tag_start:n{leaders}\tag_mc_end:}
+\NewSocketPlug{tagsupport/toc/leaders/before}{artifact}
+ {\tag_mc_begin:n{artifact}\nobreak}
+\NewSocketPlug{tagsupport/toc/leaders/after}{artifact}
+ {\nobreak\tag_mc_end:}
+\AssignSocketPlug{tagsupport/toc/leaders/before}{artifact}
+\AssignSocketPlug{tagsupport/toc/leaders/after}{artifact}
% \end{macrocode}
-
+% \end{plugdecl}
%
% \begin{macrocode}
%</package>
diff --git a/macros/latex/required/latex-lab/latex-lab-toc.pdf b/macros/latex/required/latex-lab/latex-lab-toc.pdf
index b60f71fb0b..071c82c763 100644
--- a/macros/latex/required/latex-lab/latex-lab-toc.pdf
+++ b/macros/latex/required/latex-lab/latex-lab-toc.pdf
Binary files differ
diff --git a/macros/latex/required/latex-lab/latex-lab.ins b/macros/latex/required/latex-lab/latex-lab.ins
index 548f18a6fa..7071ed6e3d 100644
--- a/macros/latex/required/latex-lab/latex-lab.ins
+++ b/macros/latex/required/latex-lab/latex-lab.ins
@@ -154,8 +154,16 @@ where one can also log issues in case there are any.
%table
\generate{\file{table-latex-lab-testphase.ltx}{\from{latex-lab-table.dtx}{latex-lab}}}
+\generate{\file{tabular-latex-lab-testphase.ltx}{\from{latex-lab-table.dtx}{latex-lab-alias}}}
\generate{\file{latex-lab-testphase-table.sty}{\from{latex-lab-table.dtx}{package}}}
+%title
+\generate{\file{title-latex-lab-testphase.ltx}{\from{latex-lab-title.dtx}{latex-lab}}}
+\generate{\file{latex-lab-testphase-title.sty}{\from{latex-lab-title.dtx}{package}}}
+
+%marginpar
+\generate{\file{marginpar-latex-lab-testphase.ltx}{\from{latex-lab-marginpar.dtx}{latex-lab}}}
+\generate{\file{latex-lab-testphase-marginpar.sty}{\from{latex-lab-marginpar.dtx}{package}}}
% stop docstrip adding \endinput
\preamble