diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..705d0c2
--- /dev/null
+++ b/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/luamml-amsmath.lua b/luamml-amsmath.lua
index 2b74265..26b157b 100644
--- a/luamml-amsmath.lua
+++ b/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/luamml-array.lua b/luamml-array.lua
index 9a7b358..f1fd7c5 100644
--- a/luamml-array.lua
+++ b/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/luamml-convert.lua b/luamml-convert.lua
index fe529de..abb6615 100644
--- a/luamml-convert.lua
+++ b/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/luamml-patches-amsmath.sty b/luamml-patches-amsmath.sty
index 0b09bc7..66ffdbe 100644
--- a/luamml-patches-amsmath.sty
+++ b/luamml-patches-amsmath.sty
@@ -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
-}
+ \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
+ \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
+ }
+ \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} }
+ }
-\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
-}
+ \PackageInfo{luamml}{patching~\string\endgather}
+ \cs_set:Npn \endgather {
+ \math@cr
+ \black@ \totwidth@
+ \UseExpandableTaggingSocket{math/luamml/mtable/finalize} {gather}
+ \egroup
+ $$
+ \ignorespacesafterend
+ }
+
% align and friends
-\cs_set:Npn \align@preamble {
- &
- \hfil
- \strut@
- \setboxz@h {
- \@lign
- $
- \m@th
- \displaystyle
- {##}
- \ifmeasuring@
- \luamml_ignore:
- \else
- \luamml_save:nNn {} \displaystyle {mtd}
- \fi
- $
+ \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
+ }
+
+% 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}
+ }
}
- \ifmeasuring@
- \savefieldlength@
- \else
- \__luamml_amsmath_add_box_to_row:
- \fi
- \set@field
- \tabskip\z@skip
- &
- \setboxz@h {
- \@lign
- $
- \m@th
- \displaystyle
- {
- {}
- ##
- }
- \ifmeasuring@
- \luamml_ignore:
+ \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
- \luamml_save:nNn {} \displaystyle {mtd}
+ $$
\fi
- $
+ \ignorespacesafterend
}
- \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:
- }
-}
-
-\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
- }
-}
-
-\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} }
-}
+
+ \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
- }
- }
- }
- \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@{}}
-}
-
-
-\cs_set:Npn \bBigg@ #1 #2 {
- {
- \ensuremath {
- \Uvextensible height~#1 \big@size axis~exact~#2
+ \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
+ \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} {}{ \, }
+ }
+
+ % {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/luamml-patches-amstext.sty b/luamml-patches-amstext.sty
index 97b1b1f..3f16a86 100644
--- a/luamml-patches-amstext.sty
+++ b/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}
+ {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
- }
- \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
- }
+% 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
+ }}}
}
}
- \int_if_odd:nT { \int_div_truncate:nn { \l__luamml_flag_int } { 8 } } {
- \tag_mc_end:
- \tag_struct_end:
- }
-}
diff --git a/luamml-patches-array.sty b/luamml-patches-array.sty
deleted file mode 100644
index b08d561..0000000
--- a/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/luamml-patches-kernel.sty b/luamml-patches-kernel.sty
index 38eb28b..bcd3064 100644
--- a/luamml-patches-kernel.sty
+++ b/luamml-patches-kernel.sty
@@ -1,52 +1,64 @@
\ProvidesExplPackage {luamml-patches-kernel} {2024-10-30} {0.2.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/luamml-patches-lab-math.sty b/luamml-patches-lab-math.sty
index 7776576..c74a206 100644
--- a/luamml-patches-lab-math.sty
+++ b/luamml-patches-lab-math.sty
@@ -1,11 +1,17 @@
\ProvidesExplPackage {luamml-patches-lab-math} {2024-10-30} {0.2.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/luamml-patches-mathtools.sty b/luamml-patches-mathtools.sty
index 3dc1570..e520190 100644
--- a/luamml-patches-mathtools.sty
+++ b/luamml-patches-mathtools.sty
@@ -1,35 +1,38 @@
\ProvidesExplPackage {luamml-patches-mathtools} {2024-10-26} {0.2.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/luamml-structelemwriter.lua b/luamml-structelemwriter.lua
index 7c2e549..3087305 100644
--- a/luamml-structelemwriter.lua
+++ b/luamml-structelemwriter.lua
@@ -6,6 +6,14 @@ 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
@@ -44,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))
@@ -70,7 +78,7 @@ local function write_elem(tree, stash)
return tex.runtoks(function()
return tex.sprint(struct_use_num, '{', tree[':structnum'], '}')
end)
- 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
@@ -81,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]
@@ -115,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/luamml-table.lua b/luamml-table.lua
index 4fb553a..2333104 100644
--- a/luamml-table.lua
+++ b/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/luamml-xmlwriter.lua b/luamml-xmlwriter.lua
index 6880074..ad67845 100644
--- a/luamml-xmlwriter.lua
+++ b/luamml-xmlwriter.lua
@@ -48,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/luamml.dtx b/luamml.dtx
index c45dca1..f2c85fd 100644
--- a/luamml.dtx
+++ b/luamml.dtx
@@ -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,9 +96,9 @@
% }
% \end{verbatim}
% produces a |TeX| element in the output instead of trying to import \TeX~as a mathematical expression.
-%
+%
% 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.
+% 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}
@@ -103,12 +106,12 @@
% \tagstructbegin{tag=mtext,stash}\tagmcbegin{}
% \luamml_annotate:en{nucleus=true,structnum=\tag_get:n{struct_num}}
% {\mbox{some~text~with~\emph{structure}}}
-% \tagmcend\tagstructend
+% \tagmcend\tagstructend
% $
% \end{verbatim}
-% Such a construction should check that the flag for structure elements has actually
+% 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}
@@ -316,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).
%
@@ -523,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}
+%
+% \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}
+%
+% \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}
+
+%
+% \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}
+%
+% \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}
+%
+% \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}
+%
+% \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}
+
+%
+% \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}
+%
+% \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}
+%
+% \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}
+%
+% \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}
+%
+% \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}
+%
+% \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}
@@ -549,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 }
@@ -557,7 +996,6 @@
\__luamml_patch_package:n {amstext}
\__luamml_patch_package:n {amsmath}
\__luamml_patch_package:n {mathtools}
-\__luamml_patch_package:n {array}
%
% \end{macrocode}
diff --git a/testfiles-lua/cases.mlr b/testfiles-lua/cases.mlr
index ab7b075..35edb39 100644
--- a/testfiles-lua/cases.mlr
+++ b/testfiles-lua/cases.mlr
@@ -106,9 +106,6 @@
.
-
diff --git a/testfiles-lua/test_xml.mlt b/testfiles-lua/test_xml.mlt
index ff1a82b..004279b 100644
--- a/testfiles-lua/test_xml.mlt
+++ b/testfiles-lua/test_xml.mlt
@@ -1,17 +1,21 @@
\DocumentMetadata{
uncompress,
pdfversion = 2.0,
- testphase = phase-I,
+ testphase = {phase-III,table,math},
}
\input{regression-test}
\documentclass{article}
-\usepackage[l3build]{luamml-demo}
-
\usepackage{unicode-math}
\begin{document}
-\tagstructbegin{tag=Document}
-\LuaMMLTagAF{} {
+\ExplSyntaxOn
+\luamml_set_filename:n {
+ \jobname .mml
+ }
+\luamml_process:
+\luamml_begin_single_file:
+\ExplSyntaxOff
+
\[
\begin{pmatrix}
1 & 0 & 0 \\
@@ -24,26 +28,21 @@
2 & \text{else}
\end{cases}
\]
-}
-\LuaMMLTagAF{} {
+
\[
x = \frac{-b \pm \sqrt{b^2-4ac}}{2a}.
\]
-}
-\LuaMMLTagAF{} {
+
\[
\sum_a\underline c\dot bc'
\]
-}
-\LuaMMLTagAF{} {
\begin{align}
abc&=def & e^{\mathrm{i}\pi}&=-1\\
\Big(1+2&=3\Big)\\
5
\end{align}
-}
-Es gilt \LuaMMLTagAF{}{$\sin(x)-\sin(x+2\pi)=0$}.
-\tagstructend
+Es gilt $\sin(x)-\sin(x+2\pi)=0$.
+
\end{document}