Skip to content

Commit 4f1f9c9

Browse files
committed
Redo the xmp metadata file generation
1 parent 669a2ce commit 4f1f9c9

File tree

1 file changed

+106
-52
lines changed

1 file changed

+106
-52
lines changed

src/utils/xmp.js

Lines changed: 106 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,120 @@
11
import { LICENSES, licenseSlug } from '@/utils/license-utilities'
22

3-
function minify(data) {
4-
return data.replace(/ {2,}/gi, '').replace(/\n/gi, '')
5-
}
3+
/** The xmp metadata is structured in accordance with the Adobe XMP specifications from 2012:
4+
https://wwwimages2.adobe.com/content/dam/acom/en/devnet/xmp/pdfs/XMP%20SDK%20Release%20cc-2016-08/XMPSpecificationPart1.pdf
5+
6+
The following data is written into the xmp file:
7+
8+
xapRights:WebStatement: A Web URL for a statement of the ownership and usage rights for this resource.
9+
Uses the value of the 'Link to Work' field from the Attribution details form.
10+
xapRights:Marked: Indicates that this is a public-domain or CC0 resource if false. Otherwise, one of the 6 CC licenses.
11+
xapRights:Owner: A list of legal owners of the resource.
12+
Uses the value of the 'Creator of Work' field from the Attribution details form.
13+
xapRights:UsageTerms: A collection of text instructions on how a resource can be legally used, given in a variety of languages.
14+
Uses license statement with the link to the license deed, with '<>"' characters escaped.
15+
dc:title: A name or title given to the resource, by which it is formally known, given in various languages.
16+
Uses the value of the 'Title of Work' field from the Attribution details form.
17+
cc:license: the link to the CC license deed.
18+
cc:attributionName
19+
Uses the value of the 'Creator of Work' field from the Attribution details form.
20+
*/
21+
22+
// To make the values of these variables human-readable, and format the resulting document correctly,
23+
// we use the backtick-formatted strings, but remove the '\n' character in the beginning of the values
24+
const XAP_WEB_STATEMENT = `
25+
<xapRights:WebStatement rdf:resource='{workUrlTemplate}'/>`.slice(1)
26+
27+
const XAP_MARKED = `
28+
<xapRights:Marked>{isCopyrightedTemplate}</xapRights:Marked>`.slice(1)
29+
30+
const XAP_OWNER = `
31+
<xapRights:Owner>
32+
<rdf:Bag>
33+
<rdf:li>{creatorNameTemplate}</rdf:li>
34+
</rdf:Bag>
35+
</xapRights:Owner>`.slice(1)
36+
37+
const DC_WORK_TITLE_TEMPLATE = `
38+
<dc:title>
39+
<rdf:Alt>
40+
<rdf:li xml:lang='x-default'>{workTitleTemplate}</rdf:li>
41+
<rdf:li xml:lang='{langTemplate}'>{workTitleTemplate}</rdf:li>
42+
</rdf:Alt>
43+
</dc:title>`.slice(1)
44+
45+
const CC_LICENSE_URL_TEMPLATE = `
46+
<cc:license rdf:resource='{licenseUrlTemplate}'/>`.slice(1)
47+
48+
const XAP_RIGHTS_USAGE_TERMS = `
49+
<xapRights:UsageTerms>
50+
<rdf:Alt>
51+
<rdf:li xml:lang='x-default'>{ccLicenseNoticeTemplate}</rdf:li>
52+
<rdf:li xml:lang='{langTemplate}' >{ccLicenseNoticeTemplate}</rdf:li>
53+
</rdf:Alt>
54+
</xapRights:UsageTerms>`.slice(1)
55+
56+
const CC_ATTRIBUTION_NAME = `
57+
<cc:attributionName>{creatorNameTemplate}</cc:attributionName>`.slice(1)
58+
59+
const LINE_START = ' '
60+
const addIndent = (str) => (str.replace(/\n/gi, '\n' + LINE_START))
661

762
export const createXMP = ({ shortName, workUrl = '', workTitle = '', creatorName = '', lang = 'en-US' }) => {
863
const slug = licenseSlug(shortName).replace(/-/gi, '_').toUpperCase()
964

10-
const copyrighted = shortName !== LICENSES.CC0.SHORT
11-
const xapRights = copyrighted
12-
? `<rdf:Description rdf:about='' xmlns:xapRights='http://ns.adobe.com/xap/1.0/rights/'>
13-
<xapRights:Marked>true</xapRights:Marked></rdf:Description>`
14-
: ''
15-
const xapWorkUrl = workUrl
16-
? `<rdf:Description rdf:about='' xmlns:xapRights='http://ns.adobe.com/xap/1.0/rights/'>
17-
<xapRights:WebStatement rdf:resource='${workUrl}'/></rdf:Description>`
18-
: ''
19-
const xapWorkTitle = workTitle
20-
? `
21-
<rdf:Description rdf:about='' xmlns:dc='http://purl.org/dc/elements/1.1/'><dc:title><rdf:Alt><rdf:li xml:lang='x-default'>
22-
${workTitle}</rdf:li><rdf:li xml:lang='${lang}'>${workTitle}</rdf:li></rdf:Alt></dc:title></rdf:Description>`
23-
: ''
24-
2565
const licenseUrl = LICENSES[slug].URL
2666

27-
const ccLicenseUrl = `
28-
<rdf:Description rdf:about='' xmlns:cc='http://creativecommons.org/ns#'><cc:license rdf:resource='${licenseUrl}'/></rdf:Description>`
67+
const ccLicenseUrl = addIndent(CC_LICENSE_URL_TEMPLATE.replace('{licenseUrlTemplate}', licenseUrl))
2968

30-
const ccLicenseNotice = `
31-
This work is licensed under <a rel="license noopener noreferrer" target="_blank" href="${licenseUrl}">${LICENSES[slug].FULL}</a>`
69+
const ccLicenseNotice = `This work is licensed under <a href="${licenseUrl}">${LICENSES[slug].FULL}</a>`
70+
.replace(/</gi, '&lt;')
71+
.replace(/>/gi, '&gt;')
72+
.replace(/"/gi, '&#34;')
3273

33-
const xapRightsUsageTerms = `
34-
<rdf:Description rdf:about='' xmlns:xapRights='http://ns.adobe.com/xap/1.0/rights/'>
35-
<xapRights:UsageTerms><rdf:Alt><rdf:li xml:lang='${lang}' >${ccLicenseNotice}</rdf:li></rdf:Alt>
36-
</xapRights:UsageTerms></rdf:Description>`
74+
const xapData = {
75+
owner: '',
76+
webStatement: '',
77+
marked: '',
78+
rightsUsageTerms: addIndent(XAP_RIGHTS_USAGE_TERMS
79+
.replace('{ccLicenseNoticeTemplate}', ccLicenseNotice)
80+
.replace('{langTemplate}', lang))
81+
}
3782

38-
const xapWebStatement = workUrl
39-
? `
40-
<rdf:Description rdf:about='' xmlns:xapRights='http://ns.adobe.com/xap/1.0/rights/'>
41-
<xapRights:WebStatement rdf:resource='${workUrl}'/></rdf:Description>`
42-
: ''
83+
const copyrighted = shortName !== LICENSES.CC0.SHORT ? 'True' : 'False'
84+
xapData.marked = addIndent(XAP_MARKED
85+
.replace('{isCopyrightedTemplate}', copyrighted))
4386

44-
const ccAttributionName = creatorName
45-
? `
46-
<rdf:Description rdf:about='' xmlns:cc='http://creativecommons.org/ns#'>
47-
<cc:attributionName>${creatorName}</cc:attributionName></rdf:Description>`
87+
if (workUrl) {
88+
xapData.webStatement = addIndent(XAP_WEB_STATEMENT
89+
.replace('{workUrlTemplate}', workUrl))
90+
}
91+
const dcWorkTitle = workTitle
92+
? addIndent(DC_WORK_TITLE_TEMPLATE
93+
.replace(/{workTitleTemplate}/gi, workTitle)
94+
.replace('{langTemplate}', lang))
4895
: ''
49-
// eslint-disable-line quotes
50-
const xmpData = `
51-
<?xpacket begin='' id=''?>
52-
<x:xmpmeta xmlns:x='adobe:ns:meta/'>
53-
<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>
54-
${xapRights}
55-
${xapWorkUrl}
56-
${xapWebStatement}
57-
${xapRightsUsageTerms}
58-
${xapWorkTitle}
59-
${ccLicenseUrl}
60-
${ccAttributionName}
61-
</rdf:RDF>
62-
</x:xmpmeta>
63-
<?xpacket end='r'?>`
64-
// We return minified string to not increase the size of the licensed file
65-
return minify(xmpData)
96+
let ccAttributionName = ''
97+
if (creatorName) {
98+
ccAttributionName = addIndent(CC_ATTRIBUTION_NAME
99+
.replace('{creatorNameTemplate}', creatorName))
100+
xapData.owner = addIndent(XAP_OWNER.replace('{creatorNameTemplate}', creatorName))
101+
}
102+
return `
103+
<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?>
104+
<x:xmpmeta xmlns:x='adobe:ns:meta/'>
105+
<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'
106+
xmlns:xapRights='http://ns.adobe.com/xap/1.0/rights/'
107+
xmlns:cc='http://creativecommons.org/ns#'${workTitle ? addIndent("\nxmlns:dc='http://purl.org/dc/elements/1.1/'") : ''}>
108+
<rdf:Description rdf:about=''>
109+
${xapData.marked}
110+
${xapData.owner}
111+
${xapData.webStatement}
112+
${xapData.rightsUsageTerms}
113+
${ccLicenseUrl}
114+
${ccAttributionName}
115+
${dcWorkTitle}
116+
</rdf:Description>
117+
</rdf:RDF>
118+
</x:xmpmeta>
119+
<?xpacket end='r'?>`.slice(1)
66120
}

0 commit comments

Comments
 (0)