@manuscripts/transform 4.3.22 → 4.3.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/README.md +2 -2
  2. package/dist/cjs/jats/__tests__/jats-exporter.test.js +11 -45
  3. package/dist/cjs/jats/__tests__/jats-importer.test.js +54 -76
  4. package/dist/cjs/jats/__tests__/jats-roundtrip.test.js +1 -2
  5. package/dist/cjs/jats/__tests__/utils.js +4 -17
  6. package/dist/cjs/jats/exporter/jats-exporter.js +190 -279
  7. package/dist/cjs/jats/importer/jats-dom-parser.js +16 -42
  8. package/dist/cjs/jats/importer/jats-parser-utils.js +5 -29
  9. package/dist/cjs/jats/importer/jats-transformations.js +10 -0
  10. package/dist/cjs/jats/importer/parse-jats-article.js +1 -6
  11. package/dist/cjs/schema/__tests__/docs.js +1830 -0
  12. package/dist/cjs/schema/__tests__/migration.test.js +3 -37
  13. package/dist/cjs/schema/migration/migration-scripts/4.3.12.js +39 -0
  14. package/dist/cjs/schema/migration/migration-scripts/index.js +2 -0
  15. package/dist/cjs/schema/nodes/blockquote_element.js +0 -2
  16. package/dist/cjs/schema/nodes/comment.js +2 -1
  17. package/dist/cjs/schema/nodes/contributor.js +11 -11
  18. package/dist/cjs/schema/nodes/equation.js +1 -3
  19. package/dist/cjs/schema/nodes/list.js +0 -2
  20. package/dist/cjs/schema/nodes/listing.js +1 -3
  21. package/dist/cjs/schema/nodes/paragraph.js +0 -2
  22. package/dist/cjs/schema/nodes/pullquote_element.js +0 -2
  23. package/dist/cjs/transformer/id.js +2 -14
  24. package/dist/cjs/transformer/node-names.js +6 -1
  25. package/dist/cjs/transformer/node-types.js +1 -47
  26. package/dist/cjs/version.js +1 -1
  27. package/dist/es/jats/__tests__/jats-exporter.test.js +11 -45
  28. package/dist/es/jats/__tests__/jats-importer.test.js +54 -76
  29. package/dist/es/jats/__tests__/jats-roundtrip.test.js +1 -2
  30. package/dist/es/jats/__tests__/utils.js +4 -17
  31. package/dist/es/jats/exporter/jats-exporter.js +190 -279
  32. package/dist/es/jats/importer/jats-dom-parser.js +16 -42
  33. package/dist/es/jats/importer/jats-parser-utils.js +6 -30
  34. package/dist/es/jats/importer/jats-transformations.js +10 -0
  35. package/dist/es/jats/importer/parse-jats-article.js +1 -6
  36. package/dist/es/schema/__tests__/docs.js +1827 -0
  37. package/dist/es/schema/__tests__/migration.test.js +3 -4
  38. package/dist/es/schema/migration/migration-scripts/4.3.12.js +37 -0
  39. package/dist/es/schema/migration/migration-scripts/index.js +2 -0
  40. package/dist/es/schema/nodes/blockquote_element.js +0 -2
  41. package/dist/es/schema/nodes/comment.js +2 -1
  42. package/dist/es/schema/nodes/contributor.js +11 -11
  43. package/dist/es/schema/nodes/equation.js +1 -3
  44. package/dist/es/schema/nodes/list.js +0 -2
  45. package/dist/es/schema/nodes/listing.js +1 -3
  46. package/dist/es/schema/nodes/paragraph.js +0 -2
  47. package/dist/es/schema/nodes/pullquote_element.js +0 -2
  48. package/dist/es/transformer/id.js +2 -14
  49. package/dist/es/transformer/node-names.js +4 -0
  50. package/dist/es/transformer/node-types.js +1 -47
  51. package/dist/es/version.js +1 -1
  52. package/dist/types/jats/__tests__/utils.d.ts +1 -11
  53. package/dist/types/jats/exporter/jats-exporter.d.ts +5 -10
  54. package/dist/types/jats/importer/jats-dom-parser.d.ts +0 -15
  55. package/dist/types/jats/importer/parse-jats-article.d.ts +1 -11
  56. package/dist/types/schema/__tests__/docs.d.ts +2 -0
  57. package/dist/types/schema/migration/migration-scripts/4.3.12.d.ts +8 -0
  58. package/dist/types/schema/migration/migration-scripts/index.d.ts +2 -1
  59. package/dist/types/schema/nodes/comment.d.ts +2 -2
  60. package/dist/types/schema/nodes/contributor.d.ts +11 -21
  61. package/dist/types/schema/types.d.ts +22 -0
  62. package/dist/types/transformer/node-names.d.ts +1 -0
  63. package/dist/types/transformer/node-types.d.ts +0 -2
  64. package/dist/types/version.d.ts +1 -1
  65. package/package.json +2 -2
  66. package/dist/cjs/jats/importer/jats-journal-meta-parser.js +0 -103
  67. package/dist/cjs/lib/styled-content.js +0 -28
  68. package/dist/es/jats/importer/jats-journal-meta-parser.js +0 -95
  69. package/dist/es/lib/styled-content.js +0 -23
  70. package/dist/types/jats/importer/jats-journal-meta-parser.d.ts +0 -46
  71. package/dist/types/lib/styled-content.d.ts +0 -22
@@ -30,28 +30,15 @@ const uuidRegex = /[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[
30
30
  const replaceUUIDWithTest = (input) => input.replace(uuidRegex, 'test');
31
31
  const updateContributorNodeIDs = (node) => {
32
32
  if ((0, schema_1.isContributorNode)(node)) {
33
- node.attrs.footnote = node.attrs.footnote.map((fn) => {
34
- return { ...fn, noteID: replaceUUIDWithTest(fn.noteID) };
35
- });
36
- node.attrs.corresp = node.attrs.corresp.map((corresp) => {
37
- return { ...corresp, correspID: replaceUUIDWithTest(corresp.correspID) };
38
- });
39
- node.attrs.affiliations = node.attrs.affiliations.map((aff) => replaceUUIDWithTest(aff));
40
- if (node.attrs.bibliographicName._id) {
41
- node.attrs.bibliographicName._id = replaceUUIDWithTest(node.attrs.bibliographicName._id);
42
- }
33
+ node.attrs.footnoteIDs = node.attrs.footnoteIDs?.map((id) => replaceUUIDWithTest(id));
34
+ node.attrs.correspIDs = node.attrs.correspIDs?.map((id) => replaceUUIDWithTest(id));
35
+ node.attrs.affiliationIDs = node.attrs.affiliationIDs?.map((id) => replaceUUIDWithTest(id));
43
36
  }
44
37
  };
45
38
  const updateCommentNodeIDs = (node) => {
46
39
  if ((0, schema_1.isCommentNode)(node)) {
47
40
  node.attrs.target = replaceUUIDWithTest(node.attrs.target);
48
- node.attrs.contributions = node.attrs.contributions?.map((contribution) => {
49
- return {
50
- ...contribution,
51
- _id: replaceUUIDWithTest(contribution._id),
52
- timestamp: 1234,
53
- };
54
- });
41
+ node.attrs.timestamp = 1234;
55
42
  }
56
43
  };
57
44
  const updateNodeRID = (node) => {
@@ -138,7 +138,7 @@ class JATSExporter {
138
138
  this.document = document.implementation.createDocument(null, 'article', document.implementation.createDocumentType('article', versionIds.publicId, versionIds.systemId));
139
139
  const article = this.document.documentElement;
140
140
  article.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xlink', xml_1.XLINK_NAMESPACE);
141
- const front = this.buildFront(options.journal);
141
+ const front = this.buildFront();
142
142
  article.appendChild(front);
143
143
  article.setAttribute('article-type', manuscriptNode.attrs.articleType || 'other');
144
144
  article.setAttributeNS(xml_1.XML_NAMESPACE, 'lang', manuscriptNode.attrs.primaryLanguageCode || 'en');
@@ -247,60 +247,10 @@ class JATSExporter {
247
247
  }
248
248
  }
249
249
  };
250
- this.buildFront = (journal) => {
250
+ this.buildFront = () => {
251
251
  const front = this.createElement('front');
252
- const journalMeta = this.createElement('journal-meta');
253
- front.appendChild(journalMeta);
254
252
  const articleMeta = this.createElement('article-meta');
255
253
  front.appendChild(articleMeta);
256
- if (journal) {
257
- if (journal.journalIdentifiers) {
258
- for (const item of journal.journalIdentifiers) {
259
- const element = this.createElement('journal-id');
260
- if (item.journalIDType) {
261
- element.setAttribute('journal-id-type', item.journalIDType);
262
- }
263
- element.textContent = item.journalID;
264
- journalMeta.appendChild(element);
265
- }
266
- }
267
- if (journal.title || journal.abbreviatedTitles) {
268
- const parentElement = this.createElement('journal-title-group');
269
- journalMeta.appendChild(parentElement);
270
- if (journal.title) {
271
- const element = this.createElement('journal-title');
272
- element.textContent = journal.title;
273
- parentElement.appendChild(element);
274
- }
275
- if (journal.abbreviatedTitles) {
276
- for (const item of journal.abbreviatedTitles) {
277
- const element = this.createElement('abbrev-journal-title');
278
- if (item.abbrevType) {
279
- element.setAttribute('abbrev-type', item.abbrevType);
280
- }
281
- element.textContent = item.abbreviatedTitle;
282
- parentElement.appendChild(element);
283
- }
284
- }
285
- }
286
- if (journal.ISSNs) {
287
- for (const item of journal.ISSNs) {
288
- const element = this.createElement('issn');
289
- if (item.publicationType) {
290
- element.setAttribute('pub-type', item.publicationType);
291
- }
292
- element.textContent = item.ISSN;
293
- journalMeta.appendChild(element);
294
- }
295
- }
296
- if (journal.publisherName) {
297
- const publisher = this.createElement('publisher');
298
- const publisherName = this.createElement('publisher-name');
299
- publisherName.textContent = journal.publisherName;
300
- publisher.appendChild(publisherName);
301
- journalMeta.appendChild(publisher);
302
- }
303
- }
304
254
  if (this.manuscriptNode.attrs.doi) {
305
255
  const articleID = this.createElement('article-id');
306
256
  articleID.setAttribute('pub-id-type', 'doi');
@@ -385,18 +335,15 @@ class JATSExporter {
385
335
  counts.append(...countingElements);
386
336
  articleMeta.append(counts);
387
337
  }
388
- if (!journalMeta.hasChildNodes()) {
389
- journalMeta.remove();
390
- }
391
- const selfUriAttachments = this.getChildrenOfType(schema_1.schema.nodes.attachment);
392
- selfUriAttachments.forEach((attachment) => {
393
- const selfUriElement = this.createElement('self-uri');
394
- selfUriElement.setAttribute('content-type', attachment.attrs.type);
395
- selfUriElement.setAttributeNS(xml_1.XLINK_NAMESPACE, 'href', attachment.attrs.href);
338
+ const attachments = this.getChildrenOfType(schema_1.schema.nodes.attachment);
339
+ attachments.forEach((attachment) => {
340
+ const $selfUri = this.createElement('self-uri');
341
+ $selfUri.setAttribute('content-type', attachment.attrs.type);
342
+ $selfUri.setAttributeNS(xml_1.XLINK_NAMESPACE, 'href', attachment.attrs.href);
396
343
  const insertBeforeElements = articleMeta.querySelector('related-article, related-object, abstract, trans-abstract, kwd-group, funding-group, support-group, conference, counts, custom-meta-group');
397
344
  insertBeforeElements
398
- ? articleMeta.insertBefore(selfUriElement, insertBeforeElements)
399
- : articleMeta.appendChild(selfUriElement);
345
+ ? articleMeta.insertBefore($selfUri, insertBeforeElements)
346
+ : articleMeta.appendChild($selfUri);
400
347
  });
401
348
  return front;
402
349
  };
@@ -1007,219 +954,219 @@ class JATSExporter {
1007
954
  this.serializeNode = (node) => this.serializer.serializeNode(node, {
1008
955
  document: this.document,
1009
956
  });
1010
- this.validateContributor = (contributor) => {
1011
- if (!contributor.attrs.bibliographicName) {
1012
- throw new Error(`${contributor.attrs.id} has no bibliographicName`);
1013
- }
1014
- const { family, given } = contributor.attrs.bibliographicName;
1015
- if (!family && !given) {
1016
- throw new Error(`${contributor.attrs.id} has neither family nor given name`);
1017
- }
1018
- };
1019
957
  this.buildContributors = (articleMeta) => {
1020
958
  const contributors = this.getChildrenOfType(schema_1.schema.nodes.contributor).sort(sortContributors);
1021
- const affiliationLabels = new Map();
1022
- const creatAffiliationLabel = (rid) => {
1023
- let label = affiliationLabels.get(rid);
959
+ if (!contributors.length) {
960
+ return;
961
+ }
962
+ const labels = new Map();
963
+ const createLabel = (id) => {
964
+ let label = labels.get(id);
1024
965
  if (!label) {
1025
- label = String(affiliationLabels.size + 1);
1026
- affiliationLabels.set(rid, label);
966
+ label = labels.size + 1;
967
+ labels.set(id, label);
1027
968
  }
1028
969
  const sup = this.createElement('sup');
1029
970
  sup.textContent = String(label);
1030
971
  return sup;
1031
972
  };
1032
- const createFootNotesLabels = (content) => {
1033
- const sup = this.createElement('sup');
1034
- sup.textContent = String(content);
1035
- return sup;
1036
- };
1037
- if (contributors.length) {
1038
- const contribGroup = this.createElement('contrib-group');
1039
- contribGroup.setAttribute('content-type', 'authors');
1040
- articleMeta.appendChild(contribGroup);
1041
- contributors.forEach((contributor) => {
1042
- try {
1043
- this.validateContributor(contributor);
1044
- }
1045
- catch (error) {
1046
- return;
1047
- }
1048
- const contrib = this.createElement('contrib');
1049
- contrib.setAttribute('contrib-type', 'author');
1050
- contrib.setAttribute('id', normalizeID(contributor.attrs.id));
1051
- if (contributor.attrs.isCorresponding) {
1052
- contrib.setAttribute('corresp', 'yes');
1053
- }
1054
- if (contributor.attrs.role) {
1055
- this.appendElement(contrib, 'role', contributor.attrs.role);
1056
- }
1057
- if (contributor.attrs.ORCIDIdentifier) {
1058
- this.appendElement(contrib, 'contrib-id', contributor.attrs.ORCIDIdentifier, { 'contrib-id-type': 'orcid' });
1059
- }
1060
- const name = this.buildContributorName(contributor);
1061
- contrib.appendChild(name);
1062
- if (contributor.attrs.email) {
1063
- this.appendElement(contrib, 'email', contributor.attrs.email);
1064
- }
1065
- if (contributor.attrs.affiliations) {
1066
- contributor.attrs.affiliations.forEach((rid) => {
1067
- const xref = this.appendElement(contrib, 'xref', '', {
1068
- 'ref-type': 'aff',
1069
- rid: normalizeID(rid),
1070
- });
1071
- xref.appendChild(creatAffiliationLabel(rid));
1072
- contrib.appendChild(xref);
1073
- });
1074
- }
1075
- if (contributor.attrs.footnote) {
1076
- contributor.attrs.footnote.map((note) => {
1077
- const xref = this.appendElement(contrib, 'xref', '', {
1078
- 'ref-type': 'fn',
1079
- rid: normalizeID(note.noteID),
1080
- });
1081
- xref.appendChild(createFootNotesLabels(note.noteLabel));
1082
- contrib.appendChild(xref);
1083
- });
1084
- }
1085
- if (contributor.attrs.corresp) {
1086
- contributor.attrs.corresp.map((corresp) => {
1087
- const xref = this.appendElement(contrib, 'xref', '', {
1088
- 'ref-type': 'corresp',
1089
- rid: normalizeID(corresp.correspID),
1090
- });
1091
- xref.appendChild(createFootNotesLabels(corresp.correspLabel));
1092
- contrib.appendChild(xref);
1093
- });
1094
- }
1095
- if (contributor.attrs.creditRoles) {
1096
- contributor.attrs.creditRoles.forEach((cr) => {
1097
- const role = this.createElement('role');
1098
- const creditUrl = credit_roles_1.CreditRoleUrls.get(cr.vocabTerm);
1099
- if (creditUrl) {
1100
- role.setAttribute('vocab-identifier', 'http://credit.niso.org/');
1101
- role.setAttribute('vocab', 'CRediT');
1102
- role.setAttribute('vocab-term', cr.vocabTerm);
1103
- role.setAttribute('vocab-term-identifier', creditUrl);
1104
- role.textContent = cr.vocabTerm;
1105
- }
1106
- contrib.appendChild(role);
1107
- });
1108
- }
1109
- contribGroup.appendChild(contrib);
1110
- });
1111
- const affiliationRIDs = [];
1112
- for (const contributor of contributors) {
1113
- if (contributor.attrs.affiliations) {
1114
- affiliationRIDs.push(...contributor.attrs.affiliations);
1115
- }
973
+ const $contribGroup = this.createElement('contrib-group');
974
+ $contribGroup.setAttribute('content-type', 'authors');
975
+ articleMeta.appendChild($contribGroup);
976
+ contributors.forEach((contributor) => {
977
+ const $contrib = this.createElement('contrib');
978
+ $contrib.setAttribute('contrib-type', 'author');
979
+ $contrib.setAttribute('id', normalizeID(contributor.attrs.id));
980
+ if (contributor.attrs.isCorresponding) {
981
+ $contrib.setAttribute('corresp', 'yes');
982
+ }
983
+ if (contributor.attrs.role) {
984
+ this.appendElement($contrib, 'role', contributor.attrs.role);
1116
985
  }
1117
- const affiliationIDs = contributors.flatMap((n) => n.attrs.affiliations);
1118
- const sortAffiliations = (a, b) => affiliationIDs.indexOf(a.attrs.id) - affiliationIDs.indexOf(b.attrs.id);
1119
- this.getChildrenOfType(schema_1.schema.nodes.affiliation)
1120
- .filter((a) => affiliationIDs.includes(a.attrs.id))
1121
- .sort(sortAffiliations)
1122
- .forEach((affiliation) => {
1123
- const $aff = this.createElement('aff', '', {
1124
- id: normalizeID(affiliation.attrs.id),
986
+ if (contributor.attrs.ORCID) {
987
+ this.appendElement($contrib, 'contrib-id', contributor.attrs.ORCID, {
988
+ 'contrib-id-type': 'orcid',
1125
989
  });
1126
- const label = affiliationLabels.get(affiliation.attrs.id);
1127
- if (label) {
1128
- this.appendElement($aff, 'label', String(label));
1129
- }
1130
- const affiliationParts = [
1131
- {
1132
- value: affiliation.attrs.department,
1133
- tag: 'institution',
1134
- 'content-type': 'dept',
1135
- },
1136
- { value: affiliation.attrs.institution, tag: 'institution' },
1137
- { value: affiliation.attrs.addressLine1, tag: 'addr-line' },
1138
- { value: affiliation.attrs.addressLine2, tag: 'addr-line' },
1139
- { value: affiliation.attrs.addressLine3, tag: 'addr-line' },
1140
- { value: affiliation.attrs.city, tag: 'city' },
1141
- { value: affiliation.attrs.county, tag: 'state' },
1142
- { value: affiliation.attrs.country, tag: 'country' },
1143
- { value: affiliation.attrs.postCode, tag: 'postal-code' },
1144
- ].filter((obj) => obj.value);
1145
- affiliationParts.forEach((location, index) => {
1146
- if (index) {
1147
- const punctuation = this.document.createTextNode(', ');
1148
- $aff.appendChild(punctuation);
1149
- }
1150
- const { tag, value, ...rest } = location;
1151
- this.appendElement($aff, tag, value, rest);
990
+ }
991
+ const $name = this.buildContributorName(contributor);
992
+ $contrib.appendChild($name);
993
+ if (contributor.attrs.email) {
994
+ this.appendElement($contrib, 'email', contributor.attrs.email);
995
+ }
996
+ contributor.attrs.affiliationIDs?.forEach((rid) => {
997
+ const $xref = this.appendElement($contrib, 'xref', '', {
998
+ 'ref-type': 'aff',
999
+ rid: normalizeID(rid),
1000
+ });
1001
+ $xref.appendChild(createLabel(rid));
1002
+ });
1003
+ contributor.attrs.footnoteIDs?.forEach((rid) => {
1004
+ const $xref = this.appendElement($contrib, 'xref', '', {
1005
+ 'ref-type': 'fn',
1006
+ rid: normalizeID(rid),
1152
1007
  });
1153
- const { href, text } = affiliation.attrs.email ?? {};
1154
- if (href) {
1155
- const email = this.appendElement($aff, 'email', text ?? href);
1156
- email.setAttributeNS(xml_1.XLINK_NAMESPACE, 'href', href);
1008
+ $xref.appendChild(createLabel(rid));
1009
+ });
1010
+ contributor.attrs.correspIDs?.forEach((rid) => {
1011
+ const $xref = this.appendElement($contrib, 'xref', '', {
1012
+ 'ref-type': 'corresp',
1013
+ rid: normalizeID(rid),
1014
+ });
1015
+ $xref.appendChild(createLabel(rid));
1016
+ });
1017
+ contributor.attrs.creditRoles?.forEach((credit) => {
1018
+ const url = credit_roles_1.CreditRoleUrls.get(credit.vocabTerm);
1019
+ if (!url) {
1020
+ return;
1157
1021
  }
1158
- contribGroup.appendChild($aff);
1022
+ this.appendElement($contrib, 'role', credit.vocabTerm, {
1023
+ 'vocab-identifier': 'http://credit.niso.org/',
1024
+ 'vocab': 'CRediT',
1025
+ 'vocab-term': credit.vocabTerm,
1026
+ 'vocab-term-identifier': url,
1027
+ });
1159
1028
  });
1160
- const authorNotesEl = this.createAuthorNotesElement();
1161
- if (authorNotesEl.childNodes.length > 0) {
1162
- articleMeta.insertBefore(authorNotesEl, contribGroup.nextSibling);
1029
+ $contribGroup.appendChild($contrib);
1030
+ });
1031
+ const affiliationIDs = contributors.flatMap((n) => n.attrs.affiliationIDs);
1032
+ const sortAffiliations = (a, b) => affiliationIDs.indexOf(a.attrs.id) - affiliationIDs.indexOf(b.attrs.id);
1033
+ this.getChildrenOfType(schema_1.schema.nodes.affiliation)
1034
+ .filter((a) => affiliationIDs.includes(a.attrs.id))
1035
+ .sort(sortAffiliations)
1036
+ .forEach((affiliation) => {
1037
+ const $content = [];
1038
+ if (affiliation.attrs.department) {
1039
+ const $institution = this.createElement('institution', affiliation.attrs.department, {
1040
+ 'content-type': 'dept',
1041
+ });
1042
+ $content.push($institution);
1043
+ }
1044
+ if (affiliation.attrs.institution) {
1045
+ const $institution = this.createElement('institution', affiliation.attrs.institution);
1046
+ $content.push($institution);
1163
1047
  }
1048
+ if (affiliation.attrs.addressLine1) {
1049
+ const $addrLine = this.createElement('addr-line', affiliation.attrs.addressLine1);
1050
+ $content.push($addrLine);
1051
+ }
1052
+ if (affiliation.attrs.addressLine2) {
1053
+ const $addrLine = this.createElement('addr-line', affiliation.attrs.addressLine2);
1054
+ $content.push($addrLine);
1055
+ }
1056
+ if (affiliation.attrs.addressLine3) {
1057
+ const $addrLine = this.createElement('addr-line', affiliation.attrs.addressLine3);
1058
+ $content.push($addrLine);
1059
+ }
1060
+ if (affiliation.attrs.city) {
1061
+ const $city = this.createElement('city', affiliation.attrs.city);
1062
+ $content.push($city);
1063
+ }
1064
+ if (affiliation.attrs.county) {
1065
+ const $state = this.createElement('state', affiliation.attrs.county);
1066
+ $content.push($state);
1067
+ }
1068
+ if (affiliation.attrs.country) {
1069
+ const $country = this.createElement('country', affiliation.attrs.country);
1070
+ $content.push($country);
1071
+ }
1072
+ if (affiliation.attrs.postCode) {
1073
+ const $postalCode = this.createElement('postal-code', affiliation.attrs.postCode);
1074
+ $content.push($postalCode);
1075
+ }
1076
+ const $aff = this.createElement('aff');
1077
+ $aff.setAttribute('id', normalizeID(affiliation.attrs.id));
1078
+ $contribGroup.appendChild($aff);
1079
+ const label = labels.get(affiliation.attrs.id);
1080
+ if (label) {
1081
+ this.appendElement($aff, 'label', String(label));
1082
+ }
1083
+ $content.forEach((node, i) => {
1084
+ if (i > 0) {
1085
+ $aff.appendChild(this.document.createTextNode(', '));
1086
+ }
1087
+ $aff.appendChild(node);
1088
+ });
1089
+ });
1090
+ const $authorNotes = this.createAuthorNotesElement(contributors);
1091
+ if ($authorNotes) {
1092
+ articleMeta.insertBefore($authorNotes, $contribGroup.nextSibling);
1164
1093
  }
1165
1094
  };
1166
1095
  this.buildContributorName = (contributor) => {
1167
- const { given, family } = contributor.attrs.bibliographicName;
1096
+ const { given, family } = contributor.attrs;
1168
1097
  if (Boolean(given) !== Boolean(family)) {
1169
1098
  return this.createElement('string-name', given || family);
1170
1099
  }
1171
1100
  const name = this.createElement('name');
1172
- if (contributor.attrs.bibliographicName.family) {
1173
- this.appendElement(name, 'surname', contributor.attrs.bibliographicName.family);
1101
+ if (contributor.attrs.family) {
1102
+ this.appendElement(name, 'surname', contributor.attrs.family);
1174
1103
  }
1175
- if (contributor.attrs.bibliographicName.given) {
1176
- this.appendElement(name, 'given-names', contributor.attrs.bibliographicName.given);
1104
+ if (contributor.attrs.given) {
1105
+ this.appendElement(name, 'given-names', contributor.attrs.given);
1177
1106
  }
1178
1107
  if (contributor.attrs.prefix) {
1179
1108
  this.appendElement(name, 'prefix', contributor.attrs.prefix);
1180
1109
  }
1181
1110
  return name;
1182
1111
  };
1183
- this.createAuthorNotesElement = () => {
1184
- const authorNotesEl = this.createElement('author-notes');
1185
- const authorNotesNode = this.getFirstChildOfType(schema_1.schema.nodes.author_notes);
1186
- if (authorNotesNode) {
1187
- this.appendModelsToAuthorNotes(authorNotesEl, authorNotesNode);
1112
+ this.createAuthorNotesElement = (contributors) => {
1113
+ const authorNotes = this.getFirstChildOfType(schema_1.schema.nodes.author_notes);
1114
+ if (!authorNotes || !authorNotes.childCount) {
1115
+ return;
1188
1116
  }
1189
- return authorNotesEl;
1117
+ const $authorNotes = this.createElement('author-notes');
1118
+ const used = contributors.flatMap((c) => c.attrs.correspIDs);
1119
+ authorNotes.descendants((node) => {
1120
+ switch (node.type) {
1121
+ case schema_1.schema.nodes.paragraph: {
1122
+ const $p = this.writeParagraph(node);
1123
+ $authorNotes.append($p);
1124
+ break;
1125
+ }
1126
+ case schema_1.schema.nodes.footnote: {
1127
+ const $fn = this.writeFootnote(node);
1128
+ $authorNotes.append($fn);
1129
+ break;
1130
+ }
1131
+ case schema_1.schema.nodes.corresp: {
1132
+ if (used.includes(node.attrs.id)) {
1133
+ const $corresp = this.writeCorresp(node);
1134
+ $authorNotes.append($corresp);
1135
+ }
1136
+ break;
1137
+ }
1138
+ }
1139
+ return false;
1140
+ });
1141
+ return $authorNotes;
1190
1142
  };
1191
- this.appendCorrespondingToElement = (corresponding, element) => {
1192
- const correspondingEl = this.createElement('corresp');
1193
- correspondingEl.setAttribute('id', normalizeID(corresponding.attrs.id));
1194
- if (corresponding.attrs.label) {
1195
- const labelEl = this.createElement('label');
1196
- labelEl.textContent = corresponding.attrs.label;
1197
- correspondingEl.appendChild(labelEl);
1198
- }
1199
- correspondingEl.append(corresponding.textContent);
1200
- element.appendChild(correspondingEl);
1143
+ this.writeCorresp = (corresp) => {
1144
+ const $corresp = this.createElement('corresp');
1145
+ $corresp.setAttribute('id', normalizeID(corresp.attrs.id));
1146
+ if (corresp.attrs.label) {
1147
+ this.appendElement($corresp, 'label', corresp.attrs.label);
1148
+ }
1149
+ $corresp.append(corresp.textContent);
1150
+ return $corresp;
1201
1151
  };
1202
- this.appendParagraphToElement = (paragraph, element) => {
1203
- const parsedDoc = new DOMParser().parseFromString(paragraph.textContent, 'text/html');
1204
- if (parsedDoc.body.innerHTML.length) {
1205
- const paragraphEl = this.createElement('p');
1206
- paragraphEl.innerHTML = parsedDoc.body.innerHTML;
1207
- paragraphEl.setAttribute('id', normalizeID(paragraph.attrs.id));
1208
- element.appendChild(paragraphEl);
1209
- }
1152
+ this.writeParagraph = (paragraph) => {
1153
+ const dom = new DOMParser().parseFromString(paragraph.textContent, 'text/html');
1154
+ const $p = this.createElement('p');
1155
+ $p.setAttribute('id', normalizeID(paragraph.attrs.id));
1156
+ if (dom.body.innerHTML.length) {
1157
+ $p.innerHTML = dom.body.innerHTML;
1158
+ }
1159
+ return $p;
1210
1160
  };
1211
- this.appendFootnoteToElement = (footnote, element) => {
1212
- const footnoteEl = this.createElement('fn');
1213
- footnoteEl.setAttribute('id', normalizeID(footnote.attrs.id));
1214
- if (!footnote.textContent.includes('<p>')) {
1215
- const p = this.createElement('p');
1216
- p.innerHTML = footnote.textContent;
1217
- footnoteEl.appendChild(p);
1218
- }
1219
- else {
1220
- footnoteEl.innerHTML = footnote.textContent;
1221
- }
1222
- element.appendChild(footnoteEl);
1161
+ this.writeFootnote = (footnote) => {
1162
+ const $fn = this.createElement('fn');
1163
+ $fn.setAttribute('id', normalizeID(footnote.attrs.id));
1164
+ let content = footnote.textContent;
1165
+ if (!content.includes('<p>')) {
1166
+ content = `<p>${content}</p>`;
1167
+ }
1168
+ $fn.innerHTML = content;
1169
+ return $fn;
1223
1170
  };
1224
1171
  this.fixBody = (body) => {
1225
1172
  this.manuscriptNode.descendants((node) => {
@@ -1277,7 +1224,6 @@ class JATSExporter {
1277
1224
  }
1278
1225
  const tbodyRows = Array.from(tbody.childNodes);
1279
1226
  const thead = this.createElement('thead');
1280
- const tfoot = this.createElement('tfoot');
1281
1227
  tbodyRows.forEach((row, i) => {
1282
1228
  const isRow = row instanceof Element && row.tagName.toLowerCase() === 'tr';
1283
1229
  if (isRow) {
@@ -1290,18 +1236,11 @@ class JATSExporter {
1290
1236
  }
1291
1237
  thead.appendChild(row);
1292
1238
  }
1293
- else if (i === tbodyRows.length - 1) {
1294
- tbody?.removeChild(row);
1295
- tfoot.appendChild(row);
1296
- }
1297
1239
  }
1298
1240
  });
1299
1241
  if (thead.hasChildNodes()) {
1300
1242
  table.insertBefore(thead, tbody);
1301
1243
  }
1302
- if (tfoot.hasChildNodes()) {
1303
- table.insertBefore(tfoot, tbody);
1304
- }
1305
1244
  };
1306
1245
  this.unwrapBody = (body) => {
1307
1246
  const container = body.querySelector(':scope > sec[sec-type="body"]');
@@ -1479,34 +1418,6 @@ class JATSExporter {
1479
1418
  return mathml;
1480
1419
  }
1481
1420
  }
1482
- appendModelsToAuthorNotes(authorNotesEl, authorNotesNode) {
1483
- const contributorsNodes = this.getChildrenOfType(schema_1.schema.nodes.contributor);
1484
- const usedCorrespondings = this.getUsedCorrespondings(contributorsNodes);
1485
- authorNotesNode.descendants((node) => {
1486
- switch (node.type) {
1487
- case schema_1.schema.nodes.paragraph:
1488
- this.appendParagraphToElement(node, authorNotesEl);
1489
- break;
1490
- case schema_1.schema.nodes.footnote:
1491
- this.appendFootnoteToElement(node, authorNotesEl);
1492
- break;
1493
- case schema_1.schema.nodes.corresp:
1494
- if (usedCorrespondings.includes(node)) {
1495
- this.appendCorrespondingToElement(node, authorNotesEl);
1496
- }
1497
- break;
1498
- }
1499
- return false;
1500
- });
1501
- }
1502
- getUsedCorrespondings(contributors) {
1503
- return contributors
1504
- .flatMap((c) => c.attrs.corresp ?? [])
1505
- .map((corresp) => {
1506
- return (0, prosemirror_utils_1.findChildrenByAttr)(this.manuscriptNode, (attr) => attr.id === corresp.correspID)[0]?.node;
1507
- })
1508
- .filter((corresp) => !!corresp);
1509
- }
1510
1421
  buildKeywords(articleMeta) {
1511
1422
  const keywordGroups = this.getChildrenOfType(schema_1.schema.nodes.keyword_group);
1512
1423
  keywordGroups.forEach((group) => {