@manuscripts/transform 3.0.61 → 3.0.63-LEAN-4531.0

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.
@@ -25,6 +25,7 @@ const debug_1 = __importDefault(require("debug"));
25
25
  const prosemirror_model_1 = require("prosemirror-model");
26
26
  const prosemirror_utils_1 = require("prosemirror-utils");
27
27
  const w3c_xmlserializer_1 = __importDefault(require("w3c-xmlserializer"));
28
+ const credit_roles_1 = require("../../lib/credit-roles");
28
29
  const footnotes_1 = require("../../lib/footnotes");
29
30
  const html_1 = require("../../lib/html");
30
31
  const schema_1 = require("../../schema");
@@ -1056,13 +1057,7 @@ class JATSExporter {
1056
1057
  }
1057
1058
  };
1058
1059
  this.buildContributors = (articleMeta) => {
1059
- const contributorNodes = this.getChildrenOfType(schema_1.schema.nodes.contributor);
1060
- const authorContributorNodes = contributorNodes
1061
- .filter((n) => n.attrs.role === 'author')
1062
- .sort(sortContributors);
1063
- const otherContributorsNodes = contributorNodes
1064
- .filter((n) => n.attrs.role !== 'author')
1065
- .sort(sortContributors);
1060
+ const contributorNodes = this.getChildrenOfType(schema_1.schema.nodes.contributor).sort(sortContributors);
1066
1061
  const affiliationLabels = new Map();
1067
1062
  const creatAffiliationLabel = (rid) => {
1068
1063
  let label = affiliationLabels.get(rid);
@@ -1079,11 +1074,11 @@ class JATSExporter {
1079
1074
  sup.textContent = String(content);
1080
1075
  return sup;
1081
1076
  };
1082
- if (authorContributorNodes.length) {
1077
+ if (contributorNodes.length) {
1083
1078
  const contribGroup = this.createElement('contrib-group');
1084
1079
  contribGroup.setAttribute('content-type', 'authors');
1085
1080
  articleMeta.appendChild(contribGroup);
1086
- authorContributorNodes.forEach((contributor) => {
1081
+ contributorNodes.forEach((contributor) => {
1087
1082
  try {
1088
1083
  this.validateContributor(contributor);
1089
1084
  }
@@ -1097,95 +1092,68 @@ class JATSExporter {
1097
1092
  if (contributor.attrs.isCorresponding) {
1098
1093
  contrib.setAttribute('corresp', 'yes');
1099
1094
  }
1095
+ if (contributor.attrs.role) {
1096
+ this.appendElement(contrib, 'role', contributor.attrs.role);
1097
+ }
1100
1098
  if (contributor.attrs.ORCIDIdentifier) {
1101
- const identifier = this.createElement('contrib-id');
1102
- identifier.setAttribute('contrib-id-type', 'orcid');
1103
- identifier.textContent = contributor.attrs.ORCIDIdentifier;
1104
- contrib.appendChild(identifier);
1099
+ this.appendElement(contrib, 'contrib-id', contributor.attrs.ORCIDIdentifier, { 'contrib-id-type': 'orcid' });
1105
1100
  }
1106
1101
  const name = this.buildContributorName(contributor);
1107
1102
  contrib.appendChild(name);
1108
1103
  if (contributor.attrs.email) {
1109
- const email = this.createElement('email');
1110
- email.textContent = contributor.attrs.email;
1111
- contrib.appendChild(email);
1104
+ this.appendElement(contrib, 'email', contributor.attrs.email);
1112
1105
  }
1113
1106
  if (contributor.attrs.affiliations) {
1114
1107
  contributor.attrs.affiliations.forEach((rid) => {
1115
- const xref = this.createElement('xref');
1116
- xref.setAttribute('ref-type', 'aff');
1117
- xref.setAttribute('rid', normalizeID(rid));
1108
+ const xref = this.appendElement(contrib, 'xref', '', {
1109
+ 'ref-type': 'aff',
1110
+ rid: normalizeID(rid),
1111
+ });
1118
1112
  xref.appendChild(creatAffiliationLabel(rid));
1119
1113
  contrib.appendChild(xref);
1120
1114
  });
1121
1115
  }
1122
1116
  if (contributor.attrs.footnote) {
1123
1117
  contributor.attrs.footnote.map((note) => {
1124
- const xref = this.createElement('xref');
1125
- xref.setAttribute('ref-type', 'fn');
1126
- xref.setAttribute('rid', normalizeID(note.noteID));
1118
+ const xref = this.appendElement(contrib, 'xref', '', {
1119
+ 'ref-type': 'fn',
1120
+ rid: normalizeID(note.noteID),
1121
+ });
1127
1122
  xref.appendChild(createFootNotesLabels(note.noteLabel));
1128
1123
  contrib.appendChild(xref);
1129
1124
  });
1130
1125
  }
1131
1126
  if (contributor.attrs.corresp) {
1132
1127
  contributor.attrs.corresp.map((corresp) => {
1133
- const xref = this.createElement('xref');
1134
- xref.setAttribute('ref-type', 'corresp');
1135
- xref.setAttribute('rid', normalizeID(corresp.correspID));
1128
+ const xref = this.appendElement(contrib, 'xref', '', {
1129
+ 'ref-type': 'corresp',
1130
+ rid: normalizeID(corresp.correspID),
1131
+ });
1136
1132
  xref.appendChild(createFootNotesLabels(corresp.correspLabel));
1137
1133
  contrib.appendChild(xref);
1138
1134
  });
1139
1135
  }
1136
+ if (contributor.attrs.CRediTRoles) {
1137
+ contributor.attrs.CRediTRoles.forEach((cr) => {
1138
+ const role = this.createElement('role');
1139
+ const creditUrl = credit_roles_1.CRediTRoleUrls.get(cr.vocabTerm);
1140
+ if (creditUrl) {
1141
+ role.setAttribute('vocab-identifier', 'http://credit.niso.org/');
1142
+ role.setAttribute('vocab', 'CRediT');
1143
+ role.setAttribute('vocab-term', cr.vocabTerm);
1144
+ role.setAttribute('vocab-term-identifier', creditUrl);
1145
+ role.innerHTML = cr.vocabTerm;
1146
+ }
1147
+ if (cr.degreeContribution) {
1148
+ role.setAttribute('degree-contribution', cr.degreeContribution);
1149
+ }
1150
+ contrib.appendChild(role);
1151
+ });
1152
+ }
1140
1153
  contribGroup.appendChild(contrib);
1141
1154
  });
1142
- if (otherContributorsNodes.length) {
1143
- const contribGroup = this.createElement('contrib-group');
1144
- articleMeta.appendChild(contribGroup);
1145
- otherContributorsNodes.forEach((contributor) => {
1146
- try {
1147
- this.validateContributor(contributor);
1148
- }
1149
- catch (error) {
1150
- warn(error.message);
1151
- return;
1152
- }
1153
- const contrib = this.createElement('contrib');
1154
- contrib.setAttribute('id', normalizeID(contributor.attrs.id));
1155
- const name = this.buildContributorName(contributor);
1156
- contrib.appendChild(name);
1157
- if (contributor.attrs.email) {
1158
- const email = this.createElement('email');
1159
- email.textContent = contributor.attrs.email;
1160
- contrib.appendChild(email);
1161
- }
1162
- if (contributor.attrs.affiliations) {
1163
- contributor.attrs.affiliations.forEach((rid) => {
1164
- const xref = this.createElement('xref');
1165
- xref.setAttribute('ref-type', 'aff');
1166
- xref.setAttribute('rid', normalizeID(rid));
1167
- xref.appendChild(creatAffiliationLabel(rid));
1168
- contrib.appendChild(xref);
1169
- });
1170
- }
1171
- if (contributor.attrs.footnote) {
1172
- contributor.attrs.footnote.map((note) => {
1173
- const xref = this.createElement('xref');
1174
- xref.setAttribute('ref-type', 'fn');
1175
- xref.setAttribute('rid', normalizeID(note.noteID));
1176
- xref.appendChild(createFootNotesLabels(note.noteLabel));
1177
- contrib.appendChild(xref);
1178
- });
1179
- }
1180
- contribGroup.appendChild(contrib);
1181
- });
1182
- }
1183
1155
  const affiliationRIDs = [];
1184
- const sortedContributors = [
1185
- ...authorContributorNodes,
1186
- ...otherContributorsNodes,
1187
- ];
1188
- for (const contributor of sortedContributors) {
1156
+ for (const contributor of contributorNodes) {
1189
1157
  if (contributor.attrs.affiliations) {
1190
1158
  affiliationRIDs.push(...contributor.attrs.affiliations);
1191
1159
  }
@@ -1534,14 +1502,13 @@ class JATSExporter {
1534
1502
  this.buildContributorName = (contributor) => {
1535
1503
  const name = this.createElement('name');
1536
1504
  if (contributor.attrs.bibliographicName.family) {
1537
- const surname = this.createElement('surname');
1538
- surname.textContent = contributor.attrs.bibliographicName.family;
1539
- name.appendChild(surname);
1505
+ this.appendElement(name, 'surname', contributor.attrs.bibliographicName.family);
1540
1506
  }
1541
1507
  if (contributor.attrs.bibliographicName.given) {
1542
- const givenNames = this.createElement('given-names');
1543
- givenNames.textContent = contributor.attrs.bibliographicName.given;
1544
- name.appendChild(givenNames);
1508
+ this.appendElement(name, 'given-names', contributor.attrs.bibliographicName.given);
1509
+ }
1510
+ if (contributor.attrs.prefix) {
1511
+ this.appendElement(name, 'prefix', contributor.attrs.prefix);
1545
1512
  }
1546
1513
  return name;
1547
1514
  };
@@ -402,8 +402,8 @@ class JATSDOMParser {
402
402
  }
403
403
  }
404
404
  return {
405
- id: element.getAttribute('id'),
406
- role: 'author',
405
+ id: element.getAttribute('id') || undefined,
406
+ role: (0, utils_1.getTrimmedTextContent)(element, 'role'),
407
407
  affiliations,
408
408
  corresp,
409
409
  footnote,
@@ -416,8 +416,10 @@ class JATSDOMParser {
416
416
  ObjectType: json_schema_1.ObjectTypes.BibliographicName,
417
417
  },
418
418
  ORCIDIdentifier: (0, utils_1.getTrimmedTextContent)(element, 'contrib-id[contrib-id-type="orcid"]'),
419
+ CRediTRoles: (0, utils_1.getCRediTRoleRole)(element),
419
420
  priority: this.parsePriority(element.getAttribute('priority')),
420
421
  email: (0, utils_1.getTrimmedTextContent)(element, 'email') || '',
422
+ prefix: (0, utils_1.getTrimmedTextContent)(element, 'prefix'),
421
423
  };
422
424
  },
423
425
  getContent: () => {
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ /*!
3
+ * © 2025 Atypon Systems LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.CRediTRoleUrls = void 0;
19
+ exports.CRediTRoleUrls = new Map([
20
+ [
21
+ "Conceptualization",
22
+ 'https://credit.niso.org/contributor-roles/conceptualization/',
23
+ ],
24
+ [
25
+ "Data curation",
26
+ 'https://credit.niso.org/contributor-roles/data-curation/',
27
+ ],
28
+ [
29
+ "Formal analysis",
30
+ 'https://credit.niso.org/contributor-roles/formal-analysis/',
31
+ ],
32
+ [
33
+ "Funding acquisition",
34
+ 'https://credit.niso.org/contributor-roles/funding-acquisition/',
35
+ ],
36
+ [
37
+ "Investigation",
38
+ 'https://credit.niso.org/contributor-roles/investigation/',
39
+ ],
40
+ [
41
+ "Methodology",
42
+ 'https://credit.niso.org/contributor-roles/methodology/',
43
+ ],
44
+ [
45
+ "ProjectAdministration",
46
+ 'https://credit.niso.org/contributor-roles/project-administration/',
47
+ ],
48
+ [
49
+ "Resources",
50
+ 'https://credit.niso.org/contributor-roles/resources/',
51
+ ],
52
+ [
53
+ "Software",
54
+ 'https://credit.niso.org/contributor-roles/software/',
55
+ ],
56
+ [
57
+ "Supervision",
58
+ 'https://credit.niso.org/contributor-roles/supervision/',
59
+ ],
60
+ [
61
+ "Validation",
62
+ 'https://credit.niso.org/contributor-roles/validation/',
63
+ ],
64
+ [
65
+ "Visualization",
66
+ 'https://credit.niso.org/contributor-roles/visualization/',
67
+ ],
68
+ [
69
+ "Writing \u2013 original draft",
70
+ 'https://credit.niso.org/contributor-roles/writing-original-draft/',
71
+ ],
72
+ [
73
+ "Writing \u2013 review & editing",
74
+ 'https://credit.niso.org/contributor-roles/writing-review-editing/',
75
+ ],
76
+ ]);
@@ -15,9 +15,10 @@
15
15
  * limitations under the License.
16
16
  */
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.dateToTimestamp = exports.getHTMLContent = exports.getTrimmedTextContent = exports.findParentNodeClosestToPos = exports.isInBibliographySection = exports.isInGraphicalAbstractSection = exports.findNodePositions = exports.iterateChildren = void 0;
18
+ exports.getCRediTRoleRole = exports.dateToTimestamp = exports.getHTMLContent = exports.getTrimmedTextContent = exports.findParentNodeClosestToPos = exports.isInBibliographySection = exports.isInGraphicalAbstractSection = exports.findNodePositions = exports.iterateChildren = void 0;
19
19
  const jats_parser_utils_1 = require("../jats/importer/jats-parser-utils");
20
20
  const schema_1 = require("../schema");
21
+ const credit_roles_1 = require("./credit-roles");
21
22
  function* iterateChildren(node, recurse = false) {
22
23
  for (let i = 0; i < node.childCount; i++) {
23
24
  const child = node.child(i);
@@ -102,3 +103,22 @@ const dateToTimestamp = (dateElement) => {
102
103
  return Date.UTC(values[0], values[1] - 1, values[2]) / 1000;
103
104
  };
104
105
  exports.dateToTimestamp = dateToTimestamp;
106
+ function getCRediTRoleRole(elem) {
107
+ const sources = elem.querySelectorAll('role[vocab="CRediT"][vocab-identifier="http://credit.niso.org/"][vocab-term][vocab-term-identifier]');
108
+ const results = [];
109
+ sources.forEach((source) => {
110
+ if (source &&
111
+ credit_roles_1.CRediTRoleUrls.has(source.getAttribute('vocab-term'))) {
112
+ const result = {
113
+ vocabTerm: source.getAttribute('vocab-term'),
114
+ };
115
+ if (source.getAttribute('degree-contribution')) {
116
+ result.degreeContribution =
117
+ source.getAttribute('degree-contribution') || undefined;
118
+ }
119
+ results.push(result);
120
+ }
121
+ });
122
+ return results;
123
+ }
124
+ exports.getCRediTRoleRole = getCRediTRoleRole;
@@ -17,8 +17,10 @@ exports.contributor = {
17
17
  isJointContributor: { default: undefined },
18
18
  ORCIDIdentifier: { default: undefined },
19
19
  priority: { default: undefined },
20
+ CRediTRoles: { default: [] },
20
21
  dataTracked: { default: null },
21
22
  contents: { default: '' },
23
+ prefix: { default: '' },
22
24
  },
23
25
  group: 'block',
24
26
  toDOM: (node) => {
@@ -1,4 +1,4 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VERSION = void 0;
4
- exports.VERSION = "3.0.61";
4
+ exports.VERSION = "3.0.63-LEAN-4531.0";
@@ -19,6 +19,7 @@ import debug from 'debug';
19
19
  import { DOMParser as ProsemirrorDOMParser, DOMSerializer, } from 'prosemirror-model';
20
20
  import { findChildrenByAttr, findChildrenByType } from 'prosemirror-utils';
21
21
  import serializeToXML from 'w3c-xmlserializer';
22
+ import { CRediTRoleUrls } from '../../lib/credit-roles';
22
23
  import { generateFootnoteLabels } from '../../lib/footnotes';
23
24
  import { nodeFromHTML, textFromHTML } from '../../lib/html';
24
25
  import { isCitationNode, isNodeOfType, schema, } from '../../schema';
@@ -1048,13 +1049,7 @@ export class JATSExporter {
1048
1049
  }
1049
1050
  };
1050
1051
  this.buildContributors = (articleMeta) => {
1051
- const contributorNodes = this.getChildrenOfType(schema.nodes.contributor);
1052
- const authorContributorNodes = contributorNodes
1053
- .filter((n) => n.attrs.role === 'author')
1054
- .sort(sortContributors);
1055
- const otherContributorsNodes = contributorNodes
1056
- .filter((n) => n.attrs.role !== 'author')
1057
- .sort(sortContributors);
1052
+ const contributorNodes = this.getChildrenOfType(schema.nodes.contributor).sort(sortContributors);
1058
1053
  const affiliationLabels = new Map();
1059
1054
  const creatAffiliationLabel = (rid) => {
1060
1055
  let label = affiliationLabels.get(rid);
@@ -1071,11 +1066,11 @@ export class JATSExporter {
1071
1066
  sup.textContent = String(content);
1072
1067
  return sup;
1073
1068
  };
1074
- if (authorContributorNodes.length) {
1069
+ if (contributorNodes.length) {
1075
1070
  const contribGroup = this.createElement('contrib-group');
1076
1071
  contribGroup.setAttribute('content-type', 'authors');
1077
1072
  articleMeta.appendChild(contribGroup);
1078
- authorContributorNodes.forEach((contributor) => {
1073
+ contributorNodes.forEach((contributor) => {
1079
1074
  try {
1080
1075
  this.validateContributor(contributor);
1081
1076
  }
@@ -1089,95 +1084,68 @@ export class JATSExporter {
1089
1084
  if (contributor.attrs.isCorresponding) {
1090
1085
  contrib.setAttribute('corresp', 'yes');
1091
1086
  }
1087
+ if (contributor.attrs.role) {
1088
+ this.appendElement(contrib, 'role', contributor.attrs.role);
1089
+ }
1092
1090
  if (contributor.attrs.ORCIDIdentifier) {
1093
- const identifier = this.createElement('contrib-id');
1094
- identifier.setAttribute('contrib-id-type', 'orcid');
1095
- identifier.textContent = contributor.attrs.ORCIDIdentifier;
1096
- contrib.appendChild(identifier);
1091
+ this.appendElement(contrib, 'contrib-id', contributor.attrs.ORCIDIdentifier, { 'contrib-id-type': 'orcid' });
1097
1092
  }
1098
1093
  const name = this.buildContributorName(contributor);
1099
1094
  contrib.appendChild(name);
1100
1095
  if (contributor.attrs.email) {
1101
- const email = this.createElement('email');
1102
- email.textContent = contributor.attrs.email;
1103
- contrib.appendChild(email);
1096
+ this.appendElement(contrib, 'email', contributor.attrs.email);
1104
1097
  }
1105
1098
  if (contributor.attrs.affiliations) {
1106
1099
  contributor.attrs.affiliations.forEach((rid) => {
1107
- const xref = this.createElement('xref');
1108
- xref.setAttribute('ref-type', 'aff');
1109
- xref.setAttribute('rid', normalizeID(rid));
1100
+ const xref = this.appendElement(contrib, 'xref', '', {
1101
+ 'ref-type': 'aff',
1102
+ rid: normalizeID(rid),
1103
+ });
1110
1104
  xref.appendChild(creatAffiliationLabel(rid));
1111
1105
  contrib.appendChild(xref);
1112
1106
  });
1113
1107
  }
1114
1108
  if (contributor.attrs.footnote) {
1115
1109
  contributor.attrs.footnote.map((note) => {
1116
- const xref = this.createElement('xref');
1117
- xref.setAttribute('ref-type', 'fn');
1118
- xref.setAttribute('rid', normalizeID(note.noteID));
1110
+ const xref = this.appendElement(contrib, 'xref', '', {
1111
+ 'ref-type': 'fn',
1112
+ rid: normalizeID(note.noteID),
1113
+ });
1119
1114
  xref.appendChild(createFootNotesLabels(note.noteLabel));
1120
1115
  contrib.appendChild(xref);
1121
1116
  });
1122
1117
  }
1123
1118
  if (contributor.attrs.corresp) {
1124
1119
  contributor.attrs.corresp.map((corresp) => {
1125
- const xref = this.createElement('xref');
1126
- xref.setAttribute('ref-type', 'corresp');
1127
- xref.setAttribute('rid', normalizeID(corresp.correspID));
1120
+ const xref = this.appendElement(contrib, 'xref', '', {
1121
+ 'ref-type': 'corresp',
1122
+ rid: normalizeID(corresp.correspID),
1123
+ });
1128
1124
  xref.appendChild(createFootNotesLabels(corresp.correspLabel));
1129
1125
  contrib.appendChild(xref);
1130
1126
  });
1131
1127
  }
1128
+ if (contributor.attrs.CRediTRoles) {
1129
+ contributor.attrs.CRediTRoles.forEach((cr) => {
1130
+ const role = this.createElement('role');
1131
+ const creditUrl = CRediTRoleUrls.get(cr.vocabTerm);
1132
+ if (creditUrl) {
1133
+ role.setAttribute('vocab-identifier', 'http://credit.niso.org/');
1134
+ role.setAttribute('vocab', 'CRediT');
1135
+ role.setAttribute('vocab-term', cr.vocabTerm);
1136
+ role.setAttribute('vocab-term-identifier', creditUrl);
1137
+ role.innerHTML = cr.vocabTerm;
1138
+ }
1139
+ if (cr.degreeContribution) {
1140
+ role.setAttribute('degree-contribution', cr.degreeContribution);
1141
+ }
1142
+ contrib.appendChild(role);
1143
+ });
1144
+ }
1132
1145
  contribGroup.appendChild(contrib);
1133
1146
  });
1134
- if (otherContributorsNodes.length) {
1135
- const contribGroup = this.createElement('contrib-group');
1136
- articleMeta.appendChild(contribGroup);
1137
- otherContributorsNodes.forEach((contributor) => {
1138
- try {
1139
- this.validateContributor(contributor);
1140
- }
1141
- catch (error) {
1142
- warn(error.message);
1143
- return;
1144
- }
1145
- const contrib = this.createElement('contrib');
1146
- contrib.setAttribute('id', normalizeID(contributor.attrs.id));
1147
- const name = this.buildContributorName(contributor);
1148
- contrib.appendChild(name);
1149
- if (contributor.attrs.email) {
1150
- const email = this.createElement('email');
1151
- email.textContent = contributor.attrs.email;
1152
- contrib.appendChild(email);
1153
- }
1154
- if (contributor.attrs.affiliations) {
1155
- contributor.attrs.affiliations.forEach((rid) => {
1156
- const xref = this.createElement('xref');
1157
- xref.setAttribute('ref-type', 'aff');
1158
- xref.setAttribute('rid', normalizeID(rid));
1159
- xref.appendChild(creatAffiliationLabel(rid));
1160
- contrib.appendChild(xref);
1161
- });
1162
- }
1163
- if (contributor.attrs.footnote) {
1164
- contributor.attrs.footnote.map((note) => {
1165
- const xref = this.createElement('xref');
1166
- xref.setAttribute('ref-type', 'fn');
1167
- xref.setAttribute('rid', normalizeID(note.noteID));
1168
- xref.appendChild(createFootNotesLabels(note.noteLabel));
1169
- contrib.appendChild(xref);
1170
- });
1171
- }
1172
- contribGroup.appendChild(contrib);
1173
- });
1174
- }
1175
1147
  const affiliationRIDs = [];
1176
- const sortedContributors = [
1177
- ...authorContributorNodes,
1178
- ...otherContributorsNodes,
1179
- ];
1180
- for (const contributor of sortedContributors) {
1148
+ for (const contributor of contributorNodes) {
1181
1149
  if (contributor.attrs.affiliations) {
1182
1150
  affiliationRIDs.push(...contributor.attrs.affiliations);
1183
1151
  }
@@ -1526,14 +1494,13 @@ export class JATSExporter {
1526
1494
  this.buildContributorName = (contributor) => {
1527
1495
  const name = this.createElement('name');
1528
1496
  if (contributor.attrs.bibliographicName.family) {
1529
- const surname = this.createElement('surname');
1530
- surname.textContent = contributor.attrs.bibliographicName.family;
1531
- name.appendChild(surname);
1497
+ this.appendElement(name, 'surname', contributor.attrs.bibliographicName.family);
1532
1498
  }
1533
1499
  if (contributor.attrs.bibliographicName.given) {
1534
- const givenNames = this.createElement('given-names');
1535
- givenNames.textContent = contributor.attrs.bibliographicName.given;
1536
- name.appendChild(givenNames);
1500
+ this.appendElement(name, 'given-names', contributor.attrs.bibliographicName.given);
1501
+ }
1502
+ if (contributor.attrs.prefix) {
1503
+ this.appendElement(name, 'prefix', contributor.attrs.prefix);
1537
1504
  }
1538
1505
  return name;
1539
1506
  };
@@ -15,7 +15,7 @@
15
15
  */
16
16
  import { buildBibliographicDate, buildBibliographicName, buildContribution, ObjectTypes, } from '@manuscripts/json-schema';
17
17
  import { DOMParser, Fragment } from 'prosemirror-model';
18
- import { dateToTimestamp, getHTMLContent, getTrimmedTextContent, } from '../../lib/utils';
18
+ import { dateToTimestamp, getCRediTRoleRole, getHTMLContent, getTrimmedTextContent, } from '../../lib/utils';
19
19
  import { publicationTypeToPM, } from '../../schema';
20
20
  import { DEFAULT_PROFILE_ID } from './jats-comments';
21
21
  export class JATSDOMParser {
@@ -399,8 +399,8 @@ export class JATSDOMParser {
399
399
  }
400
400
  }
401
401
  return {
402
- id: element.getAttribute('id'),
403
- role: 'author',
402
+ id: element.getAttribute('id') || undefined,
403
+ role: getTrimmedTextContent(element, 'role'),
404
404
  affiliations,
405
405
  corresp,
406
406
  footnote,
@@ -413,8 +413,10 @@ export class JATSDOMParser {
413
413
  ObjectType: ObjectTypes.BibliographicName,
414
414
  },
415
415
  ORCIDIdentifier: getTrimmedTextContent(element, 'contrib-id[contrib-id-type="orcid"]'),
416
+ CRediTRoles: getCRediTRoleRole(element),
416
417
  priority: this.parsePriority(element.getAttribute('priority')),
417
418
  email: getTrimmedTextContent(element, 'email') || '',
419
+ prefix: getTrimmedTextContent(element, 'prefix'),
418
420
  };
419
421
  },
420
422
  getContent: () => {
@@ -0,0 +1,73 @@
1
+ /*!
2
+ * © 2025 Atypon Systems LLC
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ export const CRediTRoleUrls = new Map([
17
+ [
18
+ "Conceptualization",
19
+ 'https://credit.niso.org/contributor-roles/conceptualization/',
20
+ ],
21
+ [
22
+ "Data curation",
23
+ 'https://credit.niso.org/contributor-roles/data-curation/',
24
+ ],
25
+ [
26
+ "Formal analysis",
27
+ 'https://credit.niso.org/contributor-roles/formal-analysis/',
28
+ ],
29
+ [
30
+ "Funding acquisition",
31
+ 'https://credit.niso.org/contributor-roles/funding-acquisition/',
32
+ ],
33
+ [
34
+ "Investigation",
35
+ 'https://credit.niso.org/contributor-roles/investigation/',
36
+ ],
37
+ [
38
+ "Methodology",
39
+ 'https://credit.niso.org/contributor-roles/methodology/',
40
+ ],
41
+ [
42
+ "ProjectAdministration",
43
+ 'https://credit.niso.org/contributor-roles/project-administration/',
44
+ ],
45
+ [
46
+ "Resources",
47
+ 'https://credit.niso.org/contributor-roles/resources/',
48
+ ],
49
+ [
50
+ "Software",
51
+ 'https://credit.niso.org/contributor-roles/software/',
52
+ ],
53
+ [
54
+ "Supervision",
55
+ 'https://credit.niso.org/contributor-roles/supervision/',
56
+ ],
57
+ [
58
+ "Validation",
59
+ 'https://credit.niso.org/contributor-roles/validation/',
60
+ ],
61
+ [
62
+ "Visualization",
63
+ 'https://credit.niso.org/contributor-roles/visualization/',
64
+ ],
65
+ [
66
+ "Writing \u2013 original draft",
67
+ 'https://credit.niso.org/contributor-roles/writing-original-draft/',
68
+ ],
69
+ [
70
+ "Writing \u2013 review & editing",
71
+ 'https://credit.niso.org/contributor-roles/writing-review-editing/',
72
+ ],
73
+ ]);
@@ -15,6 +15,7 @@
15
15
  */
16
16
  import { htmlFromJatsNode } from '../jats/importer/jats-parser-utils';
17
17
  import { isBibliographySectionNode, isGraphicalAbstractSectionNode, } from '../schema';
18
+ import { CRediTRoleUrls } from './credit-roles';
18
19
  export function* iterateChildren(node, recurse = false) {
19
20
  for (let i = 0; i < node.childCount; i++) {
20
21
  const child = node.child(i);
@@ -91,3 +92,21 @@ export const dateToTimestamp = (dateElement) => {
91
92
  }
92
93
  return Date.UTC(values[0], values[1] - 1, values[2]) / 1000;
93
94
  };
95
+ export function getCRediTRoleRole(elem) {
96
+ const sources = elem.querySelectorAll('role[vocab="CRediT"][vocab-identifier="http://credit.niso.org/"][vocab-term][vocab-term-identifier]');
97
+ const results = [];
98
+ sources.forEach((source) => {
99
+ if (source &&
100
+ CRediTRoleUrls.has(source.getAttribute('vocab-term'))) {
101
+ const result = {
102
+ vocabTerm: source.getAttribute('vocab-term'),
103
+ };
104
+ if (source.getAttribute('degree-contribution')) {
105
+ result.degreeContribution =
106
+ source.getAttribute('degree-contribution') || undefined;
107
+ }
108
+ results.push(result);
109
+ }
110
+ });
111
+ return results;
112
+ }
@@ -14,8 +14,10 @@ export const contributor = {
14
14
  isJointContributor: { default: undefined },
15
15
  ORCIDIdentifier: { default: undefined },
16
16
  priority: { default: undefined },
17
+ CRediTRoles: { default: [] },
17
18
  dataTracked: { default: null },
18
19
  contents: { default: '' },
20
+ prefix: { default: '' },
19
21
  },
20
22
  group: 'block',
21
23
  toDOM: (node) => {
@@ -1 +1 @@
1
- export const VERSION = "3.0.61";
1
+ export const VERSION = "3.0.63-LEAN-4531.0";
@@ -0,0 +1,32 @@
1
+ /*!
2
+ * © 2025 Atypon Systems LLC
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ export declare const enum CreditVocabTerm {
17
+ Conceptualization = "Conceptualization",
18
+ DataCuration = "Data curation",
19
+ FormalAnalysis = "Formal analysis",
20
+ FundingAcquisition = "Funding acquisition",
21
+ Investigation = "Investigation",
22
+ Methodology = "Methodology",
23
+ ProjectAdministration = "ProjectAdministration",
24
+ Resources = "Resources",
25
+ Software = "Software",
26
+ Supervision = "Supervision",
27
+ Validation = "Validation",
28
+ Visualization = "Visualization",
29
+ WritingOriginalDraft = "Writing \u2013 original draft",
30
+ WritingReviewEditing = "Writing \u2013 review & editing"
31
+ }
32
+ export declare const CRediTRoleUrls: Map<CreditVocabTerm, string>;
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
  import { Node as ProsemirrorNode, ResolvedPos } from 'prosemirror-model';
17
- import { ManuscriptEditorState, ManuscriptNode } from '../schema';
17
+ import { CRediTRole, ManuscriptEditorState, ManuscriptNode } from '../schema';
18
18
  export declare function iterateChildren(node: ManuscriptNode, recurse?: boolean): Iterable<ManuscriptNode>;
19
19
  export declare const findNodePositions: (state: ManuscriptEditorState, predicate: (node: ManuscriptNode) => boolean) => number[];
20
20
  export declare const isInGraphicalAbstractSection: ($pos: ResolvedPos) => boolean;
@@ -28,3 +28,4 @@ export declare const findParentNodeClosestToPos: ($pos: ResolvedPos, predicate:
28
28
  export declare const getTrimmedTextContent: (node: Element | Document | null, selector?: string) => string | undefined;
29
29
  export declare const getHTMLContent: (node: Element, querySelector: string) => string | undefined;
30
30
  export declare const dateToTimestamp: (dateElement: Element) => number | undefined;
31
+ export declare function getCRediTRoleRole(elem: Element): CRediTRole[];
@@ -1,5 +1,6 @@
1
1
  import { BibliographicName } from '@manuscripts/json-schema';
2
2
  import { NodeSpec } from 'prosemirror-model';
3
+ import { CreditVocabTerm } from '../../lib/credit-roles';
3
4
  import { ManuscriptNode } from '../types';
4
5
  export type ContributorCorresp = {
5
6
  correspID: string;
@@ -9,12 +10,16 @@ export type ContributorFootnote = {
9
10
  noteID: string;
10
11
  noteLabel: string;
11
12
  };
13
+ export type CRediTRole = {
14
+ vocabTerm: CreditVocabTerm;
15
+ degreeContribution?: string;
16
+ };
12
17
  interface Attrs {
13
18
  id: string;
14
19
  role: string;
15
20
  corresp: ContributorCorresp[];
16
21
  affiliations: string[];
17
- bibliographicName: BibliographicName;
22
+ bibliographicName: Omit<BibliographicName, '_id'>;
18
23
  userID: string;
19
24
  email: string;
20
25
  invitationID: string;
@@ -23,6 +28,8 @@ interface Attrs {
23
28
  priority: number;
24
29
  isJointContributor: boolean;
25
30
  footnote: ContributorFootnote[];
31
+ prefix: string;
32
+ CRediTRoles?: CRediTRole[];
26
33
  }
27
34
  export interface ContributorNode extends ManuscriptNode {
28
35
  attrs: Attrs;
@@ -1 +1 @@
1
- export declare const VERSION = "3.0.61";
1
+ export declare const VERSION = "3.0.63-LEAN-4531.0";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@manuscripts/transform",
3
3
  "description": "ProseMirror transformer for Manuscripts applications",
4
- "version": "3.0.61",
4
+ "version": "3.0.63-LEAN-4531.0",
5
5
  "repository": "github:Atypon-OpenSource/manuscripts-transform",
6
6
  "license": "Apache-2.0",
7
7
  "main": "dist/cjs",