summaryrefslogtreecommitdiff
path: root/macros
diff options
context:
space:
mode:
Diffstat (limited to 'macros')
-rw-r--r--macros/latex/contrib/physics-patch/README.txt2
-rw-r--r--macros/latex/contrib/physics-patch/physics-patch.pdfbin87751 -> 85258 bytes
-rw-r--r--macros/latex/contrib/physics-patch/physics-patch.sty434
-rw-r--r--macros/latex/contrib/physics-patch/physics-patch.tex262
-rw-r--r--macros/latex/contrib/tagpdf/README.md4
-rw-r--r--macros/latex/contrib/tagpdf/ex-AF-file.pdf56
-rw-r--r--macros/latex/contrib/tagpdf/ex-alt-actualtext.pdfbin34624 -> 34624 bytes
-rw-r--r--macros/latex/contrib/tagpdf/ex-attribute.pdf14
-rw-r--r--macros/latex/contrib/tagpdf/ex-formula-problem.pdf14
-rw-r--r--macros/latex/contrib/tagpdf/ex-list.pdf14
-rw-r--r--macros/latex/contrib/tagpdf/ex-mc-manual-para-split-obsolete.pdf110
-rw-r--r--macros/latex/contrib/tagpdf/ex-softhyphen.pdf14
-rw-r--r--macros/latex/contrib/tagpdf/ex-spaceglyph-listings.pdf14
-rw-r--r--macros/latex/contrib/tagpdf/ex-structure-obsolete.pdf14
-rw-r--r--macros/latex/contrib/tagpdf/ex-tagpdf-template.pdf16
-rw-r--r--macros/latex/contrib/tagpdf/tagpdf-backend.dtx8
-rw-r--r--macros/latex/contrib/tagpdf/tagpdf-checks.dtx25
-rw-r--r--macros/latex/contrib/tagpdf/tagpdf-code.pdfbin1335037 -> 1283658 bytes
-rw-r--r--macros/latex/contrib/tagpdf/tagpdf-data.dtx16
-rw-r--r--macros/latex/contrib/tagpdf/tagpdf-mc-generic.dtx103
-rw-r--r--macros/latex/contrib/tagpdf/tagpdf-mc-luacode.dtx6
-rw-r--r--macros/latex/contrib/tagpdf/tagpdf-mc-shared.dtx4
-rw-r--r--macros/latex/contrib/tagpdf/tagpdf-roles.dtx4
-rw-r--r--macros/latex/contrib/tagpdf/tagpdf-space.dtx4
-rw-r--r--macros/latex/contrib/tagpdf/tagpdf-struct.dtx28
-rw-r--r--macros/latex/contrib/tagpdf/tagpdf-tree.dtx4
-rw-r--r--macros/latex/contrib/tagpdf/tagpdf-user.dtx361
-rw-r--r--macros/latex/contrib/tagpdf/tagpdf.dtx29
-rw-r--r--macros/latex/contrib/tagpdf/tagpdf.pdfbin1142551 -> 1142738 bytes
-rw-r--r--macros/latex/contrib/tagpdf/tagpdf.tex86
-rw-r--r--macros/latex/contrib/tagpdf/tagpdfdocu-patches.sty2
-rw-r--r--macros/latex/contrib/textcase/textcase.dtx16
-rw-r--r--macros/latex/contrib/textcase/textcase.pdfbin231295 -> 231861 bytes
-rw-r--r--macros/luatex/latex/luamml/CHANGELOG.md19
-rw-r--r--macros/luatex/latex/luamml/luamml-amsmath.lua9
-rw-r--r--macros/luatex/latex/luamml/luamml-array.lua2
-rw-r--r--macros/luatex/latex/luamml/luamml-convert.lua3
-rw-r--r--macros/luatex/latex/luamml/luamml-demo.sty2
-rw-r--r--macros/luatex/latex/luamml/luamml-patches-amsmath.sty784
-rw-r--r--macros/luatex/latex/luamml/luamml-patches-amstext.sty60
-rw-r--r--macros/luatex/latex/luamml/luamml-patches-array.sty101
-rw-r--r--macros/luatex/latex/luamml/luamml-patches-kernel.sty106
-rw-r--r--macros/luatex/latex/luamml/luamml-patches-lab-math.sty13
-rw-r--r--macros/luatex/latex/luamml/luamml-patches-mathtools.sty69
-rw-r--r--macros/luatex/latex/luamml/luamml-pdf-demo.sty2
-rw-r--r--macros/luatex/latex/luamml/luamml-structelemwriter.lua44
-rw-r--r--macros/luatex/latex/luamml/luamml-table.lua7
-rw-r--r--macros/luatex/latex/luamml/luamml-tex-annotate.lua12
-rw-r--r--macros/luatex/latex/luamml/luamml-xmlwriter.lua8
-rw-r--r--macros/luatex/latex/luamml/luamml.dtx470
-rw-r--r--macros/luatex/latex/luamml/luamml.pdfbin169375 -> 205795 bytes
-rw-r--r--macros/luatex/latex/marginalia/README.md16
-rw-r--r--macros/luatex/latex/marginalia/marginalia-doc-ysep-explanation.pdfbin0 -> 436691 bytes
-rw-r--r--macros/luatex/latex/marginalia/marginalia-doc.pdfbin0 -> 845420 bytes
-rw-r--r--macros/luatex/latex/marginalia/marginalia.dtx1931
-rw-r--r--macros/luatex/latex/marginalia/marginalia.ins67
-rw-r--r--macros/xetex/latex/xduts/xduts.dtx7
-rw-r--r--macros/xetex/latex/xduts/xduts.pdfbin333865 -> 333871 bytes
58 files changed, 4031 insertions, 1365 deletions
diff --git a/macros/latex/contrib/physics-patch/README.txt b/macros/latex/contrib/physics-patch/README.txt
index ef059badb5..8a664a8812 100644
--- a/macros/latex/contrib/physics-patch/README.txt
+++ b/macros/latex/contrib/physics-patch/README.txt
@@ -1,4 +1,4 @@
-physics-patch 2.1
+physics-patch 2.4
Improved version of the physics package
diff --git a/macros/latex/contrib/physics-patch/physics-patch.pdf b/macros/latex/contrib/physics-patch/physics-patch.pdf
index e43c360ad3..d90ba10dd4 100644
--- a/macros/latex/contrib/physics-patch/physics-patch.pdf
+++ b/macros/latex/contrib/physics-patch/physics-patch.pdf
Binary files differ
diff --git a/macros/latex/contrib/physics-patch/physics-patch.sty b/macros/latex/contrib/physics-patch/physics-patch.sty
index 52e3786b22..ee29806427 100644
--- a/macros/latex/contrib/physics-patch/physics-patch.sty
+++ b/macros/latex/contrib/physics-patch/physics-patch.sty
@@ -1,5 +1,5 @@
\ProvidesPackage{physics-patch}
-% physics-patch 2.1
+% physics-patch 2.4
%
% Improved version of the physics package
%
@@ -17,7 +17,7 @@
%
% Author: Willie Shen (Willie169)
% Repository: https://github.com/Willie169/physics-patch
-% Last update: Feb 16, 2025
+% Last update: Feb 17, 2025
%
% For documentation, see physics-patch.pdf
@@ -40,17 +40,26 @@
\newif\iforiginaldiv
\DeclareOption{originaldiv}{\originaldivtrue} % Let \div be division symbol (default)
\DeclareOption{nooriginaldiv}{\originaldivfalse} % Let \div be \divergence
-\DeclareOption{trig}{\let\trigopt = 1} % Redefine trig function and operator (default)
-\DeclareOption{notrig}{\let\trigopt = 0} % Not redefine trig function and operator
+\newif\iftrig
+\DeclareOption{trig}{\trigtrue} % Redefine trig function and operator (default)
+\DeclareOption{notrig}{\trigfalse} % Not redefine trig function and operator
\DeclareOption{uprightdiff}{\def\diffd{\mathrm{d}}} % Upright differentials (default)
\DeclareOption{italicdiff}{\def\diffd{d}} % Italic differentials
\DeclareOption{bolddel}{\DeclareDocumentCommand\vnabla{}{\boldsymbol\nabla}} % Vector bold \nabla symbol (default)
\DeclareOption{arrowdel}{\DeclareDocumentCommand\vnabla{}{\vec{\boldsymbol\nabla}}} % Vector arrow \nabla symbol
+\DeclareOption{bolddot}{\DeclareDocumentCommand\dotproduct{}{\boldsymbol\cdot}} % Vector bold dot product symbol
+\DeclareOption{plaindot}{\DeclareDocumentCommand\dotproduct{}{\cdot}} % Vector plain dot product symbol (default)
\newif\ifshortgreek
-\DeclareOption{shortgreek}{\shortgreektrue} % Define shorthands for Greek letters
-\DeclareOption{noshortgreek}{\shortgreekfalse} % Not define shorthands for Greek letters (default)
+\DeclareOption{shortgreek}{\shortgreektrue} % Define shorthands for Greek alphabet
+\DeclareOption{noshortgreek}{\shortgreekfalse} % Not define shorthands for Greek alphabet (default)
+\newif\ifshortmathrm
+\DeclareOption{shortmathrm}{\shortmathrmtrue} % Define shorthands for mathrm alphabet and chemical element symbols
+\DeclareOption{noshortmathrm}{\shortmathrmfalse} % Not define shorthands for mathrm alphabet and chemical element symbols (default)
+\newif\ifshorttext
+\DeclareOption{shorttext}{\shorttexttrue} % Define shorthands for textnormal alphabet
+\DeclareOption{noshorttext}{\shorttextfalse} % Not define shorthands for textnormal alphabet (default)
\DeclareOption*{}
-\ExecuteOptions{override,pretend,nosiintegrate,originaldiv,trig,uprightdiff,bolddel,noshortgreek,noshortalphabet}
+\ExecuteOptions{override,pretend,nosiintegrate,originaldiv,trig,uprightdiff,bolddel,plaindot,noshortgreek,noshortmathrm,noshorttext}
\ProcessOptions\relax
\newif\ifphysics
@@ -62,56 +71,56 @@
\makeatother
\fi
-% Shorthands for Greek letters
+% shortgreek
\ifshortgreek
-\DeclareDocumentCommand{\tgAlpha}{O{}}{\text{\textAlpha}}
-\DeclareDocumentCommand{\tgBeta}{O{}}{\text{\textBeta}}
-\DeclareDocumentCommand{\tgGamma}{O{}}{\text{\textGamma}}
-\DeclareDocumentCommand{\tgDelta}{O{}}{\text{\textDelta}}
-\DeclareDocumentCommand{\tgEpsilon}{O{}}{\text{\textEpsilon}}
-\DeclareDocumentCommand{\tgZeta}{O{}}{\text{\textZeta}}
-\DeclareDocumentCommand{\tgEta}{O{}}{\text{\textEta}}
-\DeclareDocumentCommand{\tgTheta}{O{}}{\text{\textTheta}}
-\DeclareDocumentCommand{\tgIota}{O{}}{\text{\textIota}}
-\DeclareDocumentCommand{\tgKappa}{O{}}{\text{\textKappa}}
-\DeclareDocumentCommand{\tgLambda}{O{}}{\text{\textLambda}}
-\DeclareDocumentCommand{\tgMu}{O{}}{\text{\textMu}}
-\DeclareDocumentCommand{\tgNu}{O{}}{\text{\textNu}}
-\DeclareDocumentCommand{\tgXi}{O{}}{\text{\textXi}}
-\DeclareDocumentCommand{\tgOmicron}{O{}}{\text{\textOmicron}}
-\DeclareDocumentCommand{\tgPi}{O{}}{\text{\textPi}}
-\DeclareDocumentCommand{\tgRho}{O{}}{\text{\textRho}}
-\DeclareDocumentCommand{\tgSigma}{O{}}{\text{\textSigma}}
-\DeclareDocumentCommand{\tgTau}{O{}}{\text{\textTau}}
-\DeclareDocumentCommand{\tgUpsilon}{O{}}{\text{\textUpsilon}}
-\DeclareDocumentCommand{\tgPhi}{O{}}{\text{\textPhi}}
-\DeclareDocumentCommand{\tgChi}{O{}}{\text{\textChi}}
-\DeclareDocumentCommand{\tgPsi}{O{}}{\text{\textPsi}}
-\DeclareDocumentCommand{\tgOmega}{O{}}{\text{\textOmega}}
-\DeclareDocumentCommand{\tgalpha}{O{}}{\text{\textalpha}}
-\DeclareDocumentCommand{\tgbeta}{O{}}{\text{\textbeta}}
-\DeclareDocumentCommand{\tggamma}{O{}}{\text{\textgamma}}
-\DeclareDocumentCommand{\tgdelta}{O{}}{\text{\textdelta}}
-\DeclareDocumentCommand{\tgepsilon}{O{}}{\text{\textepsilon}}
-\DeclareDocumentCommand{\tgzeta}{O{}}{\text{\textzeta}}
-\DeclareDocumentCommand{\tgeta}{O{}}{\text{\texteta}}
-\DeclareDocumentCommand{\tgtheta}{O{}}{\text{\texttheta}}
-\DeclareDocumentCommand{\tgiota}{O{}}{\text{\textiota}}
-\DeclareDocumentCommand{\tgkappa}{O{}}{\text{\textkappa}}
-\DeclareDocumentCommand{\tglambda}{O{}}{\text{\textlambda}}
-\DeclareDocumentCommand{\tgmu}{O{}}{\text{\textmu}}
-\DeclareDocumentCommand{\tgnu}{O{}}{\text{\textnu}}
-\DeclareDocumentCommand{\tgxi}{O{}}{\text{\textxi}}
-\DeclareDocumentCommand{\tgomicron}{O{}}{\text{\textomicron}}
-\DeclareDocumentCommand{\tgpi}{O{}}{\text{\textpi}}
-\DeclareDocumentCommand{\tgrho}{O{}}{\text{\textrho}}
-\DeclareDocumentCommand{\tgsigma}{O{}}{\text{\textsigma}}
-\DeclareDocumentCommand{\tgtau}{O{}}{\text{\texttau}}
-\DeclareDocumentCommand{\tgupsilon}{O{}}{\text{\textupsilon}}
-\DeclareDocumentCommand{\tgphi}{O{}}{\text{\textphi}}
-\DeclareDocumentCommand{\tgchi}{O{}}{\text{\textchi}}
-\DeclareDocumentCommand{\tgpsi}{O{}}{\text{\textpsi}}
-\DeclareDocumentCommand{\tgomega}{O{}}{\text{\textomega}}
+\DeclareDocumentCommand{\tgAlpha}{g}{\text{\textAlpha}}
+\DeclareDocumentCommand{\tgBeta}{g}{\text{\textBeta}}
+\DeclareDocumentCommand{\tgGamma}{g}{\text{\textGamma}}
+\DeclareDocumentCommand{\tgDelta}{g}{\text{\textDelta}}
+\DeclareDocumentCommand{\tgEpsilon}{g}{\text{\textEpsilon}}
+\DeclareDocumentCommand{\tgZeta}{g}{\text{\textZeta}}
+\DeclareDocumentCommand{\tgEta}{g}{\text{\textEta}}
+\DeclareDocumentCommand{\tgTheta}{g}{\text{\textTheta}}
+\DeclareDocumentCommand{\tgIota}{g}{\text{\textIota}}
+\DeclareDocumentCommand{\tgKappa}{g}{\text{\textKappa}}
+\DeclareDocumentCommand{\tgLambda}{g}{\text{\textLambda}}
+\DeclareDocumentCommand{\tgMu}{g}{\text{\textMu}}
+\DeclareDocumentCommand{\tgNu}{g}{\text{\textNu}}
+\DeclareDocumentCommand{\tgXi}{g}{\text{\textXi}}
+\DeclareDocumentCommand{\tgOmicron}{g}{\text{\textOmicron}}
+\DeclareDocumentCommand{\tgPi}{g}{\text{\textPi}}
+\DeclareDocumentCommand{\tgRho}{g}{\text{\textRho}}
+\DeclareDocumentCommand{\tgSigma}{g}{\text{\textSigma}}
+\DeclareDocumentCommand{\tgTau}{g}{\text{\textTau}}
+\DeclareDocumentCommand{\tgUpsilon}{g}{\text{\textUpsilon}}
+\DeclareDocumentCommand{\tgPhi}{g}{\text{\textPhi}}
+\DeclareDocumentCommand{\tgChi}{g}{\text{\textChi}}
+\DeclareDocumentCommand{\tgPsi}{g}{\text{\textPsi}}
+\DeclareDocumentCommand{\tgOmega}{g}{\text{\textOmega}}
+\DeclareDocumentCommand{\tgalpha}{g}{\text{\textalpha}}
+\DeclareDocumentCommand{\tgbeta}{g}{\text{\textbeta}}
+\DeclareDocumentCommand{\tggamma}{g}{\text{\textgamma}}
+\DeclareDocumentCommand{\tgdelta}{g}{\text{\textdelta}}
+\DeclareDocumentCommand{\tgepsilon}{g}{\text{\textepsilon}}
+\DeclareDocumentCommand{\tgzeta}{g}{\text{\textzeta}}
+\DeclareDocumentCommand{\tgeta}{g}{\text{\texteta}}
+\DeclareDocumentCommand{\tgtheta}{g}{\text{\texttheta}}
+\DeclareDocumentCommand{\tgiota}{g}{\text{\textiota}}
+\DeclareDocumentCommand{\tgkappa}{g}{\text{\textkappa}}
+\DeclareDocumentCommand{\tglambda}{g}{\text{\textlambda}}
+\DeclareDocumentCommand{\tgmu}{g}{\text{\textmu}}
+\DeclareDocumentCommand{\tgnu}{g}{\text{\textnu}}
+\DeclareDocumentCommand{\tgxi}{g}{\text{\textxi}}
+\DeclareDocumentCommand{\tgomicron}{g}{\text{\textomicron}}
+\DeclareDocumentCommand{\tgpi}{g}{\text{\textpi}}
+\DeclareDocumentCommand{\tgrho}{g}{\text{\textrho}}
+\DeclareDocumentCommand{\tgsigma}{g}{\text{\textsigma}}
+\DeclareDocumentCommand{\tgtau}{g}{\text{\texttau}}
+\DeclareDocumentCommand{\tgupsilon}{g}{\text{\textupsilon}}
+\DeclareDocumentCommand{\tgphi}{g}{\text{\textphi}}
+\DeclareDocumentCommand{\tgchi}{g}{\text{\textchi}}
+\DeclareDocumentCommand{\tgpsi}{g}{\text{\textpsi}}
+\DeclareDocumentCommand{\tgomega}{g}{\text{\textomega}}
\DeclareDocumentCommand{\vAlpha}{}{\varAlpha}
\DeclareDocumentCommand{\vBeta}{}{\varBeta}
\DeclareDocumentCommand{\vGamma}{}{\varGamma}
@@ -258,9 +267,223 @@
\DeclareDocumentCommand{\uvomega}{}{\upvaromega}
\fi
+% shortmathrm
+\ifshortmathrm
+\DeclareDocumentCommand{\rmA}{e{_^}}{\ensuremath{\mathrm{A}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmB}{e{_^}}{\ensuremath{\mathrm{B}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmC}{e{_^}}{\ensuremath{\mathrm{C}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmD}{e{_^}}{\ensuremath{\mathrm{D}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmE}{e{_^}}{\ensuremath{\mathrm{E}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmF}{e{_^}}{\ensuremath{\mathrm{F}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmG}{e{_^}}{\ensuremath{\mathrm{G}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmH}{e{_^}}{\ensuremath{\mathrm{H}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmI}{e{_^}}{\ensuremath{\mathrm{I}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmJ}{e{_^}}{\ensuremath{\mathrm{J}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmK}{e{_^}}{\ensuremath{\mathrm{K}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmL}{e{_^}}{\ensuremath{\mathrm{L}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmM}{e{_^}}{\ensuremath{\mathrm{M}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmN}{e{_^}}{\ensuremath{\mathrm{N}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmO}{e{_^}}{\ensuremath{\mathrm{O}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmP}{e{_^}}{\ensuremath{\mathrm{P}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmQ}{e{_^}}{\ensuremath{\mathrm{Q}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmR}{e{_^}}{\ensuremath{\mathrm{R}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmS}{e{_^}}{\ensuremath{\mathrm{S}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmT}{e{_^}}{\ensuremath{\mathrm{T}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmU}{e{_^}}{\ensuremath{\mathrm{U}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmV}{e{_^}}{\ensuremath{\mathrm{V}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmW}{e{_^}}{\ensuremath{\mathrm{W}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmX}{e{_^}}{\ensuremath{\mathrm{X}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmY}{e{_^}}{\ensuremath{\mathrm{Y}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmZ}{e{_^}}{\ensuremath{\mathrm{Z}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rma}{e{_^}}{\ensuremath{\mathrm{a}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmb}{e{_^}}{\ensuremath{\mathrm{b}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmc}{e{_^}}{\ensuremath{\mathrm{c}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmd}{e{_^}}{\ensuremath{\mathrm{d}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rme}{e{_^}}{\ensuremath{\mathrm{e}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmf}{e{_^}}{\ensuremath{\mathrm{f}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmg}{e{_^}}{\ensuremath{\mathrm{g}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmh}{e{_^}}{\ensuremath{\mathrm{h}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmi}{e{_^}}{\ensuremath{\mathrm{i}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmj}{e{_^}}{\ensuremath{\mathrm{j}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmk}{e{_^}}{\ensuremath{\mathrm{k}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rml}{e{_^}}{\ensuremath{\mathrm{l}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmm}{e{_^}}{\ensuremath{\mathrm{m}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmn}{e{_^}}{\ensuremath{\mathrm{n}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmo}{e{_^}}{\ensuremath{\mathrm{o}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmp}{e{_^}}{\ensuremath{\mathrm{p}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmq}{e{_^}}{\ensuremath{\mathrm{q}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmr}{e{_^}}{\ensuremath{\mathrm{r}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rms}{e{_^}}{\ensuremath{\mathrm{s}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmt}{e{_^}}{\ensuremath{\mathrm{t}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmu}{e{_^}}{\ensuremath{\mathrm{u}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmv}{e{_^}}{\ensuremath{\mathrm{v}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmw}{e{_^}}{\ensuremath{\mathrm{w}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmx}{e{_^}}{\ensuremath{\mathrm{x}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmy}{e{_^}}{\ensuremath{\mathrm{y}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmz}{e{_^}}{\ensuremath{\mathrm{z}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmHe}{e{_^}}{\ensuremath{\mathrm{He}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmLi}{e{_^}}{\ensuremath{\mathrm{Li}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmBe}{e{_^}}{\ensuremath{\mathrm{Be}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmNe}{e{_^}}{\ensuremath{\mathrm{Ne}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmNa}{e{_^}}{\ensuremath{\mathrm{Na}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmMg}{e{_^}}{\ensuremath{\mathrm{Mg}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmAl}{e{_^}}{\ensuremath{\mathrm{Al}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmSi}{e{_^}}{\ensuremath{\mathrm{Si}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmCl}{e{_^}}{\ensuremath{\mathrm{Cl}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmAr}{e{_^}}{\ensuremath{\mathrm{Ar}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmCa}{e{_^}}{\ensuremath{\mathrm{Ca}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmSc}{e{_^}}{\ensuremath{\mathrm{Sc}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmTi}{e{_^}}{\ensuremath{\mathrm{Ti}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmCr}{e{_^}}{\ensuremath{\mathrm{Cr}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmMn}{e{_^}}{\ensuremath{\mathrm{Mn}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmFe}{e{_^}}{\ensuremath{\mathrm{Fe}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmCo}{e{_^}}{\ensuremath{\mathrm{Co}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmNi}{e{_^}}{\ensuremath{\mathrm{Ni}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmCu}{e{_^}}{\ensuremath{\mathrm{Cu}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmZn}{e{_^}}{\ensuremath{\mathrm{Zn}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmGa}{e{_^}}{\ensuremath{\mathrm{Ga}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmGe}{e{_^}}{\ensuremath{\mathrm{Ge}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmAs}{e{_^}}{\ensuremath{\mathrm{As}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmSe}{e{_^}}{\ensuremath{\mathrm{Se}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmBr}{e{_^}}{\ensuremath{\mathrm{Br}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmKr}{e{_^}}{\ensuremath{\mathrm{Kr}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmRb}{e{_^}}{\ensuremath{\mathrm{Rb}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmSr}{e{_^}}{\ensuremath{\mathrm{Sr}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmZr}{e{_^}}{\ensuremath{\mathrm{Zr}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmNb}{e{_^}}{\ensuremath{\mathrm{Nb}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmMo}{e{_^}}{\ensuremath{\mathrm{Mo}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmTc}{e{_^}}{\ensuremath{\mathrm{Tc}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmRu}{e{_^}}{\ensuremath{\mathrm{Ru}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmRh}{e{_^}}{\ensuremath{\mathrm{Rh}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmPd}{e{_^}}{\ensuremath{\mathrm{Pd}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmAg}{e{_^}}{\ensuremath{\mathrm{Ag}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmCd}{e{_^}}{\ensuremath{\mathrm{Cd}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmIn}{e{_^}}{\ensuremath{\mathrm{In}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmSn}{e{_^}}{\ensuremath{\mathrm{Sn}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmSb}{e{_^}}{\ensuremath{\mathrm{Sb}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmTe}{e{_^}}{\ensuremath{\mathrm{Te}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmXe}{e{_^}}{\ensuremath{\mathrm{Xe}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmCs}{e{_^}}{\ensuremath{\mathrm{Cs}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmBa}{e{_^}}{\ensuremath{\mathrm{Ba}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmLa}{e{_^}}{\ensuremath{\mathrm{La}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmCe}{e{_^}}{\ensuremath{\mathrm{Ce}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmPr}{e{_^}}{\ensuremath{\mathrm{Pr}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmNd}{e{_^}}{\ensuremath{\mathrm{Nd}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmPm}{e{_^}}{\ensuremath{\mathrm{Pm}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmSm}{e{_^}}{\ensuremath{\mathrm{Sm}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmEu}{e{_^}}{\ensuremath{\mathrm{Eu}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmGd}{e{_^}}{\ensuremath{\mathrm{Gd}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmTb}{e{_^}}{\ensuremath{\mathrm{Tb}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmDy}{e{_^}}{\ensuremath{\mathrm{Dy}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmHo}{e{_^}}{\ensuremath{\mathrm{Ho}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmEr}{e{_^}}{\ensuremath{\mathrm{Er}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmTm}{e{_^}}{\ensuremath{\mathrm{Tm}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmYb}{e{_^}}{\ensuremath{\mathrm{Yb}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmLu}{e{_^}}{\ensuremath{\mathrm{Lu}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmHf}{e{_^}}{\ensuremath{\mathrm{Hf}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmTa}{e{_^}}{\ensuremath{\mathrm{Ta}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmRe}{e{_^}}{\ensuremath{\mathrm{Re}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmOs}{e{_^}}{\ensuremath{\mathrm{Os}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmIr}{e{_^}}{\ensuremath{\mathrm{Ir}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmPt}{e{_^}}{\ensuremath{\mathrm{Pt}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmAu}{e{_^}}{\ensuremath{\mathrm{Au}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmHg}{e{_^}}{\ensuremath{\mathrm{Hg}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmTl}{e{_^}}{\ensuremath{\mathrm{Tl}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmPb}{e{_^}}{\ensuremath{\mathrm{Pb}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmBi}{e{_^}}{\ensuremath{\mathrm{Bi}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmPo}{e{_^}}{\ensuremath{\mathrm{Po}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmAt}{e{_^}}{\ensuremath{\mathrm{At}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmRn}{e{_^}}{\ensuremath{\mathrm{Rn}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmFr}{e{_^}}{\ensuremath{\mathrm{Fr}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmRa}{e{_^}}{\ensuremath{\mathrm{Ra}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmAc}{e{_^}}{\ensuremath{\mathrm{Ac}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmTh}{e{_^}}{\ensuremath{\mathrm{Th}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmPa}{e{_^}}{\ensuremath{\mathrm{Pa}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmNp}{e{_^}}{\ensuremath{\mathrm{Np}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmPu}{e{_^}}{\ensuremath{\mathrm{Pu}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmAm}{e{_^}}{\ensuremath{\mathrm{Am}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmCm}{e{_^}}{\ensuremath{\mathrm{Cm}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmBk}{e{_^}}{\ensuremath{\mathrm{Bk}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmCf}{e{_^}}{\ensuremath{\mathrm{Cf}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmEs}{e{_^}}{\ensuremath{\mathrm{Es}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmFm}{e{_^}}{\ensuremath{\mathrm{Fm}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmMd}{e{_^}}{\ensuremath{\mathrm{Md}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmNo}{e{_^}}{\ensuremath{\mathrm{No}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmLr}{e{_^}}{\ensuremath{\mathrm{Lr}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmRf}{e{_^}}{\ensuremath{\mathrm{Rf}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmDb}{e{_^}}{\ensuremath{\mathrm{Db}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmSg}{e{_^}}{\ensuremath{\mathrm{Sg}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmBh}{e{_^}}{\ensuremath{\mathrm{Bh}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmHs}{e{_^}}{\ensuremath{\mathrm{Hs}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmMt}{e{_^}}{\ensuremath{\mathrm{Mt}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmDs}{e{_^}}{\ensuremath{\mathrm{Ds}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmRg}{e{_^}}{\ensuremath{\mathrm{Rg}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmCn}{e{_^}}{\ensuremath{\mathrm{Cn}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmNh}{e{_^}}{\ensuremath{\mathrm{Nh}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmFl}{e{_^}}{\ensuremath{\mathrm{Fl}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmMc}{e{_^}}{\ensuremath{\mathrm{Mc}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmLv}{e{_^}}{\ensuremath{\mathrm{Lv}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmTs}{e{_^}}{\ensuremath{\mathrm{Ts}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\DeclareDocumentCommand{\rmOg}{e{_^}}{\ensuremath{\mathrm{Og}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
+\fi
+
+% shorttext
+\ifshorttext
+\DeclareDocumentCommand{\txA}{}{\textnormal{A}}
+\DeclareDocumentCommand{\txB}{}{\textnormal{B}}
+\DeclareDocumentCommand{\txC}{}{\textnormal{C}}
+\DeclareDocumentCommand{\txD}{}{\textnormal{D}}
+\DeclareDocumentCommand{\txE}{}{\textnormal{E}}
+\DeclareDocumentCommand{\txF}{}{\textnormal{F}}
+\DeclareDocumentCommand{\txG}{}{\textnormal{G}}
+\DeclareDocumentCommand{\txH}{}{\textnormal{H}}
+\DeclareDocumentCommand{\txI}{}{\textnormal{I}}
+\DeclareDocumentCommand{\txJ}{}{\textnormal{J}}
+\DeclareDocumentCommand{\txK}{}{\textnormal{K}}
+\DeclareDocumentCommand{\txL}{}{\textnormal{L}}
+\DeclareDocumentCommand{\txM}{}{\textnormal{M}}
+\DeclareDocumentCommand{\txN}{}{\textnormal{N}}
+\DeclareDocumentCommand{\txO}{}{\textnormal{O}}
+\DeclareDocumentCommand{\txP}{}{\textnormal{P}}
+\DeclareDocumentCommand{\txQ}{}{\textnormal{Q}}
+\DeclareDocumentCommand{\txR}{}{\textnormal{R}}
+\DeclareDocumentCommand{\txS}{}{\textnormal{S}}
+\DeclareDocumentCommand{\txT}{}{\textnormal{T}}
+\DeclareDocumentCommand{\txU}{}{\textnormal{U}}
+\DeclareDocumentCommand{\txV}{}{\textnormal{V}}
+\DeclareDocumentCommand{\txW}{}{\textnormal{W}}
+\DeclareDocumentCommand{\txX}{}{\textnormal{X}}
+\DeclareDocumentCommand{\txY}{}{\textnormal{Y}}
+\DeclareDocumentCommand{\txZ}{}{\textnormal{Z}}
+\DeclareDocumentCommand{\txa}{}{\textnormal{a}}
+\DeclareDocumentCommand{\txb}{}{\textnormal{b}}
+\DeclareDocumentCommand{\txc}{}{\textnormal{c}}
+\DeclareDocumentCommand{\txd}{}{\textnormal{d}}
+\DeclareDocumentCommand{\txe}{}{\textnormal{e}}
+\DeclareDocumentCommand{\txf}{}{\textnormal{f}}
+\DeclareDocumentCommand{\txg}{}{\textnormal{g}}
+\DeclareDocumentCommand{\txh}{}{\textnormal{h}}
+\DeclareDocumentCommand{\txi}{}{\textnormal{i}}
+\DeclareDocumentCommand{\txj}{}{\textnormal{j}}
+\DeclareDocumentCommand{\txk}{}{\textnormal{k}}
+\DeclareDocumentCommand{\txl}{}{\textnormal{l}}
+\DeclareDocumentCommand{\txm}{}{\textnormal{m}}
+\DeclareDocumentCommand{\txn}{}{\textnormal{n}}
+\DeclareDocumentCommand{\txo}{}{\textnormal{o}}
+\DeclareDocumentCommand{\txp}{}{\textnormal{p}}
+\DeclareDocumentCommand{\txq}{}{\textnormal{q}}
+\DeclareDocumentCommand{\txr}{}{\textnormal{r}}
+\DeclareDocumentCommand{\txs}{}{\textnormal{s}}
+\DeclareDocumentCommand{\txt}{}{\textnormal{t}}
+\DeclareDocumentCommand{\txu}{}{\textnormal{u}}
+\DeclareDocumentCommand{\txv}{}{\textnormal{v}}
+\DeclareDocumentCommand{\txw}{}{\textnormal{w}}
+\DeclareDocumentCommand{\txx}{}{\textnormal{x}}
+\DeclareDocumentCommand{\txy}{}{\textnormal{y}}
+\DeclareDocumentCommand{\txz}{}{\textnormal{z}}
+\fi
+
% Others
-\DeclareDocumentCommand{\autommode}{m}{\relax\ifmmode #1\else\(#1\)\fi}
-\let\amm\autommode
\DeclareDocumentCommand{\mathcolorbox}{ m m }{
\begingroup
\setlength{\fboxsep}{0pt}
@@ -271,16 +494,16 @@
{\colorbox{#1}{$\scriptscriptstyle#2$}}
\endgroup
}
-\let\mcbox\mathcolorbox
+\DeclareDocumentCommand\mcbox{}{\mathcolorbox}
\DeclareDocumentCommand{\autocolorbox}{m m}{
\relax\ifmmode \mathcolorbox{#1}{#2}\else\colorbox{#1}{#2}\fi
}
-\let\acbox\autocolorbox
-\let\cbox\autocolorbox
-\DeclareDocumentCommand{\tentothepowerof}{m}{\relax\ifmmode 10^{#1}\else\(10^{#1}\)\fi}
-\let\tenpow\tentothepowerof
-\DeclareDocumentCommand{\scientificnotation}{m m}{\relax\ifmmode #1\times 10^{#2}\else\(#1\times 10^{#2}\)\fi}
-\let\scinote\scientificnotation
+\DeclareDocumentCommand\acbox{}{\autocolorbox}
+\DeclareDocumentCommand\cbox{}{\autocolorbox}
+\DeclareDocumentCommand{\tentothepowerof}{m}{\ensuremath{10^{#1}}}
+\DeclareDocumentCommand\tenpow{}{\tentothepowerof}
+\DeclareDocumentCommand{\scientificnotation}{m m}{\ensuremath{#1\times 10^{#2}}}
+\DeclareDocumentCommand\scinote{}{\scientificnotation}
% Symbols
\DeclareDocumentCommand\lparen{}{(} % Left parenthesis
@@ -292,6 +515,13 @@
\DeclareDocumentCommand{\venti}{}{\cbox{cyan}{\phantom{\sum_x^x}}}
\DeclareDocumentCommand\Vtextvisiblespace{O{.3em}}{\mbox{\kern.06em\vrule height.3ex}\vbox{\hrule width#1}\hbox{\vrule height.3ex}}
+\DeclareDocumentCommand{\calE}{}{\mathcal{E}}
+\DeclareDocumentCommand{\bbR}{}{\mathbb{R}}
+\DeclareDocumentCommand{\bbC}{}{\mathbb{C}}
+\DeclareDocumentCommand{\bbQ}{}{\mathbb{Q}}
+\DeclareDocumentCommand{\bbN}{}{\mathbb{N}}
+\DeclareDocumentCommand{\bbZ}{}{\mathbb{Z}}
+
% Brackets and braces
\DeclareDocumentCommand{\PHquantity}{ t\big t\Big t\bigg t\Bigg o d() d|| g }
{ % Flexible automatic bracketing of an expression in () or [] or {} or ||
@@ -333,7 +563,7 @@
\IfNoValueTF{#8}{}{#8}
}
}
-\let\PHqty\PHquantity
+\DeclareDocumentCommand\PHqty{}{\PHquantity}
\IfPackageLoadedTF{siunitx}
{
\DeclareDocumentCommand{\ITquantity}{ t\big t\Big t\bigg t\Bigg o d() d|| g g }
@@ -383,17 +613,17 @@
}
}
}
- \let\ITqty\ITquantity
+ \DeclareDocumentCommand\ITqty{}{\ITquantity}
\ifsiintegrate
- \let\PTquantity\ITquantity
+ \DeclareDocumentCommand\PTquantity{}{\ITquantity}
\else
- \let\PTquantity\PHquantity
+ \DeclareDocumentCommand\PTquantity{}{\PHquantity}
\fi
-}{\let\PTquantity\PHquantity}
-\let\PTqty\PTquantity
+}{\DeclareDocumentCommand\PTquantity{}{\PHquantity}}
+\DeclareDocumentCommand\PTqty{}{\PTquantity}
\ifoverride
- \let\qty\PTquantity
- \let\quantity\PTquantity
+ \DeclareDocumentCommand\qty{}{\PTquantity}
+ \DeclareDocumentCommand\quantity{}{\PTquantity}
\fi
\DeclareDocumentCommand\pqty{ l m }{\braces#1{\lparen}{\rparen}{#2}}
\DeclareDocumentCommand\bqty{ l m }{\braces#1{\lbrack}{\rbrack}{#2}}
@@ -402,7 +632,7 @@
\DeclareDocumentCommand\omqty{m}{\begin{matrix}#1\end{matrix}}
\DeclareDocumentCommand\pmqty{m}{\begin{pmatrix}#1\end{pmatrix}}
\DeclareDocumentCommand\PTpmqty{s m}{\IfNoValueTF{#1}{\begin{pmatrix}#2\end{pmatrix}}{\left\lgroup\begin{matrix}#2\end{matrix}\right\rgroup}}
-\ifoverride\let\pmqty\PTpmqty\fi
+\ifoverride\DeclareDocumentCommand\pmqty{}{\PTpmqty}\fi
\DeclareDocumentCommand\Pmqty{m}{\left\lgroup\begin{matrix}#1\end{matrix}\right\rgroup}
\DeclareDocumentCommand\bmqty{m}{\begin{bmatrix}#1\end{bmatrix}}
\DeclareDocumentCommand\vmqty{m}{\begin{vmatrix}#1\end{vmatrix}}
@@ -435,15 +665,15 @@
\IfNoValueTF{#5}{}{|#5|}
}
}
-\let\PTmqty\PTmatrixquantity
-\ifoverride\let\mqty\PTmatrixquantity\fi
+\DeclareDocumentCommand\PTmqty{}{\PTmatrixquantity}
+\ifoverride\DeclareDocumentCommand\mqty{}{\PTmatrixquantity}\fi
\DeclareDocumentCommand\matrixdeterminant{m}{\vmqty{#1}} % Matrix determinant
\DeclareDocumentCommand\mdet{}{\matrixdeterminant} % Shorthand for matrix determinant
\DeclareDocumentCommand\somqty{m}{\begin{smallmatrix}#1\end{smallmatrix}}
\DeclareDocumentCommand\spmqty{m}{\pqty{\begin{smallmatrix}#1\end{smallmatrix}}}
\DeclareDocumentCommand\PTspmqty{s m}{\IfNoValueTF{#1}{\pqty{\begin{smallmatrix}#2\end{smallmatrix}}}{\left\lgroup\begin{smallmatrix}#2\end{smallmatrix}\right\rgroup}}
-\ifoverride\let\spmqty\PTspmqty\fi
+\ifoverride\DeclareDocumentCommand\spmqty{}{\PTspmqty}\fi
\DeclareDocumentCommand\sPmqty{m}{\left\lgroup\begin{smallmatrix}#1\end{smallmatrix}\right\rgroup}
\DeclareDocumentCommand\sbmqty{m}{\bqty{\begin{smallmatrix}#1\end{smallmatrix}}}
\DeclareDocumentCommand\svmqty{m}{\vqty{\begin{smallmatrix}#1\end{smallmatrix}}}
@@ -476,8 +706,8 @@
\IfNoValueTF{#5}{}{|#5|}
}
}
-\let\PTsmqty\PTsmallmatrixquantity
-\ifoverride\let\smqty\PTsmallmatrixquantity\fi
+\DeclareDocumentCommand\PTsmqty{}{\PTsmallmatrixquantity}
+\ifoverride\DeclareDocumentCommand\smqty{}{\PTsmallmatrixquantity}\fi
\DeclareDocumentCommand\smallmatrixdeterminant{m}{\svmqty{#1}} % Small matrix determinant
\DeclareDocumentCommand\smdet{}{\smallmatrixdeterminant} % Shorthand for small matrix determinant
@@ -572,8 +802,7 @@
\DeclareDocumentCommand\vectorunit{ s m }{\IfBooleanTF{#1}{\boldsymbol{\hat{#2}}}{\mathbf{\hat{#2}}}} % Unit vector [star for Greek and italic Roman]
\DeclareDocumentCommand\vu{}{\vectorunit} % Shorthand for \vectorunit
-\DeclareDocumentCommand\dotproduct{}{\boldsymbol\cdot} % Vector dot product symbol
-\DeclareDocumentCommand\vdot{}{\dotproduct} % Shorthand for \dotproduct [note that the command sequence \dp is protected]
+\DeclareDocumentCommand\vdot{}{\dotproduct}
\DeclareDocumentCommand\crossproduct{}{\boldsymbol\times} % Vector cross product symbol
\DeclareDocumentCommand\cross{}{\crossproduct} % Shorthand for \crossproduct
@@ -593,26 +822,25 @@
\DeclareDocumentCommand\divergence{ g o d() }{ % Divergence
\IfNoValueTF{#1}{
\IfNoValueTF{#2}{
- \IfNoValueTF{#3}{\vnabla \vdot}{\vnabla \vdot \quantity(#3)}
+ \IfNoValueTF{#3}{\vnabla \dotproduct}{\vnabla \dotproduct \quantity(#3)}
}
- {\vnabla \vdot \quantity[#2] \IfNoValueTF{#3}{}{(#3)}}
+ {\vnabla \dotproduct \quantity[#2] \IfNoValueTF{#3}{}{(#3)}}
}
- {\vnabla \vdot #1 \IfNoValueTF{#2}{}{[#2]} \IfNoValueTF{#3}{}{(#3)}}
+ {\vnabla \dotproduct #1 \IfNoValueTF{#2}{}{[#2]} \IfNoValueTF{#3}{}{(#3)}}
}
-\let\divg\divergence
+\DeclareDocumentCommand\divg{}{\divergence}
\iforiginaldiv
\ifphysics
- \let\div\divisionsymbol
- \let\divg\divergence
+ \DeclareDocumentCommand\div{}{\divisionsymbol}
\else
- \let\divisionsymbol\div
+ \DeclareDocumentCommand\divisionsymbol{}{\div}
\fi
\else
\ifphysics
- \let\div\divergence
+ \DeclareDocumentCommand\div{}{\divergence}
\else
- \let\divisionsymbol\div % Rename \div [division symbol] in order to free up control sequence for \divergence
- \let\div\divergence
+ \DeclareDocumentCommand\divisionsymbol{}{\div} % Rename \div [division symbol] in order to free up control sequence for \divergence
+ \DeclareDocumentCommand\div{}{\divergence}
\fi
\fi
@@ -645,8 +873,6 @@
\DeclareDocumentCommand\principalvalue{g}{\IfNoValueTF{#1}{\mathcal{P}}{\mathcal{P}\mathord{#1}}}
\DeclareDocumentCommand\pv{}{\principalvalue}
\DeclareDocumentCommand\PV{g}{\IfNoValueTF{#1}{\mathrm{P.V.}}{\mathrm{P.V.}\mathord{#1}}}
-\let\real\Re \DeclareDocumentCommand\Re{g}{\IfNoValueTF{#1}{\operatorname{Re}}{\fbraces{\lbrace}{\rbrace}{\operatorname{Re}}{#1}}}
-\let\imaginary\Im \DeclareDocumentCommand\Im{g}{\IfNoValueTF{#1}{\operatorname{Im}}{\fbraces{\lbrace}{\rbrace}{\operatorname{Im}}{#1}}}
\DeclareDocumentCommand\opbraces{ m g o d() }
{
\IfNoValueTF{#2}
@@ -676,7 +902,7 @@
}
% Trig function and operator redefinitions
-\ifx\trigopt 1
+\iftrig
\let\sine\sin \DeclareDocumentCommand\sin{}{\trigbraces{\sine}}
\let\cosine\cos \DeclareDocumentCommand\cos{}{\trigbraces{\cosine}}
\let\tangent\tan \DeclareDocumentCommand\tan{}{\trigbraces{\tangent}}
@@ -805,8 +1031,8 @@
{\fractype{\diffd \IfNoValueTF{#2}{}{^{#2}} #3}{\diffd #4\IfNoValueTF{#2}{}{^{#2}}}}
\IfNoValueTF{#5}{}{\argopen(#5\argclose)}
}
-\let\PTdv\PTderivative
-\ifoverride\let\dv\PTderivative\fi
+\DeclareDocumentCommand\PTdv{}{\PTderivative}
+\ifoverride\DeclareDocumentCommand\dv{}{\PTderivative}\fi
\DeclareDocumentCommand\PTpartialderivative{ s o m g g d() }
{ % Partial derivative
% s: star for \flatfrac flat derivative
@@ -831,11 +1057,11 @@
\IfNoValueTF{#6}{}{\argopen(#6\argclose)}
}
}
-\let\PTpdv\PTpartialderivative
-\let\PTpderivative\PTpartialderivative
+\DeclareDocumentCommand\PTpdv{}{\PTpartialderivative}
+\DeclareDocumentCommand\PTpderivative{}{\PTpartialderivative}
\ifoverride
- \let\pderivative\PTpartialderivative
- \let\pdv\PTpartialderivative
+ \DeclareDocumentCommand\pderivative{}{\PTpartialderivative}
+ \DeclareDocumentCommand\pdv{}{\PTpartialderivative}
\fi
\DeclareDocumentCommand\variation{ o g d() }{ % Functional variation
@@ -1133,8 +1359,8 @@
}
\the\matrixtoks
}
-\let\PTxmat\PTxmatrix
-\ifoverride\let\xmat\PTxmatrix\fi
+\DeclareDocumentCommand\PTxmat{}{\PTxmatrix}
+\ifoverride\DeclareDocumentCommand\xmat{}{\PTxmatrix}\fi
\DeclareDocumentCommand\zeromatrix{ m g }{\IfNoValueTF{#2}{\PTxmatrix{0}{#1}{#1}}{\PTxmatrix{0}{#1}{#2}}}
\DeclareDocumentCommand\zmat{}{\zeromatrix}
@@ -1231,8 +1457,8 @@
\DeclareDocumentCommand\flatfrac{ m m }{\left.#1\middle\slash#2\right.}
\DeclareDocumentCommand\homework{}{ % You can try it
\ensuremath{
- \div{\vb{E}}=\frac{\rho}{\epsilon_0} \qc
- \div{\vb{B}}=0 \qc
+ \divg{\vb{E}}=\frac{\rho}{\epsilon_0} \qc
+ \divg{\vb{B}}=0 \qc
\curl{\vb{E}}=-\pdv{\vb{B}}{t}\qc
\curl{\vb{B}}=\mu_0\vb{J}+\frac{1}{c^2}\pdv{\vb{E}}{t}\qc
H\ket{\Psi}=i\hbar\pdv{}{t}\ket{\Psi},
diff --git a/macros/latex/contrib/physics-patch/physics-patch.tex b/macros/latex/contrib/physics-patch/physics-patch.tex
index 17f01bb682..c7f1fdc419 100644
--- a/macros/latex/contrib/physics-patch/physics-patch.tex
+++ b/macros/latex/contrib/physics-patch/physics-patch.tex
@@ -6,10 +6,14 @@
\setmainfont{TeX Gyre Termes}[Ligatures=TeX]
\setsansfont{TeX Gyre Heros}[Ligatures=TeX]
\setmonofont{TeX Gyre Cursor}[Ligatures=TeX]
+\usepackage{unicode-math}
+\setmathfont{XITS Math}\setmathfont[range={cal,bfcal},StylisticSet=1]{XITS Math}
\everymath{\displaystyle}
\everydisplay{\displaystyle}
\newcolumntype{M}{>{$\displaystyle}c<{$}}
\newcolumntype{L}{>{$\displaystyle}l<{$}}
+\setlength{\LTleft}{\fill}
+\setlength{\LTright}{\fill}
\renewcommand{\maketitle}{
\begin{titlepage}
\begin{center}
@@ -23,7 +27,6 @@
\end{center}
\end{titlepage}
}
-\renewcommand{\arraystretch}{2}
\lstset{
basicstyle=\ttfamily\scriptsize,
keywordstyle=\color{blue},
@@ -42,7 +45,7 @@ breakatwhitespace=false
}
\title{The \texttt{physics-patch} package\\\mbox{}\\\textnormal{\large Improved version of the physics package}}
\author{\mbox{}\\Willie Shen (Willie169)}
-\date{Version 2.1\\\textnormal{Last update: Feb. 16, 2025}}
+\date{Version 2.4\\\textnormal{Last update: Feb. 17, 2025}}
\begin{document}
\onehalfspacing\thispagestyle{empty}\Needspace{1\textheight}\maketitle\setcounter{page}{1}\Needspace{1\textheight}\tableofcontents\Needspace{1\textheight}\setcounter{page}{1}
\section{Preface}
@@ -87,9 +90,9 @@ See \href{https://ctan.org/pkg/physics}{https://ctan.org/pkg/physics} for the de
\section{List of Commands}
In the commands listed below, the left column is long-form names with non-default alternate names (if any), the middle column is default shorthand commands with detailed syntaxes and explanations.\\
Commands that have different definitions come with \texttt{PT} in the beginning of their name (e.g. \verb|\PTmqty|). If \texttt{nooverride} is not used or the \texttt{physics} package is not loaded before this package, the commands without \texttt{PT} will be silent overriden to be the same as the ones with \texttt{PT}.
-{\fontsize{6pt}{9pt}\selectfont
\subsection{Automatic bracing}
-\begin{longtable}[l]{ p{6cm} l p{6cm} l p{6cm} }
+\begin{longtable}[l]{ | p{6cm} | p{6cm} | p{6cm} | }
+\hline
\verb|\PTquantity| or \verb|\PHquantity| or \verb|\PHqty| & \verb|\PTqty(\typical)| $\displaystyle\rightarrow \PTqty(\typical)$ & automatic $\PTqty(\;)$ braces \\
& \verb|\PTqty(\tall)| $\displaystyle\rightarrow \PTqty(\tall)$ & \\
& \verb|\PTqty(\grande)| $\displaystyle\rightarrow \PTqty(\grande)$ & \\
@@ -103,72 +106,74 @@ Commands that have different definitions come with \texttt{PT} in the beginning
& \verb|\pqty{}| $\leftrightarrow$ \verb|\PTqty()| & \multirow{2}{*}{\parbox{6cm}{alternative syntax; robust and more \LaTeX-friendly}} \\
& \verb|\bqty{}| $\leftrightarrow$ \verb|\PTqty[]| & \\
& \verb+\vqty{}+ $\leftrightarrow$ \verb+\PTqty||+ & \\
-& \verb|\Bqty{}| $\leftrightarrow$ \verb|\PTqty{}| & \\
+& \verb|\Bqty{}| $\leftrightarrow$ \verb|\PTqty{}| & \\\hline
\verb|\absolutevalue| & \verb|\abs{a}| $\rightarrow \abs{a}$ & automatic sizing; equivalent to \verb|\PTqty| \!\!\texttt{|a|} \\
& \verb|\abs\Big{a}| $\rightarrow \abs\Big{a}$ & inherits manual sizing syntax from \verb|\PTqty| \\
-& \verb|\abs*{\grande}| $\displaystyle\rightarrow \abs*{\grande}$ & star for no resize \\
+& \verb|\abs*{\grande}| $\displaystyle\rightarrow \abs*{\grande}$ & star for no resize \\\hline
\verb|\norm| & \verb|\norm{a}| $\rightarrow \norm{a}$ & automatic sizing \\
& \verb|\norm\Big{a}| $\rightarrow \norm\Big{a}$ & manual sizing \\
-& \verb|\norm*{\grande}| $\displaystyle\rightarrow \norm*{\grande}$ & star for no resize \\
+& \verb|\norm*{\grande}| $\displaystyle\rightarrow \norm*{\grande}$ & star for no resize \\\hline
\verb|\evaluated| & \verb|\eval{x}_0^\infty| $\displaystyle\rightarrow \eval{x}_0^\infty$ & vertical bar for evaluation limits \\
& \verb|\eval(x| \!\!\texttt{|}\!\! \verb|_0^\infty| $\displaystyle\rightarrow \eval(x|_0^\infty$ & alternate form \\
& \verb|\eval[x| \!\!\texttt{|}\!\! \verb|_0^\infty| $\displaystyle\rightarrow \eval[x|_0^\infty$ & alternate form \\
& \verb|\eval[\venti| \!\!\texttt{|}\!\! \verb|_0^\infty| $\displaystyle\rightarrow \eval[\venti|_0^\infty$ & automatic sizing\\
-& \verb|\eval*[\venti| \!\!\texttt{|}\!\! \verb|_0^\infty| $\displaystyle\rightarrow \eval*[\venti|_0^\infty$ & star for no resize \\
+& \verb|\eval*[\venti| \!\!\texttt{|}\!\! \verb|_0^\infty| $\displaystyle\rightarrow \eval*[\venti|_0^\infty$ & star for no resize \\\hline
\verb|\order| & \verb|\order{x^2}| $\rightarrow \order{x^2}$ & order symbol; automatic sizing and space handling \\
& \verb|\order\Big{x^2}| $\rightarrow \order\Big{x^2}$ & manual sizing \\
-& \verb|\order*{\grande}| $\displaystyle\rightarrow \order*{\grande}$ & star for no resize \\
+& \verb|\order*{\grande}| $\displaystyle\rightarrow \order*{\grande}$ & star for no resize \\\hline
\verb|\commutator| & \verb|\comm{A}{B}| $\rightarrow \comm{A}{B}$ & automatic sizing \\
& \verb|\comm\Big{A}{B}| $\rightarrow \comm\Big{A}{B}$ & manual sizing \\
-& \verb|\comm*{A}{\grande}| $\displaystyle\rightarrow \comm*{A}{\grande}$ & star for no resize \\
-\verb|\anticommutator| or \verb|\acommutator| & \verb|\acomm{A}{B}| $\rightarrow \acomm{A}{B}$ & same as \verb|\poissonbracket| \\
-\verb|\poissonbracket| & \verb|\pb{A}{B}| $\rightarrow \pb{A}{B}$ & same as \verb|\anticommutator|
+& \verb|\comm*{A}{\grande}| $\displaystyle\rightarrow \comm*{A}{\grande}$ & star for no resize \\\hline
+\verb|\anticommutator| or \verb|\acommutator| & \verb|\acomm{A}{B}| $\rightarrow \acomm{A}{B}$ & same as \verb|\poissonbracket| \\\hline
+\verb|\poissonbracket| & \verb|\pb{A}{B}| $\rightarrow \pb{A}{B}$ & same as \verb|\anticommutator|\\\hline
\end{longtable}
\subsection{Vector notation}
The default del symbol $\vnabla$ used in \texttt{physics-patch} vector notation can be switched to appear with an arrow $\vec{\vnabla}$ by including the option \texttt{arrowdel} in the document preamble:
\begin{lstlisting}[language=TeX]
\usepackage[arrowdel]{physics-patch}
\end{lstlisting}
-\begin{longtable}[l]{ p{6cm} l p{6cm} l p{6cm} }
+\begin{longtable}[l]{ | p{6cm} | p{6cm} | p{6cm} | }
+\hline
\verb|\vectorbold| & \verb|\vb{a}| $\rightarrow \vb{a}$ & upright/no Greek \\
-& \verb|\vb*{a}|, \verb|\vb*{\theta}| $\rightarrow \vb*{a}$, $\vb*{\theta}$ & italic/Greek \\
+& \verb|\vb*{a}|, \verb|\vb*{\theta}| $\rightarrow \vb*{a}$, $\vb*{\theta}$ & italic/Greek \\\hline
\verb|\vectorarrow| & \verb|\va{a}| $\rightarrow \va{a}$ & upright/no Greek \\
-& \verb|\va*{a}|, \verb|\va*{\theta}| $\rightarrow \va*{a}$, $\va*{\theta}$ & italic/Greek \\
+& \verb|\va*{a}|, \verb|\va*{\theta}| $\rightarrow \va*{a}$, $\va*{\theta}$ & italic/Greek \\\hline
\verb|\vectorunit| & \verb|\vu{a}| $\rightarrow \vu{a}$ & upright/no Greek \\
-& \verb|\vu*{a}|, \verb|\vu*{\theta}| $\rightarrow \vu*{a}$, $\vu*{\theta}$ & italic/Greek \\
-\verb|\dotproduct| & \verb|\vdot| $\rightarrow \vdot$ as in $\vb{a} \vdot \vb{b}$ & note: \verb|\dp| is a protected \TeX\ primitive \\
+& \verb|\vu*{a}|, \verb|\vu*{\theta}| $\rightarrow \vu*{a}$, $\vu*{\theta}$ & italic/Greek \\\hline
+\verb|\dotproduct| & \verb|\vdot| $\rightarrow \vdot$ as in $\vb{a} \vdot \vb{b}$ & note: \verb|\dp| is a protected \TeX\ primitive \\\hline
\verb|\crossproduct| & \verb|\cross| $\rightarrow \cross$ as in $\vb{a} \cross \vb{b}$ & alternate name \\
-& \verb|\cp| $\rightarrow \cp$ as in $\vb{a} \cp \vb{b}$ & shorthand name \\
+& \verb|\cp| $\rightarrow \cp$ as in $\vb{a} \cp \vb{b}$ & shorthand name \\\hline
\verb|\gradient| & \verb|\grad| $\rightarrow \grad$ & \\
& \verb|\grad{\Psi}| $\rightarrow \grad{\Psi}$ & default mode \\
& \verb|\grad(\Psi+\tall)| $\displaystyle\rightarrow \grad(\Psi+\tall)$ & long-form (like \verb|\PTqty| but also handles spacing) \\
-& \verb|\grad[\Psi+\tall]| $\displaystyle\rightarrow \grad[\Psi+\tall]$ & \\
+& \verb|\grad[\Psi+\tall]| $\displaystyle\rightarrow \grad[\Psi+\tall]$ & \\\hline
+\verb|\divisionsymbol| & \verb|\divisionsymbol| $\rightarrow \divisionsymbol$ & \\\hline
\verb|\divergence| & \verb|\divg| $\rightarrow \divg$ & note: if \texttt{nooriginaldiv} option is used, \verb|\div| will be overriden as $\divg$ too (not recommended) \\
-\verb|\divisionsymbol| & \verb|\divisionsymbol| $\rightarrow \divisionsymbol$ & \\
& \verb|\divg{\vb{a}}| $\rightarrow \divg{\vb{a}}$ & default mode \\
& \verb|\divg(\vb{a}+\tall)| $\displaystyle\rightarrow \divg(\vb{a}+\tall)$ & long-form \\
-& \verb|\divg[\vb{a}+\tall]| $\displaystyle\rightarrow \divg[\vb{a}+\tall]$ & \\
+& \verb|\divg[\vb{a}+\tall]| $\displaystyle\rightarrow \divg[\vb{a}+\tall]$ & \\\hline
\verb|\curl| & \verb|\curl| $\rightarrow \curl$ & \\
& \verb|\curl{\vb{a}}| $\rightarrow \curl{\vb{a}}$ & default mode \\
& \verb|\curl(\vb{a}+\tall)| $\displaystyle\rightarrow \curl(\vb{a}+\tall)$ & long-form \\
-& \verb|\curl[\vb{a}+\tall]| $\displaystyle\rightarrow \curl[\vb{a}+\tall]$ & \\
+& \verb|\curl[\vb{a}+\tall]| $\displaystyle\rightarrow \curl[\vb{a}+\tall]$ & \\\hline
\verb|\laplacian| & \verb|\laplacian| $\rightarrow \laplacian$ & \\
& \verb|\laplacian{\Psi}| $\rightarrow \laplacian{\Psi}$ & default mode \\
& \verb|\laplacian(\Psi+\tall)| $\displaystyle\rightarrow \laplacian(\Psi+\tall)$ & long-form \\
-& \verb|\laplacian[\Psi+\tall]| $\displaystyle\rightarrow \laplacian[\Psi+\tall]$ &
+& \verb|\laplacian[\Psi+\tall]| $\displaystyle\rightarrow \laplacian[\Psi+\tall]$ &\\\hline
\end{longtable}
\subsection{Operators}
The standard set of trig functions is redefined in \texttt{physics-patch} to provide automatic braces that behave like \verb|\PTqty()|. In addition, an optional power argument is provided. This behavior can be switched off by including the option \texttt{notrig} in the preamble:
\begin{lstlisting}[language=TeX]
\usepackage[notrig]{physics-patch}
\end{lstlisting}
-\begin{longtable}[l]{ l l p{8cm} }
-\multicolumn{3}{l}{Example trig redefinitions:} \\
+\begin{longtable}[l]{ | p{6cm} | p{6cm} | p{6cm} | }
+\hline
+\multicolumn{3}{|l|}{Example trig redefinitions:} \\\hline
\verb|\sin| & \verb|\sin(\grande)| $\displaystyle\rightarrow \sin(\grande)$ & automatic braces; old \verb|\sin| renamed \verb|\sine| \\
& \verb|\sin[2](x)| $\rightarrow \sin[2](x)$ & optional power \\
-& \verb|\sin x| $\rightarrow \sin x$ & can still use without an argument
+& \verb|\sin x| $\rightarrow \sin x$ & can still use without an argument \\\hline
\end{longtable}
-The full set of available trig functions in \texttt{physics-patch} includes:
+The full set of available trig functions in \texttt{physics-patch} includes:\\
\begin{longtable}{llll}
\verb|\sin(x)| & \verb|\sinh(x)| & \verb|\arcsin(x)| & \verb|\asin(x)| \\
\verb|\cos(x)| & \verb|\cosh(x)| & \verb|\arccos(x)| & \verb|\acos(x)| \\
@@ -183,72 +188,75 @@ The full set of available trig functions in \texttt{physics-patch} includes:
\tan(x) & \tanh(x) & \arctan(x) & \atan(x) \\
\csc(x) & \csch(x) & \arccsc(x) & \acsc(x) \\
\sec(x) & \sech(x) & \arcsec(x) & \asec(x) \\
-\cot(x) & \coth(x) & \arccot(x) & \acot(x)
+\cot(x) & \coth(x) & \arccot(x) & \acot(x)\\
\end{longtable}
-The standard trig functions (plus a few that are missing in \texttt{amsmath}) are available without any automatic bracing under a new set of longer names:
+The standard trig functions (plus a few that are missing in \texttt{amsmath}) are available without any automatic bracing under a new set of longer names:\\
\begin{longtable}{llll}
\verb|\sine| & \verb|\hypsine| & \verb|\arcsine| & \verb|\asine| \\
\verb|\cosine| & \verb|\hypcosine| & \verb|\arccosine| & \verb|\acosine| \\
\verb|\tangent| & \verb|\hyptangent| & \verb|\arctangent| & \verb|\atangent| \\
\verb|\cosecant| & \verb|\hypcosecant| & \verb|\arccosecant| & \verb|\acosecant| \\
\verb|\secant| & \verb|\hypsecant| & \verb|\arcsecant| & \verb|\asecant| \\
-\verb|\cotangent| & \verb|\hypcotangent| & \verb|\arccotangent| & \verb|\acotangent|
+\verb|\cotangent| & \verb|\hypcotangent| & \verb|\arccotangent| & \verb|\acotangent|\\
\end{longtable}
-Similar behavior has also been extended to the following functions:
-\begin{longtable}{l>{$}l<{$}ll}
-\verb|\exp(\tall)| & \exp(\tall) & & \verb|\exponential| \\
-\verb|\log(\tall)| & \log(\tall) & & \verb|\logarithm| \\
-\verb|\ln(\tall)| & \ln(\tall) & old definitions $\Rightarrow$ & \verb|\naturallogarithm| \\
-\verb|\det(\tall)| & \det(\tall) & & \verb|\determinant| \\
-\verb|\Pr(\tall)| & \Pr(\tall) & & \verb|\Probability|
+Similar behavior has also been extended to the following functions:\\
+\begin{longtable}{|l|>{$}l<{$}|l|l|}
+\hline
+\verb|\exp(\tall)| & \exp(\tall) & \multirow{5}{*}{old definitions $\Rightarrow$} & \verb|\exponential| \\\cline{1-2}\cline{4-4}
+\verb|\log(\tall)| & \log(\tall) & & \verb|\logarithm| \\\cline{1-2}\cline{4-4}
+\verb|\ln(\tall)| & \ln(\tall) & & \verb|\naturallogarithm| \\\cline{1-2}\cline{4-4}
+\verb|\det(\tall)| & \det(\tall) & & \verb|\determinant| \\\cline{1-2}\cline{4-4}
+\verb|\Pr(\tall)| & \Pr(\tall) & & \verb|\Probability|\\\hline
\end{longtable}
-\begin{longtable}[l]{ l l p{8cm} }
-\multicolumn{3}{l}{New operators:} \\
-\verb|\trace| or \verb|\tr| & \verb|\tr\rho| $\rightarrow \tr\rho$ also \verb|\tr(\tall)| $\rightarrow \tr(\tall)$ & trace; same bracing as trig functions \\
-\verb|\Trace| or \verb|\Tr| & \verb|\Tr\rho| $\rightarrow \Tr\rho$ & alternate \\
-\verb|\rank| & \verb|\rank M| $\rightarrow \rank M$ & matrix rank \\
-\verb|\erf| & \verb|\erf(x)|$\rightarrow \erf(x)$ & Gauss error function \\
-\verb|\Res| & \verb|\Res[f(z)]|$\rightarrow \Res[f(z)]$ & residue; same bracing as trig functions \\
+\begin{longtable}[l]{ | p{6cm} | p{6cm} | p{6cm} | }
+\hline
+\multicolumn{3}{|l|}{New operators:} \\\hline
+\verb|\trace| or \verb|\tr| & \verb|\tr\rho| $\rightarrow \tr\rho$ also \verb|\tr(\tall)| $\rightarrow \tr(\tall)$ & trace; same bracing as trig functions \\\hline
+\verb|\Trace| or \verb|\Tr| & \verb|\Tr\rho| $\rightarrow \Tr\rho$ & alternate \\\hline
+\verb|\rank| & \verb|\rank M| $\rightarrow \rank M$ & matrix rank \\\hline
+\verb|\erf| & \verb|\erf(x)|$\rightarrow \erf(x)$ & Gauss error function \\\hline
+\verb|\Res| & \verb|\Res[f(z)]|$\rightarrow \Res[f(z)]$ & \parbox{6cm}{residue; same bracing as trig functions} \\\hline
\verb|\principalvalue| & \verb|\pv{\int f(z) \dd{z}}|$\rightarrow \pv{\int f(z) \dd{z}}$ & Cauchy principal value \\
-& \verb|\PV{\int f(z) \dd{z}}|$\rightarrow \PV{\int f(z) \dd{z}}$ & alternate \\
-\verb|\Re| & \verb|\Re{z}| $\rightarrow \Re{z}$ & old \verb|\Re| renamed to \verb|\real| $\rightarrow \real$ \\
-\verb|\Im| & \verb|\Im{z}| $\rightarrow \Im{z}$ & old \verb|\Im| renamed to \verb|\imaginary| $\rightarrow \imaginary$
+& \verb|\PV{\int f(z) \dd{z}}|$\rightarrow \PV{\int f(z) \dd{z}}$ & alternate \\\hline
\end{longtable}
\subsection{Quick quad text}
-This set of commands produces text in math-mode padded by \verb|\quad| spacing on either side. This is meant to provide a quick way to insert simple words or phrases in a sequence of equations. Each of the following commands includes a starred version which pads the text only on the right side with \verb|\quad| for use in aligned environments such as \texttt{cases}.
-\begin{longtable}[l]{ p{6cm} l p{6cm} l p{6cm} }
-General text: & & \\
+This set of commands produces text in math-mode padded by \verb|\quad| spacing on either side. This is meant to provide a quick way to insert simple words or phrases in a sequence of equations. Each of the following commands includes a starred version which pads the text only on the right side with \verb|\quad| for use in aligned environments such as \texttt{cases}.\\
+\begin{longtable}[l]{ | p{6cm} | p{6cm} | p{6cm} | }
+\hline
+\multicolumn{3}{|l|}{General text:} \\\hline
\verb|\qqtext| & \verb|\qq{}| & general quick quad text with argument \\
& \verb|\qq{word or phrase}| $\rightarrow$\Vtextvisiblespace[1em]$\text{word or phrase}$\Vtextvisiblespace[1em] & normal mode; left and right \verb|\quad| \\
-& \verb|\qq*{word or phrase}| $\rightarrow \text{word or phrase}$\Vtextvisiblespace[1em] & starred mode; right \verb|\quad| only
+& \verb|\qq*{word or phrase}| $\rightarrow \text{word or phrase}$\Vtextvisiblespace[1em] & starred mode; right \verb|\quad| only\\\hline
\end{longtable}
-\begin{longtable}[l]{ l l }
-Special macros: & \\
-\verb|\qcomma| or \verb|\qc| $\rightarrow ,$\Vtextvisiblespace[1em] & right \verb|\quad| only \\
-\verb|\qcc| $\rightarrow$\Vtextvisiblespace[1em]$\text{c.c.}$\Vtextvisiblespace[1em] & complex conjugate; left and right \verb|\quad| unless starred \verb|\qcc*| $\rightarrow \text{c.c.}$\Vtextvisiblespace[1em] \\
-\verb|\qif| $\rightarrow$\Vtextvisiblespace[1em]$\text{if}$\Vtextvisiblespace[1em] & left and right \verb|\quad| unless starred \verb|\qif*| $\rightarrow \text{if}$\Vtextvisiblespace[1em]
+\begin{longtable}[l]{| l | l | }
+\hline
+Special macros: & \\\hline
+\verb|\qcomma| or \verb|\qc| $\rightarrow ,$\Vtextvisiblespace[1em] & right \verb|\quad| only \\\hline
+\verb|\qcc| $\rightarrow$\Vtextvisiblespace[1em]$\text{c.c.}$\Vtextvisiblespace[1em] & complex conjugate; left and right \verb|\quad| unless starred \verb|\qcc*| $\rightarrow \text{c.c.}$\Vtextvisiblespace[1em] \\\hline
+\verb|\qif| $\rightarrow$\Vtextvisiblespace[1em]$\text{if}$\Vtextvisiblespace[1em] & left and right \verb|\quad| unless starred \verb|\qif*| $\rightarrow \text{if}$\Vtextvisiblespace[1em]\\\hline
\end{longtable}
-\begin{longtable}[l]{ l }
-Similar to \verb|\qif|: \\
-\verb|\qthen|, \verb|\qelse|, \verb|\qotherwise|, \verb|\qunless|, \verb|\qgiven|, \verb|\qusing|, \verb|\qassume|, \verb|\qsince|, \\
-\verb|\qlet|, \verb|\qfor|, \verb|\qall|, \verb|\qeven|, \verb|\qodd|, \verb|\qinteger|, \verb|\qand|, \verb|\qor|, \verb|\qas|, \verb|\qin|
+\begin{longtable}[l]{ | l | }
+\hline
+Similar to \verb|\qif|: \\\hline
+\verb|\qthen|, \verb|\qelse|, \verb|\qotherwise|, \verb|\qunless|, \verb|\qgiven|, \verb|\qusing|, \verb|\qassume|, \verb|\qsince|, \verb|\qlet| \\ \verb|\qfor|, \verb|\qall|, \verb|\qeven|, \verb|\qodd|, \verb|\qinteger|, \verb|\qand|, \verb|\qor|, \verb|\qas|, \verb|\qin| \\\hline
\end{longtable}
\subsection{Derivatives}
The default differential symbol $\dd$ which is used in \verb|\differential| and \verb|\derivative| can be switched to an italic form $d$ by including the option \texttt{italicdiff} in the preamble:
\begin{lstlisting}[language=TeX]
\usepackage[italicdiff]{physics-patch}
\end{lstlisting}
-\begin{longtable}[l]{ p{6cm} l p{6cm} l p{6cm} }
+\begin{longtable}[l]{ | p{6cm} | p{6cm} | p{6cm} | }
+\hline
\verb|\differential| & \verb|\dd| $\rightarrow \dd$ & \\
& \verb|\dd x| $\rightarrow \dd x$ & no spacing (not recommended) \\
& \verb|\dd{x}| $\rightarrow$ \textvisiblespace\,$\dd{x}$\textvisiblespace & automatic spacing based on neighbors \\
& \verb|\dd[3]{x}| $\rightarrow \dd[3]{x}$ & optional power \\
-& \verb|\dd(\cos\theta)| $\rightarrow \dd(\cos\theta)$ & long-form; automatic braces \\
+& \verb|\dd(\cos\theta)| $\rightarrow \dd(\cos\theta)$ & long-form; automatic braces \\\hline
\verb|\PTderivative| & \verb|\PTdv{x}| $\displaystyle\rightarrow \PTdv{x}$ & one argument \\
& \verb|\PTdv{f}{x}| $\displaystyle\rightarrow \PTdv{f}{x}$ & two arguments \\
& \verb|\PTdv[n]{f}{x}| $\displaystyle\rightarrow \PTdv[n]{f}{x}$ & optional power \\
& \verb|\PTdv{x}(\grande)| $\displaystyle\rightarrow \PTdv{x}(\grande)$ & long-form; automatic braces, spacing \\
-& \verb|\PTdv*{f}{x}| $\displaystyle\rightarrow \PTdv*{f}{x}$ & inline form using \verb|\flatfrac| \\
+& \verb|\PTdv*{f}{x}| $\displaystyle\rightarrow \PTdv*{f}{x}$ & inline form using \verb|\flatfrac| \\\hline
\verb|\PTpartialderivative| or \verb|\PTpderivative| & \verb|\PTdv{f}{x}(\grande)| $\displaystyle\rightarrow \PTdv{f}{x}(\grande)$ & note: in original \texttt{physics} package, \verb|\dv{f}{x}(\grande)| $\displaystyle\rightarrow \dv{f}{x}$\\
& \verb|\PTpdv{x}| $\displaystyle\rightarrow \PTpdv{x}$ & shorthand name \\
& \verb|\PTpdv{f}{x}| $\displaystyle\rightarrow \PTpdv{f}{x}$ & two arguments \\
@@ -256,13 +264,13 @@ The default differential symbol $\dd$ which is used in \verb|\differential| and
& \verb|\PTpdv{x}(\grande)| $\displaystyle\rightarrow \PTpdv{x}(\grande)$ & long-form \\
& \verb|\PTpdv{f}{x}{y}| $\displaystyle\rightarrow \PTpdv{f}{x}{y}$ & mixed partial \\
& \verb|\PTpdv*{f}{x}| $\displaystyle\rightarrow \PTpdv*{f}{x}$ & inline form using \verb|\flatfrac| \\
-& \verb|\PTpdv{f}{x}(\grande)| $\displaystyle\rightarrow \PTpdv{f}{x}(\grande)$ & note: in original \texttt{physics} package, \verb|\pdv{f}{x}(\grande)| $\displaystyle\rightarrow \pdv{f}{x}$ \\
+& \verb|\PTpdv{f}{x}(\grande)| $\displaystyle\rightarrow \PTpdv{f}{x}(\grande)$ & note: in original \texttt{physics} package, \verb|\pdv{f}{x}(\grande)| $\displaystyle\rightarrow \pdv{f}{x}$ \\\hline
\verb|\variation| & \verb|\var{F[g(x)]}| $\rightarrow \var{F[g(x)]}$ & functional variation (works like \verb|\dd|) \\
-& \verb|\var(E-TS)| $\rightarrow \var(E-TS)$ & long-form \\
+& \verb|\var(E-TS)| $\rightarrow \var(E-TS)$ & long-form \\\hline
\verb|\functionalderivative| & \verb|\fdv{g}| $\displaystyle\rightarrow \fdv{g}$ & functional derivative (works like \verb|\PTdv|) \\
& \verb|\fdv{F}{g}| $\displaystyle\rightarrow \fdv{F}{g}$ & \\
& \verb|\fdv{V}(E-TS)| $\displaystyle\rightarrow \fdv{V}(E-TS)$ & long-form \\
-& \verb|\fdv*{F}{x}| $\displaystyle\rightarrow \fdv*{F}{x}$ & inline form using \verb|\flatfrac|
+& \verb|\fdv*{F}{x}| $\displaystyle\rightarrow \fdv*{F}{x}$ & inline form using \verb|\flatfrac| \\\hline
\end{longtable}
\subsection{Dirac bra-ket notation}
The following collection of macros for Dirac notation contains two fundamental commands, \verb|\bra| and \verb|\ket|, along with a set of more specialized macros which are essentially combinations of the fundamental pair. The fundamental commands are designed to contract with one another algebraically when appropriate and are thus suggested for general use. For instance, the following code renders correctly\footnote{Note the lack of a space between the bra and ket commands. This is necessary in order for the bra to find the corresponding ket and form a contraction.}
@@ -277,44 +285,44 @@ On the other hand, the correct output can be generated by sticking to the fundam
\begin{displaymath}
\verb|\bra{\phi}\ket{\psi}\bra{\xi}| \rightarrow \bra{\phi}\ket{\psi}\bra{\xi}
\end{displaymath}
-allowing the user to type out complicated quantum mechanical expressions without worrying about bra-ket contractions. That being said, the high-level macros do have a place in convenience and readability, as long as the user is aware of rendering issues that may arise due to an absence of automatic contractions.
-\begin{longtable}[l]{ p{6cm} l p{6cm} l p{6cm} }
+allowing the user to type out complicated quantum mechanical expressions without worrying about bra-ket contractions. That being said, the high-level macros do have a place in convenience and readability, as long as the user is aware of rendering issues that may arise due to an absence of automatic contractions.\\
+\begin{longtable}[l]{ | p{6cm} | p{6cm} | p{6cm} | }
+\hline
\verb|\ket| & \verb|\ket{\tall}| $\rightarrow \ket{\tall}$ & automatic sizing \\
-& \verb|\ket*{\tall}| $\rightarrow \ket*{\tall}$ & no resize \\
+& \verb|\ket*{\tall}| $\rightarrow \ket*{\tall}$ & no resize \\\hline
\verb|\bra| & \verb|\bra{\tall}| $\rightarrow \bra{\tall}$ & automatic sizing \\
& \verb|\bra*{\tall}| $\rightarrow \bra*{\tall}$ & no resize \\
& \verb|\bra{\phi}\ket{\psi}| $\rightarrow \bra{\phi}\ket{\psi}$ & automatic contraction \\
& \verb|\bra{\phi}\ket{\tall}| $\rightarrow \bra{\phi}\ket{\tall}$ & contraction inherits automatic sizing \\
& \verb|\bra{\phi}\ket*{\tall}| $\rightarrow \bra{\phi}\ket*{\tall}$ & \multirow{2}{*}{\parbox{6cm}{a star on either term in the contraction prohibits resizing}} \\
& \verb|\bra*{\phi}\ket{\tall}| $\rightarrow \bra*{\phi}\ket{\tall}$ & \\
-& \verb|\bra*{\phi}\ket*{\tall}| $\rightarrow \bra*{\phi}\ket*{\tall}$ & \\
+& \verb|\bra*{\phi}\ket*{\tall}| $\rightarrow \bra*{\phi}\ket*{\tall}$ & \\\hline
\verb|\innerproduct| & $\verb|\braket{a}{b}| \rightarrow \braket{a}{b}$ & two-argument braket \\
& \verb|\braket{a}| $\rightarrow \braket{a}$ & one-argument (norm) \\
& \verb|\braket{a}{\tall}| $\rightarrow \braket{a}{\tall}$ & automatic sizing \\
& \verb|\braket*{a}{\tall}| $\rightarrow \braket*{a}{\tall}$ & no resize \\
-& \verb|\ip{a}{b}| $\rightarrow \ip{a}{b}$ & shorthand name \\
+& \verb|\ip{a}{b}| $\rightarrow \ip{a}{b}$ & shorthand name \\\hline
\verb|\outerproduct| & \verb|\dyad{a}{b}| $\rightarrow \dyad{a}{b}$ & two-argument dyad \\
& \verb|\dyad{a}| $\rightarrow \dyad{a}$ & one-argument (projector) \\
& \verb|\dyad{a}{\tall}| $\rightarrow \dyad{a}{\tall}$ & automatic sizing \\
& \verb|\dyad*{a}{\tall}| $\rightarrow \dyad*{a}{\tall}$ & no resize \\
& \verb|\ketbra{a}{b}| $\rightarrow \ketbra{a}{b}$ & alternative name \\
-& \verb|\op{a}{b}| $\rightarrow \op{a}{b}$ & shorthand name \\
+& \verb|\op{a}{b}| $\rightarrow \op{a}{b}$ & shorthand name \\\hline
\verb|\expectationvalue| & \verb|\expval{A}| $\rightarrow \expval{A}$ & implicit form \\
& \verb|\expval{A}{\Psi}| $\rightarrow \expval{A}{\Psi}$ & explicit form \\
& \verb|\ev{A}{\Psi}| $\rightarrow \ev{A}{\Psi}$ & shorthand name \\
& \verb|\ev{\grande}{\Psi}| $\rightarrow \ev{\grande}{\Psi}$ & default sizing ignores middle argument \\
& \verb|\ev*{\grande}{\tall}| $\rightarrow \ev*{\grande}{\tall}$ & single star does no resizing whatsoever \\
-& \verb|\ev**{\grande}{\Psi}| $\rightarrow \ev**{\grande}{\Psi}$ & double star resizes based on all parts \\
+& \verb|\ev**{\grande}{\Psi}| $\rightarrow \ev**{\grande}{\Psi}$ & double star resizes based on all parts \\\hline
\verb|\matrixelement| & \verb|\matrixel{n}{A}{m}| $\rightarrow \matrixel{n}{A}{m}$ & requires all three arguments \\
& \verb|\mel{n}{A}{m}| $\rightarrow \mel{n}{A}{m}$ & shorthand name \\
& \verb|\mel{n}{\grande}{m}| $\rightarrow \mel{n}{\grande}{m}$ & default sizing ignores middle argument \\
& \verb|\mel*{n}{\grande}{\tall}| $\rightarrow \mel*{n}{\grande}{\tall}$ & single star does no resizing whatsoever \\
-& \verb|\mel**{n}{\grande}{m}| $\rightarrow \mel**{n}{\grande}{m}$ & double star resizes based on all parts
+& \verb|\mel**{n}{\grande}{m}| $\rightarrow \mel**{n}{\grande}{m}$ & double star resizes based on all parts \\\hline
\end{longtable}
\subsection{Matrix macros}
-{\fontsize{4pt}{6pt}\selectfont
Note: \verb|\mqty| and \verb|\smqty| in \texttt{physics} uses \verb|\mathord|, while \verb|\PTmqty| and \verb|\PTsmqty| in \texttt{physics-patch} don't.\\\\
-The following matrix macros produce unformatted rows and columns of matrix elements for use as separate matrices as well as blocks within larger matrices. For example, the command \verb|\identitymatrix{2}| which has also has the shortcut \verb|\imat{2}| produces the elements of a $2 \times 2$ identity matrix $\PTsmqty{\imat{2}}$ without braces or grouping. This allows the command to also be used within another matrix, as in:
+The following matrix macros produce unformatted rows and columns of matrix elements for use as separate matrices as well as blocks within larger matrices. For example, the command \verb|\identitymatrix{2}| which has also has the shortcut \verb|\imat{2}| produces the elements of a $2 \times 2$ identity matrix $\PTsmqty{\imat{2}}$ without braces or grouping. This allows the command to also be used within another matrix, as in:\\
\begin{minipage}{3cm}
\begin{lstlisting}[language=TeX]
\begin{pmatrix}
@@ -330,7 +338,7 @@ The following matrix macros produce unformatted rows and columns of matrix eleme
\end{pmatrix}
\end{displaymath}
\end{minipage}
-To specify elements on the right of left sides of our \verb|\imat{2}| sub-matrix we use the grouping command \verb|\PTmatrixquantity| or \verb|\PTmqty| to effectively convert \verb|\imat{2}| into a single matrix element of a larger matrix:
+To specify elements on the right of left sides of our \verb|\imat{2}| sub-matrix we use the grouping command \verb|\PTmatrixquantity| or \verb|\PTmqty| to effectively convert \verb|\imat{2}| into a single matrix element of a larger matrix:\\
\begin{minipage}{9cm}
\begin{lstlisting}[language=TeX]
\begin{pmatrix}
@@ -346,7 +354,7 @@ To specify elements on the right of left sides of our \verb|\imat{2}| sub-matrix
\end{pmatrix}
\end{displaymath}
\end{minipage}
-The extra \verb|\PTmqty| groups were required in this case in order to get the $a$ and $b$ elements to behave as a single element, since \verb|\PTmqty{\imat{2}}| also acts like a single matrix element (the same can be said of the grouped $c$ and $d$ elements). Finally, the outermost \texttt{pmatrix} environment could have also been replaced with the \texttt{physics-patch} macro \verb|\PTmqty()|, allowing the above example to be written on one line:
+The extra \verb|\PTmqty| groups were required in this case in order to get the $a$ and $b$ elements to behave as a single element, since \verb|\PTmqty{\imat{2}}| also acts like a single matrix element (the same can be said of the grouped $c$ and $d$ elements). Finally, the outermost \texttt{pmatrix} environment could have also been replaced with the \texttt{physics-patch} macro \verb|\PTmqty()|, allowing the above example to be written on one line:\\
\begin{minipage}{9cm}
\begin{lstlisting}[language=TeX]
\PTmqty(\PTmqty{\imat{2}} & \PTmqty{a\\b} \\ \PTmqty{c & d} & e)
@@ -358,7 +366,9 @@ The extra \verb|\PTmqty| groups were required in this case in order to get the $
\PTmqty(\PTmqty{\imat{2}} & \PTmqty{a\\b} \\ \PTmqty{c & d} & e)
\end{displaymath}
\end{minipage}
-\begin{longtable}[l]{ p{6cm} l p{6cm} l p{6cm} }
+{\fontsize{8pt}{12pt}\selectfont\\
+\begin{longtable}[l]{ | p{6cm} | p{6cm} | p{6cm} | }
+\hline
\verb|\PTmatrixquantity| & \verb|\PTmqty{a & b \\ c & d}| $\rightarrow \PTmqty{a & b \\ c & d}$ & groups a set of matrix elements into a single object \\
& \verb|\PTmqty(a & b \\ c & d)| $\rightarrow {\PTmqty(a & b \\ c & d)}$ & parentheses \\
& \verb|\PTmqty*(a & b \\ c & d)| $\rightarrow {\PTmqty*(a & b \\ c & d)}$ & alternate parentheses \\
@@ -370,16 +380,16 @@ The extra \verb|\PTmqty| groups were required in this case in order to get the $
& \verb|\PTpmqty*{}| $\leftrightarrow$ \verb|\PTmqty*{}| & \\
& \verb|\Pmqty{}| $\leftrightarrow$ \verb|\PTmqty*()| & \\
& \verb|\bmqty{}| $\leftrightarrow$ \verb|\PTmqty[]| & \\
-& \verb|\vmqty{}| $\leftrightarrow$ \verb+\PTmqty||+ & \\
+& \verb|\vmqty{}| $\leftrightarrow$ \verb+\PTmqty||+ & \\\hline
\verb|\PTsmallmatrixquantity| & \verb|\PTsmqty{a & b \\ c & d}| $\rightarrow \PTsmqty{a & b \\ c & d}$ & the \texttt{smallmatrix} form of \verb|\PTmqty| \\
& \verb|\PTsmqty()| \qor \verb|\spmqty{}| \qor \verb|\PTspmqty{}| & small version of \verb|\PTmqty()| \\
& \verb|\PTsmqty*()| \qor \verb|\sPmqty{}| \qor \verb|\PTspmqty*{}| & small version of \verb|\PTmqty*()|\\
& \verb|\PTsmqty[]| \qor \verb|\sbmqty{}| & small version of \verb|\PTmqty[]| \\
-& \verb+\PTsmqty||+ \qor \verb|\svmqty{}| & small version of \verb+\PTmqty||+ \\
+& \verb+\PTsmqty||+ \qor \verb|\svmqty{}| & small version of \verb+\PTmqty||+ \\\hline
\verb|\matrixdeterminant| & \verb|\mdet{a & b \\ c & d}| $\rightarrow {\mdet{a & b \\ c & d}}$ & matrix determinant \\
-& \verb|\smdet{a & b \\ c & d}| $\rightarrow {\smdet{a & b \\ c & d}}$ & small matrix determinant \\
+& \verb|\smdet{a & b \\ c & d}| $\rightarrow {\smdet{a & b \\ c & d}}$ & small matrix determinant \\\hline
\verb|\identitymatrix| & \verb|\imat{n}| & elements of $n \times n$ identity matrix \\
-& \verb|\PTmqty(\imat{3})| $\rightarrow \PTmqty(\imat{3})$ & formatted with \verb|\PTmqty| or \verb|\PTsmqty| \\
+& \verb|\PTmqty(\imat{3})| $\rightarrow \PTmqty(\imat{3})$ & formatted with \verb|\PTmqty| or \verb|\PTsmqty| \\\hline
\verb|\PTxmatrix| & \verb|\PTxmat{x}{n}{m}| & \multirow{4}{*}{\parbox{6cm}{elements of $n \times m$ matrix filled with $x$, if not provided, $1$ is used}} \\
& \verb|\PTmqty(\PTxmat{x}{3}{3})| $\rightarrow \PTmqty(\PTxmat{x}{3}{3})$ & \\
& \verb|\PTmqty(\PTxmat{x}{}{3})| $\rightarrow \PTmqty(\PTxmat{x}{}{3})$ & \\
@@ -407,54 +417,76 @@ The extra \verb|\PTmqty| groups were required in this case in order to get the $
& \verb|\PTxmat[0 or 1 or 2]{x}{n}{m}[p][q]| & \multirow{4}{*}{\parbox{6cm}{Change the \texttt{\textbackslash vdots} row/\texttt{\textbackslash ldots} column from the second last one to last one, 0 for both, 1 for row only, 2 for column only. Only work when corresponding $p$/$q$ is provided and do not change the behavior of element indices}} \\
& \verb|\PTmqty(\PTxmat[0]{x}{5}{5}[3][3])| $\rightarrow \PTmqty(\PTxmat[0]{x}{5}{5}[3][3])$ & \\
& \verb|\PTmqty(\PTxmat[1]{x}{5}{5}[3][3])| $\rightarrow \PTmqty(\PTxmat[1]{x}{5}{5}[3][3])$ & \\
-& \verb|\PTmqty(\PTxmat[2]{x}{5}{5}[3][3])| $\rightarrow \PTmqty(\PTxmat[2]{x}{5}{5}[3][3])$ & \\
+& \verb|\PTmqty(\PTxmat[2]{x}{5}{5}[3][3])| $\rightarrow \PTmqty(\PTxmat[2]{x}{5}{5}[3][3])$ & \\\hline
\verb|\zeromatrix| & \verb|\zmat{n}{m}| & \multirow{3}{*}{\parbox{6cm}{$n \times m$ matrix filled with zeros, equivalent to \texttt{\textbackslash xmat\{0\}\{n\}\{m\}}. If $m$ isn't provided, $n$ is used}} \\
& \verb|\PTmqty(\zmat{2}{2})| $\rightarrow \PTmqty(\zmat{2}{2})$ & \\
-& \verb|\PTmqty(\zmat{2})| $\rightarrow \PTmqty(\zmat{2})$ & \\
+& \verb|\PTmqty(\zmat{2})| $\rightarrow \PTmqty(\zmat{2})$ & \\\hline
\verb|\paulimatrix| & \verb|\pmat{n}| & $n^\text{th}$ Pauli matrix \\
& \verb|\PTmqty(\pmat{0})| $\rightarrow \PTmqty(\pmat{0})$ & $n\in \lbrace 0,1,2,3$ or $x,y,z \rbrace$ \\
& \verb|\PTmqty(\pmat{1})| $\rightarrow \PTmqty(\pmat{1})$ & \\
& \verb|\PTmqty(\pmat{2})| $\rightarrow \PTmqty(\pmat{2})$ & \\
-& \verb|\PTmqty(\pmat{3})| $\rightarrow \PTmqty(\pmat{3})$ & \\
+& \verb|\PTmqty(\pmat{3})| $\rightarrow \PTmqty(\pmat{3})$ & \\\hline
\verb|\diagonalmatrix| & \verb|\dmat{a,b,c,...}| & \multirow{2}{*}{\parbox{6cm}{specify up to eight diagonal or block diagonal elements}} \\
& \verb|\PTmqty(\dmat{1,2,3})| $\rightarrow \PTmqty(\dmat{1,2,3})$ & \\
& \verb|\PTmqty(\dmat[0]{1,2})| $\rightarrow \PTmqty(\dmat[0]{1,2})$ & optional argument to fill spaces \\
-& \verb|\PTmqty(\dmat{1,2&3\\4&5})| $\rightarrow \PTmqty(\dmat{1,2&3\\4&5})$ & enter matrix elements for each block as a single diagonal element \\
+& \verb|\PTmqty(\dmat{1,2&3\\4&5})| $\rightarrow \PTmqty(\dmat{1,2&3\\4&5})$ & enter matrix elements for each block as a single diagonal element \\\hline
\verb|\antidiagonalmatrix| & \verb|\admat{a,b,c,...}| & same as syntax as \verb|\dmat| \\
-& \verb|\PTmqty(\admat{1,2,3})| $\rightarrow \PTmqty(\admat{1,2,3})$ & \\
+& \verb|\PTmqty(\admat{1,2,3})| $\rightarrow \PTmqty(\admat{1,2,3})$ & \\\hline
\end{longtable}
+}
\subsection{Symbols}
-\begin{longtable}[l]{ p{0.5\textwidth} l p{0.5\textwidth} }
-\verb|\lparen| $\rightarrow ($ &\\
-\verb|\rparen| $\rightarrow )$ &\\
-\verb|\ordersymbol| $\rightarrow \ordersymbol$ & \\
-\verb|\typical| $\rightarrow \typical$ & \\
-\verb|\tall| $\rightarrow \tall$ & \\
-\verb|\grande| $\rightarrow \grande$ & \\
-\verb|\venti| $\rightarrow \venti$ & \\
-\verb|\Vtextvisiblespace[width]| $\rightarrow$ \Vtextvisiblespace & a visible space character, where the optional argument (defaulting to \texttt{.3em}) sets the width of the horizontal rule
+\begin{center}\begin{tabular}{ | p{6cm} | p{6cm} | }
+\hline
+\verb|\lparen| $\rightarrow\; ($ &\\\hline
+\verb|\rparen| $\rightarrow\; )$ &\\\hline
+\verb|\ordersymbol| $\rightarrow \ordersymbol$ & \\\hline
+\verb|\typical| $\rightarrow \typical$ & \\\hline
+\verb|\tall| $\rightarrow \tall$ & \\\hline
+\verb|\grande| $\rightarrow \grande$ & \\\hline
+\verb|\venti| $\rightarrow \venti$ & \\\hline
+\verb|\calE|$\rightarrow$\verb|\mathcal{E}| & \\\hline
+\verb|\bbR|$\rightarrow$\verb|\mathbb{R}| & \\\hline
+\verb|\bbC|$\rightarrow$\verb|\mathbb{C}| & \\\hline
+\verb|\bbQ|$\rightarrow$\verb|\mathbb{Q}| & \\\hline
+\verb|\bbN|$\rightarrow$\verb|\mathbb{N}| & \\\hline
+\verb|\bbZ|$\rightarrow$\verb|\mathbb{Z}| & \\\hline
+\verb|\Vtextvisiblespace[width]| $\rightarrow$ \Vtextvisiblespace & \parbox{6cm}{a visible space character, where the optional argument, defaulting to \texttt{.3em}, sets the width of the horizontal rule}\\\hline
+\end{tabular}\end{center}
+\subsection{Shorthands for Greek alphabet}
+If option \texttt{shortgreek} is used, the following shorthands will be defined for every uppercase and lowercase Greek letter:\\
+\begin{center}\begin{tabular}{ | p{6cm} | p{10cm} | }
+\hline
+\verb|\tgAlpha| $\rightarrow$ \verb|\text{\textAlpha}}| & accept an optional argument argument in \texttt{\{\}} that is simply skipped \\\hline
+\verb|\vAlpha| $\rightarrow$ \verb|\varAlpha| & \\\hline
+\verb|\uAlpha| $\rightarrow$ \verb|\upAlpha| & \\\hline
+\verb|\uvAlpha| $\rightarrow$ \verb|\upvarAlpha| & \\\hline
+\end{tabular}\end{center}
+Note that these don’t ensure those commands are defined.
+\subsection{Shorthands for mathrm alphabet and chemical element symbols}
+If option \texttt{shortmathrm} is used, the following shorthands will be defined for every uppercase and lowercase English letter and every chemical element symbols (\verb|A\verb| for example):\\
+\begin{longtable}[l]{ | p{6cm} | p{6cm} | }
+\hline
+\verb|\rmA_a^b| $\rightarrow\mathrm{A}_a^b$ & work in both math mode and text mode
+\\\hline
\end{longtable}
-}
-\subsection{Shorthands for Greek letters}
-If option \texttt{shortgreek} is used, the following shorthands will be defined for every Greeks letter:
+which are implemented with:
\begin{lstlisting}[language=TeX]
-\DeclareDocumentCommand{\tgAlpha}{O{}}{\text{\textAlpha}}
-\DeclareDocumentCommand{\tgalpha}{O{}}{\text{\textalpha}}
-\DeclareDocumentCommand{\vAlpha}{}{\varAlpha}
-\DeclareDocumentCommand{\valpha}{}{\varalpha}
-\DeclareDocumentCommand{\uAlpha}{}{\upAlpha}
-\DeclareDocumentCommand{\ualpha}{}{\upalpha}
-\DeclareDocumentCommand{\uvAlpha}{}{\upvarAlpha}
-\DeclareDocumentCommand{\uvalpha}{}{\upvaralpha}
+\DeclareDocumentCommand{\rmA}{e{_^}}{\ensuremath{\mathrm{A}\IfValueTF{#1}{_{#1}}{}\IfValueTF{#2}{^{#2}}{}}}
\end{lstlisting}
+\subsection{Shorthands for textnormal alphabet}
+If option \texttt{shorttext} is used, the following shorthands will be defined for every uppercase and lowercase English letter (\verb|A\verb| for example):\\
+\begin{longtable}{| l |}
+\hline
+\verb|\txA| $\rightarrow$ \verb|\textnormal{A}|
+\\\hline
+\end{longtable}
\subsection{Others}
-\begin{longtable}[l]{ p{6cm} l p{6cm} l p{6cm} }
-\verb|\autommode| & \verb|\amm{content}| & \verb|\relax\ifmmode #1\else\(#1\)\fi| \\
+\begin{longtable}[l]{ | p{6cm} | p{6cm} | p{6cm} | }
+\hline
\verb|\mathcolorbox| & \verb|\mcbox{color}{content}| & \multirow{2}{*}{\parbox{6cm}{\texttt{\textbackslash colorbox} for math environment, applying to all four levels of math styles}} \\
-& \verb|\mcbox{cyan}{\phantom{A}}| $\rightarrow \mcbox{cyan}{\phantom{A}}$ & \\
-\verb|\autocolorbox| or \verb|\acbox| & \verb|\cbox{color}{content}| & samw as \verb|\colorbox| in text environment, same as \verb|\mathcolorbox| in math environment \\
-\verb|\tentothepowerof| & \verb|\tenpow{n}| $\rightarrow \tenpow{n}$ & work in both math mode and text mode \\
-\verb|\scientificnotation| & \verb|\scinote{3.00}{8}| $\rightarrow \scinote{3.00}{8}$ & \parbox{6cm}{work in both math mode and text mode}
+& \verb|\mcbox{cyan}{\phantom{A}}| $\rightarrow \mcbox{cyan}{\phantom{A}}$ & \\\hline
+\verb|\autocolorbox| or \verb|\acbox| & \verb|\cbox{color}{content}| & calls \verb|\colorbox| when in text mode, calls \verb|\mathcolorbox| when in math mode \\\hline
+\verb|\tentothepowerof| & \verb|\tenpow{n}| $\rightarrow \tenpow{n}$ & work in both math mode and text mode \\\hline
+\verb|\scientificnotation| & \verb|\scinote{3.00}{8}| $\rightarrow \scinote{3.00}{8}$ & work in both math mode and text mode\\\hline
\end{longtable}
-}
\end{document} \ No newline at end of file
diff --git a/macros/latex/contrib/tagpdf/README.md b/macros/latex/contrib/tagpdf/README.md
index 4c2bddb040..c834fc7919 100644
--- a/macros/latex/contrib/tagpdf/README.md
+++ b/macros/latex/contrib/tagpdf/README.md
@@ -1,6 +1,6 @@
#tagpdf — A package to create tagged pdf
-Packageversion: 0.99l
-Packagedate: 2025/01/12
+Packageversion: 0.99m
+Packagedate: 2025/02/17
Author: Ulrike Fischer, LaTeX Project Team
## License
diff --git a/macros/latex/contrib/tagpdf/ex-AF-file.pdf b/macros/latex/contrib/tagpdf/ex-AF-file.pdf
index 80b24fb71b..0740fc01f9 100644
--- a/macros/latex/contrib/tagpdf/ex-AF-file.pdf
+++ b/macros/latex/contrib/tagpdf/ex-AF-file.pdf
@@ -1,11 +1,11 @@
%PDF-2.0
%
22 0 obj
-<< /Subtype /application#2Fx-tex/Type /EmbeddedFile /Params<</ModDate (D:20250112182121+01'00') /Size 151 /CheckSum (BF5402FD538201DDD048C93921EE42AE) >> /Length 151 >>
+<< /Subtype /application#2Fx-tex/Type /EmbeddedFile /Params<</ModDate (D:20250217201814+01'00') /Size 151 /CheckSum (972B520F640A86101C6290D75A35D3ED) >> /Length 151 >>
stream
%% LaTeX2e file `example-input-file.tex'
%% generated by the `filecontents' environment
-%% from source `ex-AF-file' on 2025/01/12.
+%% from source `ex-AF-file' on 2025/02/17.
%%
Additional info!
@@ -15,7 +15,7 @@ endobj
<< /Type /Filespec /AFRelationship /Unspecified /F (example-input-file.tex) /UF <FEFF006500780061006D0070006C0065002D0069006E007000750074002D00660069006C0065002E007400650078> /EF<</F 22 0 R/UF 22 0 R>> >>
endobj
25 0 obj
-<< /Subtype /text#2Fplain/Type /EmbeddedFile /Params<</ModDate (D:20250112) >> /Length 19 >>
+<< /Subtype /text#2Fplain/Type /EmbeddedFile /Params<</ModDate (D:20250217) >> /Length 19 >>
stream
Bär with teh shirt
endstream
@@ -24,7 +24,7 @@ endobj
<< /Type /Filespec /AFRelationship /Supplement /F (tag-AFfile1.txt) /UF <FEFF007400610067002D0041004600660069006C00650031002E007400780074> /EF<</F 25 0 R/UF 25 0 R>> >>
endobj
28 0 obj
-<< /Subtype /text#2Fplain/Type /EmbeddedFile /Params<</ModDate (D:20250112) >> /Length 4 >>
+<< /Subtype /text#2Fplain/Type /EmbeddedFile /Params<</ModDate (D:20250217) >> /Length 4 >>
stream
Duck
endstream
@@ -248,17 +248,17 @@ stream
</dc:language>
<dc:date>
<rdf:Seq>
- <rdf:li>2025-01-12T18:21:42+01:00</rdf:li>
+ <rdf:li>2025-02-17T20:18:35+01:00</rdf:li>
</rdf:Seq>
</dc:date>
<dc:format>application/pdf</dc:format>
<dc:source>ex-AF-file.tex</dc:source>
<xmp:CreatorTool>LaTeX</xmp:CreatorTool>
- <xmp:CreateDate>2025-01-12T18:21:42+01:00</xmp:CreateDate>
- <xmp:ModifyDate>2025-01-12T18:21:42+01:00</xmp:ModifyDate>
- <xmp:MetadataDate>2025-01-12T18:21:42+01:00</xmp:MetadataDate>
+ <xmp:CreateDate>2025-02-17T20:18:35+01:00</xmp:CreateDate>
+ <xmp:ModifyDate>2025-02-17T20:18:35+01:00</xmp:ModifyDate>
+ <xmp:MetadataDate>2025-02-17T20:18:35+01:00</xmp:MetadataDate>
<xmpMM:DocumentID>uuid:38d5a844-2217-4081-87cc-b2129dc357a6</xmpMM:DocumentID>
- <xmpMM:InstanceID>uuid:c704519b-1d71-488d-8e72-0839311ad892</xmpMM:InstanceID>
+ <xmpMM:InstanceID>uuid:a5f7791b-e51c-40f7-8294-a7dff11efa37</xmpMM:InstanceID>
<prism:complianceProfile>three</prism:complianceProfile>
<prism:pageCount>1</prism:pageCount>
</rdf:Description>
@@ -353,7 +353,7 @@ endobj
<< /Type /Namespace /NS (https://www.latex-project.org/ns/book) /RoleMapNS 18 0 R >>
endobj
19 0 obj
-<< /Type /Namespace /NS (data:,C51A65F5-9FB6-A72F-250-B661B5B92D79) >>
+<< /Type /Namespace /NS (data:,9950B78E-BF3A-47B4-2224-15383D8E28B4) >>
endobj
8 0 obj
[ 9 0 R 11 0 R 13 0 R 15 0 R 17 0 R 19 0 R ]
@@ -455,7 +455,7 @@ endobj
<< /Type /Catalog /Pages 36 0 R /MarkInfo 37 0 R/Lang (de-DE)/Metadata 31 0 R/StructTreeRoot 5 0 R >>
endobj
46 0 obj
-<< /Producer (luahbtex-1.18.0)/Creator (LaTeX)/CreationDate (D:20250112182142+01'00')/ModDate (D:20250112182142+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.18.0 (TeX Live 2024)) >>
+<< /Producer (luahbtex-1.18.0)/Creator (LaTeX)/CreationDate (D:20250217201835+01'00')/ModDate (D:20250217201835+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.18.0 (TeX Live 2024)) >>
endobj
xref
0 47
@@ -464,10 +464,10 @@ xref
0000000003 00000 f
0000000004 00000 f
0000000010 00000 f
-0000016682 00000 n
+0000016683 00000 n
0000013958 00000 n
0000014169 00000 n
-0000016112 00000 n
+0000016113 00000 n
0000014748 00000 n
0000000012 00000 f
0000014816 00000 n
@@ -480,34 +480,34 @@ xref
0000015751 00000 n
0000016024 00000 n
0000000000 00000 f
-0000016173 00000 n
+0000016174 00000 n
0000000020 00000 n
0000000382 00000 n
-0000016286 00000 n
+0000016287 00000 n
0000000603 00000 n
0000000758 00000 n
-0000016418 00000 n
+0000016419 00000 n
0000000943 00000 n
0000001083 00000 n
-0000016550 00000 n
+0000016551 00000 n
0000001268 00000 n
0000013812 00000 n
0000013677 00000 n
0000013071 00000 n
-0000020435 00000 n
-0000020789 00000 n
+0000020436 00000 n
+0000020790 00000 n
0000013922 00000 n
0000014015 00000 n
0000014132 00000 n
-0000016802 00000 n
-0000019251 00000 n
-0000016988 00000 n
-0000019472 00000 n
-0000020589 00000 n
-0000020851 00000 n
-0000020969 00000 n
+0000016803 00000 n
+0000019252 00000 n
+0000016989 00000 n
+0000019473 00000 n
+0000020590 00000 n
+0000020852 00000 n
+0000020970 00000 n
trailer
-<< /Size 47 /Root 45 0 R /Info 46 0 R /ID [ <067902BFB55BEFFA0B5AA4AB40EE0447> <067902BFB55BEFFA0B5AA4AB40EE0447> ] >>
+<< /Size 47 /Root 45 0 R /Info 46 0 R /ID [ <D3674883B7C1A7E22461441F41FB6250> <D3674883B7C1A7E22461441F41FB6250> ] >>
startxref
-21192
+21193
%%EOF
diff --git a/macros/latex/contrib/tagpdf/ex-alt-actualtext.pdf b/macros/latex/contrib/tagpdf/ex-alt-actualtext.pdf
index fe54ebccb5..a9363d1800 100644
--- a/macros/latex/contrib/tagpdf/ex-alt-actualtext.pdf
+++ b/macros/latex/contrib/tagpdf/ex-alt-actualtext.pdf
Binary files differ
diff --git a/macros/latex/contrib/tagpdf/ex-attribute.pdf b/macros/latex/contrib/tagpdf/ex-attribute.pdf
index 8cfbdabd8f..32bc30ef37 100644
--- a/macros/latex/contrib/tagpdf/ex-attribute.pdf
+++ b/macros/latex/contrib/tagpdf/ex-attribute.pdf
@@ -222,17 +222,17 @@ stream
</dc:language>
<dc:date>
<rdf:Seq>
- <rdf:li>2025-01-12T18:22:40+01:00</rdf:li>
+ <rdf:li>2025-02-17T20:19:21+01:00</rdf:li>
</rdf:Seq>
</dc:date>
<dc:format>application/pdf</dc:format>
<dc:source>ex-attribute.tex</dc:source>
<xmp:CreatorTool>LaTeX</xmp:CreatorTool>
- <xmp:CreateDate>2025-01-12T18:22:40+01:00</xmp:CreateDate>
- <xmp:ModifyDate>2025-01-12T18:22:40+01:00</xmp:ModifyDate>
- <xmp:MetadataDate>2025-01-12T18:22:40+01:00</xmp:MetadataDate>
+ <xmp:CreateDate>2025-02-17T20:19:21+01:00</xmp:CreateDate>
+ <xmp:ModifyDate>2025-02-17T20:19:21+01:00</xmp:ModifyDate>
+ <xmp:MetadataDate>2025-02-17T20:19:21+01:00</xmp:MetadataDate>
<xmpMM:DocumentID>uuid:7a9cf910-1c19-429a-8f24-339c62d8a57f</xmpMM:DocumentID>
- <xmpMM:InstanceID>uuid:aa445eab-ae6a-4460-8f00-8df1815e6415</xmpMM:InstanceID>
+ <xmpMM:InstanceID>uuid:6fe7e93e-595c-428c-86f7-60f2634e9888</xmpMM:InstanceID>
<prism:complianceProfile>three</prism:complianceProfile>
<prism:pageCount>1</prism:pageCount>
</rdf:Description>
@@ -456,7 +456,7 @@ endobj
<< /Type /Catalog /Pages 26 0 R /MarkInfo 27 0 R/Lang (de_DE)/Metadata 21 0 R/StructTreeRoot 5 0 R >>
endobj
38 0 obj
-<< /Producer (luahbtex-1.18.0)/Creator (LaTeX)/Title (Title)/CreationDate (D:20250112182240+01'00')/ModDate (D:20250112182240+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.18.0 (TeX Live 2024)) >>
+<< /Producer (luahbtex-1.18.0)/Creator (LaTeX)/Title (Title)/CreationDate (D:20250217201921+01'00')/ModDate (D:20250217201921+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.18.0 (TeX Live 2024)) >>
endobj
xref
0 39
@@ -500,7 +500,7 @@ xref
0000018052 00000 n
0000018170 00000 n
trailer
-<< /Size 39 /Root 37 0 R /Info 38 0 R /ID [ <E4503C91BF19E889D52ED5C8EB202035> <E4503C91BF19E889D52ED5C8EB202035> ] >>
+<< /Size 39 /Root 37 0 R /Info 38 0 R /ID [ <CF27CC40ED8D0A7710EF729F276E25BC> <CF27CC40ED8D0A7710EF729F276E25BC> ] >>
startxref
18407
%%EOF
diff --git a/macros/latex/contrib/tagpdf/ex-formula-problem.pdf b/macros/latex/contrib/tagpdf/ex-formula-problem.pdf
index e4f80ad687..7af4543048 100644
--- a/macros/latex/contrib/tagpdf/ex-formula-problem.pdf
+++ b/macros/latex/contrib/tagpdf/ex-formula-problem.pdf
@@ -245,17 +245,17 @@ stream
</dc:language>
<dc:date>
<rdf:Seq>
- <rdf:li>2025-01-12T18:23:12+01:00</rdf:li>
+ <rdf:li>2025-02-17T20:19:44+01:00</rdf:li>
</rdf:Seq>
</dc:date>
<dc:format>application/pdf</dc:format>
<dc:source>ex-formula-problem.tex</dc:source>
<xmp:CreatorTool>LaTeX</xmp:CreatorTool>
- <xmp:CreateDate>2025-01-12T18:23:12+01:00</xmp:CreateDate>
- <xmp:ModifyDate>2025-01-12T18:23:12+01:00</xmp:ModifyDate>
- <xmp:MetadataDate>2025-01-12T18:23:12+01:00</xmp:MetadataDate>
+ <xmp:CreateDate>2025-02-17T20:19:44+01:00</xmp:CreateDate>
+ <xmp:ModifyDate>2025-02-17T20:19:44+01:00</xmp:ModifyDate>
+ <xmp:MetadataDate>2025-02-17T20:19:44+01:00</xmp:MetadataDate>
<xmpMM:DocumentID>uuid:8eb2ce1d-b2ec-440a-8bc2-73733eb3eeb0</xmpMM:DocumentID>
- <xmpMM:InstanceID>uuid:1cfcaf2c-9f45-4a71-899a-acd29928c27b</xmpMM:InstanceID>
+ <xmpMM:InstanceID>uuid:5985782d-da43-4c24-824d-067a5d0becd9</xmpMM:InstanceID>
<prism:complianceProfile>three</prism:complianceProfile>
<prism:pageCount>2</prism:pageCount>
</rdf:Description>
@@ -431,7 +431,7 @@ endobj
<< /Type /Catalog /Pages 16 0 R /MarkInfo 23 0 R/Lang (de-DE)/Metadata 19 0 R/StructTreeRoot 5 0 R >>
endobj
33 0 obj
-<< /Producer (luahbtex-1.18.0)/Creator (LaTeX)/CreationDate (D:20250112182312+01'00')/ModDate (D:20250112182312+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.18.0 (TeX Live 2024)) >>
+<< /Producer (luahbtex-1.18.0)/Creator (LaTeX)/CreationDate (D:20250217201944+01'00')/ModDate (D:20250217201944+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.18.0 (TeX Live 2024)) >>
endobj
xref
0 34
@@ -470,7 +470,7 @@ xref
0000019217 00000 n
0000019335 00000 n
trailer
-<< /Size 34 /Root 32 0 R /Info 33 0 R /ID [ <A13639F642E641BFB6F68A6A6C666F1A> <A13639F642E641BFB6F68A6A6C666F1A> ] >>
+<< /Size 34 /Root 32 0 R /Info 33 0 R /ID [ <65FB02FCFE0E082DC8BD8B306BCF5F6C> <65FB02FCFE0E082DC8BD8B306BCF5F6C> ] >>
startxref
19558
%%EOF
diff --git a/macros/latex/contrib/tagpdf/ex-list.pdf b/macros/latex/contrib/tagpdf/ex-list.pdf
index f9408e7f92..a31a500332 100644
--- a/macros/latex/contrib/tagpdf/ex-list.pdf
+++ b/macros/latex/contrib/tagpdf/ex-list.pdf
@@ -216,17 +216,17 @@ stream
</dc:language>
<dc:date>
<rdf:Seq>
- <rdf:li>2025-01-12T18:23:45+01:00</rdf:li>
+ <rdf:li>2025-02-17T20:20:08+01:00</rdf:li>
</rdf:Seq>
</dc:date>
<dc:format>application/pdf</dc:format>
<dc:source>ex-list.tex</dc:source>
<xmp:CreatorTool>LaTeX</xmp:CreatorTool>
- <xmp:CreateDate>2025-01-12T18:23:45+01:00</xmp:CreateDate>
- <xmp:ModifyDate>2025-01-12T18:23:45+01:00</xmp:ModifyDate>
- <xmp:MetadataDate>2025-01-12T18:23:45+01:00</xmp:MetadataDate>
+ <xmp:CreateDate>2025-02-17T20:20:08+01:00</xmp:CreateDate>
+ <xmp:ModifyDate>2025-02-17T20:20:08+01:00</xmp:ModifyDate>
+ <xmp:MetadataDate>2025-02-17T20:20:08+01:00</xmp:MetadataDate>
<xmpMM:DocumentID>uuid:4c749825-1de7-414c-879f-29e4d0bef66e</xmpMM:DocumentID>
- <xmpMM:InstanceID>uuid:1a9213e6-6347-4690-84d8-1b6ae5002b4e</xmpMM:InstanceID>
+ <xmpMM:InstanceID>uuid:ff72a2a1-7f84-4f40-86ef-1adc9fac6b89</xmpMM:InstanceID>
<prism:complianceProfile>three</prism:complianceProfile>
<prism:pageCount>1</prism:pageCount>
</rdf:Description>
@@ -660,7 +660,7 @@ endobj
<< /Type /Catalog /Pages 54 0 R /MarkInfo 55 0 R/Lang (en)/Metadata 48 0 R/StructTreeRoot 5 0 R >>
endobj
72 0 obj
-<< /Producer (luahbtex-1.18.0)/Creator (LaTeX)/CreationDate (D:20250112182345+01'00')/ModDate (D:20250112182345+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.18.0 (TeX Live 2024)) >>
+<< /Producer (luahbtex-1.18.0)/Creator (LaTeX)/CreationDate (D:20250217202008+01'00')/ModDate (D:20250217202008+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.18.0 (TeX Live 2024)) >>
endobj
xref
0 73
@@ -738,7 +738,7 @@ xref
0000029921 00000 n
0000030036 00000 n
trailer
-<< /Size 73 /Root 71 0 R /Info 72 0 R /ID [ <892CE49A431B9D4130359B1AEE1C46D7> <892CE49A431B9D4130359B1AEE1C46D7> ] >>
+<< /Size 73 /Root 71 0 R /Info 72 0 R /ID [ <EDCD107F3303A8C9F277133249DC5EDC> <EDCD107F3303A8C9F277133249DC5EDC> ] >>
startxref
30259
%%EOF
diff --git a/macros/latex/contrib/tagpdf/ex-mc-manual-para-split-obsolete.pdf b/macros/latex/contrib/tagpdf/ex-mc-manual-para-split-obsolete.pdf
index 198b559a6a..b76ed20222 100644
--- a/macros/latex/contrib/tagpdf/ex-mc-manual-para-split-obsolete.pdf
+++ b/macros/latex/contrib/tagpdf/ex-mc-manual-para-split-obsolete.pdf
@@ -1,16 +1,20 @@
%PDF-1.7
%
-12 0 obj
-<< /Length 2896 >>
+11 0 obj
+<< /Length 3038 >>
stream
/opacity1 gs
/Artifact BMC
+EMC
+/Artifact BMC
q
1 0 0 1 106.869 685.928 cm
[] 0 d 0 J 0.398 w 0 0 m 343.711 0 l S
Q
EMC
-/P <</MCID 0 >> BDC
+/Artifact BMC
+EMC
+/P<</MCID 0>> BDC
BT
/F15 9.96264 Tf
1 0 0 1 121.813 658.164 Tm [<002A0060001C0062>-415<0032003B003200620069001C0062>-415<004200540062006D004B>-416<001C>-415<004D0042006200480058>-416<006F00420070>55<001C004B>28<006D0062>-414<0070>55<001C00600042006D0062>-414<002F0051004800510060>-416<006D0069>-415<002F00510048005100600058>-416<0036>82<006D0062002B0032>-414<0070>27<00320048>-415<0032004D0042004B0058>]TJ
@@ -19,21 +23,31 @@ BT
1 0 0 1 106.869 622.299 Tm [<0054>-28<0032004D001C006900420023006D0062>-394<00320069>-394<004B001C003B004D00420062>-395<002F00420062>-394<0054001C00600069006D006000420032004D>27<0069>-393<004B0051004D>27<006900320062002D>-394<004D001C0062002B00320069006D0060>-394<00600042002F0042002B006D0048006D0062>-394<004B>27<006D00620058>-394<0041004D>27<00690032003B00320060>-394<001C0069>]TJ
1 0 0 1 106.869 610.344 Tm [<0069006D00600054004200620058>-288<002A006D004B>-289<00620051>-28<002B004200420062>-288<004D001C00690051>-28<005B006D0032>-289<0054>-28<0032004D001C006900420023006D0062>-288<00320069>-289<004B001C003B004D00420062>-288<002F00420062>-289<0054001C00600069006D006000420032004D>28<0069>-288<004B0051004D>27<006900320062002D>-288<004D001C0062002B00320069006D0060>]TJ
1 0 0 1 106.869 598.389 Tm [<00600042002F0042002B006D0048006D0062>-279<004B>27<006D00620058>-278<002E006D00420062>-280<003700600042004D003B004200480048001C002D>-279<00480042003B006D0048001C>-279<00620032002F>-279<0054>-28<005100600069001C>-280<003700600042004D003B004200480048001C002D>-279<00480042003B006D0048001C>-279<0072004200620042>-279<002B0051004B004B0051>-28<002F0051>-280<00370032004800420062002D>]TJ
-1 0 0 1 106.869 586.433 Tm [<006D0069>-249<001C002F0042005400420062002B0042004D003B>-249<00370032004800420062>-249<002F006D0042>-249<0042004D>-249<0032004D0042004B0058>-249<0061006D00620054>-28<0032004D002F0042006200620032>-249<004B001C004800320062006D001C002F001C>-249<006D0048006900600042002B00320062>-249<001C004D>27<006900320058>-249<0053>28<0032004800480032004D>28<006900320062005B006D0032>]TJ
+1 0 0 1 106.869 586.433 Tm [<006D0069>-249<001C002F0042005400420062002B0042004D003B>-249<00370032004800420062>-249<002F006D0042>-249<0042004D>-249<0032004D0042004B0058>-249<0061006D00620054>-28<0032004D002F0042006200620032>-249<004B001C004800320062006D001C002F001C>-249<006D0048006900600042002B00320062>-249<001C004D>27<006900320058>]TJ
+ET
+EMC
+/P<</MCID 1>> BDC
+BT
+/F15 9.96264 Tf
+1 0 0 1 396.981 586.433 Tm [<0053>28<0032004800480032004D>28<006900320062005B006D0032>]TJ
ET
EMC
/Artifact BMC
EMC
+/Artifact BMC
+EMC
+/Artifact BMC
+EMC
endstream
endobj
-9 0 obj
-<< /Type /Page /Contents 12 0 R /Resources 11 0 R /MediaBox [ 0 0 612 792 ] /Tabs /S /Parent 14 0 R >>
+10 0 obj
+<< /Type /Page /Contents 11 0 R /Resources 9 0 R /MediaBox [ 0 0 612 792 ] /Tabs /S /Parent 13 0 R >>
endobj
-11 0 obj
-<< /ExtGState 1 0 R /Font << /F15 13 0 R >> /ProcSet [ /PDF /Text ] >>
+9 0 obj
+<< /ExtGState 1 0 R /Font << /F15 12 0 R >> /ProcSet [ /PDF /Text ] >>
endobj
-15 0 obj
+14 0 obj
<< /Type /Metadata /Subtype /XML /Length 11732 >>
stream
@@ -249,17 +263,17 @@ stream
</dc:language>
<dc:date>
<rdf:Seq>
- <rdf:li>2025-01-12T18:24:11+01:00</rdf:li>
+ <rdf:li>2025-02-17T20:20:30+01:00</rdf:li>
</rdf:Seq>
</dc:date>
<dc:format>application/pdf</dc:format>
<dc:source>ex-mc-manual-para-split-obsolete.tex</dc:source>
<xmp:CreatorTool>LaTeX</xmp:CreatorTool>
- <xmp:CreateDate>2025-01-12T18:24:11+01:00</xmp:CreateDate>
- <xmp:ModifyDate>2025-01-12T18:24:11+01:00</xmp:ModifyDate>
- <xmp:MetadataDate>2025-01-12T18:24:11+01:00</xmp:MetadataDate>
+ <xmp:CreateDate>2025-02-17T20:20:30+01:00</xmp:CreateDate>
+ <xmp:ModifyDate>2025-02-17T20:20:30+01:00</xmp:ModifyDate>
+ <xmp:MetadataDate>2025-02-17T20:20:30+01:00</xmp:MetadataDate>
<xmpMM:DocumentID>uuid:c33d64b4-96ec-4e48-8f27-0b3edc831547</xmpMM:DocumentID>
- <xmpMM:InstanceID>uuid:70e1c559-6419-4f4c-88f7-a96010263abf</xmpMM:InstanceID>
+ <xmpMM:InstanceID>uuid:2ab9a5b5-04eb-4481-8d77-b8c9a5896899</xmpMM:InstanceID>
<prism:complianceProfile>three</prism:complianceProfile>
<prism:pageCount>2</prism:pageCount>
</rdf:Description>
@@ -279,16 +293,20 @@ stream
endstream
endobj
17 0 obj
-<< /Length 1913 >>
+<< /Length 1983 >>
stream
/opacity1 gs
/Artifact BMC
+EMC
+/Artifact BMC
q
1 0 0 1 160.667 685.928 cm
[] 0 d 0 J 0.398 w 0 0 m 343.711 0 l S
Q
EMC
-/P <</MCID 0 >> BDC
+/Artifact BMC
+EMC
+/P<</MCID 0>> BDC
BT
/F15 9.96264 Tf
1 0 0 1 160.667 658.164 Tm [<0062002B003200480032006000420062005B006D0032>-423<001C006D003B006D0032>-424<006200420069>-423<001C004B00320069>-424<006D0060004D001C0058>-424<004C006D00480048001C>-424<0070>27<00510048006D00690054001C0069>-422<001C00480042005B006D00320069>-424<0069005100600069005100600058>-424<002A0060001C0062>-424<001C00480042005B006D001C004B002D>]TJ
@@ -300,14 +318,18 @@ ET
EMC
/Artifact BMC
EMC
+/Artifact BMC
+EMC
+/Artifact BMC
+EMC
endstream
endobj
-10 0 obj
-<< /Type /Page /Contents 17 0 R /Resources 16 0 R /MediaBox [ 0 0 612 792 ] /Tabs /S /Parent 14 0 R >>
-endobj
16 0 obj
-<< /ExtGState 1 0 R /Font << /F15 13 0 R >> /ProcSet [ /PDF /Text ] >>
+<< /Type /Page /Contents 17 0 R /Resources 15 0 R /MediaBox [ 0 0 612 792 ] /Tabs /S /Parent 13 0 R >>
+endobj
+15 0 obj
+<< /ExtGState 1 0 R /Font << /F15 12 0 R >> /ProcSet [ /PDF /Text ] >>
endobj
1 0 obj
<< /opacity1 <</ca 1/CA 1>> >>
@@ -406,25 +428,25 @@ end
endstream
endobj
-13 0 obj
+12 0 obj
<< /Type /Font /Subtype /Type0 /Encoding /Identity-H /BaseFont /DUCKUG+LMRoman10-Regular /DescendantFonts [ 23 0 R ] /ToUnicode 22 0 R >>
endobj
23 0 obj
<< /Type /Font /Subtype /CIDFontType0 /BaseFont /DUCKUG+LMRoman10-Regular /FontDescriptor 19 0 R /W 18 0 R /CIDSystemInfo << /Registry (Adobe) /Ordering (Identity) /Supplement 0 >> >>
endobj
-14 0 obj
-<< /Type /Pages /Count 2 /Kids [ 9 0 R 10 0 R ] >>
+13 0 obj
+<< /Type /Pages /Count 2 /Kids [ 10 0 R 16 0 R ] >>
endobj
24 0 obj
-<< /Type /Catalog /Pages 14 0 R /Lang (de)/Metadata 15 0 R >>
+<< /Type /Catalog /Pages 13 0 R /Lang (de)/Metadata 14 0 R >>
endobj
25 0 obj
-<< /Producer (luahbtex-1.18.0)/Creator (LaTeX)/CreationDate (D:20250112182411+01'00')/ModDate (D:20250112182411+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.18.0 (TeX Live 2024)) >>
+<< /Producer (luahbtex-1.18.0)/Creator (LaTeX)/CreationDate (D:20250217202030+01'00')/ModDate (D:20250217202030+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.18.0 (TeX Live 2024)) >>
endobj
xref
0 26
0000000002 65535 f
-0000017182 00000 n
+0000017393 00000 n
0000000003 00000 f
0000000004 00000 f
0000000005 00000 f
@@ -432,25 +454,25 @@ xref
0000000007 00000 f
0000000008 00000 f
0000000000 00000 f
-0000002976 00000 n
-0000016976 00000 n
-0000003094 00000 n
+0000003236 00000 n
+0000003118 00000 n
0000000020 00000 n
-0000023803 00000 n
-0000024157 00000 n
-0000003181 00000 n
-0000017095 00000 n
-0000015003 00000 n
-0000017229 00000 n
-0000022352 00000 n
-0000017536 00000 n
-0000017611 00000 n
-0000022588 00000 n
-0000023957 00000 n
-0000024225 00000 n
-0000024303 00000 n
+0000024014 00000 n
+0000024368 00000 n
+0000003322 00000 n
+0000017306 00000 n
+0000017187 00000 n
+0000015144 00000 n
+0000017440 00000 n
+0000022563 00000 n
+0000017747 00000 n
+0000017822 00000 n
+0000022799 00000 n
+0000024168 00000 n
+0000024437 00000 n
+0000024515 00000 n
trailer
-<< /Size 26 /Root 24 0 R /Info 25 0 R /ID [ <9F17D4B6F263CC4AA59084FF1B8E2BF9> <9F17D4B6F263CC4AA59084FF1B8E2BF9> ] >>
+<< /Size 26 /Root 24 0 R /Info 25 0 R /ID [ <1567E94DB9CD4FD0633A3FE19F068506> <1567E94DB9CD4FD0633A3FE19F068506> ] >>
startxref
-24526
+24738
%%EOF
diff --git a/macros/latex/contrib/tagpdf/ex-softhyphen.pdf b/macros/latex/contrib/tagpdf/ex-softhyphen.pdf
index 3d657521c2..a2d151d51e 100644
--- a/macros/latex/contrib/tagpdf/ex-softhyphen.pdf
+++ b/macros/latex/contrib/tagpdf/ex-softhyphen.pdf
@@ -216,17 +216,17 @@ stream
</dc:language>
<dc:date>
<rdf:Seq>
- <rdf:li>2025-01-12T18:24:36+01:00</rdf:li>
+ <rdf:li>2025-02-17T20:20:50+01:00</rdf:li>
</rdf:Seq>
</dc:date>
<dc:format>application/pdf</dc:format>
<dc:source>ex-softhyphen.tex</dc:source>
<xmp:CreatorTool>LaTeX</xmp:CreatorTool>
- <xmp:CreateDate>2025-01-12T18:24:36+01:00</xmp:CreateDate>
- <xmp:ModifyDate>2025-01-12T18:24:36+01:00</xmp:ModifyDate>
- <xmp:MetadataDate>2025-01-12T18:24:36+01:00</xmp:MetadataDate>
+ <xmp:CreateDate>2025-02-17T20:20:50+01:00</xmp:CreateDate>
+ <xmp:ModifyDate>2025-02-17T20:20:50+01:00</xmp:ModifyDate>
+ <xmp:MetadataDate>2025-02-17T20:20:50+01:00</xmp:MetadataDate>
<xmpMM:DocumentID>uuid:aa82e685-4098-469d-861c-3c45dfc700c7</xmpMM:DocumentID>
- <xmpMM:InstanceID>uuid:734954df-61c1-4997-8526-337db2b7200a</xmpMM:InstanceID>
+ <xmpMM:InstanceID>uuid:a52184b7-6ad5-4f9f-8021-9c0d4a5e34fb</xmpMM:InstanceID>
<prism:complianceProfile>three</prism:complianceProfile>
<prism:pageCount>1</prism:pageCount>
</rdf:Description>
@@ -399,7 +399,7 @@ endobj
<< /Type /Catalog /Pages 19 0 R /MarkInfo 20 0 R/Lang (de)/Metadata 14 0 R/StructTreeRoot 5 0 R >>
endobj
30 0 obj
-<< /Producer (luahbtex-1.18.0)/Creator (LaTeX)/CreationDate (D:20250112182436+01'00')/ModDate (D:20250112182436+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.18.0 (TeX Live 2024)) >>
+<< /Producer (luahbtex-1.18.0)/Creator (LaTeX)/CreationDate (D:20250217202050+01'00')/ModDate (D:20250217202050+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.18.0 (TeX Live 2024)) >>
endobj
xref
0 31
@@ -435,7 +435,7 @@ xref
0000018444 00000 n
0000018559 00000 n
trailer
-<< /Size 31 /Root 29 0 R /Info 30 0 R /ID [ <006956472164C4FE1FAC782B108C444F> <006956472164C4FE1FAC782B108C444F> ] >>
+<< /Size 31 /Root 29 0 R /Info 30 0 R /ID [ <9C588A06835F5E227F5D006216F70A71> <9C588A06835F5E227F5D006216F70A71> ] >>
startxref
18782
%%EOF
diff --git a/macros/latex/contrib/tagpdf/ex-spaceglyph-listings.pdf b/macros/latex/contrib/tagpdf/ex-spaceglyph-listings.pdf
index 6d2e34f7f9..edf79966c2 100644
--- a/macros/latex/contrib/tagpdf/ex-spaceglyph-listings.pdf
+++ b/macros/latex/contrib/tagpdf/ex-spaceglyph-listings.pdf
@@ -216,17 +216,17 @@ stream
</dc:language>
<dc:date>
<rdf:Seq>
- <rdf:li>2025-01-12T18:25:00+01:00</rdf:li>
+ <rdf:li>2025-02-17T20:21:10+01:00</rdf:li>
</rdf:Seq>
</dc:date>
<dc:format>application/pdf</dc:format>
<dc:source>ex-spaceglyph-listings.tex</dc:source>
<xmp:CreatorTool>LaTeX</xmp:CreatorTool>
- <xmp:CreateDate>2025-01-12T18:25:00+01:00</xmp:CreateDate>
- <xmp:ModifyDate>2025-01-12T18:25:00+01:00</xmp:ModifyDate>
- <xmp:MetadataDate>2025-01-12T18:25:00+01:00</xmp:MetadataDate>
+ <xmp:CreateDate>2025-02-17T20:21:10+01:00</xmp:CreateDate>
+ <xmp:ModifyDate>2025-02-17T20:21:10+01:00</xmp:ModifyDate>
+ <xmp:MetadataDate>2025-02-17T20:21:10+01:00</xmp:MetadataDate>
<xmpMM:DocumentID>uuid:acdc2435-bf29-4e54-8d09-1c9b6dc32038</xmpMM:DocumentID>
- <xmpMM:InstanceID>uuid:9cd454ba-1c6b-4025-810f-404adc0fa8df</xmpMM:InstanceID>
+ <xmpMM:InstanceID>uuid:7bb7b8df-b80e-4d49-8b6a-03132c216ddd</xmpMM:InstanceID>
<prism:complianceProfile>three</prism:complianceProfile>
<prism:pageCount>1</prism:pageCount>
</rdf:Description>
@@ -360,7 +360,7 @@ endobj
<< /Type /Catalog /Pages 15 0 R /MarkInfo 16 0 R/Lang (de)/Metadata 10 0 R/StructTreeRoot 5 0 R >>
endobj
26 0 obj
-<< /Producer (luahbtex-1.18.0)/Creator (LaTeX)/CreationDate (D:20250112182500+01'00')/ModDate (D:20250112182500+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.18.0 (TeX Live 2024)) >>
+<< /Producer (luahbtex-1.18.0)/Creator (LaTeX)/CreationDate (D:20250217202110+01'00')/ModDate (D:20250217202110+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.18.0 (TeX Live 2024)) >>
endobj
xref
0 27
@@ -392,7 +392,7 @@ xref
0000015816 00000 n
0000015931 00000 n
trailer
-<< /Size 27 /Root 25 0 R /Info 26 0 R /ID [ <1565B5760D3907B17119096DA6341279> <1565B5760D3907B17119096DA6341279> ] >>
+<< /Size 27 /Root 25 0 R /Info 26 0 R /ID [ <19825D490F05554266B312B272B3D812> <19825D490F05554266B312B272B3D812> ] >>
startxref
16154
%%EOF
diff --git a/macros/latex/contrib/tagpdf/ex-structure-obsolete.pdf b/macros/latex/contrib/tagpdf/ex-structure-obsolete.pdf
index 824beecfa9..82be6f7b9b 100644
--- a/macros/latex/contrib/tagpdf/ex-structure-obsolete.pdf
+++ b/macros/latex/contrib/tagpdf/ex-structure-obsolete.pdf
@@ -216,17 +216,17 @@ stream
</dc:language>
<dc:date>
<rdf:Seq>
- <rdf:li>2025-01-12T18:25:25+01:00</rdf:li>
+ <rdf:li>2025-02-17T20:21:30+01:00</rdf:li>
</rdf:Seq>
</dc:date>
<dc:format>application/pdf</dc:format>
<dc:source>ex-structure-obsolete.tex</dc:source>
<xmp:CreatorTool>LaTeX</xmp:CreatorTool>
- <xmp:CreateDate>2025-01-12T18:25:25+01:00</xmp:CreateDate>
- <xmp:ModifyDate>2025-01-12T18:25:25+01:00</xmp:ModifyDate>
- <xmp:MetadataDate>2025-01-12T18:25:25+01:00</xmp:MetadataDate>
+ <xmp:CreateDate>2025-02-17T20:21:30+01:00</xmp:CreateDate>
+ <xmp:ModifyDate>2025-02-17T20:21:30+01:00</xmp:ModifyDate>
+ <xmp:MetadataDate>2025-02-17T20:21:30+01:00</xmp:MetadataDate>
<xmpMM:DocumentID>uuid:bf5e4a2b-cfa9-4fc5-878c-8f9d2ee95445</xmpMM:DocumentID>
- <xmpMM:InstanceID>uuid:9a931b0e-bcff-44df-80e8-9b91b0b51ad1</xmpMM:InstanceID>
+ <xmpMM:InstanceID>uuid:a25399bb-8533-408c-885a-c947a88fd205</xmpMM:InstanceID>
<prism:complianceProfile>three</prism:complianceProfile>
<prism:pageCount>1</prism:pageCount>
</rdf:Description>
@@ -532,7 +532,7 @@ endobj
<< /Type /Catalog /Pages 26 0 R /MarkInfo 27 0 R/Lang (de)/Metadata 20 0 R/StructTreeRoot 5 0 R >>
endobj
43 0 obj
-<< /Producer (luahbtex-1.18.0)/Creator (LaTeX)/CreationDate (D:20250112182525+01'00')/ModDate (D:20250112182525+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.18.0 (TeX Live 2024)) >>
+<< /Producer (luahbtex-1.18.0)/Creator (LaTeX)/CreationDate (D:20250217202130+01'00')/ModDate (D:20250217202130+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.18.0 (TeX Live 2024)) >>
endobj
xref
0 44
@@ -581,7 +581,7 @@ xref
0000023754 00000 n
0000023869 00000 n
trailer
-<< /Size 44 /Root 42 0 R /Info 43 0 R /ID [ <39FF36562397C0C6C81CC6219516251E> <39FF36562397C0C6C81CC6219516251E> ] >>
+<< /Size 44 /Root 42 0 R /Info 43 0 R /ID [ <2D6C91DAC5B906226610619241F0682C> <2D6C91DAC5B906226610619241F0682C> ] >>
startxref
24092
%%EOF
diff --git a/macros/latex/contrib/tagpdf/ex-tagpdf-template.pdf b/macros/latex/contrib/tagpdf/ex-tagpdf-template.pdf
index 8eaca21627..f0f097d0b1 100644
--- a/macros/latex/contrib/tagpdf/ex-tagpdf-template.pdf
+++ b/macros/latex/contrib/tagpdf/ex-tagpdf-template.pdf
@@ -216,17 +216,17 @@ stream
</dc:language>
<dc:date>
<rdf:Seq>
- <rdf:li>2025-01-12T18:25:51+01:00</rdf:li>
+ <rdf:li>2025-02-17T20:21:53+01:00</rdf:li>
</rdf:Seq>
</dc:date>
<dc:format>application/pdf</dc:format>
<dc:source>ex-tagpdf-template.tex</dc:source>
<xmp:CreatorTool>LaTeX</xmp:CreatorTool>
- <xmp:CreateDate>2025-01-12T18:25:51+01:00</xmp:CreateDate>
- <xmp:ModifyDate>2025-01-12T18:25:51+01:00</xmp:ModifyDate>
- <xmp:MetadataDate>2025-01-12T18:25:51+01:00</xmp:MetadataDate>
+ <xmp:CreateDate>2025-02-17T20:21:53+01:00</xmp:CreateDate>
+ <xmp:ModifyDate>2025-02-17T20:21:53+01:00</xmp:ModifyDate>
+ <xmp:MetadataDate>2025-02-17T20:21:53+01:00</xmp:MetadataDate>
<xmpMM:DocumentID>uuid:f320abfc-f6ab-4d12-8719-d176f4d947cf</xmpMM:DocumentID>
- <xmpMM:InstanceID>uuid:58ccc763-872f-4eb3-84fd-754affd3d4fe</xmpMM:InstanceID>
+ <xmpMM:InstanceID>uuid:ed06b142-8255-42d6-821f-5e8aacccf14e</xmpMM:InstanceID>
<prism:complianceProfile>three</prism:complianceProfile>
<prism:pageCount>1</prism:pageCount>
</rdf:Description>
@@ -313,7 +313,7 @@ endobj
<< /Type /Namespace /NS (https://www.latex-project.org/ns/book) /RoleMapNS 18 0 R >>
endobj
19 0 obj
-<< /Type /Namespace /NS (data:,8B86276B-4958-603A-2BF5-B35304ADF8CD) >>
+<< /Type /Namespace /NS (data:,9CF54CF0-337A-2CD9-E4D1-AAE4176F2304) >>
endobj
8 0 obj
[ 9 0 R 11 0 R 13 0 R 15 0 R 17 0 R 19 0 R ]
@@ -405,7 +405,7 @@ endobj
<< /Type /Catalog /Pages 31 0 R /MarkInfo 32 0 R/Lang (en)/Metadata 26 0 R/StructTreeRoot 5 0 R >>
endobj
42 0 obj
-<< /Producer (luahbtex-1.18.0)/Creator (LaTeX)/CreationDate (D:20250112182551+01'00')/ModDate (D:20250112182551+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.18.0 (TeX Live 2024)) >>
+<< /Producer (luahbtex-1.18.0)/Creator (LaTeX)/CreationDate (D:20250217202153+01'00')/ModDate (D:20250217202153+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.18.0 (TeX Live 2024)) >>
endobj
xref
0 43
@@ -453,7 +453,7 @@ xref
0000018163 00000 n
0000018278 00000 n
trailer
-<< /Size 43 /Root 41 0 R /Info 42 0 R /ID [ <EBFEA6CC7DF783B4BA808AF359A86264> <EBFEA6CC7DF783B4BA808AF359A86264> ] >>
+<< /Size 43 /Root 41 0 R /Info 42 0 R /ID [ <CEED71BFB25DDD4FE722B044E56F2D24> <CEED71BFB25DDD4FE722B044E56F2D24> ] >>
startxref
18501
%%EOF
diff --git a/macros/latex/contrib/tagpdf/tagpdf-backend.dtx b/macros/latex/contrib/tagpdf/tagpdf-backend.dtx
index e6c9e8d39e..9ad3b8e359 100644
--- a/macros/latex/contrib/tagpdf/tagpdf-backend.dtx
+++ b/macros/latex/contrib/tagpdf/tagpdf-backend.dtx
@@ -47,13 +47,13 @@
% }^^A
% }
%
-% \date{Version 0.99l, released 2025-01-12}
+% \date{Version 0.99m, released 2025-02-17}
% \maketitle
% \begin{implementation}
% \begin{macrocode}
%<@@=tag>
%<*luatex>
-\ProvidesExplFile {tagpdf-luatex.def} {2025-01-12} {0.99l}
+\ProvidesExplFile {tagpdf-luatex.def} {2025-02-17} {0.99m}
{tagpdf~driver~for~luatex}
% \end{macrocode}
% \section{Loading the lua}
@@ -174,8 +174,8 @@
local ProvidesLuaModule = {
name = "tagpdf",
- version = "0.99l", --TAGVERSION
- date = "2025-01-12", --TAGDATE
+ version = "0.99m", --TAGVERSION
+ date = "2025-02-17", --TAGDATE
description = "tagpdf lua code",
license = "The LATEX Project Public License 1.3c"
}
diff --git a/macros/latex/contrib/tagpdf/tagpdf-checks.dtx b/macros/latex/contrib/tagpdf/tagpdf-checks.dtx
index 7258d91d68..cb9ea0cae5 100644
--- a/macros/latex/contrib/tagpdf/tagpdf-checks.dtx
+++ b/macros/latex/contrib/tagpdf/tagpdf-checks.dtx
@@ -48,7 +48,7 @@
% }^^A
% }
%
-% \date{Version 0.99l, released 2025-01-12}
+% \date{Version 0.99m, released 2025-02-17}
% \maketitle
% \begin{documentation}
% \section{Commands}
@@ -331,7 +331,7 @@
% \begin{macrocode}
%<@@=tag>
%<*header>
-\ProvidesExplPackage {tagpdf-checks-code} {2025-01-12} {0.99l}
+\ProvidesExplPackage {tagpdf-checks-code} {2025-02-17} {0.99m}
{part of tagpdf - code related to checks, conditionals, debugging and messages}
%</header>
% \end{macrocode}
@@ -350,7 +350,7 @@
% \begin{macro}{mc-tag-missing}
% If the tag is missing
% \begin{macrocode}
-\msg_new:nnn { tag } {mc-tag-missing} { required~tag~missing~-~mcid~#1 }
+\msg_new:nnn { tag } {mc-tag-missing} { MC-tag~missing;~#1~used~instead~-~mcid~#2 }
% \end{macrocode}
% \end{macro}
% \begin{macro}{mc-label-unknown}
@@ -869,18 +869,23 @@
% \end{macrocode}
% \end{macro}
% \begin{macro}{\@@_check_mc_tag:N}
-% This checks if the mc has a (known) tag.
+% This checks if the mc has a (known) tag, if it is empty
+% (e.g. if due to a call to the output routine, see issue https://github.com/latex3/tagpdf/issues/111)
+% then we fall back to the structure name.
% \begin{macrocode}
\cs_new_protected:Npn \@@_check_mc_tag:N #1 %#1 is var with a tag name in it
{
- \tl_if_empty:NT #1
+ \tl_if_empty:NTF #1
{
- \msg_error:nne { tag } {mc-tag-missing} { \@@_get_mc_abs_cnt: }
+ \tl_set:No #1 { \g_@@_struct_tag_tl }
+ \msg_info:nnee { tag } {mc-tag-missing} { \g_@@_struct_tag_tl }{ \@@_get_mc_abs_cnt: }
+ }
+ {
+ \prop_if_in:NoF \g_@@_role_tags_NS_prop {#1}
+ {
+ \msg_warning:nne { tag } {role-unknown-tag} {#1}
+ }
}
- \prop_if_in:NoF \g_@@_role_tags_NS_prop {#1}
- {
- \msg_warning:nne { tag } {role-unknown-tag} {#1}
- }
}
% \end{macrocode}
% \end{macro}
diff --git a/macros/latex/contrib/tagpdf/tagpdf-code.pdf b/macros/latex/contrib/tagpdf/tagpdf-code.pdf
index 58eb2ab028..33d694ea34 100644
--- a/macros/latex/contrib/tagpdf/tagpdf-code.pdf
+++ b/macros/latex/contrib/tagpdf/tagpdf-code.pdf
Binary files differ
diff --git a/macros/latex/contrib/tagpdf/tagpdf-data.dtx b/macros/latex/contrib/tagpdf/tagpdf-data.dtx
index a3a10ee4fe..f9994ab90d 100644
--- a/macros/latex/contrib/tagpdf/tagpdf-data.dtx
+++ b/macros/latex/contrib/tagpdf/tagpdf-data.dtx
@@ -47,7 +47,7 @@
% }^^A
% }
%
-% \date{Version 0.99l, released 2025-01-12}
+% \date{Version 0.99m, released 2025-02-17}
% \maketitle
% \begin{documentation}
% This files contains a various data files which are read in
@@ -61,7 +61,7 @@
% latex-lab has also a namespace module, which takes precedence!
% \begin{macrocode}
%<*ns-latex>
-%% \ProvidesExplFile {tagpdf-ns-latex.def} {2025-01-12} {0.99l}
+%% \ProvidesExplFile {tagpdf-ns-latex.def} {2025-02-17} {0.99m}
%% {latex} {https://www.latex-project.org/ns/dflt}{}
title, Title, pdf2,
part, Title, pdf2,
@@ -93,7 +93,7 @@ text, P, pdf2,
% It is bound to change
% \begin{macrocode}
%<*ns-latex-book>
-%% \ProvidesExplFile {tagpdf-ns-latex-book.def} {2025-01-12} {0.99l}
+%% \ProvidesExplFile {tagpdf-ns-latex-book.def} {2025-02-17} {0.99m}
%% {latex-book} {https://www.latex-project.org/ns/book}{}
chapter, H1,pdf2,
section, H2,pdf2,
@@ -107,7 +107,7 @@ subparagraph, H6,pdf2,
% \section{The pdf namespace data}
% \begin{macrocode}
%<*ns-pdf>
-%% \ProvidesExplFile {tagpdf-ns-pdf.def} {2025-01-12} {0.99l}
+%% \ProvidesExplFile {tagpdf-ns-pdf.def} {2025-02-17} {0.99m}
%% {pdf} {http://iso.org/pdf/ssn}{}
StructTreeRoot,StructTreeRoot,pdf,D,
Document,Document,pdf,D,
@@ -175,7 +175,7 @@ Strong,Span,pdf,I,
% \section{The pdf 2.0 namespace data}
% \begin{macrocode}
%<*ns-pdf2>
-%% \ProvidesExplFile {tagpdf-ns-pdf2.def} {2025-01-12} {0.99l}
+%% \ProvidesExplFile {tagpdf-ns-pdf2.def} {2025-02-17} {0.99m}
%% {pdf2} {http://iso.org/pdf2/ssn}{}
StructTreeRoot,StructTreeRoot,pdf2,D,
Document,Document,pdf2,D,
@@ -232,7 +232,7 @@ Strong,Strong,pdf2,I,
% \section{The mathml namespace data}
% \begin{macrocode}
%<*ns-mathml>
-%% \ProvidesExplFile {tagpdf-ns-mathml.def} {2025-01-12} {0.99l}
+%% \ProvidesExplFile {tagpdf-ns-mathml.def} {2025-02-17} {0.99m}
% {mathml}{http://www.w3.org/1998/Math/MathML}{}
abs,abs,mathml,
and,and,mathml,
@@ -467,7 +467,7 @@ xor,xor,mathml,
% This will perhaps change in future.
% \begin{macrocode}
%<*parent-child>
-%% \ProvidesExplFile {tagpdf-parent-child.csv} {2025-01-12} {0.99l}
+%% \ProvidesExplFile {tagpdf-parent-child.csv} {2025-02-17} {0.99m}
,,,StructTreeRoot,Document,Art,Part,Div,Sect,BlockQuote,NonStruct,TOC,TOCI,Index,Private,Quote,Note,Reference,BibEntry,P,Hn,H,Lbl,Code,Span,Link,Annot,Form,Ruby,RB,RT,RP,Warichu,WT,WP,L,LI,LBody,Table,TR,TH,TD,THead,TBody,TFoot,Caption,Figure,Formula,MC
Document,both,document level,1,0..n,∅,‡,‡,∅,0..n,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅
Art,1.7,grouping,∅,0..n,∅,‡,‡,0..n,0..n,‡,∅,∅,∅,0..n,∅,0..n,∅,∅,∅,0..1,0..1,∅,∅,∅,0..n,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,∅,∅
@@ -522,7 +522,7 @@ MC,both,---,∅,∅,∅,∅,∅,∅,0..n,‡,∅,∅,∅,0..n,0..n,0..n,0..n,0..
% This will perhaps change in future.
% \begin{macrocode}
%<*parent-child-2>
-%% \ProvidesExplFile {tagpdf-parent-child-2.csv} {2025-01-12} {0.99l}
+%% \ProvidesExplFile {tagpdf-parent-child-2.csv} {2025-02-17} {0.99m}
,,,StructTreeRoot,Document,DocumentFragment,Art,Part,Div,Sect,Aside,BlockQuote,NonStruct,TOC,TOCI,Index,Private,Title,Sub,Quote,Note,Reference,BibEntry,P,Hn,H,Lbl,Code,Em,Strong,Span,Link,Annot,Form,Ruby,RB,RT,RP,Warichu,WT,WP,FENote,L,LI,LBody,Table,TR,TH,TD,THead,TBody,TFoot,Caption,Figure,Formula,math,mathml,Artifact,MC
Document,both,document level,1,0..n,0..n,∅,‡,‡,∅,0..n,0..n,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅
DocumentFragment,2.0,document level,∅,0..n,0..n,0..n,‡,‡,0..n,0..n,0..n,‡,∅,∅,∅,0..n,∅,∅,∅,∅*,∅,∅,∅,∅,∅,∅,∅*,∅,∅,∅,∅*,∅*,∅,∅,∅,∅,∅,∅,∅,∅,∅*,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅*,∅,∅,∅,∅,0..n,∅
diff --git a/macros/latex/contrib/tagpdf/tagpdf-mc-generic.dtx b/macros/latex/contrib/tagpdf/tagpdf-mc-generic.dtx
index 8b819a1d2f..bbf2fac691 100644
--- a/macros/latex/contrib/tagpdf/tagpdf-mc-generic.dtx
+++ b/macros/latex/contrib/tagpdf/tagpdf-mc-generic.dtx
@@ -46,7 +46,7 @@
% }^^A
% }
%
-% \date{Version 0.99l, released 2025-01-12}
+% \date{Version 0.99m, released 2025-02-17}
% \maketitle
% \begin{documentation}
% \end{documentation}
@@ -55,11 +55,11 @@
% \begin{macrocode}
%<@@=tag>
%<*generic>
-\ProvidesExplPackage {tagpdf-mc-code-generic} {2025-01-12} {0.99l}
+\ProvidesExplPackage {tagpdf-mc-code-generic} {2025-02-17} {0.99m}
{part of tagpdf - code related to marking chunks - generic mode}
%</generic>
%<*debug>
-\ProvidesExplPackage {tagpdf-debug-generic} {2025-01-12} {0.99l}
+\ProvidesExplPackage {tagpdf-debug-generic} {2025-02-17} {0.99m}
{part of tagpdf - debugging code related to marking chunks - generic mode}
%</debug>
% \end{macrocode}
@@ -544,89 +544,22 @@
% We also define a wrapper around the low-level command as luamode will need
% something different.
% \begin{macrocode}
-\bool_if:NTF\g_@@_delayed_shipout_bool
- {
- \hook_gput_code:nnn {shipout/before}{tagpdf}{ \flag_clear:n { @@/mcid } }
- \cs_set_protected:Npn \@@_mc_bdc_mcid:nn #1 #2
- {
- \int_gincr:N \c@g_@@_MCID_abs_int
- \@@_property_record:eV
- {
- mcid-\int_use:N \c@g_@@_MCID_abs_int
- }
- \c_@@_property_mc_clist
- \@@_mc_bdc_shipout:ee
- {#1}
- {
- /MCID~\flag_height:n { @@/mcid }
- \flag_raise:n { @@/mcid }~ #2
- }
- }
- }
-% \end{macrocode}
-% if the engine is too old, we have to revert to earlier method.
-% \begin{macrocode}
- {
- \msg_new:nnn { tagpdf } { old-engine }
- {
- The~engine~or~the~PDF management~is~too~old~or\\
- delayed~shipout~has~been~disabled.\\
- Fast~numbering~of~MC-chunks~not~available.\\
- More~compilations~will~be~needed~in~generic~mode.
- }
- \msg_warning:nn { tagpdf} { old-engine }
- \@@_prop_new:N \g_@@_MCID_byabspage_prop
- \int_new:N \g_@@_MCID_tmp_bypage_int
- \cs_generate_variant:Nn \@@_mc_bdc:nn {ne}
-% \end{macrocode}
-% revert the attribute:
-% \begin{macrocode}
- \property_gset:nnnn {tagmcid } { now }
- {0} { \int_use:N \g_@@_MCID_tmp_bypage_int }
- \cs_new_protected:Npn \@@_mc_bdc_mcid:nn #1 #2
+\hook_gput_code:nnn {shipout/before}{tagpdf}{ \flag_clear:n { @@/mcid } }
+\cs_set_protected:Npn \@@_mc_bdc_mcid:nn #1 #2
+ {
+ \int_gincr:N \c@g_@@_MCID_abs_int
+ \@@_property_record:eV
{
- \int_gincr:N \c@g_@@_MCID_abs_int
- \tl_set:Ne \l_@@_mc_ref_abspage_tl
- {
- \property_ref:enn %3 args
- {
- mcid-\int_use:N \c@g_@@_MCID_abs_int
- }
- { tagabspage }
- {-1}
- }
- \prop_get:NoNTF
- \g_@@_MCID_byabspage_prop
- {
- \l_@@_mc_ref_abspage_tl
- }
- \l_@@_mc_tmpa_tl
- {
- %key already present, use value for MCID and add 1 for the next
- \int_gset:Nn \g_@@_MCID_tmp_bypage_int { \l_@@_mc_tmpa_tl }
- \@@_prop_gput:Nee
- \g_@@_MCID_byabspage_prop
- { \l_@@_mc_ref_abspage_tl }
- { \int_eval:n {\l_@@_mc_tmpa_tl +1} }
- }
- {
- %key not present, set MCID to 0 and insert 1
- \int_gzero:N \g_@@_MCID_tmp_bypage_int
- \@@_prop_gput:Nee
- \g_@@_MCID_byabspage_prop
- { \l_@@_mc_ref_abspage_tl }
- {1}
- }
- \@@_property_record:eV
- {
- mcid-\int_use:N \c@g_@@_MCID_abs_int
- }
- \c_@@_property_mc_clist
- \@@_mc_bdc:ne
- {#1}
- { /MCID~\int_eval:n { \g_@@_MCID_tmp_bypage_int }~ \exp_not:n { #2 } }
- }
- }
+ mcid-\int_use:N \c@g_@@_MCID_abs_int
+ }
+ \c_@@_property_mc_clist
+ \@@_mc_bdc_shipout:ee
+ {#1}
+ {
+ /MCID~\flag_height:n { @@/mcid }
+ \flag_raise:n { @@/mcid }~ #2
+ }
+ }
\cs_new_protected:Npn \@@_mc_bdc_mcid:n #1
{
\@@_mc_bdc_mcid:nn {#1} {}
diff --git a/macros/latex/contrib/tagpdf/tagpdf-mc-luacode.dtx b/macros/latex/contrib/tagpdf/tagpdf-mc-luacode.dtx
index fac3dac0d6..f73b578b21 100644
--- a/macros/latex/contrib/tagpdf/tagpdf-mc-luacode.dtx
+++ b/macros/latex/contrib/tagpdf/tagpdf-mc-luacode.dtx
@@ -46,7 +46,7 @@
% }^^A
% }
%
-% \date{Version 0.99l, released 2025-01-12}
+% \date{Version 0.99m, released 2025-02-17}
% \maketitle
% \begin{implementation}
% The code is split into three parts: code shared by all engines,
@@ -86,11 +86,11 @@
% \begin{macrocode}
%<@@=tag>
%<*luamode>
-\ProvidesExplPackage {tagpdf-mc-code-lua} {2025-01-12} {0.99l}
+\ProvidesExplPackage {tagpdf-mc-code-lua} {2025-02-17} {0.99m}
{tagpdf - mc code only for the luamode }
%</luamode>
%<*debug>
-\ProvidesExplPackage {tagpdf-debug-lua} {2025-01-12} {0.99l}
+\ProvidesExplPackage {tagpdf-debug-lua} {2025-02-17} {0.99m}
{part of tagpdf - debugging code related to marking chunks - lua mode}
%</debug>
% \end{macrocode}
diff --git a/macros/latex/contrib/tagpdf/tagpdf-mc-shared.dtx b/macros/latex/contrib/tagpdf/tagpdf-mc-shared.dtx
index 7eff1a6eca..b375d33bd4 100644
--- a/macros/latex/contrib/tagpdf/tagpdf-mc-shared.dtx
+++ b/macros/latex/contrib/tagpdf/tagpdf-mc-shared.dtx
@@ -46,7 +46,7 @@
% }^^A
% }
%
-% \date{Version 0.99l, released 2025-01-12}
+% \date{Version 0.99m, released 2025-02-17}
% \maketitle
% \begin{documentation}
% \section{Public Commands}
@@ -207,7 +207,7 @@
% \begin{macrocode}
%<@@=tag>
%<*header>
-\ProvidesExplPackage {tagpdf-mc-code-shared} {2025-01-12} {0.99l}
+\ProvidesExplPackage {tagpdf-mc-code-shared} {2025-02-17} {0.99m}
{part of tagpdf - code related to marking chunks -
code shared by generic and luamode }
%</header>
diff --git a/macros/latex/contrib/tagpdf/tagpdf-roles.dtx b/macros/latex/contrib/tagpdf/tagpdf-roles.dtx
index e2909d96fa..7b66026ea0 100644
--- a/macros/latex/contrib/tagpdf/tagpdf-roles.dtx
+++ b/macros/latex/contrib/tagpdf/tagpdf-roles.dtx
@@ -46,7 +46,7 @@
% }^^A
% }
%
-% \date{Version 0.99l, released 2025-01-12}
+% \date{Version 0.99m, released 2025-02-17}
% \maketitle
% \begin{documentation}
% \begin{function}
@@ -98,7 +98,7 @@
% \begin{macrocode}
%<@@=tag>
%<*header>
-\ProvidesExplPackage {tagpdf-roles-code} {2025-01-12} {0.99l}
+\ProvidesExplPackage {tagpdf-roles-code} {2025-02-17} {0.99m}
{part of tagpdf - code related to roles and structure names}
%</header>
% \end{macrocode}
diff --git a/macros/latex/contrib/tagpdf/tagpdf-space.dtx b/macros/latex/contrib/tagpdf/tagpdf-space.dtx
index bed83d1124..dfcc45fc04 100644
--- a/macros/latex/contrib/tagpdf/tagpdf-space.dtx
+++ b/macros/latex/contrib/tagpdf/tagpdf-space.dtx
@@ -46,7 +46,7 @@
% }^^A
% }
%
-% \date{Version 0.99l, released 2025-01-12}
+% \date{Version 0.99m, released 2025-02-17}
% \maketitle
% \begin{documentation}
% \begin{function}{activate/space (setup-key),interwordspace (deprecated)}
@@ -66,7 +66,7 @@
% \begin{macrocode}
%<@@=tag>
%<*header>
-\ProvidesExplPackage {tagpdf-space-code} {2025-01-12} {0.99l}
+\ProvidesExplPackage {tagpdf-space-code} {2025-02-17} {0.99m}
{part of tagpdf - code related to real space chars}
%</header>
% \end{macrocode}
diff --git a/macros/latex/contrib/tagpdf/tagpdf-struct.dtx b/macros/latex/contrib/tagpdf/tagpdf-struct.dtx
index c966f972b2..418619eae1 100644
--- a/macros/latex/contrib/tagpdf/tagpdf-struct.dtx
+++ b/macros/latex/contrib/tagpdf/tagpdf-struct.dtx
@@ -47,7 +47,7 @@
% }^^A
% }
%
-% \date{Version 0.99l, released 2025-01-12}
+% \date{Version 0.99m, released 2025-02-17}
% \maketitle
% \begin{documentation}
% \section{Public Commands}
@@ -308,7 +308,7 @@
% \begin{macrocode}
%<@@=tag>
%<*header>
-\ProvidesExplPackage {tagpdf-struct-code} {2025-01-12} {0.99l}
+\ProvidesExplPackage {tagpdf-struct-code} {2025-02-17} {0.99m}
{part of tagpdf - code related to storing structure}
%</header>
% \end{macrocode}
@@ -878,7 +878,7 @@
% \begin{macrocode}
\cs_new_protected:Npn \@@_struct_fill_kid_key:n #1 %#1 is the struct num
{
- \bool_if:NF\g_@@_mode_lua_bool
+ \bool_if:NF \g_@@_mode_lua_bool
{
\seq_clear:N \l_@@_tmpa_seq
\seq_map_inline:cn { g_@@_struct_kids_#1_seq }
@@ -904,7 +904,7 @@
{
% in this case we need a special command in
% luamode to get the array right. See issue #13
- \bool_if:NTF\g_@@_mode_lua_bool
+ \sys_if_engine_luatex:TF
{
\@@_struct_exchange_kid_command:c
{g_@@_struct_kids_#1_seq}
@@ -1229,7 +1229,8 @@
% actualtext,
% lang,
% ref,
-% E
+% E,
+% phoneme
% }
% \begin{macrocode}
\keys_define:nn { @@ / struct }
@@ -1320,6 +1321,21 @@
{ <\l_@@_tmpa_str>}
}
},
+ phoneme .code:n = % ActualText property
+ {
+ \tl_if_empty:oF{#1}
+ {
+ \str_set_convert:Noon
+ \l_@@_tmpa_str
+ { #1 }
+ { default }
+ { utf16/hex }
+ \@@_struct_prop_gput:nne
+ { \int_use:N \c@g_@@_struct_abs_int }
+ { Phoneme }
+ { <\l_@@_tmpa_str>}
+ }
+ },
lang .code:n = % Lang property
{
\@@_struct_prop_gput:nne
@@ -2118,7 +2134,7 @@
% \section{Attributes and attribute classes}
% \begin{macrocode}
%<*header>
-\ProvidesExplPackage {tagpdf-attr-code} {2025-01-12} {0.99l}
+\ProvidesExplPackage {tagpdf-attr-code} {2025-02-17} {0.99m}
{part of tagpdf - code related to attributes and attribute classes}
%</header>
% \end{macrocode}
diff --git a/macros/latex/contrib/tagpdf/tagpdf-tree.dtx b/macros/latex/contrib/tagpdf/tagpdf-tree.dtx
index f8d03e99fa..381b97f1d9 100644
--- a/macros/latex/contrib/tagpdf/tagpdf-tree.dtx
+++ b/macros/latex/contrib/tagpdf/tagpdf-tree.dtx
@@ -47,13 +47,13 @@
% }^^A
% }
%
-% \date{Version 0.99l, released 2025-01-12}
+% \date{Version 0.99m, released 2025-02-17}
% \maketitle
% \begin{implementation}
% \begin{macrocode}
%<@@=tag>
%<*header>
-\ProvidesExplPackage {tagpdf-tree-code} {2025-01-12} {0.99l}
+\ProvidesExplPackage {tagpdf-tree-code} {2025-02-17} {0.99m}
{part of tagpdf - code related to writing trees and dictionaries to the pdf}
%</header>
% \end{macrocode}
diff --git a/macros/latex/contrib/tagpdf/tagpdf-user.dtx b/macros/latex/contrib/tagpdf/tagpdf-user.dtx
index aa17c83a8f..5ce90ab47a 100644
--- a/macros/latex/contrib/tagpdf/tagpdf-user.dtx
+++ b/macros/latex/contrib/tagpdf/tagpdf-user.dtx
@@ -47,7 +47,7 @@
% }^^A
% }
%
-% \date{Version 0.99l, released 2025-01-12}
+% \date{Version 0.99m, released 2025-02-17}
% \maketitle
% \begin{documentation}
% \section{Setup commands}
@@ -164,7 +164,7 @@
% |debug/structures| = \meta{structure number}
% \end{syntax}
% This key is available only if the tagpdf-debug package is loaded
-% and shows all structures starting with the one with the number
+% and shows all structures starting with the one with the number
% given by the key.
% \end{function}
@@ -195,13 +195,13 @@
% \begin{syntax}
% |para/tagging| = |true|\verb+|+|false|\\
% |debug/show=para|\\
-% |debug/show=paraOff|
+% |debug/show=paraOff|
% \end{syntax}
% The |para/tagging| key can be used in |\tagpdfsetup| and enable/disables tagging
% of paragraphics.
% |debug/show=para| puts small colored numbers at the begin and end of a paragraph.
% This is meant as a debugging help. The number are boxes and have a (tiny) height,
-% so they can affect typesetting.
+% so they can affect typesetting.
% \end{function}
%
% \begin{function}{\tagpdfparaOn,\tagpdfparaOff}
@@ -259,9 +259,9 @@
% { Contents }
% { (ref) }
% \end{verbatim}
-%
+%
% \section{Socket support}
-%
+%
% \begin{function}{\tag_socket_use:n,\tag_socket_use:nnn,\UseTaggingSocket}
% \begin{syntax}
% \cs{tag_socket_use:n} \Arg{socket name}\\
@@ -273,7 +273,7 @@
% \cs{UseTaggingSocket} \Arg{socket name} \Arg{socket argument} \Arg{socket argument}\\
% \end{syntax}
% \end{function}
-%
+%
% Given that we sometimes have to suspend tagging, it would be fairly
% inefficient to put different plugs into these sockets whenever that
% happens. We therefore offer \cs{UseTaggingSocket} which is like
@@ -290,8 +290,8 @@
% instead of changing the plugs of the tagging support sockets back and forth.
%
% Usually, these sockets have (beside the default plug defined for every socket)
-% one additional plug defined and directly assigned. This plug is used when
-% tagging is active.
+% one additional plug defined and directly assigned. This plug is used when
+% tagging is active.
% There may be more plugs, e.g., tagging with special debugging or special behaviour
% depending on the class or PDF version etc., but right now it is usually just on or off.
%
@@ -304,14 +304,14 @@
% \cs{UseSocket} directly, but in this case the socket remains active
% if e.g. \cs{SuspendTagging} is in force. There may be reasons for doing
% that but in general we expect to always use \cs{UseTaggingSocket}.
-%
+%
% For special cases like in some \cs{halign} contexts we need a fully expandable
% version of the commend. For these cases, \cs{UseExpandableTaggingSocket} can be
% used. To allow being expandable, it does not output any debugging information
% if \cs{DebugSocketsOn} is in effect and therefore should be avoided whenever possible.
%
% The L3 programming layer versions \cs{tag_socket_use_expandable:n}, \cs{tag_socket_use:n}, and
-% \cs{tag_socket_use:nn}, \cs{tag_socket_use:nnn}
+% \cs{tag_socket_use:nn}, \cs{tag_socket_use:nnn}
% are slightly more efficient than
% \cs{UseTaggingSocket} because they do not have to determine how
% many arguments the socket takes when disabling it.
@@ -322,7 +322,7 @@
% \begin{macrocode}
%<@@=tag>
%<*header>
-\ProvidesExplPackage {tagpdf-user} {2025-01-12} {0.99l}
+\ProvidesExplPackage {tagpdf-user} {2025-02-17} {0.99m}
{tagpdf - user commands}
%</header>
% \end{macrocode}
@@ -347,11 +347,11 @@
%<base>\cs_new_protected:Npn\tag_tool:n #1 {}
%<base>\cs_set_eq:NN\tagtool\tag_tool:n
%<*package>
-\cs_set_protected:Npn\tag_tool:n #1
+\cs_set_protected:Npn\tag_tool:n #1
{
- \tag_if_active:T { \keys_set:nn {tag / tool}{#1} }
+ \tag_if_active:T { \keys_set:nn {tag / tool}{#1} }
}
-\cs_set_eq:NN\tagtool\tag_tool:n
+\cs_set_eq:NN\tagtool\tag_tool:n
%</package>
% \end{macrocode}
% \end{macro}
@@ -448,7 +448,7 @@
% \end{macrocode}
%
% \begin{macrocode}
-\cs_set_protected:Npn \tag_socket_use:nn #1#2
+\cs_set_protected:Npn \tag_socket_use:nn #1#2
{
\bool_if:NT \l_@@_active_socket_bool
{ \socket_use:nn {tagsupport/#1} {#2} }
@@ -456,7 +456,7 @@
% \end{macrocode}
%
% \begin{macrocode}
-\cs_set_protected:Npn \tag_socket_use:nnn #1#2#3
+\cs_set_protected:Npn \tag_socket_use:nnn #1#2#3
{
\bool_if:NTF \l_@@_active_socket_bool
{ \socket_use:nnn {tagsupport/#1} {#2} {#3} }
@@ -464,14 +464,14 @@
}
% \end{macrocode}
% \begin{macrocode}
-\cs_set:Npn \tag_socket_use_expandable:n #1
+\cs_set:Npn \tag_socket_use_expandable:n #1
{
\bool_if:NT \l_@@_active_socket_bool
{ \socket_use_expandable:n {tagsupport/#1} }
}
% \end{macrocode}
% \begin{macrocode}
-\cs_set_protected:Npn \UseTaggingSocket #1
+\cs_set_protected:Npn \UseTaggingSocket #1
{
\bool_if:NTF \l_@@_active_socket_bool
{ \socket_use:nw {tagsupport/#1} }
@@ -493,7 +493,7 @@
% \end{macrocode}
% \begin{macrocode}
-\cs_set:Npn \UseExpandableTaggingSocket #1
+\cs_set:Npn \UseExpandableTaggingSocket #1
{
\bool_if:NTF \l_@@_active_socket_bool
{ \socket_use_expandable:nw {tagsupport/#1} }
@@ -512,7 +512,7 @@
\ERRORusetaggingsocket
}
}
-%</package>
+%</package>
% \end{macrocode}
% \end{macro}
%
@@ -540,7 +540,7 @@
{
mc-data .code:n =
{
- \sys_if_engine_luatex:T
+ \bool_if:NT \g_@@_mode_lua_bool
{
\lua_now:e{ltx.@@.trace.show_all_mc_data(#1,\@@_get_mc_abs_cnt:,0)}
}
@@ -556,60 +556,57 @@
\keys_define:nn { @@ / show }
{ mc-current .code:n =
{
- \bool_if:NTF \g_@@_mode_lua_bool
- {
- \sys_if_engine_luatex:T
- {
- \int_compare:nNnTF
- { -2147483647 }
- =
- {
- \lua_now:e
- {
- tex.print
- (tex.getattribute
- (luatexbase.attributes.g_@@_mc_cnt_attr))
- }
- }
- {
- \lua_now:e
- {
- ltx.@@.trace.log
- (
- "mc-current:~no~MC~open,~current~abscnt
- =\@@_get_mc_abs_cnt:"
- ,0
- )
- texio.write_nl("")
- }
- }
- {
- \lua_now:e
- {
- ltx.@@.trace.log
- (
- "mc-current:~abscnt=\@@_get_mc_abs_cnt:=="
- ..
- tex.getattribute(luatexbase.attributes.g_@@_mc_cnt_attr)
- ..
- "~=>tag="
- ..
- tostring
- (ltx.@@.func.get_tag_from
- (tex.getattribute
- (luatexbase.attributes.g_@@_mc_type_attr)))
- ..
- "="
- ..
- tex.getattribute
- (luatexbase.attributes.g_@@_mc_type_attr)
- ,0
- )
- texio.write_nl("")
- }
- }
- }
- }
+ \bool_if:NTF \g_@@_mode_lua_bool
+ {
+ \int_compare:nNnTF
+ { -2147483647 }
+ =
+ {
+ \lua_now:e
+ {
+ tex.print
+ (tex.getattribute
+ (luatexbase.attributes.g_@@_mc_cnt_attr))
+ }
+ }
+ {
+ \lua_now:e
+ {
+ ltx.@@.trace.log
+ (
+ "mc-current:~no~MC~open,~current~abscnt
+ =\@@_get_mc_abs_cnt:"
+ ,0
+ )
+ texio.write_nl("")
+ }
+ }
+ {
+ \lua_now:e
+ {
+ ltx.@@.trace.log
+ (
+ "mc-current:~abscnt=\@@_get_mc_abs_cnt:=="
+ ..
+ tex.getattribute(luatexbase.attributes.g_@@_mc_cnt_attr)
+ ..
+ "~=>tag="
+ ..
+ tostring
+ (ltx.@@.func.get_tag_from
+ (tex.getattribute
+ (luatexbase.attributes.g_@@_mc_type_attr)))
+ ..
+ "="
+ ..
+ tex.getattribute
+ (luatexbase.attributes.g_@@_mc_type_attr)
+ ,0
+ )
+ texio.write_nl("")
+ }
+ }
+ }
{
\msg_note:nn{ tag }{ mc-current }
}
@@ -676,44 +673,44 @@
,struct-stack / show .code:n = \seq_show:N \g_@@_struct_tag_stack_seq
,struct-stack .default:n = show
}
-%</package>
+%</package>
% \end{macrocode}
% \end{macro}
% \begin{macro}{debug/structures (show-key)}
% The following key is available only if the tagpdf-debug package is loaded
-% and shows all structures starting with the one with the number
+% and shows all structures starting with the one with the number
% given by the key.
% \begin{macrocode}
%<*debug>
\keys_define:nn { @@ / show }
{
- ,debug/structures .code:n =
+ ,debug/structures .code:n =
{
\int_step_inline:nnn{#1}{\c@g_@@_struct_abs_int}
{
- \msg_term:nneeee
+ \msg_term:nneeee
{ tag/debug } { show-struct }
{ ##1 }
- {
- \prop_map_function:cN
- {g_@@_struct_debug_##1_prop}
- \msg_show_item_unbraced:nn
+ {
+ \prop_map_function:cN
+ {g_@@_struct_debug_##1_prop}
+ \msg_show_item_unbraced:nn
}
{ } { }
- \msg_term:nneeee
+ \msg_term:nneeee
{ tag/debug } { show-kids }
{ ##1 }
- {
- \seq_map_function:cN
- {g_@@_struct_debug_kids_##1_seq}
+ {
+ \seq_map_function:cN
+ {g_@@_struct_debug_kids_##1_seq}
\msg_show_item_unbraced:n
}
- { } { }
+ { } { }
}
- }
+ }
,debug/structures .default:n = 1
}
-%</debug>
+%</debug>
% \end{macrocode}
% \end{macro}
%
@@ -723,7 +720,7 @@
% or do a first step to apply tagpdf commands to document commands.
% This part should be regularly revisited to check if the code should go to a
% better place or can be improved.
-%
+%
% \begin{macrocode}
%<*package>
% \end{macrocode}
@@ -737,26 +734,26 @@
\hook_gput_code:nnn{tagpdf/finish/before}{tagpdf}{\tagstructend}
\keys_define:nn { @@ / setup}
- {
- activate/socket .bool_set:N = \l_@@_active_socket_bool,
+ {
+ activate/socket .bool_set:N = \l_@@_active_socket_bool,
activate .code:n =
{
\keys_set:nn { @@ / setup }
{ activate/mc,activate/tree,activate/struct,activate/socket }
- \tl_gset:Nn\g_@@_root_default_tl {#1}
+ \tl_gset:Nn\g_@@_root_default_tl {#1}
},
activate .default:n = Document
}
-
+
% \end{macrocode}
% \end{macro}
-%
+%
% \subsection{Structure destinations}
% Since TeXlive 2022 pdftex and luatex offer support for structure destinations
% and the pdfmanagement has backend support for. We activate them if
% structures are actually created.
-% Structure destinations are actually PDF 2.0 only but they don't harm in
-% older PDF and can improve html export.
+% Structure destinations are actually PDF 2.0 only but they don't harm in
+% older PDF and can improve html export.
% \begin{macrocode}
\AddToHook{begindocument/before}
{
@@ -764,7 +761,7 @@
{ \g_@@_active_struct_dest_bool }
{ \g_@@_active_struct_bool }
{
- \tl_set:Nn \l_pdf_current_structure_destination_tl
+ \tl_set:Nn \l_pdf_current_structure_destination_tl
{ {@@/struct}{\g_@@_struct_stack_current_tl }}
\pdf_activate_indexed_structure_destination:
}
@@ -776,14 +773,14 @@
% We need a luatex variant for |\pdffakespace|. This should probably go into
% the kernel at some time. We also provide a no-op version for dvi mode
% \begin{macrocode}
-\sys_if_engine_luatex:T
+\bool_if:NT \g_@@_mode_lua_bool
{
\NewDocumentCommand\pdffakespace { }
{
\@@_fakespace:
}
}
-\providecommand\pdffakespace{}
+\providecommand\pdffakespace{}
% \end{macrocode}
% \end{macro}
%
@@ -833,7 +830,7 @@
% \begin{macrocode}
\tl_if_exist:NF \l_@@_para_attr_class_tl
{\tl_new:N \l_@@_para_attr_class_tl }
-\tl_new:N \l_@@_para_main_attr_class_tl
+\tl_new:N \l_@@_para_main_attr_class_tl
% \end{macrocode}
% \end{macro}
@@ -845,7 +842,7 @@
% \@@_gincr_para_end_int:
% }
% The global para counter should be set through commands so
-% that \cs{tag_stop:} can stop them.
+% that \cs{tag_stop:} can stop them.
% \begin{macrocode}
\cs_new_protected:Npn \@@_gincr_para_main_begin_int:
{
@@ -884,7 +881,7 @@
\cs_set_protected:Npn \@@_gincr_para_end_int:
{
\int_gincr:N \g_@@_para_end_int
- }
+ }
}
\cs_new_protected:Npn \@@_stop_para_ints:
{
@@ -892,46 +889,21 @@
\cs_set_eq:NN \@@_gincr_para_begin_int: \prg_do_nothing:
\cs_set_eq:NN \@@_gincr_para_main_end_int: \prg_do_nothing:
\cs_set_eq:NN \@@_gincr_para_end_int: \prg_do_nothing:
- }
+ }
% \end{macrocode}
% \end{macro}
%
-% We want to be able to inspect the current para main structure, so
+% We want to be able to inspect the current para main structure, so
% we need a command to store its structure number
% \begin{macro}{\@@_para_main_store_struct:}
% \begin{macrocode}
-\cs_new:Npn \@@_para_main_store_struct:
+\cs_new:Npn \@@_para_main_store_struct:
{
- \tl_gset:Ne \g_@@_para_main_struct_tl {\int_use:N \c@g_@@_struct_abs_int }
+ \tl_gset:Ne \g_@@_para_main_struct_tl {\int_use:N \c@g_@@_struct_abs_int }
}
% \end{macrocode}
% \end{macro}
-% TEMPORARY FIX (2023-11-17). Until latex-lab is updated we must adapt a sec command:
-% \begin{macrocode}
-\AddToHook{package/latex-lab-testphase-sec/after}
- {
- \cs_set_protected:Npn \@kernel@tag@hangfrom #1
- {
- \tagstructbegin{tag=\l_@@_para_tag_tl}
- \@@_gincr_para_begin_int:
- \tagstructbegin{tag=Lbl}
- \setbox\@tempboxa
- \hbox
- {
- \bool_lazy_and:nnT
- {\tag_if_active_p:}
- {\g_@@_mode_lua_bool}
- {\tagmcbegin{tag=Lbl}}
- {#1}
- }
- \tag_suspend:n{hangfrom}
- \hangindent \wd\@tempboxa\noindent
- \tag_resume:n{hangfrom}
- \tagmcbegin{}\box\@tempboxa\tagmcend\tagstructend\tagmcbegin{}
- }
- }
-% \end{macrocode}
-% and one temporary adaptions for the block module:
+% temporary adaption for the block module:
% \begin{macrocode}
\AddToHook{package/latex-lab-testphase-block/after}
{
@@ -939,8 +911,7 @@
{
\tl_set:Nn \l_@@_para_attr_class_tl { \l_tag_para_attr_class_tl }
}
-}
-
+}
% \end{macrocode}
%\begin{macro}
% {
@@ -957,14 +928,14 @@
% paratagging-show (deprecated),
% paratag (deprecated),
% }
-% These keys enable/disable locally paratagging.
+% These keys enable/disable locally paratagging.
% Paragraphs are typically tagged with two structure: A main structure
% around the whole paragraph, and inner structures around the various chunks.
% Debugging can be
-% activated locally with |debug/show=para|, this can affect the typesetting
+% activated locally with |debug/show=para|, this can affect the typesetting
% as the small numbers
% are boxes and they have a (small) height. Debugging can be deactivated
-% with |debug/show=paraOff|
+% with |debug/show=paraOff|
% The |para/tag| key sets the tag used by
% the inner structure, |para/maintag| the tag of the outer structure,
% both can also be changed with |\tag_tool:n|
@@ -978,7 +949,7 @@
para/maintag .tl_set:N = \l_@@_para_main_tag_tl,
para/flattened .bool_set:N = \l_@@_para_flattened_bool
}
-\keys_define:nn { tag / tool}
+\keys_define:nn { tag / tool}
{
para/tagging .bool_set:N = \l_@@_para_bool,
para/tag .tl_set:N = \l_@@_para_tag_tl,
@@ -994,7 +965,7 @@
paratagging-show .bool_set:N = \l_@@_para_show_bool,
paratag .tl_set:N = \l_@@_para_tag_tl
}
-\keys_define:nn { tag / tool}
+\keys_define:nn { tag / tool}
{
para .bool_set:N = \l_@@_para_bool,
paratag .tl_set:N = \l_@@_para_tag_tl,
@@ -1003,13 +974,13 @@
}
% \end{macrocode}
% \end{macro}
-% Helper command for debugging:
+% Helper command for debugging:
% \begin{macrocode}
-\cs_new_protected:Npn \@@_check_para_begin_show:nn #1 #2
+\cs_new_protected:Npn \@@_check_para_begin_show:nn #1 #2
%#1 color, #2 prefix
{
\bool_if:NT \l_@@_para_show_bool
- {
+ {
\tag_mc_begin:n{artifact}
\llap{\color_select:n{#1}\tiny#2\int_use:N\g_@@_para_begin_int\ }
\tag_mc_end:
@@ -1020,7 +991,7 @@
%#1 color, #2 prefix
{
\bool_if:NT \l_@@_para_show_bool
- {
+ {
\tag_mc_begin:n{artifact}
\rlap{\color_select:n{#1}\tiny\ #2\int_use:N\g_@@_para_end_int}
\tag_mc_end:
@@ -1036,7 +1007,7 @@
% It is possible that we will need more variants, so
% we setup a socket so that the code can be easily switched.
% This code should move into lttagging, so we add a test for
-% the transition.
+% the transition.
% \begin{macrocode}
\str_if_exist:cF { l__socket_tagsupport/para/begin_plug_str }
{
@@ -1054,13 +1025,13 @@
{
tag=\l_@@_para_main_tag_tl,
}
- \@@_para_main_store_struct:
+ \@@_para_main_store_struct:
}
\@@_gincr_para_begin_int:
\tag_struct_begin:n {tag=\l_@@_para_tag_tl}
\@@_check_para_begin_show:nn {green}{}
\tag_mc_begin:n {}
- }
+ }
}
\socket_new_plug:nnn{tagsupport/para/begin}{block}
{
@@ -1080,7 +1051,7 @@
tag=\l_@@_para_main_tag_tl,
attribute-class=\l_@@_para_main_attr_class_tl,
}
- \@@_para_main_store_struct:
+ \@@_para_main_store_struct:
}
}
\@@_gincr_para_begin_int:
@@ -1090,10 +1061,10 @@
tag=\l_@@_para_tag_tl
,attribute-class=\l_@@_para_attr_class_tl
}
- \@@_check_para_begin_show:nn {green}{\PARALABEL}
+ \@@_check_para_begin_show:nn {green}{\PARALABEL}
\tag_mc_begin:n {}
}
- }
+ }
}
% \end{macrocode}
% there was no real difference between the original and
@@ -1114,7 +1085,7 @@
\@@_gincr_para_main_end_int:
\tag_struct_end:
}
- }
+ }
}
}
% \end{macrocode}
@@ -1161,7 +1132,7 @@
\tag_if_active:F
{
\msg_redirect_name:nnn { tag } { para-hook-count-wrong } { warning }
- }
+ }
\int_compare:nNnF {\g_@@_para_main_begin_int}={\g_@@_para_main_end_int}
{
\msg_error:nneee
@@ -1179,51 +1150,55 @@
{\int_use:N\g_@@_para_begin_int}
{\int_use:N\g_@@_para_end_int}
{text}
- }
+ }
}
% \end{macrocode}
+% \subsection{output routine stuff}
% We need at least the new-or-1 code.
-% In generic mode we also must insert the code to finish the MC-chunks
+% In generic mode we also must insert the code to finish the MC-chunks
+% This part here can go in June 2025
% \begin{macrocode}
\@ifpackageloaded{footmisc}
{\PackageWarning{tagpdf}{tagpdf~has~been~loaded~too~late!}} %
{\RequirePackage{latex-lab-testphase-new-or-1}}
-
+
\AddToHook{begindocument/before}
{
- \providecommand\@kernel@tagsupport@@@@makecol{}
- \providecommand\@kernel@before@cclv{}
\bool_if:NF \g_@@_mode_lua_bool
{
\cs_if_exist:NT \@kernel@before@footins
{
\tl_put_right:Nn \@kernel@before@footins
{ \tag_mc_add_missing_to_stream:Nn \footins {footnote} }
- \tl_put_right:Nn \@kernel@before@cclv
- {
- \@@_check_typeout_v:n {====>~In~\token_to_str:N \@makecol\c_space_tl\the\c@page}
- \tag_mc_add_missing_to_stream:Nn \@cclv {main}
- }
\tl_put_right:Nn \@kernel@tagsupport@@@@makecol
{
\@@_check_typeout_v:n {====>~In~\token_to_str:N \@makecol\c_space_tl\the\c@page}
\tag_mc_add_missing_to_stream:Nn \@outputbox {main}
- }
- \tl_if_exist:NT \@mult@ptagging@hook
- {
- \tl_put_right:Nn \@mult@ptagging@hook
- {
- \@@_check_typeout_v:n {====>~In~\string\page@sofar}
- \process@cols\mult@firstbox
- {
- \tag_mc_add_missing_to_stream:Nn \count@ {multicol}
- }
- \tag_mc_add_missing_to_stream:Nn \mult@rightbox {multicol}
- }
- }
+ }
}
}
}
+
+% \end{macrocode}
+% If the new OR is there, we use it
+% \begin{macrocode}
+\str_if_exist:cT { l__socket_tagsupport/build/column/outputbox_plug_str }
+ {
+ \NewSocketPlug{tagsupport/build/column/outputbox}{tagpdf}
+ {
+ \@@_check_typeout_v:n { ====>~In~\token_to_str:N \@makecol
+ \c_space_tl\the\c@page }
+ \tag_mc_add_missing_to_stream:Nn \@outputbox {main}
+ }
+ \NewSocketPlug{tagsupport/build/column/footins}{tagpdf}
+ { \tag_mc_add_missing_to_stream:Nn \footins {footnote} }
+
+ \bool_if:NF \g_@@_mode_lua_bool
+ {
+ \AssignSocketPlug{tagsupport/build/column/outputbox}{tagpdf}
+ \AssignSocketPlug{tagsupport/build/column/footins}{tagpdf}
+ }
+ }
%</package>
% \end{macrocode}
% \begin{macro}
@@ -1265,7 +1240,7 @@
% \end{macrocode}
% \end{macro}
% \subsection{Language support}
-%
+%
% With the following key the lang variable is set. All structures in the current group will
% then set this lang variable.
% \begin{macro}{test/lang (setup-key)}
@@ -1287,7 +1262,9 @@
\cs_new_protected:Npn\@@_hook_kernel_after_head:{}
\cs_new_protected:Npn\@@_hook_kernel_before_foot:{}
\cs_new_protected:Npn\@@_hook_kernel_after_foot:{}
-
+% \end{macrocode}
+% This can go once the new OR is active (June 2025)
+% \begin{macrocode}
\AddToHook{begindocument}
{
\cs_if_exist:NT \@kernel@before@head
@@ -1298,7 +1275,31 @@
\tl_put_left:Nn \@kernel@after@foot {\@@_hook_kernel_after_foot:}
}
}
-
+% \end{macrocode}
+% If the new page sockets exist, we use them.
+% \begin{macrocode}
+\str_if_exist:cT { l__socket_tagsupport/build/page/footer_plug_str }
+ {
+ \NewSocketPlug{tagsupport/build/page/header}{tagpdf}
+ {
+ \@@_hook_kernel_before_head:
+ #2
+ \@@_hook_kernel_after_head:
+ }
+
+ \AssignSocketPlug{tagsupport/build/page/header}{tagpdf}
+ \NewSocketPlug{tagsupport/build/page/footer}{tagpdf}
+ {
+ \@@_hook_kernel_before_foot:
+ #2
+ \@@_hook_kernel_after_foot:
+ }
+ \AssignSocketPlug{tagsupport/build/page/footer}{tagpdf}
+ }
+
+% \end{macrocode}
+%
+% \begin{macrocode}
\bool_new:N \g_@@_saved_in_mc_bool
\cs_new_protected:Npn \@@_exclude_headfoot_begin:
{
diff --git a/macros/latex/contrib/tagpdf/tagpdf.dtx b/macros/latex/contrib/tagpdf/tagpdf.dtx
index 4f7e2c0c40..6c3b7d0ce5 100644
--- a/macros/latex/contrib/tagpdf/tagpdf.dtx
+++ b/macros/latex/contrib/tagpdf/tagpdf.dtx
@@ -47,7 +47,7 @@
% }^^A
% }
%
-% \date{Version 0.99l, released 2025-01-12}
+% \date{Version 0.99m, released 2025-02-17}
% \maketitle%
%
% \begin{documentation}
@@ -153,7 +153,7 @@
% \begin{macrocode}
%<@@=tag>
%<*package>
-\ProvidesExplPackage {tagpdf} {2025-01-12} {0.99l}
+\ProvidesExplPackage {tagpdf} {2025-02-17} {0.99m}
{ LaTeX kernel code for PDF tagging }
\bool_if:nF
@@ -179,7 +179,7 @@
% \end{macrocode}
%<*debug>
% \begin{macrocode}
-\ProvidesExplPackage {tagpdf-debug} {2025-01-12} {0.99l}
+\ProvidesExplPackage {tagpdf-debug} {2025-02-17} {0.99m}
{ debug code for tagpdf }
\@ifpackageloaded{tagpdf}{}{\PackageWarning{tagpdf-debug}{tagpdf~not~loaded,~quitting}\endinput}
% \end{macrocode}
@@ -202,29 +202,18 @@
% we define a base package with dummy functions
% \begin{macrocode}
%<*base>
-\ProvidesExplPackage {tagpdf-base} {2025-01-12} {0.99l}
+\ProvidesExplPackage {tagpdf-base} {2025-02-17} {0.99m}
{part of tagpdf - provide base, no-op versions of the user commands }
%</base>
% \end{macrocode}
%\section{Package options}
-% There are only two documented options to switch for luatex between generic and luamode,
-% TODO try to get rid of them.
-% The option \texttt{disabledelayedshipout} is only temporary to be able to debug
-% problem with the new shipout keyword if needed.
+% The boolean is kept for now for compability, can go in 2026.
% \begin{macrocode}
%<*package>
-\bool_new:N\g_@@_mode_lua_bool
-\bool_new:N\g_@@_delayed_shipout_bool
-\bool_lazy_and:nnT
- { \bool_if_exist_p:N \l__pdfmanagement_delayed_shipout_bool }
- { \l__pdfmanagement_delayed_shipout_bool }
- {
- \bool_gset_true:N\g_@@_delayed_shipout_bool
- }
-\DeclareOption {luamode} { \sys_if_engine_luatex:T { \bool_gset_true:N \g_@@_mode_lua_bool } }
-\DeclareOption {genericmode}{ \bool_gset_false:N\g_@@_mode_lua_bool }
-\DeclareOption {disabledelayedshipout}{ \bool_gset_false:N\g_@@_delayed_shipout_bool }
-\ExecuteOptions{luamode}
+\bool_new:N\g_@@_mode_lua_bool
+\sys_if_engine_luatex:T {\bool_gset_true:N \g_@@_mode_lua_bool}
+\DeclareOption {luamode} { }
+\DeclareOption {genericmode}{ }
\ProcessOptions
% \end{macrocode}
% \section{Packages}
diff --git a/macros/latex/contrib/tagpdf/tagpdf.pdf b/macros/latex/contrib/tagpdf/tagpdf.pdf
index 70482db902..dd8b74f617 100644
--- a/macros/latex/contrib/tagpdf/tagpdf.pdf
+++ b/macros/latex/contrib/tagpdf/tagpdf.pdf
Binary files differ
diff --git a/macros/latex/contrib/tagpdf/tagpdf.tex b/macros/latex/contrib/tagpdf/tagpdf.tex
index 53a25466a8..91806189ed 100644
--- a/macros/latex/contrib/tagpdf/tagpdf.tex
+++ b/macros/latex/contrib/tagpdf/tagpdf.tex
@@ -16,8 +16,8 @@
}
\DebugBlocksOff
\makeatletter
-\def\UlrikeFischer@package@version{0.99l}
-\def\UlrikeFischer@package@date{2025-01-12}
+\def\UlrikeFischer@package@version{0.99m}
+\def\UlrikeFischer@package@date{2025-02-17}
\makeatother
\documentclass[bibliography=totoc,a4paper]{article}
@@ -156,7 +156,7 @@ tagging should become part of the \LaTeX\ kernel.
The code has been written so that it can be added as module to the \LaTeX{}
-kernel itself if it turns out to be usable. It therefore avoid to patch
+kernel itself if it turned out to be usable. It therefore avoid to patch
commands from other packages. It was also not an aim of the package to
develop patches to directly enable tagging in other packages. While in the end changes to various commands in many
classes and packages will be needed to automatically get tagged \PDF{} files, these changes
@@ -185,7 +185,7 @@ Please also check the github site and latex-lab for new examples and improvement
While the package is named \pkg{tagpdf} the goal is also \emph{accessible}
\PDF{}-files. Tagging is \emph{one} (the most difficult) requirement for
accessibility but there are others. I will mention some later on in this
-documentation, and -- if sensible -- I will also try to add code, keys or
+documentation, and -- if sensible -- also add code, keys or
tips for them.
So the name of the package is a bit wrong. As excuse I can only say that it
@@ -194,7 +194,7 @@ is short and easy to pronounce (and of course, it was always meant to be tempora
\subsection{Engines and modes}
- Theoretically, the package works with all engines, but the xelatex and the
+Theoretically, the package works with all engines, but the xelatex and the
latex-dvips-route are basically untested and they also don't support real
space glyphs so I don't recommend them. lualatex is the most powerful and
safe modus and should be used for new documents, it is slower than pdflatex
@@ -204,7 +204,8 @@ for the tagging.
The package has two modes: the \emph{generic mode} which should work in
theory with every engine and the \emph{lua mode} which works only with
-lualatex and (since version 0.98k) with dvilualatex.
+lualatex and (since version 0.98k) with dvilualatex. Since version 0.99m,
+the lua mode is forced if luatex is detected, otherwise generic mode is used.
I implemented the generic mode first. Mostly because my \TeX\ skills are much
better than my lua skills and I wanted to get the \TeX\ side right before
@@ -238,16 +239,16 @@ cost through the PDF association.
it knows more structure types, it allows to add associated files to
structures---these are small, embedded files that can, for example, contain
the mathML or source code of an equation---, it knows structure destinations,
-which allows to link to a structure.
+which allows to link to a structure. It knows the MathML namespace.
-\PDF{}~2.0 features are currently (end of 2023) not well supported by
-\PDF~consumer. No PDF viewer (including Acrobat) for example can handle name
-spaces and associated files. The PDF Accessibility Checker (PAC) even crashes
-if one tries to load a \PDF{} 2.0 file, and pdftk will create a \PDF{}~1.0
-from it.
+\LaTeX{} therefore targets \PDF{} 2.0 and tagpdf has support for
+associated files, for name spaces and other \PDF{} 2.0 features.
-Nevertheless \LaTeX{} targets \PDF{} 2.0, tagpdf has added support for
-associated files, for name spaces and other \PDF{} 2.0 features. We recommend
+\PDF{}~2.0 features are currently (begin of 2025) still not well supported by
+\PDF~consumer, but some progress has been made. Foxit can handle MathML associated files
+and to some extend MathML structure elements and
+together with development versions of NVDA and MathCat reading of equations is already quite good. The PDF Accessibility Checker (PAC) no longer crashes
+if one tries to load a \PDF{} 2.0 file. We recommend
to use \PDF{} 2.0 if possible and then to complain to the PDF{} consumer if
something doesn't work.
@@ -261,7 +262,6 @@ incompatibilities.
\subsection{Validation}
-
\PDF{}'s created with the commands of this package must be validated:
\begin{itemize}
@@ -280,17 +280,17 @@ One must check how good the accessibility is \emph{practically}.
\end{itemize}
-Syntax validation and formal standard validation can be done for example with
-preflight of the (non-free) Adobe Acrobat. It can also be done
-(only for PDF 1.7 and older) also with the
-free \PDF{} Accessibility Checker (PAC~2024) \parencite{pac2024}. There is also
-the validator veraPDF \parencite{verapdf} which can also handle PDF 2.0 files.
+Syntax validation and formal standard validation can be done with the
+validator veraPDF \parencite{verapdf} which can also handle PDF 2.0 files.
+Other options (only for PDF 1.7 and older) are preflight of the (non-free) Adobe Acrobat and the free \PDF{} Accessibility Checker (PAC~2024) \parencite{pac2024}.
A quite useful tool
is \enquote{Next Generation PDF} \parencite{ngpdf}, a browser application
which converts a tagged PDF to html, allows to inspect its structure and also
to edit the structure. For PDF~2.0 files there is also a checker based on the
Arlington model from veraPDF.
+A tool developed by the \LaTeX{} team allows to extract the structure as XML and to validate it against a schema. This can be tested as \url{https://texlive.net/showtags}.
+
Practical validation is naturally the more complicated part.
It needs screen reader, users which actually knows how to handle them,
can test documents and can report where a \PDF{} has real accessibility problems.
@@ -302,7 +302,7 @@ Sadly validators can not be always trusted.
As an example for an reason that I don't understand the adobe preflight
don't like the list structure \texttt{L}.
It is also possible that validators contradict: that the one says everything is okay,
-while the other complains.
+while the other complains. Generally when in doubt I recommend to use and trust verapdf.
\subsection{Examples wanted!}
@@ -444,17 +444,9 @@ false.
The package has two different modes: The \textbf{generic mode} works
(in theory, currently only fully tested with pdflatex) probably with
all engines, the \textbf{lua mode} only with lualatex. The differences
-between both modes will be described later. The mode can be set with
-package options:
-
-\DescribeKey{luamode}
+between both modes will be described later.
-This is the default mode. It will use the generic mode if the document
-is processed with pdflatex and the lua mode with lualatex.
-
-\DescribeKey{genericmode}
-
-This will force the generic mode for all engines.
+Starting with version 0.99m the mode is set automatically (lua mode for luatex, generic mode otherwise). The package options do nothing anymore and will be remove in future versions.
\subsection{Setup and activation}\label{ssec:setup}
@@ -899,26 +891,7 @@ This sounds easy. But there are quite a number of traps, mostly with pdfLaTeX:
mark these text chunks correctly one has to analyze the code creating
such content to find suitable places to inject the literals.
- \item The literals are inserted directly and not at shipout. This means
- that due to the asynchronous page breaking of \TeX\ the MCID-number
- can be wrong even if the counter is reset at every page. This package
- uses in generic mode a label-ref-system to get around this problem.
- This sadly means that often at least three compilations are needed
- until everything has settled down.
-
- It can actually be worse: If the text is changed after the MCID-numbers
- have been assigned, and a new mc-chunk is inserted in the middle of the
- page, then all the numbers have to be recalculated and that requires
- again a number of compilations until it really settles down again.
- Internal references are especially problematic here, as the first
- compilation typically creates a non-link |??|, and only the second
- inserts the structure and the new mc. When the reference system in \LaTeX\
- will be extended, care will be taken to ensure that already the dummy
- text builds a chunk. Until then the advice is to first compile the
- document and resolve all cross-reference and to activate tagging only at
- the end.
-
-
+
\item There exist environments which process their content more than once
-- examples are \texttt{align} and \texttt{tabularx}.
So one has to check for doublets and holes in the counting system.
@@ -1869,6 +1842,11 @@ The key-val list understands the following keys:
\item[\PrintKeyName{E}] This key sets the |/E| key, the expanded
form of an abbreviation or an acronym (I couldn't think of a
better name, so I sticked to E).
+
+ \item[\PrintKeyName{phoneme}] This key sets the |/Phoneme| key, a pronunciation hint. The value should be a IPA text (the PDF spec
+ allows other variants but this not yet implemented).
+ This is a new key from PDF 2.0 but as far as I know not used by any
+ viewer.
\end{description}
\begin{docCommands}
@@ -3091,6 +3069,12 @@ is then used automatically if the new engines are detected.
Deprecated |\tag_start:|, |\tag_stop:|, |\tag_stop:n| and
|\tag_start:n| in favor of |\tag_suspend:n| and |\tag_resume:n|.
+
+\subsection{Changes in version 0.99m}
+
+Removed/deactivated package options |luamode| and |genericmode|.
+Added first support for pronunciation hints, the |phoneme| key.
+
\printbibliography[heading=bibintoc]
diff --git a/macros/latex/contrib/tagpdf/tagpdfdocu-patches.sty b/macros/latex/contrib/tagpdf/tagpdfdocu-patches.sty
index ab23a61e24..22687ff757 100644
--- a/macros/latex/contrib/tagpdf/tagpdfdocu-patches.sty
+++ b/macros/latex/contrib/tagpdf/tagpdfdocu-patches.sty
@@ -1,5 +1,5 @@
%\RequirePackage[enable-debug]{expl3}[2018/06/14]
-\ProvidesExplPackage {tagpdfdocu-patches} {2025-01-12} {0.99l}
+\ProvidesExplPackage {tagpdfdocu-patches} {2025-02-17} {0.99m}
{patches/commands for the tagpdf documentation}
\RequirePackage{etoolbox,xpatch}
diff --git a/macros/latex/contrib/textcase/textcase.dtx b/macros/latex/contrib/textcase/textcase.dtx
index 3d8ab3997e..37458dee1d 100644
--- a/macros/latex/contrib/textcase/textcase.dtx
+++ b/macros/latex/contrib/textcase/textcase.dtx
@@ -1,6 +1,6 @@
% \iffalse
%% Source File: textcase.dtx
-%% Copyright 1997 1998 2019 2022 2023 David Carlisle
+%% Copyright 1997 1998 2019 2022 2023 2025 David Carlisle
%%
%% This file may be distributed under the terms of the LPPL.
%% See 00readme.txt for details.
@@ -13,7 +13,7 @@
%<driver> \ProvidesFile{textcase.drv}
% \fi
% \ProvidesFile{textcase.dtx}
- [2023/07/27 v1.04 Text only upper/lower case changing (DPC)]
+ [2025/02/16 v1.05 Text only upper/lower case changing (DPC)]
%
% \iffalse
%<*driver>
@@ -253,17 +253,25 @@
}
\reserved@a { Upper }
\reserved@a { Lower }
+% \end{macrocode}
+% Internal change to \verb|\@@text@case@aux| requires modifed arguments in new formats
+% \changes{v1.05}{2025/02/16}
+% {changed internal in new formats}
+% \begin{macrocode}
+\IfFormatAtLeastTF{2024-11-12}{\def\textcase@case{case}}{\def\textcase@case{}}
+% \end{macrocode}
+% \begin{macrocode}
\cs_new_protected:cpn {
MakeTextLowercase \c_space_tl \c_space_tl \c_space_tl } [#1] #2
{%{
\let \OE \oe
- \@@text@case@aux { lower } {#1} {#2}
+ \@@text@case@aux { lower \textcase@case } {#1} {#2}
}%}
\cs_new_protected:cpn {
MakeTextUppercase \c_space_tl \c_space_tl \c_space_tl } [#1] #2
{%{
\let \oe \OE
- \@@text@case@aux { upper } {#1} {#2}
+ \@@text@case@aux { upper \textcase@case } {#1} {#2}
}%}
\ExplSyntaxOff
% \end{macrocode}
diff --git a/macros/latex/contrib/textcase/textcase.pdf b/macros/latex/contrib/textcase/textcase.pdf
index 9cc4365d35..a8d08b321b 100644
--- a/macros/latex/contrib/textcase/textcase.pdf
+++ b/macros/latex/contrib/textcase/textcase.pdf
Binary files differ
diff --git a/macros/luatex/latex/luamml/CHANGELOG.md b/macros/luatex/latex/luamml/CHANGELOG.md
new file mode 100644
index 0000000000..705d0c21c8
--- /dev/null
+++ b/macros/luatex/latex/luamml/CHANGELOG.md
@@ -0,0 +1,19 @@
+# Changelog
+All notable changes to the `luamml` package since the
+2025-02-17 will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+this project uses date-based 'snapshot' version identifiers.
+## [Unreleased]
+
+## 2025-02-17
+
+### Changed
+- Ulrike Fischer, 2024-11-29
+ luamml-structelemwriter.lua: moved the actualtext for e.g. stretched braces from the structure element to the mc-chunk.
+
+- Ulrike Fischer, 2024-03-03
+ luamml.dtx: add plug for mbox socket to correctly annotate them in math.
+
+- Ulrike Fischer, 2024-11-29
+ luamml-structelemwriter.lua: use structnum instead of label when stashing.
diff --git a/macros/luatex/latex/luamml/luamml-amsmath.lua b/macros/luatex/latex/luamml/luamml-amsmath.lua
index 2b74265501..26b157b4c7 100644
--- a/macros/luatex/latex/luamml/luamml-amsmath.lua
+++ b/macros/luatex/latex/luamml/luamml-amsmath.lua
@@ -3,6 +3,7 @@ local make_root = require'luamml-convert'.make_root
local save_result = require'luamml-tex'.save_result
local store_column = require'luamml-table'.store_column
local store_tag = require'luamml-table'.store_tag
+local store_notag = require'luamml-table'.store_notag
local get_table = require'luamml-table'.get_table
local set_row_attribute = require'luamml-table'.set_row_attribute
local to_text = require'luamml-lr'
@@ -125,9 +126,9 @@ funcid = luatexbase.new_luafunction'__luamml_amsmath_set_tag:'
token.set_lua('__luamml_amsmath_set_tag:', funcid, 'protected')
lua.get_functions_table()[funcid] = function()
if not last_tag then
- texio.write_nl'WARNING: Tag extraction failed'
- return
+ store_notag({[0] = 'mtd',''})
+ else
+ store_tag({[0] = 'mtd', last_tag})
+ last_tag = nil
end
- store_tag({[0] = 'mtd', last_tag})
- last_tag = nil
end
diff --git a/macros/luatex/latex/luamml/luamml-array.lua b/macros/luatex/latex/luamml/luamml-array.lua
index 9a7b3581f2..f1fd7c56ef 100644
--- a/macros/luatex/latex/luamml/luamml-array.lua
+++ b/macros/luatex/latex/luamml/luamml-array.lua
@@ -54,7 +54,7 @@ end
local saved_array
-funcid = luatexbase.new_luafunction'__luamml_array_finalize_array:'
+funcid = luatexbase.new_luafunction'__luamml_array_save_array:'
token.set_lua('__luamml_array_save_array:', funcid)
lua.get_functions_table()[funcid] = function()
-- TODO: Error handling etc.
diff --git a/macros/luatex/latex/luamml/luamml-convert.lua b/macros/luatex/latex/luamml/luamml-convert.lua
index fe529debc0..abb6615228 100644
--- a/macros/luatex/latex/luamml/luamml-convert.lua
+++ b/macros/luatex/latex/luamml/luamml-convert.lua
@@ -370,7 +370,8 @@ local function radical_to_table(radical, sub, cur_style, text_families)
elem, core = {[0] = 'msqrt', nucleus, }, nil
elseif kind == 'uroot' then
-- FIXME: Check that this is really a root
- elem, core = {[0] = 'msqrt', nucleus, kernel_to_table(radical.degree, 7, text_families)}, nil
+ -- UF 2024-12-04: force use of only one return value
+ elem, core = {[0] = 'mroot', nucleus, (kernel_to_table(radical.degree, 7, text_families))}, nil
elseif kind == 'uunderdelimiter' then
elem, core = {[0] = 'munder', left, nucleus}, left
elseif kind == 'uoverdelimiter' then
diff --git a/macros/luatex/latex/luamml/luamml-demo.sty b/macros/luatex/latex/luamml/luamml-demo.sty
index 9aabb38719..e3fef941b1 100644
--- a/macros/luatex/latex/luamml/luamml-demo.sty
+++ b/macros/luatex/latex/luamml/luamml-demo.sty
@@ -1,5 +1,5 @@
\NeedsTeXFormat{LaTeX2e}
-\ProvidesExplPackage{luamml-demo}{2024-10-30}{0.2.0}{Reasonable default definitions for luamml}
+\ProvidesExplPackage{luamml-demo}{2025-02-17}{0.3.0}{Reasonable default definitions for luamml}
\sys_if_engine_luatex:F {
\msg_new:nnn {luamml-demo} {pdftex-option-ignored} {Option~`#1'~is~being~ignored~in~pdfTeX~mode.}
diff --git a/macros/luatex/latex/luamml/luamml-patches-amsmath.sty b/macros/luatex/latex/luamml/luamml-patches-amsmath.sty
index 0b09bc7843..f59d2ee218 100644
--- a/macros/luatex/latex/luamml/luamml-patches-amsmath.sty
+++ b/macros/luatex/latex/luamml/luamml-patches-amsmath.sty
@@ -1,4 +1,4 @@
-\ProvidesExplPackage {luamml-patches-amsmath} {2024-10-30} {0.2.0}
+\ProvidesExplPackage {luamml-patches-amsmath} {2025-02-17} {0.3.0}
{Feel free to add a description here}
\lua_now:n { require'luamml-amsmath' }
@@ -7,411 +7,415 @@
% But they are almost identical to the original and only
% add luamml commands in appropriate places, so they would
% mostly disappear if there were enough hooks in amsmath.
-
-% aligned and friends
-\cs_set:Npn \start@aligned #1#2 {
- \RIfM@
- \else
- \nonmatherr@ { \begin { \@currenvir } }
- \fi
- \savecolumn@ % Assumption: called inside a group
- \luamml_annotate:en {
- core = false
- } {
- \alignedspace@left
- }
- \ams@start@box {#1} \bgroup
- \maxfields@ #2 \relax
- \ifnum \maxfields@ > \m@ne
- \multiply \maxfields@ \tw@
- \let \math@cr@@@ \math@cr@@@alignedat
- \alignsep@ \z@skip
- \else
- \let \math@cr@@@ \math@cr@@@aligned
- \alignsep@ \minalignsep
- \fi
- \Let@ \chardef \dspbrk@context \@ne
- \default@tag
- \spread@equation % no-op if already called
- \global \column@ \z@
- \ialign \bgroup
- & \column@plus
- \hfil
- \strut@
- $
- \m@th
- \displaystyle
- {##}
- \luamml_save:nNn {} \displaystyle {mtd}
- $
- \__luamml_amsmath_add_last_to_row:
- \tabskip \z@skip
- & \column@plus
- $
- \m@th
- \displaystyle
- {
- {}
- ##
- }
- \luamml_save:nNn {} \displaystyle {mtd}
- $
- \__luamml_amsmath_add_last_to_row:
- \hfil
- \tabskip\alignsep@
- \crcr
- \ams@return@opt@arg
-}
-
-\renewcommand \gathered [1] [c] {
- \RIfM@
- \else
- \nonmatherr@ { \begin {gathered} }
- \fi
- \luamml_annotate:en {
- core = false
- } {
- \alignedspace@left
- }
- \ams@start@box {#1} \bgroup
- \Let@
- \chardef \dspbrk@context \@ne
- \restore@math@cr
- \spread@equation
- \ialign \bgroup
- \hfil
- \strut@
- $
- \m@th
- \displaystyle
- ##
- \luamml_save:nNn {} \displaystyle {mtd}
- $
- \__luamml_amsmath_add_last_to_row:
- \hfil
- \crcr
- \ams@return@opt@arg
-}
-
-\cs_set:Npn \endaligned {
- \crcr
- \__luamml_amsmath_save_inner_table:n \@currenvir
- \egroup
- \restorecolumn@
- \egroup
- \__luamml_amsmath_finalize_inner_table:
-}
-
-% gather
-\cs_set:Npn \gather@ #1 {
- \ingather@true
- \let \split \insplit@
- \let \tag \tag@in@align
- \let \label \label@in@display
- \chardef \dspbrk@context \z@
- \intertext@ \displ@y@ \Let@
- \let \math@cr@@@ \math@cr@@@gather
- \gmeasure@ {#1}
- \global \shifttag@false
- \tabskip \z@skip
- \global \row@ \@ne
- \halign to \displaywidth \bgroup
- \strut@
- \setboxz@h {
- $
- \m@th
- \displaystyle
- {##}
- \luamml_save:nNn {} \displaystyle {mtd}
- $
- }
- \__luamml_amsmath_add_box_to_row:
- \calc@shift@gather
- \set@gather@field
- \tabskip\@centering
- &
- \setboxz@h {
- \strut@
- {##}
- }
- \dim_compare:nNnF {0pt} = {
- \box_wd:N \c_zero_int
- } {
- \__luamml_amsmath_set_tag:
- }
- \place@tag@gather
- \tabskip \iftagsleft@
- \gdisplaywidth@
+\IfPackageAtLeastTF{latex-lab-testphase-math}{2025-01-24}
+ {}
+ {
+ \PackageInfo{luamml}{patching~\string\start@aligned}
+ % aligned and friends
+ \cs_set:Npn \start@aligned #1#2 {
+ \RIfM@
\else
- \z@skip
- \span \fi
- \crcr
- #1
-}
-
-\cs_new_eq:NN \__luamml_amsmath_original_gmeasure:n \gmeasure@
-\cs_set:Npn \gmeasure@ #1 {
- \exp_last_unbraced:Nno
- \use_ii_i:nn
- { \luamml_ignore: }
- { \__luamml_amsmath_original_gmeasure:n {#1} }
-}
-
-\cs_set:Npn \endgather {
- \math@cr
- \black@ \totwidth@
- \__luamml_amsmath_finalize_table:n {gather}
- \egroup
- $$
- \ignorespacesafterend
-}
-
-% align and friends
-\cs_set:Npn \align@preamble {
- &
- \hfil
- \strut@
- \setboxz@h {
- \@lign
- $
- \m@th
- \displaystyle
- {##}
- \ifmeasuring@
- \luamml_ignore:
+ \nonmatherr@ { \begin { \@currenvir } }
+ \fi
+ \savecolumn@ % Assumption: called inside a group
+ \UseTaggingSocket{ math/luamml/annotate/false } {}{ \alignedspace@left }
+ \ams@start@box {#1} \bgroup
+ \maxfields@ #2 \relax
+ \ifnum \maxfields@ > \m@ne
+ \multiply \maxfields@ \tw@
+ \let \math@cr@@@ \math@cr@@@alignedat
+ \alignsep@ \z@skip
\else
- \luamml_save:nNn {} \displaystyle {mtd}
+ \let \math@cr@@@ \math@cr@@@aligned
+ \alignsep@ \minalignsep
\fi
- $
+ \Let@ \chardef \dspbrk@context \@ne
+ \default@tag
+ \spread@equation % no-op if already called
+ \global \column@ \z@
+ \ialign \bgroup
+ & \column@plus
+ \hfil
+ \strut@
+ $
+ \m@th
+ \displaystyle
+ {##}
+ \UseTaggingSocket{math/luamml/save/nNn}{ {} \displaystyle {mtd}}
+ $
+ \UseTaggingSocket{math/luamml/mtable/finalizecol}{last}
+ \tabskip \z@skip
+ & \column@plus
+ $
+ \m@th
+ \displaystyle
+ {
+ {}
+ ##
+ }
+ \UseTaggingSocket{math/luamml/save/nNn}{ {} \displaystyle {mtd}}
+ $
+ \UseTaggingSocket{math/luamml/mtable/finalizecol}{last}
+ \hfil
+ \tabskip\alignsep@
+ \crcr
+ \ams@return@opt@arg
}
- \ifmeasuring@
- \savefieldlength@
- \else
- \__luamml_amsmath_add_box_to_row:
- \fi
- \set@field
- \tabskip\z@skip
- &
- \setboxz@h {
- \@lign
- $
- \m@th
- \displaystyle
- {
- {}
- ##
- }
- \ifmeasuring@
- \luamml_ignore:
- \else
- \luamml_save:nNn {} \displaystyle {mtd}
- \fi
- $
+ \PackageInfo{luamml}{patching~gathered}
+ \renewcommand \gathered [1] [c] {
+ \RIfM@
+ \else
+ \nonmatherr@ { \begin {gathered} }
+ \fi
+ \UseTaggingSocket{ math/luamml/annotate/false } {}{ \alignedspace@left }
+ \ams@start@box {#1} \bgroup
+ \Let@
+ \chardef \dspbrk@context \@ne
+ \restore@math@cr
+ \spread@equation
+ \ialign \bgroup
+ \hfil
+ \strut@
+ $
+ \m@th
+ \displaystyle
+ ##
+ \UseTaggingSocket{math/luamml/save/nNn}{ {} \displaystyle {mtd}}
+ $
+ \UseTaggingSocket{math/luamml/mtable/finalizecol}{last}
+ \hfil
+ \crcr
+ \ams@return@opt@arg
+ }
+ \PackageInfo{luamml}{patching~\string\endaligned}
+ \cs_set:Npn \endaligned {
+ \crcr
+ \UseExpandableTaggingSocket{math/luamml/mtable/innertable/save}
+ \egroup
+ \restorecolumn@
+ \egroup
+ \UseTaggingSocket{math/luamml/mtable/innertable/finalize}
+ }
+ \PackageInfo{luamml}{patching~\string\gather@}
+ \cs_set:Npn \gather@ #1 {
+ \ingather@true
+ \let \split \insplit@
+ \let \tag \tag@in@align
+ \let \label \label@in@display
+ \chardef \dspbrk@context \z@
+ \intertext@ \displ@y@ \Let@
+ \let \math@cr@@@ \math@cr@@@gather
+ \gmeasure@ {#1}
+ \global \shifttag@false
+ \tabskip \z@skip
+ \global \row@ \@ne
+ \halign to \displaywidth \bgroup
+ \strut@
+ \setboxz@h {
+ $
+ \m@th
+ \displaystyle
+ {##}
+ \UseTaggingSocket{math/luamml/save/nNn}{ {} \displaystyle {mtd}}
+ $
+ }
+ \UseTaggingSocket{math/luamml/mtable/finalizecol}{box}
+ \calc@shift@gather
+ \set@gather@field
+ \tabskip\@centering
+ &
+ \setboxz@h {
+ \strut@
+ {##}
+ }
+ \dim_compare:nNnTF {0pt} = {
+ \box_wd:N \c_zero_int
+ }
+ { \place@tag@gather }
+ {
+ \place@tag@gather
+ \UseTaggingSocket{math/luamml/mtable/tag/set}
+ }
+ \tabskip \iftagsleft@
+ \gdisplaywidth@
+ \else
+ \z@skip
+ \span \fi
+ \crcr
+ #1
+ }
+% in latex lab, add the luamml_ignore to \measuring@true instead.
+ \PackageInfo{luamml}{patching~\string\gmeasure@}
+ \cs_new_eq:NN \__luamml_amsmath_original_gmeasure:n \gmeasure@
+ \cs_set:Npn \gmeasure@ #1 {
+ \exp_last_unbraced:Nno
+ \use_ii_i:nn
+ { \luamml_ignore: }
+ { \__luamml_amsmath_original_gmeasure:n {#1} }
}
- \ifmeasuring@
- \savefieldlength@
- \else
- \__luamml_amsmath_add_box_to_row:
- \fi
- \set@field
- \hfil
- \tabskip\alignsep@
-}
-\cs_set:Npn \math@cr@@@align {
- \ifst@rred
- \nonumber
- \fi
- \if@eqnsw
- \global \tag@true
- \fi
- \global \advance \row@ \@ne
- \add@amps \maxfields@
- \omit
- \kern -\alignsep@
- \iftag@
- \setboxz@h {
- \@lign
- \strut@
- { \make@display@tag }
- }
- \place@tag
- \__luamml_amsmath_set_tag:
- \fi
- \ifst@rred
- \else
- \global \@eqnswtrue
- \fi
- \global \lineht@ \z@
- \cr
-}
-\cs_set:Npn \maketag@@@ #1 {
- \hbox {
- \m@th
- \normalfont
- #1
- \__luamml_amsmath_save_tag:
- }
-}
+ \PackageInfo{luamml}{patching~\string\endgather}
+ \cs_set:Npn \endgather {
+ \math@cr
+ \black@ \totwidth@
+ \UseExpandableTaggingSocket{math/luamml/mtable/finalize} {gather}
+ \egroup
+ $$
+ \ignorespacesafterend
+ }
-\cs_set:Npn \endalign {
- \math@cr
- \black@ \totwidth@
- \__luamml_amsmath_finalize_table:n {align}
- \egroup
- \ifingather@
- \restorealignstate@
- \egroup
- \nonumber
- \ifnum0=`{\fi\iffalse}\fi
- \else
- $$
- \fi
- \ignorespacesafterend
-}
-% For a more interesting one, let's consider multline:
-\cs_new_eq:NN \__luamml_amsmath_original_multline:n \multline@
-\cs_set:Npn \multline@ #1 {
- \__luamml_amsmath_original_multline:n {
- \ifmeasuring@ \else
- \__luamml_amsmath_set_row_columnalign:n {left}
- \fi
- #1
- \ifmeasuring@ \else
- \__luamml_amsmath_set_row_columnalign:n {right}
- \fi
- }
-}
+% align and friends
+ \PackageInfo{luamml}{patching~\string\align@preamble}
+ \cs_set:Npn \align@preamble {
+ &
+ \hfil
+ \strut@
+ \setboxz@h {
+ \@lign
+ $
+ \m@th
+ \displaystyle
+ {##}
+ \ifmeasuring@
+ \luamml_ignore:
+ \else
+ \UseTaggingSocket{math/luamml/save/nNn}{ {} \displaystyle {mtd}}
+ \fi
+ $
+ }
+ \ifmeasuring@
+ \savefieldlength@
+ \else
+ \UseTaggingSocket{math/luamml/mtable/finalizecol}{box}
+ \fi
+ \set@field
+ \tabskip\z@skip
+ &
+ \setboxz@h {
+ \@lign
+ $
+ \m@th
+ \displaystyle
+ {
+ {}
+ ##
+ }
+ \ifmeasuring@
+ \luamml_ignore:
+ \else
+ \UseTaggingSocket{math/luamml/save/nNn}{ {} \displaystyle {mtd}}
+ \fi
+ $
+ }
+ \ifmeasuring@
+ \savefieldlength@
+ \else
+ \UseTaggingSocket{math/luamml/mtable/finalizecol}{box}
+ \fi
+ \set@field
+ \hfil
+ \tabskip\alignsep@
+ }
+ \PackageInfo{luamml}{patching~\string\math@cr@@@align}
+ \cs_set:Npn \math@cr@@@align {
+ \ifst@rred
+ \nonumber
+ \fi
+ \if@eqnsw
+ \global \tag@true
+ \fi
+ \global \advance \row@ \@ne
+ \add@amps \maxfields@
+ \omit
+ \kern -\alignsep@
+ \iftag@
+ \setboxz@h {
+ \@lign
+ \strut@
+ { \make@display@tag }
+ }
+ \place@tag
+ \UseTaggingSocket{math/luamml/mtable/tag/set}
+ \fi
+ \ifst@rred
+ \else
+ \global \@eqnswtrue
+ \fi
+ \global \lineht@ \z@
+ \cr
+ }
-\cs_new_eq:NN \__luamml_amsmath_original_mmeasure:n \mmeasure@
-\cs_set:Npn \mmeasure@ #1 {
- \exp_last_unbraced:Nno
- \use_ii_i:nn
- { \luamml_ignore: }
- { \__luamml_amsmath_original_mmeasure:n {#1} }
-}
+% This was lost anyway, as the latex-lab code overwrites
+% the definition again.
+ \PackageInfo{luamml}{patching~\string\maketag@@@}
+ \cs_set:Npn \maketag@@@ #1
+ {
+ \hbox {
+ \m@th
+ \normalfont
+ #1
+ \UseTaggingSocket{math/luamml/mtable/tag/save}
+ }
+ }
+ \PackageInfo{luamml}{patching~\string\endalign}
+% this handled in latex-lab through \common@align@ending
+ \cs_set:Npn \endalign {
+ \math@cr
+ \black@ \totwidth@
+ \UseTaggingSocket{math/luamml/mtable/finalize} {align}
+ \egroup
+ \ifingather@
+ \restorealignstate@
+ \egroup
+ \nonumber
+ \ifnum0=`{\fi\iffalse}\fi
+ \else
+ $$
+ \fi
+ \ignorespacesafterend
+ }
+
+ \PackageInfo{luamml}{patching~\string\multline@}
+ % For a more interesting one, let's consider multline:
+ \cs_new_eq:NN \__luamml_amsmath_original_multline:n \multline@
+ \cs_set:Npn \multline@ #1 {
+ \__luamml_amsmath_original_multline:n {
+ \ifmeasuring@ \else
+ \UseTaggingSocket{math/luamml/mtable/aligncol} {left}
+ \fi
+ #1
+ \ifmeasuring@ \else
+ \UseTaggingSocket{math/luamml/mtable/aligncol} {right}
+ \fi
+ }
+ }
+ %this is not move to latex-lab as the luamml_ignore is inserting with
+ % \measuringtrue
+ \PackageInfo{luamml}{patching~\string\mmeasure@}
+ \cs_new_eq:NN \__luamml_amsmath_original_mmeasure:n \mmeasure@
+ \cs_set:Npn \mmeasure@ #1 {
+ \exp_last_unbraced:Nno
+ \use_ii_i:nn
+ { \luamml_ignore: }
+ { \__luamml_amsmath_original_mmeasure:n {#1} }
+ }
% Luckily, {multline} uses \endmultline@math in exactly
% the spot where we have to set the flag.
% Less luckily, \endmultline@math sometimes get overwritten for the last line.
% But that isn't a problem since we want special behavior there anyway.
-\cs_set:Npn \endmultline@math {
- \luamml_save:nNn {} \displaystyle {mtd}
- $
- \__luamml_amsmath_add_last_to_row:
-}
-
-\cs_set:Npn \rendmultline@ {
- \iftag@
- \luamml_save:nNn {} \displaystyle {mtd}
+ \PackageInfo{luamml}{patching~\string\endmultline@math}
+ \cs_set:Npn \endmultline@math {
+ \UseTaggingSocket{math/luamml/save/nNn}{{} \displaystyle {mtd}}
$
- \__luamml_amsmath_add_last_to_row:
- \let \endmultline@math \relax
- \ifshifttag@
- \hskip \multlinegap
- \llap {
- \vtop {
- \raise@tag
- \normalbaselines
- \setbox \@ne \null
- \dp \@ne \lineht@
- \box \@ne
- \hbox {
- \strut@
- \make@display@tag
+ \UseTaggingSocket{math/luamml/mtable/finalizecol}{last}
+ }
+ \PackageInfo{luamml}{patching~\string\rendmultline@}
+ \cs_set:Npn \rendmultline@ {
+ \iftag@
+ \UseTaggingSocket{math/luamml/save/nNn}{{} \displaystyle {mtd}}
+ $
+ \UseTaggingSocket{math/luamml/mtable/finalizecol}{last}
+ \let \endmultline@math \relax
+ \ifshifttag@
+ \hskip \multlinegap
+ \llap {
+ \vtop {
+ \raise@tag
+ \normalbaselines
+ \setbox \@ne \null
+ \dp \@ne \lineht@
+ \box \@ne
+ \hbox {
+ \strut@
+ \make@display@tag
+ }
+ }
}
- }
- }
- \else
- \hskip \multlinetaggap
- \make@display@tag
- \fi
- \__luamml_amsmath_set_tag:
- \else
- \hskip \multlinegap
- \fi
- \hfilneg
- \math@cr
- \__luamml_amsmath_finalize_table:n {multline}
- \egroup
- $$
-}
-
-\cs_set:Npn \lendmultline@ {
- \hfilneg
- \hskip\multlinegap
- \math@cr
- \__luamml_amsmath_finalize_table:n {multline}
- \egroup
- $$
-}
-
-% Finally some slightly different stuff.
-% While {matrix} is covered by {array}, we still have {smallmatrix}:
-\renewenvironment {smallmatrix} {
- \luamml_annotate:en {
- core = false
- } {
- \null
- \,
- }
- \vcenter \bgroup
- \Let@
- \restore@math@cr
- \default@tag
- \baselineskip 6 \ex@
- \lineskip 1.5 \ex@
- \lineskiplimit \lineskip
- \ialign \bgroup
- \hfil
- $
- \m@th
- \scriptstyle
- ##
- \luamml_save:nn {} {mtd} % No \scriptsize here since we want to add the mstyle nodes
- $
- \__luamml_amsmath_add_last_to_row:
- \hfil
- &&
- \thickspace
- \hfil
- $
- \m@th
- \scriptstyle
- ##
- \luamml_save:nn {} {mtd} % No \scriptsize here since we want to add the mstyle nodes
- $
- \__luamml_amsmath_add_last_to_row:
- \hfil
- \crcr
-}{%
- \crcr
- \__luamml_amsmath_save_smallmatrix:
- \egroup
- \egroup
- \__luamml_amsmath_finalize_inner_table:
- \luamml_annotate:en {
- core = false
- } {
- \,
- }
-}
-
-% {cases} is defined by the kernel, but we patch the overwritten version by amsmath.
-\cs_set:Npn \env@cases {
- \let \@ifnextchar \new@ifnextchar
- \left \lbrace
- \def \arraystretch {1.2}
- \array {@{}l@{\quad \luamml_ignore:}l@{}}
-}
-
+ \else
+ \hskip \multlinetaggap
+ \make@display@tag
+ \fi
+ \UseTaggingSocket{math/luamml/mtable/tag/set}
+ \else
+ \hskip \multlinegap
+ \fi
+ \hfilneg
+ \math@cr
+ \UseExpandableTaggingSocket {math/luamml/mtable/finalize} {multline}
+ \egroup
+ $$
+ }
+ \PackageInfo{luamml}{patching~\string\lendmultline@}
+ \cs_set:Npn \lendmultline@ {
+ \hfilneg
+ \hskip\multlinegap
+ \math@cr
+ \UseExpandableTaggingSocket {math/luamml/mtable/finalize} {multline}
+ %\__luamml_amsmath_finalize_table:n {multline}
+ \egroup
+ $$
+ }
+
+ \PackageInfo{luamml}{patching~smallmatrix}
+ \renewenvironment {smallmatrix} {
+ \UseTaggingSocket{ math/luamml/annotate/false } {} { \null\, }
+ \vcenter \bgroup
+ \Let@
+ \restore@math@cr
+ \default@tag
+ \baselineskip 6 \ex@
+ \lineskip 1.5 \ex@
+ \lineskiplimit \lineskip
+ \ialign \bgroup
+ \hfil
+ $
+ \m@th
+ \scriptstyle
+ ##
+ % No \scriptsize here since we want to add the mstyle nodes
+ \UseTaggingSocket{math/luamml/save/nn}{ {} {mtd}}
+ $
+ \UseTaggingSocket{math/luamml/mtable/finalizecol}{last}
+ \hfil
+ &&
+ \thickspace
+ \hfil
+ $
+ \m@th
+ \scriptstyle
+ ##
+ % No \scriptsize here since we want to add the mstyle nodes
+ \UseTaggingSocket{math/luamml/save/nn}{ {} {mtd}}
+ $
+ \UseTaggingSocket{math/luamml/mtable/finalizecol}{last}
+ \hfil
+ \crcr
+ }{%
+ \crcr
+ \UseExpandableTaggingSocket{math/luamml/mtable/smallmatrix/save}
+ \egroup
+ \egroup
+ \UseTaggingSocket{math/luamml/mtable/innertable/finalize}
+ \UseTaggingSocket{math/luamml/annotate/false} {}{ \, }
+ }
-\cs_set:Npn \bBigg@ #1 #2 {
- {
- \ensuremath {
- \Uvextensible height~#1 \big@size axis~exact~#2
+ % {cases} is defined by the kernel, but we patch the overwritten version by amsmath.
+ \PackageInfo{luamml}{patching~\string\env@cases}
+ \cs_set:Npn \env@cases {
+ \let \@ifnextchar \new@ifnextchar
+ \left \lbrace
+ \def \arraystretch {1.2}
+ \array {@{}l@{\quad \luamml_ignore:}l@{}}
}
- }
-}
+ \PackageInfo{luamml}{patching~\string\bBigg@}
+ \cs_set:Npn \bBigg@ #1 #2 {
+ {
+ \ensuremath {
+ \Uvextensible height~#1 \big@size axis~exact~#2
+ }
+ }
+ }
+} %end package test
diff --git a/macros/luatex/latex/luamml/luamml-patches-amstext.sty b/macros/luatex/latex/luamml/luamml-patches-amstext.sty
index 97b1b1f176..f7d24431e6 100644
--- a/macros/luatex/latex/luamml/luamml-patches-amstext.sty
+++ b/macros/luatex/latex/luamml/luamml-patches-amstext.sty
@@ -1,37 +1,29 @@
-\ProvidesExplPackage {luamml-patches-amstext} {2024-10-30} {0.2.0}
- {Feel free to add a description here}
+\ProvidesExplPackage {luamml-patches-amstext} {2025-02-17} {0.3.0}
+ {patches of amstext commands}
-\int_new:N \g__luamml_amsmath_text_struct_int
-\cs_set:Npn \textdef@ #1 #2 #3 {
- \int_if_odd:nTF { \int_div_truncate:nn { \l__luamml_flag_int } { 8 } } {
- \int_gincr:N \g__luamml_amsmath_text_struct_int
- \tag_struct_begin:n {
- tag = mtext/mathml,
- stash,
- label = __luamml_amsmath_text_ \int_use:N \g__luamml_amsmath_text_struct_int
+% This is the same definition as in latex-lab-amsmath. It can go with the
+% 2025-06-01 release.
+\IfPackageAtLeastTF{latex-lab-testphase-math}{2025-01-24}
+ {}
+ {
+ \PackageInfo{luamml}{patching~\string\text@}
+ \sys_if_engine_luatex:T
+ {
+ \def\text@#1{
+ \tag_socket_use:nnn {math/luamml/hbox}{}
+ {{%
+ \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
+ }}}
}
- \tag_mc_begin:n {
- tag = mtext
- }
- \AnnotateFormula {
- nucleus = true,
- struct = "__luamml_amsmath_text_ \int_use:N \g__luamml_amsmath_text_struct_int"
- }
- } {
- \use:n
- }
- {
- \hbox {
- {
- \everymath {#1}
- \let \f@size #2
- \selectfont
- #3
- }
- }
- }
- \int_if_odd:nT { \int_div_truncate:nn { \l__luamml_flag_int } { 8 } } {
- \tag_mc_end:
- \tag_struct_end:
}
-}
diff --git a/macros/luatex/latex/luamml/luamml-patches-array.sty b/macros/luatex/latex/luamml/luamml-patches-array.sty
deleted file mode 100644
index b08d5615e4..0000000000
--- a/macros/luatex/latex/luamml/luamml-patches-array.sty
+++ /dev/null
@@ -1,101 +0,0 @@
-\ProvidesExplPackage {luamml-patches-array} {2024-10-30} {0.2.0}
- {Feel free to add a description here}
-
-\lua_now:n { require'luamml-array' }
-
-\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_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_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_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
-}
-
-\IfPackageAtLeastTF {array} {2023/12/11} {
- \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_new_eq:NN \insert@pcolumn \insert@column
- \cs_set:Npn \endarray {
- \crcr
- \__luamml_array_save_array:
- \egroup
- \egroup
- \mode_if_math:T { \__luamml_array_finalize_array: }
- \@arrayright
- \gdef \@preamble {}
- }
-}
diff --git a/macros/luatex/latex/luamml/luamml-patches-kernel.sty b/macros/luatex/latex/luamml/luamml-patches-kernel.sty
index 38eb28bd5f..d477635af7 100644
--- a/macros/luatex/latex/luamml/luamml-patches-kernel.sty
+++ b/macros/luatex/latex/luamml/luamml-patches-kernel.sty
@@ -1,52 +1,64 @@
-\ProvidesExplPackage {luamml-patches-kernel} {2024-10-30} {0.2.0}
+\ProvidesExplPackage {luamml-patches-kernel} {2025-02-17} {0.3.0}
{Feel free to add a description here}
-\cs_set:Npn \mathsm@sh #1 #2 {
- \setbox \z@ \hbox {
- $
- \m@th #1 {
- #2
- }
- \luamml_save:nNn {mathsmash} #1 {mpadded}
- \luamml_pdf_write:
- $
- }
- \luamml_annotate:nen {2} {
- nucleus = true,
- core = consume_label('mathsmash', function(padded)
- padded.height, padded.depth = 0, 0~
- end),
- } {
- {}
- \finsm@sh
- }
-}
-\cs_set:Npn \mathph@nt #1 #2 {
- \setbox \z@ = \hbox {
- $
- \m@th
- #1
- {#2}
- \luamml_save:nNn {mathphant} #1 {mphantom}
- $
- }
- \luamml_annotate:nen {1} {
- nucleus = true,
- core = {[0] = 'mpadded',
- \ifh@\else
- width = 0,
- \fi
- \ifv@\else
- height = 0, depth = 0,
- \fi
- consume_label'mathphant',
- }
- } {
- \finph@nt
- }
-}
+\IfPackageAtLeastTF{latex-lab-testphase-math}{2025-01-24}
+ {}
+ {
+ \PackageInfo{luamml}{patching~\string\mathsm@sh}
+ \cs_set:Npn \mathsm@sh #1 #2 {
+ \setbox \z@ \hbox {
+ $
+ \m@th #1 {
+ #2
+ }
+ \luamml_save:nNn {mathsmash} #1 {mpadded}
+ \luamml_pdf_write:
+ $
+ }
+ \luamml_annotate:nen {2} {
+ nucleus = true,
+ core = consume_label('mathsmash', function(padded)
+ padded.height, padded.depth = 0, 0~
+ end),
+ } {
+ {}
+ \finsm@sh
+ }
+ }
+
+ \PackageInfo{luamml}{patching~\string\mathph@nt}
+ \cs_set:Npn \mathph@nt #1 #2 {
+ \setbox \z@ = \hbox {
+ $
+ \m@th
+ #1
+ {#2}
+ \luamml_save:nNn {mathphant} #1 {mphantom}
+ $
+ }
+ \luamml_annotate:nen {1} {
+ nucleus = true,
+ core = {[0] = 'mpadded',
+ \ifh@\else
+ width = 0,
+ \fi
+ \ifv@\else
+ height = 0, depth = 0,
+ \fi
+ consume_label'mathphant',
+ }
+ } {
+ \finph@nt
+ }
+ }
+ \IfFileLoadedT {latex-lab-math.ltx} {
+ \RequirePackage{luamml-patches-lab-math}
+ }
+ }
+% This is not moved to latex-lab for now. It doesn't work properly with structure elements
+% active: the content is outside of the math.
\@ifpackageloaded {unicode-math} {} {
\cs_new:Npn \__luamml_kernel_define_character:Nnn #1#2#3 {
\cs_set:cpx { \cs_to_str:N #1 ~ } {
@@ -70,7 +82,3 @@
\__luamml_kernel_define_character:Nnn \longleftrightarrow {3} {27f7}
\__luamml_kernel_define_character:Nnn \longmapsto {4} {27fc}
}
-
-\IfFileLoadedT {latex-lab-math.ltx} {
- \RequirePackage{luamml-patches-lab-math}
-}
diff --git a/macros/luatex/latex/luamml/luamml-patches-lab-math.sty b/macros/luatex/latex/luamml/luamml-patches-lab-math.sty
index 7776576536..abb23ad744 100644
--- a/macros/luatex/latex/luamml/luamml-patches-lab-math.sty
+++ b/macros/luatex/latex/luamml/luamml-patches-lab-math.sty
@@ -1,11 +1,17 @@
-\ProvidesExplPackage {luamml-patches-lab-math} {2024-10-30} {0.2.0}
+\ProvidesExplPackage {luamml-patches-lab-math} {2025-02-17} {0.3.0}
{Feel free to add a description here}
-\AddToHook{begindocument} {
+% This definition is identical to the one in latex-lab-math.
+% The redefinition and the whole patch file can be removed in 2025-06-01
+\IfPackageAtLeastTF{latex-lab-testphase-math}{2025-01-24}
+ {}
+ {
+ \AddToHook{begindocument} {
+ \PackageInfo{luamml}{patching~\string\common@align@ending}
\cs_set:Npn \common@align@ending {
\math@cr
\black@ \totwidth@
- \__luamml_amsmath_finalize_table:n {align}
+ \UseExpandableTaggingSocket{math/luamml/mtable/finalize}{align}
\egroup
\ifingather@
\restorealignstate@
@@ -16,5 +22,6 @@
$$
\fi
\ignorespacesafterend
+ }
}
}
diff --git a/macros/luatex/latex/luamml/luamml-patches-mathtools.sty b/macros/luatex/latex/luamml/luamml-patches-mathtools.sty
index 3dc1570b02..1c9cb74eb6 100644
--- a/macros/luatex/latex/luamml/luamml-patches-mathtools.sty
+++ b/macros/luatex/latex/luamml/luamml-patches-mathtools.sty
@@ -1,35 +1,38 @@
-\ProvidesExplPackage {luamml-patches-mathtools} {2024-10-26} {0.2.0}
+\ProvidesExplPackage {luamml-patches-mathtools} {2025-02-17} {0.3.0}
{Feel free to add a description here}
-
-\RequirePackage{luamml-patches-amsmath}
-% see https://github.com/latex3/tagging-project/issues/734
-\renewcommand*\MT_mult_internal:n [1]{
- \MH_if_boolean:nF {outer_mult}{\alignedspace@left} %<-- requires amsmath 2016/11/05
- \MT_next:
- \bgroup
- \Let@
- \def\l_MT_multline_lastline_fint{0 }
- \chardef\dspbrk@context\@ne \restore@math@cr
- \MH_let:NwN \math@cr@@\MT_mult_mathcr_atat:w
- \MH_let:NwN \shoveleft\MT_shoveleft:wn
- \MH_let:NwN \shoveright\MT_shoveright:wn
- \spread@equation
- \MH_set_boolean_F:n {mult_firstline}
- \MT_measure_mult:n {#1}
- \MH_if_dim:w \l_MT_multwidth_dim<\l_MT_multline_measure_fdim
- \MH_setlength:dn \l_MT_multwidth_dim{\l_MT_multline_measure_fdim}
- \fi
- \MH_set_boolean_T:n {mult_firstline}
- \MH_if_num:w \l_MT_multline_lastline_fint=\@ne
- \MH_let:NwN \math@cr@@ \MT_mult_firstandlast_mathcr:w
- \MH_fi:
- \ialign\bgroup
- \hfil\strut@$\m@th\displaystyle{}##
- \luamml_save:nNn {} \displaystyle {mtd}
- $
- \__luamml_amsmath_add_last_to_row:
- \hfil
- \crcr
- \hfilneg
- #1
+\IfPackageAtLeastTF{latex-lab-testphase-math}{2025-01-24}
+ {}
+ {
+ \RequirePackage{luamml-patches-amsmath}
+ % see https://github.com/latex3/tagging-project/issues/734
+ \renewcommand*\MT_mult_internal:n [1]{
+ \MH_if_boolean:nF {outer_mult}{\alignedspace@left} %<-- requires amsmath 2016/11/05
+ \MT_next:
+ \bgroup
+ \Let@
+ \def\l_MT_multline_lastline_fint{0 }
+ \chardef\dspbrk@context\@ne \restore@math@cr
+ \MH_let:NwN \math@cr@@\MT_mult_mathcr_atat:w
+ \MH_let:NwN \shoveleft\MT_shoveleft:wn
+ \MH_let:NwN \shoveright\MT_shoveright:wn
+ \spread@equation
+ \MH_set_boolean_F:n {mult_firstline}
+ \MT_measure_mult:n {#1}
+ \MH_if_dim:w \l_MT_multwidth_dim<\l_MT_multline_measure_fdim
+ \MH_setlength:dn \l_MT_multwidth_dim{\l_MT_multline_measure_fdim}
+ \fi
+ \MH_set_boolean_T:n {mult_firstline}
+ \MH_if_num:w \l_MT_multline_lastline_fint=\@ne
+ \MH_let:NwN \math@cr@@ \MT_mult_firstandlast_mathcr:w
+ \MH_fi:
+ \ialign\bgroup
+ \hfil\strut@$\m@th\displaystyle{}##
+ \UseTaggingSocket{math/luamml/save/nNn}{ {} \displaystyle {mtd}}
+ $
+ \UseTaggingSocket{math/luamml/mtable/finalizecol}{last}
+ \hfil
+ \crcr
+ \hfilneg
+ #1
+ }
}
diff --git a/macros/luatex/latex/luamml/luamml-pdf-demo.sty b/macros/luatex/latex/luamml/luamml-pdf-demo.sty
index 73c93f076c..1b3e245c1b 100644
--- a/macros/luatex/latex/luamml/luamml-pdf-demo.sty
+++ b/macros/luatex/latex/luamml/luamml-pdf-demo.sty
@@ -1,5 +1,5 @@
\NeedsTeXFormat{LaTeX2e}
-\ProvidesExplPackage{luamml-pdf-demo}{2024-10-30}{0.2.0}{Reasonable default definitions for luamml-pdf}
+\ProvidesExplPackage{luamml-pdf-demo}{2025-02-17}{0.3.0}{Reasonable default definitions for luamml-pdf}
\RequirePackage{luamml-pdf}% Loading luamml-pdf is pretty much the point
% \RequirePackage{amsmath,array}% May come back if the patches get ported
diff --git a/macros/luatex/latex/luamml/luamml-structelemwriter.lua b/macros/luatex/latex/luamml/luamml-structelemwriter.lua
index 97a90acedb..3087305757 100644
--- a/macros/luatex/latex/luamml/luamml-structelemwriter.lua
+++ b/macros/luatex/latex/luamml/luamml-structelemwriter.lua
@@ -1,10 +1,19 @@
local struct_begin = token.create'tag_struct_begin:n'
local struct_use = token.create'tag_struct_use:n'
+local struct_use_num = token.create'tag_struct_use_num:n'
local struct_end = token.create'tag_struct_end:'
local mc_begin = token.create'tag_mc_begin:n'
local mc_end = token.create'tag_mc_end:'
+local catlatex = luatexbase.registernumber("catcodetable@latex")
+
+ltx = ltx or {}
+ltx.__tag = ltx.__tag or {}
+ltx.__tag.struct = ltx.__tag.struct or {}
+ltx.__tag.struct.luamml = ltx.__tag.struct.luamml or {}
+ltx.__tag.struct.luamml.labels = ltx.__tag.struct.luamml.labels or {}
+
local function escape_name(name)
return name
end
@@ -43,7 +52,7 @@ local attributes = setmetatable({}, {__index = function(t, k)
local attr_name = string.format('luamml_attr_%i', attribute_counter)
t[k] = attr_name
tex.runtoks(function()
- tex.sprint(string.format('\\tagpdfsetup{newattribute={%s}{/O/NSO/NS %i 0 R',
+ tex.sprint(catlatex,string.format('\\tagpdfsetup{newattribute={%s}{/O/NSO/NS %i 0 R',
attr_name, mathml_ns_obj or get_mathml_ns_obj()))
-- tex.sprint(string.format('\\tagpdfsetup{newattribute={%s}{/O/MathML-3',
-- attr_name))
@@ -65,6 +74,11 @@ local function write_elem(tree, stash)
return tex.sprint(struct_use, '{', tree[':struct'], '}')
end)
end
+ if tree[':structnum'] then
+ return tex.runtoks(function()
+ return tex.sprint(struct_use_num, '{', tree[':structnum'], '}')
+ end)
+ end
if not tree[0] then print('ERR', require'inspect'(tree)) end
local i = 0
for attr, val in next, tree do if type(attr) == 'string' and not string.find(attr, ':') and attr ~= 'xmlns' then
@@ -75,28 +89,27 @@ local function write_elem(tree, stash)
table.sort(attrs)
if stash then
- stash_cnt = stash_cnt + 1
- stash = '__luamml_stashed_' .. stash_cnt
- tree[':struct'] = stash
- stash = ', stash, label = ' .. stash
+ tree[':structnum'] = get_ltx().tag.get_struct_num_next()
+ stash = ', stash, '
end
local attr_flag = i ~= 0 and ', attribute=' .. attributes[table.concat(attrs)]
tex.sprint(struct_begin, '{tag=' .. tree[0] .. '/mathml')
if stash then tex.sprint(stash) end
if attr_flag then tex.sprint(attr_flag) end
- if tree[':actual'] then
- tex.sprint(', actualtext = {')
- tex.cprint(12, tree[':actual'])
- tex.sprint'}'
- end
tex.sprint'}'
for j = 1, i do attrs[j] = nil end
if tree[':nodes'] then
local n = tree[':nodes']
tex.runtoks(function()
- tex.sprint{mc_begin, string.format('{tag=%s}', tree[0])}
+ if tree[':actual'] then
+ tex.sprint(mc_begin,'{tag=Span,actualtext=')
+ tex.cprint(12,tree[':actual'])
+ tex.sprint('}')
+ else
+ tex.sprint{mc_begin, string.format('{tag=%s}', tree[0])}
+ end
-- NOTE: This will also flush all previous sprint's... That's often annoying, but in this case actually intentional.
end)
local mct, mcc = tex.attribute[mc_type], tex.attribute[mc_cnt]
@@ -109,7 +122,14 @@ local function write_elem(tree, stash)
end)
end
for _, elem in ipairs(tree) do
- if type(elem) ~= 'string' then
+ if type(elem) ~= 'string' and not elem['tex:ignore'] then
+ if elem['intent']==':equationlabel' and ltx.__tag.struct.luamml.labels then
+ if #ltx.__tag.struct.luamml.labels > 0 then
+ -- print("CHECK LABEL STRUCTURE: ",table.serialize(elem), table.serialize(ltx.__tag.struct.luamml.labels))
+ local num= table.remove(ltx.__tag.struct.luamml.labels,1)
+ elem[1][#elem+1]={[':structnum']= num}
+ end
+ end
write_elem(elem)
end
end
diff --git a/macros/luatex/latex/luamml/luamml-table.lua b/macros/luatex/latex/luamml/luamml-table.lua
index 4fb553af28..23331042c1 100644
--- a/macros/luatex/latex/luamml/luamml-table.lua
+++ b/macros/luatex/latex/luamml/luamml-table.lua
@@ -63,6 +63,12 @@ local function store_tag(xml)
last_tag = nil
end
+local function store_notag(xml)
+ local mml_row = store_get_row()
+ xml.intent = ':noequationlabel'
+ table.insert(mml_row, 1, xml)
+end
+
local function set_row_attribute(name, value)
local mml_row = store_get_row()
mml_row[name] = value
@@ -105,6 +111,7 @@ return {
store_column = store_column,
store_column_xml = store_column_xml,
store_tag = store_tag,
+ store_notag = store_notag,
set_row_attribute = set_row_attribute,
get_table = get_table,
}
diff --git a/macros/luatex/latex/luamml/luamml-tex-annotate.lua b/macros/luatex/latex/luamml/luamml-tex-annotate.lua
index 050a00a90e..958b3eed5d 100644
--- a/macros/luatex/latex/luamml/luamml-tex-annotate.lua
+++ b/macros/luatex/latex/luamml/luamml-tex-annotate.lua
@@ -83,6 +83,18 @@ local function annotate()
end
end
end
+ if annotation.structnum ~= nil then
+ local saved = props.mathml_filter
+ local structnum = annotation.structnum
+ function props.mathml_filter(mml, core)
+ mml[':structnum'] = structnum
+ if saved then
+ return saved(mml, core)
+ else
+ return mml, core
+ end
+ end
+ end
else
tex.error'Unable to annotate nucleus of node without nucleus'
end
diff --git a/macros/luatex/latex/luamml/luamml-xmlwriter.lua b/macros/luatex/latex/luamml/luamml-xmlwriter.lua
index a2b5abefbf..ad67845d81 100644
--- a/macros/luatex/latex/luamml/luamml-xmlwriter.lua
+++ b/macros/luatex/latex/luamml/luamml-xmlwriter.lua
@@ -34,6 +34,10 @@ local function write_elem(tree, indent)
return out .. '/>'
end
out = out .. '>'
+ -- Never indent the content if it's purely text.
+ if #tree == 1 and type(tree[1]) == 'string' then
+ indent = nil
+ end
local inner_indent = indent and indent .. ' '
local is_string
for _, elem in ipairs(tree) do
@@ -44,7 +48,9 @@ local function write_elem(tree, indent)
out = out .. escape_text(elem)
is_string = true
else
- out = out .. write_elem(elem, inner_indent)
+ if not elem['tex:ignore'] then
+ out = out .. write_elem(elem, inner_indent)
+ end
is_string = nil
end
end
diff --git a/macros/luatex/latex/luamml/luamml.dtx b/macros/luatex/latex/luamml/luamml.dtx
index 651185af9b..41bbf04246 100644
--- a/macros/luatex/latex/luamml/luamml.dtx
+++ b/macros/luatex/latex/luamml/luamml.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-%% Copyright (C) 2020-2024 by Marcel Krueger
+%% Copyright (C) 2020-2025 by Marcel Krueger
%%
%% This file may be distributed and/or modified under the
%% conditions of the LaTeX Project Public License, either
@@ -37,6 +37,9 @@
\usepackage{csquotes,luacolor}
\MakeShortVerb{\|}
\RecordChanges
+\ProvideDocElement[printtype=\textit{socket},idxtype=socket,idxgroup=Sockets]{Socket}{socketdecl}
+\ProvideDocElement[printtype=\textit{plug},idxtype=plug,idxgroup=Plugs]{Plug}{plugdecl}
+
\begin{document}
\tracingmathml2
\DocInput{luamml.dtx}
@@ -93,7 +96,23 @@
% }
% \end{verbatim}
% produces a |<mi>TeX</mi>| element in the output instead of trying to import \TeX~as a mathematical expression.
-% The table structure is explained in an appendix.
+%
+% It it possible to add a structure around the construct, stash that structure
+% and then to tell \cmd{luamml_annotate:en} to insert it later inside the math.
+% For this the keys \texttt{struct} (which takes a label as argument) or \texttt{structnum}
+% (which takes a structure number) can be used. For example
+% \begin{verbatim}
+% $a = b \quad
+% \tagstructbegin{tag=mtext,stash}\tagmcbegin{}
+% \luamml_annotate:en{nucleus=true,structnum=\tag_get:n{struct_num}}
+% {\mbox{some~text~with~\emph{structure}}}
+% \tagmcend\tagstructend
+% $
+% \end{verbatim}
+% Such a construction should check that the flag for structure elements has actually
+% been set to avoid orphaned structures if the stashed structure is ignored.
+%
+% More about the table structure is explained in an appendix.
%
% \section{Features \& Limitations}
% Currently all mathematical expressions which purely contain Unicode encoded math mode material without embedded non-math should get converted successfully.
@@ -114,11 +133,11 @@
% \begin{macrocode}
%<@@=luamml>
%<*luatex>
-\ProvidesExplPackage {luamml} {2024-10-30} {0.2.0}
+\ProvidesExplPackage {luamml} {2025-02-17} {0.3.0}
{Automatically generate presentational MathML from LuaTeX math expressions}
%</luatex>
%<*pdftex>
-\ProvidesExplPackage {luamml-pdf} {2024-10-30} {0.2.0}
+\ProvidesExplPackage {luamml-pdf} {2025-02-17} {0.3.0}
{MathML generation for L̶u̶a̶pdfLaTeX}
%</pdftex>
% \end{macrocode}
@@ -300,7 +319,7 @@
% written by a previous formula. Therefore this has to be called separately
% for every formula or it must expand to different values to be useful.
% The value is fully expanded when the file is written.
-%
+%
% Only complete formulas get written into files (so formulas where
% \cs{luamml_process:} or \cs{luamml_structelem:} are in effect).
%
@@ -507,11 +526,447 @@
% \end{macrocode}
% \end{macro}
%
+% \subsection{Sockets}
+% In various places luamml has to add code to kernel commands. This is done through
+% sockets which are predeclared in lttagging.
+%
+% \subsubsection{Save sockets}
+% These sockets are wrappers around the \cs{luamml_save:...} commands
+% They should be provided until 2025-06-01
+% \begin{macrocode}
+\str_if_exist:cF { l__socket_tagsupport/math/luamml/save/nn_plug_str }
+ {
+ \NewSocket{tagsupport/math/luamml/save/nn}{1}
+ \AssignSocketPlug{tagsupport/math/luamml/save/nn}{noop}
+ \NewSocket{tagsupport/math/luamml/save/nNn}{1}
+ \AssignSocketPlug{tagsupport/math/luamml/save/nNn}{noop}
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\NewSocketPlug{tagsupport/math/luamml/save/nNn}{luamml}
+ {
+ \luamml_save:nNn #1
+ }
+\AssignSocketPlug{tagsupport/math/luamml/save/nNn}{luamml}
+\NewSocketPlug{tagsupport/math/luamml/save/nn}{luamml}
+ {
+ \luamml_save:nn #1
+ }
+\AssignSocketPlug{tagsupport/math/luamml/save/nn}{luamml}
+% \end{macrocode}
+%
+% \subsubsection{sockets to annotate content}
+%
+% \begin{macrocode}
+\str_if_exist:cF { l__socket_tagsupport/math/luamml/annotate/false_plug_str }
+ {
+ \NewSocket{tagsupport/math/luamml/annotate/false}{2}
+ \NewSocketPlug{tagsupport/math/luamml/annotate/false}{default}{#2}
+ \AssignSocketPlug{tagsupport/math/luamml/annotate/false}{default}
+ }
+%<*luatex>
+\NewSocketPlug{tagsupport/math/luamml/annotate/false}{luamml}
+ {
+ \luamml_annotate:en { core = false }
+ {
+ #2
+ }
+ }
+\AssignSocketPlug{tagsupport/math/luamml/annotate/false}{luamml}
+%</luatex>
+% \end{macrocode}
+% \subsubsection{socket plugs for the array package}
+%
+% The socket declaration can go with the 2025-06-01 release
+% \begin{macrocode}
+\str_if_exist:cF { l__socket_tagsupport/math/luamml/array/finalize_plug_str }
+ {
+ \NewSocket{tagsupport/math/luamml/array/save}{0}
+ \NewSocket{tagsupport/math/luamml/array/finalize}{0}
+ \NewSocket{tagsupport/math/luamml/array/initcol}{0}
+ \NewSocket{tagsupport/math/luamml/array/finalizecol}{1}
+ \AssignSocketPlug{tagsupport/math/luamml/array/finalizecol}{noop}
+ }
+% \end{macrocode}
+%
+% The luamml support makes only sense with luatex.
+% \begin{macrocode}
+%<*luatex>
+\AddToHook{package/array/after}{\lua_now:n { require'luamml-array' }}
+% \end{macrocode}
+% \begin{plugdecl}{tagsupport/math/luamml/array/save}
+% The socket of this plug is used in \cs{endarray}.
+% \begin{macrocode}
+\NewSocketPlug{tagsupport/math/luamml/array/save}{luamml}
+ {
+ \__luamml_array_save_array:
+ }
+% \end{macrocode}
+% \end{plugdecl}
+%
+% \begin{plugdecl}{tagsupport/math/luamml/array/finalize}
+% This socket of this plug is used in \cs{endarray}.
+% \begin{macrocode}
+\NewSocketPlug{tagsupport/math/luamml/array/finalize}{luamml}
+ {
+ \mode_if_math:T { \__luamml_array_finalize_array: }
+ }
+% \end{macrocode}
+% \end{plugdecl}
+%
+% \begin{plugdecl}{tagsupport/math/luamml/array/initcol}
+% The socket of this plug is used in \cs{@classz}.
+% \begin{macrocode}
+\NewSocketPlug{tagsupport/math/luamml/array/initcol}{luamml}
+ {
+ \__luamml_array_init_col:
+ }
+% \end{macrocode}
+% \end{plugdecl}
+%
+%
+% \begin{plugdecl}{tagsupport/math/luamml/array/finalizecol}
+% The socket of this plug is used used in \cs{@classz}.
+% \begin{macrocode}
+\NewSocketPlug{tagsupport/math/luamml/array/finalizecol}{luamml}
+ {
+ \__luamml_array_finalize_col:w #1~
+ }
+% \end{macrocode}
+% \end{plugdecl}
+% \begin{macrocode}
+\AssignSocketPlug{tagsupport/math/luamml/array/save}{luamml}
+\AssignSocketPlug{tagsupport/math/luamml/array/finalize}{luamml}
+\AssignSocketPlug{tagsupport/math/luamml/array/initcol}{luamml}
+\AssignSocketPlug{tagsupport/math/luamml/array/finalizecol}{luamml}
+%</luatex>
+% \end{macrocode}
+% \subsubsection{amsmath alignments}
+%
+% This socket is used at the end of alignment cells and adds the content to
+% the current row.
+%
+% \begin{macrocode}
+\str_if_exist:cF { l__socket_tagsupport/math/luamml/mtable/finalizecol_plug_str }
+ {
+ \NewSocket{tagsupport/math/luamml/mtable/finalizecol}{1}
+ }
+% \end{macrocode}
+% \begin{macrocode}
+%<*luatex>
+\NewSocketPlug{tagsupport/math/luamml/mtable/finalizecol}{luamml}
+ {
+ \use:c{__luamml_amsmath_add_#1_to_row:}
+ }
+\AssignSocketPlug{tagsupport/math/luamml/mtable/finalizecol}{luamml}
+
+%</luatex>
+% \end{macrocode}
+%
+% These sockets save an inner table
+% \begin{macrocode}
+\str_if_exist:cF { l__socket_tagsupport/math/luamml/mtable/innertable/save_plug_str }
+ {
+ \NewSocket{tagsupport/math/luamml/mtable/innertable/save}{0}
+ \NewSocket{tagsupport/math/luamml/mtable/smallmatrix/save}{0}
+ \NewSocket{tagsupport/math/luamml/mtable/innertable/finalize}{0}
+ }
+% \end{macrocode}
+% \begin{macrocode}
+%<*luatex>
+\NewSocketPlug{tagsupport/math/luamml/mtable/innertable/save}{luamml}
+ {
+ \__luamml_amsmath_save_inner_table:n \@currenvir
+ }
+\AssignSocketPlug{tagsupport/math/luamml/mtable/innertable/save}{luamml}
+\NewSocketPlug{tagsupport/math/luamml/mtable/smallmatrix/save}{luamml}
+ {
+ \__luamml_amsmath_save_smallmatrix:
+ }
+\AssignSocketPlug{tagsupport/math/luamml/mtable/smallmatrix/save}{luamml}
+\NewSocketPlug{tagsupport/math/luamml/mtable/innertable/finalize}{luamml}
+ {
+ \__luamml_amsmath_finalize_inner_table:
+ }
+\AssignSocketPlug{tagsupport/math/luamml/mtable/innertable/finalize}{luamml}
+%</luatex>
+% \end{macrocode}
+%
+%
+% This socket finalize the \texttt{mtable} in alignments like align or gather.
+% It takes an argument, the environment.
+% It should be used normally with \cs{UseExpandableTaggingSocket}.
+% \begin{macrocode}
+\str_if_exist:cF { l__socket_tagsupport/math/luamml/mtable/finalize_plug_str }
+ {
+ \NewSocket{tagsupport/math/luamml/mtable/finalize}{1}
+ \AssignSocketPlug{tagsupport/math/luamml/mtable/finalize}{noop}
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<*luatex>
+\NewSocketPlug{tagsupport/math/luamml/mtable/finalize}{luamml}
+ {
+ \__luamml_amsmath_finalize_table:n {#1}
+ }
+\AssignSocketPlug{tagsupport/math/luamml/mtable/finalize}{luamml}
+%</luatex>
+% \end{macrocode}
+%
+% This socket adds attributes for the alignment in \texttt{multline}.
+% It takes an argument, the alignment.
+% \begin{macrocode}
+\str_if_exist:cF { l__socket_tagsupport/math/luamml/mtable/aligncol_plug_str }
+ {
+ \NewSocket{tagsupport/math/luamml/mtable/aligncol}{1}
+ \AssignSocketPlug{tagsupport/math/luamml/mtable/aligncol}{noop}
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<*luatex>
+\NewSocketPlug{tagsupport/math/luamml/mtable/aligncol}{luamml}
+ {
+ \__luamml_amsmath_set_row_columnalign:n {#1}
+ }
+\AssignSocketPlug{tagsupport/math/luamml/mtable/aligncol}{luamml}
+%</luatex>
+% \end{macrocode}
+
+%
+% \subsubsection{Tags and labels}
+% These sockets save and set tags and labels in alignments.
+% \begin{macrocode}
+\str_if_exist:cF { l__socket_tagsupport/math/luamml/mtable/tag/save_plug_str }
+ {
+ \NewSocket{tagsupport/math/luamml/mtable/tag/save}{0}
+ \NewSocket{tagsupport/math/luamml/mtable/tag/set}{0}
+ }
+% \end{macrocode}
+% \begin{macrocode}
+%<*luatex>
+\NewSocketPlug{tagsupport/math/luamml/mtable/tag/save}{luamml}
+ {
+ \__luamml_amsmath_save_tag:
+ }
+\AssignSocketPlug{tagsupport/math/luamml/mtable/tag/save}{luamml}
+\NewSocketPlug{tagsupport/math/luamml/mtable/tag/set}{luamml}
+ {
+ \__luamml_amsmath_set_tag:
+ }
+\AssignSocketPlug{tagsupport/math/luamml/mtable/tag/set}{luamml}
+
+%</luatex>
+% \end{macrocode}
%
+% If math structure elements are created the Lbl-structure of a tag
+% must be moved inside the math structure, typically as an additional column in an
+% \texttt{mtable} with an intent \texttt{:equationlabel}.
+%
+% The luamml-code handles this by stashing the Lbl-structure, storing the
+% structure number in an array and reusing it once it creates the math structure elements.
+%
+% This should only be done for specific environments, we define
+% a constant to test:
+% \begin{macrocode}
+\str_if_exist:cF { l__socket_tagsupport/math/display/tag/begin_plug_str }
+ {
+ \NewSocket{tagsupport/math/display/tag/begin}{0}
+ \NewSocket{tagsupport/math/display/tag/end}{0}
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<*luatex>
+\clist_map_inline:nn
+ {
+ align,
+ align*,
+ alignat,
+ alignat*,
+ xalignat,
+ xalignat*,
+% \end{macrocode}
+% there is never a tag/label in xxalignat, so does it make sense to add a label column?
+% Left out for now.
+% \begin{macrocode}
+ %xxalignat,
+ flalign,
+ flalign*,
+ gather,
+ gather*,
+% \end{macrocode}
+% equation and multline have at most one tag, so we do not use a label column
+% but rely on the external Lbl for now.
+% \begin{macrocode}
+ %multline, % NO
+ %multline*, % NO
+ %equation, % NO
+ %equation*, % NO
+% \end{macrocode}
+% split has never a numbering so is ignored
+% \begin{macrocode}
+ %split, % NO
+ }
+ {\tl_const:cn { c__luamml_label_#1_tl}{}}
+% \end{macrocode}
+%
+%
+% \begin{macrocode}
+\NewSocketPlug{tagsupport/math/display/tag/begin}{luamml}
+ {
+ \tag_mc_end:
+ \bool_lazy_and:nnTF
+ { \tl_if_exist_p:c { c__luamml_label_ \@currenvir _tl } }
+ { \int_if_odd_p:n { \int_div_truncate:nn { \l__luamml_flag_int } { 8 } } }
+ {
+ %\typeout{Stash~and~move~\@currenvir\c_space_tl Lbl}
+ \tag_struct_begin:n {tag=Lbl,stash}
+ \directlua{table.insert(ltx.__tag.struct.luamml.labels,\tag_get:n{struct_num})}
+ }
+ {
+ \tag_struct_begin:n {tag=Lbl}
+ }
+ \tag_mc_begin:n {}
+ }
+\AssignSocketPlug{tagsupport/math/display/tag/begin}{luamml}
+%</luatex>
+% \end{macrocode}
+%
+%
+% \subsubsection{Horizontal boxes}
+% This socket annotates an \cs{hbox} inside box commands used in math.
+% We test for the socket until the release 2025-06-01.
+% \begin{macrocode}
+\str_if_exist:cF { l__socket_tagsupport/math/luamml/hbox_plug_str }
+ {
+ \NewSocket{tagsupport/math/luamml/hbox}{2}
+ \NewSocketPlug{tagsupport/math/luamml/hbox}{default}{#2}
+ \AssignSocketPlug{tagsupport/math/luamml/hbox}{default}
+ }
+%<*luatex>
+\NewSocketPlug{tagsupport/math/luamml/hbox}{luamml}
+ {
+ \bool_lazy_and:nnTF
+ { \mode_if_math_p: }
+ { \int_if_odd_p:n { \int_div_truncate:nn { \l__luamml_flag_int } { 8 } } }
+ {
+ \tag_struct_begin:n
+ {
+ tag=mtext,
+ stash,
+ }
+ \tag_mc_begin:n {}
+ \luamml_annotate:en
+ {
+ nucleus = true,
+ structnum=\tag_get:n{struct_num}
+ }
+ { #2 }
+ \tag_mc_end:
+ \tag_struct_end:
+ }
+ { #2 }
+ }
+\AssignSocketPlug{tagsupport/math/luamml/hbox}{luamml}
+%</luatex>
+% \end{macrocode}
+%
+% \subsubsection{Artifact characters}
+% Unicode characters like a root sign should be marked as artifacts
+% to avoid duplication e.g. in derivation if mathml
+% structure elements are used that imply the meaning.
+% We test for the socket until the release 2025-06-01.
+% \begin{macrocode}
+\str_if_exist:cF { l__socket_tagsupport/math/luamml/artifact_plug_str }
+ {
+ \NewSocket{tagsupport/math/luamml/artifact}{0}
+ }
+%<*luatex>
+\NewSocketPlug{tagsupport/math/luamml/artifact}{luamml}
+ {
+ \int_if_odd:nT { \int_div_truncate:nn { \l__luamml_flag_int } { 8 } }
+ {
+ \tag_mc_begin:n{artifact}
+ }
+ }
+\AssignSocketPlug{tagsupport/math/luamml/artifact}{luamml}
+%</luatex>
+% \end{macrocode}
+%
+% \subsubsection{Math phantom socket}
+% This socket is used around \cs{finph@nt}.
+% It should provided until 2025-06-01
+% \begin{macrocode}
+\str_if_exist:cF { l__socket_tagsupport/math/luamml/finph@nt_plug_str }
+ {
+ \NewSocket{tagsupport/math/luamml/finph@nt}{2}
+ \NewSocketPlug{tagsupport/math/luamml/finph@nt}{default}{#2}
+ \AssignSocketPlug{tagsupport/math/luamml/finph@nt}{default}
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<*luatex>
+\NewSocketPlug{tagsupport/math/luamml/finph@nt}{luamml}
+ {
+ \luamml_annotate:nen {1}
+ {
+ nucleus = true,
+ core =
+ {
+ [0] = 'mpadded',
+ \ifh@\else
+ width = 0,
+ \fi
+ \ifv@\else
+ height = 0, depth = 0,
+ \fi
+ consume_label'mathphant',
+ }
+ }
+ { #2 }
+ }
+\AssignSocketPlug{tagsupport/math/luamml/finph@nt}{luamml}
+%</luatex>
+% \end{macrocode}
+
+% \subsubsection{Math smash socket}
+% This socket is used around \cs{finsm@sh}.
+% It should provided until 2025-06-01
+% \begin{macrocode}
+\str_if_exist:cF { l__socket_tagsupport/math/luamml/finsm@sh_plug_str }
+ {
+ \NewSocket{tagsupport/math/luamml/finsm@sh}{2}
+ \NewSocketPlug{tagsupport/math/luamml/finsm@sh}{default}{#2}
+ \AssignSocketPlug{tagsupport/math/luamml/finsm@sh}{default}
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<*luatex>
+\NewSocketPlug{tagsupport/math/luamml/finsm@sh}{luamml}
+ {
+ \luamml_annotate:nen {2}
+ {
+ nucleus = true,
+ core =
+ consume_label('mathsmash',
+ function(padded)
+ padded.height, padded.depth = 0, 0~
+ end),
+ }
+ { #2 }
+ }
+\AssignSocketPlug{tagsupport/math/luamml/finsm@sh}{luamml}
+%</luatex>
+% \end{macrocode}
% \subsection{Patching}
% For some packages, we ship with patches to make them more compatible and to
% demonstrate how other code can be patched to work with \texttt{luamml}.
-%
+%
% These are either loaded directly if the packages are loaded or delayed using
% \LaTeX's hook system otherwise.
% \begin{macro}{\__luamml_patch_package:nn, \__luamml_patch_package:n}
@@ -533,7 +988,7 @@
% \end{macrocode}
% \end{macro}
%
-% We currently provide minimal patching for the kernel, \pkg{amsmath} and \pkg{array}.
+% We currently provide minimal patching for the kernel, \pkg{amsmath}.
% Currently only the kernel code supports pdf\TeX, but it's planned to extend this.
% \begin{macrocode}
\RequirePackage { luamml-patches-kernel }
@@ -541,7 +996,6 @@
\__luamml_patch_package:n {amstext}
\__luamml_patch_package:n {amsmath}
\__luamml_patch_package:n {mathtools}
-\__luamml_patch_package:n {array}
%</luatex>
% \end{macrocode}
diff --git a/macros/luatex/latex/luamml/luamml.pdf b/macros/luatex/latex/luamml/luamml.pdf
index 3684db701f..72c8344e30 100644
--- a/macros/luatex/latex/luamml/luamml.pdf
+++ b/macros/luatex/latex/luamml/luamml.pdf
Binary files differ
diff --git a/macros/luatex/latex/marginalia/README.md b/macros/luatex/latex/marginalia/README.md
new file mode 100644
index 0000000000..288fcf4c46
--- /dev/null
+++ b/macros/luatex/latex/marginalia/README.md
@@ -0,0 +1,16 @@
+# `marginalia` - Non-floating marginal content with automatic placement for LuaLaTeX
+
+## Description
+
+This LuaLaTeX package allows the placement of marginal content anywhere, without `\marginpar`'s limits, and
+automatically adjusts positions to prevent overlaps or content being pushed off the page. In short, it tries to combine
+the best features from the packages `marginnote`, `marginfix` and `marginfit` with key--value settings that allow
+fine-grained customization.
+
+## Author
+
+This package is by Alan J. Cain: a.j.cain (AT) gmail.com
+
+## Licence
+
+Released under the LaTeX Project Public License v1.3c or later: https://www.latex-project.org/lppl.txt
diff --git a/macros/luatex/latex/marginalia/marginalia-doc-ysep-explanation.pdf b/macros/luatex/latex/marginalia/marginalia-doc-ysep-explanation.pdf
new file mode 100644
index 0000000000..f667b1f5d6
--- /dev/null
+++ b/macros/luatex/latex/marginalia/marginalia-doc-ysep-explanation.pdf
Binary files differ
diff --git a/macros/luatex/latex/marginalia/marginalia-doc.pdf b/macros/luatex/latex/marginalia/marginalia-doc.pdf
new file mode 100644
index 0000000000..de4e9c33a4
--- /dev/null
+++ b/macros/luatex/latex/marginalia/marginalia-doc.pdf
Binary files differ
diff --git a/macros/luatex/latex/marginalia/marginalia.dtx b/macros/luatex/latex/marginalia/marginalia.dtx
new file mode 100644
index 0000000000..7d7bc9846f
--- /dev/null
+++ b/macros/luatex/latex/marginalia/marginalia.dtx
@@ -0,0 +1,1931 @@
+% \iffalse meta-comment
+%
+% Copyright (C) 2025 Alan J. Cain
+%
+% This file may be distributed and/or modified under the conditions of the LaTeX Project Public License, either version
+% 1.3c of this license or (at your option) any later version. The latest version of this license is in:
+%
+% http://www.latex-project.org/lppl.txt
+%
+% and version 1.3c or later is part of all distributions of LaTeX version 2008-05-04 or later.
+%
+% \fi
+%
+% \iffalse
+%<*driver>
+\PassOptionsToPackage{inline}{enumitem}
+\documentclass{l3doc}
+
+
+\makeatletter
+\ExplSyntaxOn
+
+\cs_gset:Npn \l@subsection { \@dottedtocline{2}{2.5em}{2.8em} } % #2 = 1.5em
+\cs_gset:Npn \l@subsubsection { \@dottedtocline{3}{5.3em}{3.5em} } % #2 = 1.5em
+\cs_gset:Npn \l@paragraph { \@dottedtocline{4}{8.8em}{3.2em} } % #2 = 1.5em
+
+\ExplSyntaxOff
+\makeatother
+
+
+\usepackage{xcolor}
+
+\definecolor{linkcolor}{rgb}{0.0,0.4,0.7}
+\colorlet{citecolor}{linkcolor}
+\colorlet{urlcolor}{linkcolor}
+
+\hypersetup{
+ linkcolor=linkcolor,%
+ citecolor=citecolor,%
+ urlcolor=urlcolor,%
+}
+
+
+\newcommand*\fullref[2]{%
+ \hyperref[#2]{#1\penalty 200\ \ref*{#2}}%
+}
+
+
+\setcounter{tocdepth}{7}
+\numberwithin{figure}{section}
+
+
+
+\usepackage{marginalia}
+
+
+\marginaliasetup{
+ ysep=0pt,
+ ysep page top=10mm,
+ ysep page bottom=5mm,
+}
+\renewcommand*\marginpar[1]{\marginalia[pos=left]{#1}}
+
+
+\usepackage{titleps}
+
+\newpagestyle{sideheadings}[\normalfont]{
+ \sethead{%
+ \smash{%
+ \marginalia[
+ pos=left,
+ valign=b,
+ yshift={-\topskip-2\baselineskip},
+ type=optfixed,
+ xsep=2em,
+ ysep={2\baselineskip},
+ column=one,
+ width=40mm,
+ ]{%
+ \raggedleft
+ \itshape
+ \large
+ \sectiontitle
+ }%
+ }%
+ }
+ {}
+ {}
+ \setfoot{}
+ {\thepage}
+ {}
+}
+
+
+
+
+
+\usepackage{booktabs}
+\usepackage{graphicx}
+
+
+\newlist{vallist}{description}{1}
+\setlist[vallist]{
+ leftmargin=3em,
+ style=unboxed,
+ labelsep=1em,
+ font=\descriptionitemcolon,
+ nosep,
+}
+
+\newcommand*{\descriptionitemcolon}[1]{\kern 1em #1:}
+
+
+\usepackage{siunitx}
+\sisetup{
+ mode=match,
+}
+\DeclareSIUnit\inch{in}
+\DeclareSIUnit\point{pt}
+
+
+\usepackage{tikz}
+\usetikzlibrary{decorations.pathmorphing}
+
+
+\newrobustcmd*\examplelabel[1]{%
+ \smash{%
+ \begin{tikzpicture}[baseline=(labelnode.base)]
+ \node[node font=\sffamily\footnotesize] (labelnode) at (0,0) {#1};
+ \draw[gray] (labelnode.center) circle (5pt);
+ \end{tikzpicture}%
+ }%
+}
+
+
+\usepackage{mathtools}
+
+\DeclarePairedDelimiter{\abs}{\lvert}{\rvert}
+\DeclarePairedDelimiter{\set}{\lbrace}{\rbrace}
+
+
+\newcommand*\key[1]{\texttt{#1}}
+\newcommand*\val[1]{\texttt{#1}}
+\newcommand*\keyvalue[2]{\texttt{#1=#2}}
+
+\NewDocumentCommand{\default}{ m }{(\textit{Default:} #1)}
+
+
+\newcommand*\luafunc[1]{\texttt{#1}}
+\newcommand*\luavar[1]{\texttt{#1}}
+
+
+\usepackage{listings}
+
+\lstset{
+ language=[LaTeX]TeX,
+ basicstyle=\small\ttfamily,
+ basewidth=0.5em,
+}
+
+
+
+\newcounter{sidenote}
+\newcommand*\sidenote[1]{%
+ \stepcounter{sidenote}%
+ \textsuperscript{\thesidenote}%
+ \marginalia[
+ pos=left,
+ style={\raggedright\footnotesize},
+ width=33mm,
+ xsep=1em,
+ ]{%
+ \leavevmode\strut\llap{\thesidenote~}#1\strut%
+ }%
+}
+
+
+
+\begin{document}
+
+\DocInput{\jobname.dtx}
+
+\PrintIndex
+
+\end{document}
+%</driver>
+% \fi
+%
+%
+%
+% \GetFileInfo{marginalia.sty}
+%
+%
+%
+% \title{^^A
+% \pkg{marginalia} ^^A
+% --- Non-floating marginal content with automatic placement for Lua\LaTeX^^A
+% \thanks{This file describes \fileversion, last revised \filedate.}^^A
+% }
+%
+% \author{^^A
+% Alan J. Cain^^A
+% }
+%
+% \date{Released \filedate}
+%
+% \maketitle
+%
+%
+%
+% \begin{abstract}
+% This Lua\LaTeX\ package allows the placement of marginal content anywhere, without \cs{marginpar}'s limits, and
+% automatically adjusts positions to prevent overlaps or content being pushed off the page. In short, it tries to
+% combine the best features from the packages \pkg{marginnote}, \pkg{marginfix} and \pkg{marginfit} with key--value
+% settings that allow fine-grained customization.
+% \end{abstract}
+%
+%
+%
+% \tableofcontents
+%
+%
+%
+% \begin{documentation}
+%
+%
+%
+% \section{Introduction}
+% \pagestyle{sideheadings}
+%
+% The \LaTeX\ \cs{marginpar} command is the basic method for placing content in the margin. For purposes such as drawing
+% attention to particular points in the text, it functions well. Its main limitation is that \cs{marginpar} works via
+% the \LaTeX\ float mechanism and so cannot be used to create marginal content next to a figure, table, or other float,
+% or next to a footnote, or to place running heads in the margin, such as are found in the left-hand margin of this
+% document except for the `implementation' section. (Bringhurst called this style `running shoulder\-heads'
+% \cite[p.~65]{bringhurst_elements}, but the term may be non-standard.)
+%
+% Trying to set many separate pieces of marginal content using \cs{marginpar} can lead to other problems. If two
+% \texttt{marginpar}s would clash, \LaTeX\ shifts the second item downward. But the cumulative effect can lead to
+% \texttt{marginpar}s being shifted downward off the bottom of the page. Further, the asynchronous nature of \TeX's
+% page-breaking can cause:
+% \begin{enumerate*}[label={(\arabic*)}]
+% \item a \texttt{marginpar} to be placed in the wrong margin;
+% \item the topmost \texttt{marginpar} on a page to be unnecessarily shifted downward because of a hypothetical clash
+% that would have occured with the previous \texttt{marginpar}, had they been on the same page.
+% \end{enumerate*}
+%
+% Packages like \pkg{mparhack}\sidenote{\textsc{url:} \url{https://ctan.org/pkg/mparhack}} (Tom Sgouros \& Stefan
+% Ulrich), \pkg{marginnote}\sidenote{\textsc{url}: \url{https://ctan.org/pkg/marginnote}} (Markus Kohm),
+% \pkg{marginfix}\sidenote{\textsc{url:} \url{https://ctan.org/pkg/marginfix}} (Stephen Hicks) and
+% \pkg{marginfit}\sidenote{\textsc{url:} \url{https://ctan.org/pkg/marginfit}} (Maurice Leclaire) were created to avoid
+% these limitations and problems. \pkg{mparhack} only ensures that each \texttt{marginpar} appears on the correct side
+% of the page. \pkg{marginnote} allows marginal content to be placed anywhere, but does not adjust positions to avoid
+% clashes. \pkg{marginfix} adjusts positions, but the unadjusted vertical positioning can be slightly off, and the
+% package still uses floats. \pkg{marginfit} gets positions exactly right, but uses the insert mechanism and so marginal
+% content cannot appear next to floats or footnotes.
+%
+% This Lua\LaTeX\ package, \pkg{marginalia}, provides a \cs{marginalia} command that attempts to avoid these
+% limitations. Marginal content is placed, not via floats or inserts, but by a calculated per-item horizontal shift
+% inside an (invisible) \cs{rlap} or \cs{llap} from the position where the \cs{marginalia} command was issued (which is
+% similar to the technique used by \pkg{marginnote}), plus a calculated per-item vertical shift to avoid clashes with
+% other content. The vertical shift is usually downward, but may be upward when necessary to prevent content from being
+% shifted off the bottom of the page (which is similar to the vertical shifts performed by \pkg{marginfix} and
+% \pkg{marginfit}).
+%
+% The calculation of the horizontal and vertical shifts uses information written to the \file{.aux} file during the
+% previous Lua\LaTeX\ run. It thus takes at least two runs for all content to appear in the correct places. The package
+% reports any changes from the previous run and any problems encountered.
+%
+% \bigskip
+%
+% \noindent\emph{Caveat:} \pkg{marginalia} was written to typeset running heads in the margin, sidenote references,
+% side-captions for floats, and small marginal figures in the author's book \textit{Form \& Number: A History of
+% Mathematical Beauty} \cite{cain_formandnumber_ebook_large}.\sidenote{\textit{Form \& Number} is freely available on
+% the Internet Archive under a Creative Commons licence.
+% \textsc{url}:~\url{https://archive.org/details/cain_formandnumber_ebook_large}} Thus the basic functionality has been
+% tested extensively, and it has performed correctly.
+%
+%
+%
+% \paragraph*{Licence.} \noindent\pkg{marginalia} is released under the \LaTeX\ Project Public Licence v1.3c or
+% later.\footnote{\textsc{url}: \url{https://www.latex-project.org/lppl.txt}}
+%
+%
+%
+% \section{Requirements}
+%
+% \pkg{marginalia} requires
+% \begin{enumerate*}[label={(\arabic*)}]
+% \item Lua\LaTeX,
+% \item a recent \LaTeX\ kernel with \pkg{expl3} support (any kernel version since 2020-02-02 should suffice).
+% \end{enumerate*}
+% It does not depend on any other packages.
+%
+%
+%
+% \section{Installation}
+%
+% To install \pkg{marginalia} manually, run \texttt{luatex marginalia.ins} and copy \texttt{marginalia.sty} and
+% \texttt{marginalia.lua} to somewhere Lua\LaTeX\ can find them.
+%
+%
+%
+% \section{Getting started}
+%
+% \pkg{marginalia} works `out of the box'. Load the package (there are no package options) and use the main
+% \cs{marginalia} command to place marginal content. \fullref{Figure}{fig:getting-started} shows the source code for a
+% small demonstration and the resulting document. \emph{The source code must be processed \textsl{twice} by Lua\LaTeX\
+% for the marginal content to be placed correctly.} (See \fullref{Section}{sec:usage} for discussion of the need for
+% multiple runs.)
+%
+% \begin{figure}[t]
+% \lstinputlisting{marginalia-doc-example.tex}
+% \begin{tikzpicture}
+% \pgfmathsetmacro{\s}{(\textwidth+.4pt)/210mm}
+% \pgfmathsetlengthmacro{\w}{\s*210mm}
+% \pgfmathsetlengthmacro{\h}{\s*100mm}
+% \path[save path=\outline] (0,0) -| ++(\w,-\h) -| cycle;
+% \begin{scope}
+% \clip[use path=\outline];
+% \node[anchor=north west,inner sep=0] at (0,0) {\includegraphics[scale=\s]{marginalia-doc-example.pdf}};
+% \end{scope}
+% \draw[gray,use path=\outline];
+% \end{tikzpicture}
+%
+% \caption{A small demonstration of \pkg{marginalia}.}
+% \label{fig:getting-started}
+% \end{figure}
+%
+% Turn to \fullref{Section}{sec:commands} for a detailed description of the available user commands, and
+% \fullref{Section}{sec:options} for the various options (such as \keyvalue{style}{\meta{code}}) than can be used to
+% change the placement and formatting of the marginal content.
+%
+%
+%
+% \section{User commands}
+% \label{sec:commands}
+%
+% \begin{function}{\marginalia}
+% \begin{syntax}
+% \cs{marginalia}\oarg{options}\marg{content}
+% \end{syntax}
+% This is the basic command for placing marginal content. The \meta{content} can, roughly speaking, be anything: text,
+% mathematics, included graphics, Ti\textit{k}Z. The optional argument \meta{options} is a key--value list that
+% specifies how the content is typeset. The keys are described in \fullref{Subsection}{sec:options}.
+% \end{function}
+%
+%
+%
+% \begin{function}{\marginaliasetup}
+% \begin{syntax}
+% \cs{marginaliasetup}\marg{options}
+% \end{syntax}
+% This command is used to set options globally. The argument \meta{options} is the same kind of key--value list as the
+% \meta{options} argument for the \cs{marginalia} command, and are described in \fullref{Subsection}{sec:options}.
+% \end{function}
+%
+%
+%
+% \begin{function}{\marginalianewgeometry}
+% \begin{syntax}
+% \cs{marginalianewgeometry}
+% \end{syntax}
+% This command signals to \pkg{marginalia} that the page layout has been changed, for instance by using the
+% \cs{newgeometry} command from the \pkg{geometry} package,\sidenote{\textsc{url}:
+% \url{https://ctan.org/pkg/geometry}} or by using the \LaTeX\ command \cs{twocolumn} to switch to two-column mode. It
+% should be issued immediately after such a change, and certainly before the first page with the new layout has been
+% shipped out. There is no harm in using it unnecessarily.
+% \end{function}
+%
+%
+%
+% \subsection{Access to page and column}
+%
+% Two counters available within the \meta{content} of \cs{marginalia} specify the actual page and column in which the
+% call to \cs{marginalia} appears. These counters can be used to select different actions depending on the page on which
+% the content appears or (in two-column mode) whether it pertains to the left or right column. It is best to use the
+% variants of the \key{style} and \key{width} keys if marginal content should have different widths or styles depending
+% on whether they appear on a recto/verso page or pertain to a particular column. These counters are made available for
+% purposes not covered by the \key{style} and \key{width} variants.
+%
+% \begin{variable}{\marginaliapage}
+% A counter register, available within the \meta{content} of \cs{marginalia}, that holds the actual page on which the
+% marginal content appears. The value is based on the previous Lua\LaTeX\ run and will default to \(1\).
+% \end{variable}
+%
+% \begin{variable}{\marginaliacolumn}
+% A counter register, available within the \meta{content} of \cs{marginalia}, that holds the actual column to which
+% the marginal content pertains. The value is \(1\) for the left column, \(2\) for the right column. In one-column
+% mode, the value is always \(0\). (If the key \key{column} is used to manually specify the column to which the
+% content pertains, the value of \cs{marginaliacolumn} will change accordingly.) The value is based on the previous
+% Lua\LaTeX\ run and will default to \(0\).
+% \end{variable}
+%
+%
+%
+% \section{Options}
+% \label{sec:options}
+%
+% The description of keys in this section, which are summarized in \fullref{Table}{tbl:keys-summary}, should be read in
+% conjunction with the discussion of how marginal content is placed in \fullref{Section}{sec:placement}. In particular,
+% the variants of the keys \key{width} and \key{style} follow the terminology shown in
+% \fullref{Figure}{fig:terminology}.
+%
+% \begin{table}[p]
+% \centering
+% \caption{Summary of keys that can be set using \cs{marginaliasetup} or passed in the optional argument to
+% \cs{marginalia}.}
+% \label{tbl:keys-summary}
+% \begin{tabular}{lll}
+% \toprule
+% Key name & Value & Default \\
+% \midrule
+% \key{type} & \(\set{\val{normal},\val{fixed},\val{optfixed}}\) & \val{normal} \\
+% \midrule
+% \key{pos} & \parbox[t]{40mm}{\raggedright\hangindent=2em\(\set{\val{auto},\val{reverse},\val{left},\allowbreak
+% \val{right},\val{nearest}}\)\strut} & \val{auto} \\
+% \key{column} & \(\set{\val{auto},\val{one},\val{left},\val{right}}\) & \val{auto} \\
+% \key{xsep} & Dimension & \val{\cs{marginparwidth}} \\
+% \key{xsep outer} & Dimension & \val{\cs{marginparwidth}} \\
+% \key{xsep inner} & Dimension & \val{\cs{marginparwidth}} \\
+% \key{xsep between} & Dimension & \val{\cs{marginparwidth}} \\
+% \key{xsep recto outer} & Dimension & \val{\cs{marginparwidth}} \\
+% \key{xsep recto inner} & Dimension & \val{\cs{marginparwidth}} \\
+% \key{xsep verso outer} & Dimension & \val{\cs{marginparwidth}} \\
+% \key{xsep verso inner} & Dimension & \val{\cs{marginparwidth}} \\
+% \key{xsep right between} & Dimension & \val{\cs{marginparwidth}} \\
+% \key{xsep left between} & Dimension & \val{\cs{marginparwidth}} \\
+% \midrule
+% \key{valign} & \(\set{\val{t},\val{b}}\) & \val{t} \\
+% \key{yshift} & Dimension & \qty{0}{\point} \\
+% \key{ysep} & Dimension & \val{\cs{marginparpush}} \\
+% \key{ysep above} & Dimension & \val{\cs{marginparpush}} \\
+% \key{ysep below} & Dimension & \val{\cs{marginparpush}} \\
+% \key{ysep page top} & Dimension & \val{\cs{marginparpush}} \\
+% \key{ysep page top} & Dimension & \val{\cs{marginparpush}} \\
+% \midrule
+% \key{width} & Dimension & \val{\cs{marginparwidth}} \\
+% \key{width outer} & Dimension & \val{\cs{marginparwidth}} \\
+% \key{width inner} & Dimension & \val{\cs{marginparwidth}} \\
+% \key{width between} & Dimension & \val{\cs{marginparwidth}} \\
+% \key{width recto outer} & Dimension & \val{\cs{marginparwidth}} \\
+% \key{width recto inner} & Dimension & \val{\cs{marginparwidth}} \\
+% \key{width verso outer} & Dimension & \val{\cs{marginparwidth}} \\
+% \key{width verso inner} & Dimension & \val{\cs{marginparwidth}} \\
+% \key{width right between} & Dimension & \val{\cs{marginparwidth}} \\
+% \key{width left between} & Dimension & \val{\cs{marginparwidth}} \\
+% \key{style} & \LaTeX\ code & [Empty] \\
+% \key{style recto outer} & \LaTeX\ code & [Empty] \\
+% \key{style recto inner} & \LaTeX\ code & [Empty] \\
+% \key{style verso outer} & \LaTeX\ code & [Empty] \\
+% \key{style verso inner} & \LaTeX\ code & [Empty] \\
+% \key{style right between} & \LaTeX\ code & [Empty] \\
+% \key{style left between} & \LaTeX\ code & [Empty] \\
+% \bottomrule
+% \end{tabular}
+% \end{table}
+%
+%
+%
+% \subsection{Type}
+%
+% \DescribeOption{type} The \key{type} of an item of marginal content can be set to one of the following three values:
+% \begin{vallist}
+% \item[\val{normal}] The vertical position of the item will be changed automatically if necessary to prevent a clash
+% with another item of content.
+% \item[\val{fixed}] The vertical position of the item will \emph{never} be changed automatically from the position
+% specified by \key{yshift}, even if there is a clash with another item. (The type \val{fixed} was designed for
+% setting float captions in the margin, since a caption should not move away from the float with which it is
+% associated.)
+% \item[\val{optfixed}] The vertical position of the item will \emph{never} be changed automatically from the position
+% specified by \key{yshift}, even if there is a clash with another item. But an \val{optfixed} item will not appear in
+% the document if it would clash with a \val{fixed} item. (The type \val{optfixed} was designed for setting running
+% heads in the margin, which should not appear if they would clash with a figure caption set in the margin.)
+% \end{vallist}
+% \default{\val{normal}}
+%
+%
+%
+% \subsection{Horizontal placement}
+%
+% \DescribeOption{pos} The position in which an item of marginal content should be placed. It can be set to one of the
+% the following four values:
+% \begin{vallist}
+% \item[\val{auto}] Place the item in the default position as described in \fullref{Section}{sec:placement}: the outer
+% margin in single-column mode, and on the opposite side from the other column in two-column mode.
+% \item[\val{reverse}] Place the item on the opposite side of the text block (in one-column mode) or column (in
+% two-column mode) from \val{auto}.
+% \item[\val{left}] The left side of the text block or column.
+% \item[\val{right}] The right side of the text block of column.
+% \item[\val{nearest}] The side of the text block or column nearest to which \cs{marginalia} was called.
+% \end{vallist}%
+% \default{\val{auto}}
+%
+%
+% \medskip\goodbreak
+%
+%
+% \DescribeOption{column} In two-column mode, \pkg{marginalia} tries to determine to which column an item of marginal
+% content pertains using the position of the call to \cs{marginalia}. If the call is to the left of the mid-point
+% between the columns, the item is assumed to pertain to the left column; otherwise, it is assumed to pertain to the
+% right column. In certain situations, this might lead to undesired placement of the item. In particular, any call to
+% \cs{marginalia} in a full-width float in two-column mode would be handled as if it were a call from one of the columns
+% and might thus be set in the wrong place. Similarly, an overfull hbox or a piece of \cs{rlap}-ped text might carry a
+% call to \cs{marginalia} from the left column text into the area of the page occupied by the right column.
+%
+% The key \key{column} can be used to specify which column \pkg{marginalia} should place the item in. It can be set to
+% one of four values:
+% \begin{vallist}
+% \item[\val{auto}] Automatically determine which column an item of marginal content is placed in.
+% \item[\val{one}] Treat the item as being called from one-column mode.
+% \item[\val{left}] Treat the item as pertaining to the left column.
+% \item[\val{right}] Treat the item as pertaining to the right column.
+% \end{vallist}
+% The value of \key{column} has no effect in one-column mode. \default{\val{auto}}
+%
+%
+% \medskip\goodbreak
+%
+%
+% \DescribeOption{xsep}
+% \DescribeOption{xsep outer}
+% \DescribeOption{xsep inner}
+% \DescribeOption{xsep between}
+% \DescribeOption{xsep recto outer}
+% \DescribeOption{xsep recto inner}
+% \DescribeOption{xsep verso outer}
+% \DescribeOption{xsep verso inner}
+% \DescribeOption{xsep right between}
+% \DescribeOption{xsep left between}
+% These keys specify the horizontal separation between an item of marginal content and the text block next
+% to which it is placed. Which separation is used will depend on where the item is typeset. The terminology is as
+% in \fullref{Figure}{fig:terminology}.
+% \begin{vallist}
+% \item[\key{xsep recto outer}] used for an item in the outer margin of a recto page.
+% \item[\key{xsep recto inner}] used for an item in the inner margin of a recto page.
+% \item[\key{xsep verso outer}] used for an item in the outer margin of a verso page.
+% \item[\key{xsep verso inner}] used for an item in the inner margin of a verso page.
+% \item[\key{xsep right between}] used for an item set from the right column between the columns.
+% \item[\key{xsep left between}] used for an item set from the left column between the columns.
+% \item[\key{xsep outer}] a shorthand for setting the keys \key{xsep recto outer} and \key{xsep verso outer}
+% simultaneously to the same value.
+% \item[\key{xsep inner}] a shorthand for setting the keys \key{xsep recto inner} and \key{xsep verso inner}
+% simultaneously to the same value.
+% \item[\key{xsep between}] a shorthand for setting the keys \key{xsep right between} and \key{xsep left between}
+% simultaneously to the same value.
+% \item[\key{xsep}] a shorthand for setting all of these keys simultaneously.
+% \end{vallist}
+% (The shorthands \key{xsep outer} and \key{xsep inner} exist because page geometry is usually symmetrical between recto
+% and verso pages as regards outer and inner margins. The shorthand \key{xsep between} exists because the space between
+% columns, if used at all for marginal content, will often be shared equally.) Each of these keys must be set to a valid
+% dimension. \default{value of \cs{marginparsep} when the package is loaded}
+%
+%
+%
+% \subsection{Vertical placement}
+%
+% \DescribeOption{valign} The option \key{valign} can be either \val{t} or \val{b}. In the former case, the baseline of
+% the marginal content item is the baseline of the topmost box in its contents; in the latter case, its baseline is the
+% baseline of the bottommost box in its contents. (Essentially, \cs{vtop} and \cs{vbox} are used to set the two options)
+% \default{\val{t}}
+%
+%
+% \medskip\goodbreak
+%
+%
+% \DescribeOption{yshift}
+% The key \key{yshift} is used to shift the default position of the marginal content item up (positive) or
+% down (negative) from its normal position, which is to have its baseline aligned with the baseline of the callout
+% position. It must be set to a valid dimension. Note that if \keyvalue{type}{normal}, then the vertical
+% position may be adjusted from that specified by \key{yshift}. If this is not desired, specify a different \key{type}.
+% \default{0pt}.
+%
+%
+% \medskip\goodbreak
+%
+%
+% \DescribeOption{ysep}
+% \DescribeOption{ysep above}
+% \DescribeOption{ysep below}
+% \DescribeOption{ysep page top}
+% \DescribeOption{ysep page bottom}
+% These keys specify the minimum vertical separation above and below an item of marginal content
+% \begin{vallist}
+% \item[\key{ysep above}] the minimum vertical separation between an item and the one above.
+% \item[\key{ysep below}] the minimum vertical separation between an item and the one below.
+% \item[\key{ysep page top}] the minimum vertical separation between an item and top of the page.
+% \item[\key{ysep page bottom}] the minimum vertical separation between an item and bottom of the page.
+% \item[\key{ysep}] is a shorthand for setting all of these keys simultaneously to the same value.
+% \end{vallist}
+% (See \fullref{Figure}{fig:ysep-explanation}.) Each of these keys must be set to a valid dimension. \default{value of
+% \cs{marginparpush} when the package is loaded}.
+%
+% \begin{figure}[t]
+% \centering
+% \includegraphics{marginalia-doc-ysep-explanation.pdf}
+% \caption{(Illustration of \key{ysep}) The length \examplelabel{1} is at least the value of \key{ysep below}
+% specified (locally or globally) for marginal content item \examplelabel{A} and at least the value of \key{ysep
+% above} specified for item \examplelabel{B}. In this example diagram, \examplelabel{B} has been automatically moved
+% down from its natural position to maintain the required distance. Similarly, the length \examplelabel{2} is at least
+% the value of \key{ysep below} specified for \examplelabel{C} and at least the value of \key{ysep above} specified
+% for \examplelabel{D}, and the length \examplelabel{3} is at least the value of \key{ysep page bottom} specified for
+% \examplelabel{D}. In this example, to maintain the required distances, \examplelabel{C} and \examplelabel{D} have
+% been automatically moved (respectively) up and down from their natural positions.}
+% \label{fig:ysep-explanation}
+% \end{figure}
+%
+%
+%
+% \subsection{Appearance}
+%
+% An item of marginal content that appears in the inner margin might be narrower than one that appears in the outer
+% margin, and an item appearing in the outer margin of a recto page might be set ragged right, while an item appearing
+% in the outer margin of a verso page might be set ragged left. And since it is not known where an item will appear
+% until the page is assembled, the keys in this subsection, dealing with the width and style of an item, have variants
+% that apply depending on where the item appears on the page.
+%
+%
+% \medskip\goodbreak
+%
+%
+% \DescribeOption{width}
+% \DescribeOption{width outer}
+% \DescribeOption{width inner}
+% \DescribeOption{width between}
+% \DescribeOption{width recto outer}
+% \DescribeOption{width recto inner}
+% \DescribeOption{width verso outer}
+% \DescribeOption{width verso inner}
+% \DescribeOption{width right between}
+% \DescribeOption{width left between}
+% These keys specify the width of the an item of marginal content (or, more precisely, the \cs{hsize} of the box into
+% which the item is typeset). Which width is chosen will depend on the where the item is typeset. The terminology is as
+% in \fullref{Figure}{fig:terminology}.
+% \begin{vallist}
+% \item[\key{width recto outer}] used for an item in the outer margin of a recto page.
+% \item[\key{width recto inner}] used for an item in the inner margin of a recto page.
+% \item[\key{width verso outer}] used for an item in the outer margin of a verso page.
+% \item[\key{width verso inner}] used for an item in the inner margin of a verso page.
+% \item[\key{width right between}] used for an item set from the right column and placed between the columns.
+% \item[\key{width left between}] used for an item set from the right column and placed between the columns.
+% \item[\key{width outer}] a shorthand for setting the keys \key{width recto outer} and \key{width verso outer}
+% simultaneously to the same value.
+% \item[\key{width inner}] a shorthand for setting the keys \key{width recto inner} and \key{width verso inner}
+% simultaneously to the same value.
+% \item[\key{width between}] a shorthand for setting the keys \key{width right between} and \key{width left between}
+% simultaneously to the same value.
+% \item[\key{width}] a shorthand for setting all of these keys simultaneously.
+% \end{vallist}
+% (The shorthands \key{width outer} and \key{width inner} exist because page geometry is usually symmetrical between
+% recto and verso pages as regards outer and inner margins. The shorthand \key{width between} exists because the space
+% between columns, if used at all for marginal content, will often be shared equally.) Each of these keys must be set to
+% a valid dimension. \default{value of \cs{marginparwidth} when the package is loaded}
+%
+%
+% \medskip\goodbreak
+%
+%
+% \DescribeOption{style}
+% \DescribeOption{style recto outer}
+% \DescribeOption{style recto inner}
+% \DescribeOption{style verso outer}
+% \DescribeOption{style verso inner}
+% \DescribeOption{style right between}
+% \DescribeOption{style left between}
+% These keys specify the style with which an item of marginal content is typeset. Which style is chosen will depend on
+% where the item is typeset. The terminology is as in \fullref{Figure}{fig:terminology}.
+% \begin{vallist}
+% \item[\key{style recto outer}] used for an item in the outer margin of a recto page.
+% \item[\key{style recto inner}] used for an item in the inner margin of a recto page.
+% \item[\key{style verso outer}] used for an item in the outer margin of a verso page.
+% \item[\key{style verso inner}] used for an item in the inner margin of a verso page.
+% \item[\key{style right between}] used for an item set from the right column between the columns.
+% \item[\key{style left between}] used for an item set from the right column between the columns.
+% \item[\key{style}] a shorthand for setting all of these keys simultaneously.
+% \end{vallist}
+% Each of these keys should be set to \LaTeX\ code that specifies the style. \default{[Empty]}
+%
+%
+%
+% \section{Placement}
+% \label{sec:placement}
+%
+% The placement of an item of marginal content depends on where the call to \cs{marginalia} appears in the finished
+% document. Both horizontal and vertical placement can be complicated.
+%
+%
+%
+% \subsection{Horizontal placement}
+%
+% To understand the horizontal placement, first recall some terminology: a recto page is an odd-numbered page in
+% two-sided mode, or any page in one-sided mode; a verso page is an even-numbered page in two-sided mode. The
+% description in the paragraphs that follow is summarized in \fullref{Figure}{fig:terminology}.
+%
+% \begin{figure}[t]
+% \centering
+% \begin{tikzpicture}[
+% x={.45*\textwidth},
+% y={sqrt(2)*.45*\textwidth},
+% ]
+%
+% \begin{scope}[
+% every node/.style ={
+% node font=\footnotesize\scshape,
+% align=center,
+% }
+% ]
+% \begin{scope}
+% \clip[decorate,decoration={snake,amplitude=1mm,segment length=5mm}] (-1,0) -- (1,0) -- (1,.5) -| cycle;
+% \begin{scope}[fill=lightgray]
+% \fill (-.7,-.35) rectangle (-.2,.35);
+% \node at (-.45,.175) {one\\column};
+% \fill (.7,-.35) rectangle (.2,.35);
+% \node at (.45,.175) {one\\column};
+% \end{scope}
+% \end{scope}
+%
+% \begin{scope}
+% \clip[decorate,decoration={snake,amplitude=1mm,segment length=5mm}] (-1,0) -- (1,0) -- (1,-.5) -| cycle;
+% \begin{scope}[fill=lightgray]
+% \fill (-.85,-.35) rectangle (-.65,.35);
+% \node at (-.75,-.175) {left\\column};
+% \fill (-.35,-.35) rectangle (-.15,.35);
+% \node at (-.25,-.175) {right\\column};
+% \fill (.35,-.35) rectangle (.15,.35);
+% \node at (.25,-.175) {left\\column};
+% \fill (.85,-.35) rectangle (.65,.35);
+% \node at (.75,-.175) {right\\column};
+% \end{scope}
+% \end{scope}
+%
+% \end{scope}
+%
+% \pgfresetboundingbox
+%
+% \draw[white,line width=1pt,decorate,decoration={snake,amplitude=1mm,segment length=5mm}] (-1,0) -- (1,0);
+%
+% \draw (0,-.5) -- (0,.5);
+% \draw (-1,-.5) rectangle (1,.5);
+%
+% \begin{scope}[
+% every node/.style={
+% node font=\footnotesize\ttfamily,
+% inner xsep=3pt,
+% }
+% ]
+% \node[anchor=north west,align=left] at (.7,.35) {auto\\right};
+% \node[anchor=north east,align=right] at (.2,.35) {reverse\\left};
+%
+% \node[anchor=south east,align=right] at (.15,-.35) {auto\\left};
+% \node[anchor=north,shift={(.03,0)},align=left] at (.35,-.35) {reverse\\right};
+% \node[anchor=north,shift={(-.03,0)},align=right] at (.65,-.35) {reverse\\left};
+% \node[anchor=south west,align=left] at (.85,-.35) {auto\\\strut\smash{right}};
+%
+% \node[anchor=north east,align=right] at (-.7,.35) {auto\\left};
+% \node[anchor=north west,align=left] at (-.2,.35) {reverse\\right};
+%
+% \node[anchor=south east,align=right] at (-.85,-.35) {auto\\left};
+% \node[anchor=north,shift={(.03,0)},align=left] at (-.65,-.35) {reverse\\right};
+% \node[anchor=north,shift={(-.03,0)},align=right] at (-.35,-.35) {reverse\\left};
+% \node[anchor=south west,align=left] at (-.15,-.35) {auto\\right};
+%
+% \end{scope}
+%
+% \begin{scope}[
+% every node/.style={
+% node font=\small\ttfamily,
+% inner xsep=6pt,
+% }
+% ]
+% \node[rotate=90,anchor=north] at (-1,0) {verso outer};
+% \node[rotate=90,anchor=north east,align=right] at (-.65,0) {left\\[-1pt]between};
+% \node[rotate=-90,anchor=north west,align=left] at (-.35,0) {right\\[-1pt]between};
+% \node[rotate=-90,anchor=north] at (0,0) {verso inner};
+% \node[rotate=90,anchor=north] at (0,0) {recto inner};
+% \node[rotate=90,anchor=north east,align=right] at (.35,0) {left\\[-1pt]between};
+% \node[rotate=-90,anchor=north west,align=left] at (.65,0) {right\\[-1pt]between};
+% \node[rotate=-90,anchor=north] at (1,0) {recto outer};
+% \end{scope}
+%
+% \end{tikzpicture}
+% \caption{Summary of the positioning of marginal content using \key{pos}, and terminology used in \key{width} and
+% \key{style} keys, on recto and verso pages, in both one-column and two-column mode.}
+% \label{fig:terminology}
+% \end{figure}
+%
+%
+% In one-column mode, marginal content is placed by default in the outer margin: right on recto pages, left on verso
+% pages. If \keyvalue{pos}{reverse} is applied, it is placed in the inner margin: left on recto pages, right on verso
+% pages.
+%
+% In two-column mode, the default placement is next to the column in which the call to \cs{marginalia} appears, on the
+% side opposite to the other column. Thus, if the call to \cs{marginalia} was in the left column, the marginal content
+% item is placed by default on the left: on a recto page, the inner margin, on a verso page, the outer margin. If
+% \keyvalue{pos}{reverse} is applied, it is placed between the two columns, adjacent to the left column. If the call to
+% \cs{marginalia} was in the right column, the item is placed by default on the right: on a recto page, the
+% outer margin, on a verso page, the inner margin. If \keyvalue{pos}{reverse} is applied, it is placed between the two
+% columns, adjacent to the right column.
+%
+% \keyvalue{pos}{left} specifies that the item is to be placed on the left of the text block or column
+% containing the call to \cs{marginalia}.
+%
+% \keyvalue{pos}{right} similarly specifies that the item is to be placed on the right of the text block or column
+% containing the call to \cs{marginalia}.
+%
+% \pkg{marginalia} determines in which column the call to \cs{marginalia} was made using its horizontal position. As
+% discussed in the description of key \key{column}, there are situations where this can go wrong and which
+% necessitate a manual specification of a particular column.
+%
+%
+%
+% \subsection{Vertical placement}
+% \label{subsec:vertical-placement}
+%
+% \pkg{marginalia} tries by default to place the each item of marginal content with its baseline shifted by the value of
+% \key{yshift} (by default, \qty{0}{\point}) from the baseline where \cs{marginalia} was called. The actual vertical
+% placement is calculated by the procedure described below, carried out for the items appearing in a particular
+% horizontal location. (As shown in \fullref{Figure}{fig:terminology}, in one-column mode the possible locations are in
+% outer and inner margins; in two-column mode the possible locationd are the outer and inner margins and on the left and
+% right sides of the space between the columns.) A \emph{clash} exists when two items are closer than specified by
+% \key{ysep below} for the upper item or \key{ysep above} for the lower item, whichever is greater.
+%
+% For the items in each horizontal location, the procedure is as follows:
+% \begin{enumerate}
+% \item Place the items appearing in a given horizontal location on the page into a list.
+% \item Set the vertical shift of each item to the one specified by \key{yshift}.
+% \item For each \keyvalue{type}{optfixed} item, if it clashes with any \keyvalue{type}{fixed} item, delete it from
+% the list of items that appear on the page.
+% \item Sort the list by the position of the call to \cs{marginalia}, top-to-bottom, left-to-right, breaking ties
+% by the order of calls. (Because of floats, footnotes, etc., the sorted order of the list is not necessarily
+% the same as the order of appearance of \cs{marginalia} commands in the source code.)
+% \item Pass through the list of items in sorted order. For each \keyvalue{type}{normal} item, if necessary shift it
+% in a negative (downward) direction so that it
+% \begin{enumerate*}[label={(\arabic*)}]
+% \item does not reach closer to the top of the page than specified by \texttt{ysep page top}, and
+% \item does not clash with the previous (above) item.
+% \end{enumerate*}
+% (After this stage, it is possible for an assigned vertical shift to push a \keyvalue{type}{normal} item off
+% the bottom of the page.)
+% \item Pass through the list of items in the reverse of the sorted order. For each \keyvalue{type}{normal} item, if
+% necessary shift it in a positive (upward) direction so that it
+% \begin{enumerate*}[label={(\arabic*)}]
+% \item does not reach closer to the bottom of the page than specified by \texttt{ysep page bottom}, and
+% \item does not clash with the next (below) item.
+% \end{enumerate*}
+% \end{enumerate}
+% During this process, it may be found that it is impossible to prevent clashes or items reaching beyong the limits
+% (e.g. fixed items clash with each other; a fixed item conflicts with \texttt{ysep page top} or \texttt{ysep page
+% bottom}, or there are simply too many items of marginal content to fit (in which case, the top of some of them will be
+% above the limit specified by \texttt{ysep page top} or will clash with fixed items)). In these cases, warnings are
+% issued at the end of the Lua\LaTeX\ run.
+%
+%
+%
+% \section{Usage notes}
+% \label{sec:usage}
+%
+% \pkg{marginalia} requires a minimum of two Lua\LaTeX\ runs, and often more, to place items of marginal content
+% correctly. On the first pass, information about items, including their vertical size, is written to the \file{.aux}
+% file, and this information is used to position them correctly on the next run. However, because \key{width} and
+% \key{style} have variants dependent on the margin in which the item is placed, an item may only be typeset at the
+% correct size on this second run. Thus the vertical size of the item may have changed and so the information written to
+% the \file{.aux} file on the previous run may be out of date. In this case a third run may be needed for correct
+% placement.
+%
+% More runs may be needed if the position of the call to \cs{marginalia} changes between runs. Provided the main text
+% stabilizes, the placement of items using \cs{marginalia} should be correct two runs later.
+%
+% At the end of the Lua\LaTeX\ run, \pkg{marginalia} reports any problems encountered in the vertical placement of items
+% (as decribed at the end of \fullref{Subsection}{subsec:vertical-placement}). These problems are based on calculations
+% made on the basis of information from the previous written to the \file{.aux} file on the previous run, and may not
+% arise if item positions or sizes (i.e. height or depth) have changed. \pkg{marginalia} also reports any changes in
+% positions or sizes compared to the previous run.
+%
+% In these reports, a page number refers to a visible page number if it is prefixed with `\texttt{p}'; it otherwise
+% refers to the absolute page number of the output.
+%
+%
+%
+% \section{Incompatibilities}
+%
+% Using \pkg{marginalia} alongside \cs{marginpar} or packages like \pkg{mparhak}, \pkg{marginnote}, \pkg{marginfix}, or
+% \pkg{marginfit} should not produce any errors, but \pkg{marginalia} will ignore marginal content not created using
+% \cs{marginalia}; for example, an item of marginal content created using \cs{marginalia} might overlap with one created
+% using \cs{marginpar}.
+%
+%
+%
+% \section{Limitations}
+% \label{sec:limitations}
+%
+% As noted in the introduction, \pkg{marginalia} was originally written to typeset a particular kind of book. It thus
+% has several limitations. Three of these are:
+% \begin{description}
+% \item[Lua\LaTeX only] Most of the code for deciding the placement of items of marginal content is written in Lua.
+% In principle, the it could be replaced with a pure \LaTeX\ solution.
+% \item[No support for `moving past' fixed items] The adjustment of vertical positions will never cause a
+% \keyvalue{type}{normal} item to be shifted past a \keyvalue{type}{fixed} one, even when there is space on
+% the other side. It may be desirable to have this available as an option.
+% \item[No support for nested content items] Nesting might be desirable for typesetting editions of manuscripts
+% which sometimes contain marginal glosses, and then glosses upon those glosses.
+% \end{description}
+%
+% The lack of any built-in facility for producing (for example) numbered sidenotes is a conscious design choice. This is
+% properly the concern of a command that merely uses \cs{marginalia} to place the notes correctly.
+%
+%
+%
+% ^^A\bibliography{\jobname}
+% ^^A\bibliographystyle{alphaabbrv}
+%
+% \begin{thebibliography}{Cai24}
+%
+% \bibitem[Bri04]{bringhurst_elements}
+% R.~Bringhurst.
+% \newblock {\em {T}he {E}lements of {T}ypographic {S}tyle}.
+% \newblock Hartley {\&} Marks, version 3.0, 2004.
+%
+% \bibitem[Cai24]{cain_formandnumber_ebook_large}
+% A.~J. Cain.
+% \newblock {\em {F}orm {\&} {N}umber: {A} {H}istory of {M}athematical {B}eauty}.
+% \newblock Lisbon, 2024.
+% \newblock {\sc url:}
+% \href{https://archive.org/details/cain_formandnumber_ebook_large}{\nolinkurl{https://archive.org/details/cain_formandnumber_ebook_large}}.
+%
+% \end{thebibliography}
+%
+%
+%
+% \end{documentation}
+%
+%
+%
+% \iffalse
+%<*example>
+\documentclass[11pt]{article}
+
+\usepackage{marginalia}
+
+\begin{document}
+
+Here is some body text.\marginalia{Here is a marginal note.} Some more
+body text.\marginalia[style=\footnotesize\itshape\raggedright]{Here is another
+ marginal note, set in smaller text and italics, whose position has been been
+ adjusted automatically.}
+
+Some final body text.\marginalia[pos=left, valign=b, style=\sffamily\raggedleft,
+width=35mm]{This note is placed on the left side of the page, wider, in sans
+ serif, ragged left, and bottom-aligned.}
+
+\end{document}
+%</example>
+% \fi
+%
+%
+%
+% \clearpage
+% \begin{implementation}
+%
+%
+%
+% \section{Implementation (\LaTeX\ package)}
+%
+% \begin{macrocode}
+%<*package>
+%<@@=marginalia>
+% \end{macrocode}
+%
+%
+%
+% \subsection{Initial set-up}
+%
+% Package identification/version information.
+% \begin{macrocode}
+\NeedsTeXFormat{LaTeX2e}[2020-02-02]
+\ProvidesExplPackage{marginalia}{2025-02-17}{0.80.1}
+ {Non-floating marginal content for LuaLaTeX}
+% \end{macrocode}
+% Check that Lua\TeX\ is in use.
+% \begin{macrocode}
+\sys_if_engine_luatex:F
+ {
+ \msg_new:nnn{marginalia}{lualatex_required}
+ {LuaLaTeX~required.~Package~loading~will~abort.}
+ \msg_critical:nn{marginalia}{lualatex_required}
+ }
+% \end{macrocode}
+%
+%
+%
+% \subsection{Options}
+%
+% Set up the key--value options and the variables in which the settings will be stored.
+%
+%
+%
+% \subsubsection{Type}
+%
+% \begin{macro}{
+% \l_@@_type_int,
+% }
+% A key to store the type of the marginal content item. The setting is held in an integer variable:
+% \(1 = \key{normal}\), \(2 = \key{fixed}\), \(3 = \key{optfixed}\).
+% \begin{macrocode}
+\int_new:N\l_@@_type_int
+\keys_define:nn { marginalia }
+{
+ type .choices:nn = {normal,fixed,optfixed}{
+ \int_set:Nn\l_@@_type_int{\l_keys_choice_int}
+ },
+ type .initial:n = normal,
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \subsubsection{Horizontal placement}
+%
+% \begin{macro}{
+% \l_@@_pos_int,
+% }
+% A key to store the specified position of the marginal content item. The setting is held in an integer variable:
+% \(1 = \key{auto}\), (the outer margin in one-column mode; left margin in left column, right margin in right column
+% in two-column mode) \(2 = \key{reverse}\) (inner margin in one-column mode; between the columns in two-column mode),
+% \(3 = \key{left}\), \(4 = \key{right}\), \(5 = \key{nearest}\).
+% \begin{macrocode}
+\int_new:N\l_@@_pos_int
+\keys_define:nn { marginalia }
+{
+ pos .choices:nn = {auto,reverse,left,right,nearest}{
+ \int_set:Nn\l_@@_pos_int{\l_keys_choice_int}
+ },
+ pos .initial:n = auto
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{
+% \l_@@_column_int,
+% }
+% A key to force the marginal content item to be treated in one-column mode or as being set from the left or right
+% column. The setting is held in an integer variable: \(-1 = \key{auto}\) (automatic), \(0 = \key{one}\) (one-column
+% mode), \(1 = \key{left}\) (left column) \(2 = \key{right}\) (right column).
+% \begin{macrocode}
+\int_new:N\l_@@_column_int
+\keys_define:nn { marginalia }
+{
+ column .choices:nn = {auto,one,left,right}{
+ \int_set:Nn\l_@@_column_int{\l_keys_choice_int-2}
+ },
+ column .initial:n = auto,
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{
+% \l_@@_xsep_recto_outer_dim,
+% \l_@@_xsep_recto_inner_dim,
+% \l_@@_xsep_verso_outer_dim,
+% \l_@@_xsep_verso_inner_dim,
+% \l_@@_xsep_right_between_dim,
+% \l_@@_xsep_left_between_dim,
+% }
+% Dimension keys to hold the separation between the marginal content item and the main text, which can be dependent on
+% where it appears on the page.
+% \begin{macrocode}
+\keys_define:nn { marginalia }
+{
+ xsep~recto~outer .dim_set:N = \l_@@_xsep_recto_outer_dim,
+ xsep~recto~inner .dim_set:N = \l_@@_xsep_recto_inner_dim,
+ xsep~verso~outer .dim_set:N = \l_@@_xsep_verso_outer_dim,
+ xsep~verso~inner .dim_set:N = \l_@@_xsep_verso_inner_dim,
+ xsep~right~between .dim_set:N = \l_@@_xsep_right_between_dim,
+ xsep~left~between .dim_set:N = \l_@@_xsep_left_between_dim,
+ xsep .code:n = {
+ \keys_set:nn{ marginalia }{
+ xsep~recto~outer=#1,
+ xsep~recto~inner=#1,
+ xsep~verso~outer=#1,
+ xsep~verso~inner=#1,
+ xsep~right~between=#1,
+ xsep~left~between=#1,
+ }
+ },
+ xsep~outer .code:n = {
+ \keys_set:nn{ marginalia }{
+ xsep~recto~outer=#1,
+ xsep~verso~outer=#1,
+ }
+ },
+ xsep~inner .code:n = {
+ \keys_set:nn{ marginalia }{
+ xsep~recto~inner=#1,
+ xsep~verso~inner=#1,
+ }
+ },
+ xsep~between .code:n = {
+ \keys_set:nn{ marginalia }{
+ xsep~right~between=#1,
+ xsep~left~between=#1,
+ }
+ },
+ xsep .initial:n = \marginparsep,
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \subsubsection{Vertical placement}
+%
+% \begin{macro}{
+% \l_@@_valign_int,
+% }
+% A key to store the vertical alignment of the marginal content item. The setting is held in a integer variable:
+% \(1 = \key{t}\) (aligned at the baseline of the topmost line of the item), \(2 = \key{b}\) (aligned at the baseline
+% of the bottommost line of the item).
+% \begin{macrocode}
+\int_new:N\l_@@_valign_int
+\keys_define:nn { marginalia }
+{
+ valign .choices:nn = {t,b}{
+ \int_set_eq:NN\l_@@_valign_int\l_keys_choice_int
+ },
+ valign .initial:n = t,
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{
+% \l_@@_default_yshift_dim,
+% }
+% Dimension key to hold the default vertical shift of the marginal content item from its natural position.
+% \begin{macrocode}
+\keys_define:nn { marginalia }
+{
+ yshift .dim_set:N = \l_@@_default_yshift_dim,
+ yshift .initial:n = 0pt,
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{
+% \l_@@_ysep_above_dim,
+% \l_@@_ysep_below_dim,
+% \l_@@_ysep_page_top_dim,
+% \l_@@_ysep_page_bottom_dim
+% }
+% Dimension keys to hold the the minimum vertical spacing between a marginal content item and (respectively) the item
+% above, the item below, the page top, and the page bottom.
+% \begin{macrocode}
+\keys_define:nn { marginalia }
+{
+ ysep~above .dim_set:N = \l_@@_ysep_above_dim,
+ ysep~below .dim_set:N = \l_@@_ysep_below_dim,
+ ysep~page~top .dim_set:N = \l_@@_ysep_page_top_dim,
+ ysep~page~bottom .dim_set:N = \l_@@_ysep_page_bottom_dim,
+ ysep .code:n = {
+ \keys_set:nn{ marginalia }{
+ ysep~below=#1,
+ ysep~above=#1,
+ ysep~page~top=#1,
+ ysep~page~bottom=#1,
+ }
+ },
+ ysep .initial:n = \marginparpush,
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \subsubsection{Appearance}
+%
+% \begin{macro}{
+% \l_@@_width_recto_outer_dim,
+% \l_@@_width_recto_inner_dim,
+% \l_@@_width_verso_outer_dim,
+% \l_@@_width_verso_inner_dim,
+% \l_@@_width_right_between_dim,
+% \l_@@_width_left_between_dim,
+% }
+% Dimension keys to hold the width of the marginal content item, which can be dependent on where it appears on the
+% page.
+% \begin{macrocode}
+\keys_define:nn { marginalia }
+{
+ width~recto~outer .dim_set:N = \l_@@_width_recto_outer_dim,
+ width~recto~inner .dim_set:N = \l_@@_width_recto_inner_dim,
+ width~verso~outer .dim_set:N = \l_@@_width_verso_outer_dim,
+ width~verso~inner .dim_set:N = \l_@@_width_verso_inner_dim,
+ width~right~between .dim_set:N = \l_@@_width_right_between_dim,
+ width~left~between .dim_set:N = \l_@@_width_left_between_dim,
+ width .code:n = {
+ \keys_set:nn{ marginalia }{
+ width~recto~outer=#1,
+ width~recto~inner=#1,
+ width~verso~outer=#1,
+ width~verso~inner=#1,
+ width~right~between=#1,
+ width~left~between=#1,
+ }
+ },
+ width~outer .code:n = {
+ \keys_set:nn{ marginalia }{
+ width~recto~outer=#1,
+ width~verso~outer=#1,
+ }
+ },
+ width~inner .code:n = {
+ \keys_set:nn{ marginalia }{
+ width~recto~inner=#1,
+ width~verso~inner=#1,
+ }
+ },
+ width~between .code:n = {
+ \keys_set:nn{ marginalia }{
+ width~right~between=#1,
+ width~left~between=#1,
+ }
+ },
+ width .initial:n = \marginparwidth,
+}
+% \end{macrocode}
+% \end{macro}
+%
+%% \begin{macro}{
+% \l_@@_style_recto_outer_tl,
+% \l_@@_style_recto_inner_tl,
+% \l_@@_style_verso_outer_tl,
+% \l_@@_style_verso_inner_tl,
+% \l_@@_style_right_between_tl,
+% \l_@@_style_left_between_tl,
+% }
+% Token list keys to hold the style with which a marginal content item is typeset, which can be dependent on where it
+% appears on the page.
+% \begin{macrocode}
+\keys_define:nn { marginalia }
+{
+ style~recto~outer .tl_set:N = \l_@@_style_recto_outer_tl,
+ style~recto~inner .tl_set:N = \l_@@_style_recto_inner_tl,
+ style~verso~outer .tl_set:N = \l_@@_style_verso_outer_tl,
+ style~verso~inner .tl_set:N = \l_@@_style_verso_inner_tl,
+ style~right~between .tl_set:N = \l_@@_style_right_between_tl,
+ style~left~between .tl_set:N = \l_@@_style_left_between_tl,
+ style .code:n = {
+ \keys_set:nn{ marginalia }{
+ style~recto~outer=#1,
+ style~recto~inner=#1,
+ style~verso~outer=#1,
+ style~verso~inner=#1,
+ style~right~between=#1,
+ style~left~between=#1,
+ }
+ },
+ style .initial:n = {},
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \subsection{Lua backend and interface}
+%
+% Load the Lua backend.
+% \begin{macrocode}
+ \lua_now:n{
+ marginalia = require('marginalia')
+ }
+% \end{macrocode}
+%
+% The following 9 macros interface between \LaTeX\ and Lua code. Each control sequence \cs[no-index]{@@_lua_XYZ}
+% simply calls the corresponding Lua function \luafunc{marginalia.XYZ}.
+% \begin{macro}{
+% \@@_lua_store_default_page_data:,
+% \@@_lua_store_page_data:n,
+% \@@_lua_check_page_data:n,
+% \@@_lua_store_item_data:n,
+% \@@_lua_check_item_data:n,
+% \@@_lua_compute_items:,
+% \@@_lua_write_problem_report:,
+% \@@_lua_write_item_change_report:,
+% }
+% The first 8 macros do not require expansion of parameters: they either have none, or process data not containing
+% control sequences (read from the \file{.aux} file); hence \cs{lua_now:n} is used.
+% \begin{macrocode}
+\cs_new:Npn\@@_lua_store_default_page_data:
+ {
+ \lua_now:n{ marginalia.store_default_page_data() }
+ }
+\cs_new:Npn\@@_lua_store_page_data:n #1
+ {
+ \lua_now:n{ marginalia.store_page_data('#1') }
+ }
+\cs_new:Npn\@@_lua_check_page_data:n #1
+ {
+ \lua_now:n{ marginalia.check_page_data('#1') }
+ }
+\cs_new:Npn\@@_lua_write_page_change_report:
+ {
+ \lua_now:n{ marginalia.write_page_change_report() }
+ }
+\cs_new:Npn\@@_lua_store_item_data:n #1
+ {
+ \lua_now:n{ marginalia.store_item_data('#1') }
+ }
+\cs_new:Npn\@@_lua_check_item_data:n #1
+ {
+ \lua_now:n{ marginalia.check_item_data('#1') }
+ }
+\cs_new:Npn\@@_lua_compute_items:
+ {
+ \lua_now:n{ marginalia.compute_items() }
+ }
+\cs_new:Npn\@@_lua_write_problem_report:
+ {
+ \lua_now:n{ marginalia.write_problem_report() }
+ }
+\cs_new:Npn\@@_lua_write_item_change_report:
+ {
+ \lua_now:n{ marginalia.write_item_change_report() }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{
+% \@@_lua_load_item_data:n,
+% }
+% The last macro will receive a control sequence parameter and so requires expansion; hence
+% \cs{lua_now:e} is used.
+% \begin{macrocode}
+\cs_new:Npn\@@_lua_load_item_data:n #1
+ {
+ \lua_now:e{ marginalia.load_item_data('#1') }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \subsection{Processing data from the \texorpdfstring{\file{.aux}}{.aux} file}
+%
+% \begin{macro}[int]{
+% \marginalia@pagedata,
+% }
+% This command is used to store page data in the \file{.aux} file.
+% \begin{macrocode}
+\NewDocumentCommand{\marginalia@pagedata}{ m }{
+ \@@_process_page_data:n{#1}
+}
+% \end{macrocode}
+% Initially \cs{@@_process_page_data:n} is set to \cs{@@_lua_store_page_data:n}. Thus, when the \file{.aux} file is
+% read, \cs{marginalia@pagedata} will pass the page data to the Lua backend to be stored.
+% \begin{macrocode}
+\cs_set_eq:NN
+ \@@_process_page_data:n
+ \@@_lua_store_page_data:n
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{
+% \marginalia@itemdata,
+% }
+% This command is used to store data for each marginal content item in the \file{.aux} file.
+% \begin{macrocode}
+\DeclareDocumentCommand{\marginalia@itemdata}{ m }{
+ \@@_process_item_data:n{#1}
+}
+% \end{macrocode}
+% \end{macro}
+% Initially \cs{@@_process_item_data:n} is set to \cs{@@_lua_store_item_data:n}. Thus, when the \file{.aux} file is
+% read, \cs{marginalia@itemdata} will pass the item data to the Lua backend to be stored.
+% \begin{macrocode}
+\cs_set_eq:NN
+ \@@_process_item_data:n
+ \@@_lua_store_item_data:n
+% \end{macrocode}
+% At the \texttt{begindocument} hook, the \file{.aux} file has been read and closed. The Lua backend now stores the
+% geometry and computes the vertical shift for each item. Then the handle for the main \file{.aux} file is stored for
+% use in this package.
+% \begin{macrocode}
+\AddToHook{begindocument}{
+ \@@_lua_store_default_page_data:
+ \@@_lua_compute_items:
+ \cs_set_eq:NN\l_@@_aux_iow\@mainaux
+}
+% \end{macrocode}
+% The \texttt{enddocument/afterlastpage} hook is before the \file{.aux} file is read back, so this is where
+% \cs{@@_process_page_data:n} and \cs{@@_process_item_data:n} are set, respectively, to \cs{@@_lua_check_page_data:n}
+% and \cs{@@_lua_check_item_data:n}. Thus, when the \file{.aux} file is read back, \cs{marginalia@pagedata} and
+% \cs{marginalia@itemdata} will pass data to the Lua backend to be checked for changes.
+% \begin{macrocode}
+\AddToHook{enddocument/afterlastpage}{
+ \cs_set_eq:NN
+ \@@_process_page_data:n
+ \@@_lua_check_page_data:n
+ \cs_set_eq:NN
+ \@@_process_item_data:n
+ \@@_lua_check_item_data:n
+ }
+% \end{macrocode}
+% \begin{macro}{\@@_write_reports:}
+% All the reports of changes and/or problems are assembled in the Lua backend. This macro will write the reports as
+% package warnings, using the following three messages, to which the Lua-assembled reports are passed as parameters:
+% \begin{macrocode}
+\msg_new:nnn{marginalia}{placement_problem}
+ { Problems~in~placement.~#1 }
+\msg_new:nnn{marginalia}{item_change}
+ { Changes~in~item~data.~#1 }
+\msg_new:nnn{marginalia}{page_change}
+ { Changes~in~page~data.~#1 }
+\cs_new:Npn\@@_write_reports:
+ {
+ \group_begin:
+ \tl_set:Ne\l_tmpa_tl{\@@_lua_write_problem_report:}
+ \tl_if_blank:VF\l_tmpa_tl
+ {
+ \msg_warning:nne{marginalia}{placement_problem}{\tl_use:N\l_tmpa_tl}
+ }
+ \tl_set:Ne\l_tmpa_tl{\@@_lua_write_item_change_report:}
+ \tl_if_blank:VF\l_tmpa_tl
+ {
+ \msg_warning:nne{marginalia}{item_change}{\tl_use:N\l_tmpa_tl}
+ }
+ \tl_set:Ne\l_tmpa_tl{\@@_lua_write_page_change_report:}
+ \tl_if_blank:VF\l_tmpa_tl
+ {
+ \msg_warning:nne{marginalia}{page_change}{\tl_use:N\l_tmpa_tl}
+ }
+ \group_end:
+ }
+% \end{macrocode}
+% \end{macro}
+% Use the \texttt{enddocument/info} hook to write the reports of changes and/or problems.
+% \begin{macrocode}
+\AddToHook{enddocument/info}{
+ \@@_write_reports:
+}
+% \end{macrocode}
+%
+%
+%
+% \subsection{Writing page data to the \texorpdfstring{\file{.aux}}{.aux} file}
+%
+% To compute the positions of marginal content items, certain page layout data is required. And since all the
+% computation takes place at the beginning of the document, it is necessary to write this information to the \file{.aux}
+% file.
+%
+% \begin{macro}{\g_@@_pagedatano_int}
+% Global integer variable to index page data items written to the \file{.aux} file.
+% \begin{macrocode}
+\int_new:N\g_@@_pagedatano_int
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_write_page_data}
+% This command will be used to write the current page data to the \file{.aux} file. It is initially defined to do
+% nothing, so that the use of \cs{marginalianewgeometry} in the preamble does not cause errors (because the
+% \file{.aux} file is not available for writing until \texttt{begindocument/end}).
+% \begin{macrocode}
+\cs_set_eq:NN\@@_write_page_data:\prg_do_nothing:
+\cs_new:Npn\@@_write_page_data_real:
+ {
+ \int_gincr:N\g_@@_pagedatano_int
+ \iow_now:Ne\l_@@_aux_iow{
+ \token_to_str:N\marginalia@pagedata{
+ pagedatano=\int_value:w\g_@@_pagedatano_int,
+ abspageno=\int_eval:n{\g_shipout_readonly_int+1},
+ hoffset=\int_value:w\hoffset,
+ voffset=\int_value:w\voffset,
+ paperheight=\int_value:w\paperheight,
+ oddsidemargin=\int_value:w\oddsidemargin,
+ evensidemargin=\int_value:w\evensidemargin,
+ textwidth=\int_value:w\textwidth,
+ columncount=\int_value:w\col@number,
+ columnwidth=\int_value:w\columnwidth,
+ columnsep=\int_value:w\columnsep,
+ twoside=\bool_to_str:n{\legacy_if_p:n{@twoside}},
+ }
+ }
+ }
+% \end{macrocode}
+% At the \texttt{begindocument/end} hook, the \file{.aux} file has been opened for writing, and so the macro
+% \cs{@@_write_page_data:} is enabled and the initial page data is written out.
+% \begin{macrocode}
+\AddToHook{begindocument/end}
+ {
+ \cs_set_eq:NN
+ \@@_write_page_data:
+ \@@_write_page_data_real:
+ \@@_write_page_data:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \subsection{Marginal content item processing}
+%
+% \subsubsection{Variables}
+%
+% \paragraph{Variables set by \LaTeX.}
+%
+% \begin{macro}{\g_@@_itemno_int}
+% Global integer variable to index marginal content items.
+% \begin{macrocode}
+\int_new:N\g_@@_itemno_int
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\l_@@_item_box}
+% Box variable to hold the typeset marginal content item.
+% \begin{macrocode}
+\box_new:N\l_@@_item_box
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{
+% \l_@@_item_height_dim,
+% \l_@@_item_depth_dim,
+% }
+% Dimension variables to hold the height and depth of the typeset margin content item.
+% \begin{macrocode}
+\dim_new:N\l_@@_item_height_dim
+\dim_new:N\l_@@_item_depth_dim
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \paragraph{Variables set by Lua.}
+%
+% The following variables will be set by the Lua backend via \texttt{tex.count} and \texttt{tex.dimen} when
+% \cs{@@_lua_load_item_data:n} is called.
+%
+% \begin{macro}{\l_@@_page_int}
+% Integer variable for the page on which the marginal content item appears. This variable will be
+% made available via \cs{marginaliapage} within the \meta{content} of \cs{marginalia}.
+% \begin{macrocode}
+\int_new:N\l_@@_page_int
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\l_@@_column_computed_int}
+% Integer variable for the column next to which the marginal content item appears. This variable will be
+% will be made available via \cs{marginaliacolumn} within the \meta{content} of \cs{marginalia}.
+% \begin{macrocode}
+\int_new:N\l_@@_column_computed_int
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{
+% \l_@@_xshift_computed_dim,
+% \l_@@_yshift_computed_dim,
+% }
+% Dimension variables to hold the differences in \(x\) and \(y\) coordinates between the call to \cs{marginalia} and
+% the position where the marginal content item should appear.
+% \begin{macrocode}
+\dim_new:N\l_@@_xshift_computed_dim
+\dim_new:N\l_@@_yshift_computed_dim
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\l_@@_side_computed_int}
+% Integer variable to indicate the side of the text block or column on which the marginal content item should be
+% placed: \(0 = \textrm{right}\) and \(1 = \textrm{left}\).
+% \begin{macrocode}
+\int_new:N\l_@@_side_computed_int
+% \end{macrocode}
+% (This variable could be a boolean, but an integer is used because there is no canonical access to booleans from
+% Lua.)
+% \end{macro}
+%
+% \begin{macro}{\l_@@_marginno_computed_int}
+% Integer variable to indicate in which margin the content will be be placed, to enable quick selection of width and
+% style: \(0 = \textrm{recto outer}\), \(1 = \textrm{recto inner}\), \(2 = \textrm{verso outer}\), \(3 = \textrm{verso
+% inner}\), \(4 = \textrm{right between}\), \(5 = \textrm{left between}\).
+% \begin{macrocode}
+\int_new:N\l_@@_marginno_computed_int
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\l_@@_enabled_computed_int}
+% Integer variable to indicate whether the marginal content item is enabled: \(0 = \textrm{disabled}\),
+% \(1 = \textrm{enabled}\).
+% \begin{macrocode}
+\int_new:N\l_@@_enabled_computed_int
+% \end{macrocode}
+% (This variable could be a boolean, but an integer is used because there is no canonical access to booleans from
+% Lua.)
+% \end{macro}
+%
+%
+%
+% \subsubsection{Core macro}
+%
+% \begin{macro}{\@@_process_item:nn}
+% This macro does most of the work in setting the marginal content item. The first parameter is \meta{options}, the
+% second is \meta{content}.
+% \begin{macrocode}
+\cs_new:Npn\@@_process_item:nn #1#2
+ {
+% \end{macrocode}
+% First, increment the index, then enter a group where all the action will happen.
+% \begin{macrocode}
+ \int_gincr:N\g_@@_itemno_int
+ \group_begin:
+% \end{macrocode}
+% Process \meta{options}. These settings apply locally inside the group.
+% \begin{macrocode}
+ \keys_set:nn{marginalia}{ #1 }
+% \end{macrocode}
+% Get item data from the Lua backend: the integer variables \cs{l_@@_page_int}, \cs{l_@@_column_computed_int},
+% \cs{l_@@_side_computed_int}, \cs{l_@@_enabled_computed_int}, and the dimension variables
+% \cs{l_@@_xshift_computed_dim}, and \cs{l_@@_yshift_computed_dim} are set by Lua via \texttt{tex.count} and
+% \texttt{tex.dimen}. If no data is available (if, for instance, no data has been stored from a previous run), default
+% values will be set by Lua. On later runs, the Lua backend will supply the values computed from the data written to
+% the \file{.aux} file on the previous run.
+% \begin{macrocode}
+ \@@_lua_load_item_data:n
+ { \int_value:w\g_@@_itemno_int }
+% \end{macrocode}
+% Choose the correct auxiliary function for typesetting, depending on which mode \TeX\ is in.
+% \begin{macrocode}
+ \mode_if_math:TF
+ {
+ \cs_set_eq:NN
+ \@@_typeset:n
+ \@@_typeset_mmode:n
+ }
+ {
+ \legacy_if:nT{@inlabel}
+ { \leavevmode }
+ \mode_if_horizontal:TF
+ {
+ \cs_set_eq:NN
+ \@@_typeset:n
+ \@@_typeset_hmode:n
+ }
+ {
+ \cs_set_eq:NN
+ \@@_typeset:n
+ \@@_typeset_vmode:n
+ }
+ }
+% \end{macrocode}
+% Choose the correct box in which to typeset the item. \cs{l_@@_valign_int} can only be \(1\) or \(2\), so take \(2\)
+% to signify bottom-aligned, anything else signifies top-aligned.
+% \begin{macrocode}
+ \int_compare:nNnTF{\l_@@_valign_int}={2}
+ {
+ \cs_set_eq:NN\@@_item_box_set:Nn\vbox_set:Nn
+ }
+ {
+ \cs_set_eq:NN\@@_item_box_set:Nn\vbox_set_top:Nn
+ }
+% \end{macrocode}
+% Choose the correct horizontal separation, width, and style for the item.
+% \begin{macrocode}
+ \@@_set_xsep_width_style:
+% \end{macrocode}
+% Typeset the \meta{content} into \cs{l_@@_item_box}. Use \cs{@parboxrestore} for brevity, even though \cs{hsize} and
+% \cs{linewidth} are subsequently set to \cs{l_@@_width_dim}. Make available \cs{marginaliapage} and
+% \cs{marginaliacolumn}.
+% \begin{macrocode}
+ \@@_item_box_set:Nn\l_@@_item_box{
+ \@parboxrestore
+ \normalfont\normalsize
+
+ \tl_use:N\l_@@_style_tl
+ \dim_set_eq:NN\hsize\l_@@_width_dim
+ \dim_set_eq:NN\linewidth\hsize
+
+ \cs_set_eq:NN\marginaliapage\l_@@_page_int
+ \cs_set_eq:NN\marginaliacolumn\l_@@_column_computed_int
+
+ \group_begin:
+ \ignorespaces
+ #2
+ \par
+ \group_end:
+ }
+% \end{macrocode}
+% Measure \cs{l_@@_item_box}.
+% \begin{macrocode}
+ \dim_set:Nn\l_@@_item_height_dim
+ {\box_ht:N\l_@@_item_box}
+ \dim_set:Nn\l_@@_item_depth_dim
+ {\box_dp:N\l_@@_item_box}
+% \end{macrocode}
+% Everything is now ready to place the item on the page and write the necessary data to the \file{.aux} file. Use the
+% chosen auxiliary function for typesetting, and immediately use \cs{savepos} to store the callout position.
+% \begin{macrocode}
+ \@@_typeset:n{
+ \savepos
+% \end{macrocode}
+% Write the item data to the \file{.aux} file. All tokens that will change for future items, and which are currently
+% meaningful, are expanded now; the remainder will be expanded at shipout time, when \emph{they} are meaningful.
+% \begin{macrocode}
+ \iow_shipout_e:Ne\l_@@_aux_iow{
+ \token_to_str:N\marginalia@itemdata{
+ itemno=\int_value:w\g_@@_itemno_int,
+ abspageno=\exp_not:N\int_eval:n{\g_shipout_readonly_int},
+ pageno=\exp_not:N\int_value:w\c@page,
+ type=\str_use:N\int_value:w\l_@@_type_int,
+ xpos=\exp_not:N\int_value:w\lastxpos,
+ ypos=\exp_not:N\int_value:w\lastypos,
+ height=\int_value:w\l_@@_item_height_dim,
+ depth=\int_value:w\l_@@_item_depth_dim,
+ pos=\int_value:w\l_@@_pos_int,
+ column=\int_value:w\l_@@_column_int,
+ yshift=\int_value:w\l_@@_default_yshift_dim,
+ ysep~above=\int_value:w\l_@@_ysep_above_dim,
+ ysep~below=\int_value:w\l_@@_ysep_below_dim,
+ ysep~page~top=\int_value:w\l_@@_ysep_page_top_dim,
+ ysep~page~bottom=\int_value:w\l_@@_ysep_page_bottom_dim,
+ }
+ }
+% \end{macrocode}
+% Finally, if the item is enabled, typeset it onto the page: shift the item by
+% \[
+% \abs[\big]{\cs{l_@@_xshift_computed_dim}} + \abs[\big]{\cs{l_@@_xsep_dim}}
+% \]
+% to the right in an \cs{rlap} or to the left in an \cs{llap}, depending on \cs{l_@@_side_computed_int}, then use
+% \cs{@@_place_item_box} for the vertical placement.
+% \begin{macrocode}
+ \int_if_zero:nF{\l_@@_enabled_computed_int}
+ {
+ \int_if_zero:nTF{\l_@@_side_computed_int}
+ {
+ \rlap{
+ \kern\l_@@_xshift_computed_dim
+ \kern\l_@@_xsep_dim
+ \@@_place_item_box:
+ }
+ }
+ {
+ \llap{
+ \@@_place_item_box:
+ \kern\l_@@_xsep_dim
+ \kern-\l_@@_xshift_computed_dim
+ }
+ }
+ }
+ }
+% \end{macrocode}
+% Close the group started near the beginning of \cs{@@_process_item:nn}.
+% \begin{macrocode}
+ \group_end:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \subsubsection{Width and style selection}
+%
+% \begin{macro}{\@@_set_xsep_width_style}
+% Set \cs{l_@@_xsep_dim}, \cs{l_@@_width_dim}, and \cs{l_@@_style_tl}, based on \cs{l_@@_marginno_computed_int}.
+% \begin{macrocode}
+\cs_new:Npn\@@_set_xsep_width_style:
+ {
+ \int_case:nn{\l_@@_marginno_computed_int}
+ {
+ {0}
+ {
+ \cs_set_eq:NN\l_@@_xsep_dim
+ \l_@@_xsep_recto_outer_dim
+ \cs_set_eq:NN\l_@@_width_dim
+ \l_@@_width_recto_outer_dim
+ \cs_set_eq:NN\l_@@_style_tl
+ \l_@@_style_recto_outer_tl
+ }
+ {1}
+ {
+ \cs_set_eq:NN\l_@@_xsep_dim
+ \l_@@_xsep_recto_inner_dim
+ \cs_set_eq:NN\l_@@_width_dim
+ \l_@@_width_recto_inner_dim
+ \cs_set_eq:NN\l_@@_style_tl
+ \l_@@_style_recto_inner_tl
+ }
+ {2}
+ {
+ \cs_set_eq:NN\l_@@_xsep_dim
+ \l_@@_xsep_verso_outer_dim
+ \cs_set_eq:NN\l_@@_width_dim
+ \l_@@_width_verso_outer_dim
+ \cs_set_eq:NN\l_@@_style_tl
+ \l_@@_style_verso_outer_tl
+ }
+ {3}
+ {
+ \cs_set_eq:NN\l_@@_xsep_dim
+ \l_@@_xsep_verso_inner_dim
+ \cs_set_eq:NN\l_@@_width_dim
+ \l_@@_width_verso_inner_dim
+ \cs_set_eq:NN\l_@@_style_tl
+ \l_@@_style_verso_inner_tl
+ }
+ {4}
+ {
+ \cs_set_eq:NN\l_@@_xsep_dim
+ \l_@@_xsep_right_between_dim
+ \cs_set_eq:NN\l_@@_width_dim
+ \l_@@_width_right_between_dim
+ \cs_set_eq:NN\l_@@_style_tl
+ \l_@@_style_right_between_tl
+ }
+ {5}
+ {
+ \cs_set_eq:NN\l_@@_xsep_dim
+ \l_@@_xsep_left_between_dim
+ \cs_set_eq:NN\l_@@_width_dim
+ \l_@@_width_left_between_dim
+ \cs_set_eq:NN\l_@@_style_tl
+ \l_@@_style_left_between_tl
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \subsubsection{Auxiliary placement macros}
+%
+% \begin{macro}{\@@_place_item_box:}
+% Place the item that has been set in \cs{l_@@_item_box}, vertically shifted by \cs{l_@@_yshift_computed_dim} and
+% \cs{smash}ed to avoid altering vertical spacing in the main text.
+% \begin{macrocode}
+\cs_new:Npn\@@_place_item_box:
+ {
+ \smash
+ {
+ \box_move_up:nn{\l_@@_yshift_computed_dim}
+ {
+ \box_use:N\l_@@_item_box
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{
+% \@@_typeset_mmode:n,
+% \@@_typeset_hmmode:n,
+% \@@_typeset_vmode:n,
+% }
+% These three macros handle typsetting in math mode, horizontal mode, and vertical mode. Nothing special needs to be
+% done in math mode. In horizontal mode, \cs{@bsphack}\ldots\cs{@bsphack} avoids double spacing. In vertical mode, a
+% new paragraph containing only a \cs{strut} is started, the item is typeset, the paragraph is ended, and then a
+% vertical skip of \(-\cs{baselineskip}\) should `hide' that invisible paragraph.
+% \begin{macrocode}
+\cs_new:Npn\@@_typeset_mmode:n #1
+ {
+ #1
+ }
+\cs_new:Npn\@@_typeset_hmode:n #1
+ {
+ \@bsphack
+ #1
+ \@esphack
+ }
+\cs_new:Npn\@@_typeset_vmode:n #1
+ {
+ \nobreak\noindent\strut #1\par
+ \skip_vertical:n{-\baselineskip}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \subsection{User commands}
+%
+% Finally, set up the commands for the user.
+%
+% \begin{macro}{\marginalia}
+% This is the main user command for creating a marginal content item. This macro does nothing but hand off to
+% \cs{@@_process_item:nn}.
+% \begin{macrocode}
+\NewDocumentCommand{\marginalia}{ O{} +m }
+ {
+ \@@_process_item:nn{#1}{#2}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\marginaliasetup}
+% The user command to set the configuration.
+% \begin{macrocode}
+\NewDocumentCommand{\marginaliasetup}{ m }
+{
+ \keys_set:nn{marginalia}{ #1 }
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\marginalianewgeometry}
+% The user command to signal that the page geometry has been changed.
+% \begin{macrocode}
+\NewDocumentCommand{\marginalianewgeometry}{}
+{
+ \@@_write_page_data:
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macrocode}
+%</package>
+% \end{macrocode}
+%
+%
+%
+LUACODE
+%
+%
+%
+% \clearpage
+% \end{implementation}
diff --git a/macros/luatex/latex/marginalia/marginalia.ins b/macros/luatex/latex/marginalia/marginalia.ins
new file mode 100644
index 0000000000..b8fc393b36
--- /dev/null
+++ b/macros/luatex/latex/marginalia/marginalia.ins
@@ -0,0 +1,67 @@
+%%
+%% Copyright (C) 2025 Alan J. Cain
+%%
+%% This file may be distributed and/or modified under the
+%% conditions of the LaTeX Project Public License, either
+%% version 1.3c of this license or (at your option) any later
+%% version. The latest version of this license is in:
+%%
+%% http://www.latex-project.org/lppl.txt
+%%
+%% and version 1.3c or later is part of all distributions of
+%% LaTeX version 2008-05-04 or later.
+%%
+\input l3docstrip.tex
+\askforoverwritefalse
+\nopostamble
+
+
+\preamble
+
+This is a generated file.
+
+Copyright (C) 2025 Alan J. Cain
+
+This file may be distributed and/or modified under the
+conditions of the LaTeX Project Public License, either
+version 1.3c of this license or (at your option) any later
+version. The latest version of this license is in:
+
+http://www.latex-project.org/lppl.txt
+
+and version 1.3c or later is part of all distributions of
+LaTeX version 2008-05-04 or later.
+
+\endpreamble
+
+\generate{\file{marginalia.sty}{\from{marginalia.dtx}{package}}}
+
+\nopreamble
+\generate{\file{marginalia-doc-example.tex}{\from{marginalia.dtx}{example}}}
+
+
+
+\def\MetaPrefix{--}
+
+\preamble
+
+This is a generated file.
+
+Copyright (C) 2025 Alan J. Cain
+
+This file may be distributed and/or modified under the
+conditions of the LaTeX Project Public License, either
+version 1.3c of this license or (at your option) any later
+version. The latest version of this license is in:
+
+http://www.latex-project.org/lppl.txt
+
+and version 1.3c or later is part of all distributions of
+LaTeX version 2008-05-04 or later.
+
+\endpreamble
+
+\generate{\file{marginalia.lua}{\from{marginalia.dtx}{lua}}}
+
+
+\endbatchfile
diff --git a/macros/xetex/latex/xduts/xduts.dtx b/macros/xetex/latex/xduts/xduts.dtx
index bd461a0549..ccd92aec37 100644
--- a/macros/xetex/latex/xduts/xduts.dtx
+++ b/macros/xetex/latex/xduts/xduts.dtx
@@ -1,7 +1,7 @@
% \iffalse
%<*driver>
\ProvidesFile{xduts.dtx}
-[2025/02/05 v6.2.4.0 Xidian University TeX Suite]
+[2025/02/17 v6.2.5.0 Xidian University TeX Suite]
%</driver>
%<class|sty>\NeedsTeXFormat{LaTeX2e}
%<class|sty>\RequirePackage{expl3}
@@ -9,7 +9,7 @@
%<xduugtp>\ProvidesExplClass{xduugtp}
%<xdupgthesis>\ProvidesExplClass{xdupgthesis}
%<xduugthesis>\ProvidesExplClass{xduugthesis}
-%<class|sty> {2025/02/05}{6.2.4.0}
+%<class|sty> {2025/02/17}{6.2.5.0}
%<xdufont> {Xidian University Font package}
%<xduugtp> {Xidian University Undergraduate Thesis Proposal class}
%<xdupgthesis> {Xidian University Postgraduate Thesis document class}
@@ -6829,6 +6829,7 @@ literate = {\$}{{\textcolor{purple3}{\$}}}{1}
% \end{macrocode}
% \end{macro}
% \begin{macro}{\@@_statement:}
+% \changes{v6.2.5.0}{2025/02/17}{修正声明页字距}
% \changes{v6.2.4.0}{2025/02/05}{修正研究生学位论文关于论文使用授权的说明标题后空行}
% \changes{v6.2.0.0}{2025/01/11}{更新研究生学位论文关于论文使用授权的说明}
% \changes{v1.19.0.0}{2022/05/30}{学位论文独创性声明和关于论文使用授权的说明}
@@ -6849,6 +6850,7 @@ literate = {\$}{{\textcolor{purple3}{\$}}}{1}
\vbox_to_ht:nn { 120pt }
{
\rmfamily \zihao { -4 }
+ \xeCJKsetup { CJKglue = { \hskip 0pt } }
\dim_set:Nn \parindent { 2em }
\dim_set:Nn \baselineskip { 20pt }
秉承学校严谨的学风和优良的科学道德,本人声明所呈交的论文是我个人在导师指
@@ -6891,6 +6893,7 @@ literate = {\$}{{\textcolor{purple3}{\$}}}{1}
\vbox_to_ht:nn { 160pt }
{
\rmfamily \zihao { -4 }
+ \xeCJKsetup { CJKglue = { \hskip 0pt } }
\dim_set:Nn \parindent { 2em }
\dim_set:Nn \baselineskip { 20pt }
本人完全了解西安电子科技大学有关保留和使用学位论文的规定,即:研究生在校
diff --git a/macros/xetex/latex/xduts/xduts.pdf b/macros/xetex/latex/xduts/xduts.pdf
index 3dcaea364d..9f05ecfed9 100644
--- a/macros/xetex/latex/xduts/xduts.pdf
+++ b/macros/xetex/latex/xduts/xduts.pdf
Binary files differ