summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/hyperxmp
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2020-06-14 03:02:26 +0000
committerNorbert Preining <norbert@preining.info>2020-06-14 03:02:26 +0000
commit893b65e5d4c0b7cb8ebbfca9ee6b090b9a4a182c (patch)
treef6b0cff2cf2f8e30ef3edbfa6c7205e588e81515 /macros/latex/contrib/hyperxmp
parent2d0067edb74f15b431d7a1e3a42b4f525986cef0 (diff)
CTAN sync 202006140302
Diffstat (limited to 'macros/latex/contrib/hyperxmp')
-rw-r--r--macros/latex/contrib/hyperxmp/hyperxmp.dtx541
-rw-r--r--macros/latex/contrib/hyperxmp/hyperxmp.pdfbin1303174 -> 1326332 bytes
2 files changed, 476 insertions, 65 deletions
diff --git a/macros/latex/contrib/hyperxmp/hyperxmp.dtx b/macros/latex/contrib/hyperxmp/hyperxmp.dtx
index 1d2c332018..e4e4f52837 100644
--- a/macros/latex/contrib/hyperxmp/hyperxmp.dtx
+++ b/macros/latex/contrib/hyperxmp/hyperxmp.dtx
@@ -22,7 +22,7 @@
%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01]
%<package>\ProvidesPackage{hyperxmp}
%<*package>
- [2020/05/12 v5.2 Store hyperref metadata in XMP format]
+ [2020/06/13 v5.3 Store hyperref metadata in XMP format]
%</package>
%
%<*driver>
@@ -112,7 +112,7 @@
%</driver>
% \fi
%
-% \CheckSum{2425}
+% \CheckSum{2610}
%
% \CharacterTable
% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
@@ -169,6 +169,8 @@
% standards, as requested by Robin Schwab}
% \changes{v5.0}{2020/02/26}{Added support for \protect\acro{PDF/X}
% standards, as requested by Robin Schwab}
+% \changes{v5.0}{2020/03/17}{Don't set any document dates (creation,
+% modification, or metadata) from \string\optname{pdfdate}}
% \changes{v5.2}{2020/04/29}{Introduced the \protect\optname{pdfidentifier}
% package option, which enables an author to specify a unique identifier
% for the document}
@@ -189,6 +191,7 @@
% ^^A Define a few logical styles.
% \DeclareRobustCommand{\term}[1]{#1\SortIndex{#1}{#1}}
% \DeclareRobustCommand{\pkgname}[1]{\mbox{\textsf{#1}}\SortIndex{#1}{\textsf{#1}}}
+% \DeclareRobustCommand{\clsname}[1]{\mbox{\textsf{#1}}\SortIndex{#1}{\textsf{#1}}}
% \makeatletter
% \DeclareRobustCommand{\xmpprop}[2][]{^^A XMP property
% \def\xmppropopt{#1}^^A
@@ -1128,15 +1131,27 @@
% can include \term{Unicode} characters in its \acro{XMP} fields.
%
% \usagenote{Automatically specified metadata}
-% \optname{pdftitle} defaults to the document's title as specified by
-% |\title{|\dots|}|. \optname{pdfauthor} defaults to the document's
-% author(s) as specified by |\author{|\dots|}|. \optname{pdfdate}
-% defaults to the current date and time. \optname{pdfmetalang}
-% defaults to the same value as \optname{pdflang} if non-empty,
-% ``|x-default|'' otherwise. An implication of automatic
-% metadata specification is that an author can simply include
-% |\usepackage{hyperxmp}| in a document's preamble and benefit from
-% a modicum of \acro{XMP} metadata with no additional effort.
+% \pkgname{hyperxmp} attempts to identify certain metadata
+% automatically. The hope is that in many cases, an author can simply
+% include |\usepackage{hyperxmp}| in a document's preamble and benefit
+% from a modicum of \acro{XMP} metadata with no additional effort.
+%
+% Currently, \optname{pdftitle} defaults to the document's title as
+% specified by |\title{|\dots|}|. \optname{pdfauthor} defaults to the
+% document's author(s) as specified by |\author{|\dots|}|.
+% \optname{pdfdate} defaults to the current date and time.
+% \optname{pdfmetalang} defaults to the same value as \optname{pdflang}
+% if non-empty, ``|x-default|'' otherwise. \pkgname{hyperxmp}
+% recognizes some class-specific metadata as well, such as that provided
+% via the Koma letter classes (e.g.,~\clsname{scrlttr2}) and the
+% \acro{ACM} article class (\clsname{acmart}).
+%
+% If a document uses the \pkgname{polyglossia} package, it is
+% recommended that it \emph{not} explicitly set \optname{pdflang}.
+% \optname{pdflang} accepts only a single language name while
+% \pkgname{hyperxmp} can automatically query \pkgname{polyglossia} for a
+% list of all languages used in the document and include this list in an
+% \acro{XMP} \xmpterm{dc:language} element.
%
% \usagenote{Multilingual metadata}
% \label{note:multilingual}
@@ -1435,22 +1450,24 @@
% Thanks to Heiko Oberdiek for the bug report and suggested modifications.}
%
% \begin{macro}{\hyxmp@at@end}
-% \begin{macro}{\hyxmp@driver}
% The |\hyxmp@at@end| macro includes code at the end of the document.
-% For \pdfTeX, the standard |\AtEndDocument| works well enough. For all
-% the other backends we use |\AtEndDvi| from the \pkgname{atenddvi}
-% package, which is more robust but requires an addition \LaTeX\ run.
-% \begin{macrocode}
-\def\hyxmp@driver{hpdftex}
-\ifx\hyxmp@driver\Hy@driver
- \let\hyxmp@at@end=\AtEndDocument
-\else
+% When available (as is the case in most modern \tex\ backends),
+% \cs{AtEndDocument} works well enough. Otherwise, we invoke
+% \cs{AtEndDvi} from the \pkgname{atenddvi} package, which is robust but
+% requires an addition \LaTeX\ run.
+% \changes{v5.3}{2020/05/29}{Use \protect\cs{AtEndDocument} in all
+% \protect\tex\ back ends that provide it. Thanks to Nelson Posse
+% Lago for pointing out why \protect\pkgname{atenddvi} is best avoided
+% if possible}
+% \begin{macrocode}
+\@ifundefined{AtEndDocument}{%
\RequirePackage{atenddvi}
\let\hyxmp@at@end=\AtEndDvi
-\fi
+}{%
+ \let\hyxmp@at@end=\AtEndDocument
+}
% \end{macrocode}
% \end{macro}
-% \end{macro}
%
%
% \subsection{Integration with \textsf{hyperref}}
@@ -1504,6 +1521,20 @@
% \end{macro}
% \end{macro}
%
+% \begin{macro}{\@if@def@and@nonempty}
+% This macro combines \cs{@ifundefined} and \cs{@ifmtargexp}. If the
+% macro named |#1| is both defined and non-empty, evaluate~|#2|.
+% Otherwise, evaluate~|#3|.
+% \changes{v5.3}{2020/06/07}{Added this macro}
+% \begin{macrocode}
+\newcommand*{\@if@def@and@nonempty}[3]{%
+ \@ifundefined{#1}{#3}{%
+ \expandafter\@ifmtargexp\expandafter{\csname#1\endcsname}{#3}{#2}%
+ }%
+}
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}{\hyxmp@pdfstringdef}
% \begin{macro}{\hyxmp@textunderscore}
% Because \pkgname{hyperxmp} uses underscores to represent hard spaces,
@@ -2421,30 +2452,78 @@
% \end{macro}
% \end{macro}
%
-% Rather than load \pkgname{hyperref} ourself we let the author do it
-% then verify he actually did. This approach gives the author the
-% flexibility to load \pkgname{hyperxmp} and \pkgname{hyperref} in
-% either order and to call |\hypersetup| anywhere in the document's
-% preamble, not just before \pkgname{hyperxmp} is loaded.
+% \begin{macro}{\hyxmp@set@koma@phones}
+% \changes{v5.3}{2020/06/07}{Added this macro}
+% \begin{macro}{\hyxmp@koma@phones}
+% Define \cs{hyxmp@koma@phones} as a comma-separated list of the phone
+% numbers provided to a Koma letter class (mobile and landline).
% \begin{macrocode}
-\AtBeginDocument{%
- \@ifpackageloaded{hyperref}{%
+\newcommand*{\hyxmp@set@koma@phones}{%
+ \@if@def@and@nonempty{scr@frommobilephone@var}{%
+ \@if@def@and@nonempty{scr@fromphone@var}{%
+ \edef\hyxmp@koma@phones{\scr@frommobilephone@var,\scr@fromphone@var}%
+ }{%
+ \edef\hyxmp@koma@phones{\scr@frommobilephone@var}%
+ }%
+ }{%
+ \@if@def@and@nonempty{scr@fromphone@var}{%
+ \edef\hyxmp@koma@phones{\scr@fromphone@var}%
+ }{%
+ }%
+ }%
+}
% \end{macrocode}
-% In older versions of \pkgname{hyperref}, |\@pdflang| is set to
-% |\@empty| if \optname{pdflang} is not specified. In newer versions of
-% \pkgname{hyperref}, |\@pdflang| is set to |\relax| if
-% \optname{pdflang} is not specified. The latter is a bit problematic
-% for \pkgname{hyperxmp} because it makes |\@pdflang| non-expandable,
-% which causes a literal ``|\@pdflang|'' to be written as \acro{XMP}
-% metadata. To avoid that situation we redefine |\@pdflang| as
-% |\@empty| if we see it set to |\relax|.
-% \changes{v2.3a}{2013/04/16}{Bug fix: Redefine \cs{@pdflang} as
-% \cs{@empty} when \protect\pkgname{hyperref} has set
-% it to \cs{relax}}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@use@first@valid}
+% Given a \pkgname{hyperxmp} option~(|#1|), its current value~(|#2|),
+% and a comma-separated list of option names~(|#3|), if the current
+% value is empy, invoke \cs{hypersetup} to set the option to the first
+% non-empty item in the list. If all items in the list are empty, do
+% nothing.
+% \changes{v5.3}{2020/05/29}{Added this macro}
% \begin{macrocode}
- \ifx\@pdflang\relax
- \let\@pdflang=\@empty
+\newcommand*{\hyxmp@use@first@valid}[3]{%
+ \@ifmtargexp{#2}{%
+ \hyxmp@use@first@valid@i{#1}#3,!,%
+ }%
+ {}%
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@use@first@valid@i}
+% This macro performs all the work for \cs{hyxmp@use@first@valid}. It
+% loops over a comma-separated list of macros~(|#2|), stopping when it
+% encounters an end-of-list marker~(``|!|''). The first list element
+% that is neither undefined nor empty is assigned to a given option
+% name~(|#1|) using \cs{hypersetup}.
+% \begin{macrocode}
+\def\hyxmp@use@first@valid@i#1#2,{%
+ \def\next{\hyxmp@use@first@valid@i{#1}}%
+ \ifx#2!%
+ \let\next=\relax
+ \else
+ \ifx#2\undefined
+ \else
+ \@ifnotmtargexp{#2}{%
+ \hypersetup{#1={#2}}%
+ \def\next##1!,{}%
+ }%
\fi
+ \fi
+ \next
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@auto@assign@data}
+% If certain metadata are unspecified, try to specify meaningful values
+% using data provided by author via other means (e.g.,~\cs{title} for
+% the document's title).
+% \begin{macrocode}
+\newcommand*{\hyxmp@auto@assign@data}{%
% \end{macrocode}
% If the author explicitly specified the language to use for the
% document's metadata, we use that. If not, we use the document
@@ -2461,37 +2540,346 @@
% \protect\texttt{x-default}. This addresses a bug report by Niklas
% Beisert}
% \begin{macrocode}
- \ifx\@pdfmetalang\@empty
- \ifx\@pdflang\@empty
- \let\@pdfmetalang=\hyxmp@x@default
- \else
- \edef\@pdfmetalang{\@pdflang}%
- \fi
+ \ifx\@pdfmetalang\@empty
+ \ifx\@pdflang\@empty
+ \let\@pdfmetalang=\hyxmp@x@default
+ \else
+ \edef\@pdfmetalang{\@pdflang}%
\fi
- \hyxmp@xmlify\@pdfmetalang
+ \fi
+ \hyxmp@xmlify\@pdfmetalang
% \end{macrocode}
-% \changes{v5.0}{2020/03/17}{Don't set any document dates (creation,
-% modification, or metadata) from \string\optname{pdfdate}}
% If the author left \optname{pdftitle} blank but specified |\title|,
-% use the title for \optname{pdftitle}. Likewise, if the author left
-% \optname{pdfauthor} blank but specified |\author|, use the author for
-% \optname{pdfauthor}.
+% use the title for \optname{pdftitle}. Do likewise for various other
+% metadata: identify author-provided information that can be co-opted
+% for use as \acro{XMP} metadata.
% \changes{v2.7}{2016/02/01}{Automatically use \cs{title} and \cs{author}
% if \protect\optname{pdftitle} and \protect\optname{pdfauthor} are left
% unspecified. Thanks to Maciej Radziejewski for the suggestion}
+% \changes{v5.3}{2020/05/29}{Consider other author-provided sources of
+% metadata. Thanks to Robin Schwab for proposing that
+% \protect\pkgname{hyperxmp} use the Koma letter classes's metadata}
% \begin{macrocode}
- \@ifmtargexp{\@pdftitle}{%
- \@ifnotmtargexp{\@title}{%
- \hypersetup{pdftitle={\@title}}%
+ \hyxmp@use@first@valid{pdftitle}{\@pdftitle}{%
+ \scr@subject@var,%
+ \@title
+ }%
+ \hyxmp@use@first@valid{pdfauthor}{\@pdfauthor}{%
+ \scr@fromname@var,%
+ \@author
+ }%
+ \hyxmp@use@first@valid{pdfcontactemail}{\@pdfcontactemail}{%
+ \scr@fromemail@var
+ }%
+ \hyxmp@set@koma@phones
+ \hyxmp@use@first@valid{pdfcontactphone}{\@pdfcontactphone}{%
+ \hyxmp@koma@phones
+ }%
+ \hyxmp@use@first@valid{pdfcontacturl}{\@pdfcontacturl}{%
+ \scr@fromurl@var
+ }%
+ \hyxmp@use@first@valid{pdfsubtitle}{\@pdfsubtitle}{%
+ \@subtitle
+ }%
+ \hyxmp@use@first@valid{pdfpublisher}{\@pdfpublisher}{%
+ \@publishers
+ }%
+% \end{macrocode}
+% We handle the \clsname{acmart} class specially. \clsname{acmart}
+% stores author-provided contact information in a structured format that
+% we can process fairly easily. Note that if the author is not using
+% the \clsname{acmart} class, \cs{hyxmp@parse@acmart} will have been
+% redefined to do nothing.
+% \begin{macrocode}
+ \hyxmp@parse@acmart
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@parse@acmart}
+% The \clsname{acmart} class stores a rich set of author metadata in its
+% \cs{addresses} macro. \cs{hyxmp@parse@acmart} extracts the contact
+% information for the first author and converts that to \acro{XMP}
+% metadata.
+% \changes{v5.3}{2020/05/30}{Added this macro}
+% \begin{macrocode}
+\newcommand*{\hyxmp@parse@acmart}{%
+ \begingroup
+% \end{macrocode}
+% \begin{macro}{\@author}
+% \clsname{acmart} has already invoked
+% |\hypersetup{pdfauthor=|\dots|}| to specify the complete list of
+% authors. At this point, |\@author| is defined to produce a warning
+% message. We locally redefine it to do nothing.
+% \begin{macrocode}
+ \let\@author=\@gobble
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\email}
+% \begin{macro}{\hyxmp@address@val}
+% Within \cs{addresses}, \cs{email} is defined to accept two arguments,
+% the second of which is the author's email address.
+% \begin{macrocode}
+ \def\email##1##2{%
+ \def\hyxmp@address@val{##2}%
+ \hyxmp@use@first@valid{pdfcontactemail}{\@pdfcontactemail}{%
+ \hyxmp@address@val
}%
}%
- {}%
- \@ifmtargexp{\@pdfauthor}{%
- \@ifnotmtargexp{\@author}{%
- \hypersetup{pdfauthor={\@author}}%
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\streetaddress}
+% \begin{macro}{\hyxmp@address@val}
+% \cs{streetaddress} wraps the author's street address.
+% \begin{macrocode}
+ \def\streetaddress##1{%
+ \def\hyxmp@address@val{##1}%
+ \hyxmp@use@first@valid{pdfcontactaddress}{\@pdfcontactaddress}{%
+ \hyxmp@address@val
}%
}%
- {}%
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\city}
+% \begin{macro}{\hyxmp@address@val}
+% \cs{city} wraps the author's city name.
+% \begin{macrocode}
+ \def\city##1{%
+ \def\hyxmp@address@val{##1}%
+ \hyxmp@use@first@valid{pdfcontactcity}{\@pdfcontactcity}{%
+ \hyxmp@address@val
+ }%
+ }%
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\state}
+% \begin{macro}{\hyxmp@address@val}
+% \cs{state} wraps the author's state or region name.
+% \begin{macrocode}
+ \def\state##1{%
+ \def\hyxmp@address@val{##1}%
+ \hyxmp@use@first@valid{pdfcontactregion}{\@pdfcontactregion}{%
+ \hyxmp@address@val
+ }%
+ }%
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\country}
+% \begin{macro}{\hyxmp@address@val}
+% \cs{country} wraps the author's country name.
+% \begin{macrocode}
+ \def\country##1{%
+ \def\hyxmp@address@val{##1}%
+ \hyxmp@use@first@valid{pdfcontactcountry}{\@pdfcontactcountry}{%
+ \hyxmp@address@val
+ }%
+ }%
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\postcode}
+% \begin{macro}{\hyxmp@address@val}
+% \cs{postcode} wraps the author's postal code.
+% \begin{macrocode}
+ \def\postcode##1{%
+ \def\hyxmp@address@val{##1}%
+ \hyxmp@use@first@valid{pdfcontactpostcode}{\@pdfcontactpostcode}{%
+ \hyxmp@address@val
+ }%
+ }%
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\affiliation}
+% We want to produce \acro{XMP} metadata for only a single affiliation.
+% Although \cs{hyxmp@use@first@valid} will ensure that only the first
+% email, city, country, etc.\ encountered is considered, we run the
+% first of one affiliation defining, say, a city and state but no
+% country and a subsequent affiliation defining a country. In that
+% case, the \acro{XMP} would include the first author's city and state
+% and the subsequent author's country. Hence, we define
+% \cs{affiliation} to ``self destruct'' after its first use, discarding
+% all further affiliations.
+% \begin{macrocode}
+ \def\affiliation##1##2{%
+ ##2%
+ \let\affiliation=\@gobbletwo
+ }%
+% \end{macrocode}
+% \end{macro}
+%
+% We want to evaluate \cs{addresses} with the preceding local
+% definitions in effect, but we don't want to typeset any text appearing
+% in the string. Hence, we ``typeset'' \cs{addresses} within a box that
+% is subsequently discarded.
+% \begin{macrocode}
+ \setbox0=\hbox{\addresses}%
+ \endgroup
+% \end{macrocode}
+%
+% \clsname{acmart} supports other relevant metadata in addition to the
+% authors' mailing addresses. For instance, papers accepted for
+% publication indicate their \acro{DOI} number. However, papers under
+% review will contain either a placeholder \acro{DOI},
+% ``10.1145/nnnnnnn.nnnnnnn'', or the example \acro{DOI} specified in
+% the \clsname{acmart} example document, ``10.1145/1122445.1122456''.
+% We ignore both of those \acro{DOI}s.
+% \begin{macrocode}
+ \@if@def@and@nonempty{@acmDOI}{%
+ \IfSubStr{\@acmDOI}{10.1145/1122445.1122456}{}{%
+ \IfSubStr{\@acmDOI}{10.1145/nnnnnnn.nnnnnnn}{}{%
+ \hyxmp@use@first@valid{pdfdoi}{\@pdfdoi}{%
+ \@acmDOI
+ }%
+ }%
+ }%
+ }%
+% \end{macrocode}
+% \begin{macro}{\hyxmp@strip@isbn@date}
+% \begin{macro}{\hyxmp@acm@isbn}
+% Papers appearing in conference proceedings specify the proceedings'
+% \acro{ISBN}. As with \cs{@acmDOI} above, we ignore both the
+% placeholder \acro{ISBN}, ``978-x-xxxx-xxxx-x/YY/MM'', and the example
+% \acro{ISBN}, ``978-1-4503-XXXX-X/18/06''. We also strip off the
+% ``\texttt{/}\meta{year}\texttt{/}\meta{month}'' suffix so as to
+% include a true \acro{ISBN} in the \acro{XMP} metadata.
+% \begin{macrocode}
+ \@if@def@and@nonempty{@acmISBN}{%
+ \IfSubStr{\@acmISBN}{XXXX}{}{%
+ \IfSubStr{\@acmISBN}{xxxx}{}{%
+ \def\hyxmp@strip@isbn@date##1/##2!{##1}%
+ \edef\hyxmp@acm@isbn{%
+ \expandafter\hyxmp@strip@isbn@date\@acmISBN/!%
+ }%
+ \hyxmp@use@first@valid{pdfisbn}{\@pdfisbn}{%
+ \hyxmp@acm@isbn
+ }%
+ }%
+ }%
+ }%
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\hyxmp@acm@publisher}
+% The publisher is of course \acro{ACM}.
+% \begin{macrocode}
+ \def\hyxmp@acm@publisher{Association for Computing Machinery}%
+ \hyxmp@use@first@valid{pdfpublisher}{\@pdfpublisher}{%
+ \hyxmp@acm@publisher
+ }%
+% \end{macrocode}
+% Use the journal name if defined, otherwise the book name (for
+% conference proceedings).
+% \begin{macrocode}
+ \hyxmp@use@first@valid{pdfpublication}{\@pdfpublication}{%
+ \@journalName,%
+ \@acmBooktitle,%
+ \@acmConference
+ }%
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\hyxmp@acm@pubtype}
+% \clsname{acmart} makes clear whether it's typesetting a journal
+% article. If it's not a journal, we assume it's a book (conference
+% proceedings).
+% \begin{macrocode}
+ \if@ACM@journal
+ \def\hyxmp@acm@pubtype{journal}%
+ \else
+ \def\hyxmp@acm@pubtype{book}%
+ \fi
+ \hyxmp@use@first@valid{pdfpubtype}{\@pdfpubtype}{%
+ \hyxmp@acm@pubtype
+ }%
+% \end{macrocode}
+% \end{macro}
+% Journal articles have a volume and issue number.
+% \begin{macrocode}
+ \hyxmp@use@first@valid{pdfvolumenum}{\@pdfvolumenum}{%
+ \@acmVolume
+ }%
+ \hyxmp@use@first@valid{pdfissuenum}{\@pdfissuenum}{%
+ \@acmNumber
+ }%
+}
+% \end{macrocode}
+% \end{macro}
+%
+% Nullify \cs{hyxmp@parse@acmart} if the author is not using the
+% \clsname{acmart} class.
+% \begin{macrocode}
+\@ifclassloaded{acmart}{}{\let\hyxmp@parse@acmart=\relax}
+% \end{macrocode}
+%
+% \begin{macro}{\hyxmp@set@dc@lang}
+% \begin{macro}{\hyxmp@dc@lang}
+% \cs{@pdflang} is used in both the \acro{PDF} document catalog (the
+% \pdfterm{Lang} key, written to the \acro{PDF} file by
+% \pkgname{hyperref}) and in the Dublin Core \xmpterm{dc:language} tag
+% (Section~\ref{sec:dublin-core}). Normally, these are the same.
+% However, \pdfterm{Lang} accepts only a single language while
+% \xmpterm{dc:language} accepts multiple languages. If the document
+% loads \pkgname{polyglossia} and does not specify \optname{pdflang} in
+% \cs{hypersetup}, \cs{hyxmp@set@dc@lang} is redefined below to set
+% \cs{hyxmp@dc@lang} to \pkgname{polyglossia}'s list of used languages
+% (once this is known). Otherwise, \cs{hyxmp@set@dc@lang} assigns the
+% language specified by \optname{pdflang} (if any) to
+% \cs{hyxmp@dc@lang}.
+% \begin{macrocode}
+\newcommand*{\hyxmp@set@dc@lang}{%
+ \let\hyxmp@dc@lang=\@pdflang
+}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% Rather than load \pkgname{hyperref} ourself we let the author do it
+% then verify he actually did. This approach gives the author the
+% flexibility to load \pkgname{hyperxmp} and \pkgname{hyperref} in
+% either order and to call |\hypersetup| anywhere in the document's
+% preamble, not just before \pkgname{hyperxmp} is loaded.
+% \begin{macrocode}
+\AtEndPreamble{%
+ \@ifpackageloaded{hyperref}{%
+% \end{macrocode}
+% In older versions of \pkgname{hyperref}, \cs{@pdflang} is set to
+% \cs{@empty} if \optname{pdflang} is not specified. In newer versions
+% of \pkgname{hyperref}, \cs{@pdflang} is set to \cs{relax} if
+% \optname{pdflang} is not specified. The latter is a bit problematic
+% for \pkgname{hyperxmp} because it makes \cs{@pdflang} non-expandable,
+% which causes a literal ``\cs{@pdflang}'' to be written as \acro{XMP}
+% metadata. To avoid that situation we redefine \cs{@pdflang} as
+% \cs{@empty} if we see it set to \cs{relax}. Actually, we first check
+% if the \pkgname{polyglossia} package has specified the document's main
+% language in \cs{mainbcp47id}. If so, we use that instead of
+% \cs{@empty} and redefine \cs{hyxmp@set@dc@lang} to consider
+% \pkgname{polyglossia}'s list of used languages.
+% \changes{v2.3a}{2013/04/16}{Bug fix: Redefine \cs{@pdflang} as
+% \cs{@empty} when \protect\pkgname{hyperref} has set
+% it to \cs{relax}}
+% \changes{v5.3}{2020/06/08}{Acquire the default language from the
+% \protect\pkgname{polyglossia} package, if loaded. Thanks to
+% Robin Schwab for bringing that package to my attention}
+% \begin{macrocode}
+ \ifx\@pdflang\relax
+ \@ifundefined{mainbcp47id}{%
+ \let\@pdflang=\@empty
+ }{%
+ \xdef\@pdflang{\csname mainbcp47id\endcsname}%
+ \renewcommand*{\hyxmp@set@dc@lang}{%
+ \edef\hyxmp@dc@lang{\xpg@bcp@loaded}%
+ }%
+ }%
+ \fi
+% \end{macrocode}
+% Fill in any missing metadata we can using values provided by the author
+% via mechanisms other than the \cs{hypersetup} command.
+% \begin{macrocode}
+ \hyxmp@auto@assign@data
% \end{macrocode}
% Most \acro{PDF} standards dictate that if the same metadata appear in
% both the \acro{XMP} packet and the \acro{PDF} \pdfterm{Info}
@@ -2550,6 +2938,19 @@
}
% \end{macrocode}
%
+% A number of classes either require or recommend that authors declare
+% various class-specific metadata \emph{after} the |\begin{document}|.
+% So where do we invoke \cs{hyxmp@auto@assign@data}? On one hand, we
+% want to invoke it before the |\begin{document}| because this may
+% obviate \pkgname{hyperxmp}'s ``\meta{job name} did not specify any
+% metadata'' warning message. On the other hand, we want to invoke it
+% after the |\begin{document}| so it picks up metadata not specified in
+% the preamble. Our solution is to invoke \cs{hyxmp@auto@assign@data}
+% twice: both before the |\begin{document}| at at the |\end{document}|.
+% \begin{macrocode}
+\hyxmp@at@end{\hyxmp@auto@assign@data}
+% \end{macrocode}
+%
%
% \subsection{Manipulating author-supplied data}
%
@@ -4436,7 +4837,7 @@ ______</dc:#2>^^J%
% \changes{v4.1}{2019/04/05}{Added this macro}
% \begin{macrocode}
\newcommand{\hyxmp@singleton@dc}[3][Bag]{%
- \@ifnotmtarg{#3}{%
+ \@ifnotmtargexp{#3}{%
\hyxmp@xmlify{#3}%
\hyxmp@add@to@xml{%
______<dc:#2>^^J%
@@ -4498,7 +4899,6 @@ ______</dc:#2>^^J%
\hyxmp@rdf@dc{rights}{\@pdfcopyright}%
\hyxmp@singleton@dc{publisher}{\@pdfpublisher}%
\hyxmp@singleton@dc[Seq]{date}{\hyxmp@today@xmp}%
- \hyxmp@singleton@dc{language}{\@pdflang}%
\hyxmp@singleton@dc{type}{\@pdftype}%
\hyxmp@list@to@xml[\ifHy@pdfa]{creator}{Seq}{\hyxmp@pdfauthor}%
\hyxmp@list@to@xml{subject}{Bag}{\hyxmp@pdfkeywords}%
@@ -4507,6 +4907,17 @@ ______</dc:#2>^^J%
\hyxmp@add@simple{dc:source}{\@pdfsource}%
\fi
% \end{macrocode}
+% Set \cs{hyxmp@dc@lang} to either the single language \cs{@pdflang}
+% (which may be unspecified) or to a list of languages used in the
+% document via \pkgname{polyglossia}. See
+% Section~\ref{sec:hyperref-int} for the definition of
+% \cs{hyxmp@set@dc@lang}.
+% \changes{v5.3}{2020/06/13}{Include all languages used in the document
+% in \protect\xmpterm{dc:language}}
+% \begin{macrocode}
+ \hyxmp@set@dc@lang
+ \hyxmp@list@to@xml{language}{Bag}{\hyxmp@dc@lang}%
+% \end{macrocode}
% If |\@pdfidentifier| is empty, try setting it to each of |\@pdfdoi|,
% |\@pdfeissn|, |\@pdfissn|, and |\@pdfisbn|, in turn, with proper
% syntactic adjustments.
@@ -4777,7 +5188,7 @@ ______</dc:#2>^^J%
%
% \begin{macro}{\hyxmp@list@to@lines}
% Given a property~(|#1|) and a macro containing a comma-separated
-% list~(|#2|), replace commas with |\xmplinesep|. Do nothing it the
+% list~(|#2|), replace commas with |\xmplinesep|. Do nothing if the
% list is empty.
% \changes{v2.2}{2012/12/07}{Added this macro}
% \begin{macrocode}
diff --git a/macros/latex/contrib/hyperxmp/hyperxmp.pdf b/macros/latex/contrib/hyperxmp/hyperxmp.pdf
index 01425c6e03..28b08b0787 100644
--- a/macros/latex/contrib/hyperxmp/hyperxmp.pdf
+++ b/macros/latex/contrib/hyperxmp/hyperxmp.pdf
Binary files differ