Skip to content

Commit 83837e0

Browse files
committed
feat: nameIdentifier@type=email for usernames, ref #115
1 parent 9adf706 commit 83837e0

3 files changed

Lines changed: 57 additions & 4 deletions

File tree

collection-export/fixtures/syllabus-one-faculty.mods.xml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<mods xmlns="http://www.loc.gov/mods/v3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
22
version="3.8"
33
xsi:schemaLocation="http://www.loc.gov/mods/v3 http://www.loc.gov/standards/mods/v3/mods-3-8.xsd">
4-
4+
<!-- this is just an example of what output should look like and not used in any tests -->
55
<titleInfo>
66
<title>FASHN-360 Media History</title>
77
<partNumber>Fall 2026</partNumber>
@@ -14,13 +14,14 @@
1414
<role>
1515
<roleTerm authority="marcrelator" authorityURI="http://id.loc.gov/vocabulary/relators" valueURI="http://id.loc.gov/vocabulary/relators/tch">teacher</roleTerm>
1616
</role>
17+
<nameIdentifier type="email" typeURI="https://datatracker.ietf.org/doc/html/rfc5322" displayLabel="Email">ephetteplace@cca.edu</nameIdentifier>
1718
</name>
1819

1920
<name type="corporate">
2021
<namePart>Design Division</namePart>
2122
<namePart>Fasion Design (BFA)</namePart>
2223
<role>
23-
<roleTerm type="text" authority="marcrelator">sponsor</roleTerm>
24+
<roleTerm authority="marcrelator" authorityURI="http://id.loc.gov/vocabulary/relators" valueURI="http://id.loc.gov/vocabulary/relators/spn">sponsor</roleTerm>
2425
</role>
2526
</name>
2627

collection-export/syllabus.js

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ import {
88
} from './xml-helpers.js'
99
import {convertPartNumbers, moveAndRenameElement, removeEmptyElements} from './strict-mods.js'
1010

11-
// TODO handle username as nameIdentifier
12-
1311
/**
1412
* Add a role/roleTerm child to a parent element assuming marcrelator authority.
1513
* Used by personalNames and corporateName functions.
@@ -101,6 +99,27 @@ export function personalNames(doc) {
10199
})
102100
}
103101

102+
// usernames list -> nameIdentifier elements
103+
const facultyID = safeSelectFirst("//local/courseInfo/facultyID", doc)
104+
const usernames = facultyID ? facultyID.textContent.split(', ')
105+
.map(id => id.trim())
106+
.filter(id => id.length > 0) : []
107+
const nameElements = safeSelect("//mods/name[@type='personal']", doc)
108+
109+
// sanity check: only add nameIdentifier if we have the same number of usernames as names
110+
if (usernames.length !== nameElements.length) {
111+
return doc
112+
}
113+
114+
for (let i = 0; i < usernames.length; i++) {
115+
const nameIdentifier = createElement(doc, 'nameIdentifier')
116+
nameIdentifier.setAttribute('type', 'email')
117+
nameIdentifier.setAttribute('typeURI', 'https://datatracker.ietf.org/doc/html/rfc5322')
118+
nameIdentifier.setAttribute('displayLabel', 'Email')
119+
nameIdentifier.textContent = `${usernames[i]}@cca.edu`
120+
nameElements[i].appendChild(nameIdentifier)
121+
}
122+
104123
return doc
105124
}
106125

collection-export/syllabus.test.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,39 @@ describe('personalNames', () => {
8787
assert.ok(namePart2)
8888
assert.strictEqual(namePart2.textContent, 'Jane Smith')
8989
})
90+
91+
it('should add an email nameIdentifier for each personal name if local/facultyID is present', async () => {
92+
const inputXML = x(`<local><courseInfo><faculty>John Doe, Jane Smith</faculty><facultyID>jdoe, jsmith</facultyID></courseInfo></local>`)
93+
const result = convertSyllabusXMLtoMODS(inputXML)
94+
const nameElements = xpath.select('//mods/name[@type="personal"]', result)
95+
assert.strictEqual(nameElements.length, 2)
96+
const nameIdentifiers = xpath.select('//mods/name[@type="personal"]/nameIdentifier', result)
97+
assert.strictEqual(nameIdentifiers.length, 2)
98+
assert.ok(nameIdentifiers[0])
99+
assert.strictEqual(nameIdentifiers[0].textContent, 'jdoe@cca.edu')
100+
assert.ok(nameIdentifiers[1])
101+
assert.strictEqual(nameIdentifiers[1].textContent, 'jsmith@cca.edu')
102+
})
103+
104+
it('should not add email nameIdentifiers if local/facultyID is missing', async () => {
105+
const inputXML = x(`<local><courseInfo><faculty>John Doe, Jane Smith</faculty></courseInfo></local>`)
106+
const result = convertSyllabusXMLtoMODS(inputXML)
107+
const nameElements = xpath.select('//mods/name[@type="personal"]', result)
108+
assert.strictEqual(nameElements.length, 2)
109+
const nameIdentifier1 = xpath.select1('nameIdentifier', nameElements[0])
110+
assert.ok(!nameIdentifier1)
111+
const nameIdentifier2 = xpath.select1('nameIdentifier', nameElements[1])
112+
assert.ok(!nameIdentifier2)
113+
})
114+
115+
it('should not add emails if they do not correspond with names', async () => {
116+
const inputXML = x(`<local><courseInfo><faculty>John Doe</faculty><facultyID>jdoe, jsmith</facultyID></courseInfo></local>`)
117+
const result = convertSyllabusXMLtoMODS(inputXML)
118+
const nameElements = xpath.select('//mods/name[@type="personal"]', result)
119+
assert.strictEqual(nameElements.length, 1)
120+
const nameIdentifier1 = xpath.select1('nameIdentifier', nameElements[0])
121+
assert.ok(!nameIdentifier1)
122+
})
90123
})
91124

92125
describe('corporateName', () => {

0 commit comments

Comments
 (0)