@manuscripts/transform 4.5.2 → 4.5.3

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 (60) hide show
  1. package/dist/cjs/jats/__tests__/data/section-categories.js +5 -5
  2. package/dist/cjs/jats/__tests__/jats-importer.test.js +19 -5
  3. package/dist/cjs/jats/exporter/jats-exporter.js +725 -910
  4. package/dist/cjs/jats/exporter/jats-versions.js +9 -9
  5. package/dist/cjs/jats/importer/jats-dom-parser.js +25 -24
  6. package/dist/cjs/jats/importer/jats-transformations.js +14 -30
  7. package/dist/cjs/lib/section-categories.js +31 -1
  8. package/dist/cjs/schema/index.js +3 -0
  9. package/dist/cjs/schema/migration/migration-scripts/4.5.3.js +37 -0
  10. package/dist/cjs/schema/migration/migration-scripts/index.js +2 -0
  11. package/dist/cjs/schema/nodes/abstract.js +51 -0
  12. package/dist/cjs/schema/nodes/abstracts.js +1 -1
  13. package/dist/cjs/transformer/node-names.js +1 -0
  14. package/dist/cjs/transformer/node-title.js +2 -0
  15. package/dist/cjs/version.js +1 -1
  16. package/dist/es/jats/__tests__/data/section-categories.js +5 -5
  17. package/dist/es/jats/__tests__/jats-importer.test.js +19 -5
  18. package/dist/es/jats/exporter/jats-exporter.js +728 -913
  19. package/dist/es/jats/exporter/jats-versions.js +7 -7
  20. package/dist/es/jats/importer/jats-dom-parser.js +25 -24
  21. package/dist/es/jats/importer/jats-transformations.js +14 -30
  22. package/dist/es/lib/section-categories.js +28 -0
  23. package/dist/es/schema/index.js +3 -0
  24. package/dist/es/schema/migration/migration-scripts/4.5.3.js +35 -0
  25. package/dist/es/schema/migration/migration-scripts/index.js +2 -0
  26. package/dist/es/schema/nodes/abstract.js +47 -0
  27. package/dist/es/schema/nodes/abstracts.js +1 -1
  28. package/dist/es/transformer/node-names.js +1 -0
  29. package/dist/es/transformer/node-title.js +2 -0
  30. package/dist/es/version.js +1 -1
  31. package/dist/types/jats/exporter/jats-exporter.d.ts +31 -27
  32. package/dist/types/jats/exporter/jats-versions.d.ts +4 -4
  33. package/dist/types/jats/importer/jats-dom-parser.d.ts +0 -1
  34. package/dist/types/lib/section-categories.d.ts +3 -0
  35. package/dist/types/schema/index.d.ts +1 -0
  36. package/dist/types/schema/migration/migration-scripts/4.5.3.d.ts +8 -0
  37. package/dist/types/schema/migration/migration-scripts/index.d.ts +2 -1
  38. package/dist/types/schema/nodes/abstract.d.ts +26 -0
  39. package/dist/types/schema/types.d.ts +1 -1
  40. package/dist/types/version.d.ts +1 -1
  41. package/package.json +1 -1
  42. package/src/jats/__tests__/__snapshots__/jats-exporter.test.ts.snap +3 -3
  43. package/src/jats/__tests__/__snapshots__/jats-importer.test.ts.snap +86 -132
  44. package/src/jats/__tests__/__snapshots__/jats-roundtrip.test.ts.snap +3 -3
  45. package/src/jats/__tests__/data/section-categories.ts +5 -5
  46. package/src/jats/__tests__/jats-importer.test.ts +22 -6
  47. package/src/jats/exporter/jats-exporter.ts +855 -1126
  48. package/src/jats/exporter/jats-versions.ts +11 -11
  49. package/src/jats/importer/jats-dom-parser.ts +34 -34
  50. package/src/jats/importer/jats-transformations.ts +21 -37
  51. package/src/lib/section-categories.ts +36 -0
  52. package/src/schema/index.ts +3 -0
  53. package/src/schema/migration/migration-scripts/4.5.3.ts +57 -0
  54. package/src/schema/migration/migration-scripts/index.ts +2 -0
  55. package/src/schema/nodes/abstract.ts +66 -0
  56. package/src/schema/nodes/abstracts.ts +2 -1
  57. package/src/schema/types.ts +1 -0
  58. package/src/transformer/node-names.ts +1 -0
  59. package/src/transformer/node-title.ts +2 -0
  60. package/src/version.ts +1 -1
@@ -15,19 +15,19 @@
15
15
  */
16
16
  const versions = {
17
17
  '1.1': {
18
- publicId: '-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD with OASIS Tables with MathML3 v1.1 20151215//EN',
19
- systemId: 'http://jats.nlm.nih.gov/archiving/1.1/JATS-archive-oasis-article1-mathml3.dtd',
18
+ publicID: '-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD with OASIS Tables with MathML3 v1.1 20151215//EN',
19
+ systemID: 'http://jats.nlm.nih.gov/archiving/1.1/JATS-archive-oasis-article1-mathml3.dtd',
20
20
  },
21
21
  '1.2d1': {
22
- publicId: '-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD with OASIS Tables with MathML3 v1.2d1 20170631//EN',
23
- systemId: 'http://jats.nlm.nih.gov/archiving/1.2d1/JATS-archive-oasis-article1-mathml3.dtd',
22
+ publicID: '-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD with OASIS Tables with MathML3 v1.2d1 20170631//EN',
23
+ systemID: 'http://jats.nlm.nih.gov/archiving/1.2d1/JATS-archive-oasis-article1-mathml3.dtd',
24
24
  },
25
25
  '1.2': {
26
- publicId: '-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD with OASIS Tables with MathML3 v1.2 20190208//EN',
27
- systemId: 'http://jats.nlm.nih.gov/archiving/1.2/JATS-archive-oasis-article1-mathml3.dtd',
26
+ publicID: '-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD with OASIS Tables with MathML3 v1.2 20190208//EN',
27
+ systemID: 'http://jats.nlm.nih.gov/archiving/1.2/JATS-archive-oasis-article1-mathml3.dtd',
28
28
  },
29
29
  };
30
- export const selectVersionIds = (version) => {
30
+ export const selectVersionIDs = (version) => {
31
31
  if (!(version in versions)) {
32
32
  throw new Error(`Unknown version ${version}`);
33
33
  }
@@ -1,4 +1,5 @@
1
1
  import { DOMParser, Fragment } from 'prosemirror-model';
2
+ import { abstractTypeToCategory, findMatchingCategory, } from '../../lib/section-categories';
2
3
  import { dateToTimestamp, getCreditRole, getHTMLContent, getTrimmedTextContent, } from '../../lib/utils';
3
4
  import { XLINK_NAMESPACE, XML_NAMESPACE } from '../../lib/xml';
4
5
  import { DEFAULT_PROFILE_ID } from './jats-comments';
@@ -458,6 +459,10 @@ export class JATSDOMParser {
458
459
  tag: 'history',
459
460
  ignore: true,
460
461
  },
462
+ {
463
+ tag: 'statement',
464
+ ignore: true,
465
+ },
461
466
  {
462
467
  tag: 'break',
463
468
  node: 'hard_break',
@@ -819,7 +824,7 @@ export class JATSDOMParser {
819
824
  },
820
825
  },
821
826
  {
822
- tag: 'trans-abstract[sec-type="abstract-graphical"]',
827
+ tag: 'trans-abstract[abstract-type="graphical"]',
823
828
  node: 'trans_graphical_abstract',
824
829
  getAttrs: (node) => {
825
830
  const element = node;
@@ -830,7 +835,7 @@ export class JATSDOMParser {
830
835
  },
831
836
  },
832
837
  {
833
- tag: 'trans-abstract[sec-type="abstract-key-image"]',
838
+ tag: 'trans-abstract[abstract-type="key-image"]',
834
839
  node: 'trans_graphical_abstract',
835
840
  getAttrs: (node) => {
836
841
  const element = node;
@@ -890,7 +895,7 @@ export class JATSDOMParser {
890
895
  getAttrs: (node) => this.parseRef(node),
891
896
  },
892
897
  {
893
- tag: 'sec[sec-type="abstract-graphical"]',
898
+ tag: 'abstract[abstract-type="graphical"]',
894
899
  node: 'graphical_abstract_section',
895
900
  getAttrs: (node) => {
896
901
  const element = node;
@@ -900,7 +905,7 @@ export class JATSDOMParser {
900
905
  },
901
906
  },
902
907
  {
903
- tag: 'sec[sec-type="abstract-key-image"]',
908
+ tag: 'abstract[abstract-type="key-image"]',
904
909
  node: 'graphical_abstract_section',
905
910
  getAttrs: (node) => {
906
911
  const element = node;
@@ -909,6 +914,18 @@ export class JATSDOMParser {
909
914
  };
910
915
  },
911
916
  },
917
+ {
918
+ tag: 'abstract',
919
+ node: 'abstract',
920
+ getAttrs: (node) => {
921
+ const element = node;
922
+ return {
923
+ id: element.getAttribute('id'),
924
+ category: this.chooseSectionCategory(element) ||
925
+ abstractTypeToCategory(element.getAttribute('abstract-type')),
926
+ };
927
+ },
928
+ },
912
929
  {
913
930
  tag: 'sec',
914
931
  node: 'section',
@@ -971,7 +988,7 @@ export class JATSDOMParser {
971
988
  {
972
989
  tag: 'title',
973
990
  node: 'section_title',
974
- context: 'section/|footnotes_section/|bibliography_section/|keywords/|supplements/|author_notes/|graphical_abstract_section/|trans_abstract/|trans_graphical_abstract/',
991
+ context: 'section/|footnotes_section/|bibliography_section/|keywords/|supplements/|author_notes/|abstract/|graphical_abstract_section/|trans_abstract/|trans_graphical_abstract/',
975
992
  },
976
993
  {
977
994
  tag: 'tr',
@@ -1107,29 +1124,13 @@ export class JATSDOMParser {
1107
1124
  parse(doc, options) {
1108
1125
  return this.parser.parse(doc, options);
1109
1126
  }
1110
- isMatchingCategory(secType, titleNode, category) {
1111
- if ((secType && category.synonyms.includes(secType)) ||
1112
- category.id === secType) {
1113
- return true;
1114
- }
1115
- if (titleNode && titleNode.nodeName === 'title' && titleNode.textContent) {
1116
- const textContent = titleNode.textContent.trim().toLowerCase();
1117
- if (category.synonyms.includes(textContent)) {
1118
- return true;
1119
- }
1120
- }
1121
- return false;
1122
- }
1123
1127
  chooseSectionCategory(section) {
1124
1128
  const secType = section.getAttribute('sec-type');
1125
1129
  const abstractType = section.getAttribute('abstract-type');
1126
- const effectiveSecType = secType || (abstractType ? `abstract-${abstractType}` : null);
1130
+ const effectiveSecType = secType ?? abstractType;
1127
1131
  const titleNode = section.firstElementChild;
1128
- for (const category of this.sectionCategories) {
1129
- if (this.isMatchingCategory(effectiveSecType, titleNode, category)) {
1130
- return category.id;
1131
- }
1132
- }
1132
+ const titleText = titleNode?.nodeName === 'title' ? titleNode.textContent : null;
1133
+ return findMatchingCategory(this.sectionCategories, effectiveSecType, titleText)?.id;
1133
1134
  }
1134
1135
  getNameContent(element, type) {
1135
1136
  const query = `person-group[person-group-type="${type}"] > *`;
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
  import { defaultTitle } from '../../lib/deafults';
17
- import { XML_NAMESPACE } from '../../lib/xml';
17
+ import { abstractTypeToCategory, findMatchingCategory, } from '../../lib/section-categories';
18
18
  import { htmlFromJatsNode } from './jats-parser-utils';
19
19
  const removeNodeFromParent = (node) => node.parentNode && node.parentNode.removeChild(node);
20
20
  const capitalizeFirstLetter = (str) => str.charAt(0).toUpperCase() + str.slice(1);
@@ -108,8 +108,7 @@ export const moveAffiliations = (front, createElement) => {
108
108
  export const moveAbstracts = (front, group, createElement, sectionCategories) => {
109
109
  const abstracts = front.querySelectorAll('article-meta > abstract, article-meta > trans-abstract');
110
110
  abstracts.forEach((abstract) => {
111
- const sec = createAbstractSection(abstract, createElement, sectionCategories);
112
- removeNodeFromParent(abstract);
111
+ const sec = prepareAbstract(abstract, createElement, sectionCategories);
113
112
  group.appendChild(sec);
114
113
  });
115
114
  };
@@ -171,7 +170,7 @@ const moveSpecialFootnotes = (doc, group, sectionCategories, createElement) => {
171
170
  const fns = [...doc.querySelectorAll('fn[fn-type]')];
172
171
  for (const fn of fns) {
173
172
  const type = fn.getAttribute('fn-type') || '';
174
- const category = sectionCategories.find((category) => category.synonyms.includes(type));
173
+ const category = findMatchingCategory(sectionCategories, type);
175
174
  if (category) {
176
175
  const section = createElement('sec');
177
176
  const fnTitle = fn.querySelector('label') ||
@@ -205,35 +204,20 @@ export const moveCaptionsToEnd = (body) => {
205
204
  }
206
205
  }
207
206
  };
208
- const createAbstractSection = (abstract, createElement, sectionCategories) => {
209
- const abstractType = abstract.getAttribute('abstract-type');
210
- const sectionType = abstractType ? `abstract-${abstractType}` : 'abstract';
211
- let section = createElement('sec');
212
- if (abstract.nodeName === 'trans-abstract') {
213
- section = createElement('trans-abstract');
214
- const lang = abstract.getAttributeNS(XML_NAMESPACE, 'lang');
215
- if (lang) {
216
- section.setAttributeNS(XML_NAMESPACE, 'lang', lang);
217
- }
218
- }
219
- section.setAttribute('sec-type', sectionType);
207
+ const prepareAbstract = (abstract, createElement, sectionCategories) => {
208
+ const rawType = abstract.getAttribute('abstract-type');
209
+ const category = abstractTypeToCategory(rawType);
220
210
  if (!abstract.querySelector(':scope > title')) {
211
+ const matched = sectionCategories && findMatchingCategory(sectionCategories, category);
221
212
  const title = createElement('title');
222
- const category = sectionCategories?.find((c) => c.id === sectionType || c.synonyms.includes(sectionType));
223
- if (category?.titles[0]) {
224
- title.textContent = category.titles[0];
225
- }
226
- else {
227
- title.textContent = abstractType
228
- ? `${capitalizeFirstLetter(abstractType.split('-').join(' '))} Abstract`
229
- : 'Abstract';
230
- }
231
- section.appendChild(title);
232
- }
233
- while (abstract.firstChild) {
234
- section.appendChild(abstract.firstChild);
213
+ title.textContent =
214
+ matched?.titles[0] ??
215
+ (rawType
216
+ ? `${capitalizeFirstLetter(rawType.split('-').join(' '))} Abstract`
217
+ : 'Abstract');
218
+ abstract.insertBefore(title, abstract.firstChild);
235
219
  }
236
- return section;
220
+ return abstract;
237
221
  };
238
222
  const createAcknowledgmentsSection = (ack, createElement) => {
239
223
  const section = createElement('sec');
@@ -19,3 +19,31 @@ export const getGroupCategories = (sections, group) => {
19
19
  : Array.from(sections.values());
20
20
  return sectionsArray.filter((section) => section.group === group);
21
21
  };
22
+ export const findMatchingCategory = (categories, type, titleText) => {
23
+ return categories.find((category) => {
24
+ if (type && (category.id === type || category.synonyms.includes(type))) {
25
+ return true;
26
+ }
27
+ if (titleText) {
28
+ const normalizedTitle = titleText.trim().toLowerCase();
29
+ if (category.synonyms.includes(normalizedTitle)) {
30
+ return true;
31
+ }
32
+ }
33
+ return false;
34
+ });
35
+ };
36
+ export const abstractTypeToCategory = (abstractType) => abstractType || 'abstract';
37
+ export const FOOTNOTE_SECTION_CATEGORY_IDS = [
38
+ 'con',
39
+ 'conflict',
40
+ 'deceased',
41
+ 'equal',
42
+ 'present-address',
43
+ 'presented-at',
44
+ 'previously-at',
45
+ 'supplementary-material',
46
+ 'supported-by',
47
+ 'financial-disclosure',
48
+ 'coi-statement',
49
+ ];
@@ -16,6 +16,7 @@
16
16
  */
17
17
  import { Schema } from 'prosemirror-model';
18
18
  import { bold, code, italic, smallcaps, strikethrough, styled, subscript, superscript, tracked_delete, tracked_insert, underline, } from './marks';
19
+ import { abstract } from './nodes/abstract';
19
20
  import { abstracts } from './nodes/abstracts';
20
21
  import { affiliation } from './nodes/affiliation';
21
22
  import { affiliations } from './nodes/affiliations';
@@ -96,6 +97,7 @@ import { title } from './nodes/title';
96
97
  import { transAbstract } from './nodes/trans_abstract';
97
98
  import { transGraphicalAbstract } from './nodes/trans_graphical_abstract';
98
99
  export * from './groups';
100
+ export * from './nodes/abstract';
99
101
  export * from './nodes/affiliation';
100
102
  export * from './nodes/affiliations';
101
103
  export * from './nodes/alt_text';
@@ -199,6 +201,7 @@ export const schema = new Schema({
199
201
  caption,
200
202
  caption_title: captionTitle,
201
203
  citation,
204
+ abstract,
202
205
  abstracts,
203
206
  body,
204
207
  backmatter,
@@ -0,0 +1,35 @@
1
+ const TRANS_ABSTRACT_TYPES = ['trans_abstract', 'trans_graphical_abstract'];
2
+ class Migration453 {
3
+ constructor() {
4
+ this.fromVersion = '4.5.2';
5
+ this.toVersion = '4.5.3';
6
+ }
7
+ migrateNode(node) {
8
+ if (node.type !== 'abstracts' || !node.content) {
9
+ return node;
10
+ }
11
+ const children = node.content.map((child) => {
12
+ const type = child.type === 'section' ? 'abstract' : child.type;
13
+ const category = child.attrs?.category;
14
+ const attrs = category && category.startsWith('abstract-')
15
+ ? { ...child.attrs, category: category.slice('abstract-'.length) }
16
+ : child.attrs;
17
+ return { ...child, type, attrs };
18
+ });
19
+ const regular = [];
20
+ const translated = [];
21
+ for (const child of children) {
22
+ if (TRANS_ABSTRACT_TYPES.includes(child.type)) {
23
+ translated.push(child);
24
+ }
25
+ else {
26
+ regular.push(child);
27
+ }
28
+ }
29
+ return {
30
+ ...node,
31
+ content: [...regular, ...translated],
32
+ };
33
+ }
34
+ }
35
+ export default Migration453;
@@ -29,6 +29,7 @@ import Migration4334 from './4.3.34';
29
29
  import Migration4335 from './4.3.35';
30
30
  import Migration442 from './4.4.2';
31
31
  import Migration447 from './4.4.7';
32
+ import Migration453 from './4.5.3';
32
33
  const migrations = [
33
34
  new Migration125(),
34
35
  new Migration2322(),
@@ -46,5 +47,6 @@ const migrations = [
46
47
  new Migration4335(),
47
48
  new Migration442(),
48
49
  new Migration447(),
50
+ new Migration453(),
49
51
  ];
50
52
  export default migrations;
@@ -0,0 +1,47 @@
1
+ /*!
2
+ * © 2026 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 abstract = {
17
+ content: 'section_label? section_title (paragraph | element)* sections*',
18
+ attrs: {
19
+ id: { default: '' },
20
+ category: { default: '' },
21
+ dataTracked: { default: null },
22
+ },
23
+ group: 'block sections',
24
+ selectable: false,
25
+ parseDOM: [
26
+ {
27
+ tag: 'section.abstract',
28
+ getAttrs: (dom) => {
29
+ const element = dom;
30
+ return {
31
+ id: element.getAttribute('id') || '',
32
+ category: element.getAttribute('data-category') || '',
33
+ };
34
+ },
35
+ },
36
+ ],
37
+ toDOM: (node) => {
38
+ const abstractNode = node;
39
+ const { id, category } = abstractNode.attrs;
40
+ const attrs = { id, class: 'abstract' };
41
+ if (category) {
42
+ attrs['data-category'] = category;
43
+ }
44
+ return ['section', attrs, 0];
45
+ },
46
+ };
47
+ export const isAbstractNode = (node) => node.type === node.type.schema.nodes.abstract;
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
  export const abstracts = {
17
- content: 'sections* (trans_abstract | trans_graphical_abstract)*',
17
+ content: '(abstract | graphical_abstract_section)* (trans_abstract | trans_graphical_abstract)*',
18
18
  attrs: {
19
19
  id: { default: '' },
20
20
  },
@@ -51,6 +51,7 @@ export const nodeNames = new Map([
51
51
  [schema.nodes.paragraph, 'Paragraph'],
52
52
  [schema.nodes.text_block, 'Paragraph'],
53
53
  [schema.nodes.section, 'Section'],
54
+ [schema.nodes.abstract, 'Abstract'],
54
55
  [schema.nodes.graphical_abstract_section, 'Graphical Abstract'],
55
56
  [schema.nodes.trans_abstract, 'Trans Abstract'],
56
57
  [schema.nodes.trans_graphical_abstract, 'Trans Graphical Abstract'],
@@ -50,6 +50,7 @@ export const nodeTitle = (node) => {
50
50
  case nodes.manuscript:
51
51
  return snippetOfNodeType(node, nodes.title);
52
52
  case nodes.section:
53
+ case nodes.abstract:
53
54
  case nodes.bibliography_section:
54
55
  case nodes.footnotes_section:
55
56
  case nodes.keywords:
@@ -86,6 +87,7 @@ export const nodeTitlePlaceholder = (nodeType) => {
86
87
  case nodes.manuscript:
87
88
  return 'Untitled Manuscript';
88
89
  case nodes.section:
90
+ case nodes.abstract:
89
91
  return 'Untitled Section';
90
92
  case nodes.bibliography_section:
91
93
  return 'Bibliography';
@@ -1 +1 @@
1
- export const VERSION = "4.5.2";
1
+ export const VERSION = "4.5.3";
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
  import { DOMSerializer, type NodeType } from 'prosemirror-model';
17
- import { ManuscriptNode } from '../../schema';
17
+ import { ActualManuscriptNode, ManuscriptNode } from '../../schema';
18
18
  import { IDGenerator } from '../types';
19
19
  import { Version } from './jats-versions';
20
20
  import { Target } from './labels';
@@ -34,56 +34,60 @@ export declare class JATSExporter {
34
34
  protected serializer: DOMSerializer;
35
35
  protected labelTargets: Map<string, Target>;
36
36
  protected footnoteLabels: Map<string, string>;
37
- protected manuscriptNode: ManuscriptNode;
37
+ protected manuscriptNode: ActualManuscriptNode;
38
38
  private engine;
39
39
  private renderedCitations;
40
40
  private nodesMap;
41
+ private contributorLabels;
41
42
  private populateNodesMap;
42
43
  protected getFirstChildOfType<T extends ManuscriptNode>(type: NodeType, node?: ManuscriptNode): T | undefined;
43
44
  protected getChildrenOfType<T extends ManuscriptNode>(type: NodeType, node?: ManuscriptNode): T[];
44
- serializeToJATS: (manuscriptNode: ManuscriptNode, options: ExportOptions) => Promise<string>;
45
+ serializeToJATS: (manuscriptNode: ActualManuscriptNode, options: ExportOptions) => Promise<string>;
45
46
  private appendChildNodeOfType;
46
47
  private appendChildrenNodeOfType;
47
- protected appendCaption: (element: HTMLElement, node: ManuscriptNode) => void;
48
+ protected appendCaption: ($element: Element, node: ManuscriptNode) => void;
48
49
  private initCiteprocEngine;
49
50
  private nodeFromJATS;
50
51
  protected rewriteIDs: (generator?: IDGenerator) => Promise<void>;
51
- protected setTitleContent: (element: HTMLElement, title: string) => void;
52
- protected buildFront: () => HTMLElement;
52
+ protected buildFront: ($coiStatement?: Element) => HTMLElement;
53
+ private appendChildren;
54
+ private buildArticleID;
55
+ private buildTitleGroup;
56
+ private buildSupplements;
57
+ private buildHistory;
58
+ private buildCounts;
59
+ private buildAwards;
60
+ private buildSelfUris;
53
61
  protected buildDateElement: (timestamp: number, type: string) => HTMLElement;
54
- protected buildCountingElement: (tagName: string, count: number | undefined) => HTMLElement | undefined;
55
62
  protected buildBody: () => HTMLElement;
56
- protected buildBack: (body: HTMLElement) => HTMLElement;
63
+ protected buildBack: () => HTMLElement;
64
+ private findSection;
65
+ private findSections;
66
+ private routeBackmatterSections;
67
+ private extractCoiStatement;
68
+ private buildRefList;
57
69
  private createElement;
58
70
  private appendElement;
59
71
  protected createSerializer: () => void;
60
72
  private createEquation;
61
73
  protected serializeNode: (node: ManuscriptNode) => Node;
62
- private buildContributors;
74
+ private buildContributorGroup;
75
+ private buildAuthorNotes;
76
+ private computeContributorLabels;
77
+ private createLabelSup;
78
+ private buildContributorElement;
79
+ private buildAffiliationElement;
63
80
  private buildContributorName;
64
- private createAuthorNotesElement;
65
81
  private writeCorresp;
66
82
  private writeParagraph;
67
83
  private writeFootnote;
84
+ private appendAuthorNotes;
68
85
  private buildKeywords;
69
- private fixBody;
70
86
  private changeTag;
71
- private fixTable;
72
- private unwrapBody;
73
- private removeBackContainer;
74
- private moveAwards;
75
- private moveAbstracts;
76
- private getAbstractCategories;
77
- private getAbstractSections;
78
- private isAbstractSection;
79
- private createTransAbstractNode;
80
- private createAbstractNode;
81
- private setAbstractType;
82
- private moveSectionsToBack;
83
- sectionToFootnote: (section: Element, fnType: string) => HTMLElement;
84
- private moveFloatsGroup;
85
- private moveCoiStatementToAuthorNotes;
86
- private updateFootnoteTypes;
87
+ private normalizeTable;
88
+ private buildAbstracts;
89
+ sectionToFootnote: ($section: Element, fnType: string) => HTMLElement;
90
+ private buildFloatsGroup;
87
91
  private fillEmptyElements;
88
92
  private addParagraphsToSections;
89
93
  private fillEmptyFootnotes;
@@ -13,10 +13,10 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
- interface VersionIds {
17
- publicId: string;
18
- systemId: string;
16
+ interface VersionIDs {
17
+ publicID: string;
18
+ systemID: string;
19
19
  }
20
20
  export type Version = '1.1' | '1.2d1' | '1.2';
21
- export declare const selectVersionIds: (version: Version) => VersionIds;
21
+ export declare const selectVersionIDs: (version: Version) => VersionIDs;
22
22
  export {};
@@ -6,7 +6,6 @@ export declare class JATSDOMParser {
6
6
  private parser;
7
7
  constructor(sectionCategories: SectionCategory[], schema: Schema);
8
8
  parse(doc: Node, options?: ParseOptions): import("prosemirror-model").Node;
9
- private isMatchingCategory;
10
9
  private chooseSectionCategory;
11
10
  private parsePriority;
12
11
  private getEquationContent;
@@ -15,3 +15,6 @@
15
15
  */
16
16
  import { SectionCategory, SectionGroup } from '../schema';
17
17
  export declare const getGroupCategories: (sections: Map<string, SectionCategory> | SectionCategory[], group: SectionGroup) => SectionCategory[];
18
+ export declare const findMatchingCategory: (categories: SectionCategory[], type?: string | null, titleText?: string | null) => SectionCategory | undefined;
19
+ export declare const abstractTypeToCategory: (abstractType: string | null) => string;
20
+ export declare const FOOTNOTE_SECTION_CATEGORY_IDS: string[];
@@ -17,6 +17,7 @@
17
17
  import { Schema } from 'prosemirror-model';
18
18
  import { Marks, Nodes } from './types';
19
19
  export * from './groups';
20
+ export * from './nodes/abstract';
20
21
  export * from './nodes/affiliation';
21
22
  export * from './nodes/affiliations';
22
23
  export * from './nodes/alt_text';
@@ -0,0 +1,8 @@
1
+ import { JSONProsemirrorNode } from '../../../types';
2
+ import { MigrationScript } from '../migration-script';
3
+ declare class Migration453 implements MigrationScript {
4
+ fromVersion: string;
5
+ toVersion: string;
6
+ migrateNode(node: JSONProsemirrorNode): JSONProsemirrorNode;
7
+ }
8
+ export default Migration453;
@@ -29,5 +29,6 @@ import Migration4334 from './4.3.34';
29
29
  import Migration4335 from './4.3.35';
30
30
  import Migration442 from './4.4.2';
31
31
  import Migration447 from './4.4.7';
32
- declare const migrations: (Migration125 | Migration2322 | Migration3012 | Migration3021 | Migration3030 | Migration3031 | Migration3041 | Migration3055 | Migration3056 | Migration4213 | Migration4215 | Migration4323 | Migration4334 | Migration4335 | Migration442 | Migration447)[];
32
+ import Migration453 from './4.5.3';
33
+ declare const migrations: (Migration125 | Migration2322 | Migration3012 | Migration3021 | Migration3030 | Migration3031 | Migration3041 | Migration3055 | Migration3056 | Migration4213 | Migration4215 | Migration4323 | Migration4334 | Migration4335 | Migration442 | Migration447 | Migration453)[];
33
34
  export default migrations;
@@ -0,0 +1,26 @@
1
+ /*!
2
+ * © 2026 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
+ import { NodeSpec } from 'prosemirror-model';
17
+ import { ManuscriptNode } from '../types';
18
+ export interface AbstractAttrs {
19
+ id: string;
20
+ category: string;
21
+ }
22
+ export interface AbstractNode extends ManuscriptNode {
23
+ attrs: AbstractAttrs;
24
+ }
25
+ export declare const abstract: NodeSpec;
26
+ export declare const isAbstractNode: (node: ManuscriptNode) => node is AbstractNode;
@@ -17,7 +17,7 @@ import { Fragment, Mark as ProsemirrorMark, MarkType, Node as ProsemirrorNode, N
17
17
  import { EditorState, NodeSelection, Plugin, TextSelection, Transaction } from 'prosemirror-state';
18
18
  import { EditorView, NodeView } from 'prosemirror-view';
19
19
  export type Marks = 'bold' | 'code' | 'italic' | 'smallcaps' | 'strikethrough' | 'styled' | 'subscript' | 'superscript' | 'underline' | 'tracked_insert' | 'tracked_delete';
20
- export type Nodes = 'attribution' | 'bibliography_item' | 'bibliography_element' | 'bibliography_section' | 'blockquote_element' | 'quote_image' | 'list' | 'caption' | 'caption_title' | 'comment' | 'comments' | 'citation' | 'cross_reference' | 'doc' | 'equation' | 'equation_element' | 'figure' | 'graphical_abstract_section' | 'figure_element' | 'footnote' | 'footnotes_element' | 'footnotes_section' | 'hard_break' | 'highlight_marker' | 'inline_equation' | 'inline_footnote' | 'keyword' | 'keywords_element' | 'keyword_group' | 'keywords' | 'link' | 'list_item' | 'listing' | 'listing_element' | 'manuscript' | 'abstracts' | 'body' | 'backmatter' | 'missing_figure' | 'paragraph' | 'placeholder' | 'placeholder_element' | 'pullquote_element' | 'section' | 'section_label' | 'section_title' | 'section_title_plain' | 'table' | 'table_cell' | 'table_element' | 'table_row' | 'table_colgroup' | 'table_col' | 'table_header' | 'text' | 'text_block' | 'affiliation' | 'contributor' | 'table_element_footer' | 'title' | 'affiliations' | 'contributors' | 'supplements' | 'supplement' | 'author_notes' | 'corresp' | 'general_table_footnote' | 'box_element' | 'awards' | 'award' | 'embed' | 'image_element' | 'attachment' | 'attachments' | 'alt_title' | 'alt_text' | 'alt_titles' | 'long_desc' | 'hero_image' | 'headshot_grid' | 'headshot_element' | 'headshot_image' | 'trans_abstract' | 'trans_graphical_abstract' | 'subtitle' | 'subtitles';
20
+ export type Nodes = 'attribution' | 'bibliography_item' | 'bibliography_element' | 'bibliography_section' | 'blockquote_element' | 'quote_image' | 'list' | 'caption' | 'caption_title' | 'comment' | 'comments' | 'citation' | 'cross_reference' | 'doc' | 'equation' | 'equation_element' | 'figure' | 'graphical_abstract_section' | 'figure_element' | 'footnote' | 'footnotes_element' | 'footnotes_section' | 'hard_break' | 'highlight_marker' | 'inline_equation' | 'inline_footnote' | 'keyword' | 'keywords_element' | 'keyword_group' | 'keywords' | 'link' | 'list_item' | 'listing' | 'listing_element' | 'manuscript' | 'abstract' | 'abstracts' | 'body' | 'backmatter' | 'missing_figure' | 'paragraph' | 'placeholder' | 'placeholder_element' | 'pullquote_element' | 'section' | 'section_label' | 'section_title' | 'section_title_plain' | 'table' | 'table_cell' | 'table_element' | 'table_row' | 'table_colgroup' | 'table_col' | 'table_header' | 'text' | 'text_block' | 'affiliation' | 'contributor' | 'table_element_footer' | 'title' | 'affiliations' | 'contributors' | 'supplements' | 'supplement' | 'author_notes' | 'corresp' | 'general_table_footnote' | 'box_element' | 'awards' | 'award' | 'embed' | 'image_element' | 'attachment' | 'attachments' | 'alt_title' | 'alt_text' | 'alt_titles' | 'long_desc' | 'hero_image' | 'headshot_grid' | 'headshot_element' | 'headshot_image' | 'trans_abstract' | 'trans_graphical_abstract' | 'subtitle' | 'subtitles';
21
21
  export type ManuscriptSchema = Schema<Nodes, Marks>;
22
22
  export type ManuscriptEditorState = EditorState;
23
23
  export type ManuscriptEditorView = EditorView;
@@ -1 +1 @@
1
- export declare const VERSION = "4.5.2";
1
+ export declare const VERSION = "4.5.3";
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": "4.5.2",
4
+ "version": "4.5.3",
5
5
  "repository": "github:Atypon-OpenSource/manuscripts-transform",
6
6
  "license": "Apache-2.0",
7
7
  "main": "dist/cjs",