From 1c3a11e6ef6781244703d902f924eb0c8a60135c Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Fri, 23 Dec 2022 21:05:03 +0000 Subject: tagpdf (23dec22) git-svn-id: svn://tug.org/texlive/trunk@65341 c570f23f-e606-0410-a88d-b1316a301751 --- .../source/latex/tagpdf/tagpdf-backend.dtx | 45 +- .../source/latex/tagpdf/tagpdf-checks.dtx | 70 +- .../texmf-dist/source/latex/tagpdf/tagpdf-data.dtx | 581 ++++++++ .../source/latex/tagpdf/tagpdf-mc-generic.dtx | 28 +- .../source/latex/tagpdf/tagpdf-mc-luacode.dtx | 33 +- .../source/latex/tagpdf/tagpdf-mc-shared.dtx | 4 +- .../source/latex/tagpdf/tagpdf-roles.dtx | 1455 +++++++++++++------- .../source/latex/tagpdf/tagpdf-space.dtx | 4 +- .../source/latex/tagpdf/tagpdf-struct.dtx | 207 ++- .../texmf-dist/source/latex/tagpdf/tagpdf-tree.dtx | 133 +- .../texmf-dist/source/latex/tagpdf/tagpdf-user.dtx | 17 +- Master/texmf-dist/source/latex/tagpdf/tagpdf.dtx | 57 +- Master/texmf-dist/source/latex/tagpdf/tagpdf.ins | 21 + 13 files changed, 2037 insertions(+), 618 deletions(-) create mode 100644 Master/texmf-dist/source/latex/tagpdf/tagpdf-data.dtx (limited to 'Master/texmf-dist/source/latex') diff --git a/Master/texmf-dist/source/latex/tagpdf/tagpdf-backend.dtx b/Master/texmf-dist/source/latex/tagpdf/tagpdf-backend.dtx index 800a6bfa468..47369b519b3 100644 --- a/Master/texmf-dist/source/latex/tagpdf/tagpdf-backend.dtx +++ b/Master/texmf-dist/source/latex/tagpdf/tagpdf-backend.dtx @@ -47,13 +47,13 @@ % }^^A % } % -% \date{Version 0.97, released 2022-08-24} +% \date{Version 0.98, released 2022-12-22} % \maketitle % \begin{implementation} % \begin{macrocode} %<@@=tag> %<*luatex> -\ProvidesExplFile {tagpdf-luatex.def} {2022-08-24} {0.97} +\ProvidesExplFile {tagpdf-luatex.def} {2022-12-22} {0.98} {tagpdf~driver~for~luatex} % \end{macrocode} % \section{Loading the lua} @@ -146,6 +146,7 @@ } % \end{macrocode} % \end{macro} +% % \begin{macrocode} % % \end{macrocode} @@ -157,8 +158,8 @@ local ProvidesLuaModule = { name = "tagpdf", - version = "0.97", --TAGVERSION - date = "2022-08-24", --TAGDATE + version = "0.98", --TAGVERSION + date = "2022-12-22", --TAGDATE description = "tagpdf lua code", license = "The LATEX Project Public License 1.3c" } @@ -282,6 +283,7 @@ ltx.@@.struct = ltx.@@.struct or { } -- struct data ltx.@@.tables = ltx.@@.tables or { } -- tables created with new prop and new seq. -- wasn't a so great idea ... -- g_@@_role_tags_seq used by tag<-> is in this tables! + -- used for pure lua tables too now! ltx.@@.page = ltx.@@.page or { } -- page data, currently only i->{0->mcnum,1->mcnum,...} ltx.@@.trace = ltx.@@.trace or { } -- show commands ltx.@@.func = ltx.@@.func or { } -- functions @@ -437,7 +439,28 @@ local function @@_get_mathsubtype (mathnode) end % \end{macrocode} % \end{macro} - +% +% \begin{variable}{ltx.@@.tables.role_tag_attribute,ltx.@@.tables.role_tag_attribute} +% The first is a table with key a tag and value a number (the attribute) +% The second is an array with the attribute value as key. +% \begin{macrocode} +ltx.@@.tables.role_tag_attribute = {} +ltx.@@.tables.role_attribute_tag = {} +% \end{macrocode} +% \end{variable} +% \begin{macro}{ltx.@@.func.alloctag} +% \begin{macrocode} +local @@_alloctag = + function (tag) + if not ltx.@@.tables.role_tag_attribute[tag] then + table.insert(ltx.@@.tables.role_attribute_tag,tag) + ltx.@@.tables.role_tag_attribute[tag]=#ltx.@@.tables.role_attribute_tag + @@_log ("Add "..tag.." "..ltx.@@.tables.role_tag_attribute[tag],3) + end + end +ltx.@@.func.alloctag = @@_alloctag +% \end{macrocode} +% \end{macro} % \begin{macro} % { % @@_get_num_from, @@ -451,8 +474,8 @@ end % \begin{macrocode} local @@_get_num_from = function (tag) - if ltx.@@.tables["g_@@_role_tags_prop"][tag] then - a= ltx.@@.tables["g_@@_role_tags_prop"][tag] + if ltx.@@.tables.role_tag_attribute[tag] then + a= ltx.@@.tables.role_tag_attribute[tag] else a= -1 end @@ -479,13 +502,13 @@ end % } % These functions are the opposites to the previous function: % they take as argument a number (the attribute value) and return the string |tag|. -% The first function outputs the number for lua, while the |output| function +% The first function outputs the string for lua, while the |output| function % outputs to tex. % \begin{macrocode} local @@_get_tag_from = function (num) - if ltx.@@.tables["g_@@_role_tags_seq"][num] then - a = ltx.@@.tables["g_@@_role_tags_seq"][num] + if ltx.@@.tables.role_attribute_tag[num] then + a = ltx.@@.tables.role_attribute_tag[num] else a= "UNKNOWN" end @@ -924,7 +947,7 @@ function ltx.@@.func.mark_page_elements (box,mcpagecnt,mccntprev,mcopen,name,mct elseif n.id == VLIST then -- enter the vlist mcopen,mcpagecnt,mccntprev,mctypeprev= ltx.@@.func.mark_page_elements (n,mcpagecnt,mccntprev,mcopen,"INTERNAL VLIST",mctypeprev) - elseif n.id == GLUE then -- at glue real space chars are inserted, but this has + elseif n.id == GLUE and not n.leader then -- at glue real space chars are inserted, but this has -- been done if the previous shipout wandering, so here it is ignored elseif n.id == LOCAL_PAR then -- local_par is ignored elseif n.id == PENALTY then -- penalty is ignored diff --git a/Master/texmf-dist/source/latex/tagpdf/tagpdf-checks.dtx b/Master/texmf-dist/source/latex/tagpdf/tagpdf-checks.dtx index e5ba53195fe..52113f348f2 100644 --- a/Master/texmf-dist/source/latex/tagpdf/tagpdf-checks.dtx +++ b/Master/texmf-dist/source/latex/tagpdf/tagpdf-checks.dtx @@ -48,7 +48,7 @@ % }^^A % } % -% \date{Version 0.97, released 2022-08-24} +% \date{Version 0.98, released 2022-12-22} % \maketitle % \begin{documentation} % \section{Commands} @@ -295,7 +295,7 @@ % \begin{macrocode} %<@@=tag> %<*header> -\ProvidesExplPackage {tagpdf-checks-code} {2022-08-24} {0.97} +\ProvidesExplPackage {tagpdf-checks-code} {2022-12-22} {0.98} {part of tagpdf - code related to checks, conditionals, debugging and messages} % % \end{macrocode} @@ -402,9 +402,22 @@ % Informational message shown if log-mode is high enough % \begin{macrocode} \msg_new:nnn { tag } {struct-show-closing} - { closing~structure~#1~tagged~\prop_item:cn{g_@@_struct_#1_prop}{S} } + { closing~structure~#1~tagged~\use:e{\prop_item:cn{g_@@_struct_#1_prop}{S}} } % \end{macrocode} % \end{macro} +% \begin{macro}{tree-struct-still-open} +% Message issued at the end if there are beside Root other +% open structures on the stack. +% \begin{macrocode} +\msg_new:nnn { tag } {tree-struct-still-open} + { + There~are~still~open~structures~on~the~stack!\\ + The~stack~contains~\seq_use:Nn\g_@@_struct_tag_stack_seq{,}.\\ + The~structures~are~automatically~closed,\\ + but~their~nesting~can~be~wrong. + } +% \end{macrocode} +% \end{macro} % % \subsection{Attributes} % Not much yet, as attributes aren't used so much. @@ -423,11 +436,30 @@ \msg_new:nnn { tag } {role-unknown-tag} { tag~#1~is~not~known } % \end{macrocode} % \end{macro} +% \begin{macro}{role-parent-child} +% This is info and warning message about the containment rules between child and +% parent tags. +% \begin{macrocode} +\msg_new:nnn { tag } {role-parent-child} + { The~rule~between~parent~'#1'~\\and~child~'#2'~is~#3} +% \end{macrocode} +% \end{macro} +% \begin{macro}{role-parent-child} +% This is info and warning message about the containment rules between child and +% parent tags. +% \begin{macrocode} +\msg_new:nnn { tag } {role-remapping} + { remapping~tag~to~#1 } +% \end{macrocode} +% \end{macro} % \begin{macro}{role-tag,new-tag} % Info messages. % \begin{macrocode} \msg_new:nnn { tag } {role-tag} { mapping~tag~#1~to~role~#2 } \msg_new:nnn { tag } {new-tag} { adding~new~tag~#1 } +\msg_new:nnn { tag } {read-namespace} { reading~namespace~definitions~tagpdf-ns-#1.def } +\msg_new:nnn { tag } {namespace-missing}{ namespace~definitions~tagpdf-ns-#1.def~not~found } +\msg_new:nnn { tag } {namespace-unknown}{ namespace~#1~is~not~declared } % \end{macrocode} % \end{macro} % @@ -562,7 +594,7 @@ % \begin{macrocode} \cs_new_protected:Npn \@@_check_structure_tag:N #1 { - \prop_if_in:NoF \g_@@_role_tags_prop {#1} + \prop_if_in:NoF \g_@@_role_tags_NS_prop {#1} { \msg_warning:nnx { tag } {role-unknown-tag} {#1} } @@ -618,10 +650,10 @@ { \tl_if_empty:nTF {#2} { - \msg_warning:nnn { tag } {role-missing} {#1} + \msg_error:nnn { tag } {role-missing} {#1} } { - \prop_get:NnNTF \g_@@_role_tags_prop {#2} \l_tmpa_tl + \prop_get:NnNTF \g_@@_role_tags_NS_prop {#2} \l_tmpa_tl { \int_compare:nNnT {\l_@@_loglevel_int} > { 0 } { @@ -629,13 +661,35 @@ } } { - \msg_warning:nnn { tag } {role-unknown} {#2} + \msg_error:nnn { tag } {role-unknown} {#2} + } + } + } +% \end{macrocode} +% Similar with a namespace +% \begin{macrocode} +\cs_new_protected:Npn \@@_check_add_tag_role:nnn #1 #2 #3 %#1 tag/NS, #2 role #3 namespace + { + \tl_if_empty:nTF {#2} + { + \msg_error:nnn { tag } {role-missing} {#1} + } + { + \prop_get:cnNTF { g_@@_role_NS_#3_prop } {#2} \l_tmpa_tl + { + \int_compare:nNnT {\l_@@_loglevel_int} > { 0 } + { + \msg_info:nnnn { tag } {role-tag} {#1} {#2/#3} + } + } + { + \msg_error:nnn { tag } {role-unknown} {#2/#3} } } } % \end{macrocode} % \end{macro} -% + % \subsection{Check related to mc-chunks} % % \begin{macro}{\@@_check_mc_if_nested:,\@@_check_mc_if_open:} diff --git a/Master/texmf-dist/source/latex/tagpdf/tagpdf-data.dtx b/Master/texmf-dist/source/latex/tagpdf/tagpdf-data.dtx new file mode 100644 index 00000000000..560856bf28b --- /dev/null +++ b/Master/texmf-dist/source/latex/tagpdf/tagpdf-data.dtx @@ -0,0 +1,581 @@ +% \iffalse meta-comment +% +%% File: tagpdf-data.dtx +% +% Copyright (C) 2022 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/u-fischer/tagpdf +% +% for those people who are interested. +%<*driver> +\DocumentMetadata{} +\documentclass{l3doc} +\usepackage{array,booktabs,caption} +\hypersetup{pdfauthor=Ulrike Fischer, + pdftitle=tagpdf-data module (tagpdf)} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +% +% \fi +% \title{^^A +% The \pkg{tagpdf-data} module\\ +% Data files for tag namespaces and containment rules^^A +% \\ Part of the tagpdf package +% } +% +% \author{^^A +% Ulrike Fischer\thanks +% {^^A +% E-mail: +% \href{mailto:fischer@troubleshooting-tex.de} +% {fischer@troubleshooting-tex.de}^^A +% }^^A +% } +% +% \date{Version 0.98, released 2022-12-22} +% \maketitle +% \begin{documentation} +% This files contains a various data files which are read in +% by \pkg{tagpdf} to setup name spaces and rules for tag relationships. +% +% \end{documentation} +% \begin{implementation} +% \section{The LaTeX namespace} +% This is the main new namespace. It is bound to change a lot! +% It lists the new tag, the rolemap and the namespace of the rolemap. +% \begin{macrocode} +%<*ns-latex> +%% \ProvidesExplFile {tagpdf-ns-latex.def} {2022-12-22} {0.98} +%% {latex} {https://www.latex-project.org/ns/dflt/2022}{} +title, Title, pdf2, +part, Title, pdf2, +section, H1, pdf2, +subsection, H2, pdf2, +subsubsection,H3, pdf2, +paragraph, H4, pdf2, +subparagraph, H5, pdf2, +itemize, L, pdf2, +enumerate, L, pdf2, +description, L, pdf2, +item, LI, pdf2, +itemlabel, Lbl, pdf2, +itembody, LBody, pdf2, +footnote, FENote, pdf2, +footnotemark, Lbl, pdf2, +footnotelabel,Lbl, pdf2, +% +% \end{macrocode} +% \section{The LaTeX-book namespace} +% This changes the rolemapping of some tags for heading with +% to values more suitable in book classes. +% It is bound to change +% \begin{macrocode} +%<*ns-latex-book> +%% \ProvidesExplFile {tagpdf-ns-latex-book.def} {2022-12-22} {0.98} +%% {latex-book} {https://www.latex-project.org/ns/book/2022}{} +chapter, H1,pdf2, +section, H2,pdf2, +subsection, H3,pdf2, +subsubsection, H4,pdf2, +paragraph, H5,pdf2, +subparagraph, H6,pdf2, +% +% \end{macrocode} +% \section{The LaTeX-inline namespace} +% This degrades the rolemapping of some tags. It is an experimental name space. +% It can disappear again if it doesn't look usefull. +% It is bound to change a lot! +% \begin{macrocode} +%<*ns-latex-inline> +%% \ProvidesExplFile {tagpdf-ns-latex-inline.def} {2022-12-22} {0.98} +%% {latex-inline} {https://www.latex-project.org/ns/inline/2022}{} +chapter, Span, pdf2, +section, Span, pdf2, +subsection, Span, pdf2, +subsubsection, Span, pdf2, +paragraph, Span, pdf2, +subparagraph, Span, pdf2, +P, Span, pdf2, +% +% \end{macrocode} +% \section{The pdf namespace data} +% \begin{macrocode} +%<*ns-pdf> +%% \ProvidesExplFile {tagpdf-ns-pdf.def} {2022-12-22} {0.98} +%% {pdf} {http://iso.org/pdf/ssn}{} +StructTreeRoot,,,D, +Document,,,D, +Part,,,G, +Sect,,,G, +Div,,,G, +Caption,,,GB, +NonStruct,,,G, +H,,,B, +H1,,,B, +H2,,,B, +H3,,,B, +H4,,,B, +H5,,,B, +H6,,,B, +P,,,B, +L,,,BI, +LI,,,L, +Lbl,,,I, +LBody,,,L, +Table,,,B, +TR,,,T, +TH,,,T, +TD,,,T, +THead,,,T, +TBody,,,T, +TFoot,,,T, +Span,,,I, +Link,,,GBI, +Annot,,,GBI, +Figure,,,GBI, +Formula,,,GBI, +Form,,,GBI, +Ruby,,,I, +RB,,,I, +RT,,,I, +Warichu,,,I, +WT,,,I, +WP,,,I, +Artifact,,,GBI, +Art,,,,G, % only pdf, types unclear, needs correction later +BlockQuote,,,G, %or GB? +TOC,,,G, +TOCI,,,G, +Index,,,G, +Private,,,G, +Quote,,,I, +Note,,,GBI, % I in reference, but +Reference,,,B, % +BibEntry,,,B, % +Code,,,I, % +% +% \end{macrocode} +% \section{The pdf 2.0 namespace data} +% \begin{macrocode} +%<*ns-pdf2> +%% \ProvidesExplFile {tagpdf-ns-pdf2.def} {2022-12-22} {0.98} +%% {pdf2} {http://iso.org/pdf2/ssn}{} +Document,,,D, +Part,,,G, +Sect,,,G, +Div,,,G, +Caption,,,GB, +NonStruct,,,G, +H,,,B, +H1,,,B, +H2,,,B, +H3,,,B, +H4,,,B, +H5,,,B, +H6,,,B, +P,,,B, +L,,,BI, +LI,,,L, +Lbl,,,I, +LBody,,,L, +Table,,,B, +TR,,,T, +TH,,,T, +TD,,,T, +THead,,,T, +TBody,,,T, +TFoot,,,T, +Span,,,I, +Link,,,GBI, +Annot,,,GBI, +Figure,,,GBI, +Formula,,,GBI, +Form,,,GBI, +Ruby,,,I, +RB,,,I, +RT,,,I, +Warichu,,,I, +WT,,,I, +WP,,,I, +Artifact,,,GBI, +DocumentFragment,Art, pdf,D, %rest only pdf2 +Aside, Note, pdf,G, +H7, H6, pdf,B, +H8, H6, pdf,B, +H9, H6, pdf,B, +H10, H6, pdf,B, +Title, P, pdf,GB, +FENote, Note, pdf,GBI, +Sub, Span, pdf,I, +Em, Span, pdf,I, +Strong, Span, pdf,I, +% +% \end{macrocode} +% \section{The mathml namespace data} +% \begin{macrocode} +%<*ns-mathml> +%% \ProvidesExplFile {tagpdf-ns-mathml.def} {2022-12-22} {0.98} +% {mathml}{http://www.w3.org/1998/Math/MathML}{} +abs,,, +and,,, +annotation,,, +apply,,, +approx,,, +arccos,,, +arccosh,,, +arccot,,, +arccoth,,, +arccsc,,, +arccsch,,, +arcsec,,, +arcsech,,, +arcsin,,, +arcsinh,,, +arctan,,, +arctanh,,, +arg,,, +bind,,, +bvar,,, +card,,, +cartesianproduct,,, +cbytes,,, +ceiling,,, +cerror,,, +ci,,, +cn,,, +codomain,,, +complexes,,, +compose,,, +condition,,, +conjugate,,, +cos,,, +cosh,,, +cot,,, +coth,,, +cs,,, +csc,,, +csch,,, +csymbol,,, +curl,,, +declare,,, +degree,,, +determinant,,, +diff,,, +divergence,,, +divide,,, +domain,,, +domainofapplication,,, +emptyset,,, +eq,,, +equivalent,,, +eulergamma,,, +exists,,, +exp,,, +exponentiale,,, +factorial,,, +factorof,,, +false,,, +floor,,, +fn,,, +forall,,, +gcd,,, +geq,,, +grad,,, +gt,,, +ident,,, +image,,, +imaginary,,, +imaginaryi,,, +implies,,, +in,,, +infinity,,, +int,,, +integers,,, +intersect,,, +interval,,, +inverse,,, +lambda,,, +laplacian,,, +lcm,,, +leq,,, +limit,,, +ln,,, +log,,, +logbase,,, +lowlimit,,, +lt,,, +maction,,, +maligngroup,,, +malignmark,,, +math,,, +matrix,,, +matrixrow,,, +max,,, +mean,,, +median,,, +menclose,,, +merror,,, +mfenced,,, +mfrac,,, +mglyph,,, +mi,,, +min,,, +minus,,, +mlabeledtr,,, +mlongdiv,,, +mmultiscripts,,, +mn,,, +mo,,, +mode,,, +moment,,, +momentabout,,, +mover,,, +mpadded,,, +mphantom,,, +mprescripts,,, +mroot,,, +mrow,,, +ms,,, +mscarries,,, +mscarry,,, +msgroup,,, +msline,,, +mspace,,, +msqrt,,, +msrow,,, +mstack,,, +mstyle,,, +msub,,, +msubsup,,, +msup,,, +mtable,,, +mtd,,, +mtext,,, +mtr,,, +munder,,, +munderover,,, +naturalnumbers,,, +neq,,, +none,,, +not,,, +notanumber,,, +notin,,, +notprsubset,,, +notsubset,,, +or,,, +otherwise,,, +outerproduct,,, +partialdiff,,, +pi,,, +piece,,, +piecewise,,, +plus,,, +power,,, +primes,,, +product,,, +prsubset,,, +quotient,,, +rationals,,, +real,,, +reals,,, +reln,,, +rem,,, +root,,, +scalarproduct,,, +sdev,,, +sec,,, +sech,,, +selector,,, +semantics,,, +sep,,, +set,,, +setdiff,,, +share,,, +sin,,, +sinh,,, +subset,,, +sum,,, +tan,,, +tanh,,, +tendsto,,, +times,,, +transpose,,, +true,,, +union,,, +uplimit,,, +variance,,, +vector,,, +vectorproduct,,, +xor,,, +% +% \end{macrocode} +% \section{Rule naming} +% \begin{macro}{\c_@@_role_rules_prop} +% These two properties map the rule strings to numbers and back. +% There are in tagpdf-data.dtx near the csv files for easier maintainance. +% \begin{macrocode} +%<*package> +\prop_const_from_keyval:Nn \c_@@_role_rules_prop + { + 0..n = 1, + 0..1 = 2, + 1 = 3, %StructTreeRoot, not really needed + [a] = 4, %ruby + [b] = 5, %warichu + c = 6, % WP ?? + ‡ = 7, % Part,Div,NonStruct -> "check parent" + ∅* = 8, % or negative by default? + ∅ = -1, + } +%in debug?? +\prop_const_from_keyval:Nn \c_@@_role_rules_num_prop + { + 1 = 0..n, + 2 = 0..1, + 3 = 1 , %StructTreeRoot, not really needed + 4 = [a] , %ruby + 5 = [b] , %warichu + 6 = c , % WP ?? + 7 = ‡ , % Part,Div,NonStruct -> "check parent" + 8 = ∅* , % or negative by default? + -1 = ∅ , + } +% +% \end{macrocode} +% \end{macro} +% \section{The parent-child rules for pdf <2.0} +% This csv contains the parent-child matrix for pdf <2.0. +% The values are currently the strings used in the PDF reference. +% This will perhaps change in future. +% \begin{macrocode} +%<*parent-child> +%% \ProvidesExplFile {tagpdf-parent-child.csv} {2022-12-22} {0.98} +,,,StructTreeRoot,Document,Art,Part,Div,Sect,BlockQuote,NonStruct,TOC,TOCI,Index,Private,Quote,Note,Reference,BibEntry,P,Hn,H,Lbl,Code,Span,Link,Annot,Form,Ruby,RB,RT,RP,Warichu,WT,WP,L,LI,LBody,Table,TR,TH,TD,THead,TBody,TFoot,Caption,Figure,Formula,MC +Document,both,document level,1,0..n,∅,‡,‡,∅,0..n,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅ +Art,1.7,grouping,∅,0..n,∅,‡,‡,0..n,0..n,‡,∅,∅,∅,0..n,∅,0..n,∅,∅,∅,0..1,0..1,∅,∅,∅,0..n,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,∅,∅ +Part,both,grouping,∅,0..n,0..n,‡,‡,0..n,0..n,‡,∅,∅,0..n,0..n,∅,0..n,∅,0..n,∅,∅,∅,∅,0..n,∅,∅*,∅*,∅*,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,0..n,0..n,0..n,∅ +Div,both,grouping,∅,0..n,0..n,‡,‡,0..n,0..n,‡,0..n,0..n,0..n,0..n,∅,0..n,∅,0..n,∅,∅,∅,∅,0..n,∅,0..n,0..n,0..n,∅,∅,∅,∅,∅,∅,∅,∅,0..n,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅ +Sect,both,grouping,∅,0..n,0..n,‡,‡,0..n,0..n,‡,∅,∅,0..n,0..n,∅,0..n,∅,∅,∅,0..1,0..1,∅,∅,∅,0..n,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,∅,∅ +BlockQuote,1.7,grouping?,∅,0..n,0..n,‡,‡,0..n,0..n,‡,∅,∅,∅,0..n,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅*,∅*,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,0..n,0..n,0..n,∅ +NonStruct,both,grouping,∅,0..n,0..n,‡,‡,0..n,0..n,‡,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,∅ +TOC,1.7,grouping,∅,0..n,0..n,‡,‡,0..n,0..n,‡,0..n,0..n,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅ +TOCI,1.7,TOC,∅,∅,∅,‡,‡,∅,∅,‡,0..n,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅ +Index,1.7,grouping?,∅,0..n,0..n,‡,‡,0..n,0..n,‡,∅,∅,∅,0..n,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅ +Private,1.7,grouping,∅,0..n,0..n,‡,‡,0..n,0..n,‡,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,∅,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,∅ +P,both,block,∅,0..n,0..n,‡,‡,0..n,0..n,‡,∅,0..n,0..n,0..n,∅,0..n,∅,0..n,∅,∅,∅,∅,∅,∅,∅*,∅*,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅ +Hn,both,block,∅,0..n,0..n,‡,‡,0..n,0..n,‡,∅,∅,0..n,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅*,∅*,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅ +H,both,block,∅,0..1,0..1,‡,‡,0..1,0..1,‡,∅,∅,0..n,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅*,∅*,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..1,∅,∅,0..1,0..1,∅,∅,∅,0..1,0..1,0..1,∅ +Quote,1.7,inline,∅,∅,∅,‡,‡,∅,∅,‡,∅,∅,∅,0..n,0..n,0..n,∅,∅,0..n,0..n,0..n,0..n,∅,0..n,0..n,0..n,∅,∅,0..n,0..n,0..n,∅,0..n,0..n,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅ +Note,1.7,inline,∅,0..n,0..n,‡,‡,0..n,0..n,‡,∅,∅,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅ +Reference,1.7,inline,∅,∅,∅,‡,‡,∅,0..n,‡,∅,0..n,0..n,0..n,0..n,0..n,∅,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,∅*,∅*,∅,0..n,0..n,0..n,∅,0..n,0..n,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅ +BibEntry,1.7,inline,∅,∅,∅,‡,‡,∅,∅,‡,∅,∅,∅,0..n,0..n,0..n,0..n,∅,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅ +Lbl,both,inline,∅,∅,0..n,‡,‡,0..n,0..n,‡,∅,0..n,∅,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,∅,∅,0..n,0..n,0..n,0..n,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅ +Code,1.7,inline,∅,0..n,0..n,‡,‡,0..n,0..n,‡,∅,∅,∅,0..n,0..n,0..n,∅,∅,0..n,0..n,0..n,0..n,∅,0..n,0..n,0..n,∅*,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅ +Span,both,inline,∅,∅,∅,∅,‡,∅,∅,‡,∅,∅,∅,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,∅,∅,0..n,0..n,0..n,∅,0..n,0..n,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅ +Link,both,grouping!block!inline,∅,0..n,0..n,‡,‡,0..n,0..n,‡,∅,∅,∅,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,∅,0..n,∅,∅,0..n,0..n,0..n,∅,0..n,0..n,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅ +Annot,both,grouping!block!inline,∅,0..n,0..n,‡,‡,0..n,0..n,‡,∅,∅,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,∅,∅,0..n,0..n,0..n,∅,0..n,0..n,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅ +Form,both,grouping!block!inline,∅,0..n,0..n,‡,‡,0..n,0..n,‡,∅,∅,∅,0..n,0..n,0..n,∅,∅,0..n,0..n,0..n,0..n,∅,0..n,∅*,∅*,∅,∅,0..n,0..n,0..n,∅,0..n,0..n,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅ +Ruby,both,inline,∅,∅,∅,∅,‡,∅,∅,‡,∅,∅,∅,0..n,0..n,0..n,∅,∅,0..n,0..n,0..n,0..n,∅,0..n,0..n,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅ +RB,both,inline,∅,∅,∅,∅,‡,∅,∅,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,[a],∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅ +RT,both,inline,∅,∅,∅,∅,‡,∅,∅,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,[a],∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅ +RP,both,inline,∅,∅,∅,∅,‡,∅,∅,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,[a],∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅ +Warichu,both,inline,∅,∅,∅,∅,‡,∅,∅,‡,∅,∅,∅,0..n,0..n,0..n,∅,∅,0..n,0..n,0..n,0..n,∅,0..n,0..n,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅ +WT,both,inline,∅,∅,∅,∅,‡,∅,∅,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,[b],∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅ +WP,both,inline,∅,∅,∅,∅,‡,∅,∅,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,[b],∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅ +L,both,block!inline,∅,0..n,0..n,‡,‡,0..n,0..n,‡,∅,∅,0..n,0..n,∅,0..n,∅,∅,0..n,∅,∅,∅,∅,∅,∅*,∅*,∅*,∅,∅,∅,∅,∅,∅,∅,0..n,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅ +LI,both,in L,∅,∅,∅,∅,‡,∅,∅,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅ +LBody,both,in LI,∅,∅,∅,∅,‡,∅,∅,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅ +Table,both,block,∅,0..n,0..n,‡,‡,0..n,0..n,‡,∅,∅,0..n,0..n,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅*,∅*,∅*,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅ +TR,both,Table,∅,∅,∅,∅,‡,∅,∅,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,∅,0..n,0..n,0..n,∅,∅,∅,∅ +TH,both,Table,∅,∅,∅,∅,‡,∅,∅,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅ +TD,both,Table,∅,∅,∅,∅,‡,∅,∅,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅ +THead,both,Table,∅,∅,∅,∅,‡,∅,∅,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..1,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅ +TBody,both,Table,∅,∅,∅,∅,‡,∅,∅,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅ +TFoot,both,Table,∅,∅,∅,∅,‡,∅,∅,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..1,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅ +Caption,both,grouping!block,∅,∅,0..n,‡,‡,0..n,0..1,‡,0..1,0..1,0..n,0..n,∅,∅*,∅,∅,∅,∅,∅,∅,∅,∅,∅*,∅*,0..1,∅,∅,∅,∅,∅,∅,∅,0..1,∅,0..1,0..1,∅,∅,∅,∅,∅,∅,∅,0..1,0..1,∅ +Figure,both,grouping!block!inline,∅,0..n,0..n,‡,‡,0..n,0..n,‡,∅,∅,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,∅,0..n,0..n,0..n,∅*,∅,∅,∅,∅,∅,∅,c,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅ +Formula,both,grouping!block!inline,∅,0..n,0..n,‡,‡,0..n,0..n,‡,∅,∅,0..n,0..n,0..n,0..n,∅,∅,0..n,0..n,0..n,0..n,∅,0..n,0..n,0..n,∅*,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅ +MC,both,---,∅,∅,∅,∅,∅,∅,0..n,‡,∅,∅,∅,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,‡,‡,‡,0..n,‡,‡,∅,0..n,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅ +% +% \end{macrocode} +% \section{The parent-child rules for pdf <2.0} +% This csv contains the parent-child matrix for pdf <2.0. +% The values are currently the strings used in the PDF reference. +% This will perhaps change in future. +% \begin{macrocode} +%<*parent-child-2> +%% \ProvidesExplFile {tagpdf-parent-child-2.csv} {2022-12-22} {0.98} +,,,StructTreeRoot,Document,DocumentFragment,Art,Part,Div,Sect,Aside,BlockQuote,NonStruct,TOC,TOCI,Index,Private,Title,Sub,Quote,Note,Reference,BibEntry,P,Hn,H,Lbl,Code,Em,Strong,Span,Link,Annot,Form,Ruby,RB,RT,RP,Warichu,WT,WP,FENote,L,LI,LBody,Table,TR,TH,TD,THead,TBody,TFoot,Caption,Figure,Formula,math,mathml,Artifact,MC +Document,both,document level,1,0..n,0..n,∅,‡,‡,∅,0..n,0..n,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅ +DocumentFragment,2.0,document level,∅,0..n,0..n,0..n,‡,‡,0..n,0..n,0..n,‡,∅,∅,∅,0..n,∅,∅,∅,∅*,∅,∅,∅,∅,∅,∅,∅*,∅,∅,∅,∅*,∅*,∅,∅,∅,∅,∅,∅,∅,∅,∅*,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅*,∅,∅,∅,∅,0..n,∅ +Art,1.7,grouping,∅,0..n,0..n,∅,‡,‡,0..n,0..n,0..n,‡,∅,∅,∅,0..n,∅,∅,∅,0..n,∅,∅,∅,0..1,0..1,∅,∅,∅,∅,∅,0..n,0..n,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,∅,∅,∅,0..n,∅ +Part,both,grouping,∅,0..n,0..n,0..n,‡,‡,0..n,0..n,0..n,‡,∅,∅,0..n,0..n,0..n,∅,∅,0..n,∅,0..n,∅,∅,∅,∅,0..n,∅,∅,∅,∅*,∅*,∅*,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,0..n,0..n,0..n,∅,∅,0..n,∅ +Div,both,grouping,∅,0..n,0..n,0..n,‡,‡,0..n,0..n,0..n,‡,0..n,0..n,0..n,0..n,0..n,∅,∅,0..n,∅,0..n,∅,∅,∅,∅,0..n,∅,∅,∅,0..n,0..n,0..n,∅,∅,∅,∅,∅,∅,∅,0..n,∅,0..n,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅,∅,0..n,∅ +Sect,both,grouping,∅,0..n,0..n,0..n,‡,‡,0..n,0..n,0..n,‡,∅,∅,0..n,0..n,∅,∅,∅,0..n,∅,∅,∅,0..1,0..1,∅,∅,∅,∅,∅,0..n,0..n,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,∅,∅,∅,0..n,∅ +Aside,2.0,grouping,∅,0..n,0..n,0..n,‡,‡,0..n,∅,∅,‡,∅,∅,∅,0..n,0..n,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅*,∅*,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,0..n,0..n,0..n,∅,∅,0..n,∅ +BlockQuote,1.7,grouping?,∅,0..n,0..n,0..n,‡,‡,0..n,0..n,0..n,‡,∅,∅,∅,0..n,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅*,∅*,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,0..n,0..n,0..n,∅,∅,0..n,∅ +NonStruct,both,grouping,∅,0..n,0..n,0..n,‡,‡,0..n,0..n,0..n,‡,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,∅,∅,0..n,∅ +TOC,1.7,grouping,∅,0..n,0..n,0..n,‡,‡,0..n,0..n,0..n,‡,0..n,0..n,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅ +TOCI,1.7,TOC,∅,∅,∅,∅,‡,‡,∅,∅,∅,‡,0..n,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅ +Index,1.7,grouping?,∅,0..n,0..n,0..n,‡,‡,0..n,0..n,0..n,‡,∅,∅,∅,0..n,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅,∅,0..n,∅ +Private,1.7,grouping,∅,0..n,0..n,0..n,‡,‡,0..n,0..n,0..n,‡,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,∅,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,∅,∅,0..n,∅ +P,both,block,∅,0..n,0..n,0..n,‡,‡,0..n,0..n,0..n,‡,∅,0..n,0..n,0..n,0..n,∅,∅,0..n,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅*,∅*,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅,∅,0..n,∅ +Hn,both,block,∅,0..n,0..n,0..n,‡,‡,0..n,0..n,0..n,‡,∅,∅,0..n,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅*,∅*,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅,∅,0..n,∅ +H,both,block,∅,0..1,0..1,0..1,‡,‡,0..1,0..1,0..1,‡,∅,∅,0..n,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅*,∅*,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..1,∅,∅,0..1,0..1,∅,∅,∅,0..1,0..1,0..1,∅,∅,0..1,∅ +Title,2.0,grouping!block,∅,0..n,0..n,0..n,‡,‡,0..n,∅,0..n,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅*,∅*,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅ +Sub,2.0,inline,∅,∅,∅,∅,‡,‡,∅,∅,∅,‡,∅,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,0..n,0..n,0..n,0..n,∅,0..n,0..n,0..n,0..n,0..n,∅,∅,0..n,0..n,0..n,∅,0..n,0..n,0..n,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,0..n,∅*,0..n,∅,∅,0..n,∅ +Quote,1.7,inline,∅,∅,∅,∅,‡,‡,∅,∅,∅,‡,∅,∅,∅,0..n,0..n,0..n,0..n,0..n,∅,∅,0..n,0..n,0..n,0..n,∅,0..n,0..n,0..n,0..n,0..n,∅,∅,0..n,0..n,0..n,∅,0..n,0..n,0..n,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅,∅,0..n,∅ +Note,1.7,inline,∅,0..n,0..n,0..n,‡,‡,0..n,0..n,0..n,‡,∅,∅,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅,∅,0..n,∅ +Reference,1.7,inline,∅,∅,∅,∅,‡,‡,∅,0..n,0..n,‡,∅,0..n,0..n,0..n,0..n,0..n,0..n,0..n,∅,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,∅*,∅*,∅,0..n,0..n,0..n,∅,0..n,0..n,0..n,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅,∅,0..n,∅ +BibEntry,1.7,inline,∅,∅,∅,∅,‡,‡,∅,∅,∅,‡,∅,∅,∅,0..n,0..n,0..n,0..n,0..n,0..n,∅,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅,∅,0..n,∅ +Lbl,both,inline,∅,∅,∅,0..n,‡,‡,0..n,0..n,0..n,‡,∅,0..n,∅,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,∅,∅,0..n,0..n,0..n,0..n,0..n,0..n,∅,∅,∅,∅,∅,∅,∅,0..n,∅,0..n,∅,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅,∅,0..n,∅ +Code,1.7,inline,∅,0..n,0..n,0..n,‡,‡,0..n,0..n,0..n,‡,∅,∅,∅,0..n,0..n,0..n,0..n,0..n,∅,∅,0..n,0..n,0..n,0..n,∅,0..n,0..n,0..n,0..n,0..n,∅*,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅,∅,0..n,∅ +Em,2.0,inline,∅,∅,∅,∅,∅,‡,∅,∅,∅,‡,∅,∅,∅,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,∅,∅,0..n,0..n,0..n,∅,0..n,0..n,0..n,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅,∅,0..n,∅ +Strong,2.0,inline,∅,∅,∅,∅,∅,‡,∅,∅,∅,‡,∅,∅,∅,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,∅,∅,0..n,0..n,0..n,∅,0..n,0..n,0..n,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅,∅,0..n,∅ +Span,both,inline,∅,∅,∅,∅,∅,‡,∅,∅,∅,‡,∅,∅,∅,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,∅,∅,0..n,0..n,0..n,∅,0..n,0..n,0..n,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅,∅,0..n,∅ +Link,both,grouping!block!inline,∅,0..n,0..n,0..n,‡,‡,0..n,0..n,0..n,‡,∅,∅,∅,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,∅,0..n,∅,∅,0..n,0..n,0..n,∅,0..n,0..n,0..n,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅,∅,0..n,∅ +Annot,both,grouping!block!inline,∅,0..n,0..n,0..n,‡,‡,0..n,0..n,0..n,‡,∅,∅,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,∅,∅,0..n,0..n,0..n,∅,0..n,0..n,0..n,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅,∅,0..n,∅ +Form,both,grouping!block!inline,∅,0..n,0..n,0..n,‡,‡,0..n,0..n,0..n,‡,∅,∅,∅,0..n,0..n,0..n,0..n,0..n,∅,∅,0..n,0..n,0..n,0..n,∅,0..n,0..n,0..n,∅*,∅*,∅,∅,0..n,0..n,0..n,∅,0..n,0..n,0..n,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅,∅,0..n,∅ +Ruby,both,inline,∅,∅,∅,∅,∅,‡,∅,∅,∅,‡,∅,∅,∅,0..n,0..n,0..n,0..n,0..n,∅,∅,0..n,0..n,0..n,0..n,∅,0..n,0..n,0..n,0..n,0..n,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅,∅,0..n,∅ +RB,both,inline,∅,∅,∅,∅,∅,‡,∅,∅,∅,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,[a],∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅ +RT,both,inline,∅,∅,∅,∅,∅,‡,∅,∅,∅,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,[a],∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅ +RP,both,inline,∅,∅,∅,∅,∅,‡,∅,∅,∅,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,[a],∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅ +Warichu,both,inline,∅,∅,∅,∅,∅,‡,∅,∅,∅,‡,∅,∅,∅,0..n,0..n,0..n,0..n,0..n,∅,∅,0..n,0..n,0..n,0..n,∅,0..n,0..n,0..n,0..n,0..n,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅,∅,0..n,∅ +WT,both,inline,∅,∅,∅,∅,∅,‡,∅,∅,∅,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,[b],∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅ +WP,both,inline,∅,∅,∅,∅,∅,‡,∅,∅,∅,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,[b],∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅ +FENote,2.0,grouping!block!inline,∅,0..n,0..n,0..n,‡,‡,0..n,0..n,0..n,‡,∅,∅,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,∅,0..n,0..n,0..n,0..n,0..n,0..n,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅,∅,0..n,∅ +L,both,block!inline,∅,0..n,0..n,0..n,‡,‡,0..n,0..n,0..n,‡,∅,∅,0..n,0..n,0..n,0..n,∅,0..n,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅*,∅*,∅*,∅,∅,∅,∅,∅,∅,∅,0..n,0..n,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅,∅,0..n,∅ +LI,both,in L,∅,∅,∅,∅,∅,‡,∅,∅,∅,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅ +LBody,both,in LI,∅,∅,∅,∅,∅,‡,∅,∅,∅,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅ +Table,both,block,∅,0..n,0..n,0..n,‡,‡,0..n,0..n,0..n,‡,∅,∅,0..n,0..n,0..n,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅*,∅*,∅*,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅,∅,0..n,∅ +TR,both,Table,∅,∅,∅,∅,∅,‡,∅,∅,∅,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,∅,0..n,0..n,0..n,∅,∅,∅,∅,∅,0..n,∅ +TH,both,Table,∅,∅,∅,∅,∅,‡,∅,∅,∅,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅ +TD,both,Table,∅,∅,∅,∅,∅,‡,∅,∅,∅,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅ +THead,both,Table,∅,∅,∅,∅,∅,‡,∅,∅,∅,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..1,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅ +TBody,both,Table,∅,∅,∅,∅,∅,‡,∅,∅,∅,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅ +TFoot,both,Table,∅,∅,∅,∅,∅,‡,∅,∅,∅,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..1,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅ +Caption,both,grouping!block,∅,∅,∅,0..n,‡,‡,0..n,0..1,0..1,‡,0..1,0..1,0..n,0..n,0..1,∅,∅,∅*,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅*,∅*,0..1,∅,∅,∅,∅,∅,∅,∅,∅*,0..1,∅,0..1,0..1,∅,∅,∅,∅,∅,∅,∅,0..1,0..1,∅,∅,0..n,∅ +Figure,both,grouping!block!inline,∅,0..n,0..n,0..n,‡,‡,0..n,0..n,0..n,‡,∅,∅,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,∅,0..n,0..n,0..n,0..n,0..n,∅*,∅,∅,∅,∅,∅,∅,c,0..n,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅,∅,0..n,∅ +Formula,both,grouping!block!inline,∅,0..n,0..n,0..n,‡,‡,0..n,0..n,0..n,‡,∅,∅,0..n,0..n,0..n,0..n,0..n,0..n,∅,∅,0..n,0..n,0..n,0..n,∅,0..n,0..n,0..n,0..n,0..n,∅*,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅,∅,0..n,∅ +Artifact,2.0,grouping!block!inline,∅,0..n,0..n,0..n,‡,‡,0..n,0..n,0..n,‡,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,∅,0..n,0..n,0..n,∅,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,∅,∅,0..n,∅ +math,2.0,?,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,0..n,∅ +mathml,2.0,?,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,0..n,0..n,∅ +MC,both,---,∅,∅,∅,∅,∅,∅,∅,0..n,0..n,‡,∅,∅,∅,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,0..n,‡,‡,‡,0..n,‡,‡,0..n,∅,0..n,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,0..n,∅,0..n,0..n,∅ +% +% \end{implementation} +% \PrintIndex diff --git a/Master/texmf-dist/source/latex/tagpdf/tagpdf-mc-generic.dtx b/Master/texmf-dist/source/latex/tagpdf/tagpdf-mc-generic.dtx index 42017f48366..ea460e01042 100644 --- a/Master/texmf-dist/source/latex/tagpdf/tagpdf-mc-generic.dtx +++ b/Master/texmf-dist/source/latex/tagpdf/tagpdf-mc-generic.dtx @@ -46,7 +46,7 @@ % }^^A % } % -% \date{Version 0.97, released 2022-08-24} +% \date{Version 0.98, released 2022-12-22} % \maketitle % \begin{documentation} % \end{documentation} @@ -55,11 +55,11 @@ % \begin{macrocode} %<@@=tag> %<*generic> -\ProvidesExplPackage {tagpdf-mc-code-generic} {2022-08-24} {0.97} +\ProvidesExplPackage {tagpdf-mc-code-generic} {2022-12-22} {0.98} {part of tagpdf - code related to marking chunks - generic mode} % %<*debug> -\ProvidesExplPackage {tagpdf-debug-generic} {2022-08-24} {0.97} +\ProvidesExplPackage {tagpdf-debug-generic} {2022-12-22} {0.98} {part of tagpdf - debugging code related to marking chunks - generic mode} % % \end{macrocode} @@ -683,6 +683,11 @@ \group_begin: %hm \@@_check_mc_if_nested: \bool_gset_true:N \g_@@_in_mc_bool +% \end{macrocode} +% set default MC tags to structure: +% \begin{macrocode} + \tl_set_eq:NN \l_@@_mc_key_tag_tl \g_@@_struct_tag_tl + \tl_gset_eq:NN\g_@@_mc_key_tag_tl \g_@@_struct_tag_tl \keys_set:nn { @@ / mc } {#1} \bool_if:NTF \l_@@_mc_artifact_bool { %handle artifact @@ -703,6 +708,23 @@ } \bool_if:NF \l_@@_mc_key_stash_bool { + \exp_args:NV\@@_struct_get_tag_info:nNN + \g_@@_struct_stack_current_tl + \l_@@_tmpa_tl + \l_@@_tmpb_tl + \@@_check_parent_child:VVnnN + \l_@@_tmpa_tl \l_@@_tmpb_tl + {MC}{} + \l_@@_parent_child_check_tl + \int_compare:nNnT {\l_@@_parent_child_check_tl}<{0} + { + \msg_warning:nnxxx + { tag } + {role-parent-child} + { \g_@@_struct_tag_tl/\g_@@_struct_tag_NS_tl } + { MC~(=~real content) } + { 'not~allowed'. } + } \@@_mc_handle_stash:x { \int_use:N \c@g_@@_MCID_abs_int } } } diff --git a/Master/texmf-dist/source/latex/tagpdf/tagpdf-mc-luacode.dtx b/Master/texmf-dist/source/latex/tagpdf/tagpdf-mc-luacode.dtx index fd4362227c2..ca8645e76ca 100644 --- a/Master/texmf-dist/source/latex/tagpdf/tagpdf-mc-luacode.dtx +++ b/Master/texmf-dist/source/latex/tagpdf/tagpdf-mc-luacode.dtx @@ -46,7 +46,7 @@ % }^^A % } % -% \date{Version 0.97, released 2022-08-24} +% \date{Version 0.98, released 2022-12-22} % \maketitle % \begin{implementation} % The code is splitted into three parts: code shared by all engines, @@ -86,7 +86,7 @@ % \begin{macrocode} %<@@=tag> %<*luamode> -\ProvidesExplPackage {tagpdf-mc-code-lua} {2022-08-24} {0.97} +\ProvidesExplPackage {tagpdf-mc-code-lua} {2022-12-22} {0.98} {tagpdf - mc code only for the luamode } % % \end{macrocode} @@ -182,8 +182,7 @@ % ,\@@_mc_lua_set_mc_type_attr:o % ,\@@_mc_lua_unset_mc_type_attr: % } -% This takes a tag name, and sets the attributes to the related number. -% It is not decided yet if this will be global or local, see the global-mc option. +% This takes a tag name, and sets the attributes globally to the related number. % \begin{macrocode} \cs_new:Nn \@@_mc_lua_set_mc_type_attr:n % #1 is a tag name { @@ -300,6 +299,15 @@ \bool_set_false:N\l_@@_mc_artifact_bool \tl_clear:N \l_@@_mc_key_properties_tl \int_gincr:N \c@g_@@_MCID_abs_int +% \end{macrocode} +% set the default tag to the structure: +% \begin{macrocode} + \tl_set_eq:NN \l_@@_mc_key_tag_tl \g_@@_struct_tag_tl + \tl_gset_eq:NN\g_@@_mc_key_tag_tl \g_@@_struct_tag_tl + \lua_now:e + { + ltx.@@.func.store_mc_data(\@@_get_mc_abs_cnt:,"tag","\g_@@_struct_tag_tl") + } \keys_set:nn { @@ / mc }{ label={}, #1 } %check that a tag or artifact has been used \@@_check_mc_tag:N \l_@@_mc_key_tag_tl @@ -315,6 +323,23 @@ % if not stashed record the absolute number \bool_if:NF \l_@@_mc_key_stash_bool { + \exp_args:NV\@@_struct_get_tag_info:nNN + \g_@@_struct_stack_current_tl + \l_@@_tmpa_tl + \l_@@_tmpb_tl + \@@_check_parent_child:VVnnN + \l_@@_tmpa_tl \l_@@_tmpb_tl + {MC}{} + \l_@@_parent_child_check_tl + \int_compare:nNnT {\l_@@_parent_child_check_tl}<{0} + { + \msg_warning:nnxxx + { tag } + {role-parent-child} + { \g_@@_struct_tag_tl/\g_@@_struct_tag_NS_tl } + { MC~(=~real content) } + { 'not~allowed'. } + } \@@_mc_handle_stash:x { \@@_get_mc_abs_cnt: } } } diff --git a/Master/texmf-dist/source/latex/tagpdf/tagpdf-mc-shared.dtx b/Master/texmf-dist/source/latex/tagpdf/tagpdf-mc-shared.dtx index 6ea1b355442..2e49c84725a 100644 --- a/Master/texmf-dist/source/latex/tagpdf/tagpdf-mc-shared.dtx +++ b/Master/texmf-dist/source/latex/tagpdf/tagpdf-mc-shared.dtx @@ -46,7 +46,7 @@ % }^^A % } % -% \date{Version 0.97, released 2022-08-24} +% \date{Version 0.98, released 2022-12-22} % \maketitle % \begin{documentation} % \section{Public Commands} @@ -174,7 +174,7 @@ % \begin{macrocode} %<@@=tag> %<*header> -\ProvidesExplPackage {tagpdf-mc-code-shared} {2022-08-24} {0.97} +\ProvidesExplPackage {tagpdf-mc-code-shared} {2022-12-22} {0.98} {part of tagpdf - code related to marking chunks - code shared by generic and luamode } % diff --git a/Master/texmf-dist/source/latex/tagpdf/tagpdf-roles.dtx b/Master/texmf-dist/source/latex/tagpdf/tagpdf-roles.dtx index 0b1899bf71d..b17515882eb 100644 --- a/Master/texmf-dist/source/latex/tagpdf/tagpdf-roles.dtx +++ b/Master/texmf-dist/source/latex/tagpdf/tagpdf-roles.dtx @@ -46,7 +46,7 @@ % }^^A % } % -% \date{Version 0.97, released 2022-08-24} +% \date{Version 0.98, released 2022-12-22} % \maketitle % \begin{documentation} % \begin{function} @@ -55,106 +55,222 @@ % tag (rolemap-key), % namespace (rolemap-key), % role (rolemap-key), -% role-namespace (rolemap-key) +% role-namespace (rolemap-key), % } -% This key can be used in \cs{tagpdfsetup} to declare and rolemap new tags. +% The \texttt{add-new-tag} key can be used in \cs{tagpdfsetup} to declare and rolemap new tags. % It takes as value a key-value list or a simple |new-tag/old-tag|. % % The key-value list knows the following keys: % \begin{description} -% \item[\texttt{tag}] This is the name of the new type as it should then be used in \cs{tagstructbegin}. -% \item[\texttt{namespace}] This is the namespace of the new type. +% \item[\texttt{tag}] This is the name of the new tag as it should +% then be used in \cs{tagstructbegin}. +% \item[\texttt{namespace}] This is the namespace of the new tag. % The value should be a shorthand of a namespace. -% The allowed values are currently |pdf|, |pdf2|, |mathml| and |user|. +% The allowed values are currently |pdf|, |pdf2|, |mathml|,|latex|, |latex-book| and |user|. % The default value (and recommended value for a new tag) is |user|. % The public name of the user namespace is |tag/NS/user|. This can be used to reference % the namespace e.g. in attributes. -% \item[\texttt{role}] This is the type the tag should be mapped too. -% In a PDF 1.7 or earlier this is normally a type from the |pdf| set, +% \item[\texttt{role}] This is the tag the tag should be mapped too. +% In a PDF 1.7 or earlier this is normally a tag from the |pdf| set, % in PDF 2.0 from the |pdf|, |pdf2| and |mathml| set. -% It can also be a user type, or a still unknown type. +% It can also be a user tag. The tag must be declared before, as the code retrieves +% the class of the new tag from it. % The PDF format allows mapping to be done transitively. % But tagpdf can't/won't check such unusual role mapping. -% \item[\texttt{role-namespace}] If the role is a known type -% the default value is the default namespace of this type. -% If the role is unknown, |user| is used and -% the code hopes that the type will be defined later. With this key a specific -% namespace can be forced. +% \item[\texttt{role-namespace}] If the role is a known tag +% the default value is the default namespace of this tag. +% With this key a specific namespace can be forced. % \end{description} +% +% Namespaces are mostly a PDF 2.0 property, but it doesn't harm to +% set them also in a PDF 1.7 or earlier. % \end{function} % \end{documentation} % \begin{implementation} % \begin{macrocode} %<@@=tag> %<*header> -\ProvidesExplPackage {tagpdf-roles-code} {2022-08-24} {0.97} +\ProvidesExplPackage {tagpdf-roles-code} {2022-12-22} {0.98} {part of tagpdf - code related to roles and structure names} % % \end{macrocode} % \section{Code related to roles and structure names} -% \subsection{Variables} -% Tags have both a name (a string) and a number (for the lua attribute). -% Testing a name is easier with a prop, while accessing with a number is -% better done with a seq. So both are used and must be kept in sync if a new -% tag is added. The number is only relevant for the MC type, tags with the same -% name from different names spaces can have the same number. -% \begin{variable}{\g_@@_role_tags_seq,\g_@@_role_tags_prop} % \begin{macrocode} %<*package> -\@@_seq_new:N \g_@@_role_tags_seq %to get names (type/NS) from numbers -\@@_prop_new:N \g_@@_role_tags_prop %to get numbers from names (type/NS) % \end{macrocode} -% \end{variable} -% \begin{variable}{\g_@@_role_tags_NS_prop} -% in pdf 2.0 tags belong to a name space. For every tag we store a default +% +% +% \subsection{Variables} +% Tags are used in structures (\cs{tagstructbegin}) and mc-chunks (\cs{tagmcbegin}). +% +% They have a name (a string), in lua a number (for the lua attribute), and +% in PDF 2.0 belong to one or more name spaces, with one being the default % name space. -% The keys are the tags, the value shorthands like pdf2, or mathml. +% +% Tags of structures are classified, e.g. as grouping, +% inline or block level structure (and a few special classes like lists and tables), +% and must follow containments rules depending on their classification +% (for example a inline structure can not contain +% a block level structure). New tags inherit their +% classification from their rolemapping to the standard namespaces (\texttt{pdf} +% and/or \texttt{pdf2}). +% We store this classification as it will probably +% be needed for tests but currently the data is not much used. +% The classification for math (and the containment rules) +% is unclear currently and so not set. +% +% The attribute number is only relevant in lua and only for the MC chunks +% (so tags with the same name from different names spaces can have the same number), +% and so only stored if luatex is detected. +% +% Due to the namespaces the storing and processing of tags and there data +% are different in various places for PDF~2.0 and PDF~<2.0, which makes +% things a bit difficult and leads to some duplications. Perhaps at some time +% there should be a clear split. +% +% This are the main variables used by the code: +% \begin{description} +% \item[\cs{g_@@_role_tags_NS_prop}] +% This is the core list of tag names. It uses tags as keys +% and the shorthand (e.g. pdf2, or mathml) of the default name space as value. +% +% In pdf 2.0 the value is needed in the structure dictionaries. +% +% \item[\cs{g_@@_role_tags_class_prop}] +% This contains for each tag a classification type. It is used in pdf <2.0. +% +% \item[\cs{g_@@_role_NS_prop}] This contains the names spaces. The +% values are the object references. They are used in pdf 2.0. +% +% \item[\cs{g_@@_role_rolemap_prop}] +% This contains for each tag the role to a standard tag. +% It is used in pdf<2.0 for tag checking and to fill at the end the +% RoleMap dictionary. +% +% \item[\texttt{g\_@@\_role/RoleMap\_dict}] This dictionary contains +% the standard rolemaps. It is relevant only for pdf <2.0. +% +% \item[\cs{g_@@_role_NS__prop}] This prop contains the tags of +% a name space and their role. The props are also use for +% remapping. As value they contain two brace groups: tag and namespace. +% In pdf <2.0 the namespace is empty. +% +% \item[\cs{g_@@_role_NS__class_prop}] +% This prop contains the tags of +% a name space and their type. The value is only needed for pdf 2.0. +% +% \item[\cs{g_@@_role_index_prop}] +% This prop contains the standard tags (pdf in pdf<2.0, +% pdf,pdf2 + mathml in pdf 2.0) as keys, the values are a two-digit +% number. These numbers are used to get the containment rule of two tags +% from the intarray. +% +%\item[\cs{l_@@_role_debug_prop}] This property is used to pass some info +% around for info messages or debugging. +% \end{description} +% +% +% \begin{variable}{\g_@@_role_tags_NS_prop} +% This is the core list of tag names. It uses tags as keys +% and the shorthand (e.g. pdf2, or mathml) of the default name space as value. +% We store the default name space also in pdf <2.0, even if not needed: +% it doesn't harm and simplifies the code. % There is no need to access this from lua, so we use the standard prop commands. % \begin{macrocode} -\prop_new:N \g_@@_role_tags_NS_prop %to namespace info +\prop_new:N \g_@@_role_tags_NS_prop % \end{macrocode} % \end{variable} +% +% \begin{variable}{\g_@@_role_tags_class_prop} +% With pdf 2.0 we store the class in the NS dependant props. +% With pdf <2.0 we store for now the type(s) of a tag in a common +% prop. +% Tags that are rolemapped should get the type from +% the target. +% \begin{macrocode} +\prop_new:N \g_@@_role_tags_class_prop +% \end{macrocode} +% \end{variable} +% % \begin{variable}{\g_@@_role_NS_prop} -% The standard names spaces are the following. The keys are the name -% tagpdf will use, the urls are the identifier in the namespace object. +% This holds the list of supported name spaces. +% The keys are the name tagpdf will use, the values the object reference. +% The urls identifier are stored in related dict object. % \begin{description} % \item[mathml] http://www.w3.org/1998/Math/MathML % \item[pdf2] http://iso.org/pdf2/ssn % \item[pdf] http://iso.org/pdf/ssn (default) % \item[user] \cs{c_@@_role_userNS_id_str} (random id, for user tags) +% \item[latex] https://www.latex-project.org/ns/dflt/2022 +% \item[latex-book] https://www.latex-project.org/ns/book/2022 +% \item[latex-inline] https://www.latex-project.org/ns/inline/2022 % \end{description} % More namespaces are possible and -% their objects references and the ones of the namespaces must be collected +% their objects references and their rolemaps must be collected % so that an array can be written to the StructTreeRoot at the end (see tagpdf-tree). -% We use a prop to store also the object reference as it will be needed rather +% We use a prop to store the object reference as it will be needed rather % often. % \begin{macrocode} -\prop_new:N \g_@@_role_NS_prop % collect namespaces +\prop_new:N \g_@@_role_NS_prop % \end{macrocode} % \end{variable} -% -% We need also a bunch of temporary variables: +% +% \begin{variable}{\g_@@_role_index_prop} +% This prop contains the standard tags (pdf in pdf<2.0, +% pdf,pdf2 + mathml in pdf 2.0) as keys, the values are a two-digit +% number. These numbers are used to get the containment rule of two tags +% from the intarray. +% \begin{macrocode} +\prop_new:N \g_@@_role_index_prop +% \end{macrocode} +% \end{variable} +% \begin{variable}{\l_@@_role_debug_prop} +% This variable is used to pass more infos to debug messages. +% \begin{macrocode} +\prop_new:N \l_@@_role_debug_prop +% \end{macrocode} +% \end{variable} +% We need also a bunch of temporary variables. % \begin{variable} % { -% \l_@@_role_tag_tmpa_tl +% ,\l_@@_role_tag_tmpa_tl % ,\l_@@_role_tag_namespace_tmpa_tl % ,\l_@@_role_role_tmpa_tl -% ,\l_@@_role_role_namespace_tmpa_tl +% ,\l_@@_role_role_namespace_tmpa_tl +% ,\l_@@_role_tmpa_seq % } % \begin{macrocode} \tl_new:N \l_@@_role_tag_tmpa_tl \tl_new:N \l_@@_role_tag_namespace_tmpa_tl \tl_new:N \l_@@_role_role_tmpa_tl -\tl_new:N \l_@@_role_role_namespace_tmpa_tl +\tl_new:N \l_@@_role_role_namespace_tmpa_tl +\seq_new:N\l_@@_role_tmpa_seq % \end{macrocode} % \end{variable} -% \subsection{Namesspaces} -% The following commands setups a names space. Namespace dictionaries can +% +% \subsection{Namespaces} +% The following commands setups a name space. +% With pdf version $<$2.0 this is only a prop with the +% rolemap. With pdf 2.0 a dictionary must be set up. +% Such a name space dictionaries can % contain an optional |/Schema| and |/RoleMapNS| entry. We only reserve the % objects but delay the writing to the finish code, where we can test if the -% keys and the name spaces are actually needed +% keys and the name spaces are actually needed. % This commands setups objects for the name space and its rolemap. It also -% initialize a prop to collect the rolemaps if needed. +% initialize a dict to collect the rolemaps if needed, and a property +% with the tags of the name space and their rolemapping for loops. +% It is unclear if a reference to a schema file will be ever needed, +% but it doesn't harm \ldots. +% +% \begin{variable}{g_@@_role/RoleMap_dict,\g_@@_role_rolemap_prop} +% This is the object which contains the normal RoleMap. It is probably not +% needed in pdf 2.0 but currently kept. +% \begin{macrocode} +\pdfdict_new:n {g_@@_role/RoleMap_dict} +\prop_new:N \g_@@_role_rolemap_prop +% \end{macrocode} +% \end{variable} +% % \begin{function}{\@@_role_NS_new:nnn} % \begin{syntax} % \cs{@@_role_NS_new:nnn}\Arg{shorthand}\Arg{URI-ID}{Schema} @@ -162,38 +278,51 @@ % \end{function} % \begin{macro}{\@@_role_NS_new:nnn} % \begin{macrocode} -\cs_new_protected:Npn \@@_role_NS_new:nnn #1 #2 #3 - { - \pdf_object_new:n {tag/NS/#1} - \pdfdict_new:n {g_@@_role/Namespace_#1_dict} - \pdf_object_new:n {@@/RoleMapNS/#1} - \pdfdict_new:n {g_@@_role/RoleMapNS_#1_dict} - \pdfdict_gput:nnn - {g_@@_role/Namespace_#1_dict} - {Type} - {/Namespace} - \pdf_string_from_unicode:nnN{utf8/string}{#2}\l_tmpa_str - \tl_if_empty:NF \l_tmpa_str - { - \pdfdict_gput:nnx - {g_@@_role/Namespace_#1_dict} - {NS} - {\l_tmpa_str} - } - %RoleMapNS is added in tree - \tl_if_empty:nF {#3} - { - \pdfdict_gput:nnx{g_@@_role/Namespace_#1_dict} - {Schema}{#3} - } - \prop_gput:Nnx \g_@@_role_NS_prop {#1}{\pdf_object_ref:n{tag/NS/#1}~} - } +\pdf_version_compare:NnTF < {2.0} + { + \cs_new_protected:Npn \@@_role_NS_new:nnn #1 #2 #3 + { + \prop_new:c { g_@@_role_NS_#1_prop } + \prop_new:c { g_@@_role_NS_#1_class_prop } + \prop_gput:Nnx \g_@@_role_NS_prop {#1}{} + } + } + { + \cs_new_protected:Npn \@@_role_NS_new:nnn #1 #2 #3 + { + \prop_new:c { g_@@_role_NS_#1_prop } + \prop_new:c { g_@@_role_NS_#1_class_prop } + \pdf_object_new:n {tag/NS/#1} + \pdfdict_new:n {g_@@_role/Namespace_#1_dict} + \pdf_object_new:n {@@/RoleMapNS/#1} + \pdfdict_new:n {g_@@_role/RoleMapNS_#1_dict} + \pdfdict_gput:nnn + {g_@@_role/Namespace_#1_dict} + {Type} + {/Namespace} + \pdf_string_from_unicode:nnN{utf8/string}{#2}\l_@@_tmpa_str + \tl_if_empty:NF \l_@@_tmpa_str + { + \pdfdict_gput:nnx + {g_@@_role/Namespace_#1_dict} + {NS} + {\l_@@_tmpa_str} + } + %RoleMapNS is added in tree + \tl_if_empty:nF {#3} + { + \pdfdict_gput:nnx{g_@@_role/Namespace_#1_dict} + {Schema}{#3} + } + \prop_gput:Nnx \g_@@_role_NS_prop {#1}{\pdf_object_ref:n{tag/NS/#1}~} + } + } % \end{macrocode} % \end{macro} % We need an id for the user space. For the tests it should be possible % to set it to a fix value. So we use random numbers which can % be fixed by setting a seed. We fake a sort of -% GUID but not try to be really exact as it doesn't matter ... +% GUID but do not try to be really exact as it doesn't matter ... % % \begin{variable}{\c_@@_role_userNS_id_str} % \begin{macrocode} @@ -213,423 +342,126 @@ } % \end{macrocode} % \end{variable} -% Now we setup the standard names spaces. Currently only if we detect pdf2.0 but -% this will perhaps have to change if the structure code gets to messy. +% Now we setup the standard names spaces. +% The mathml space is currently only loaded for pdf 2.0. % \begin{macrocode} -\pdf_version_compare:NnT > {1.9} - { - \@@_role_NS_new:nnn {pdf} {http://iso.org/pdf/ssn}{} - \@@_role_NS_new:nnn {pdf2} {http://iso.org/pdf2/ssn}{} +\@@_role_NS_new:nnn {pdf} {http://iso.org/pdf/ssn}{} +\@@_role_NS_new:nnn {pdf2} {http://iso.org/pdf2/ssn}{} +\pdf_version_compare:NnF < {2.0} + { \@@_role_NS_new:nnn {mathml}{http://www.w3.org/1998/Math/MathML}{} - %\@@_role_NS_new:nnn {latex} {https://www.latex-project.org/ns/2022}{} - \exp_args:Nnx - \@@_role_NS_new:nnn {user}{\c_@@_role_userNS_id_str}{} - } + } +\@@_role_NS_new:nnn {latex} {https://www.latex-project.org/ns/dflt/2022}{} +\@@_role_NS_new:nnn {latex-book} {https://www.latex-project.org/ns/book/2022}{} +\@@_role_NS_new:nnn {latex-inline} {https://www.latex-project.org/ns/inline/2022}{} +\exp_args:Nnx + \@@_role_NS_new:nnn {user}{\c_@@_role_userNS_id_str}{} % \end{macrocode} % -% \subsection{Data} -% In this section we setup the standard data. -% At first the list of structure types. We split them in three lists, -% the tags with which are both in the pdf and pdf2 namespace, -% the one only in pdf and the one with the tags only in pdf2. -% We also define a rolemap for the pdfII only type to pdf so that -% they can always be used. -% \begin{variable} -% { -% \c_@@_role_sttags_pdf_pdfII_clist, -% \c_@@_role_sttags_only_pdf_clist, -% \c_@@_role_sttags_only_pdfII_clist, -% \c_@@_role_sttags_mathml_clist, -% \c_@@_role_sttags_pdfII_to_pdf_prop -% } +% \subsection{Adding a new tag} +% Both when reading the files and when setting up a tag manually +% we have to store data in various places. +% +% \begin{macro}{\@@_role_alloctag:nnn} +% This command allocates a new tag without role mapping. In the +% lua backend it will also record the attribute value. % \begin{macrocode} -% -\clist_const:Nn \c_@@_role_sttags_pdf_pdfII_clist - { - Document, %A complete document. This is the root element - %of any structure tree containing - %multiple parts or multiple articles. - Part, %A large-scale division of a document. - Sect, %A container for grouping related content elements. - Div, %A generic block-level element or group of elements - Caption, %A brief portion of text describing a table or figure. - Index, - NonStruct, %probably not needed - H, - H1, - H2, - H3, - H4, - H5, - H6, - P, - L, %list - LI, %list item (around label and list item body) - Lbl, %list label - LBody, %list item body - Table, - TR, %table row - TH, %table header cell - TD, %table data cell - THead, %table header (n rows) - TBody, %table rows - TFoot, %table footer - Span, %generic inline marker - Link, % - Annot, - Figure, - Formula, - Form, - % ruby warichu etc .. - Ruby, - RB, - RT, - Warichu, - WT, - WP, - Artifact % only MC-tag ?... - } - -\clist_const:Nn \c_@@_role_sttags_only_pdf_clist - { - Art, %A relatively self-contained body of text - %constituting a single narrative or exposition - BlockQuote, %A portion of text consisting of one or more paragraphs - %attributed to someone other than the author of the - %surrounding text. - TOC, %A list made up of table of contents item entries - %(structure tag TOCI; see below) and/or other - %nested table of contents entries - TOCI, %An individual member of a table of contents. - %This entry's children can be any of the following structure tags: - %Lbl,Reference,NonStruct,P,TOC - Index, - Private, - Quote, %inline quote - Note, %footnote, endnote. Lbl can be child - Reference, %A citation to content elsewhere in the document. - BibEntry, %bibentry - Code - } - -\clist_const:Nn \c_@@_role_sttags_only_pdfII_clist - { - DocumentFragment - ,Aside - ,H7 - ,H8 - ,H9 - ,H10 - ,Title - ,FENote - ,Sub - ,Em - ,Strong - ,Artifact - } - -\clist_const:Nn \c_@@_role_sttags_mathml_clist - { - abs - ,and - ,annotation - ,apply - ,approx - ,arccos - ,arccosh - ,arccot - ,arccoth - ,arccsc - ,arccsch - ,arcsec - ,arcsech - ,arcsin - ,arcsinh - ,arctan - ,arctanh - ,arg - ,bind - ,bvar - ,card - ,cartesianproduct - ,cbytes - ,ceiling - ,cerror - ,ci - ,cn - ,codomain - ,complexes - ,compose - ,condition - ,conjugate - ,cos - ,cosh - ,cot - ,coth - ,cs - ,csc - ,csch - ,csymbol - ,curl - ,declare - ,degree - ,determinant - ,diff - ,divergence - ,divide - ,domain - ,domainofapplication - ,emptyset - ,eq - ,equivalent - ,eulergamma - ,exists - ,exp - ,exponentiale - ,factorial - ,factorof - ,false - ,floor - ,fn - ,forall - ,gcd - ,geq - ,grad - ,gt - ,ident - ,image - ,imaginary - ,imaginaryi - ,implies - ,in - ,infinity - ,int - ,integers - ,intersect - ,interval - ,inverse - ,lambda - ,laplacian - ,lcm - ,leq - ,limit - ,ln - ,log - ,logbase - ,lowlimit - ,lt - ,maction - ,maligngroup - ,malignmark - ,math - ,matrix - ,matrixrow - ,max - ,mean - ,median - ,menclose - ,merror - ,mfenced - ,mfrac - ,mglyph - ,mi - ,min - ,minus - ,mlabeledtr - ,mlongdiv - ,mmultiscripts - ,mn - ,mo - ,mode - ,moment - ,momentabout - ,mover - ,mpadded - ,mphantom - ,mprescripts - ,mroot - ,mrow - ,ms - ,mscarries - ,mscarry - ,msgroup - ,msline - ,mspace - ,msqrt - ,msrow - ,mstack - ,mstyle - ,msub - ,msubsup - ,msup - ,mtable - ,mtd - ,mtext - ,mtr - ,munder - ,munderover - ,naturalnumbers - ,neq - ,none - ,not - ,notanumber - ,notin - ,notprsubset - ,notsubset - ,or - ,otherwise - ,outerproduct - ,partialdiff - ,pi - ,piece - ,piecewise - ,plus - ,power - ,primes - ,product - ,prsubset - ,quotient - ,rationals - ,real - ,reals - ,reln - ,rem - ,root - ,scalarproduct - ,sdev - ,sec - ,sech - ,selector - ,semantics - ,sep - ,set - ,setdiff - ,share - ,sin - ,sinh - ,subset - ,sum - ,tan - ,tanh - ,tendsto - ,times - ,transpose - ,true - ,union - ,uplimit - ,variance - ,vector - ,vectorproduct - ,xor - } - -\prop_const_from_keyval:Nn \c_@@_role_sttags_pdfII_to_pdf_prop +\pdf_version_compare:NnTF < {2.0} { - DocumentFragment = Art, - Aside = Note, - Title = H1, - Sub = Span, - H7 = H6 , - H8 = H6 , - H9 = H6 , - H10 = H6, - FENote= Note, - Em = Span, - Strong= Span, - } -% \end{macrocode} -% \end{variable} -% We fill the structure tags in to the seq. We allow all pdf1.7 and pdf2.0, -% and role map if needed the 2.0 tags. -% \begin{macrocode} -% get tag name from number: \seq_item:Nn \g_@@_role_tags_seq { n } -% get tag number from name: \prop_item:Nn \g_@@_role_tags_prop { name } - -\clist_map_inline:Nn \c_@@_role_sttags_pdf_pdfII_clist - { - \@@_seq_gput_right:Nn \g_@@_role_tags_seq { #1 } - \prop_gput:Nnn \g_@@_role_tags_NS_prop { #1 }{ pdf2 } - } -\clist_map_inline:Nn \c_@@_role_sttags_only_pdf_clist - { - \@@_seq_gput_right:Nn \g_@@_role_tags_seq { #1 } - \prop_gput:Nnn \g_@@_role_tags_NS_prop { #1 }{ pdf } - } -\clist_map_inline:Nn \c_@@_role_sttags_only_pdfII_clist - { - \@@_seq_gput_right:Nn \g_@@_role_tags_seq { #1 } - \prop_gput:Nnn \g_@@_role_tags_NS_prop { #1 }{ pdf2 } - } -\pdf_version_compare:NnT > {1.9} - { - \clist_map_inline:Nn \c_@@_role_sttags_mathml_clist + \sys_if_engine_luatex:TF + { + \cs_new_protected:Npn \@@_role_alloctag:nnn #1 #2 #3 %#1 tagname, ns, type { - \@@_seq_gput_right:Nn \g_@@_role_tags_seq { #1 } - \prop_gput:Nnn \g_@@_role_tags_NS_prop { #1 }{ mathml } - } + \lua_now:e { ltx.@@.func.alloctag ('#1') } + \prop_gput:Nnn \g_@@_role_tags_NS_prop {#1}{#2} + \prop_gput:cnn {g_@@_role_NS_#2_prop} {#1}{{}{}} + \prop_gput:Nnn \g_@@_role_tags_class_prop {#1}{#3} + \prop_gput:cnn {g_@@_role_NS_#2_class_prop} {#1}{--UNUSED--} + } + } + { + \cs_new_protected:Npn \@@_role_alloctag:nnn #1 #2 #3 + { + \prop_gput:Nnn \g_@@_role_tags_NS_prop {#1}{#2} + \prop_gput:cnn {g_@@_role_NS_#2_prop} {#1}{{}{}} + \prop_gput:Nnn \g_@@_role_tags_class_prop {#1}{#3} + \prop_gput:cnn {g_@@_role_NS_#2_class_prop} {#1}{--UNUSED--} + } + } } -% \end{macrocode} -% For luatex and the MC we need a name/number relation. -% The name space is not relevant. -% \begin{macrocode} -\int_step_inline:nnnn { 1 }{ 1 }{ \seq_count:N \g_@@_role_tags_seq } { - \@@_prop_gput:Nxn \g_@@_role_tags_prop - { - \seq_item:Nn \g_@@_role_tags_seq { #1 } - } - { #1 } - } + \sys_if_engine_luatex:TF + { + \cs_new_protected:Npn \@@_role_alloctag:nnn #1 #2 #3 %#1 tagname, ns, type + { + \lua_now:e { ltx.@@.func.alloctag ('#1') } + \prop_gput:Nnn \g_@@_role_tags_NS_prop {#1}{#2} + \prop_gput:cnn {g_@@_role_NS_#2_prop} {#1}{{}{}} + \prop_gput:Nnn \g_@@_role_tags_class_prop {#1}{--UNUSED--} + \prop_gput:cnn {g_@@_role_NS_#2_class_prop} {#1}{#3} + } + } + { + \cs_new_protected:Npn \@@_role_alloctag:nnn #1 #2 #3 + { + \prop_gput:Nnn \g_@@_role_tags_NS_prop {#1}{#2} + \prop_gput:cnn {g_@@_role_NS_#2_prop} {#1}{{}{}} + \prop_gput:Nnn \g_@@_role_tags_class_prop {#1}{--UNUSED--} + \prop_gput:cnn {g_@@_role_NS_#2_class_prop} {#1}{#3} + } + } + } +\cs_generate_variant:Nn \@@_role_alloctag:nnn {nnV} % \end{macrocode} -% -% \subsection{Adding new tags and rolemapping} +% \end{macro} % % \subsubsection{pdf 1.7 and earlier} -% With this versions only RoleMap is filled. -% At first the dictionary: -% \begin{variable}{g_@@_role/RoleMap_dict} -% \begin{macrocode} -\pdfdict_new:n {g_@@_role/RoleMap_dict} -% \end{macrocode} -% \end{variable} +% % \begin{macro}{\@@_role_add_tag:nn} % The pdf 1.7 version has only two arguments: new and rolemap name. -% To make pdf 2.0 types usable we directly define a rolemapping for them. -% +% The role must be an existing tag and should not be empty. +% We allow to change the role of an existing tag: as the rolemap is written +% at the end not confusion can happen. % \begin{macrocode} -\cs_new_protected:Nn \@@_role_add_tag:nn %(new) name, reference to old +\cs_new_protected:Nn \@@_role_add_tag:nn % (new) name, reference to old { - \prop_if_in:NnF \g_@@_role_tags_prop {#1} +% \end{macrocode} +% checks and messages +% \begin{macrocode} + \@@_check_add_tag_role:nn {#1}{#2} + \prop_if_in:NnF \g_@@_role_tags_NS_prop {#1} { \int_compare:nNnT {\l_@@_loglevel_int} > { 0 } { \msg_info:nnn { tag }{new-tag}{#1} } - \@@_seq_gput_right:Nn \g_@@_role_tags_seq { #1 } - \@@_prop_gput:Nnx \g_@@_role_tags_prop { #1 } - { - \seq_count:N \g_@@_role_tags_seq - } - \prop_gput:Nnn \g_@@_role_tags_NS_prop { #1 }{ user } } - \@@_check_add_tag_role:nn {#1}{#2} +% \end{macrocode} +% now the addition +% \begin{macrocode} + \prop_get:NnN \g_@@_role_tags_class_prop {#2}\l_@@_tmpa_tl + \quark_if_no_value:NT \l_@@_tmpa_tl + { + \tl_set:Nn\l_@@_tmpa_tl{--UNKNOWN--} + } + \@@_role_alloctag:nnV {#1}{user}\l_@@_tmpa_tl +% \end{macrocode} +% We resolve rolemapping recursively so that all targets are stored as standard +% tags. +% \begin{macrocode} \tl_if_empty:nF { #2 } { - \pdfdict_gput:nnx {g_@@_role/RoleMap_dict} - {#1} - {\pdf_name_from_unicode_e:n{#2}} + \prop_get:NnN \g_@@_role_rolemap_prop {#2}\l_@@_tmpa_tl + \quark_if_no_value:NTF \l_@@_tmpa_tl + { + \prop_gput:Nnx \g_@@_role_rolemap_prop {#1}{\tl_to_str:n{#2}} + } + { + \prop_gput:NnV \g_@@_role_rolemap_prop {#1}\l_@@_tmpa_tl + } } } -\cs_generate_variant:Nn \@@_role_add_tag:nn {VV} - -\pdf_version_compare:NnT < {2.0} - { - \prop_map_inline:Nn \c_@@_role_sttags_pdfII_to_pdf_prop - { - \@@_role_add_tag:nn {#1}{#2} - } - } - +\cs_generate_variant:Nn \@@_role_add_tag:nn {VV,ne} % \end{macrocode} % \end{macro} % \subsubsection{The pdf 2.0 version} @@ -639,17 +471,17 @@ % \begin{macrocode} \cs_new_protected:Nn \@@_role_add_tag:nnnn %tag/namespace/role/namespace { + \@@_check_add_tag_role:nnn {#1/#2}{#3}{#4} \int_compare:nNnT {\l_@@_loglevel_int} > { 0 } { \msg_info:nnn { tag }{new-tag}{#1} } - \@@_seq_gput_right:Nn \g_@@_role_tags_seq { #1 } - \@@_prop_gput:Nnx \g_@@_role_tags_prop { #1 } - { - \seq_count:N \g_@@_role_tags_seq - } - \prop_gput:Nnn \g_@@_role_tags_NS_prop { #1 }{ #2 } - \@@_check_add_tag_role:nn {#1}{#3} + \prop_get:cnN { g_@@_role_NS_#4_class_prop } {#3}\l_@@_tmpa_tl + \quark_if_no_value:NT \l_@@_tmpa_tl + { + \tl_set:Nn\l_@@_tmpa_tl{--UNKNOWN--} + } + \@@_role_alloctag:nnV {#1}{#2}\l_@@_tmpa_tl \pdfdict_gput:nnx {g_@@_role/RoleMapNS_#2_dict}{#1} { [ @@ -658,10 +490,697 @@ \pdf_object_ref:n {tag/NS/#4} ] } +% \end{macrocode} +% We resolve rolemapping recursively so that all targets are stored as standard +% tags for the tests. +% \begin{macrocode} + \tl_if_empty:nF { #2 } + { + \prop_get:cnN { g__tag_role_NS_#4_prop } {#3}\l_@@_tmpa_tl + \quark_if_no_value:NTF \l_@@_tmpa_tl + { + \prop_gput:cnx { g__tag_role_NS_#2_prop } {#1} + {{\tl_to_str:n{#3}}{\tl_to_str:n{#4}}} + } + { + \prop_gput:cno { g__tag_role_NS_#2_prop } {#1}{\l_@@_tmpa_tl} + } + } } \cs_generate_variant:Nn \@@_role_add_tag:nnnn {VVVV} % \end{macrocode} % \end{macro} +% +% \subsection{Helper command to read the data from files} +% In this section we setup the helper command to read namespace files. + +% \begin{macro}{\@@_role_read_namespace_line:nw} +% This command will process a line in the name space file. +% The first argument is the name of the name space. +% The definition differ for pdf 2.0. as we have proper name spaces there. +% With pdf<2.0 not special name spaces shouldn't update the default role or add to the rolemap +% again. We use a boolean here. +% \begin{macrocode} +\bool_new:N\l_@@_role_update_bool +\bool_set_true:N \l_@@_role_update_bool +% \end{macrocode} +% +% \begin{macrocode} +\pdf_version_compare:NnTF < {2.0} + { + \cs_new_protected:Npn \@@_role_read_namespace_line:nw #1#2,#3,#4,#5,#6\q_stop % + % #1 NS, #2 tag, #3 rolemap, #4 NS rolemap #5 type + { + \tl_if_empty:nF { #2 } + { + \bool_if:NTF \l_@@_role_update_bool + { + \tl_if_empty:nTF {#5} + { + \prop_get:NnN \g_@@_role_tags_class_prop {#3}\l_@@_tmpa_tl + \quark_if_no_value:NT \l_@@_tmpa_tl + { + \tl_set:Nn\l_@@_tmpa_tl{--UNKNOWN--} + } + } + { + \tl_set:Nn \l_@@_tmpa_tl {#5} + } + \@@_role_alloctag:nnV {#2}{#1}\l_@@_tmpa_tl + \tl_if_empty:nF {#3} + { + \@@_role_add_tag:nn {#2}{#3} + } + \prop_gput:cnn {g_@@_role_NS_#1_prop} {#2}{{#3}{}} + } + { + \prop_gput:cnn {g_@@_role_NS_#1_prop} {#2}{{#3}{}} + \prop_gput:cnn {g_@@_role_NS_#1_class_prop} {#2}{--UNUSED--} + } + } + } + } + { + \cs_new_protected:Npn \@@_role_read_namespace_line:nw #1#2,#3,#4,#5,#6\q_stop % + % #1 NS, #2 tag, #3 rolemap, #4 NS rolemap #5 type + { + \tl_if_empty:nF {#2} + { + \tl_if_empty:nTF {#5} + { + \prop_get:cnN { g_@@_role_NS_#4_class_prop } {#3}\l_@@_tmpa_tl + \quark_if_no_value:NT \l_@@_tmpa_tl + { + \tl_set:Nn\l_@@_tmpa_tl{--UNKNOWN--} + } + } + { + \tl_set:Nn \l_@@_tmpa_tl {#5} + } + \@@_role_alloctag:nnV {#2}{#1}\l_@@_tmpa_tl + \bool_lazy_and:nnT + { ! \tl_if_empty_p:n {#3} }{! \str_if_eq_p:nn {#1}{pdf2}} + { + \@@_role_add_tag:nnnn {#2}{#1}{#3}{#4} + \prop_gput:cnn {g_@@_role_NS_#1_prop} {#2}{{#3}{#4}} + } + } + } + } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\@@_role_read_namespace:n} +% This command reads the namespace file. +% \begin{macrocode} +\cs_new_protected:Npn \@@_role_read_namespace:n #1 %name of namespace + { + \prop_if_exist:cF {g__tag_role_NS_#1_prop} + { \msg_warning:nnn {tag}{namespace-unknown}{#1} } + \file_if_exist:nTF { tagpdf-ns-#1.def} + { + \ior_open:Nn \g_tmpa_ior {tagpdf-ns-#1.def} + \msg_info:nnn {tag}{read-namespace}{#1} + \ior_map_inline:Nn \g_tmpa_ior + { + \@@_role_read_namespace_line:nw {#1} ##1,,,,\q_stop + } + \ior_close:N\g_tmpa_ior + } + { + \msg_warning:nnn{tag}{namespace-missing}{#1} + } + } + +% \end{macrocode} +% \end{macro} +% + +% +% \subsection{Reading the default data} +% The order is important as we want pdf2 and latex as default. +% \begin{macrocode} +\@@_role_read_namespace:n {pdf} +\@@_role_read_namespace:n {pdf2} +\pdf_version_compare:NnF < {2.0} + {\@@_role_read_namespace:n {mathml}} +\bool_set_false:N\l_@@_role_update_bool +\@@_role_read_namespace:n {latex-inline} +\@@_role_read_namespace:n {latex-book} +\bool_set_true:N\l_@@_role_update_bool +\@@_role_read_namespace:n {latex} +\@@_role_read_namespace:n {pdf} +\@@_role_read_namespace:n {pdf2} +% \end{macrocode} +% +% But is the class provides a \cs{chapter} command then we switch +% \begin{macrocode} +\pdf_version_compare:NnTF < {2.0} + { + \hook_gput_code:nnn {begindocument}{tagpdf} + { + \cs_if_exist:NT \chapter + { + \prop_map_inline:cn{g_@@_role_NS_latex-book_prop} + { + \@@_role_add_tag:ne {#1}{\use_i:nn #2\c_empty_tl\c_empty_tl} + } + } + } + } + { + \hook_gput_code:nnn {begindocument}{tagpdf} + { + \cs_if_exist:NT \chapter + { + \prop_map_inline:cn{g_@@_role_NS_latex-book_prop} + { + \prop_gput:Nnn \g_@@_role_tags_NS_prop { #1 }{ latex-book } + } + } + } + } +% \end{macrocode} +% \subsection{Parent-child rules} +% PDF define various rules about which tag can be a child of another tag. +% The following code implements the matrix to allow to use it in tests. +% \begin{variable}{\g_@@_role_parent_child_intarray} +% This intarray will store the rule as a number. For parent nm and child ij +% (n,m,i,j digits) the rule is at position nmij. As we have around 56 tags, +% we need roughly a size 6000. +% \begin{macrocode} +\intarray_new:Nn \g_@@_role_parent_child_intarray {6000} +% \end{macrocode} +% \end{variable} +% \begin{macro}{\c_@@_role_rules_prop,\c_@@_role_rules_num_prop} +% These two properties map the rule strings to numbers and back. +% There are in tagpdf-data.dtx near the csv files for easier maintenance. +% \end{macro} +% +% \begin{macro}{\@@_store_parent_child_rule:nnn} +% The helper command is used to store the rule. +% It assumes that parent and child are given as 2-digit number! +% \begin{macrocode} +\cs_new_protected:Npn \@@_store_parent_child_rule:nnn #1 #2 #3 % num parent, num child, #3 string + { + \intarray_gset:Nnn \g_@@_role_parent_child_intarray + { #1#2 }{0\prop_item:Nn\c_@@_role_rules_prop{#3}} + } +% \end{macrocode} +% \end{macro} +% +% \subsubsection{Reading in the csv-files} +% This counter will be used to identify the first (non-comment) line +% \begin{macrocode} +\int_zero:N \l_@@_tmpa_int +% \end{macrocode} +% Open the file depending on the PDF version +% \begin{macrocode} +\pdf_version_compare:NnTF < {2.0} + { + \ior_open:Nn \g_tmpa_ior {tagpdf-parent-child.csv} + } + { + \ior_open:Nn \g_tmpa_ior {tagpdf-parent-child-2.csv} + } +% \end{macrocode} + +% Now the main loop over the file +% \begin{macrocode} +\ior_map_inline:Nn \g_tmpa_ior + { +% \end{macrocode} +% ignore lines containing only comments +% \begin{macrocode} + \tl_if_empty:nF{#1} + { +% \end{macrocode} +% count the lines ... +% \begin{macrocode} + \int_incr:N\l_@@_tmpa_int +% \end{macrocode} +% put the line into a seq. Attention! empty cells are dropped. +% \begin{macrocode} + \seq_set_from_clist:Nn\l_@@_tmpa_seq { #1 } + \int_compare:nNnTF {\l_@@_tmpa_int}=1 +% \end{macrocode} +% This handles the header line. It gives the tags 2-digit numbers +% \begin{macrocode} + { + \seq_map_indexed_inline:Nn \l_@@_tmpa_seq + { + \prop_gput:Nnx\g_@@_role_index_prop + {##2} + {\int_compare:nNnT{##1}<{10}{0}##1} + } + } +% \end{macrocode} +% now the data lines. +% \begin{macrocode} + { + \seq_set_from_clist:Nn\l_@@_tmpa_seq { #1 } +% \end{macrocode} +% get the name of the child tag from the first column +% \begin{macrocode} + \seq_pop_left:NN\l_@@_tmpa_seq\l_@@_tmpa_tl +% \end{macrocode} +% get the number of the child, and store it in \cs{l_@@_tmpb_tl} +% \begin{macrocode} + \prop_get:NVN \g_@@_role_index_prop \l_@@_tmpa_tl \l_@@_tmpb_tl +% \end{macrocode} +% remove column 2+3 +% \begin{macrocode} + \seq_pop_left:NN\l_@@_tmpa_seq\l_@@_tmpa_tl + \seq_pop_left:NN\l_@@_tmpa_seq\l_@@_tmpa_tl +% \end{macrocode} +% Now map over the rest. The index \verb+##1+ gives us the +% number of the parent, \verb+##2+ is the data. +% \begin{macrocode} + \seq_map_indexed_inline:Nn \l_@@_tmpa_seq + { + \exp_args:Nnx + \@@_store_parent_child_rule:nnn {##1}{\l_@@_tmpb_tl}{ ##2 } + } + } + } + } +% \end{macrocode} +% close the read handle. +% \begin{macrocode} +\ior_close:N\g_tmpa_ior +% \end{macrocode} +% The Root, +% Hn and mathml tags are special and need to be added explicitly +% \begin{macrocode} +\prop_get:NnN\g_@@_role_index_prop{StructTreeRoot}\l_@@_tmpa_tl +\prop_gput:Nnx\g_@@_role_index_prop{Root}{\l_@@_tmpa_tl} +\prop_get:NnN\g_@@_role_index_prop{Hn}\l_@@_tmpa_tl +\pdf_version_compare:NnTF < {2.0} + { + \int_step_inline:nn{6} + { + \prop_gput:Nnx\g_@@_role_index_prop{H#1}{\l_@@_tmpa_tl} + } + } + { + \int_step_inline:nn{10} + { + \prop_gput:Nnx\g_@@_role_index_prop{H#1}{\l_@@_tmpa_tl} + } +% \end{macrocode} +% all mathml tags are currently handled identically +% \begin{macrocode} + \prop_get:NnN\g_@@_role_index_prop {mathml}\l_@@_tmpa_tl + \prop_get:NnN\g_@@_role_index_prop {math}\l_@@_tmpb_tl + \prop_map_inline:Nn \g_@@_role_NS_mathml_prop + { + \prop_gput:NnV\g_@@_role_index_prop{#1}\l_@@_tmpa_tl + } + \prop_gput:NnV\g_@@_role_index_prop{math}\l_@@_tmpb_tl + } +% \end{macrocode} +% +% \subsubsection{Retrieving the parent-child rule} +% +% \begin{macro}{\l_@@_role_real_parent_tl} +% Part, Div and NonStruct have no own rules, instead +% the parent(s) have to be inspected. To store this real parent +% we use this tlvar +% \begin{macrocode} +\tl_new:N \l_@@_role_real_parent_tl +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_role_get_parent_child_rule:nnN} +% This command retrieves the rule (as a number) and stores it in the tl-var. +% TODO check temporary variables. Check if the tl-var should be fix. +% The arguments should be standard tags for which a rule exist and +% role mapping should have already be done. +% \begin{macrocode} +\tl_new:N \l_@@_parent_child_check_tl +\cs_new_protected:Npn \@@_role_get_parent_child_rule:nnN #1 #2 #3 + % #1 parent (string) #2 child (string) #3 tl for state + { + \tl_set:Nn \l_@@_role_real_parent_tl {#1} +% \end{macrocode} +% +% \begin{macrocode} + \prop_get:NnN \g_@@_role_index_prop{#1}\l_@@_tmpa_tl + \prop_get:NnN \g_@@_role_index_prop{#2}\l_@@_tmpb_tl + \bool_lazy_and:nnTF + { ! \quark_if_no_value_p:N \l_@@_tmpa_tl } + { ! \quark_if_no_value_p:N \l_@@_tmpb_tl } + { +% \end{macrocode} +% Get the rule from the intarray +% \begin{macrocode} + \tl_set:Nx#3 + { + \intarray_item:Nn + \g_@@_role_parent_child_intarray + {\l_@@_tmpa_tl\l_@@_tmpb_tl} + } +% \end{macrocode} +% If the state is ‡ we have to check the parents from the stack and +% use the first which is not Part, Div or NonStruct +% \begin{macrocode} + \int_compare:nNnT + {#3} = {\prop_item:Nn\c_@@_role_rules_prop{‡}} + { + \seq_set_eq:NN \l_@@_role_tmpa_seq \g_@@_struct_tag_stack_seq +% \end{macrocode} +% we must take the current child from the stack if is already there, +% depending on location the check is called, this could also remove the +% parent, but that is ok too. +% \begin{macrocode} + \seq_pop_left:NN \l_@@_role_tmpa_seq\l_@@_get_tmpc_tl + \seq_map_inline:Nn\l_@@_role_tmpa_seq + { + \tl_if_in:nnF {-Part-Div-NonStruct-}{-##1-} + { + \tl_set:Nn\l_@@_role_real_parent_tl {##1} + \int_zero:N\l_@@_tmpa_int + \@@_role_get_parent_child_rule:nnN {##1}{#2}#3 + \int_set:Nn\l_@@_tmpa_int{1} + \seq_map_break: + } + } + } +% \end{macrocode} +% This is the message, this can perhaps go into debug mode. +% \begin{macrocode} + \group_begin: + \int_compare:nNnT {\l_@@_tmpa_int*\l_@@_loglevel_int} > { 0 } + { + \prop_get:NVNF\c_@@_role_rules_num_prop #3 \l_@@_tmpa_tl + { + \tl_set:Nn \l_@@_tmpa_tl {unknown} + } + \tl_set:Nn \l_@@_tmpb_tl {#1} + \msg_note:nnxxx + { tag } + { role-parent-child } + { #1 + \tl_if_eq:NNTF\l_@@_tmpb_tl\l_@@_role_real_parent_tl + { + \bool_lazy_and:nnT + { + \prop_if_in_p:Nn \l_@@_role_debug_prop {parent} + } + { + !\str_if_eq_p:ee {#1}{\prop_item:Nn\l_@@_role_debug_prop {parent}} + } + { + \c_space_tl (from~\prop_item:Nn\l_@@_role_debug_prop {parent}) + } + } + { + \c_space_tl(inherited~from~\l_@@_role_real_parent_tl) + } + } + { + #2 + \bool_lazy_and:nnT + { + \prop_if_in_p:Nn \l_@@_role_debug_prop {child} + } + { + !\str_if_eq_p:ee {#2}{\prop_item:Nn\l_@@_role_debug_prop {child}} + } + { + \c_space_tl (from~\prop_item:Nn\l_@@_role_debug_prop {child}) + } + } + { '#3~(\l_@@_tmpa_tl)' } + } + \group_end: + } + { + \tl_set:Nn#3 {0} + \msg_warning:nnxxx + { tag } + {role-parent-child} + { #1 } + { #2 } + { unknown! } + } + } +\cs_generate_variant:Nn\@@_role_get_parent_child_rule:nnN {VVN} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{@@_check_parent_child:nnnnN} +% This is the main command. +% It has to retrieve the standard tags for a comparison. +% In pdf 2.0 the name spaces of the tags are relevant, so we +% have arguments for them, but in pdf <2.0 they are ignored and can +% be left empty. +% \begin{macrocode} +\pdf_version_compare:NnTF < {2.0} + { + \cs_new_protected:Npn \@@_check_parent_child:nnnnN #1 #2 #3 #4 #5 + { +% \end{macrocode} +% for debugging messages we store the arguments. +% \begin{macrocode} + \prop_put:Nnn \l_@@_role_debug_prop {parent} {#1} + \prop_put:Nnn \l_@@_role_debug_prop {child} {#3} +% \end{macrocode} +% get the standard tags through rolemapping if needed +% at first the parent +% \begin{macrocode} + \prop_get:NnNTF \g_@@_role_index_prop {#1}\l_@@_tmpa_tl + { + \tl_set:Nn \l_@@_tmpa_tl {#1} + } + { + \prop_get:NnNF \g_@@_role_rolemap_prop {#1}\l_@@_tmpa_tl + { + \tl_set:Nn \l_@@_tmpa_tl {\q_no_value} + } + } +% \end{macrocode} +% now the child +% \begin{macrocode} + \prop_get:NnNTF \g_@@_role_index_prop {#3}\l_@@_tmpb_tl + { + \tl_set:Nn \l_@@_tmpb_tl {#3} + } + { + \prop_get:NnNF \g_@@_role_rolemap_prop {#3}\l_@@_tmpb_tl + { + \tl_set:Nn \l_@@_tmpb_tl {\q_no_value} + } + } +% \end{macrocode} +% if we got tags for parent and child we call the checking command +% \begin{macrocode} + \bool_lazy_and:nnTF + { ! \quark_if_no_value_p:N \l_@@_tmpa_tl } + { ! \quark_if_no_value_p:N \l_@@_tmpb_tl } + { + \@@_role_get_parent_child_rule:VVN \l_@@_tmpa_tl \l_@@_tmpb_tl #5 + } + { + \tl_set:Nn #5 {0} + \msg_warning:nnxxx + { tag } + {role-parent-child} + { #1 } + { #3 } + { unknown! } + } + } + \cs_new_protected:Npn \@@_check_parent_child:nnN #1#2#3 + { + \@@_check_parent_child:nnnnN {#1}{}{#2}{}#3 + } + } +% \end{macrocode} +% and now the pdf 2.0 version +% The version with three arguments retrieves the default +% names space and then calls the full command. +% Not sure if this will ever be needed but we leave it for now. +% \begin{macrocode} + { + \cs_new_protected:Npn \@@_check_parent_child:nnN #1 #2 #3 + { + \prop_get:NnN\g_@@_role_tags_NS_prop {#1}\l_@@_role_tag_namespace_tmpa_tl + \prop_get:NnN\g_@@_role_tags_NS_prop {#2}\l_@@_role_tag_namespace_tmpb_tl + \str_if_eq:nnT{#2}{MC}{\tl_clear:N \l_@@_role_tag_namespace_tmpb_tl} + \bool_lazy_and:nnTF + { ! \quark_if_no_value_p:N \l_@@_role_tag_namespace_tmpa_tl } + { ! \quark_if_no_value_p:N \l_@@_role_tag_namespace_tmpb_tl } + { + \@@_check_parent_child:nVnVN + {#1}\l_@@_role_tag_namespace_tmpa_tl + {#2}\l_@@_role_tag_namespace_tmpb_tl + #3 + } + { + \tl_set:Nn #3 {0} + \msg_warning:nnxxx + { tag } + {role-parent-child} + { #1 } + { #2 } + { unknown! } + } + } +% \end{macrocode} +% and now the real command. +% \begin{macrocode} + \cs_new_protected:Npn \@@_check_parent_child:nnnnN #1 #2 #3 #4 #5 %tag,NS,tag,NS, tl var + { + \prop_put:Nnn \l_@@_role_debug_prop {parent} {#1/#2} + \prop_put:Nnn \l_@@_role_debug_prop {child} {#3/#4} +% \end{macrocode} +% If the namespace is empty, we assume a standard tag, +% otherwise we retrieve the rolemapping from the namespace +% \begin{macrocode} + \tl_if_empty:nTF {#2} + { + \tl_set:Nn \l_@@_tmpa_tl {#1} + } + { + \prop_get:cnNTF + { g_@@_role_NS_#2_prop } + {#1} + \l_@@_tmpa_tl + { + \tl_set:Nx \l_@@_tmpa_tl {\tl_head:N\l_@@_tmpa_tl} + \tl_if_empty:NT\l_@@_tmpa_tl + { + \tl_set:Nn \l_@@_tmpa_tl {#1} + } + } + { + \tl_set:Nn \l_@@_tmpa_tl {\q_no_value} + } + } +% \end{macrocode} +% and the same for the child +% If the namespace is empty, we assume a standard tag, +% otherwise we retrieve the rolemapping from the namespace +% \begin{macrocode} + \tl_if_empty:nTF {#4} + { + \tl_set:Nn \l_@@_tmpb_tl {#3} + } + { + \prop_get:cnNTF + { g_@@_role_NS_#4_prop } + {#3} + \l_@@_tmpb_tl + { + \tl_set:Nx \l_@@_tmpb_tl { \tl_head:N\l_@@_tmpb_tl } + \tl_if_empty:NT\l_@@_tmpb_tl + { + \tl_set:Nn \l_@@_tmpb_tl {#3} + } + } + { + \tl_set:Nn \l_@@_tmpb_tl {\q_no_value} + } + } +% \end{macrocode} +% and now get the relation +% \begin{macrocode} + \bool_lazy_and:nnTF + { ! \quark_if_no_value_p:N \l_@@_tmpa_tl } + { ! \quark_if_no_value_p:N \l_@@_tmpb_tl } + { + \@@_role_get_parent_child_rule:VVN \l_@@_tmpa_tl \l_@@_tmpb_tl #5 + } + { + \tl_set:Nn #5 {0} + \msg_warning:nnxxx + { tag } + {role-parent-child} + { #1 } + { #3 } + { unknown! } + } + } + } +\cs_generate_variant:Nn\@@_check_parent_child:nnN {VVN} +\cs_generate_variant:Nn\@@_check_parent_child:nnnnN {VVVVN,nVnVN,VVnnN} +% \end{macrocode} +% \end{macro} +% +% \subsection{Remapping of tags} +% In some context it can be necessary to remap or replace the tags. +% That means instead of tag=H1 or tag=section one wants the effect of tag=Span. +% Or instead of tag=P one wants tag=Code. +% +% The following command provide some general interface for this. +% The core idea is that before a tag is set it is fed through a function +% that can change it. We want to be able to chain such functions, +% so all of them manipulate the same variables. +% +% \begin{variable}{\l_@@_role_remap_tag_tl,\l_@@_role_remap_NS_tl} +% \begin{macrocode} +\tl_new:N \l_@@_role_remap_tag_tl +\tl_new:N \l_@@_role_remap_NS_tl +% \end{macrocode} +% \end{variable} +% \begin{macro}{\@@_role_remap:} +% This function is used in the structure and the mc code before using a tag. By default it +% does nothing with the tl vars. Perhaps this should be a hook? +% \begin{macrocode} +\cs_new_protected:Npn \@@_role_remap: { } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_role_remap_id: } +% This is copy in case we have to restore the main command. +% \begin{macrocode} +\cs_set_eq:NN \@@_role_remap_id: \@@_role_remap: +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_role_remap_inline:} +% The mapping is meant to \enquote{degrade} tags, e.g. if used +% inside some complex object. +% The pdf<2.0 code maps the tag to the new role, the pdf 2.0 code only +% switch the NS. +% \begin{macrocode} +\pdf_version_compare:NnTF < {2.0} + { + \cs_new_protected:Npn \@@_role_remap_inline: + { + \prop_get:cVNT { g__tag_role_NS_latex-inline_prop }\l_@@_role_remap_tag_tl\l_@@_tmpa_tl + { + \tl_set:Nx\l_@@_role_remap_tag_tl + { + \exp_last_unbraced:NV\use_i:nn \l_@@_tmpa_tl + } + \tl_set:Nx\l_@@_role_remap_NS_tl + { + \exp_last_unbraced:NV\use_ii:nn \l_@@_tmpa_tl + } + } + \int_compare:nNnT {\l_@@_loglevel_int} > { 0 } + { + \msg_note:nnx { tag } { role-remapping }{ \l_@@_role_remap_tag_tl } + } + } + } + { + \cs_new_protected:Npn \@@_role_remap_inline: + { + \prop_get:cVNT { g__tag_role_NS_latex-inline_prop }\l_@@_role_remap_tag_tl\l_@@_tmpa_tl + { + \tl_set:Nn\l_@@_role_remap_NS_tl {latex-inline} + } + \int_compare:nNnT {\l_@@_loglevel_int} > { 0 } + { + \msg_note:nnx { tag } { role-remapping }{ \l_@@_role_remap_tag_tl/latex-inline } + } + } + } +% \end{macrocode} +% \end{macro} +% % \subsection{Key-val user interface} % The user interface uses the key |add-new-tag|, which takes either a % keyval list as argument, or a tag/role. diff --git a/Master/texmf-dist/source/latex/tagpdf/tagpdf-space.dtx b/Master/texmf-dist/source/latex/tagpdf/tagpdf-space.dtx index 20f189f8a54..ad5e17ff5b1 100644 --- a/Master/texmf-dist/source/latex/tagpdf/tagpdf-space.dtx +++ b/Master/texmf-dist/source/latex/tagpdf/tagpdf-space.dtx @@ -46,7 +46,7 @@ % }^^A % } % -% \date{Version 0.97, released 2022-08-24} +% \date{Version 0.98, released 2022-12-22} % \maketitle % \begin{documentation} % \begin{function}{interwordspace (setup-key)} @@ -64,7 +64,7 @@ % \begin{macrocode} %<@@=tag> %<*header> -\ProvidesExplPackage {tagpdf-space-code} {2022-08-24} {0.97} +\ProvidesExplPackage {tagpdf-space-code} {2022-12-22} {0.98} {part of tagpdf - code related to real space chars} % % \end{macrocode} diff --git a/Master/texmf-dist/source/latex/tagpdf/tagpdf-struct.dtx b/Master/texmf-dist/source/latex/tagpdf/tagpdf-struct.dtx index dd85e47277b..6f6d60ba4b9 100644 --- a/Master/texmf-dist/source/latex/tagpdf/tagpdf-struct.dtx +++ b/Master/texmf-dist/source/latex/tagpdf/tagpdf-struct.dtx @@ -46,7 +46,7 @@ % }^^A % } % -% \date{Version 0.97, released 2022-08-24} +% \date{Version 0.98, released 2022-12-22} % \maketitle % \begin{documentation} % \section{Public Commands} @@ -242,7 +242,7 @@ % \begin{macrocode} %<@@=tag> %<*header> -\ProvidesExplPackage {tagpdf-struct-code} {2022-08-24} {0.97} +\ProvidesExplPackage {tagpdf-struct-code} {2022-12-22} {0.98} {part of tagpdf - code related to storing structure} % % \end{macrocode} @@ -298,6 +298,14 @@ % \end{macrocode} % \end{variable} % +% \begin{variable}{\g_@@_struct_tag_NS_prop} +% For the parent-child check, we need the tag and NS of every structure +% \begin{macrocode} +\prop_new:N\g_@@_struct_tag_NS_prop +% \end{macrocode} +% \end{variable} +% +% % \begin{variable}{\g_@@_struct_stack_current_tl,\l_@@_struct_stack_parent_tmpa_tl} % The global variable will hold the current structure number. It is already % defined in \texttt{tagpdf-base}. @@ -399,6 +407,28 @@ \bool_new:N \l_@@_struct_elem_stash_bool % \end{macrocode} % \end{variable} +% +% \subsection{Variables used by tagging code of basic elements} +% +% \begin{variable}{\g_@@_struct_dest_num_prop} +% This variable records for (some or all, not clear yet) +% destination names the related structure number to allow +% to reference them in a Ref. The key is the destination. +% It is currently used by the toc-tagging and sec-tagging code. +% \begin{macrocode} +\prop_new:N \g_@@_struct_dest_num_prop +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\g_@@_struct_ref_by_dest_prop} +% This variable contains structures whose Ref key should be updated +% at the end to point to structured related with this destination. +% As this is probably need in other places too, it is not only a toc-variable. +% \begin{macrocode} +\prop_new:N \g_@@_struct_ref_by_dest_prop +% \end{macrocode} +% \end{variable} +% % \section{Commands} % % The properties must be in some places handled expandably. @@ -442,7 +472,11 @@ % \begin{macrocode} \tl_gset:Nn \g_@@_struct_stack_current_tl {0} % \end{macrocode} - +% \begin{macro}{\@@_pdf_name_e:n} +% \begin{macrocode} +\cs_new:Npn \@@_pdf_name_e:n #1{\pdf_name_from_unicode_e:n{#1}} +% \end{macrocode} +% \end{macro} % % \begin{variable}{g_@@_struct_0_prop,g_@@_struct_kids_0_seq} % \begin{macrocode} @@ -450,13 +484,17 @@ \@@_new_output_prop_handler:n {0} \@@_seq_new:c { g_@@_struct_kids_0_seq } -\@@_prop_gput:cnn +\@@_prop_gput:cnx { g_@@_struct_0_prop } { Type } - { /StructTreeRoot } - + { \pdf_name_from_unicode_e:n {StructTreeRoot} } +\@@_prop_gput:cnx + { g_@@_struct_0_prop } + { S } + { \pdf_name_from_unicode_e:n {StructTreeRoot} } +\prop_gput:Nnn \g_@@_struct_tag_NS_prop {0}{{StructTreeRoot}{pdf}} % \end{macrocode} % Namespaces are pdf 2.0 but it doesn't harm % to have an empty entry. We could add a test, but if the code moves into @@ -468,6 +506,65 @@ { \pdf_object_ref:n { @@/tree/namespaces } } % \end{macrocode} % \end{variable} +% +% \subsection{Filling in the tag info} + +% \begin{macro}{\@@_struct_set_tag_info:nnn } +% This adds or updates the tag info to a structure given by a number. +% We need also the original data, so we store both. +% \begin{macrocode} +\pdf_version_compare:NnTF < {2.0} + { + \cs_new_protected:Npn \@@_struct_set_tag_info:nnn #1 #2 #3 + %#1 structure number, #2 tag, #3 NS + { + \@@_prop_gput:cnx + { g_@@_struct_#1_prop } + { S } + { \pdf_name_from_unicode_e:n {#2} } % + \prop_gput:Nnn \g_@@_struct_tag_NS_prop {#1}{{#2}{#3}} + } + } + { + \cs_new_protected:Npn \@@_struct_set_tag_info:nnn #1 #2 #3 + { + \@@_prop_gput:cnx + { g_@@_struct_#1_prop } + { S } + { \pdf_name_from_unicode_e:n {#2} } % + \prop_get:NnNT \g_@@_role_NS_prop {#3} \l_@@_get_tmpc_tl + { + \@@_prop_gput:cnx + { g_@@_struct_#1_prop } + { NS } + { \l_@@_get_tmpc_tl } % + } + \prop_gput:Nnn \g_@@_struct_tag_NS_prop {#1}{{#2}{#3}} + } + } +\cs_generate_variant:Nn \@@_struct_set_tag_info:nnn {eVV} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\cc} +% We also need a way to get the tag info back from parent structures. +% \begin{macrocode} +\cs_new_protected:Npn \@@_struct_get_tag_info:nNN #1 #2 #3 + %#1 struct num, #2 tlvar for tag , #3 tlvar for NS + { + \prop_get:NnNTF \g_@@_struct_tag_NS_prop {#1}\l_@@_get_tmpc_tl + { + \tl_set:Nx #2{\exp_last_unbraced:NV\use_i:nn \l_@@_get_tmpc_tl} + \tl_set:Nx #3{\exp_last_unbraced:NV\use_ii:nn \l_@@_get_tmpc_tl} + } + { + \tl_clear:N#2 + \tl_clear:N#3 + } + } +\cs_generate_variant:Nn\@@_struct_get_tag_info:nNN {eNN} +% \end{macrocode} +% \end{macro} % \subsection{Handlings kids} % Commands to store the kids. Kids in a structure can be a reference to a mc-chunk, % an object reference to another structure element, or a object reference to an @@ -857,21 +954,10 @@ parent .default:n = {-1}, tag .code:n = % S property { - \seq_set_split:Nne \l_@@_tmpa_seq { / } {#1/\prop_item:No\g__tag_role_tags_NS_prop{#1}} - \tl_gset:Nx \g_@@_struct_tag_tl { \seq_item:Nn\l_@@_tmpa_seq {1} } - \tl_gset:Nx \g_@@_struct_tag_NS_tl { \seq_item:Nn\l_@@_tmpa_seq {2} } + \seq_set_split:Nne \l_@@_tmpa_seq { / } {#1/\prop_item:Ne\g__tag_role_tags_NS_prop{#1}} + \tl_gset:Nx \g_@@_struct_tag_tl { \seq_item:Nn\l_@@_tmpa_seq {1} } + \tl_gset:Nx \g_@@_struct_tag_NS_tl{ \seq_item:Nn\l_@@_tmpa_seq {2} } \@@_check_structure_tag:N \g_@@_struct_tag_tl - \@@_prop_gput:cnx - { g_@@_struct_\int_eval:n {\c@g_@@_struct_abs_int}_prop } - { S } - { \pdf_name_from_unicode_e:n{ \g_@@_struct_tag_tl} } % - \prop_get:NVNT \g_@@_role_NS_prop\g_@@_struct_tag_NS_tl\l_@@_tmpa_tl - { - \@@_prop_gput:cnx - { g_@@_struct_\int_eval:n {\c@g_@@_struct_abs_int}_prop } - { NS } - { \l_@@_tmpa_tl } % - } }, title .code:n = % T property { @@ -1114,7 +1200,13 @@ { /StructElem } \tl_set:Nn \l_@@_struct_stack_parent_tmpa_tl {-1} \keys_set:nn { @@ / struct} { #1 } - \@@_check_structure_has_tag:n { \int_eval:n {\c@g_@@_struct_abs_int} } +% \end{macrocode} +% \begin{macrocode} + \@@_struct_set_tag_info:eVV + { \int_eval:n {\c@g_@@_struct_abs_int} } + \g_@@_struct_tag_tl + \g_@@_struct_tag_NS_tl + \@@_check_structure_has_tag:n { \int_eval:n {\c@g_@@_struct_abs_int} } \tl_if_empty:NF \l_@@_struct_key_label_tl { @@ -1139,7 +1231,43 @@ %\seq_show:N \g_@@_struct_stack_seq \bool_if:NF \l_@@_struct_elem_stash_bool - {%set the parent + { +% \end{macrocode} +% check if the tag can be used inside the parent. It only makes sense, +% if the structure is actually used here, so it is guarded by the stash boolean. +% For now we ignore the namespace! +% \begin{macrocode} + \@@_struct_get_tag_info:eNN + {\l_@@_struct_stack_parent_tmpa_tl} + \l_@@_get_parent_tmpa_tl + \l_@@_get_parent_tmpb_tl + \@@_check_parent_child:VVVVN + \l_@@_get_parent_tmpa_tl + \l_@@_get_parent_tmpb_tl + \g_@@_struct_tag_tl + \g_@@_struct_tag_NS_tl + \l_@@_parent_child_check_tl + \int_compare:nNnT {\l_@@_parent_child_check_tl}<0 + { + \msg_warning:nnxxx + { tag } + {role-parent-child} + { \l_@@_get_parent_tmpa_tl/\l_@@_get_parent_tmpb_tl } + { \g_@@_struct_tag_tl/\g_@@_struct_tag_NS_tl } + { not~allowed~(struct~\g_@@_struct_stack_current_tl) } + \cs_set_eq:NN \l_@@_role_remap_tag_tl \g_@@_struct_tag_tl + \cs_set_eq:NN \l_@@_role_remap_NS_tl \g_@@_struct_tag_NS_tl + \@@_role_remap: + \cs_gset_eq:NN \g_@@_struct_tag_tl \l_@@_role_remap_tag_tl + \cs_gset_eq:NN \g_@@_struct_tag_NS_tl \l_@@_role_remap_NS_tl + \@@_struct_set_tag_info:eVV + { \int_eval:n {\c@g_@@_struct_abs_int} } + \g_@@_struct_tag_tl + \g_@@_struct_tag_NS_tl + } +% \end{macrocode} +% Set the Parent. +% \begin{macrocode} \@@_prop_gput:cnx { g_@@_struct_\int_eval:n {\c@g_@@_struct_abs_int}_prop } { P } @@ -1202,7 +1330,7 @@ %\cs_new_protected:Npn \tag_struct_use:n #1 {} %<*package> \cs_set_protected:Npn \tag_struct_use:n #1 %#1 is the label - { + { \@@_check_if_active_struct:T { \prop_if_exist:cTF @@ -1220,6 +1348,33 @@ { \pdf_object_ref:e { @@/struct/\g_@@_struct_stack_current_tl } } +% \end{macrocode} +% check if the tag is allowed as child. Here we have to retrieve the +% tag info for the child, while the data for the parent is in +% the global tl-vars: +% \begin{macrocode} + \@@_struct_get_tag_info:eNN + {\__tag_ref_value:enn{tagpdfstruct-#1}{tagstruct}{0}} + \l_@@_tmpa_tl + \l_@@_tmpb_tl + \@@_check_parent_child:VVVVN + \g_@@_struct_tag_tl + \g_@@_struct_tag_NS_tl + \l_@@_tmpa_tl + \l_@@_tmpb_tl + \l_@@_parent_child_check_tl + \int_compare:nNnT {\l_@@_parent_child_check_tl}<0 + { + \cs_set_eq:NN \l_@@_role_remap_tag_tl \g_@@_struct_tag_tl + \cs_set_eq:NN \l_@@_role_remap_NS_tl \g_@@_struct_tag_NS_tl + \@@_role_remap: + \cs_gset_eq:NN \g_@@_struct_tag_tl \l_@@_role_remap_tag_tl + \cs_gset_eq:NN \g_@@_struct_tag_NS_tl \l_@@_role_remap_NS_tl + \@@_struct_set_tag_info:eVV + { \int_eval:n {\c@g_@@_struct_abs_int} } + \g_@@_struct_tag_tl + \g_@@_struct_tag_NS_tl + } } { \msg_warning:nnn{ tag }{struct-label-unknown}{#1} @@ -1271,11 +1426,11 @@ \prop_get:cnN { g_@@_struct_#1_prop } {Ref} - \l_@@_tmpb_tl + \l_@@_get_tmpc_tl \@@_prop_gput:cnx { g_@@_struct_#1_prop } { Ref } - { \quark_if_no_value:NF\l_@@_tmpb_tl { \l_@@_tmpb_tl\c_space_tl }#2 } + { \quark_if_no_value:NF\l_@@_get_tmpc_tl { \l_@@_get_tmpc_tl\c_space_tl }#2 } } \cs_generate_variant:Nn \@@_struct_gput_data_ref:nn {ee} % \end{macrocode} @@ -1319,7 +1474,7 @@ % \section{Attributes and attribute classes} % \begin{macrocode} %<*header> -\ProvidesExplPackage {tagpdf-attr-code} {2022-08-24} {0.97} +\ProvidesExplPackage {tagpdf-attr-code} {2022-12-22} {0.98} {part of tagpdf - code related to attributes and attribute classes} % % \end{macrocode} diff --git a/Master/texmf-dist/source/latex/tagpdf/tagpdf-tree.dtx b/Master/texmf-dist/source/latex/tagpdf/tagpdf-tree.dtx index 6bb4aa99806..ecbd96f04ee 100644 --- a/Master/texmf-dist/source/latex/tagpdf/tagpdf-tree.dtx +++ b/Master/texmf-dist/source/latex/tagpdf/tagpdf-tree.dtx @@ -47,13 +47,13 @@ % }^^A % } % -% \date{Version 0.97, released 2022-08-24} +% \date{Version 0.98, released 2022-12-22} % \maketitle % \begin{implementation} % \begin{macrocode} %<@@=tag> %<*header> -\ProvidesExplPackage {tagpdf-tree-code} {2022-08-24} {0.97} +\ProvidesExplPackage {tagpdf-tree-code} {2022-12-22} {0.98} {part of tagpdf - code related to writing trees and dictionaries to the pdf} % % \end{macrocode} @@ -81,6 +81,21 @@ } } % \end{macrocode} +% \subsection{Check structure} +% \begin{macro}{\@@_tree_final_checks:} +% \begin{macrocode} +\cs_new_protected:Npn \@@_tree_final_checks: + { + \int_compare:nNnF {\seq_count:N\g_@@_struct_stack_seq}={1} + { + \msg_warning:nn {tag}{tree-struct-still-open} + \int_step_inline:nnn{2}{\seq_count:N\g_@@_struct_stack_seq} + {\tag_struct_end:} + } + } +% \end{macrocode} +% \end{macro} +% % \subsection{Catalog: MarkInfo and StructTreeRoot} % The StructTreeRoot and the MarkInfo entry must be added to the catalog. % We do it late so that we can win, but before the pdfmanagement hook. @@ -109,18 +124,34 @@ % \begin{macro}{\@@_tree_write_structtreeroot:} % This writes out the root object. % \begin{macrocode} -\cs_new_protected:Npn \@@_tree_write_structtreeroot: - { - \@@_prop_gput:cnx - { g_@@_struct_0_prop } - { ParentTree } - { \pdf_object_ref:n { @@/tree/parenttree } } - \@@_prop_gput:cnx - { g_@@_struct_0_prop } - { RoleMap } - { \pdf_object_ref:n { @@/tree/rolemap } } - \@@_struct_write_obj:n { 0 } - } +\pdf_version_compare:NnTF < {2.0} + { + \cs_new_protected:Npn \@@_tree_write_structtreeroot: + { + \@@_prop_gput:cnx + { g_@@_struct_0_prop } + { ParentTree } + { \pdf_object_ref:n { @@/tree/parenttree } } + \@@_prop_gput:cnx + { g_@@_struct_0_prop } + { RoleMap } + { \pdf_object_ref:n { @@/tree/rolemap } } + \@@_struct_write_obj:n { 0 } + } + } +% \end{macrocode} +% no RoleMap in pdf 2.0 +% \begin{macrocode} + { + \cs_new_protected:Npn \@@_tree_write_structtreeroot: + { + \@@_prop_gput:cnx + { g_@@_struct_0_prop } + { ParentTree } + { \pdf_object_ref:n { @@/tree/parenttree } } + \@@_struct_write_obj:n { 0 } + } + } % \end{macrocode} % \end{macro} % @@ -300,7 +331,10 @@ % \begin{variable}{@@/tree/rolemap} % At first we reserve again an object. % \begin{macrocode} -\pdf_object_new:n { @@/tree/rolemap } +\pdf_version_compare:NnT < {2.0} + { + \pdf_object_new:n { @@/tree/rolemap } + } % \end{macrocode} % \end{variable} % @@ -308,13 +342,26 @@ % This writes out the rolemap, basically it simply pushes out % the dictionary which has been filled in the role module. % \begin{macrocode} -\cs_new_protected:Npn \@@_tree_write_rolemap: +\pdf_version_compare:NnTF < {2.0} { - \pdf_object_write:nnx { @@/tree/rolemap }{dict} - { + \cs_new_protected:Npn \@@_tree_write_rolemap: + { + \prop_map_inline:Nn\g_@@_role_rolemap_prop + { + \pdfdict_gput:nnx {g_@@_role/RoleMap_dict} + {##1} + {\pdf_name_from_unicode_e:n{##2}} + } + \pdf_object_write:nnx { @@/tree/rolemap }{dict} + { \pdfdict_use:n{g_@@_role/RoleMap_dict} - } + } + } + } + { + \cs_new_protected:Npn \@@_tree_write_rolemap:{} } + % \end{macrocode} % \end{macro} % @@ -360,36 +407,39 @@ % \end{macro} % \subsection{Namespaces} % Namespaces are handle in the role module, here is the code to write them out. -% Namespaces are only relevant for pdf2.0 but we don't care, it doesn't harm. +% Namespaces are only relevant for pdf2.0. % \begin{variable}{@@/tree/namespaces} % \begin{macrocode} -\pdf_object_new:nn{ @@/tree/namespaces }{array} +\pdf_object_new:n { @@/tree/namespaces } % \end{macrocode} % \end{variable} % \begin{macro}{\@@_tree_write_namespaces:} % \begin{macrocode} \cs_new_protected:Npn \@@_tree_write_namespaces: { - \prop_map_inline:Nn \g_@@_role_NS_prop - { - \pdfdict_if_empty:nF {g_@@_role/RoleMapNS_##1_dict} - { - \pdf_object_write:nnx {@@/RoleMapNS/##1}{dict} - { - \pdfdict_use:n {g_@@_role/RoleMapNS_##1_dict} - } - \pdfdict_gput:nnx{g_@@_role/Namespace_##1_dict} - {RoleMapNS}{\pdf_object_ref:n {@@/RoleMapNS/##1}} - } - \pdf_object_write:nnx{tag/NS/##1}{dict} - { - \pdfdict_use:n {g_@@_role/Namespace_##1_dict} - } - } - \pdf_object_write:nx {@@/tree/namespaces} %array - { - \prop_map_tokens:Nn \g_@@_role_NS_prop{\use_ii:nn} - } + \pdf_version_compare:NnF < {2.0} + { + \prop_map_inline:Nn \g_@@_role_NS_prop + { + \pdfdict_if_empty:nF {g_@@_role/RoleMapNS_##1_dict} + { + \pdf_object_write:nnx {@@/RoleMapNS/##1}{dict} + { + \pdfdict_use:n {g_@@_role/RoleMapNS_##1_dict} + } + \pdfdict_gput:nnx{g_@@_role/Namespace_##1_dict} + {RoleMapNS}{\pdf_object_ref:n {@@/RoleMapNS/##1}} + } + \pdf_object_write:nnx{tag/NS/##1}{dict} + { + \pdfdict_use:n {g_@@_role/Namespace_##1_dict} + } + } + \pdf_object_write:nnx {@@/tree/namespaces}{array} + { + \prop_map_tokens:Nn \g_@@_role_NS_prop{\use_ii:nn} + } + } } % \end{macrocode} % \end{macro} @@ -404,6 +454,7 @@ \bool_if:NT\g_@@_active_tree_bool { \hook_use:n {tagpdf/finish/before} + \@@_tree_final_checks: \@@_tree_write_parenttree: \@@_tree_write_rolemap: \@@_tree_write_classmap: diff --git a/Master/texmf-dist/source/latex/tagpdf/tagpdf-user.dtx b/Master/texmf-dist/source/latex/tagpdf/tagpdf-user.dtx index bd2e26ec927..a70c14bb217 100644 --- a/Master/texmf-dist/source/latex/tagpdf/tagpdf-user.dtx +++ b/Master/texmf-dist/source/latex/tagpdf/tagpdf-user.dtx @@ -46,7 +46,7 @@ % }^^A % } % -% \date{Version 0.97, released 2022-08-24} +% \date{Version 0.98, released 2022-12-22} % \maketitle % \begin{documentation} % \section{Setup commands} @@ -246,7 +246,7 @@ % \begin{macrocode} %<@@=tag> %<*header> -\ProvidesExplPackage {tagpdf-user} {2022-08-24} {0.97} +\ProvidesExplPackage {tagpdf-user} {2022-12-22} {0.98} {tagpdf - user commands} % % \end{macrocode} @@ -520,8 +520,10 @@ % \subsection{Structure destinations} % In TeXlive 2022 pdftex and luatex will offer support for structure destinations. % The pdfmanagement has already backend support. We activate them if the -% prerequisites are there: The pdf version should be 2.0, structures should be activated, +% prerequisites are there: structures should be activated, % the code in the pdfmanagement must be there. +% Structure destinations are actually PDF 2.0 only but they don't harm in +% older PDF and can improve html export. % \begin{macrocode} \AddToHook{begindocument/before} { @@ -530,7 +532,6 @@ { \g_@@_active_struct_dest_bool } { \g_@@_active_struct_bool } { \cs_if_exist_p:N \pdf_activate_structure_destination: } - { ! \pdf_version_compare_p:Nn < {2.0} } } { \tl_set:Nn \l_pdf_current_structure_destination_tl { __tag/struct/\g__tag_struct_stack_current_tl } @@ -559,15 +560,17 @@ % Probably one should add some checks if we are already in a paragraph. % % -% \begin{macro}{\l_@@_para_bool,\l_@@_para_show_bool,\g_@@_para_int} +% \begin{macro}{\l_@@_para_bool,\l_@@_para_show_bool,\g_@@_para_int,\l_@@_para_tag_default_tl} % At first some variables. % \begin{macrocode} \bool_new:N \l_@@_para_bool \bool_new:N \l_@@_para_show_bool \int_new:N \g_@@_para_begin_int \int_new:N \g_@@_para_end_int +\tl_new:N \l_@@_para_tag_default_tl +\tl_set:Nn \l_@@_para_tag_default_tl { P } \tl_new:N \l_@@_para_tag_tl -\tl_set:Nn \l_@@_para_tag_tl { P } +\tl_set:Nn \l_@@_para_tag_tl { \l_@@_para_tag_default_tl } % \end{macrocode} % \end{macro} % @@ -603,7 +606,7 @@ \llap{\color_select:n{red}\tiny\int_use:N\g_@@_para_begin_int\ } \tag_mc_end: } - \tag_mc_begin:n {tag=\l_@@_para_tag_tl} + \tag_mc_begin:n {} } } \AddToHook{para/end} diff --git a/Master/texmf-dist/source/latex/tagpdf/tagpdf.dtx b/Master/texmf-dist/source/latex/tagpdf/tagpdf.dtx index be718ec36df..d9550ab7a7f 100644 --- a/Master/texmf-dist/source/latex/tagpdf/tagpdf.dtx +++ b/Master/texmf-dist/source/latex/tagpdf/tagpdf.dtx @@ -92,7 +92,7 @@ % \begin{macrocode} %<@@=tag> %<*package> -\ProvidesExplPackage {tagpdf} {2022-08-24} {0.97} +\ProvidesExplPackage {tagpdf} {2022-12-22} {0.98} { A package to experiment with pdf tagging } \bool_if:nF @@ -118,7 +118,7 @@ % \end{macrocode} %<*debug> % \begin{macrocode} -\ProvidesExplPackage {tagpdf-debug} {2022-08-24} {0.97} +\ProvidesExplPackage {tagpdf-debug} {2022-12-22} {0.98} { debug code for tagpdf } \@ifpackageloaded{tagpdf}{}{\PackageWarning{tagpdf-debug}{tagpdf~not~loaded,~quitting}\endinput} % \end{macrocode} @@ -159,7 +159,7 @@ % \end{macrocode} % \begin{macrocode} %<*base> -\ProvidesExplPackage {tagpdf-base} {2022-08-24} {0.97} +\ProvidesExplPackage {tagpdf-base} {2022-12-22} {0.98} {part of tagpdf - provide base, no-op versions of the user commands } % % \end{macrocode} @@ -180,47 +180,6 @@ } % % \end{macrocode} -% \section{Temporary code} -% This is code which will be removed when proper support exists in LaTeX -% It writes only dictionaries! -% \subsection{Faster object writing} -% \begin{macrocode} -%<*package> -\cs_if_free:NT \pdf_object_write:nnn - { - \cs_new_protected:Npn \pdf_object_new:n #1 - { \pdf_object_new:nn{#1}{dict} } - \cs_new_protected:Npn \pdf_object_write:nnn #1#2#3 - { - \pdf_object_write:nn {#1}{#3} - } - \str_if_eq:VnT \c_sys_backend_str {pdftex} - { - \cs_set_protected:Npn \pdf_object_write:nnn #1#2#3 - { - \tex_immediate:D \tex_pdfobj:D - useobjnum ~ - \int_use:c - { c__pdf_backend_object_ \tl_to_str:n {#1} _int } - { << ~ \exp_not:n {#3} ~ >> } - } - } - \str_if_eq:VnT \c_sys_backend_str {luatex} - { - \cs_set_protected:Npn \pdf_object_write:nnn #1#2#3 - { - \tex_immediate:D \tex_pdfextension:D obj ~ - useobjnum ~ - \int_use:c - { c__pdf_backend_object_ \tl_to_str:n {#1} _int } - { << ~ \exp_not:n {#3} ~ >> } - } - } - } -\cs_generate_variant:Nn \pdf_object_write:nnn {nnx} - -% -% \end{macrocode} % \subsection{a LastPage label} % See also issue \#2 in Accessible-xref @@ -276,7 +235,10 @@ % \begin{variable} % { % \l_@@_tmpa_tl, -% \l_@@_tmpb_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, @@ -290,6 +252,9 @@ % \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 @@ -386,7 +351,7 @@ \cs_generate_variant:Nn \pdffile_embed_stream:nnn {nxx,oxx} \cs_generate_variant:Nn \prop_gput:Nnn {Nxx,Nen} \cs_generate_variant:Nn \prop_put:Nnn {Nxx} -\cs_generate_variant:Nn \prop_item:Nn {No} +\cs_generate_variant:Nn \prop_item:Nn {No,Ne} \cs_generate_variant:Nn \ref_label:nn { nv } \cs_generate_variant:Nn \seq_set_split:Nnn{Nne} \cs_generate_variant:Nn \str_set_convert:Nnnn {Nonn, Noon, Nnon } diff --git a/Master/texmf-dist/source/latex/tagpdf/tagpdf.ins b/Master/texmf-dist/source/latex/tagpdf/tagpdf.ins index 60c0803cbf2..d4940188252 100644 --- a/Master/texmf-dist/source/latex/tagpdf/tagpdf.ins +++ b/Master/texmf-dist/source/latex/tagpdf/tagpdf.ins @@ -62,6 +62,7 @@ and all files in that bundle must be distributed together. \from{tagpdf-mc-shared.dtx}{shared} \from{tagpdf.dtx}{mcloading} \from{tagpdf-tree.dtx}{package} + \from{tagpdf-data.dtx}{package} %should be before the roles code \from{tagpdf-roles.dtx}{package} \from{tagpdf-struct.dtx}{package}%contains also the attr code. \from{tagpdf-space.dtx}{package} @@ -88,6 +89,24 @@ and all files in that bundle must be distributed together. \generate {\file{tagpdf-mc-code-lua.sty}{\from{tagpdf-mc-luacode.dtx}{luamode}}} +\generate + {\file{tagpdf-ns-pdf.def}{\from{tagpdf-data.dtx}{ns-pdf}}} +\generate + {\file{tagpdf-ns-pdf2.def}{\from{tagpdf-data.dtx}{ns-pdf2}}} +\generate + {\file{tagpdf-ns-mathml.def}{\from{tagpdf-data.dtx}{ns-mathml}}} +\generate + {\file{tagpdf-ns-latex.def}{\from{tagpdf-data.dtx}{ns-latex}}} +\generate + {\file{tagpdf-ns-latex-book.def}{\from{tagpdf-data.dtx}{ns-latex-book}}} +\generate + {\file{tagpdf-ns-latex-inline.def}{\from{tagpdf-data.dtx}{ns-latex-inline}}} +\generate + {\file{tagpdf-parent-child.csv}{\from{tagpdf-data.dtx}{parent-child}}} +\generate + {\file{tagpdf-parent-child-2.csv}{\from{tagpdf-data.dtx}{parent-child-2}}} + + % check later if the mc-code uses debug guards too. \generate {\file{tagpdf-debug.sty} @@ -117,4 +136,6 @@ and all files in that bundle must be distributed together. } \def\currentpostamble{\defaultpostamble}% \generate{\file{tagpdf.lua} {\from{tagpdf-backend.dtx}{lua}}} + + \endbatchfile -- cgit v1.2.3