% \iffalse meta-comment % %% File: ltmeta.dtx %% Copyright (C) 2021-2026 %% Frank Mittelbach, 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 % % %%% From File: ltmeta.dtx %<*driver> % \fi \ProvidesFile{ltmeta.dtx} [2026-05-06 v1.0f LaTeX Kernel (Document Metadata)] % \iffalse % \documentclass{l3in2edoc} \GetFileInfo{ltmeta.dtx} \EnableCrossrefs \CodelineIndex \begin{document} \DocInput{ltmeta.dtx} \end{document} % % % \fi % % \providecommand\hook[1]{\texttt{#1}} % \providecommand\env[1]{\texttt{#1}} % % % % \title{The \texttt{ltmeta.dtx} code\thanks{This file has version % \fileversion\ dated \filedate, \copyright\ \LaTeX\ % Project.}} % \author{Frank Mittelbach} % % \maketitle % % % \begin{abstract} % This code defines the \cs{DocumentMetadata} interface. % \end{abstract} % % \tableofcontents % % % \section{Introduction} % % % In the past there was no dedicated location to declare settings % concerning a document as a whole. Settings are placed somewhere % in the preamble or with the class options or even with some % package options. For some settings this can be too late, for % example the pdf version can no longer be changed if a package has % used code which already opened the PDF. % % \cs{DocumentMetadata} as a new command unifies such settings in % one place. It must be used before \cs{documentclass} but can be % issued more than once there. % % At the moment most of the code run by \cs{DocumentMetadata} is % external to the format and subject to change. This includes the % supported key/values. % % For that reason all that happens right now in the format is to % look for suitable support files and if found, to redirect the % processing to them. % % \subsection{\cs{DocumentMetadata}} % % \begin{function}{\DocumentMetadata} % \begin{syntax} % \cs{DocumentMetadata}\Arg{key-value list} % \end{syntax} % \end{function} % % % % The keys defined for \cs{DocumentMetadata} % currently allow to set the PDF version, to set the PDF \texttt{/Lang}, % to uncompress a PDF, to set the language and to declare a few PDF standards % and some color profiles. % % \cs{DocumentMetadata} is also used to % activate the new PDF management code and it loads % a number of required files for the PDF management code. % As this forces the loading of the backend files, a backend % which can't be detected automatically like |dvipdfmx|, % must be set in the first \cs{DocumentMetadata} call (if there is more than one). % % The full set of keys currently supported is documented in \texttt{documentmetadata-support.pdf} % for now. % % % \StopEventually{\setlength\IndexMin{200pt} \PrintIndex } % % % \section{The Implementation} % % % % \begin{macrocode} %<*2ekernel|latexrelease> % \end{macrocode} % Not needed yet but \ldots % \begin{macrocode} %\ExplSyntaxOn % \end{macrocode} % % \begin{macrocode} %\NewModuleRelease{2022/06/01}{ltmeta} % {Document Metadata handling} % \end{macrocode} % We start by making the conditionals testing for the use of % \cs{DocumentMetadata} execute the the false branch. Then, inside % \cs{DocumentMetadata}, we change them to select the true branch. % \changes{v1.0d}{2025/03/01}{Provide T F variants of % \cs{IfDocumentMetadataTF} (gh/1522)} % \begin{macrocode} \let \IfDocumentMetadataTF \@secondoftwo \let \IfDocumentMetadataT \@gobble \let \IfDocumentMetadataF \@firstofone \protected\def\DocumentMetadata{% \InputIfFileExists{documentmetadata-support.ltx}% {% % \end{macrocode} % Support for \cs{DocumentMetadata} is available, so change the conditionals. % \begin{macrocode} \let \IfDocumentMetadataTF \@firstoftwo \let \IfDocumentMetadataT \@firstofone \let \IfDocumentMetadataF \@gobble }% % \end{macrocode} % The above file is changing \cs{DocumentMetadata} to a suitable % definition (or so we hope) so that it can be safely used several times % in the premable. % % If the file can't be found we say so and carry on without it. % \begin{macrocode} {% \@latex@error{No support files for \noexpand\DocumentMetadata found} {Is the 'LaTeX-lab' bundle installed?% \MessageBreak Without it, the declaration is ignored.}% % \end{macrocode} % No point in trying this more than once if there are several calls % in the document. % \begin{macrocode} \let\DocumentMetadata\@gobble }% \DocumentMetadata } % \end{macrocode} % % To allow package and class author to support for document links % we provide also the new interface commands of the hyperref package % for the creation of targets. % The commands are not only useful for document links: % When tagging is active the commands can also be used to reference structures. % This is done in the \texttt{recordtarget} socket, which records the target name. % Both for links and structure references it can be useful to change the name of the % next target. We therefore insert a hook \texttt{target/setname/after} after the name % has be set. This hook is used in the \cs{NextLinkTarget} command to adapt the target name % \cs{@currentHref}. % \changes{v1.0b}{2022/05/17}{Default definition for targets added} % \changes{v1.0c}{2024/09/21}{Added tagging support} % \changes{v1.0e}{2026/04/22}{Add hook to change target name and use it in \cs{NextLinkTarget}} % \changes{v1.0f}{2026/05/06}{Add \cs{SaveLastSkip} and \cs{RestoreLastSkip} to better mimic % hyperref's spacing behavior, gh/2070} % \changes{v1.0f}{2026/05/06}{Use \cs{latelua} to mimic a whatsit to avoid spurious warning, gh/2070} % \begin{macro}{\MakeLinkTarget} % \begin{macro}{\LinkTargetOn} % \begin{macro}{\LinkTargetOff} % \begin{macro}{\NextLinkTarget} % \begin{macrocode} %\IncludeInRelease{2026/06/01}% % {\MakeLinkTarget}{Record target name for tagging support}% \ExplSyntaxOn % \end{macrocode} % luatex complains about non-PDF specials if \cs{special} is used, so we use \cs{latelua} instead % to create an empty whatsit node. % \begin{macrocode} \ifx\directlua\@undefined \def\@kernel@whatsit{\special{}} \else \def\@kernel@whatsit{\latelua{}} \fi % \end{macrocode} % This definition is copied from \pkg{hyperref}, only the command names are changed. It is the code % \pkg{hyperref} uses around anchors/destination to avoid that they affect the spacing. % \begin{macrocode} \let\RestoreLastSkip\relax \def\SaveLastSkip{% \let\RestoreLastSkip\relax \ifvmode \ifdim\lastskip=\z@ \ifnum\lastnodetype=11 % \let\RestoreLastSkip\nobreak \else \let\RestoreLastSkip\relax \fi \else \begingroup \skip@=-\lastskip \edef\x{% \endgroup \def\noexpand\RestoreLastSkip{% \noexpand\ifvmode \noexpand\nobreak \vskip\the\skip@ \vskip\the\lastskip\relax \noexpand\fi }% }% \x \fi \else \ifhmode \ifdim\lastskip=\z@ \let\RestoreLastSkip\nobreak \else \begingroup \skip@=-\lastskip \edef\x{% \endgroup \def\noexpand\RestoreLastSkip{% \noexpand\ifhmode \noexpand\nobreak \hskip\the\skip@ \hskip\the\lastskip\relax \noexpand\fi }% }% \x \fi \fi \fi } \hook_new:n{target/setname/after} \int_new:N\g__kernel_target_int \NewDocumentCommand\MakeLinkTarget{sO{}m}{% \ifvmode \SaveLastSkip\@kernel@whatsit\RestoreLastSkip \else \@savsf\spacefactor \SaveLastSkip\smash{}\RestoreLastSkip \spacefactor\@savsf \fi \IfBooleanTF {#1} { \tl_gset:Ne \@currentHref {#3} } { \int_gincr:N\g__kernel_target_int \tl_gset:Ne \@currentHref {target*.\int_use:N\g__kernel_target_int} } \hook_use:n{target/setname/after} \UseTaggingSocket{recordtarget} } \ExplSyntaxOff %\EndIncludeInRelease %\IncludeInRelease{2024/11/01}% % {\MakeLinkTarget}{Record target name for tagging support}% %\ExplSyntaxOn %\NewDocumentCommand\MakeLinkTarget{sO{}m}{% % \ifvmode % \special{}% % \else % \@savsf\spacefactor % \smash{}% % \spacefactor\@savsf % \fi % \IfBooleanTF {#1} % { % \tl_gset:Ne \@currentHref {#3} % } % { % \int_gincr:N\g__kernel_target_int % \tl_gset:Ne \@currentHref {target*.\int_use:N\g__kernel_target_int} % } % \hook_use:n{target/setname/after} % \UseTaggingSocket{recordtarget} % } %\ExplSyntaxOff %\EndIncludeInRelease %\IncludeInRelease{2022/06/01}% % {\MakeLinkTarget}{Record target name for tagging support}% %\NewDocumentCommand\MakeLinkTarget{sO{}m}{% % \ifvmode % \special{}% % \else % \@savsf\spacefactor % \smash{}% % \spacefactor\@savsf % \fi} %\EndIncludeInRelease \NewDocumentCommand\LinkTargetOn{}{} \NewDocumentCommand\LinkTargetOff{}{} \NewDocumentCommand\NextLinkTarget{m}{% \AddToHookNext{target/setname/after}{\xdef\@currentHref {#1}}} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % We do not undo \cs{MakeLinkTarget} and friends if we roll back, in % case they are used in packages that themselves do not offer % rollback. This way a roll forward adds them, but the dummies remain % if you roll back and you don't get missing csname errors if they % are used. % \begin{macrocode} %\IncludeInRelease{0000/00/00}{ltmeta}% % {Undo Document Metadata handling} % %\let\DocumentMetadata\@undefined % %\EndModuleRelease % \end{macrocode} % Again for the future \ldots % \begin{macrocode} %\ExplSyntaxOff % \end{macrocode} % \begin{macrocode} % % \end{macrocode} % % Restore module prefix (if any): % \begin{macrocode} %<@@=> % \end{macrocode} % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \endinput %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %