diff --git a/MANIFEST b/MANIFEST index 6dfd9301f..ae41ae5f1 100644 --- a/MANIFEST +++ b/MANIFEST @@ -984,6 +984,9 @@ t/complex/hyperchars.xml t/complex/hypertest.pdf t/complex/hypertest.tex t/complex/hypertest.xml +t/complex/hyperxmp.pdf +t/complex/hyperxmp.tex +t/complex/hyperxmp.xml t/complex/labelled.pdf t/complex/labelled.tex t/complex/labelled.xml diff --git a/lib/LaTeXML/Engine/Base_Schema.pool.ltxml b/lib/LaTeXML/Engine/Base_Schema.pool.ltxml index 29d451396..f80d1bee9 100644 --- a/lib/LaTeXML/Engine/Base_Schema.pool.ltxml +++ b/lib/LaTeXML/Engine/Base_Schema.pool.ltxml @@ -81,6 +81,7 @@ RequireResource('LaTeXML.css'); "ma" => "http://www.w3.org/ns/ma-ont#", "og" => "http://ogp.me/ns#", "owl" => "http://www.w3.org/2002/07/owl#", + "prism" => "http://prismstandard.org/namespaces/basic/3.0/", "rdf" => "http://www.w3.org/1999/02/22-rdf-syntax-ns#", "rdfa" => "http://www.w3.org/ns/rdfa#", "rdfs" => "http://www.w3.org/2000/01/rdf-schema#", diff --git a/lib/LaTeXML/Package/hyperref.sty.ltxml b/lib/LaTeXML/Package/hyperref.sty.ltxml index 820339cec..052647cc3 100644 --- a/lib/LaTeXML/Package/hyperref.sty.ltxml +++ b/lib/LaTeXML/Package/hyperref.sty.ltxml @@ -86,21 +86,19 @@ foreach my $option ( # 3.1 General Options DeclareOption($option, undef); } # \hypersetup{keyvals} configures various parameters, -# for each pdf keyword, provide [property,(content|resource),datatype] -our %pdfkey_property = ( - baseurl => '', # xmp:BaseURL ?? - pdfauthor => ['dcterms:creator', 'content'], - pdfkeywords => ['dcterms:subject', 'content'], # & pdf:Keywords - pdflang => ['dcterms:language', 'content'], - pdfproducer => '', # pdf:Producer & xmp:CreatorTool - pdfsubject => ['dcterms:subject', 'content'], - pdftitle => ['dcterms:title', 'content'], - # Include hyperxmp's keywords, as well. - pdfauthortitle => '', # photoshop:AuthorsPosition - pdfcaptionwriter => '', # photoshop:CaptionWriter !?!?!? - pdfcopyright => ['dcterms:rights', 'content'], # & xmpRights:Marked - pdflicenseurl => ['cc:licence', 'resource'], # xmpRights:WebStatement - pdfmetalang => '', # dcterms:language ?? +# for each pdf keyword, provide [property,(content|resource),datatype,langsupport] +# %pdfkey_property may have already been populated by hyperxmp +our %pdfkey_property = (%pdfkey_property, + baseurl => '', # xmp:BaseURL ?? + pdfauthor => ['dcterms:creator', 'content'], + pdfcreationdate => '', # xmp:CreateDate + pdfkeywords => ['dcterms:subject', 'content'], # & pdf:Keywords + pdflang => ['dcterms:language', 'content'], + pdfmoddate => '', # xmp:ModifyDate + pdfproducer => '', # pdf:Producer & xmp:CreatorTool + pdfsubject => ['dcterms:description', 'content'], + pdftitle => ['dcterms:title', 'content'], + pdftrapped => '', # pdf:Trapped ); # date=>dcterms:date xmp:CreateDate xmp:ModifyDate xmp:MetadataDate ? # document identifier => xmlMM:DocumentID @@ -126,7 +124,7 @@ DefPrimitive('\hypersetup RequiredKeyVals:Hyp', sub { my @pairs = $kv->getPairs; while (@pairs) { my ($key, $value) = (shift(@pairs), shift(@pairs)); - hyperref_setoption($key, Digest($value)); } + hyperref_setoption($key, Expand($value)); } return; }); PushValue('@at@end@document', T_CS('\@add@PDF@RDFa@triples')); @@ -134,13 +132,16 @@ PushValue('@at@end@document', T_CS('\@add@PDF@RDFa@triples')); DefConstructor('\@add@PDF@RDFa@triples', sub { my ($document, $xproperty, $content) = @_; if (my $root = $document->getDocument->documentElement) { + my $metalang = LookupMapping('Hyperref_options', 'pdfmetalang') // LookupMapping('Hyperref_options', 'pdflang'); foreach my $key (LookupMappingKeys('Hyperref_options')) { if (my $entry = ($pdfkey_property{$key})) { - my ($property, $object, $datatype) = @$entry; - my $value = LookupMapping('Hyperref_options', $key); - my $node = $document->openElementAt($root, 'ltx:rdf', - property => $property, $object => $value, - ($datatype ? (datatype => $datatype) : ())); + my ($property, $object, $datatype, $langsupport) = @$entry; + my $value = ToString(LookupMapping('Hyperref_options', $key)); + my ($lang, $localizedValue) = $value =~ m/^\[([^]]*)\](.*)/; + my $node = $document->openElementAt($root, 'ltx:rdf', + property => $property, $object => $langsupport ? $localizedValue // $value : $value, + ($langsupport && ($lang || $metalang) ? ('xml:lang' => $lang // $metalang) : ()), + ($datatype ? (datatype => $datatype) : ())); # Must do directly; $document->setAttribute omits empty attributes $node->setAttribute(about => ''); $document->closeElementAt($node); } } } }); diff --git a/lib/LaTeXML/Package/hyperxmp.sty.ltxml b/lib/LaTeXML/Package/hyperxmp.sty.ltxml index 43700053a..8006a7e61 100644 --- a/lib/LaTeXML/Package/hyperxmp.sty.ltxml +++ b/lib/LaTeXML/Package/hyperxmp.sty.ltxml @@ -17,7 +17,63 @@ use LaTeXML::Package; RequirePackage('ifthen'); -# Basically, the effects of hyperxmp are already built -# into the LaTeXML binding for hyperref. +# macro to pass alternate language entries +# TODO support entries in multiple languages +# TODO pdfmetalang should affect *following* entries, not all of them +Let('\XMPLangAlt', '\@gobbletwo'); + +# macros for including commas in comma-separated lists +# TODO implement comma-separated lists splitting +Let('\xmpquote', '\relax'); +DefMacroI('\xmpcomma', undef, ','); + +# %pdfkey_property may have already been populated by hyperref +our %pdfkey_property = (%pdfkey_property, + # modify hyperref keywords to support specifying the language + pdfsubject => ['dcterms:description', 'content', undef, 1], + pdftitle => ['dcterms:title', 'content', undef, 1], + pdfaconformance => '', # pdfaid:conformance + pdfapart => '', # pdfaid:part + pdfauthortitle => '', # photoshop:AuthorsPosition + pdfbookedition => ['prism:bookEdition', 'content', undef, 1], + pdfbytes => ['prism:byteCount', 'content'], + pdfcaptionwriter => '', # photoshop:CaptionWriter + pdfcontactaddress => '', # Iptc4xmpCore:CiAdrExtadr + pdfcontactcity => '', # Iptc4xmpCore:CiAdrCity + pdfcontactcountry => '', # Iptc4xmpCore:CiAdrCtry + pdfcontactemail => '', # Iptc4xmpCore:CiEmailWork + pdfcontactphone => '', # Iptc4xmpCore:CiTelWork + pdfcontactpostcode => '', # Iptc4xmpCore:CiAdrPcode + pdfcontactregion => '', # Iptc4xmpCore:CiAdrRegion + pdfcontacturl => '', # Iptc4xmpCore:CiUrlWork + pdfcopyright => ['dcterms:rights', 'content', undef, 1], # & xmpRights:Marked, xmpRights:WebStatement + pdfdate => ['dcterms:date', 'content'], # (if missing, hyperxmp uses \date -- we delegate the default choice to postprocessing) + pdfdocumentid => '', # xmpMM:DocumentID + pdfdoi => ['prism:doi', 'content'], + pdfeissn => ['prism:eIssn', 'content'], + pdfidentifier => ['dcterms:identifier', 'content'], # (if missing, hyperxmp uses the first non-empty doi, eissn, issn, isbn with prefix info:doi/ or urn:ISS(B|N): -- we delegate the default choice to postprocessing) + pdfinstanceid => '', # xmpMM:InstanceID + pdfisbn => ['prism:isbn', 'content'], + pdfissn => ['prism:issn', 'content'], + pdfissuenum => ['prism:number', 'content'], + pdflicenseurl => ['cc:licence', 'resource'], # xmpRights:WebStatement + pdfmetadate => '', # xmp:MetadataDate + pdfmetalang => '', # the default language of the metadata entries themselves + pdfnumpages => ['prism:pageCount', 'content'], # xmpTPg:NPages + pdfpagerange => ['prism:pageRange', 'content'], + pdfpublication => ['prism:publicationName', 'content', undef, 1], + pdfpublisher => ['dcterms:publisher', 'content'], + pdfpubstatus => '', # jav:journal_article_version + pdfpubtype => ['prism:aggregationType', 'content'], + pdfrendition => '', # xmpMM:RenditionClass + pdfsource => ['dcterms:source', 'content'], + pdfsubtitle => ['prism:subtitle', 'content', undef, 1], + pdftype => ['dcterms:type', 'content'], + pdfuapart => '', # pdfuaid:part + pdfurl => ['prism:url', 'content'], + pdfversionid => '', # xmpMM:VersionID + pdfvolumenum => ['prism:volume', 'content'], + pdfxstandard => '', # {pdfx,pdfxid}:GTS_PDFXVersion +); 1; diff --git a/t/80_complex.t b/t/80_complex.t index e9bd5aea5..4bd80250c 100644 --- a/t/80_complex.t +++ b/t/80_complex.t @@ -9,6 +9,7 @@ latexml_tests("t/complex", cleveref_minimal => 'cleveref.sty', figure_dual_caption => {packages => 'graphicx.sty', texlive_min => 2021}, figure_mixed_content => {packages => 'graphicx.sty', texlive_min => 2021}, + hyperxmp => 'babel.sty', si => { env=>'CI', # only runs in continuous integration packages => 'siunitx.sty', texlive_min => 2015 } }); diff --git a/t/complex/hypertest.xml b/t/complex/hypertest.xml index 8aa242b17..b760145d1 100644 --- a/t/complex/hypertest.xml +++ b/t/complex/hypertest.xml @@ -50,6 +50,6 @@ - + diff --git a/t/complex/hyperxmp.pdf b/t/complex/hyperxmp.pdf new file mode 100644 index 000000000..4fd32a816 Binary files /dev/null and b/t/complex/hyperxmp.pdf differ diff --git a/t/complex/hyperxmp.tex b/t/complex/hyperxmp.tex new file mode 100644 index 000000000..5049af6cb --- /dev/null +++ b/t/complex/hyperxmp.tex @@ -0,0 +1,64 @@ +% example copied from hyperxmp with minor modifications +\pdfobjcompresslevel=0 % added to easily inspect the XMP packet +\documentclass[british]{article} % added british to test pdflang and pdfmetalang +\usepackage[utf8]{inputenc} +\usepackage{babel} +\usepackage[unicode]{hyperref} +\usepackage{hyperxmp} +% +\title{% + On a heuristic viewpoint concerning the production and + transformation of light} +\author{Albert Einstein} +\date{March 17, 1905} +% +\hypersetup{% + pdfmetalang={en-AU}, % added to test pdfmetalang + pdftitle={% + On a heuristic viewpoint concerning the production and + transformation of light}, + pdfsubtitle={[en-US]Putting that bum Maxwell in his place}, + pdfauthor={Albert Einstein}, + pdfauthortitle={\xmpquote{Technical Assistant\xmpcomma\ Level III}}, + pdfdate={1905-03-17}, + pdfcopyright={Copyright (C) 1905, Albert Einstein}, + pdfsubject={photoelectric effect}, + pdfkeywords={energy quanta, Hertz effect, quantum physics}, + pdflicenseurl={http://creativecommons.org/licenses/by-nc-nd/3.0/}, + pdfcaptionwriter={Scott Pakin}, + pdfcontactaddress={Kramgasse 49}, + pdfcontactcity={Bern}, + pdfcontactpostcode={3011}, + pdfcontactcountry={Switzerland}, + pdfcontactphone={031 312 00 91}, + pdfcontactemail={aeinstein@ipi.ch}, + pdfcontacturl={% + http://einstein.biz/, + https://www.facebook.com/AlbertEinstein + }, + pdfdocumentid={uuid:6d1ac9ec-4ff2-515a-954b-648eeb4853b0}, + pdfversionid={2.998e8}, + pdfpublication={[de]Annalen der Physik}, + pdfpublisher={Wiley-VCH}, + pdfpubtype={journal}, + pdfvolumenum={322}, + pdfissuenum={6}, + pdfpagerange={132-148}, + pdfissn={0003-3804}, + pdfeissn={1521-3889}, + pdfpubstatus={VoR}, + pdflang={en-GB}, + pdfurl={http://www.physik.uni-augsburg.de/annalen/history/einstein-papers/1905_17_132-148.pdf}, + pdfdoi={10.1002/andp.19053220607}, + pdfidentifier={info:lccn/50013519} +} +\XMPLangAlt{de}{pdftitle={Über einen die Erzeugung und Verwandlung des + Lichtes betreffenden heuristischen Gesichtspunkt}} +% +\begin{document} +\maketitle +A profound formal difference exists between the theoretical +concepts that physicists have formed about gases and other +ponderable bodies, and Maxwell's theory of electromagnetic +processes in so-called empty space\dots +\end{document} diff --git a/t/complex/hyperxmp.xml b/t/complex/hyperxmp.xml new file mode 100644 index 000000000..06292859a --- /dev/null +++ b/t/complex/hyperxmp.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + On a heuristic viewpoint concerning the production and +transformation of light + + Albert Einstein + + March 17, 1905 + +

A profound formal difference exists between the theoretical +concepts that physicists have formed about gases and other +ponderable bodies, and Maxwell’s theory of electromagnetic +processes in so-called empty space…

+
+ + + + + + + + + + + + + + + + + + + + +