% \iffalse meta-comment % %% File: tagpdf.dtx % % Copyright (C) 2019-2024 Ulrike Fischer % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this % license or (at your option) any later version. The latest version % of this license is in the file % % https://www.latex-project.org/lppl.txt % % This file is part of the "tagpdf bundle" (The Work in LPPL) % and all files in that bundle must be distributed together. % % ----------------------------------------------------------------------- % % The development version of the bundle can be found at % % https://github.com/latex3/tagpdf % % for those people who are interested. % % \fi % \begin{documentation} % \begin{function}{ % \tag_stop:, \tag_start:, % \tagstop, \tagstart } % We need commands to stop tagging in some places. % They switches three local booleans and also stop the counting % of paragraphs. If they are nested an inner \cs{tag_start:} will not % restart tagging. % \end{function} % % \begin{function}{\tag_stop:n, \tag_start:n }% % \begin{syntax} % \cs{tag_stop:n}\Arg{label} % \cs{tag_start:n}\Arg{label}\\ % \end{syntax} % The commands with argument allow to give a label. This is only used % in debugging messages to allow to follow the nesting. % \end{function} % % \begin{function}{activate/spaces (setup-key)} % |activate/spaces| activates the additional parsing needed for % interword spaces. It replaces the deprecated key |interwordspace|. % \end{function} % % \begin{function}{activate/mc (setup-key), % activate/tree (setup-key), % activate/struct (setup-key), % activate/all (setup-key), % activate-mc (deprecated), % activate-tree (deprecated), % activate-struct (deprecated), % activate-all (deprecated), % } % Keys to activate the various tagging steps. % \end{function} %\begin{function}{activate/struct-dest (setup-key),no-struct-dest (deprecated)} % The key allows to suppress the creation of structure destinations % \end{function} % % \begin{function}{debug/log (setup-key)} % The |debug/log| key takes currently the values |none|, |v|, |vv|, |vvv|, |all|. % More details are in \texttt{tagpdf-checks}. % \end{function} % % \begin{function}{activate/tagunmarked (setup-key), tagunmarked (deprecated) } % This key allows to set if (in luamode) unmarked text should be % marked up as artifact. The initial value is true. % \end{function} % % \begin{function}{page/tabsorder (setup-key), tabsorder (deprecated)} % This sets the tabsorder on a page. The values are |row|, |column|, |structure| (default) % or |none|. Currently this is set more or less globally. More finer control can be % added if needed. % \end{function} % % \begin{function}{tagstruct,tagstructobj,tagabspage,tagmcabs,tagmcid} % These are attributes used by the label/ref system. % \end{function} % \end{documentation} % \begin{implementation} % \section{Initialization and test if pdfmanagement is active.} % \begin{macrocode} %<@@=tag> %<*package> \ProvidesExplPackage {tagpdf} {2024-04-12} {0.99b} { A package to experiment with pdf tagging } \bool_if:nF { \bool_lazy_and_p:nn {\cs_if_exist_p:N \pdfmanagement_if_active_p:} { \pdfmanagement_if_active_p: } } { %error for now, perhaps warning later. \PackageError{tagpdf} { PDF~resource~management~is~no~active!\MessageBreak tagpdf~will~no~work. } { Activate~it~with \MessageBreak \string\RequirePackage{pdfmanagement-testphase}\MessageBreak \string\DocumentMetadata{}\MessageBreak before~\string\documentclass } } % % \end{macrocode} %<*debug> % \begin{macrocode} \ProvidesExplPackage {tagpdf-debug} {2024-04-12} {0.99b} { debug code for tagpdf } \@ifpackageloaded{tagpdf}{}{\PackageWarning{tagpdf-debug}{tagpdf~not~loaded,~quitting}\endinput} % \end{macrocode} % % We map the internal module name \enquote{tag} to \enquote{tagpdf} in messages. % \begin{macrocode} %<*package> \prop_gput:Nnn \g_msg_module_name_prop { tag }{ tagpdf } % % \end{macrocode} % Debug mode has its special mapping: % \begin{macrocode} %<*debug> \prop_gput:Nnn \g_msg_module_type_prop { tag / debug} {} \prop_gput:Nnn \g_msg_module_name_prop { tag / debug }{tagpdf~DEBUG} % % \end{macrocode} %\section{base package} % To avoid to have to test everywhere if tagpdf has been loaded and is active, % we define a base package with dummy functions % \begin{macrocode} %<*base> \ProvidesExplPackage {tagpdf-base} {2024-04-12} {0.99b} {part of tagpdf - provide base, no-op versions of the user commands } % % \end{macrocode} %\section{Package options} % There are only two documented options to switch for luatex between generic and luamode, % TODO try to get rid of them. % The option \texttt{disabledelayedshipout} is only temporary to be able to debug % problem with the new shipout keyword if needed. % \begin{macrocode} %<*package> \bool_new:N\g_@@_mode_lua_bool \bool_new:N\g_@@_delayed_shipout_bool \bool_lazy_and:nnT { \bool_if_exist_p:N \l__pdfmanagement_delayed_shipout_bool } { \l__pdfmanagement_delayed_shipout_bool } { \bool_gset_true:N\g_@@_delayed_shipout_bool } \DeclareOption {luamode} { \sys_if_engine_luatex:T { \bool_gset_true:N \g_@@_mode_lua_bool } } \DeclareOption {genericmode}{ \bool_gset_false:N\g_@@_mode_lua_bool } \DeclareOption {disabledelayedshipout}{ \bool_gset_false:N\g_@@_delayed_shipout_bool } \ExecuteOptions{luamode} \ProcessOptions % \end{macrocode} % \section{Packages} % To be on the safe side for now, load also the base definitions % \begin{macrocode} \RequirePackage{tagpdf-base} % % \end{macrocode} % The no-op version should behave a near enough to the real code as % possible, so we define a command which a special in the relevant backends: % \begin{macrocode} %<*base> \AddToHook{begindocument} { \str_case:VnF \c_sys_backend_str { { luatex } { \cs_new_protected:Npn \@@_whatsits: {} } { dvisvgm } { \cs_new_protected:Npn \@@_whatsits: {} } } { \cs_new_protected:Npn \@@_whatsits: {\tex_special:D {} } } } % % \end{macrocode} % \subsection{Indexed objects} % 2024-04-11: Temporary code! Can be removed after the next expl3 release! % \begin{macrocode} \cs_if_free:NT \pdf_object_new_indexed:nn { \cs_generate_variant:Nn \pdf_object_new:n {e} \cs_generate_variant:Nn \pdf_object_write:nnn {enn} \cs_new_protected:Npn \pdf_object_new_indexed:nn #1 #2 { \pdf_object_new:e {#1/\int_eval:n{#2}} } \cs_new_protected:Npn \pdf_object_write_indexed:nnnn #1 #2 #3 #4 { \pdf_object_write:enn {#1/\int_eval:n{#2}}{#3}{#4} } \cs_generate_variant:Nn \pdf_object_write_indexed:nnnn {nnne} \cs_new:Npn\pdf_object_ref_indexed:nn #1 #2 { \pdf_object_ref:e {#1/\int_eval:n{#2}} } \cs_new:Npn \__kernel_pdf_object_id_indexed:nn #1 #2 { \int_use:c { c__pdf_object_ #1/\int_eval:n{#2} _int } } } % \end{macrocode} % \subsection{a LastPage label} % See also issue \#2 in Accessible-xref % \begin{macro}{\@@_lastpagelabel:} % \begin{macrocode} %<*package> \cs_new_protected:Npn \@@_lastpagelabel: { \legacy_if:nT { @filesw } { \exp_args:NNne \exp_args:NNe\iow_now:Nn \@auxout { \token_to_str:N \new@label@record {@tag@LastPage} { {abspage} { \int_use:N \g_shipout_readonly_int} {tagmcabs}{ \int_use:N \c@g_@@_MCID_abs_int } {tagstruct}{\int_use:N \c@g_@@_struct_abs_int } } } } } \AddToHook{enddocument/afterlastpage} {\@@_lastpagelabel:} % \end{macrocode} % \end{macro} % % \section{Variables} % \begin{variable} % { % \l_@@_tmpa_tl, % \l_@@_tmpb_tl, % \l_@@_get_tmpc_tl, % \l_@@_get_parent_tmpa_tl % \l_@@_get_parent_tmpb_tl % \l_@@_tmpa_str, % \l_@@_tmpa_prop, % \l_@@_tmpa_seq, % \l_@@_tmpb_seq, % \l_@@_tmpa_clist, % \l_@@_tmpa_int, % \l_@@_tmpa_box, % \l_@@_tmpb_box % } % A few temporary variables % \begin{macrocode} \tl_new:N \l_@@_tmpa_tl \tl_new:N \l_@@_tmpb_tl \tl_new:N \l_@@_get_tmpc_tl \tl_new:N \l_@@_get_parent_tmpa_tl \tl_new:N \l_@@_get_parent_tmpb_tl \str_new:N \l_@@_tmpa_str \prop_new:N \l_@@_tmpa_prop \seq_new:N \l_@@_tmpa_seq \seq_new:N \l_@@_tmpb_seq \clist_new:N \l_@@_tmpa_clist \int_new:N \l_@@_tmpa_int \box_new:N \l_@@_tmpa_box \box_new:N \l_@@_tmpb_box % \end{macrocode} % \end{variable} % Attribute lists for the label command. We have a list for % mc-related labels, and one for structures. % \begin{macro}{\c_@@_property_mc_clist,\c_@@_property_struct_clist} % \begin{macrocode} \clist_const:Nn \c_@@_property_mc_clist {tagabspage,tagmcabs,tagmcid} \clist_const:Nn \c_@@_property_struct_clist {tagstruct,tagstructobj} % \end{macrocode} % \end{macro} % % \begin{variable}{\l_@@_loglevel_int} % This integer hold the log-level and so allows to % control the messages. % TODO: a list which log-level shows what is needed. The current behaviour % is quite ad-hoc. % \begin{macrocode} \int_new:N \l_@@_loglevel_int % \end{macrocode} % \end{variable} % % \begin{variable} % { % \g_@@_active_space_bool, % \g_@@_active_mc_bool, % \g_@@_active_tree_bool, % \g_@@_active_struct_bool, % \g_@@_active_struct_dest_bool % } % These booleans should help to control the global behaviour of tagpdf. % Ideally it should more or less do nothing if all are false. % The space-boolean controls the interword space code, % the mc-boolean activates \cs{tag_mc_begin:n}, % the tree-boolean activates writing the finish code and the pdfmanagement related % commands, the struct-boolean activates the storing of the structure data. % In a normal document all should be active, the split is only there for % debugging purpose. % Structure destination will be activated automatically, % but with the boolean struct-dest-boolean one can suppress them. % Also we assume currently that they are set only at begin document. But % if some control passing over groups are needed they could be perhaps % used in a document too. % TODO: check if they are used everywhere as needed and as wanted. % \begin{macrocode} \bool_new:N \g_@@_active_space_bool \bool_new:N \g_@@_active_mc_bool \bool_new:N \g_@@_active_tree_bool \bool_new:N \g_@@_active_struct_bool \bool_new:N \g_@@_active_struct_dest_bool \bool_gset_true:N \g_@@_active_struct_dest_bool % \end{macrocode} % \end{variable} % \begin{variable} % { % \l_@@_active_mc_bool, % \l_@@_active_struct_bool, % \l_@@_active_socket_bool % } % These booleans should help to control the \emph{local} behaviour of tagpdf. % In some cases it could e.g. be necessary to stop tagging completely. % As local booleans they respect groups. % TODO: check if they are used everywhere as needed and as wanted. % \begin{macrocode} \bool_new:N \l_@@_active_mc_bool \bool_set_true:N \l_@@_active_mc_bool \bool_new:N \l_@@_active_struct_bool \bool_set_true:N \l_@@_active_struct_bool \bool_new:N \l_@@_active_socket_bool % \end{macrocode} % \end{variable} % % \begin{variable}{\g_@@_tagunmarked_bool} % This boolean controls if the code should try to automatically % tag parts not in mc-chunk. It is currently only used in luamode. % It would be possible to used it in generic mode, but this would create % quite a lot empty artifact mc-chunks. % \begin{macrocode} \bool_new:N \g_@@_tagunmarked_bool % \end{macrocode} % \end{variable} % % \section{Variants of l3 commands} % \begin{macrocode} \prg_generate_conditional_variant:Nnn \pdf_object_if_exist:n {e}{T,F,TF} \cs_generate_variant:Nn \pdf_object_ref:n {e} \cs_generate_variant:Nn \pdfannot_dict_put:nnn {nne} \cs_generate_variant:Nn \pdffile_embed_stream:nnn {nee,oee} \cs_generate_variant:Nn \prop_gput:Nnn {Nee,Nen} %** unneeded \cs_generate_variant:Nn \prop_put:Nnn {Nee} %** unneeded \cs_generate_variant:Nn \prop_item:Nn {No,Ne} %** unneeded \cs_generate_variant:Nn \seq_set_split:Nnn{Nne} %** unneeded \cs_generate_variant:Nn \str_set_convert:Nnnn {Nonn, Noon, Nnon } \cs_generate_variant:Nn \clist_map_inline:nn {on} % \end{macrocode} % % \section{Label and Reference commands} % To ease transition to properties we setup internal definition. They can be replaced % by the property definitions once that is released. % %** do it! % \begin{macro}{\@@_property_new:nnnn,\@@_property_gset:nnnn,\@@_property_ref:nnn} % At first a command to define new properties % \begin{macrocode} \cs_new_eq:NN \@@_property_new:nnnn \property_new:nnnn % \end{macrocode} % For the non-shipout code we need also the option to reset property % \begin{macrocode} \cs_new_eq:NN \@@_property_gset:nnnn \property_gset:nnnn % \end{macrocode} % The command to reference while giving a local default. % \begin{macrocode} \cs_new_eq:NN \@@_property_ref:nnn \property_ref:nnn \cs_new_eq:NN \@@_property_ref:nn \property_ref:nn % \end{macrocode} % The command to record % \begin{macrocode} \cs_new_protected:Npn \@@_property_record:nn #1#2 { \@bsphack \property_record:nn{#1}{#2} \@esphack } % \end{macrocode} % And a few variants % \begin{macrocode} \cs_generate_variant:Nn \@@_property_ref:nnn {enn} \cs_generate_variant:Nn \@@_property_ref:nn {en} \cs_generate_variant:Nn \@@_property_record:nn {en,eV} % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_property_ref_lastpage:nn} % A command to retrieve the lastpage label, this will be adapted when there % is a proper, kernel lastpage label. % \begin{macrocode} \cs_new:Npn \@@_property_ref_lastpage:nn #1 #2 { \@@_property_ref:nnn {@tag@LastPage}{#1}{#2} } % \end{macrocode} %\end{macro} % \section{Setup label attributes} % \begin{macro}{tagstruct,tagstructobj,tagabspage,tagmcabs,tagmcid} % This are attributes used by the label/ref system. % With structures we store the structure number |tagstruct| % and the object reference |tagstructobj|. % The second is needed to be able to reference a structure which hasn't been % created yet. The alternative would be to create the object in such cases, % but then we would have to check the object existence all the time. % % With mc-chunks we store the absolute page number |tagabspage|, % the absolute id |tagmcabc|, and the id on the page |tagmcid|. % \begin{macrocode} \@@_property_new:nnnn { tagstruct } { now } {0} { \int_use:N \c@g_@@_struct_abs_int } \@@_property_new:nnnn { tagstructobj } { now } {} { \pdf_object_ref_indexed:nn { @@/struct } { \c@g_@@_struct_abs_int } } \@@_property_new:nnnn { tagabspage } { shipout } {0} { \int_use:N \g_shipout_readonly_int } \@@_property_new:nnnn { tagmcabs } { now } {0} { \int_use:N \c@g_@@_MCID_abs_int } \flag_new:n { @@/mcid } \@@_property_new:nnnn {tagmcid } { shipout } {0} { \flag_height:n { @@/mcid } } % \end{macrocode} % \end{macro} % %\section{Commands to fill seq and prop} % With most engines these are simply copies of the expl3 commands, % but luatex will overwrite them, to store the data also in lua tables. % \begin{macro} % { % \@@_prop_new:N % ,\@@_prop_new_linked:N % ,\@@_seq_new:N % ,\@@_prop_gput:Nnn % ,\@@_seq_gput_right:Nn % ,\@@_seq_item:cn % ,\@@_prop_item:cn % ,\@@_seq_show:N % ,\@@_prop_show:N % } % \begin{macrocode} \cs_set_eq:NN \@@_prop_new:N \prop_new:N \cs_set_eq:NN \@@_prop_new_linked:N \prop_new_linked:N \cs_set_eq:NN \@@_seq_new:N \seq_new:N \cs_set_eq:NN \@@_prop_gput:Nnn \prop_gput:Nnn \cs_set_eq:NN \@@_seq_gput_right:Nn \seq_gput_right:Nn \cs_set_eq:NN \@@_seq_item:cn \seq_item:cn \cs_set_eq:NN \@@_prop_item:cn \prop_item:cn \cs_set_eq:NN \@@_seq_show:N \seq_show:N \cs_set_eq:NN \@@_prop_show:N \prop_show:N % cnx temporary needed for latex-lab-graphic code \cs_generate_variant:Nn \@@_prop_gput:Nnn { Nen , Nee, Nne , cnn, cen, cne, cno, cnx} \cs_generate_variant:Nn \@@_seq_gput_right:Nn { Ne , No, cn, ce } \cs_generate_variant:Nn \@@_prop_new:N { c } \cs_generate_variant:Nn \@@_seq_new:N { c } \cs_generate_variant:Nn \@@_seq_show:N { c } \cs_generate_variant:Nn \@@_prop_show:N { c } % % \end{macrocode} % \end{macro} % % \section{General tagging commands} % % \begin{macro}{ % \tag_stop:,\tag_start:, % \tag_stop:n,\tag_start:n} % We need commands to stop tagging in some places. % They switch local booleans and also stop the counting of paragraphs. % The commands keep track of the nesting with a local % counter. Tagging only is only restarted at the outer level, % if the current level is 1. % The commands with argument allow to give a label. This is only used % in debugging messages to allow to follow the nesting. % % \begin{variable}{\l_@@_tag_stop_int} % When stop/start pairs are nested we do not want the inner % start command to restart tagging. To control this we use a % local int: The stop command will increase it. The starting % will decrease it and only restart tagging, if it is zero. % This will replace the label version. % \begin{macrocode} %<*package|debug> %\int_new:N \l_@@_tag_stop_int % \end{macrocode} % \end{variable} % % \begin{macrocode} \cs_set_protected:Npn \tag_stop: { % \msg_note:nne {tag / debug }{tag-stop}{ \int_use:N \l_@@_tag_stop_int } \int_incr:N \l_@@_tag_stop_int \bool_set_false:N \l_@@_active_struct_bool \bool_set_false:N \l_@@_active_mc_bool \bool_set_false:N \l_@@_active_socket_bool \@@_stop_para_ints: } \cs_set_protected:Npn \tag_start: { \int_if_zero:nF { \l_@@_tag_stop_int } { \int_decr:N \l_@@_tag_stop_int } \int_if_zero:nT { \l_@@_tag_stop_int } { \bool_set_true:N \l_@@_active_struct_bool \bool_set_true:N \l_@@_active_mc_bool \bool_set_true:N \l_@@_active_socket_bool \@@_start_para_ints: } % \msg_note:nne {tag / debug }{tag-start}{ \int_use:N \l_@@_tag_stop_int } } \cs_set_eq:NN\tagstop\tag_stop: \cs_set_eq:NN\tagstart\tag_start: % \end{macrocode} % \begin{macrocode} \cs_set_protected:Npn \tag_stop:n #1 { % \msg_note:nnee {tag / debug }{tag-stop}{ \int_use:N \l_@@_tag_stop_int }{#1} \int_incr:N \l_@@_tag_stop_int \bool_set_false:N \l_@@_active_struct_bool \bool_set_false:N \l_@@_active_mc_bool \bool_set_false:N \l_@@_active_socket_bool \@@_stop_para_ints: } \cs_set_protected:Npn \tag_start:n #1 { \int_if_zero:nF { \l_@@_tag_stop_int } { \int_decr:N \l_@@_tag_stop_int } \int_if_zero:nT { \l_@@_tag_stop_int } { \bool_set_true:N \l_@@_active_struct_bool \bool_set_true:N \l_@@_active_mc_bool \bool_set_true:N \l_@@_active_socket_bool \@@_start_para_ints: } % \msg_note:nnee {tag / debug }{tag-start}{ \int_use:N \l_@@_tag_stop_int }{#1} } % %<*base> \cs_new_protected:Npn \tag_stop:{} \cs_new_protected:Npn \tag_start:{} \cs_new_protected:Npn \tagstop{} \cs_new_protected:Npn \tagstart{} \cs_new_protected:Npn \tag_stop:n #1 {} \cs_new_protected:Npn \tag_start:n #1 {} % % \end{macrocode} % \end{macro} % % % \section{Keys for tagpdfsetup} % % TODO: the log-levels must be sorted % % \begin{macro} % { % activate/mc (setup-key), % activate/tree (setup-key), % activate/struct (setup-key), % activate/all (setup-key), % activate/struct-dest (setup-key), % } % Keys to (globally) activate tagging. % |activate/spaces| activates the additional parsing needed for % interword spaces. It is defined in tagpdf-space. % |activate/struct-dest| allows to activate or suppress structure destinations. % \begin{macrocode} %<*package> \keys_define:nn { @@ / setup } { activate/mc .bool_gset:N = \g_@@_active_mc_bool, activate/tree .bool_gset:N = \g_@@_active_tree_bool, activate/struct .bool_gset:N = \g_@@_active_struct_bool, activate/all .meta:n = {activate/mc={#1},activate/tree={#1},activate/struct={#1}}, activate/all .default:n = true, activate/struct-dest .bool_gset:N = \g_@@_active_struct_dest_bool, % \end{macrocode} % old, deprecated names % \begin{macrocode} activate-mc .bool_gset:N = \g_@@_active_mc_bool, activate-tree .bool_gset:N = \g_@@_active_tree_bool, activate-struct .bool_gset:N = \g_@@_active_struct_bool, activate-all .meta:n = {activate/mc={#1},activate/tree={#1},activate/struct={#1}}, activate-all .default:n = true, no-struct-dest .bool_gset_inverse:N = \g_@@_active_struct_dest_bool, % \end{macrocode} % \end{macro} % \begin{macro}{debug/show (setup-key)} % Subkeys/values are defined in various other places. % \begin{macrocode} debug/show .choice:, % \end{macrocode} % \end{macro} % \begin{macro}{debug/log (setup-key), debug/uncompress (setup-key), log (deprecated), uncompress (deprecated)} % The |log| takes currently the values |none|, |v|, |vv|, |vvv|, |all|. % The description of the log levels is in tagpdf-checks. % \begin{macrocode} debug/log .choice:, debug/log / none .code:n = {\int_set:Nn \l_@@_loglevel_int { 0 }}, debug/log / v .code:n = { \int_set:Nn \l_@@_loglevel_int { 1 } \cs_set_protected:Nn \@@_check_typeout_v:n { \iow_term:e {##1} } }, debug/log / vv .code:n = {\int_set:Nn \l_@@_loglevel_int { 2 }}, debug/log / vvv .code:n = {\int_set:Nn \l_@@_loglevel_int { 3 }}, debug/log / all .code:n = {\int_set:Nn \l_@@_loglevel_int { 10 }}, debug/uncompress .code:n = { \pdf_uncompress: }, % \end{macrocode} % deprecated but still needed as the documentmetadata key argument uses it. % \begin{macrocode} log .meta:n = {debug/log={#1}}, uncompress .code:n = { \pdf_uncompress: }, % \end{macrocode} % \end{macro} % \begin{macro}{activate/tagunmarked (setup-key),tagunmarked (deprecated)} % This key allows to set if (in luamode) unmarked text should be % marked up as artifact. The initial value is true. % \begin{macrocode} activate/tagunmarked .bool_gset:N = \g_@@_tagunmarked_bool, activate/tagunmarked .initial:n = true, % \end{macrocode} % deprecated name % \begin{macrocode} tagunmarked .bool_gset:N = \g_@@_tagunmarked_bool, % \end{macrocode} % \end{macro} % \begin{macro}{page/tabsorder (setup-key),tabsorder (deprecated)} % This sets the tabsorder on a page. The values are |row|, |column|, |structure| (default) % or |none|. Currently this is set more or less globally. More finer control can be % added if needed. % \begin{macrocode} page/tabsorder .choice:, page/tabsorder / row .code:n = \pdfmanagement_add:nnn { Page } {Tabs}{/R}, page/tabsorder / column .code:n = \pdfmanagement_add:nnn { Page } {Tabs}{/C}, page/tabsorder / structure .code:n = \pdfmanagement_add:nnn { Page } {Tabs}{/S}, page/tabsorder / none .code:n = \pdfmanagement_remove:nn {Page} {Tabs}, page/tabsorder .initial:n = structure, % \end{macrocode} % deprecated name % \begin{macrocode} tabsorder .meta:n = {page/tabsorder={#1}}, } % \end{macrocode} % \end{macro} % \section{loading of engine/more dependent code} % \begin{macrocode} \sys_if_engine_luatex:T { \file_input:n {tagpdf-luatex.def} } % % \end{macrocode} % \begin{macrocode} %<*mcloading> \bool_if:NTF \g_@@_mode_lua_bool { \RequirePackage {tagpdf-mc-code-lua} } { \RequirePackage {tagpdf-mc-code-generic} % } % %<*debug> \bool_if:NTF \g_@@_mode_lua_bool { \RequirePackage {tagpdf-debug-lua} } { \RequirePackage {tagpdf-debug-generic} % } % % \end{macrocode} % \end{implementation} % \PrintIndex