% \iffalse meta-comment % %% File: latex-lab-title.dtx (C) Copyright 2023-2024 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/required/latex-lab % % for those people who are interested or want to report an issue. % \def\ltlabtitledate{2024-02-09} \def\ltlabtitleversion{0.85c} %<*driver> \documentclass{l3doc} \EnableCrossrefs \CodelineIndex \begin{document} \DocInput{latex-lab-title.dtx} \end{document} % % % \fi % % \title{The \textsf{latex-lab-title} package\\ % Changes related to the tagging of the title} % \author{\LaTeX{} Project\thanks{Initial implementation done by Ulrike Fischer}} % \date{v\ltlabtitleversion\ \ltlabtitledate} % % \maketitle % % \newcommand{\xt}[1]{\textsl{\textsf{#1}}} % \newcommand{\TODO}[1]{\textbf{[TODO:} #1\textbf{]}} % \newcommand{\docclass}{document class \marginpar{\raggedright document class % customizations}} % % \providecommand\hook[1]{\texttt{#1}} % % \begin{abstract} % \end{abstract} % % \section{Introduction} % % This module contains changes to improve the tagging (in the standard classes) of % the title created with the \cs{maketitle} command. It also improves the % setting of the metadata related to the title and the author. % % For basic tagging of the printed title there are basically three things to do: % % \begin{itemize} % \item The actual title should be tagged with the \texttt{Title} tag. % \item The tabular used to format the author list should \emph{not} be tagged as a tabular. % \item \cs{maketitle} redefines footnote internals. These must be made tagging aware. % \end{itemize} % % A second task related to title is to store the authors and the title text % (or a shorter version) inside the XMP-metadata and (in PDF 1.7 or lower) in % the Info dictionary. Currently this can only be set if hyperref % is loaded and requires the use of the \texttt{pdftitle} and \texttt{pdfauthor} keys. % The new code therefore extends the \cs{title} and \cs{author} commands: They % stores their argument and use them at the end of the document % for the PDF metadata if the data hasn't been given in another way. % The code also gives \cs{title} and \cs{author} % an optional argument where the PDF title or author can be given with % in a key-value syntax. As with hyperref it is possible to store titles % in more than one language: % % \begin{verbatim} % \title % [pdftitle = % {[en]English Title,[de] Deutscher Titel,[fr]{titre français, avec comma}}] % {Document title} % \end{verbatim} % % It is also possible to set a subtitle which is then stored in the XMP-metadata: % % \begin{verbatim} % \title % [pdfsubtitle = % {[en]English Subtitle,[de] Deutscher Subtitel,[fr]{subtitre français, avec comma}}] % {Document title} % \end{verbatim} % % If using the \texttt{pdfauthor} key authors should be separated % by commas, and to hide commas in a name inside braces if needed: % % \begin{verbatim} % \author[pdfauthor = {Bär, Peter Anteater, {Riley, the sloth}}]{\ldots} % \end{verbatim} % % If hyperref is loaded there is no difference to the \texttt{pdftitle} and % \texttt{pdfauthor} key used in \cs{hypersetup}. Both can be used (and the last % key used will win). % % \subsection{Open questions and TODOs} % % \begin{itemize} % \item Writing into the Info dictionary needs to convert the input into a PDF string. % This is here done with a simple version of hyperref's \cs{pdfstringdef}, similar code % exist also in in the generic hyperref driver. This should be moved into a better place % module. % % \item Is it sensible to enhance \cs{author} and \cs{title} with an optional argument as done here? % An advantage is that it is rather light-weight and % doesn't require to decide how this values should be set in \cs{DocumentMetadata} (and would also work % without \cs{DocumentMetadata}. But a problem could be that various classes and packages already % extend this commands with other optional arguments. % % \item Some of the definitions related to metadata should perhaps be moved into l3pdfmeta. % % \item Are the names \texttt{pdftitle} and \texttt{pdfauthor} ok? % % \item The patch for \cs{thanks} to get a rlap-footnotemarker looks wrong. This % probably means that some configuration option is missing in the footnote code. % \end{itemize} % % % % \section{Implementation} % \begin{macrocode} %<*package> %<@@=tag> % \end{macrocode} % \begin{macrocode} \ProvidesExplPackage {latex-lab-testphase-title} {\ltlabtitledate} {\ltlabtitleversion} {Changes related to the tagging of the title} % \end{macrocode} % % \subsection{\cs{maketitle} in article class} % % \begin{macrocode} \cs_new_protected:Npn \@@_patch_thanks:n #1 { \rlap{\footnotemark} \protected@xdef\@thanks{\@thanks \protect\footnotetext[\the\c@footnote]{#1}} } % \end{macrocode} % The no-titlepage version of article, report and book % \begin{macrocode} \cs_new_protected:Npn \@@_patch_maketitle: { \par \begingroup % \end{macrocode} % Disable table tagging % \begin{macrocode} \cs_if_exist_use:N\__tag_tbl_disable: \renewcommand\thefootnote{\@fnsymbol\c@footnote}% % \end{macrocode} % the original definition redefines \cs{@makefnmark} and % \cs{@makefntext} to get an rlap-mark in the text without % affecting the mark in the note (which gives by the way % a wrong link area with hyperref). There seem to be currently % no good way in the footnote to configure this, so we redefine % \cs{thanks} instead % \begin{macrocode} \cs_set_eq:NN \thanks \@@_patch_thanks:n \if@twocolumn \ifnum \col@number=\@ne \@maketitle \else \twocolumn[\@maketitle]% \fi \else \newpage \global\@topnum\z@ % Prevents figures from going at top of page. \@maketitle \fi \thispagestyle{plain}\@thanks \endgroup \setcounter{footnote}{0}% \global\let\thanks\relax \global\let\maketitle\relax \global\let\@maketitle\relax \global\let\@thanks\@empty \global\let\@author\@empty \global\let\@date\@empty \global\let\@title\@empty \global\let\title\relax \global\let\author\relax \global\let\date\relax \global\let\and\relax } % \end{macrocode} % We must also change \cs{@maketitle} to insert a Title tag % \begin{macrocode} \cs_new_protected:Npn \@@_patch_@maketitle: { \newpage \null \vskip 2em% \begin{center}% \let \footnote \thanks % \end{macrocode} % use Title around the title. As in PDF 1.7 this is % rolemapped to P we change the text-unit tag there. % \begin{macrocode} \pdf_version_compare:NnTF > {1.7} {{\LARGE \tag_struct_begin:n{tag=Title}\@title \par\tag_struct_end:}} {{\LARGE \tagtool{paratag=Title}\@title \par}}% \vskip 1.5em% {\large \lineskip .5em% \begin{tabular}[t]{c}% \@author \end{tabular}\par}% \vskip 1em% {\large \@date}% \end{center}% \par \vskip 1.5em } % \end{macrocode} % The titlepage variant % \begin{macrocode} \cs_new_protected:Npn \@@_patch_maketitle_page: {\begin{titlepage}% % \end{macrocode} % disable table tagging % \begin{macrocode} \cs_if_exist_use:N\__tag_tbl_disable: \let\footnotesize\small \let\footnoterule\relax \let \footnote \thanks \null\vfil \vskip 60\p@ % \end{macrocode} % use Title around the title. As in PDF 1.7 this is % rolemapped to P we change the text-unit tag there. % \begin{macrocode} \begin{center}% \pdf_version_compare:NnTF > {1.7} {{\LARGE \tag_struct_begin:n{tag=Title}\@title \par\tag_struct_end:}} {{\LARGE \tagtool{paratag=Title}\@title \par}}% \vskip 3em% {\large \lineskip .75em% \begin{tabular}[t]{c}% \@author \end{tabular}\par}% \vskip 1.5em% {\large \@date \par}% % Set date in \large size. \end{center}\par \@thanks \vfil\null \end{titlepage}% \setcounter{footnote}{0}% \global\let\thanks\relax \global\let\maketitle\relax \global\let\@thanks\@empty \global\let\@author\@empty \global\let\@date\@empty \global\let\@title\@empty \global\let\title\relax \global\let\author\relax \global\let\date\relax \global\let\and\relax } % \end{macrocode} % Map the new commands onto \cs{maketitle}: % \begin{macrocode} \AddToHook{class/article/after} { \if@titlepage \cs_set_eq:NN \maketitle \@@_patch_maketitle_page: \else \cs_set_eq:NN \maketitle \@@_patch_maketitle: \cs_set_eq:NN \@maketitle \@@_patch_@maketitle: \fi } \AddToHook{class/report/after} { \if@titlepage \cs_set_eq:NN \maketitle \@@_patch_maketitle_page: \else \cs_set_eq:NN \maketitle \@@_patch_maketitle: \cs_set_eq:NN \@maketitle \@@_patch_@maketitle: \fi } \AddToHook{class/book/after} { \if@titlepage \cs_set_eq:NN \maketitle \@@_patch_maketitle_page: \else \cs_set_eq:NN \maketitle \@@_patch_maketitle: \cs_set_eq:NN \@maketitle \@@_patch_@maketitle: \fi } % \end{macrocode} % % \subsection{Helper commands to set metadata} % % Some temp variables % \begin{macrocode} \str_new:N \g_@@_title_tmpa_str \str_new:N \l_@@_title_tmpa_str \tl_new:N \l_@@_title_tmpa_tl \seq_new:N \l_@@_title_tmpa_seq % \end{macrocode} % Support for \cs{texorpdfstring} % \begin{macrocode} \providecommand\texorpdfstring[2]{#1}% % \end{macrocode} % % A helper command to convert the title into a pdfstring similar to % \cs{pdfstringdef}. % As we use \cs{text_purify} we must ensure that the default definitions % of \cs{@title} and \cs{@author} are robust: % \begin{macrocode} \protected\def\@title{\@latex@error{No \noexpand\title given}\@ehc} \protected\def\@author{\@latex@warning@no@line{No \noexpand\author given}} % \end{macrocode} % TODO: This should be improved and moved into the pdf module so that % it is generally available. % \begin{macrocode} \cs_new_protected:Npn \@@_title_pdfstring:nnN #1 #2 #3 % #1 text, #2 e.g. utf16/hex { \group_begin: % \end{macrocode} % TODO: we need probably a common boolean to handle % \cs{texorpdfstring} also without hyperref. % \begin{macrocode} \cs_set_eq:NN\texorpdfstring\use_ii:nn \str_set:Ne \l_@@_title_tmpa_str {\text_purify:n { #1 } } \pdf_string_from_unicode:nVN { #2 } \l_@@_title_tmpa_str \l_@@_title_tmpa_str \str_gset_eq:NN \g_@@_title_tmpa_str\l_@@_title_tmpa_str \group_end: \str_set_eq:NN #3 \g_@@_title_tmpa_str } \cs_generate_variant:Nn\@@_title_pdfstring:nnN {e} % \end{macrocode} % \subsection{Extend title to set metadata} % At first a variable to store the title, as \cs{@title} is emptied by \LaTeX. % \begin{macrocode} \tl_new:N \g_@@_title_title_tl % \end{macrocode} % Now we redefine \cs{title} so that it stores the title, and processes % keys in the optional argument. We use \texttt{hyp} as module % name for the key as this means that if hyperref is loaded its definition % of \texttt{pdftitle} will be used -- at some time probably this % should be moved out of hyperref so that we have only one definition. % % \begin{macrocode} \RenewDocumentCommand\title{O{}m} { \gdef\@title{#2} \tl_gset_eq:NN\g_@@_title_title_tl\@title \keys_set:nn {hyp}{#1} } % \end{macrocode} % Now we define the \texttt{pdftitle} key. This is more or less % the same definition as in the generic hyperref driver. % \begin{macrocode} \regex_new:N\l_@@_title_optlang_regex \regex_set:Nn\l_@@_title_optlang_regex {\A\[([A-Za-z\-]+)\](.*)} \cs_generate_variant:Nn \regex_extract_once:NnN{NVN} \cs_generate_variant:Nn \clist_item:nn {on} % \end{macrocode} % and now the keys. % \begin{macrocode} \keys_define:nn { hyp } { pdftitle .code:n = { \tl_if_blank:nTF {#1} { \pdfmanagement_remove:nn {Info}{Title} } { \tl_set:Ne\l_@@_title_tmpa_tl {\clist_item:on{#1}{1}} \regex_extract_once:NVN \l_@@_title_optlang_regex \l_@@_title_tmpa_tl \l_@@_title_tmpa_seq \seq_if_empty:NTF\l_@@_title_tmpa_seq { \@@_title_pdfstring:nnN {#1}{utf16/hex}\l_@@_title_tmpa_str } { \@@_title_pdfstring:enN {\seq_item:Nn \l_@@_title_tmpa_seq{3}}{utf16/hex}\l_@@_title_tmpa_str } \str_if_eq:VnF\l_@@_title_tmpa_str{} { \pdfmanagement_add:nne {Info}{Title}{\l_@@_title_tmpa_str} } } \AddToDocumentProperties[hyperref]{pdftitle}{#1} } ,pdfsubtitle .code:n = { \AddToDocumentProperties[hyperref]{pdfsubtitle}{#1} } } % \end{macrocode} % % \subsection{Extend \cs{author} to set metadata} % % At first a variable to store the authors, as \cs{@author} is emptied by \LaTeX. % \begin{macrocode} \tl_new:N \g_@@_title_author_tl % \end{macrocode} % Now we redefine \cs{author} so that it stores the authors, and processes % keys in the optional argument. We use \texttt{hyp} as module % name for the key as this means that if hyperref is loaded its definition % of \texttt{pdfauthor} will be used -- at some time probably this % should be moved out of hyperref so that we have only one definition. % % \begin{macrocode} \RenewDocumentCommand\author{O{}m} { \gdef\@author{#2} \tl_gset_eq:NN\g_@@_title_author_tl\@author \keys_set:nn {hyp}{#1} } % \end{macrocode} % % Now we define the \texttt{pdfauthor} key. This is more or less % the same definition as in the generic hyperref driver. % \begin{macrocode} \keys_define:nn { hyp } { pdfauthor .code:n = { \tl_if_blank:nTF {#1} { \pdfmanagement_remove:nn {Info}{Author} } { \tl_set:Ne\l_@@_title_tmpa_tl {\clist_item:on{#1}{1}} \regex_extract_once:NVN \l_@@_title_optlang_regex \l_@@_title_tmpa_tl \l_@@_title_tmpa_seq \seq_if_empty:NTF\l_@@_title_tmpa_seq { \@@_title_pdfstring:nnN {#1}{utf16/hex}\l_@@_title_tmpa_str } { \@@_title_pdfstring:enN {\seq_item:Nn \l_@@_title_tmpa_seq{3}}{utf16/hex}\l_@@_title_tmpa_str } \str_if_eq:VnF\l_@@_title_tmpa_str{} { \pdfmanagement_add:nne {Info}{Author}{\l_@@_title_tmpa_str} } } \AddToDocumentProperties[hyperref]{pdfauthor}{#1} } } % \end{macrocode} % \subsection{Fallback for classes and packages that redefine \cs{title} or \cs{author}} % If a class redefines \cs{author} and \cs{title} again, we try to retrieve at % least the values. % \begin{macrocode} \AddToHook{cmd/maketitle/before} { \tl_gset_eq:NN \g_@@_title_author_tl\@author \tl_gset_eq:NN \g_@@_title_title_tl\@title } % \end{macrocode} % % \subsection{Finalize document} % At last we set the title and the author at the end of document % if that hasn't happened yet: % \begin{macrocode} \AddToHook{shipout/lastpage} { \tl_if_empty:eT{\GetDocumentProperties{hyperref/pdftitle}} { \group_begin: \cs_set_eq:NN\thanks \use_none:n \str_set:Ne \l_@@_title_tmpa_str {\text_purify:n { \g_@@_title_title_tl } } \keys_set:ne{hyp}{pdftitle={\exp_not:V\l_@@_title_tmpa_str}} \group_end: } \tl_if_empty:eT{\GetDocumentProperties{hyperref/pdfauthor}} { \group_begin: \cs_set_eq:NN\thanks \use_none:n \cs_set:Npn \and {,} \str_set:Ne \l_@@_title_tmpa_str {\text_purify:n { \g_@@_title_author_tl } } \keys_set:ne{hyp}{pdfauthor={\exp_not:V\l_@@_title_tmpa_str}} \group_end: } % \end{macrocode} % force display title, if an UA-standard is detected. % \begin{macrocode} \tl_if_empty:eF{\GetDocumentProperties{document/pdfstandard-UA}} { \pdfmanagement_add:nnn {Catalog / ViewerPreferences } { DisplayDocTitle } { true } } } \DeclareHookRule{shipout/lastpage}{latex-lab-testphase-title}{before}{pdfmanagement-testphase} % % \end{macrocode} % \begin{macrocode} %<*latex-lab> \ProvidesFile{title-latex-lab-testphase.ltx} [\ltlabtitledate\space v\ltlabtitleversion\space Changes related to the tagging of the title] \RequirePackage{latex-lab-testphase-title} % % \end{macrocode}