\iow_newline:
\c_backslash_str mml\c_space_tl \int_use:N \g_@@_math_total_int
\iow_newline:
\l_@@_tmpa_str
\iow_newline:
\l_@@_content_hash_tl
\iow_newline:
}
}
% \end{macrocode}
% \end{plugdecl}
%
% With luatex we automatically generate mathml with \pkg{luamml} if the package
% can be loaded and \pkg{unicode-math} is detected.
% We start the process in the begindocument/end hook
% so that the reading from a previous compilation can happen before!
%
% For other engines, for future name changes
% and in case luamml is not loaded we provide
% some commands
% \begin{macrocode}
\cs_new_protected:Npn\@@_provide_luamml_commands:
{
\providecommand\luamml_flag_structelem:{}
\cs_if_free:NT \luamml_structelem:
{
\cs_set_eq:NN\luamml_structelem:\luamml_flag_structelem:
}
\providecommand\luamml_flag_process:{}
\cs_if_free:NT \luamml_process:
{
\cs_set_eq:NN\luamml_process:\luamml_flag_process:
}
\providecommand\luamml_flag_ignore:{}
\cs_if_free:NT \luamml_ignore:
{
\cs_set_eq:NN\luamml_ignore:\luamml_flag_ignore:
}
}
% \end{macrocode}
% \begin{macrocode}
\sys_if_engine_luatex:TF
{
\AddToHook{begindocument/before}
{
\str_case:on \g_@@_luamml_load_tl
{
{ 1 } {
\RequirePackage { luamml }
\AddToHook{begindocument/end}
{
\@@_luamml_activate_write:
}
}
{-1 } {
\AddToHook{begindocument/end}
{
\msg_note:nnnn { tag }
{ luamml-status }{ disabled }{ not~create }
}
}
{ 0 }
{
\@ifpackageloaded { unicode-math }
{
\RequirePackage { luamml }
\AddToHook{begindocument/end}
{
\@@_luamml_activate_write:
}
}
{ \msg_warning:nn { tag }{ unicode-math-missing } }
}
}
\@@_provide_luamml_commands:
}
}
{
\AddToHook{begindocument/before}
{
\@@_provide_luamml_commands:
}
}
\msg_new:nnn { tag }{ luamml-status }
{
luamml~has~been~#1~and~will~#2~an~MathML~file.
}
\msg_new:nnn { tag }{ unicode-math-missing }
{
The~package~unicode-math~is~missing\\
luamml~will~not~create~an~MathML~file.\\
To~avoid~this~warning~load~unicode-math~\\
or~disable~luamml~with~\\
\tl_to_str:n{\tagpdfsetup{math/mathml/luamml/load=false}}\\
or~force~luamml~with~\\
\tl_to_str:n{\tagpdfsetup{math/mathml/luamml/load=true}}
}
\cs_new_protected:Npn \@@_luamml_activate_write:
{
\bool_if:NT \g_@@_luamml_write_bool
{
% \end{macrocode}
% to avoid that nothing is written in the first run, we must activate the sockets:
% \begin{macrocode}
\bool_gset_true:N\g__tag_math_mathml_AF_bool
\AssignSocketPlug{tagsupport/math/struct/begin}{mathml-AF}
\AssignSocketPlug{tagsupport/math/struct/end}{mathml-AF}
\int_set:Nn \l__luamml_pretty_int { 7 }
\RegisterFamilyMapping\symsymbols{oms}
\RegisterFamilyMapping\symletters{oml}
\AssignSocketPlug{tagsupport/math/mathml/write/prepare}{On}
\iow_new:N \g_@@_luamml_iow
\iow_open:Nn \g_@@_luamml_iow {\c_sys_jobname_str-luamml-mathml.html}
\iow_now:Ne \g_@@_luamml_iow { \c_@@_mathml_write_init_tl }
\cs_new:Npn \@@_luamml_output_hook:n ##1
{
\tl_if_empty:NF \l_@@_mathml_write_before_tl
{
% \end{macrocode}
% We check here if the current group level is equal to the one stored for the
% outer math. If not, we add currently a suffix to change the hash.
% \changes{0.6k}{2024-12-04}{Test for current group level}
% \begin{macrocode}
\int_compare:nNnF
{ \@math@level } = { 1 }
{ \tl_put_right:Ne \l_@@_content_hash_tl {-INNER} }
\iow_now:Ne \g_@@_luamml_iow
{
\l_@@_mathml_write_before_tl
##1
\c_@@_mathml_write_after_tl
}
}
}
\__luamml_register_output_hook:N \@@_luamml_output_hook:n
% \end{macrocode}
% At the end of the document we must finish and close the file:
% \begin{macrocode}
\AddToHook{enddocument/afterlastpage}
{
\iow_now:Ne \g_@@_luamml_iow
{ \c_@@_mathml_write_final_tl }
\iow_close:N \g_@@_luamml_iow
}
\msg_note:nnnn { tag }
{ luamml-status }{ enabled }{ create }
}
}
% \end{macrocode}
% And now keys to activate/deactivate luamml feature
% \begin{variable}{\g_@@_luamml_load_tl}
% This variable will be used to suppress the loading of luamml
% altogether.
% \begin{macrocode}
\tl_new:N \g_@@_luamml_load_tl
\tl_gset:Nn \g_@@_luamml_load_tl {0}
% \end{macrocode}
% \end{variable}
% \begin{variable}{\g_@@_luamml_write_bool}
% This variable decides if luamml writes a mathml
% altogether.
% \begin{macrocode}
\bool_new:N \g_@@_luamml_write_bool
\bool_gset_true:N \g_@@_luamml_write_bool
% \end{macrocode}
% \end{variable}
% \begin{macro}{\@@_luamml_ignore:,\@@_luamml_structelem:}
% Internal variants of the luamml commands, that can be remapped if needed.
% \begin{macrocode}
\cs_new:Npn\@@_luamml_structelem:{}
\cs_new:Npn\@@_luamml_ignore:{}
% \end{macrocode}
% \end{macro}
%
% \begin{macrocode}
\msg_new:nnn { tag }{ PDF-2.0-recommended }
{
The~key~#1~will~not~work~properly~with~PDF~#2.\\
Switching~to~PDF~2.0~is~recommended.
}
\keys_define:nn { __tag / setup }
{
% \end{macrocode}
% At first a key to suppress the loading altogether
% \begin{macrocode}
math/mathml/luamml/load .choice: ,
math/mathml/luamml/load/true .code:n = {\tl_gset:Nn \g_@@_luamml_load_tl{1}},
math/mathml/luamml/load/false .code:n = {\tl_gset:Nn \g_@@_luamml_load_tl{-1}},
math/mathml/luamml/load .default:n = true,
math/mathml/luamml/load .usage:n=preamble,
% \end{macrocode}
% A key to activate math structure elements.
% \changes{v0.6j}{2024-11-19}{no longer enable globally for better fake math handling, issue \#764}
% \begin{macrocode}
math/mathml/structelem .choice:,
math/mathml/structelem/true .code:n =
{
\pdf_version_compare:NnT < {2.0}
{
\msg_warning:nnne { tag }{ PDF-2.0-recommended }
{ math/mathml/structelem }{ \pdf_version: }
}
\cs_set:Npn\@@_luamml_structelem:{\luamml_structelem:}
\cs_set:Npn\@@_luamml_ignore:{\luamml_ignore:}
},
math/mathml/structelem/false .code:n =
{
\cs_set_eq:NN\@@_luamml_structelem:\prg_do_nothing:
\cs_set_eq:NN\@@_luamml_ignore:\prg_do_nothing:
},
math/mathml/structelem .default:n = true,
% \end{macrocode}
% and a key to call the ignore flag. This should only be used locally.
% \begin{macrocode}
math/mathml/ignore .code:n = {\luamml_ignore:},
% \end{macrocode}
% \begin{macrocode}
math/mathml/luamml/write .choice:,
math/mathml/luamml/write/true .code:n =
{
\tl_gset:Nn \g_@@_luamml_load_tl{1}
\bool_gset_true:N \g_@@_luamml_write_bool
},
math/mathml/luamml/write/false .code:n =
{
\bool_gset_false:N \g_@@_luamml_write_bool
},
math/mathml/luamml/write .default:n = true,
math/mathml/luamml/write .usage:n=preamble,
% \end{macrocode}
% alias keys for compatibility
% \begin{macrocode}
math/mathml/luamml .bool_gset:N = \g_@@_luamml_write_bool,
math/mathml/luamml .usage:n=preamble
}
% \end{macrocode}
% \begin{socketdecl}{tagsupport/math/mathml/write}
% This writes a html-dummy with the hash and the math content.
% This should be optional, so it uses a socket that can be disabled
%
% \begin{macrocode}
\socket_new:nn {tagsupport/math/mathml/write}{0}
% \end{macrocode}
% \end{socketdecl}
%
% \begin{plugdecl}{On}
% \begin{macrocode}
\socket_new_plug:nnn{tagsupport/math/mathml/write}{On}
{
\iow_now:Ne \g_@@_writedummy_iow
{
\l_@@_mathml_write_before_tl
\c_@@_mathml_write_after_tl
}
}
% \end{macrocode}
% \end{plugdecl}
% And now a key to activate the socket.
% \begin{macrocode}
\keys_define:nn { __tag / setup }
{
math/mathml/write-dummy .code:n =
{
\bool_gset_true:N \g__tag_math_mathml_AF_bool
\tl_if_exist:NF\g_@@_writedummy_iow
{
\iow_new:N \g_@@_writedummy_iow
\iow_open:Nn \g_@@_writedummy_iow
{
\c_sys_jobname_str-mathml-dummy.html
}
\iow_now:Ne \g_@@_writedummy_iow
{
\c_@@_mathml_write_init_tl
}
\AssignSocketPlug {tagsupport/math/mathml/write/prepare}{On}
\AssignSocketPlug {tagsupport/math/mathml/write}{On}
\AddToHook{enddocument/afterlastpage}
{
\iow_now:Ne \g_@@_writedummy_iow
{ \c_@@_mathml_write_final_tl }
\iow_close:N \g_@@_writedummy_iow
}
}
},
math/mathml/write-dummy .usage:n=preamble
}
% \end{macrocode}
%
% \begin{macro}{\@@_AF_process_mathml_files:}
% \begin{macrocode}
\box_new:N\l_@@_tmpa_box
\cs_new_protected:Npn \@@_AF_process_mathml_files:
{
\hbox_set:Nn \l_@@_tmpa_box
{
\pdfdict_put:nnn { l_pdffile/Filespec }{AFRelationship} { /Supplement }
\pdfdict_put:nne
{ l_pdffile }{Subtype}
{ \pdf_name_from_unicode_e:n{application/mathml+xml} }
\char_set_catcode_other:N \#
\cs_set_eq:NN\mml \@@_AF_html_reader:w
\clist_map_inline:Nn \l__tag_math_mathml_files_clist
{
\file_if_exist:nTF {##1.html}
{
\typeout{Info:~reading~mathml~file~##1}
\file_input:n {##1.html}
\bool_gset_true:N\g__tag_math_mathml_AF_bool
}
{
\typeout{Info:~mathml~file~##1~does~not~exist}%info message
}
}
}
\bool_if:NT\g__tag_math_mathml_AF_bool
{
\typeout{Info:~Activating~mathml~support}
\AssignSocketPlug{tagsupport/math/struct/begin}{mathml-AF}
\AssignSocketPlug{tagsupport/math/struct/end}{mathml-AF}
\AddToHook{enddocument/info}
{
\iow_term:n{MathML~statistic}
\iow_term:n{================}
\iow_term:e{==>~\int_use:N\g_@@_mathml_total_int\c_space_tl
MathML~fragments~read}
\iow_term:e{==>~\int_use:N\g_@@_mathml_int\c_space_tl
different~MathML~fragments}
\iow_term:e{==>~\int_use:N\g_@@_math_total_int\c_space_tl
math~fragments~found}
\iow_term:e{==>~\int_use:N\g_@@_mathml_AF_found_int\c_space_tl
fitting~MathML~AF~found}
\iow_term:e{==>~\int_use:N\g_@@_mathml_AF_attached_int\c_space_tl
MathML~AF~attached}
}
}
}
\AddToHook{begindocument}{\@@_AF_process_mathml_files:}
% \end{macrocode}
% \end{macro}
%
% \subsection{Mathstyle detection}
% In some cases we need to detect the mathstyle used in a \cs{mathchoice}
% command and to disable/enable tagging in the unused branches.
% This is currently only used in the amstext command \cs{text}
% but is perhaps also needed in other cases, so we create a general command.
%
%\begin{macro}{\l_@@_mathstyle_int,\g_@@_mathchoice_int,mathstyle}
% \begin{macrocode}
\int_new:N \l_@@_mathstyle_int
\int_new:N \g_@@_mathchoice_int
\property_new:nnnn{mathstyle}{now}{-1}{\int_use:N \l_@@_mathstyle_int }
% \end{macrocode}
%\end{macro}
% For now internal, but perhaps will need a public version.
% The command should be used in every branch of a \cs{mathchoice}
% (with the correct mathstyle number) and with an unique label (which should
% be the same in every branch).
% \cs{g_@@_mathchoice_int} can be, e.g., increased before the mathchoice and
% then used.
% \begin{macro}{\@@_tag_if_mathstyle:nn}
% \begin{macrocode}
\cs_new_protected:Npn \@@_tag_if_mathstyle:nn #1 #2
%#1 refers to label
%#2 is a number for the mathstyle (typically 0,2,4,6)
{
\int_set:Nn \l_@@_mathstyle_int {#2}
\property_record:nn {#1} { mathstyle }
\int_compare:nNnTF { \property_ref:nn {#1}{ mathstyle} } = { #2 }
{ \tag_resume:n{\mathchoice} }{ \tag_suspend:n{\mathchoice} }
}
\cs_generate_variant:Nn \@@_tag_if_mathstyle:nn {en}
% \end{macrocode}
% \end{macro}
%
% \subsection{Tagging options}
% \begin{macrocode}
\keys_define:nn { __tag / setup }
{
math/mathml/sources .clist_set:N = \l__tag_math_mathml_files_clist,
math/alt/use .bool_set:N = \l__tag_math_alt_bool,
viewer/pane/mathml .bool_set:N = \l__tag_math_mathml_pane_bool,
viewer/pane/mathml .initial:n = true,
viewer/pane/mathsource .bool_set:N = \l__tag_math_texsource_pane_bool,
math/mathml/AF .bool_set:N = \l__tag_math_mathml_AF_bool,
math/mathml/AF .initial:n = true,
math/tex/AF .bool_set:N = \l__tag_math_texsource_AF_bool,
math/tex/AF .initial:n = true
}
% \end{macrocode}
% alt is required for pdf/UA-1.
% TODO: l3pdfmeta should support this test.
% \begin{macrocode}
\AddToHook{begindocument/end}
{
\str_if_eq:eeT
{1}
{
\exp_last_unbraced:Ne\use_i:nn
{\GetDocumentProperties{document/pdfstandard-UA}}
\c_empty_tl\c_empty_tl
}
{
\bool_if:NF \l__tag_math_alt_bool
{
\typeout{PDF/UA-1~detected.~Enabling~alt~text~on~Formula}
}
\bool_set_true:N\l__tag_math_alt_bool
}
}
% \end{macrocode}
%
% \subsubsection{Meta keys}
% The |math/setup| key accepts a list with the values |mathml-SE|, |mathml-AF| and |tex-AF|.
% It is a fast way to set the main option. It at first disables them all, to get a clean state.
% \begin{macrocode}
\keys_define:nn {__tag / setup}
{
math/setup .code:n =
{
%deactivate loading of luamml
\tl_gset:Nn \g_@@_luamml_load_tl{-1}
\keys_set:nn {__tag / setup}
{
%deactivate tex source AF
math/tex/AF = false,
%deactivate reading of mathml-AF
math/mathml/sources=,
math/mathml/AF=false,
%deactivate structelem
math/mathml/structelem=false,
%handle value
}
\clist_map_inline:nn { #1}
{
\keys_set:nn {__tag/ setup}{math/__setup/##1}
}
},
math/__setup / mathml-SE .code:n =
{
\tl_gset:Nn \g_@@_luamml_load_tl{1}
\keys_set:nn {__tag / setup}
{
math/mathml/structelem=true
}
},
math/__setup / mathml-AF .code:n =
{
\tl_gset:Nn \g_@@_luamml_load_tl{1}
\clist_put_right:Ne\l__tag_math_mathml_files_clist
{\c_sys_jobname_str-mathml,\c_sys_jobname_str-luamml-mathml}
\keys_set:nn {__tag / setup}
{
math/mathml/AF=true
}
},
math/__setup / tex-AF .code:n =
{
\keys_set:nn {__tag / setup}
{
math/tex/AF =true
}
},
}
% \end{macrocode}
% \subsection{Sockets}
% \subsubsection{Main inline math sockets}
%
% \begin{socketdecl}
% {
% tagsupport/math/inline/begin,
% tagsupport/math/inline/end,
% tagsupport/math/inline/formula/begin,
% tagsupport/math/inline/formula/end,
% }
% These sockets are already declared in lttagging and only documented here.
% The first two sockets are meant to embed inline
% math into the surrounding (so to close/reopen, e.g., MC-chunks).
% The other two implement the actual formula structure.
% The formula sockets are despite their naming not symmetric:
% the begin socket is issued after the math has started, while
% the end socket is after the math!
% \changes{v0.6j}{2024-11-19}{change the socket to two arguments so that it can
% be used as tagging socket}
% \begin{macrocode}
%\socket_new:nn {tagsupport/math/inline/begin}{0}
%\socket_new:nn {tagsupport/math/inline/end}{0}
%\socket_new:nn {tagsupport/math/inline/formula/begin}{2} %
%\socket_new:nn {tagsupport/math/inline/formula/end}{0}
% \end{macrocode}
%\end{socketdecl}
%
%
% \begin{plugdecl}{MC}
% \begin{macrocode}
\socket_new_plug:nnn
{tagsupport/math/inline/begin}
{MC}
{\tag_mc_end_push:}
\socket_new_plug:nnn
{tagsupport/math/inline/end}
{MC}
{\tag_mc_begin_pop:n{}}
% \end{macrocode}
% \end{plugdecl}
%
% We probably will want to test different tagging recipes.
% \begin{plugdecl}{default}
% \begin{macrocode}
\socket_new_plug:nnn
{tagsupport/math/inline/formula/begin}
{default}
% \end{macrocode}
% \changes{v0.6g}{2024-10-02}{disable paratagging, issue \#711}
% \changes{v0.6j}{2024-11-19}{activate structelem locally issue \#764}
% \changes{v0.6j}{2024-11-19}{change to two arguments}
% \begin{macrocode}
{ \tagpdfparaOff
\@@_luamml_structelem:
\tag_socket_use:n{math/content}
\tag_socket_use:n{math/struct/begin}
#2
\tag_socket_use:n{math/end}
}
\socket_new_plug:nnn
{tagsupport/math/inline/formula/end}
{default}
{
\socket_use:n{tagsupport/math/struct/end}
}
% \end{macrocode}
% \end{plugdecl}
%
% \subsubsection{Main display math sockets}
%
% \begin{socketdecl}
% {
% tagsupport/math/display/begin,
% tagsupport/math/display/end,
% tagsupport/math/display/formula/begin,
% tagsupport/math/display/formula/end,
% }
% These sockets are already declared in lttagging and only documented here.
% The first two sockets are meant to embed display
% math into the surrounding (so to close/reopen, e.g., MC-chunks and
% P-structure).
% The other two implement the actual formula structure.
% The formula sockets are despite their naming not symmetric:
% the begin socket is issued after the math has started, while
% the end socket is after the math!
% \changes{v0.6j}{2024-11-19}{change number of arguments of formula/begin socket}
% \begin{macrocode}
%\socket_new:nn {tagsupport/math/display/begin}{0}
%\socket_new:nn {tagsupport/math/display/end}{0}
%\socket_new:nn {tagsupport/math/display/formula/begin}{2} %
%\socket_new:nn {tagsupport/math/display/formula/end}{0}
% \end{macrocode}
%\end{socketdecl}
% \begin{plugdecl}{default}
% \begin{macrocode}
\socket_new_plug:nnn
{tagsupport/math/display/begin}
{default}
{ \__tag_tool_close_P: }
\socket_new_plug:nnn
{tagsupport/math/display/end}
{default}
{
}
% \end{macrocode}
% \end{plugdecl}
% \begin{plugdecl}{default}
% \changes{v0.6j}{2024-11-19}{moved \cs{tagpdfparaOff} into the socket, tagging/765}
% \begin{macrocode}
\socket_new_plug:nnn
{tagsupport/math/display/formula/begin}
{default}
{
\tagpdfparaOff
\@@_luamml_structelem:
\tag_socket_use:n{math/content}
\tag_socket_use:n{math/struct/begin}
#2
\tag_socket_use:n{math/end}
}
\socket_new_plug:nnn
{tagsupport/math/display/formula/end}
{default}
{
\socket_use:n{tagsupport/math/struct/end}
}
% \end{macrocode}
% \end{plugdecl}
%
% \subsubsection{Sockets plugs for tags (labels)}
% \begin{socketdecl}
% {
% tagsupport/math/display/tag/begin,
% tagsupport/math/display/tag/end,
% }
% These sockets are already declared in lttagging and only documented here.
% These sockets are used in \cs{maketag@@@} to tag
% labels as Lbl. luamml changes the plug to move
% the Lbl into the math structure with an intent.
% \changes{v0.6l}{2025-02-06}{added sockets for tags/labels}
% \begin{macrocode}
%\socket_new:nn {tagsupport/math/display/tag/begin}{0}
%\socket_new:nn {tagsupport/math/display/tag/end}{0}
% \end{macrocode}
%\end{socketdecl}
%
% \begin{plugdecl}{default}
% \changes{v0.6j}{2024-11-19}{moved \cs{tagpdfparaOff} into the socket, tagging/765}
% \begin{macrocode}
\socket_new_plug:nnn
{tagsupport/math/display/tag/begin}
{default}
{
\tag_mc_end:
\tag_struct_begin:n {tag=Lbl}
\tag_mc_begin:n {}
}
\socket_new_plug:nnn
{tagsupport/math/display/tag/end}
{default}
{
\tag_mc_end:
\tag_struct_end:
\tag_mc_begin:n{}
}
\socket_assign_plug:nn {tagsupport/math/display/tag/begin}{default}
\socket_assign_plug:nn {tagsupport/math/display/tag/end}{default}
% \end{macrocode}
% \end{plugdecl}
%
% \subsubsection{Internal sockets}
%
% \begin{variable}{\l_@@_content_template_tl}
% The default text used as alt or actual text.
% \begin{macrocode}
\tl_new:N\l_@@_content_template_tl
\tl_set:Nn \l_@@_content_template_tl
{
LaTeX~ formula~ starts~
\exp_not:N\begin{\g_@@_grabbed_env_tl}
\c_space_tl
\exp_not:V\g_@@_grabbed_math_tl
\c_space_tl
\exp_not:N\end{\g_@@_grabbed_env_tl}
\c_space_tl LaTeX~ formula~ ends~
}
% \end{macrocode}
% \end{variable}
% \begin{variable}{\l_@@_texsource_template_tl}
% The default text used as texsource
% \begin{macrocode}
\tl_new:N\l_@@_texsource_template_tl
\tl_const:Nn\c_@@_inline_env_tl {math}
\tl_set:Nn \l_@@_texsource_template_tl
{
\tl_if_eq:NNTF\g_@@_grabbed_env_tl\c_@@_inline_env_tl
{
$
\exp_not:V\g_@@_grabbed_math_tl
$
}
{
\exp_not:N\begin{\g_@@_grabbed_env_tl}
\exp_not:V\g_@@_grabbed_math_tl
\exp_not:N\end{\g_@@_grabbed_env_tl}
}
}
% \end{macrocode}
% \end{variable}
%
% \begin{socketdecl}{tagsupport/math/content}
% The math content is stored in associated files and used for
% actual and alternative text. As the exact text is still
% unclear we use a socket to be able to test variants.
% The socket should set all four tl vars above, if needed
% to identical values. It can use the two variables
% \cs{g_@@_grabbed_env_tl} and \cs{g_@@_grabbed_math_tl}
% \begin{macrocode}
\socket_new:nn {tagsupport/math/content}{0}
% \end{macrocode}
% \end{socketdecl}
%
% Some default sockets to set the contents.
% TODO: think about naming convention.
% TODO: think how this should organized so that one
% has options to change from the outside and so that
% there are less repetitions.
% \begin{plugdecl}{actual+source}
% \begin{macrocode}
\socket_new_plug:nnn
{tagsupport/math/content}
{actual+source}
{
\tl_set:Ne\l_@@_content_actual_tl
{
\l_@@_content_template_tl
}
\tl_set:Ne \l_@@_content_AF_source_tl
{
\l_@@_texsource_template_tl
}
\tl_set:Nn \l_@@_content_AF_mathml_tl {}
\tl_set:Nn \l_@@_content_alt_tl {}
}
% \end{macrocode}
% \end{plugdecl}
%
% \begin{plugdecl}{alt+source}
% \begin{macrocode}
\socket_new_plug:nnn
{tagsupport/math/content}
{alt+source}
{
\tl_set:Ne\l_@@_content_alt_tl
{
\l_@@_content_template_tl
}
\tl_set:Ne \l_@@_content_AF_source_tl
{
\l_@@_texsource_template_tl
}
\tl_set:Nn \l_@@_content_AF_mathml_tl {}
\tl_set:Nn \l_@@_content_actual_tl {}
}
% \end{macrocode}
% \end{plugdecl}
% \begin{macrocode}
\socket_assign_plug:nn {tagsupport/math/content}{alt+source}
% \end{macrocode}
%
% \begin{socketdecl}{tagsupport/math/struct/begin,
% tagsupport/math/struct/end}
% For the main structure we use a socket too.
% This allows, e.g., to create a special one for luamml
% which setups additional objects.
% The begin socket can use the two variables
% \cs{g_@@_grabbed_env_tl} and \cs{g_@@_grabbed_math_tl}
% \begin{macrocode}
\socket_new:nn {tagsupport/math/struct/begin}{0}
\socket_new:nn {tagsupport/math/struct/end}{0}
% \end{macrocode}
% \end{socketdecl}
%
% \begin{plugdecl}{default}
% TODO: think about some naming convention ...
% \begin{macrocode}
\socket_new_plug:nnn
{tagsupport/math/struct/begin}
{default}
{
\bool_if:NTF\l__tag_math_texsource_AF_bool
{ \tl_set_eq:NN \l_@@_content_AF_source_tmpa_tl \l_@@_content_AF_source_tl }
{ \tl_clear:N \l_@@_content_AF_source_tmpa_tl }
\tl_if_eq:NnTF\g_@@_grabbed_env_tl {math}
{
\tl_set:Nn\l_@@_attribute_class_tl{inline}
}
{
\tl_set:Nn\l_@@_attribute_class_tl{display}
}
\bool_if:NF\l__tag_math_alt_bool
{ \tl_set:Nn \l_@@_content_alt_tl{} }
\tag_struct_begin:n
{
tag=Formula,
attribute-class=\l_@@_attribute_class_tl,
texsource = \l_@@_content_AF_source_tmpa_tl,
title-o = \g_@@_grabbed_env_tl,
actualtext = \l_@@_content_actual_tl,
alt = \l_@@_content_alt_tl
}
\typeout{====>grabbed~math=\meaning\g_@@_grabbed_math_tl}
\tag_mc_begin:n{}
}
\socket_new_plug:nnn
{tagsupport/math/struct/end}
{default}
{ \tag_mc_end: \tag_struct_end: }
\socket_assign_plug:nn {tagsupport/math/struct/begin}{default}
\socket_assign_plug:nn {tagsupport/math/struct/end}{default}
% \end{macrocode}
% \end{plugdecl}
%
% \begin{plugdecl}{mathml-AF}
% This socket tries to add a mathml-AF to formula.
% It is activated if a mathml.html has been found and loaded.
% As it disturbs the reading of the AF
% it currently deactivates the /Alt key,
% unless it has been reenabled with |math/alt/use=true|
% \begin{macrocode}
\cs_generate_variant:Nn \str_mdfive_hash:n {o}
\tl_new:N\l_@@_content_hash_tl
% \end{macrocode}
% we need to save the grabbed math:
% \begin{macrocode}
\tl_new:N\l_@@_grabbed_math_tl
% \end{macrocode}
% the socket definition
% \begin{macrocode}
\socket_new_plug:nnn
{tagsupport/math/struct/begin}
{mathml-AF}
{
\int_gincr:N\g_@@_math_total_int
\tl_set:Ne\l_@@_content_hash_tl
{\str_mdfive_hash:o { \l_@@_content_AF_source_tl }}
\tl_set_eq:NN\l_@@_grabbed_math_tl\g_@@_grabbed_math_tl
\tl_if_eq:NnTF\g_@@_grabbed_env_tl {math}
{
\tl_set:Nn\l_@@_attribute_class_tl{inline}
}
{
\tl_set:Nn\l_@@_attribute_class_tl{display}
}
\bool_if:NF\l__tag_math_alt_bool
{ \tl_set:Nn \l_@@_content_alt_tl{} }
% \end{macrocode}
% debugging option. TODO: hide in debug key.
% \begin{macrocode}
\tl_if_exist:cTF { g_@@_mathml_ \l_@@_content_hash_tl _tl }
{
\int_gincr:N\g_@@_mathml_AF_found_int
\bool_if:NTF \l__tag_math_mathml_AF_bool
{
\int_gincr:N\g_@@_mathml_AF_attached_int
\typeout {Inserting~mathml~with~Hash~\l_@@_content_hash_tl}
}
{
\typeout {Ignoring~mathml~with~Hash~\l_@@_content_hash_tl}
}
}
{
\bool_if:NT \l__tag_math_mathml_AF_bool
{
\typeout {WARNING:~mathml~missing~for~hash~\l_@@_content_hash_tl}
}
}
\socket_use:n {tagsupport/math/mathml/write/prepare}
\socket_use:n {tagsupport/math/mathml/write} % write hash if request
\bool_if:NTF\l__tag_math_texsource_AF_bool
{ \tl_set_eq:NN \l_@@_content_AF_source_tmpa_tl \l_@@_content_AF_source_tl }
{ \tl_clear:N \l_@@_content_AF_source_tmpa_tl }
\tag_struct_begin:n
{
tag=Formula,
attribute-class=\l_@@_attribute_class_tl, %
AFref =
\bool_if:NT\l__tag_math_mathml_AF_bool
{
\cs_if_exist_use:c {g_@@_mathml_ \l_@@_content_hash_tl _tl}
},
texsource = \l_@@_content_AF_source_tmpa_tl, % should be after mathml AF!
title-o = \g_@@_grabbed_env_tl, %
alt = \l_@@_content_alt_tl
}
\typeout{====>grabbed~math=\meaning\g_@@_grabbed_math_tl}
\tag_mc_begin:n{}
}
% \end{macrocode}
% not really needed but looks more symmetric:
% \begin{macrocode}
\socket_new_plug:nnn
{tagsupport/math/struct/end}
{mathml-AF}
{
\tag_mc_end:
\tag_struct_end:
}
% \end{macrocode}
% \end{plugdecl}
%
% \begin{socketdecl}{tagsupport/math/end}
% A socket used at the end of the math (before the closing dollar(s))
% which can, e.g., set a flag for luamml.
% \begin{macrocode}
\socket_new:nn {tagsupport/math/end}{0}
% \end{macrocode}
% \end{socketdecl}
%
%
% \changes{v0.6j}{2024-11-19}{removed enable/disable command and assign tagging sockets directly}
% \begin{macrocode}
\socket_assign_plug:nn {tagsupport/math/inline/begin}{MC}
\socket_assign_plug:nn {tagsupport/math/inline/end}{MC}
\socket_assign_plug:nn {tagsupport/math/inline/formula/begin}{default}
\socket_assign_plug:nn {tagsupport/math/inline/formula/end}{default}
\socket_assign_plug:nn {tagsupport/math/display/begin}{default}
\socket_assign_plug:nn {tagsupport/math/display/end}{default}
\socket_assign_plug:nn {tagsupport/math/display/formula/begin}{default}
\socket_assign_plug:nn {tagsupport/math/display/formula/end}{default}
% \end{macrocode}
%
%
% \subsection{Interface commands}
%
% \begin{macro}
% {\@@_process:nn, \@@_process:Vn, \@@_process_auxi:nn, \@@_process_auxii:nn}
% A no-op place-holder; the internal wrapper means that it does not need to
% be concerned with internals.
% \begin{macrocode}
\cs_new_protected:Npn \@@_process:nn #1#2
{
\legacy_if:nF { measuring@ }
{
\tl_if_in:nnTF {#2} { \m@th }
{ \bool_set_true:N\l_@@_fakemath_bool }
{ \tl_trim_spaces_apply:nN {#2} \@@_process_auxi:nn {#1} }
}
}
\cs_generate_variant:Nn \@@_process:nn { V }
\cs_new_protected:Npn \@@_process_auxi:nn #1#2
{
\tl_gset:Nn \g_@@_grabbed_env_tl {#2}
\tl_gset:Nn \g_@@_grabbed_math_tl {#1}
\@@_process_auxii:nn {#2} {#1}
}
\cs_new_protected:Npn \@@_process_auxii:nn #1#2 { }
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\math_processor:n}
% A simple installer
% \begin{macrocode}
\cs_new_protected:Npn \math_processor:n #1
{ \cs_set_protected:Npn \@@_process_auxii:nn ##1##2 {#1} }
% \end{macrocode}
% \end{macro}
%
% \subsection{Content grabbing}
%
% \begin{macro}{\MathCollectTrue,\MathCollectFalse}
% \begin{macrocode}
\cs_set_protected:Npn\MathCollectTrue{\bool_set_false:N \l__math_collected_bool}
\cs_set_protected:Npn\MathCollectFalse{\bool_set_true:N \l__math_collected_bool}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_grab_dollar:w}
% \begin{macro}{\@@_grab_dollar:n}
% \changes{v0.6c}{2024-08-22}{Correct handling of empty math segments}
% Top-level function to handle grabbing of inline math mode delimited by
% |$| tokens. We provide two different ways to do that: a token-by-token
% one that can be used everywhere, and a fast delimited one that does not
% work anywhere that the end |$| token may be hidden, most obviously in
% tabulars. The function here is therefore set up as a variable starting
% point.
% \begin{macrocode}
\cs_new_protected:Npn \@@_grab_dollar:w { \@@_grab_dollar_delim:w }
% \end{macrocode}
% After grabbing inline math material, there is again common processing
% independent of mechanism of collection.
% \begin{macrocode}
\cs_new_protected:Npn \@@_grab_dollar:n #1
{
% \end{macrocode}
% We need to do processing first as this picks up \enquote{fake} math mode:
% that information is needed below.
% \begin{macrocode}
\@@_process:nn { math } {#1}
% \end{macrocode}
% We do not want math tagging in fakemath or when measuring,
% We also do not want math tagging if tagging has been suspended.
% \begin{macrocode}
\bool_lazy_any:nTF
{
{\legacy_if_p:n { measuring@ }}
{ \l_@@_fakemath_bool }
{ \tl_if_blank_p:n {#1} }
}
{
\@@_luamml_ignore:
#1 $ % $
}
{
\tag_socket_use:n {math/inline/begin} %end P-MC
% \end{macrocode}
% We do no use a tagging socket here, so that the argument (the
% math) is not lost, tagging-project issue 661.
% \changes{v0.6j}{2024-11-19}{change socket to tagging socket}
% \begin{macrocode}
\tag_socket_use:nnn {math/inline/formula/begin}{}{#1}
$ % $
\tag_socket_use:n {math/inline/formula/end}
\tag_socket_use:n {math/inline/end} % restart P-MC
}
}
% \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_grab_dollar_delim:w}
% Grab up to a single |$|, for inline math mode, suppressing
% any processing if the token is \tn{m@th} found in the content.
% \begin{macrocode}
\cs_new_protected:Npn \@@_grab_dollar_delim:w #1 $ % $
{ \@@_grab_dollar:n {#1} }
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_grab_dollardollar:w}
% And for the classical \TeX{} display structure.
% \begin{macrocode}
\cs_new_protected:Npn \@@_grab_dollardollar:w % $$
#1 $$
{
\tl_if_blank:nF {#1}
{
\@@_process:nn { equation* } {#1}
\tag_socket_use:n {math/display/begin}
\tag_socket_use:nn{math/display/formula/begin}{}{#1}
}
$$
}
% \end{macrocode}
%
% The end code is added through a \cs{aftergroup} so we
% store it inside a command.
% \changes{v0.6j}{2024-11-19}{removed unneeded \cs{tagpdfparaOn}}
% \begin{macrocode}
\cs_new_protected:Npn \@@_tag_dollardollar_display_end:
{
% \typeout{== tag dollarldollar display end}
% \ShowTagging{struct-stack}
\para_raw_end:
% \end{macrocode}
% The \cs{postdisplaypenalty} was temporarily set
% to 10000 inside the display and the \cs{belowdisplayskip} and the
% \cs{belowdisplayshortskip} was negated, so whatever was inserted
% it should have been a negative skip. Whatever
% was added, we pick up the value up, so that we can correct
% the spacing after the tagging code was inserted.
% \begin{macrocode}
\l_@@_tmpa_skip \lastskip
\tag_socket_use:n{math/display/formula/end}
% \end{macrocode}
% Now we add a skip without introducing a page break possibility,
% that should bring the current vertical position back to the point
% where \TeX{} would add the penalty and the \enquote{below skip}.
% \changes{v0.6f}{2024-09-30}{Correct logic for inserting below skips
% after displays (tagging/721)}
% \begin{macrocode}
\nobreak
\skip_vertical:n { -\l_@@_tmpa_skip }
% \end{macrocode}
% Then we finally add the real stuff: the true \cs{postdisplaypenalty}
% and then negated value of skip we saved from above. It may look
% strange that we have two identical negated skips next to each
% other, but if you think about it, that is correct: the first
% cancels the \enquote{below skip} that \TeX{} had added and the
% second puts the same amount after the penalty (which is where it
% should be).
% \begin{macrocode}
\penalty \postdisplaypenalty
\skip_vertical:n { -\l_@@_tmpa_skip } % insert the correct skip
% \end{macrocode}
% As we are now in vertical mode the situation is different from
% the way \TeX{} would handle things after a display: \TeX{} would
% internally switch to horizontal mode without adding a
% \cs{parskip}. But this is not possible to do on the macro
% level. Therefore we have to neutralize the upcoming \cs{parskip}
% since we can't prevent it from being set.
% \changes{v0.6k}{2024/12/01}{Handle \cs{parskip} after \texttt{\$\$}
% display correctly (tagging/762)}
% \begin{macrocode}
% \typeout{------->~ add~ negative~ parskip~ (to~ cancel~ the~
% one~ that~ TeX~ will~ add)}
\skip_vertical:n { -\tex_parskip:D }
% \end{macrocode}
%
% We also set the \texttt{@domathendpetrue} flag to signal that the
% \begin{macrocode}
\@domathendpetrue
\@doendpe % this has no \end{...} to take care of it
}
% \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\@@_grab_inline:w}
% Collect inline math content and deal with the need to move to math mode.
% \begin{macrocode}
\cs_new_protected:Npn \@@_grab_inline:w % \(
#1 \)
{
\tl_if_blank:nF {#1}
{
$ #1 $
}
\bool_set_false:N \l_@@_collected_bool
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_grab_eqn:w}
% For the most common use of \cs{[}/\cs{]}: turn into an environment.
% \begin{macrocode}
\cs_new_protected:Npn \@@_grab_eqn:w % \[
#1 \]
{
% \typeout{collected? = \bool_if:NTF \l_@@_collected_bool {true}{false}}
\begin { equation* } #1 \end { equation* }
}
% \end{macrocode}
% \end{macro}
%
% \subsection{Token-by-token inline grabbing}
%
% Grabbing inline math token-by-token is more involved. The mechanism here
% is essentially a simplified version of that originally seen in
% \pkg{collcell} and refined in \pkg{siunitx}. We make use of the fact that
% in math mode spaces are ignored, so we have to deal with only \texttt{N}-type
% tokens and groups. Furthermore, there is no need to look inside groups, so
% the only special cases are a small selection of \texttt{N}-type tokens.
%
% \begin{variable}{\l_@@_grabbed_tl}
% For collection of the material piecewise.
% \begin{macrocode}
\tl_new:N \l_@@_grabbed_tl
% \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_@@_grab_env_int}
% Needed to count up the number of nested environments encountered.
% \begin{macrocode}
\int_new:N \l_@@_grab_env_int
% \end{macrocode}
% \end{variable}
%
% \begin{macro}{\@@_grab_dollar_loop:}
% \begin{macro}{\@@_grab_loop:}
% The lead-off here establishes a group: we need that as we will have to
% be careful in the way \tn{cr} is handled and ensure this is only
% manipulated whilst grabbing. The main loop is then started.
% \begin{macrocode}
\cs_new_protected:Npn \@@_grab_dollar_loop:
{
\group_begin:
\tl_clear:N \l_@@_grabbed_tl
\@@_grab_loop:
}
\cs_new_protected:Npn \@@_grab_loop:
{
\peek_remove_spaces:n
{
\peek_meaning:NTF \c_group_begin_token
{ \@@_grab_loop_group:n }
{ \@@_grab_loop_token:N }
}
}
% \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_grab_loop_group:n}
% \begin{macro}{\@@_grab_loop_store:n}
% Handling of grabbed groups is pretty easy.
% \begin{macrocode}
\cs_new_protected:Npn \@@_grab_loop_group:n #1
{ \@@_grab_loop_store:n { {#1} } }
\cs_new_protected:Npn \@@_grab_loop_store:n #1
{
\tl_put_right:Nn \l_@@_grabbed_tl {#1}
\@@_grab_loop:
}
% \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_grab_loop_token:N}
% \begin{macro}
% {
% \@@_grab_loop_$: ,
% \@@_grab_loop_\\: ,
% \@@_grab_loop_\begin: ,
% \@@_grab_loop_\end: ,
% \@@_grab_loop_\ignorespaces: ,
% \@@_grab_loop_\unskip: ,
% \@@_grab_loop_\textonly@unskip:
% }
% Filter out the special cases: for performance reasons, use a hash table
% approach rather than a loop (\emph{cf.}~\pkg{collcell}).
% \begin{macrocode}
\cs_new_protected:Npn \@@_grab_loop_token:N #1
{
\cs_if_exist_use:cF
{ @@_grab_loop_ \token_to_str:N #1 : }
{ \@@_grab_loop_store:n {#1} }
}
\cs_new_protected:cpn { @@_grab_loop_ \token_to_str:N $ : }
{ \@@_grab_loop_end: }
\cs_new_protected:cpn { @@_grab_loop_ \token_to_str:N \\ : }
{
\int_compare:nNnTF \l_@@_grab_env_int = 0
{ \@@_grab_loop_newline: }
{ \@@_grab_loop_store:n { \\ } }
}
% \end{macrocode}
% In contrast to \pkg{collcell}, nesting is tracked by counting
% \cs{begin}/\cs{end} pairs: this is needed in case there is a tabular-like
% construct containing |\\| inside a cell. As a result, the end-of-tabular
% can be detected without checking the name argument: if \cs{end} is
% encountered at nesting level~0, we've hit the end of a cell. In that case,
% end the row and leave the environment to clean up.
% \begin{macrocode}
\cs_new_protected:cpn { @@_grab_loop_ \token_to_str:N \begin : }
{
\int_incr:N \l_@@_grab_env_int
\@@_grab_loop_store:n { \begin }
}
\cs_new_protected:cpn { @@_grab_loop_ \token_to_str:N \end : }
{
\int_compare:nNnTF \l_@@_grab_env_int = 0
{
\@@_grab_loop_newline:
\end
}
{
\int_decr:N \l_@@_grab_env_int
\@@_grab_loop_store:n { \end }
}
}
\tl_map_inline:nn { \ignorespaces \unskip \textonly@unskip }
{
\cs_new_protected:cpn { @@_grab_loop_ \token_to_str:N #1 : }
{ \@@_grab_loop: }
}
% \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_grab_loop_newline:}
% To allow collection of tokens in the part of the \tn{halign} template after
% |#|, we need \TeX{} to see the primitive with the loop token in the right
% place. That is done by re-defining \tn{cr} at present. Ideally there would
% be a socket in the definition of \texttt{tabular}, etc., to handle this:
% there is also the need to examine in interaction with \pkg{longtable}, which
% also redefines \tn{cr}.
% \begin{macrocode}
\cs_new_protected:Npn \@@_grab_loop_newline:
{
\if_false: { \fi:
\cs_set_protected:Npn \cr
{
\@@_grab_loop:
\tex_cr:D
}
\if_false: } \fi:
\\
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_grab_loop_end:}
% Clean up and pass on.
% \begin{macrocode}
\cs_new_protected:Npn \@@_grab_loop_end:
{
\exp_args:NNV \group_end:
\@@_grab_dollar:n \l_@@_grabbed_tl
}
% \end{macrocode}
% \end{macro}
%
% \subsection{Marking math environments}
%
% A general mechanism for math mode environments that do not grab their
% content (\emph{cf.}~most \pkg{amsmath} environments).
%
% \begin{variable}{\l_@@_env_name_tl}
% To allow us to carry out \enquote{special effects}
% \begin{macrocode}
\tl_new:N \l_@@_env_name_tl
% \end{macrocode}
% \end{variable}
%
% Here we set up specialised handling of environments. The idea for the
% \texttt{arg-spec} key is that if an environment takes arguments, we
% don't worry during the main grabbing. Rather, we remove the arguments
% from the grabbed content and forward only the payload. That is done by
% (ab)using \pkg{ltcmd}.
% \begin{macrocode}
\keys_define:nn { @@ }
{
arg-spec .code:n =
{
\ExpandArgs { c } \DeclareDocumentCommand
{ @@_env \l_@@_env_name_tl _aux: }
{#1}
{ \@@_env_forward:w }
}
}
% \end{macrocode}
%
% \begin{macro}{\math_register_env:nn}
% \begin{macro}{\math_register_env:n}
% \begin{macro}{\RegisterMathEnvironment}
% Set up to capture environment content and make available.
% \changes{0.6k}{2024-12-04}{Store the current grouplevel for luamml }
% \begin{macrocode}
\cs_new_protected:Npn \math_register_env:nn #1#2
{
\tl_set:Nn \l_@@_env_name_tl {#1}
\keys_set:nn { @@ } {#2}
\cs_gset_eq:cc { @@_env_ #1 _begin: } {#1}
\cs_gset_eq:cc { @@_env_ #1 _end: } { end #1 }
%
\ExpandArgs { nne } \RenewDocumentEnvironment {#1} { b }
{
\exp_not:N \bool_if:NTF \exp_not:N \l_@@_collected_bool
{
% \typeout{===>B1}
}
{
% \typeout{===>B2}
\cs_if_exist:cTF { @@_env #1 _aux: }
{
\exp_not:c { @@_env #1 _aux: }
##1 \exp_not:N \@@_env_end: {#1}
}
{ \exp_not:N \@@_process:nn {#1} {##1} }
\exp_not:n { \@kernel@math@registered@begin }
\bool_set_true:N \exp_not:N \l_@@_collected_bool
}
% \exp_not:N \tracingall
\exp_not:c { @@_env_ #1 _begin: }
##1
\exp_not:c { @@_env_ #1 _end: }
% \exp_not:N \tracingnone
}
{
}
}
% \end{macrocode}
% \changes{v0.6k}{2024/12/04}{Add tagging sockets for luamml support}
% \changes{v0.6k}{2024/12/04}{Store the current grouplevel for luamml }
% \begin{macrocode}
\cs_new_protected:Npn \math_register_halign_env:nn #1#2
{
\tl_set:Nn \l_@@_env_name_tl {#1}
\keys_set:nn { @@ } {#2}
\cs_gset_eq:cc { @@_env_ #1 _begin: } {#1}
\cs_gset_eq:cc { @@_env_ #1 _end: } { end #1 }
%
\ExpandArgs { nnee } \RenewDocumentEnvironment {#1} { b }
{
\exp_not:N \bool_if:NTF \exp_not:N \l_@@_collected_bool
{
% \typeout{===>B1}
}
{
% \typeout{===>B2}
\cs_if_exist:cTF { @@_env #1 _aux: }
{
\exp_not:c { @@_env #1 _aux: }
##1 \exp_not:N \@@_env_end: {#1}
}
{ \exp_not:N \@@_process:nn {#1} {##1} }
\exp_not:n { \@kernel@math@registered@begin }
\bool_set_true:N \exp_not:N \l_@@_collected_bool
}
% \exp_not:N \tracingall
\exp_not:c { @@_env_ #1 _begin: }
##1
% \exp_not:N \tracingnone
}
{
\exp_not:c { @@_env_ #1 _end: }
}
}
% \end{macrocode}
% TODO: the following command is neither documented nor used. Is is needed?
% TODO: if it is ever used in needs to set the current group level too.
% \begin{macrocode}
\cs_new_protected:Npn \math_register_odd_env:nn #1#2
{
\tl_set:Nn \l_@@_env_name_tl {#1}
\keys_set:nn { @@ } {#2}
\cs_gset_eq:cc { @@_env_ #1 _begin: } {#1}
\cs_gset_eq:cc { @@_env_ #1 _end: } { end #1 }
%
\ExpandArgs { nnee } \RenewDocumentEnvironment {#1} { b }
{
\exp_not:N \bool_if:NTF \exp_not:N \l_@@_collected_bool
{
% \typeout{===>B1}
}
{
% \typeout{===>B2}
\cs_if_exist:cTF { @@_env #1 _aux: }
{
\exp_not:c { @@_env #1 _aux: }
##1 \exp_not:N \@@_env_end: {#1}
}
{ \exp_not:N \@@_process:nn {#1} {##1} }
\exp_not:n { \@kernel@math@registered@begin }
\bool_set_true:N \exp_not:N \l_@@_collected_bool
}
% \exp_not:N \tracingall
\exp_not:c { @@_env_ #1 _begin: }
##1
}
{
\exp_not:c { @@_env_ #1 _end: }
% needed if we don't have $$...$$
% \exp_not:n { \typeout{---> @kernel@math@registered@end }}
\exp_not:n { \@kernel@math@registered@end }
}
}
\cs_new:Npn \@kernel@math@registered@begin {
% \ShowTagging{struct-stack}
%\typeout{==>A1}\ShowTagging{struct-stack,mc-current}
\mode_if_vertical:TF
{
% \legacy_if:nTF { @endpe }
% { \legacy_if_set_false:n { @endpe } }
% { \__block_list_beginpar_vmode: }
%
% \typeout{==>~ at:~ \g__tag_struct_tag_tl}
%
\tag_if_active:T
{
\exp_args:Noo\str_if_eq:nnF \g__tag_struct_tag_tl { \l__tag_para_main_tag_tl } % needs correction!
{
% \typeout{==>A2}
\__block_beginpar_vmode:
} % needs correction!
}
}
{
% \typeout{==>A3}
\__tag_tool_close_P:
}
\tag_socket_use:nn{math/display/formula/begin}{}{}
% \typeout{==>MC1}\ShowTagging{mc-current}
}
\cs_new:Npn \@kernel@math@registered@end {
% \typeout{==>MC2}\ShowTagging{mc-current}
\para_raw_end:
\tagpdfparaOn
\tag_socket_use:n{tagsupport/math/display/formula/end}
% \typeout{==>MC3}\ShowTagging{mc-current}
\@endpetrue
}
\cs_new_protected:Npn \math_register_env:n #1
{ \math_register_env:nn {#1} { } }
\NewDocumentCommand \RegisterMathEnvironment { O{} m }
{ \math_register_env:nn {#2} {#1} }
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_env_forward:w}
% \begin{macrocode}
\cs_new_protected:Npn \@@_env_forward:w #1 \@@_env_end: #2
{ \@@_process:nn {#2} {#1} }
% \end{macrocode}
% \end{macro}
%
% \subsection{Document commands}
%
% \car*{Add one more here: \texttt{displaymath}, which
% is equivalent to \cs{[} , \cs{]}\\
% and hence to the basic \texttt{equation*}.\\
% Added in more recent branch.}
%
% \begin{macro}
% {\equation, \@@_equation_begin:, \equation*, \@@_equation_star_begin:}
% \begin{macro}
% {\endequation, \@@_equation_end:, \endequation*, \@@_equation_star_end:}
% These environments are not set up by \pkg{amsmath} to collect their body,
% so we do that here. This has to be done \emph{after} we can be sure
% \pkg{amsmath} is loaded.
%
% \car*{Note that with \pkg{amsmath} loaded, \texttt{equation*} and \texttt{equation}\\
% are the two basics: they are used to define the other single-row\\
% display environments, etc.}
%
% \begin{macrocode}
\tl_gput_right:Nn \@kernel@before@begindocument
{
\math_register_env:n { equation }
\math_register_env:n { equation* }
% at the moment register_env can only do display math
% \math_register_env:n { math }
\RenewDocumentEnvironment{math} {b}{$#1$}{}
% and this one doesn't work either
% \math_register_env:n { displaymath }
\RenewDocumentEnvironment{displaymath} {b}{\[#1\]}{}
}
% \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\(, \)}
% If math mode has not been collected, we need to do that; otherwise, worry
% about whether we are in math mode or not. The closing command here can only
% occur inside a collected math block: otherwise it will be simply used as
% a delimiter.
% \begin{macrocode}
\cs_gset_protected:Npn \( % \)
{
\bool_if:NTF \l_@@_collected_bool
{
\mode_if_math:TF
{ \@badmath }
{ $ }
}
{
\@@_grab_inline:w
}
} % \(
\cs_gset_protected:Npn \)
{
\mode_if_math:TF
{ $ }
{ \@badmath }
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\[, \]}
% Again, we need to watch for when \pkg{amsmath} is loaded after this code.
% The flag usage here is to cover the case where \cs{[}/\cs{]} is hidden
% inside another environment. In this case the grabbing happens on
% the outer level and should not be repeated.
% \begin{macrocode}
\tl_gput_right:Nn \@kernel@before@begindocument
{
\cs_gset_protected:Npn \[ % \]
{
\@@_grab_eqn:w
% \bool_if:NTF \l_@@_collected_bool
% { \begin { equation* } }
% { \@@_grab_eqn:w }
} % \[
\cs_gset_protected:Npn \]
{
\@badmath
% \bool_if:NTF \l_@@_collected_bool
% { \end{ equation* } }
% { \@badmath }
}
}
% \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\ensuremath}
% A bit of nesting fun to make sure we collect only if required.
% \fmi{why does ensuremath need handling at all?}
%
% \car{Indeed! Currently, this is setup to process the math that
% it has anyways already captured as its argument; thus it is more
% efficient than leaving the capture to be repeated by the \cs{everymath}}
%
% \begin{macrocode}
%\cs_gset_protected:Npn \ensuremath #1
% {
% \mode_if_math:TF
% {#1}
% {
% \bool_if:NTF \l_@@_collected_bool
% { \@ensuredmath {#1} }
% {
% \bool_set_true:N \l_@@_collected_bool
% \@@_process:nn { math } {#1}
% \@ensuredmath {#1}
% \bool_set_false:N \l_@@_collected_bool
% }
% }
% }
% \end{macrocode}
% \end{macro}
%
% \subsection{\cs{everymath} and \cs{everydisplay}}
%
% The business end for grabbing inline math and \enquote{raw} \TeX{}
% display. Most display math mode is actually handled elsewhere, as we
% have macro control.
% \begin{macrocode}
\exp_args:No \tex_everymath:D
{
\tex_the:D \tex_everymath:D
\bool_if:NF \l_@@_collected_bool
{
\bool_set_true:N \l_@@_collected_bool
\@@_grab_dollar:w
}
}
\exp_args:No \tex_everydisplay:D
{
\tex_the:D \tex_everydisplay:D
\iftrue % this may have to be a settable flag!
% \typeout{==>~ in~ everydisplay}
% \end{macrocode}
% flipping the \cs{belowdisplay} values is done so that we get (assumption)
% a negative skip and not make the page bigger then we take that out,
% then we add the tagging code (in \cs{@@_tag_dollardollar_display_end} ) and
% then we put a real \cs{postdisplaypenalty} in and
% the right skip (of which we don't know if it is short or a
% normal \cs{belowdisplayskip}). This might need some refinement if that skip
% is actually negative from the start
% (not sure it ever is and is worth bothering about)
% \begin{macrocode}
\skip_set:Nn \belowdisplayskip {-\belowdisplayskip}
\skip_set:Nn \belowdisplayshortskip {-\belowdisplayshortskip}
\int_set:Nn \postdisplaypenalty {10000}
\group_insert_after:N \@@_tag_dollardollar_display_end:
\fi
\bool_if:NF \l_@@_collected_bool
{
\bool_set_true:N \l_@@_collected_bool
\@@_grab_dollardollar:w
}
}
% \end{macrocode}
%
% \subsection{Modifying kernel environments}
%
% We need to cover this even though it is, of course, not encouraged.
% \begin{macrocode}
\math_register_env:n { eqnarray }
\math_register_env:n { eqnarray* }
% \end{macrocode}
%
% Tabulars currently contain a \$ that shouldn't trigger math
% tagging. Also we do need to change the grabbing method to the slow
% loop-method.
% \begin{macrocode}
\RequirePackage{array}
\tl_if_exist:NT\@kernel@tabular@init
{
\tl_put_right:Nn\@kernel@tabular@init
{\cs_set_protected:Npn \@@_grab_dollar:w { \@@_grab_dollar_loop: }}
}
% \end{macrocode}
%
% \begin{macro}{\@@_m@th:, \m@th}
% Handle non-math use of math mode. At present nesting isn't supported as
% \cs{m@th} pops up in a few places that \emph{are} math mode!
% \begin{macrocode}
\cs_new_eq:NN \@@_m@th: \m@th
\cs_gset_protected:Npn \m@th
{
\bool_set_true:N \l_@@_collected_bool
\@@_m@th:
}
% \end{macrocode}
% \end{macro}
%
% \subsection{Modifying kernel commands}
%
% \begin{macro}{\mathpalette}
% The \cs{mathpalette} command is a problem if lualatex is used and math
% structure elements are created as the math is then processed more than once.
% We therefore redefine it to use \cs{mathstyle}.
%
% \begin{macrocode}
\sys_if_engine_luatex:T
{
\def\mathpalette#1#2{%
\ifcase\mathstyle
#1\displaystyle{#2}\or
#1\displaystyle{#2}\or
#1\textstyle{#2}\or
#1\textstyle{#2}\or
#1\scriptstyle{#2}\or
#1\scriptstyle{#2}\or
#1\scriptscriptstyle{#2}\or
#1\scriptscriptstyle{#2}
\fi}
}
% \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\mathsm@sh}
% Similar to the phantom commands in latex-lab-text, \cs{mathsm@sh} must be
% redefined to include luamml sockets.
% \begin{macrocode}
\def\mathsm@sh#1#2{%
\setbox\z@\hbox{$\m@th#1{#2}
\UseTaggingSocket{math/luamml/save/nNn}{{mathsmash} #1 {mpadded}}
$}%
\UseTaggingSocket{math/luamml/finsm@sh}{}{{}\finsm@sh}}
% \end{macrocode}
% \end{macro}
%
% \subsection{Disable math grabbing in the begindocument hook}
% For example amsart uses math to measure text there.
%
% \begin{macrocode}
\tl_gput_right:Nn\@kernel@before@begindocument
{
\bool_set_true:N\l_@@_collected_bool
}
\tl_gput_right:Nn\@kernel@after@begindocument
{
\bool_set_false:N\l_@@_collected_bool
}
% \end{macrocode}
%
%
% \begin{macrocode}
\ExplSyntaxOff
% \end{macrocode}
%
% \begin{macrocode}
%<@@=>
% \end{macrocode}
%
% \begin{macrocode}
%
% \end{macrocode}
%
% \Finale
%
%