% \iffalse meta-comment % %% File: documentmetadata-support.dtx % Copyright (C) 2021-2026 The LaTeX Project % % 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 % % % The development version of the bundle can be found below % % https://github.com/latex3/latex2e % % for those people who are interested or want to report an issue. % % \begin{macrocode} \def\documentmetadatasupportversion{1.1b} \def\documentmetadatasupportdate{2026-05-02} % \end{macrocode} % % %<*driver> \DocumentMetadata{tagging=on,pdfstandard=ua-2} \documentclass[kernel]{l3in2edoc} \EnableCrossrefs \CodelineIndex \begin{document} \DocInput{documentmetadata-support.dtx} \end{document} % % % \fi % % %\NewDocElement[macrolike = false , % toplevel = true, % idxtype = key , % noprint = true , % idxgroup = metadata keys , % printtype = \textit{key} % ]{Mkey}{mkey} % % % \title{The \texttt{documentmetadata-support} code\thanks{This file % has version \documentmetadatasupportversion\ dated % \documentmetadatasupportdate, \copyright\ \LaTeX\ % Project.}} % \author{Frank Mittelbach, Ulrike Fischer, \LaTeX{} Project} % % \maketitle % % % \section{Introduction} % % The kernel command \cs{DocumentMetadata}, which can be used as % the very first declaration in a document (i.e., before % \cs{documentclass}), defines metadata and other configuration % data that applies to the document as a whole (using a key/value % syntax). It loads and activates % the PDF management code from the \pkg{pdfmanagement} package and loads % and activated code currently stored in latex-lab modules % needed for various features developed as part of the multi-year ``Tagged PDF'' % project.~\cite{blueprint} % % While the underlying functionality is still under % development (e.g., further keys will be added over time and keys % marked temporary may vanish again) the code for % \cs{DocumentMetadata} is placed in a separate bundle, so that it % is easier to update it without the need to build a full \LaTeX{} % release. Over time the functionality will move fully into the % kernel. % % As the loading of the PDF management forces the loading of the \pkg{l3backend} files, % a backend that can't be detected automatically like |dvipdfmx|, % must be set in the first \cs{DocumentMetadata}. % % From a process perspective \cs{DocumentMetadata} loads the % \pkg{pdfmanagement} code and the latex-lab modules % the first time it is called and then % redefines itself to error if % called more than once. In particular, this means that a document % without a \cs{DocumentMetadata} declaration has no code available % for extended management of PDF output and for tagging support. % % \section{The \cs{DocumentMetadata} command} % % \begin{function}{\DocumentMetadata} % \begin{syntax} % \cs{DocumentMetadata}\Arg{key-value list} % \end{syntax} % % The command should be used as the first command in a document, before % \cs{documentclass}. It takes a key-value argument. % \end{function} % % Starting with the release 2025-11-01 \cs{DocumentMetadata} will always load % the new modules which changes \LaTeX{} internals and add tagging support code. % % For documents that want to load the PDF management but do not want the new tagging support % code we provide a dedicated package. Such documents should replace % \begin{verbatim} % \DocumentMetadata{pdfversion=1.7, % pdfstandard=a-3b} % \end{verbatim} % by % \begin{verbatim} % \RequirePackage{pdfmanagement} % \SetKeys[document/metadata]{pdfversion=1.7, % pdfstandard=a-3b} % \end{verbatim} % % Currently the modules loaded by \cs{DocumentMetadata} are the following. % Details and documentation can be found in the various \texttt{latex-lab-\meta{module}.pdf}: % % \begin{description} % \item[\texttt{names}] This module declares tag names for the structures. % \item[\texttt{new-or-2}] This module changes output routine sockets and adds support % for the paragraph tagging. It also loads the new footnote code. % \item[\texttt{block}] This module reimplements lists and blocks environments and % adds tagging support. % \item[\texttt{context}] This module provides context for template instances and code that needs % to know where and when it is executed. % \item[\texttt{sec},\texttt{sec-template}] These modules reimplement heading commands % and make them tagging aware. % \item[\texttt{toc}] This module adapts commands related to the table of contents and % similar list to make them tagging aware. % \item[\texttt{minipage}] This module adds tagging support to \texttt{minipage} % and \cs{parbox}.% % \item[\texttt{graphic}] This module enables tagging support for % the \cs{includegraphics} command and the \texttt{picture} environment. % \item[\texttt{float}] This module adds tagging support to floats. % \item[\texttt{bib}] This module adds tagging support to citations and bibliographies. % \item[\texttt{text}] This module adds tagging support to small text commands like % the \LaTeX{} logo, the \cs{emph} command and super and sub scripts. % \item[\texttt{marginpar}] This module adds tagging support to the \cs{marginpar} % command. % \item[\texttt{title}] This module adds tagging support to the \cs{maketitle} % command if a standard class is used. It also enhances the \cs{title} % and \cs{author} commands to fill the XMP-metadata and set the window title. % It is not compatible with packages and classes which redefine these commands % too. % \item[\texttt{table}] This module provides tagging for % \texttt{tabular}, \texttt{longtable} and similar table environments. % Its use and restrictions are documented in \texttt{latex-lab-table.pdf}. % \item[\texttt{math}] This module adapts math for tagging. % \item[\texttt{firstaid}] This module contains small adjustments to external packages. % \item[\texttt{tikz}] This module adds support for the \pkg{tikz} package. % \end{description} % % % \section{Keys and values} % % Currently the following keys are implemented for \cs{DocumentMetadata}: % \DescribeMkey{backend} % \DescribeMkey{pdfversion} % \DescribeMkey{uncompress} % \DescribeMkey{language} % \DescribeMkey{other-languages} % \DescribeMkey{lang} % \DescribeMkey{pdfstandard} % \DescribeMkey{xmp} % \DescribeMkey{colorprofiles} % \DescribeMkey{tagging} % \DescribeMkey{tagging-setup} % \DescribeMkey{check-tagging-status} % \DescribeMkey{testphase} % \DescribeMkey{debug} % % \begin{description} % \item[\texttt{backend}] Passes the backend name to expl3. This is % needed only if the correct backend can't be automatically % determined or if the workflow requires a special backend. % %^^A This will probably be extended to pass the value also to %^^A packages. % % \item[\texttt{pdfversion}] Sets the PDF version explicitly, e.g., \texttt{pdfversion=1.7}. % The key definition is in the pdfmanagement in l3pdfmeta. % % \item[\texttt{uncompress}] (no value) Forces an uncompressed pdf % --- mainly for debugging purposes. Do not unnecessarily set it in normal production % because it increases the size of the final PDF considerably. % % \item[\texttt{language}] % The language key should be used to set the main language of the % document. The value is given in BCP~47 format, % so, e.g, \texttt{languade=de-DE} or \texttt{language=fr}. % The value is stored in the document properties and can be retrieved (expandably) with % \verb+\GetDocumentProperty{document/language}+. % % The key does \emph{not} change the language setup of a document: it doesn't change the % hyphenation patterns or the fix names or forces the loading of a language package. % The expectation is that packages that need to know the document language, like \pkg{babel} or % \pkg{polyglossia}, read the value and react accordingly. % The BCP~47 value,e.g., can be parsed with \cs{text_bcp_parse:n} which produces % 7 brace groups, see interface3. % To extract, for example, the main language in the first group this code could be used: % \begin{verbatim} % \cs_generate_variant:Nn\text_bcp_parse:n{e} % \tl_set:Ne\mainlanguage % {\exp_last_unbraced:Ne\use_i:nnnnnnn % {\text_bcp_parse:e{\GetDocumentProperty{document/language}}}} % \end{verbatim} % % % The key updates the default \cs{BCPdata} command to use with the give language value. % Note that this can lead to empty fields for region or script, if, e.g., only % \texttt{language=de} instead of \texttt{language=de-Latn-AT} is used. % This is only relevant if neither \pkg{babel} nor \pkg{polyglossia} % are used as both packages overwrite the \cs{BCPdata} command with their own version. % % The value of the \texttt{language} key is also used to set the \texttt{/Lang} key in the PDF. % If a different (shorter) value is wanted there, an optional argument can be used: % \verb+language=[de]{de-DE}+, or the \texttt{lang} key can be % used to overwrite the value: \verb+language=de-DE,lang=de+. % % \item[\texttt{otherlanguage}] % The \texttt{other-languages} key can be used to declare more languages that are used % in the document. The argument is a comma list of languages in BCP~47 format: % \verb+other-languages={fr,en-US,ar}+. % The comma list is stored in the document properties and can be retrieved % (expandably) with \verb+\GetDocumentProperty{document/other-languages}+. % As with the \texttt{language} key the expectation is, that language packages % read the value and react accordingly. % % \item[\texttt{lang}] Explicitly sets the Lang entry in the Catalog, % e.g., \texttt{lang=de-DE}. If not given, the value of \verb+\BCPdata{language}+ % or \verb+ \BCPdata{main.language}+ at the beginning of the document is used (these % commands are set by \pkg{babel}, the default value is |en-US|). % The key is implicitly set if the \texttt{language} key is used. % % \item[\texttt{pdfstandard}] Choice key to set the pdf standard. % Currently |A-1b|, |A-2a|, |A-2b|, |A-2u|, |A-3a|, |A-3b|, |A-3u|, |A-4|, |A-4E| % and |A-4F| are accepted as A-standard. % values. The casing is irrelevant, |a-1b| works too. % Note that using this % key doesn't mean that the document actually follows the standard. \LaTeX{} % can neither ensure nor check all requirements of a standard, and not everything % it can do theoretically has already been implemented. % When setting an A-standard a color profile is included and the % \texttt{/OutputIntent} is set and any javascript action in hyperref are suppressed. % The |u| variants do not enforce unicode, % but they will pass the information to hyperref. The |a| variants % do \emph{not} enforce (or even test) a tagged pdf yet. % % Beside the A-standards it is also possible to use the values % |X-4|, |X-4p|, |X-5g|, |X-5n|, |X-5pg|, |X-6|, |X-6n|, |X-6p| for % a PDF/X and |UA-1| and |UA-2| for PDF/UA standard. % |UA-2| should only be used together with PDF 2.0. % Currently these keys set \emph{only} the relevant XMP-metadata. % They do not validate or enforce special requirements % (e.g., the |UA| standards do not automatically activate tagging). % % |pdfstandard| can be used more than once to set overlapping standards, e.g:\\ % |pdfstandard=A-2b,pdfstandard=X-4,pdfstandard=UA-1|. It is also possible % to pass a list like |pdfstandard={UA-2,A-4F}|. % % If XMP-metadata are added (see the following key \texttt{xmp}) % the necessary conformance markers for the standards are set. % % Standards can require some minimal or maximal PDF version and the keys will try to % adjust the PDF version as necessary. At the beginning of the document the versions are checked % again a warning is issued if PDF version and standard conflicts. % % The key is defined in the pdfmanagement in \pkg{l3pdfmeta} and more % information can be found in the documentation. % % \item[\texttt{xmp}] A boolean, if set to false no XMP metadata are added to the PDF. % The initial value is true. Details are described in the documentation of \pkg{l3pdfmeta}. % % \item[\texttt{colorprofiles}] This allows to load icc-colorprofiles. Details % are described in the documentation of \pkg{l3pdfmeta}. % % \item[\texttt{tagging}] This key allows to activate, deactivate or partially deactivate the tagging support. % It accepts the three values \texttt{on}, \texttt{off} and \texttt{draft}. % The tagpdf package and all standard modules of the tagging support are loaded regardless of the use and the % value of the key! % \begin{itemize} % \item |tagging=on| activates tagging. % \item |tagging=off| deactivates in the \texttt{class/before} hook the tagging commands, % including the \cs{tagpdfsetup} command. It also deactivates the use of real space chars. % This can be reactivated by using |tagging-setup={activate/spaces}|. % \item |tagging=draft| leaves the % tagging commands active but it deactivates the writing of the structure tree % at the end of the compilation. This can save % time when drafting a longer document but preserves, e.g., MC-content marker % in the PDF stream and warnings and errors from \pkg{tagpdf} if the structure is faulty. % \end{itemize} % % \item[\texttt{tagging-setup}] This key allows to configure the tagging. It accepts all % keys that can also be used in \cs{tagpdfsetup}; see the \pkg{tagpdf} documentation. % Additionally, it accepts two keys to extend the list of modules loaded: % \begin{description} % \item[\texttt{modules}] This key previously allowed to change the % list of modules. Starting with the release 2025-11-01 all standard modules % are loaded always, so its only use is to load a non-standard module, e.g. % |modules=verbatim-af| will load an experimental module changing the verbatim tagging. % % \item[\texttt{extra-modules}] This key allows to load non-standard modules and % starting with the release 2025-11-01 it is an alias of |modules|. % \end{description} % % \item[\texttt{check-tagging-status}] This key is provided to help to % identify packages that are potentially problematic when used with the tagging code. % When used (with no value or with the value |listfiles|, % it reads the file |latex-tagging-status.ltx| % from the \pkg{latex-tagging-status} package and then writes at the end of the compilation % a report about the compatibility of the class and the packages with the tagging project. % It follows the classification done at \url{https://latex3.github.io/tagging-project/tagging-status}. % % This is only a rough overview and a debugging aid, not a final report! % Using packages that are classified as incompatible or partially incompatible % does not mean that the tagging is necessarily broken. For example, \pkg{hyperref} % is partially incompatible as the form fields are not properly tagged (this requires the use % of the \pkg{l3pdffield} package), but in documents without form fields it is unproblematic. % (In case of partially-compatible or incompatible packages check the table at % \url{https://latex3.github.io/tagging-project/tagging-status} as it often contains % an explanation what is not yet working.) % % The package \pkg{latex-tagging-status} will be regularly updated to reflect changes % in package. Erroneous messages should be reported % at \url{https://github.com/latex3/tagging-project/issues}. It is also possible % to create a pull request which updates the data. % % \item[\texttt{testphase}] This key loaded in older \LaTeX{} versions % specific sets of modules from the testphase code. % Starting with the release 2025-11-01 all standard modules are % loaded automatically by \cs{DocumentMetadata} and with this change the key % lost most of its original purpose. % The values \texttt{phase-I}, \texttt{phase-II}, \texttt{phase=III} of the % \texttt{testphase} key will no longer load different code variants but only % activate tagging. The key can still be used to load additional experimental modules, % it then works similar to the \texttt{modules} and \texttt{extra-modules} key and does % not automatically activate tagging. % % \item[\texttt{debug}] This key activates some debug options. It takes a list of key-values % as value. Currently the following keys are known: % \begin{description} % \item[\texttt{para}] with the default and only value |show|. It will activate the |debug/show=para| % option of \pkg{tagpdf}; % \item[\texttt{log}] with the values as described in the documentation of \pkg{tagpdf}; % \item[\texttt{uncompress}] which does the same as |uncompress| as main key; % \item[\texttt{pdfmanagement}] a boolean which allows to deactivate the pdfmanagement (deprecated); % \item[\texttt{firstaidoff}] this accepts a comma lists of keywords and disables the patches % related to them. More information can be found in the documentation of % \pkg{pdfmanagement-firstaid}; % \item[\texttt{xmp-export}] this will export the XMP-metadata to a file \verb+\jobname.xmpi+. % With \texttt{debug=\{xmp-export=filename\}} the file name can be changed; % More information can be found in the documentation of \pkg{l3pdfmeta} of the \pkg{pdfmanagement-testphase} % bundle; % \item[\texttt{tagpdf}] This loads the package tagpdf-debug which enhances % various commands from tagpdf with additional debugging options. This can slow down % the compilation! % \item[\texttt{BBox}] This helps to debug BBox values of graphics, see the documentation % of latex-lab-graphic. % \end{description} % \end{description} % % \bibliographystyle{plain} % % \begin{thebibliography}{9} % % \bibitem{blueprint} Frank Mittelbach and Chris Rowley: % \emph{\LaTeX{} Tagged PDF\,---\,A blueprint for a large project}. % \url{https://latex-project.org/publications/indexbyyear/2020/} % % \end{thebibliography} % % % % \MaybeStop{\setlength\IndexMin{200pt} \PrintIndex } % % \begin{implementation} % % \section{The Implementation} % % % \begin{macrocode} %<@@=pdfmanagement> %<*code> % \end{macrocode} % % \begin{macrocode} \RequirePackage{pdfmanagement-init} % \end{macrocode} % % \begin{macrocode} \ExplSyntaxOn\makeatletter % \end{macrocode} % \subsection{Variables} % These variable definitions are currently also done in ltdocinit. % They can be removed from there once latex-lab has been updated to % provide them too. % \begin{variable}{\g_@@_firstaidoff_clist} % A list to store the firstaid code which should be disabled % \begin{macrocode} \clist_if_exist:NF \g_@@_firstaidoff_clist { \clist_new:N \g_@@_firstaidoff_clist } % \end{macrocode} % \end{variable} % \begin{variable}{\g_@@_testphase_tl} % a tl to store the testphase loading code so that we can load them at % the end of the command. % \begin{macrocode} \tl_if_exist:NF \g_@@_testphase_tl { \tl_new:N \g_@@_testphase_tl } % \end{macrocode} % \end{variable} % % \subsection{Kernel changes with \cs{DocumentMetadata}} % \begin{macro}{\@kernel@before@DocumentMetadata} % \begin{macrocode} \cs_new_protected:Npn \@kernel@before@DocumentMetadata { \ifx\Umathcode\@undefined \fontencoding{T1} \renewcommand\encodingdefault{T1} \fi } % \end{macrocode} % \end{macro} % \subsection{\cs{DocumentMetadata}} % % \begin{macro}{\DocumentMetadata} % % \cs{DocumentMetadata} should not be used after % \cs{documentclass} so we error in this case. % It can be used more than once % but follow-up calls should not do the initialization code. % \begin{macrocode} \cs_set_protected:Npn \DocumentMetadata #1 { \cs_if_eq:NNTF \documentclass \@twoclasseserror { \msg_error:nn { meta } { after-class } } { % \end{macrocode} % Load general format changes % \begin{macrocode} \@kernel@before@DocumentMetadata % \end{macrocode} % % The wanted backend must be detected first, we read the init % key and then force the loading of the backend. % The backend can contain management commands, so the boolean should % be set to true first. % \begin{macrocode} \bool_gset_true:N \g_@@_active_bool \keys_set_groups:nnn { document / metadata} {init}{ #1 } %if no backend has been loaded force it now: \str_if_exist:NF \c_sys_backend_str { \sys_load_backend:n {} } % \end{macrocode} % Now we load the extra backend code: % \begin{macrocode} \ExplSyntaxOn\makeatletter \file_input:n {l3backend-testphase-\c_sys_backend_str.def} \ExplSyntaxOff\makeatother % \end{macrocode} % \changes{v1.0m}{2025/02/17}{Set PDF 2.0 as default} % \begin{macrocode} \pdf_version_gset:n { 2.0 } % \end{macrocode} % tagpdf currently requires that the pdf version is set first. % \begin{macrocode} \keys_set_groups:nnn { document / metadata} {pdf}{ #1 } % \end{macrocode} % Load the latex-lab modules: % \changes{v1.0s}{2025/07/07}{Load latest set always.} % \begin{macrocode} \RequirePackage{latex-lab-testphase-latest} \AddToDocumentProperties [document]{tagging}{inactive} \AddToDocumentProperties [document]{tagging/para}{inactive} % \end{macrocode} % Process the non-init keys. % \changes{v1.0s}{2025/07/07}{hyperref loads the generic driver itself} % \changes{v1.0s}{2025/07/07}{pdf management is always active, so test removed} % \begin{macrocode} \keys_set_exclude_groups:nnn { document / metadata } { init,pdf } { #1 } % \end{macrocode} % Finally we set up the language default. % If the \texttt{language} key hasn't be set yet, we set it directly % either to the value of the \texttt{lang} key or to en-US. % \begin{macrocode} \tl_if_empty:eTF{\GetDocumentProperty{document/language}} { \tl_set:Ne\l_@@_tmpa_tl{\GetDocumentProperty{document/lang}} \tl_if_empty:NTF\l_@@_tmpa_tl {\AddToDocumentProperties[document]{language}{en-Latn-US}} { \keys_set:ne{document/metadata}{language=\l_@@_tmpa_tl} \@@_update_BCPdata: } } { \@@_update_BCPdata: } % \end{macrocode} % At last we set up the lang default. % This is done after the begindocument hook so that it can pick up settings % from babel. If the Catalog dictionary already contains a lang value we do nothing, % otherwise we use the value stored in \cs{BCPdata}, either the main language % (if its exists) or the fall back language. % Note: if babel is loaded without a language this gives the language \texttt{und}. % \changes{v1.0x}{2025/12/15}{Remove warning, issue tagging/1115} % \begin{macrocode} \g@addto@macro\@kernel@after@begindocument { \pdfdict_get:nnN {g__pdf_Core/Catalog}{Lang}\l_@@_tmpa_tl \quark_if_no_value:NT\l_@@_tmpa_tl { \tl_if_empty:eTF { \BCPdata{main.language} } { \tl_set:Ne \l_@@_tmpb_tl { \BCPdata{language} } } { \tl_set:Ne \l_@@_tmpb_tl { \BCPdata{main.language} } } \exp_last_unbraced:Ne \AddToDocumentProperties{[document]{lang}{\l_@@_tmpb_tl}} \pdfmanagement_add:nne {Catalog} {Lang}{(\l_@@_tmpb_tl)} } } % \end{macrocode} % \cs{pdfmanagement_add:nnn} has collected values in this hook. % \begin{macrocode} \hook_use_once:n {pdfmanagement/add} % \end{macrocode} % Now we redefine \cs{DocumentMetadata} so that it errors on future calls % \changes{1.0z}{2026-04-22}{Error if two \cs{DocumentMetadata} declarations are used.} % \begin{macrocode} \cs_set_protected:Npn \DocumentMetadata ##1 { \@latex@error {Two~\noexpand\DocumentMetadata~declarations}% {The~document~may~use~only~one~\noexpand\DocumentMetadata~declaration.} } % \end{macrocode} % Load more modules, the testphase code and the firstaid code. % \begin{macrocode} \g_@@_testphase_tl \RequirePackage{pdfmanagement-firstaid} } } % \end{macrocode} % \end{macro} % \subsection{Tagging status report} % Hide our own files % \begin{macrocode} \clist_map_inline:nn { pdfmanagement-init.sty, color-ltx.sty, xcolor-patches-tmp-ltx.sty, tagpdf-base.sty, latex-lab-testphase-latest.sty, tagpdf.sty, tagpdf-mc-code-generic.sty, tagpdf-mc-code-lua.sty, luamml-patches-kernel.sty, luamml-patches-amsmath.sty, latex-lab-enumitem.sty, latex-lab-kernel-changes.sty, latex-lab-testphase-names.sty, latex-lab-testphase-new-or-2.sty, latex-lab-testphase-block.sty, latex-lab-testphase-context.sty, latex-lab-testphase-sec.sty, latex-lab-testphase-sec-template.sty, latex-lab-testphase-toc.sty, latex-lab-testphase-minipage.sty, latex-lab-testphase-graphic.sty, latex-lab-testphase-float.sty, latex-lab-testphase-bib.sty, latex-lab-testphase-text.sty, latex-lab-testphase-marginpar.sty, latex-lab-testphase-title.sty, latex-lab-testphase-table.sty, latex-lab-testphase-math.sty, latex-lab-testphase-firstaid.sty, latex-lab-testphase-tikz.sty, pdfmanagement-firstaid.sty, } {\expandafter\chardef\csname t@status@#1\endcsname8\relax } % \end{macrocode} % \begin{macrocode} \tl_new:c {l__tag_status_0_tl} \tl_new:c {l__tag_status_1_tl} \tl_new:c {l__tag_status_2_tl} \tl_new:c {l__tag_status_3_tl} \tl_new:c {l__tag_status_4_tl} \tl_new:c {l__tag_status_-1_tl} \cs_new_protected:Npn\__tag_status_sort: { \clist_map_inline:Nn\g__tag_status_filelist_tl { \filename@parse{##1} \cs_if_exist:cTF { t@status@##1 } { \str_if_eq:onF{\filename@ext}{cls} { \tl_put_right:cn {l__tag_status_\int_use:c { t@status@##1 }_tl} {~~##1\iow_newline:} } } { \str_if_eq:onT{\filename@ext}{sty} { \tl_put_right:cn {l__tag_status_-1_tl} {~~##1\iow_newline:} } } } } \cs_new_protected:Npn \__tag_status_type:nn #1 #2 % #1 number, -1 for not listed, #2 title { \iow_term:n{~~#2} \iow_term:n{~~--------------------------} \tl_if_empty:cTF{l__tag_status_#1_tl} { \iow_term:e{~~NONE\iow_newline:} } { \iow_term:e{\tl_use:c{l__tag_status_#1_tl}} } } \cs_new_protected:Npn \__tag_status_log: { \file_if_exist_input:n {latex-tagging-status.ltx} \AddToHookNext{class/before} { \tl_const:Ne \c__tag_current_class_tl{\@currname.\@currext} \tl_const:Ne \c__tag_status_class_tl { \cs_if_exist:cTF { t@status@\@currname.\@currext } { \int_case:nn { \int_use:c { t@status@\@currname.\@currext } } { {0}{unknown} {1}{unsupported} {2}{currently~incompatible} {3}{partially~compatible} {4}{compatible} } } { not~in~the~status~list} } } \AddToHook{begindocument}{\tl_gset_eq:NN \g__tag_status_filelist_tl\@filelist} \AddToHook{enddocument/info} { \iow_term:n{} \iow_term:n {======================================} \iow_term:n{~~Status~report~of~the~tagging~support} \iow_term:n{======================================} \iow_term:n{~~Details~at~https://latex3.github.io/tagging-project/tagging-status} \iow_term:n{~~Report~erroneous~entries~at~https://github.com/latex3/tagging-project} \iow_term:n{} \iow_term:n{~~A.~CLASS} \iow_term:n{~~********} \iow_term:n{} \iow_term:e{~~\c__tag_current_class_tl\c_space_tl is~\c__tag_status_class_tl} \iow_term:n{} \iow_term:n{~~B.~PACKAGES,~LIBRARIES,~etc} \iow_term:n{~~***********} \iow_term:n{} \__tag_status_sort: \__tag_status_type:nn{1}{1.~Unsupported} \__tag_status_type:nn{2}{2.~Currently~incompatible} \__tag_status_type:nn{3}{3.~Partially~compatible} \__tag_status_type:nn{4}{4.~Compatible} \__tag_status_type:nn{0}{5.~Unknown} \__tag_status_type:nn{-1}{6.~Unclassified~files~with~extension~.sty} \iow_term:n{====================================} \iow_term:n{~~End~of~status~report} \iow_term:n{====================================} } } % \end{macrocode} %\subsection{\cs{DocumentMetadata} keys} %\changes{1.0k}{2024-12-17}{added latest value for testphase key.} %\changes{1.0n}{2025/03/25}{Allow a list as pdfstandard value.} %\changes{1.0n}{2025/03/25}{Add tagging key} %\changes{1.0n}{2025/03/25}{Add tagging-setup} %\changes{1.0o}{2025/04/03}{Add debug=BBox} %\changes{1.0p}{2025/04/28}{Add tikz module to latest key} %\changes{1.0u}{2025/10/09}{Added check-tagging-status} %\changes{1.0v}{2025/10/12}{Extend check-tagging-status to libraries} %\changes{1.0z}{2026-04-22}{Removed duplicated key definitions that are already done in pdfmanagement-init} % % \begin{macro}{\@@_update_BCPdata:n} % A helper command for the language key. % This command updates the \cs{BCPdata} command. % \begin{macrocode} \cs_generate_variant:Nn \text_bcp_parse:n {e} \cs_new_protected:Npn\@@_update_BCPdata: { \tl_set:Ne\l_@@_tmpa_tl { \text_bcp_parse:e{\GetDocumentProperty{document/language}} } \use:e { \exp_not:N\renewcommand*\exp_not:N\BCPdata[1] { \exp_not:N \str_case:nn {##1} { { language } %was en { \exp_last_unbraced:No\use_i:nnnnnnn { \l_@@_tmpa_tl} } { region } %was US { \exp_last_unbraced:No\use_iv:nnnnnnn { \l_@@_tmpa_tl} } { script } %was Latn { \exp_last_unbraced:No\use_iii:nnnnnnn { \l_@@_tmpa_tl} } { tag } %was en-US { \exp_last_unbraced:No\use_i:nnnnnnn { \l_@@_tmpa_tl}- \exp_last_unbraced:No\use_iv:nnnnnnn { \l_@@_tmpa_tl} } } } } } % \end{macrocode} % \end{macro} % \begin{macro}{\@@_language_set:n,\@@_language_set_aux:wn} % Command to handle the optional argument of the \texttt{language} key. % \begin{macrocode} \cs_new_protected:Npn \@@_language_set:n #1 { \tl_if_head_eq_charcode:nNTF {#1}[ %] { \@@_language_set_aux:wn #1 } { \AddToDocumentProperties[document]{language}{#1} \keys_set:ne{document/metadata}{lang={#1}} } } \cs_new_protected:Npn \@@_language_set_aux:wn [#1] #2 { \AddToDocumentProperties[document]{language}{#2} \keys_set:ne{document/metadata}{lang={#1}} } % \end{macrocode} % \end{macro} % The key definition: % \changes{1.1b}{2026-05-02}{Add keys \texttt{language} and \texttt{other-languages}.} % \begin{macrocode} \keys_define:nn { document / metadata } { language .code:n = { \@@_language_set:n {#1} }, other-languages.code:n = {\AddToDocumentProperties [document]{other-languages}{#1}}, } % \end{macrocode} % \begin{macrocode} \keys_define:nn { document / metadata } { backend .choices:nn = { dvipdfmx , dvips , dvisvgm , luatex , pdftex , pdfmode , xdvipdfmx , xetex } { \sys_load_backend:n {#1} }, backend .groups:n = { init } , } \keys_define:nn { document / metadata } { ,check-tagging-status .choice: ,check-tagging-status / off .code:n = {} ,check-tagging-status / listfiles .code:n = { \__tag_status_log: } ,check-tagging-status .default:n = {listfiles} } \keys_define:nn { document / metadata } { ,pdfversion .groups:n = { pdf } ,pdfstandard .groups:n = { pdf } ,lang .code:n = { \pdfmanagement_add:nnn {Catalog} {Lang}{(#1)} \AddToDocumentProperties[document]{lang}{#1} } % \end{macrocode} % As the latest set of modules is loaded by default, many testphase keys only activate tagging. % \changes{v1.0s}{2025/07/07}{Adapted testphase keys to the default loading of the tagging code} % \begin{macrocode} ,testphase .multichoices:nn = {latest,tagpdf,phase-I,phase-II,phase-III} { \keys_set:nn {document / metadata} {tagging=on} } % \end{macrocode} % The following modules are all always loaded, therefore they can be ignored when used in a testphase key: % \changes{v1.1a}{2026-04-23}{Make testphase values for loaded modules noop} % \begin{macrocode} ,testphase .multichoices:nn = {math,new-or,sec,sec-template,toc,graphic,block,minipage,float, bib,context,text,firstaid,table,title,marginpar,tikz} {} ,testphase / unknown .code:n = { \tl_gput_right:Nn\g_@@_testphase_tl { \tl_if_empty:eT{\GetDocumentProperties{document/testphase/#1}} { \AddToDocumentProperties [document]{testphase/#1}{loaded} \file_if_exist_input:nF {#1-latex-lab-testphase.ltx} { \msg_warning:nnn{meta}{latex-lab-pkg-missing}{#1} \AddToDocumentProperties [document]{testphase/#1}{missing} } } } } } % \end{macrocode} % Activating and deactivating tagging after tagpdf has been loaded requires a redefinition % of various commands. We store the needed settings in auxiliaries that we % can redefine if tagging should be used. % \changes{1.0w}{2025-10-13}{Use commands to set tagging, tagging issue \#994} % \begin{macro}{\__tag_document_set_tagging_off:, % \__tag_document_set_tagging_on:, % \__tag_document_set_tagging:} % \begin{macrocode} \cs_new_protected:Npn \__tag_document_set_tagging_off: { % \end{macrocode} % Avoid warning from non-existing hook label. This can be removed after the % next tagpdf update (2025-10-13). % \begin{macrocode} \sys_if_engine_luatex:F { \AddToHook{shipout/firstpage}[tagpdf/space]{} } \tagpdfsetup{activate/mc=false,activate/tree=false, activate/struct=false,activate/socket=false, activate/spaces=false, para/tagging=false,math/setup=} \AddToDocumentProperties [document]{tagging}{inactive} \AddToDocumentProperties [document]{tagging/para}{inactive} \AddToDocumentProperties [document]{tagging/interwordspace}{inactive} % \end{macrocode} % \changes{v1.0r}{2025/07/03}{Start a global suspend} % We must avoid that a command like \cs{LaTeX} which contains a \cs{ResumeTagging} command restarts % tagging, so we start a global suspend. Perhaps the commands should even be set to noop. % \begin{macrocode} \tag_suspend:n {global} % \end{macrocode} % \changes{v1.0t}{2025/09/25}{Disable \cs{tagpdfsetup}} % We disable the setup command, as various keys assume that the tagging structure is there, % see tagging-project issue \#994. % \begin{macrocode} \cs_set_protected:Npn\tagpdfsetup##1{} % \end{macrocode} % % perhaps, need to test: % \begin{macrocode} %\cs_set_eq:NN\tag_suspend:n\use_none:n %\cs_set_eq:NN\tag_resume:n \use_none:n } \cs_new_protected:Npn \__tag_document_set_tagging_on: { \tagpdfsetup{activate,para/tagging,activate/spaces} \AddToDocumentProperties [document]{tagging}{active} \AddToDocumentProperties [document]{tagging/para}{active} \AddToDocumentProperties [document]{tagging/interwordspace}{active} } % \end{macrocode} % By default tagging is off. % \begin{macrocode} \cs_new_eq:NN \__tag_document_set_tagging:\__tag_document_set_tagging_off: \AddToHookNext{class/before}{\__tag_document_set_tagging:} % \end{macrocode} % \end{macro} % \begin{macrocode} \keys_define:nn { document / metadata } { ,tagging .choice:, ,tagging / on .code:n = { \cs_set_eq:NN \__tag_document_set_tagging:\__tag_document_set_tagging_on: } ,tagging / off .code:n = { \cs_set_eq:NN \__tag_document_set_tagging:\__tag_document_set_tagging_off: } ,tagging / draft .code:n = { \keys_set:nn { document / metadata }{ tagging=on } \AddToHook{shipout/lastpage}[tagging-setup]{\tagpdfsetup{activate/tree=false}} \DeclareHookRule{shipout/lastpage}{tagging-setup}{before}{tagpdf} } ,tagging-setup .code:n = { \keys_set:nn { document / metadata }{ tagging=on } \tl_gclear:N\g_@@_testphase_tl \keys_set_groups:nnn{__tag/setup}{load}{#1} \AddToHook{class/before} {\keys_set_exclude_groups:nnn {__tag/setup}{load}{#1}} } ,debug .code:n = { \keys_set:nn { document / metadata / debug } {#1} } ,debug / para .code:n = { \AddToHook { package/tagpdf/after } { \tagpdfsetup{debug/show=para} } } ,debug / log .code:n = { \AddToHook { package/tagpdf/after } { \tagpdfsetup{debug/log=#1} } } ,debug / tagpdf .code:n = { \AddToHook { package/tagpdf/after } { \RequirePackage{tagpdf-debug} } } ,debug / uncompress .code:n = { \pdf_uncompress: } ,debug / pdfmanagement .bool_gset:N = \g_@@_active_bool ,debug / firstaidoff .clist_gset:N = \g_@@_firstaidoff_clist ,debug / BBox .code:n = { \AddToHook{package/latex-lab-testphase-graphic/after} { \bool_set_true:N \l__tag_graphic_debug_bool} } } \keys_define:nn{__tag/setup} { ,modules .code:n = { \keys_set:nn { document / metadata }{testphase={#1}} } ,modules .groups:n = { load } ,extra-modules .code:n = { \keys_set:nn { document / metadata }{testphase={#1}} } ,extra-modules .groups:n = { load } } % \end{macrocode} % \subsection{Messages} % \begin{macrocode} %UFi is meta the right module name here? \prop_gput:Nnn \g_msg_module_type_prop { meta } { LaTeX } \prop_gput:Nnn \g_msg_module_name_prop { meta } { DocumentMetadata } \msg_new:nnn { meta } { after-class } { \token_to_str:N \DocumentMetadata \c_space_tl should~be~used~only~before~\token_to_str:N\documentclass } \msg_new:nnn { meta } { latex-lab-pkg-missing } { LaTeX-lab~package~'#1'~not~found. } % \end{macrocode} % % \begin{macrocode} \ExplSyntaxOff\makeatother % \end{macrocode} % % % \begin{macrocode} % % \end{macrocode} % % \end{implementation} % % \Finale %