texlive[55549] Master/texmf-dist: hyperxmp (15jun20)

commits+karl at tug.org commits+karl at tug.org
Mon Jun 15 00:18:02 CEST 2020


Revision: 55549
          http://tug.org/svn/texlive?view=revision&revision=55549
Author:   karl
Date:     2020-06-15 00:18:02 +0200 (Mon, 15 Jun 2020)
Log Message:
-----------
hyperxmp (15jun20)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/latex/hyperxmp/hyperxmp.pdf
    trunk/Master/texmf-dist/source/latex/hyperxmp/hyperxmp.dtx
    trunk/Master/texmf-dist/tex/latex/hyperxmp/hyperxmp.sty

Modified: trunk/Master/texmf-dist/doc/latex/hyperxmp/hyperxmp.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/source/latex/hyperxmp/hyperxmp.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/hyperxmp/hyperxmp.dtx	2020-06-14 22:17:46 UTC (rev 55548)
+++ trunk/Master/texmf-dist/source/latex/hyperxmp/hyperxmp.dtx	2020-06-14 22:18:02 UTC (rev 55549)
@@ -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,16 +1131,28 @@
 % 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}
 % The \optname{pdfmetalang} option specifies the language in which the
@@ -1435,22 +1450,24 @@
 %   Thanks to Heiko Oberdiek for the bug report and suggested modifications.}
 %
 % \begin{macro}{\hyxmp at at@end}
-% \begin{macro}{\hyxmp at driver}
 % The |\hyxmp at 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.
+% 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}
-\def\hyxmp at driver{hpdftex}
-\ifx\hyxmp at driver\Hy at driver
-  \let\hyxmp at at@end=\AtEndDocument
-\else
+\@ifundefined{AtEndDocument}{%
   \RequirePackage{atenddvi}
   \let\hyxmp at at@end=\AtEndDvi
-\fi
+}{%
+  \let\hyxmp at 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 at def@and at 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 at def@and at nonempty}[3]{%
+  \@ifundefined{#1}{#3}{%
+    \expandafter\@ifmtargexp\expandafter{\csname#1\endcsname}{#3}{#2}%
+  }%
+}
+%    \end{macrocode}
+% \end{macro}
+%
 % \begin{macro}{\hyxmp at pdfstringdef}
 % \begin{macro}{\hyxmp at textunderscore}
 % Because \pkgname{hyperxmp} uses underscores to represent hard spaces,
@@ -2421,31 +2452,79 @@
 % \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 at set@koma at phones}
+% \changes{v5.3}{2020/06/07}{Added this macro}
+% \begin{macro}{\hyxmp at koma@phones}
+% Define \cs{hyxmp at 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 at set@koma at phones}{%
+  \@if at def@and at nonempty{scr at frommobilephone@var}{%
+    \@if at def@and at nonempty{scr at fromphone@var}{%
+      \edef\hyxmp at koma@phones{\scr at frommobilephone@var,\scr at fromphone@var}%
+    }{%
+      \edef\hyxmp at koma@phones{\scr at frommobilephone@var}%
+    }%
+  }{%
+    \@if at def@and at nonempty{scr at fromphone@var}{%
+      \edef\hyxmp at koma@phones{\scr at 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 at use@first at 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 at use@first at valid}[3]{%
+  \@ifmtargexp{#2}{%
+    \hyxmp at use@first at valid@i{#1}#3,!,%
+  }%
+  {}%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp at use@first at valid@i}
+% This macro performs all the work for \cs{hyxmp at use@first at 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 at use@first at valid@i#1#2,{%
+  \def\next{\hyxmp at use@first at 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 at auto@assign at 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 at auto@assign at 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
 % language, specified to \pkgname{hyperref} with the \protect\optname{pdflang}
@@ -2461,38 +2540,347 @@
 %   \protect\texttt{x-default}.  This addresses a bug report by Niklas
 %   Beisert}
 %    \begin{macrocode}
-    \ifx\@pdfmetalang\@empty
-      \ifx\@pdflang\@empty
-        \let\@pdfmetalang=\hyxmp at x@default
-      \else
-        \edef\@pdfmetalang{\@pdflang}%
-      \fi
+  \ifx\@pdfmetalang\@empty
+    \ifx\@pdflang\@empty
+      \let\@pdfmetalang=\hyxmp at x@default
+    \else
+      \edef\@pdfmetalang{\@pdflang}%
     \fi
-    \hyxmp at xmlify\@pdfmetalang
+  \fi
+  \hyxmp at 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 at use@first at valid{pdftitle}{\@pdftitle}{%
+    \scr at subject@var,%
+    \@title
+  }%
+  \hyxmp at use@first at valid{pdfauthor}{\@pdfauthor}{%
+    \scr at fromname@var,%
+    \@author
+  }%
+  \hyxmp at use@first at valid{pdfcontactemail}{\@pdfcontactemail}{%
+    \scr at fromemail@var
+  }%
+  \hyxmp at set@koma at phones
+  \hyxmp at use@first at valid{pdfcontactphone}{\@pdfcontactphone}{%
+    \hyxmp at koma@phones
+  }%
+  \hyxmp at use@first at valid{pdfcontacturl}{\@pdfcontacturl}{%
+    \scr at fromurl@var
+  }%
+  \hyxmp at use@first at valid{pdfsubtitle}{\@pdfsubtitle}{%
+    \@subtitle
+  }%
+  \hyxmp at use@first at 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 at parse@acmart} will have been
+% redefined to do nothing.
+%    \begin{macrocode}
+  \hyxmp at parse@acmart
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp at parse@acmart}
+% The \clsname{acmart} class stores a rich set of author metadata in its
+% \cs{addresses} macro.  \cs{hyxmp at 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 at 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 at 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 at address@val{##2}%
+      \hyxmp at use@first at valid{pdfcontactemail}{\@pdfcontactemail}{%
+        \hyxmp at address@val
       }%
     }%
-    {}%
-    \@ifmtargexp{\@pdfauthor}{%
-      \@ifnotmtargexp{\@author}{%
-        \hypersetup{pdfauthor={\@author}}%
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\streetaddress}
+% \begin{macro}{\hyxmp at address@val}
+% \cs{streetaddress} wraps the author's street address.
+%    \begin{macrocode}
+    \def\streetaddress##1{%
+      \def\hyxmp at address@val{##1}%
+      \hyxmp at use@first at valid{pdfcontactaddress}{\@pdfcontactaddress}{%
+        \hyxmp at address@val
       }%
     }%
-    {}%
 %    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\city}
+% \begin{macro}{\hyxmp at address@val}
+% \cs{city} wraps the author's city name.
+%    \begin{macrocode}
+    \def\city##1{%
+      \def\hyxmp at address@val{##1}%
+      \hyxmp at use@first at valid{pdfcontactcity}{\@pdfcontactcity}{%
+        \hyxmp at address@val
+      }%
+    }%
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\state}
+% \begin{macro}{\hyxmp at address@val}
+% \cs{state} wraps the author's state or region name.
+%    \begin{macrocode}
+    \def\state##1{%
+      \def\hyxmp at address@val{##1}%
+      \hyxmp at use@first at valid{pdfcontactregion}{\@pdfcontactregion}{%
+        \hyxmp at address@val
+      }%
+    }%
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\country}
+% \begin{macro}{\hyxmp at address@val}
+% \cs{country} wraps the author's country name.
+%    \begin{macrocode}
+    \def\country##1{%
+      \def\hyxmp at address@val{##1}%
+      \hyxmp at use@first at valid{pdfcontactcountry}{\@pdfcontactcountry}{%
+        \hyxmp at address@val
+      }%
+    }%
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\postcode}
+% \begin{macro}{\hyxmp at address@val}
+% \cs{postcode} wraps the author's postal code.
+%    \begin{macrocode}
+    \def\postcode##1{%
+      \def\hyxmp at address@val{##1}%
+      \hyxmp at use@first at valid{pdfcontactpostcode}{\@pdfcontactpostcode}{%
+        \hyxmp at 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 at use@first at 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 at def@and at nonempty{@acmDOI}{%
+    \IfSubStr{\@acmDOI}{10.1145/1122445.1122456}{}{%
+      \IfSubStr{\@acmDOI}{10.1145/nnnnnnn.nnnnnnn}{}{%
+        \hyxmp at use@first at valid{pdfdoi}{\@pdfdoi}{%
+          \@acmDOI
+        }%
+      }%
+    }%
+  }%
+%    \end{macrocode}
+% \begin{macro}{\hyxmp at strip@isbn at date}
+% \begin{macro}{\hyxmp at 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 at def@and at nonempty{@acmISBN}{%
+    \IfSubStr{\@acmISBN}{XXXX}{}{%
+      \IfSubStr{\@acmISBN}{xxxx}{}{%
+        \def\hyxmp at strip@isbn at date##1/##2!{##1}%
+        \edef\hyxmp at acm@isbn{%
+          \expandafter\hyxmp at strip@isbn at date\@acmISBN/!%
+        }%
+        \hyxmp at use@first at valid{pdfisbn}{\@pdfisbn}{%
+          \hyxmp at acm@isbn
+        }%
+      }%
+    }%
+  }%
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\hyxmp at acm@publisher}
+% The publisher is of course \acro{ACM}.
+%    \begin{macrocode}
+  \def\hyxmp at acm@publisher{Association for Computing Machinery}%
+  \hyxmp at use@first at valid{pdfpublisher}{\@pdfpublisher}{%
+    \hyxmp at acm@publisher
+  }%
+%    \end{macrocode}
+% Use the journal name if defined, otherwise the book name (for
+% conference proceedings).
+%    \begin{macrocode}
+  \hyxmp at use@first at valid{pdfpublication}{\@pdfpublication}{%
+    \@journalName,%
+    \@acmBooktitle,%
+    \@acmConference
+  }%
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{\hyxmp at 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 at ACM@journal
+    \def\hyxmp at acm@pubtype{journal}%
+  \else
+    \def\hyxmp at acm@pubtype{book}%
+  \fi
+  \hyxmp at use@first at valid{pdfpubtype}{\@pdfpubtype}{%
+    \hyxmp at acm@pubtype
+  }%
+%    \end{macrocode}
+% \end{macro}
+% Journal articles have a volume and issue number.
+%    \begin{macrocode}
+  \hyxmp at use@first at valid{pdfvolumenum}{\@pdfvolumenum}{%
+    \@acmVolume
+  }%
+  \hyxmp at use@first at valid{pdfissuenum}{\@pdfissuenum}{%
+    \@acmNumber
+  }%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% Nullify \cs{hyxmp at parse@acmart} if the author is not using the
+% \clsname{acmart} class.
+%    \begin{macrocode}
+\@ifclassloaded{acmart}{}{\let\hyxmp at parse@acmart=\relax}
+%    \end{macrocode}
+%
+% \begin{macro}{\hyxmp at set@dc at lang}
+% \begin{macro}{\hyxmp at 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 at set@dc at lang} is redefined below to set
+% \cs{hyxmp at dc@lang} to \pkgname{polyglossia}'s list of used languages
+% (once this is known).  Otherwise, \cs{hyxmp at set@dc at lang} assigns the
+% language specified by \optname{pdflang} (if any) to
+% \cs{hyxmp at dc@lang}.
+%    \begin{macrocode}
+\newcommand*{\hyxmp at set@dc at lang}{%
+  \let\hyxmp at 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 at set@dc at 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 at set@dc at lang}{%
+          \edef\hyxmp at dc@lang{\xpg at 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 at auto@assign at 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}
 % dictionary, the metadata must match.  This requirement poses a problem
@@ -2550,7 +2938,20 @@
 }
 %    \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 at auto@assign at 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 at auto@assign at data}
+% twice: both before the |\begin{document}| at at the |\end{document}|.
+%    \begin{macrocode}
+\hyxmp at at@end{\hyxmp at auto@assign at data}
+%    \end{macrocode}
 %
+%
 % \subsection{Manipulating author-supplied data}
 %
 % The author provides metadata information to \pkgname{hyperxmp} via
@@ -4436,7 +4837,7 @@
 % \changes{v4.1}{2019/04/05}{Added this macro}
 %    \begin{macrocode}
 \newcommand{\hyxmp at singleton@dc}[3][Bag]{%
-  \@ifnotmtarg{#3}{%
+  \@ifnotmtargexp{#3}{%
     \hyxmp at xmlify{#3}%
     \hyxmp at add@to at xml{%
 ______<dc:#2>^^J%
@@ -4498,7 +4899,6 @@
   \hyxmp at rdf@dc{rights}{\@pdfcopyright}%
   \hyxmp at singleton@dc{publisher}{\@pdfpublisher}%
   \hyxmp at singleton@dc[Seq]{date}{\hyxmp at today@xmp}%
-  \hyxmp at singleton@dc{language}{\@pdflang}%
   \hyxmp at singleton@dc{type}{\@pdftype}%
   \hyxmp at list@to at xml[\ifHy at pdfa]{creator}{Seq}{\hyxmp at pdfauthor}%
   \hyxmp at list@to at xml{subject}{Bag}{\hyxmp at pdfkeywords}%
@@ -4507,6 +4907,17 @@
     \hyxmp at add@simple{dc:source}{\@pdfsource}%
   \fi
 %    \end{macrocode}
+% Set \cs{hyxmp at 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 at set@dc at lang}.
+% \changes{v5.3}{2020/06/13}{Include all languages used in the document
+%   in \protect\xmpterm{dc:language}}
+%    \begin{macrocode}
+  \hyxmp at set@dc at lang
+  \hyxmp at list@to at xml{language}{Bag}{\hyxmp at 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 @@
 %
 % \begin{macro}{\hyxmp at list@to at 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}

Modified: trunk/Master/texmf-dist/tex/latex/hyperxmp/hyperxmp.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/hyperxmp/hyperxmp.sty	2020-06-14 22:17:46 UTC (rev 55548)
+++ trunk/Master/texmf-dist/tex/latex/hyperxmp/hyperxmp.sty	2020-06-14 22:18:02 UTC (rev 55549)
@@ -22,16 +22,15 @@
 %% 
 \NeedsTeXFormat{LaTeX2e}[1999/12/01]
 \ProvidesPackage{hyperxmp}
-    [2020/05/12 v5.2 Store hyperref metadata in XMP format]
+    [2020/06/13 v5.3 Store hyperref metadata in XMP format]
 \edef\hyxmp at dq@code{\the\catcode`\"}
 \catcode`\"=12
-\def\hyxmp at driver{hpdftex}
-\ifx\hyxmp at driver\Hy at driver
-  \let\hyxmp at at@end=\AtEndDocument
-\else
+\@ifundefined{AtEndDocument}{%
   \RequirePackage{atenddvi}
   \let\hyxmp at at@end=\AtEndDvi
-\fi
+}{%
+  \let\hyxmp at at@end=\AtEndDocument
+}
 \RequirePackage{kvoptions}
 \RequirePackage{pdfescape}
 \RequirePackage{stringenc}
@@ -42,6 +41,11 @@
 \RequirePackage{ifthen}
 \def\@ifmtargexp#1{\expandafter\@ifmtarg\expandafter{#1}}
 \def\@ifnotmtargexp#1{\expandafter\@ifnotmtarg\expandafter{#1}}
+\newcommand*{\@if at def@and at nonempty}[3]{%
+  \@ifundefined{#1}{#3}{%
+    \expandafter\@ifmtargexp\expandafter{\csname#1\endcsname}{#3}{#2}%
+  }%
+}
 \newcommand{\hyxmp at pdfstringdef}[2]{%
   \let\hyxmp at textunderscore=\textunderscore
   \let\textunderscore=\hyxmp at uscore
@@ -361,31 +365,184 @@
     {}%
   }%
 }
-\AtBeginDocument{%
-  \@ifpackageloaded{hyperref}{%
-    \ifx\@pdflang\relax
-      \let\@pdflang=\@empty
+\newcommand*{\hyxmp at set@koma at phones}{%
+  \@if at def@and at nonempty{scr at frommobilephone@var}{%
+    \@if at def@and at nonempty{scr at fromphone@var}{%
+      \edef\hyxmp at koma@phones{\scr at frommobilephone@var,\scr at fromphone@var}%
+    }{%
+      \edef\hyxmp at koma@phones{\scr at frommobilephone@var}%
+    }%
+  }{%
+    \@if at def@and at nonempty{scr at fromphone@var}{%
+      \edef\hyxmp at koma@phones{\scr at fromphone@var}%
+    }{%
+    }%
+  }%
+}
+\newcommand*{\hyxmp at use@first at valid}[3]{%
+  \@ifmtargexp{#2}{%
+    \hyxmp at use@first at valid@i{#1}#3,!,%
+  }%
+  {}%
+}
+\def\hyxmp at use@first at valid@i#1#2,{%
+  \def\next{\hyxmp at use@first at valid@i{#1}}%
+  \ifx#2!%
+    \let\next=\relax
+  \else
+    \ifx#2\undefined
+    \else
+      \@ifnotmtargexp{#2}{%
+        \hypersetup{#1={#2}}%
+        \def\next##1!,{}%
+      }%
     \fi
-    \ifx\@pdfmetalang\@empty
-      \ifx\@pdflang\@empty
-        \let\@pdfmetalang=\hyxmp at x@default
-      \else
-        \edef\@pdfmetalang{\@pdflang}%
-      \fi
+  \fi
+  \next
+}
+\newcommand*{\hyxmp at auto@assign at data}{%
+  \ifx\@pdfmetalang\@empty
+    \ifx\@pdflang\@empty
+      \let\@pdfmetalang=\hyxmp at x@default
+    \else
+      \edef\@pdfmetalang{\@pdflang}%
     \fi
-    \hyxmp at xmlify\@pdfmetalang
-    \@ifmtargexp{\@pdftitle}{%
-      \@ifnotmtargexp{\@title}{%
-        \hypersetup{pdftitle={\@title}}%
+  \fi
+  \hyxmp at xmlify\@pdfmetalang
+  \hyxmp at use@first at valid{pdftitle}{\@pdftitle}{%
+    \scr at subject@var,%
+    \@title
+  }%
+  \hyxmp at use@first at valid{pdfauthor}{\@pdfauthor}{%
+    \scr at fromname@var,%
+    \@author
+  }%
+  \hyxmp at use@first at valid{pdfcontactemail}{\@pdfcontactemail}{%
+    \scr at fromemail@var
+  }%
+  \hyxmp at set@koma at phones
+  \hyxmp at use@first at valid{pdfcontactphone}{\@pdfcontactphone}{%
+    \hyxmp at koma@phones
+  }%
+  \hyxmp at use@first at valid{pdfcontacturl}{\@pdfcontacturl}{%
+    \scr at fromurl@var
+  }%
+  \hyxmp at use@first at valid{pdfsubtitle}{\@pdfsubtitle}{%
+    \@subtitle
+  }%
+  \hyxmp at use@first at valid{pdfpublisher}{\@pdfpublisher}{%
+    \@publishers
+  }%
+  \hyxmp at parse@acmart
+}
+\newcommand*{\hyxmp at parse@acmart}{%
+  \begingroup
+    \let\@author=\@gobble
+    \def\email##1##2{%
+      \def\hyxmp at address@val{##2}%
+      \hyxmp at use@first at valid{pdfcontactemail}{\@pdfcontactemail}{%
+        \hyxmp at address@val
       }%
     }%
-    {}%
-    \@ifmtargexp{\@pdfauthor}{%
-      \@ifnotmtargexp{\@author}{%
-        \hypersetup{pdfauthor={\@author}}%
+    \def\streetaddress##1{%
+      \def\hyxmp at address@val{##1}%
+      \hyxmp at use@first at valid{pdfcontactaddress}{\@pdfcontactaddress}{%
+        \hyxmp at address@val
       }%
     }%
-    {}%
+    \def\city##1{%
+      \def\hyxmp at address@val{##1}%
+      \hyxmp at use@first at valid{pdfcontactcity}{\@pdfcontactcity}{%
+        \hyxmp at address@val
+      }%
+    }%
+    \def\state##1{%
+      \def\hyxmp at address@val{##1}%
+      \hyxmp at use@first at valid{pdfcontactregion}{\@pdfcontactregion}{%
+        \hyxmp at address@val
+      }%
+    }%
+    \def\country##1{%
+      \def\hyxmp at address@val{##1}%
+      \hyxmp at use@first at valid{pdfcontactcountry}{\@pdfcontactcountry}{%
+        \hyxmp at address@val
+      }%
+    }%
+    \def\postcode##1{%
+      \def\hyxmp at address@val{##1}%
+      \hyxmp at use@first at valid{pdfcontactpostcode}{\@pdfcontactpostcode}{%
+        \hyxmp at address@val
+      }%
+    }%
+    \def\affiliation##1##2{%
+      ##2%
+      \let\affiliation=\@gobbletwo
+    }%
+    \setbox0=\hbox{\addresses}%
+  \endgroup
+  \@if at def@and at nonempty{@acmDOI}{%
+    \IfSubStr{\@acmDOI}{10.1145/1122445.1122456}{}{%
+      \IfSubStr{\@acmDOI}{10.1145/nnnnnnn.nnnnnnn}{}{%
+        \hyxmp at use@first at valid{pdfdoi}{\@pdfdoi}{%
+          \@acmDOI
+        }%
+      }%
+    }%
+  }%
+  \@if at def@and at nonempty{@acmISBN}{%
+    \IfSubStr{\@acmISBN}{XXXX}{}{%
+      \IfSubStr{\@acmISBN}{xxxx}{}{%
+        \def\hyxmp at strip@isbn at date##1/##2!{##1}%
+        \edef\hyxmp at acm@isbn{%
+          \expandafter\hyxmp at strip@isbn at date\@acmISBN/!%
+        }%
+        \hyxmp at use@first at valid{pdfisbn}{\@pdfisbn}{%
+          \hyxmp at acm@isbn
+        }%
+      }%
+    }%
+  }%
+  \def\hyxmp at acm@publisher{Association for Computing Machinery}%
+  \hyxmp at use@first at valid{pdfpublisher}{\@pdfpublisher}{%
+    \hyxmp at acm@publisher
+  }%
+  \hyxmp at use@first at valid{pdfpublication}{\@pdfpublication}{%
+    \@journalName,%
+    \@acmBooktitle,%
+    \@acmConference
+  }%
+  \if at ACM@journal
+    \def\hyxmp at acm@pubtype{journal}%
+  \else
+    \def\hyxmp at acm@pubtype{book}%
+  \fi
+  \hyxmp at use@first at valid{pdfpubtype}{\@pdfpubtype}{%
+    \hyxmp at acm@pubtype
+  }%
+  \hyxmp at use@first at valid{pdfvolumenum}{\@pdfvolumenum}{%
+    \@acmVolume
+  }%
+  \hyxmp at use@first at valid{pdfissuenum}{\@pdfissuenum}{%
+    \@acmNumber
+  }%
+}
+\@ifclassloaded{acmart}{}{\let\hyxmp at parse@acmart=\relax}
+\newcommand*{\hyxmp at set@dc at lang}{%
+  \let\hyxmp at dc@lang=\@pdflang
+}
+\AtEndPreamble{%
+  \@ifpackageloaded{hyperref}{%
+    \ifx\@pdflang\relax
+      \@ifundefined{mainbcp47id}{%
+        \let\@pdflang=\@empty
+      }{%
+        \xdef\@pdflang{\csname mainbcp47id\endcsname}%
+        \renewcommand*{\hyxmp at set@dc at lang}{%
+          \edef\hyxmp at dc@lang{\xpg at bcp@loaded}%
+        }%
+      }%
+    \fi
+    \hyxmp at auto@assign at data
     \@ifundefined{XeTeXversion}{}{%
       \@ifmtargexp{\@pdfcreationdate}{%
         \let\@pdfcreationdate=\hyxmp at today@pdf
@@ -407,6 +564,7 @@
       disabled}%
   }%
 }
+\hyxmp at at@end{\hyxmp at auto@assign at data}
 \newcommand*{\hyxmp at commas@to at list}[2]{%
   \gdef#1{}%
   \expandafter\hyxmp at commas@to at list@i\expandafter#1#2,,%
@@ -1125,7 +1283,7 @@
   \fi
 }
 \newcommand{\hyxmp at singleton@dc}[3][Bag]{%
-  \@ifnotmtarg{#3}{%
+  \@ifnotmtargexp{#3}{%
     \hyxmp at xmlify{#3}%
     \hyxmp at add@to at xml{%
 ______<dc:#2>^^J%
@@ -1150,7 +1308,6 @@
   \hyxmp at rdf@dc{rights}{\@pdfcopyright}%
   \hyxmp at singleton@dc{publisher}{\@pdfpublisher}%
   \hyxmp at singleton@dc[Seq]{date}{\hyxmp at today@xmp}%
-  \hyxmp at singleton@dc{language}{\@pdflang}%
   \hyxmp at singleton@dc{type}{\@pdftype}%
   \hyxmp at list@to at xml[\ifHy at pdfa]{creator}{Seq}{\hyxmp at pdfauthor}%
   \hyxmp at list@to at xml{subject}{Bag}{\hyxmp at pdfkeywords}%
@@ -1158,6 +1315,8 @@
   \else
     \hyxmp at add@simple{dc:source}{\@pdfsource}%
   \fi
+  \hyxmp at set@dc at lang
+  \hyxmp at list@to at xml{language}{Bag}{\hyxmp at dc@lang}%
   \@ifmtargexp{\@pdfidentifier}{%
     \let\hyxmp at xmlified=\@empty
     \hyxmp at cond@dc at identifier{info:doi/}{\@pdfdoi}%



More information about the tex-live-commits mailing list.