jats-xml
Version:
Types and utilities for working with JATS in Typescript
119 lines (118 loc) • 4.9 kB
JavaScript
import { toText } from 'myst-common';
import { doi } from 'doi-utils';
import { select, selectAll } from 'unist-util-select';
import { Tags } from 'jats-tags';
import { remove } from 'unist-util-remove';
export function findArticleId(node, pubIdType = 'doi') {
if (!node)
return undefined;
const id = select(`[pub-id-type=${pubIdType}]`, node);
if (id && toText(id))
return toText(id);
const doiTag = selectAll(`${Tags.articleId},${Tags.pubId}`, node).find((t) => doi.validate(toText(t)));
return toText(doiTag) || undefined;
}
export function processContributor(contrib) {
const author = {
name: `${toText(select(Tags.givenNames, contrib))} ${toText(select(Tags.surname, contrib))}`,
};
const orcid = select('[contrib-id-type=orcid]', contrib);
if (orcid) {
author.orcid = toText(orcid).replace(/(https?:\/\/)?orcid\.org\//, '');
}
const affiliationRefs = selectAll('xref[ref-type=aff]', contrib);
const affiliationIds = affiliationRefs.map((xref) => xref.rid);
if (affiliationIds.length > 0) {
author.affiliations = affiliationIds;
}
const uri = select('uri', contrib);
if (uri === null || uri === void 0 ? void 0 : uri['xlink:href']) {
author.url = uri['xlink:href'];
}
// If there are no aff xrefs AND contrib is in a contrib group with affs AND those affs do not have IDs, add them as affiliations...
return author;
}
/**
* Perform standard toText, trim, remove trailing comma and semicolon
*
* Additionally, this returns undefined instead of empty string if node is undefined
*/
function toTextAndTrim(content) {
const text = toText(content);
if (!text)
return undefined;
return text.replace(/^[\s;,]+/, '').replace(/[\s;,]+$/, '');
}
function markForDeletion(nodes) {
nodes.forEach((node) => {
if (node)
node.type = '__delete__';
});
}
export function processAffiliation(aff) {
var _a, _b;
const id = aff.id;
let ror;
let isni;
const rorNode = select(`institution-id[institution-id-type=ror]`, aff);
if (rorNode) {
ror = toTextAndTrim(rorNode);
}
const isniNode = select(`institution-id[institution-id-type=ISNI]`, aff);
if (isniNode) {
isni = toTextAndTrim(isniNode);
}
markForDeletion(selectAll('institution-id', aff));
remove(aff, '__delete__');
const institutions = selectAll('institution', aff);
const textAddress = selectAll('addr-line > text', aff);
const namedContent = selectAll('named-content', aff);
const departmentNode = (_a = institutions.find((inst) => inst['content-type'] === 'dept')) !== null && _a !== void 0 ? _a : namedContent.find((content) => content['content-type'] === 'organisation-division');
const addressNode = namedContent.find((content) => content['content-type'] === 'street');
const cityNode = namedContent.find((content) => content['content-type'] === 'city');
const stateNode = namedContent.find((content) => content['content-type'] === 'country-part');
const postalCodeNode = namedContent.find((content) => content['content-type'] === 'post-code');
const countryNode = (_b = select('country', aff)) !== null && _b !== void 0 ? _b : namedContent.find((content) => content['content-type'] === 'country');
markForDeletion([
...textAddress,
...namedContent,
departmentNode,
addressNode,
cityNode,
stateNode,
postalCodeNode,
countryNode,
]);
remove(aff, '__delete__');
const affChildren = aff.children.filter((child) => child.type !== 'label');
let institution;
if (affChildren.filter((child) => ['text', 'institution-wrap', 'institution'].includes(child.type))
.length === affChildren.length) {
institution = toTextAndTrim(affChildren);
}
else {
institution = toTextAndTrim(institutions.find((inst) => inst['content-type'] !== 'dept'));
}
const addressLines = textAddress
.map((line) => toTextAndTrim(line))
.filter((line) => !!line);
let department = departmentNode
? toTextAndTrim(departmentNode)
: addressLines.find((line) => line.toLowerCase().includes('department'));
let address = addressNode
? toTextAndTrim(addressNode)
: addressLines.find((line) => !line.toLowerCase().includes('department'));
if (address && !institution) {
institution = address;
address = undefined;
}
if (department && !institution) {
institution = department;
department = undefined;
}
const city = toTextAndTrim(cityNode);
const state = toTextAndTrim(stateNode);
const postal_code = toTextAndTrim(postalCodeNode);
const country = toTextAndTrim(countryNode);
return { id, ror, isni, department, institution, address, city, state, postal_code, country };
}