@manuscripts/transform 1.5.7 → 1.5.8-LEAN-3030

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 (131) hide show
  1. package/dist/cjs/index.js +1 -1
  2. package/dist/cjs/jats/importer/index.js +1 -3
  3. package/dist/cjs/jats/importer/jats-body-dom-parser.js +23 -227
  4. package/dist/cjs/jats/importer/jats-body-transformations.js +110 -201
  5. package/dist/cjs/jats/importer/jats-comments.js +100 -98
  6. package/dist/cjs/jats/importer/jats-front-parser.js +87 -81
  7. package/dist/cjs/jats/importer/jats-journal-meta-parser.js +51 -39
  8. package/dist/cjs/jats/importer/jats-parser-utils.js +17 -56
  9. package/dist/cjs/jats/importer/jats-reference-parser.js +24 -79
  10. package/dist/cjs/jats/importer/jats-references.js +34 -0
  11. package/dist/cjs/jats/importer/parse-jats-article.js +67 -173
  12. package/dist/cjs/jats/index.js +1 -3
  13. package/dist/cjs/jats/jats-exporter.js +33 -54
  14. package/dist/cjs/lib/section-group-type.js +30 -0
  15. package/dist/cjs/lib/utils.js +23 -1
  16. package/dist/cjs/schema/index.js +20 -17
  17. package/dist/cjs/schema/nodes/abstracts.js +27 -0
  18. package/dist/cjs/schema/nodes/affiliations.js +27 -0
  19. package/dist/cjs/schema/nodes/backmatter.js +27 -0
  20. package/dist/cjs/schema/nodes/body.js +27 -0
  21. package/dist/cjs/schema/nodes/citation.js +10 -15
  22. package/dist/cjs/schema/nodes/{comment_list.js → comments.js} +4 -4
  23. package/dist/cjs/schema/nodes/contributors.js +27 -0
  24. package/dist/cjs/schema/nodes/{meta_section.js → core_section.js} +6 -5
  25. package/dist/cjs/schema/nodes/cross_reference.js +4 -3
  26. package/dist/cjs/schema/nodes/inline_footnote.js +6 -5
  27. package/dist/cjs/schema/nodes/keyword.js +0 -1
  28. package/dist/cjs/schema/nodes/{keywords_group.js → keyword_group.js} +6 -6
  29. package/dist/cjs/schema/nodes/{keywords_section.js → keywords.js} +7 -7
  30. package/dist/cjs/schema/nodes/keywords_element.js +1 -1
  31. package/dist/cjs/schema/nodes/manuscript.js +5 -2
  32. package/dist/cjs/transformer/builders.js +9 -86
  33. package/dist/cjs/transformer/decode.js +143 -162
  34. package/dist/cjs/transformer/encode.js +54 -45
  35. package/dist/cjs/transformer/highlight-markers.js +4 -4
  36. package/dist/cjs/transformer/html.js +5 -20
  37. package/dist/cjs/transformer/node-names.js +1 -1
  38. package/dist/cjs/transformer/node-title.js +1 -1
  39. package/dist/cjs/transformer/node-types.js +7 -6
  40. package/dist/cjs/transformer/object-types.js +1 -2
  41. package/dist/cjs/transformer/section-category.js +35 -17
  42. package/dist/es/index.js +1 -1
  43. package/dist/es/jats/importer/index.js +1 -1
  44. package/dist/es/jats/importer/jats-body-dom-parser.js +23 -227
  45. package/dist/es/jats/importer/jats-body-transformations.js +111 -202
  46. package/dist/es/jats/importer/jats-comments.js +97 -96
  47. package/dist/es/jats/importer/jats-front-parser.js +88 -82
  48. package/dist/es/jats/importer/jats-journal-meta-parser.js +51 -39
  49. package/dist/es/jats/importer/jats-parser-utils.js +16 -54
  50. package/dist/es/jats/importer/jats-reference-parser.js +27 -82
  51. package/dist/es/jats/importer/jats-references.js +30 -0
  52. package/dist/es/jats/importer/parse-jats-article.js +70 -174
  53. package/dist/es/jats/index.js +1 -1
  54. package/dist/es/jats/jats-exporter.js +33 -54
  55. package/dist/es/lib/section-group-type.js +27 -0
  56. package/dist/es/lib/utils.js +20 -0
  57. package/dist/es/schema/index.js +21 -18
  58. package/dist/es/schema/nodes/abstracts.js +24 -0
  59. package/dist/es/schema/nodes/affiliations.js +24 -0
  60. package/dist/es/schema/nodes/backmatter.js +24 -0
  61. package/dist/es/schema/nodes/body.js +24 -0
  62. package/dist/es/schema/nodes/citation.js +10 -15
  63. package/dist/es/schema/nodes/{comment_list.js → comments.js} +3 -3
  64. package/dist/es/schema/nodes/contributors.js +24 -0
  65. package/dist/es/schema/nodes/{meta_section.js → core_section.js} +5 -4
  66. package/dist/es/schema/nodes/cross_reference.js +4 -3
  67. package/dist/es/schema/nodes/inline_footnote.js +6 -5
  68. package/dist/es/schema/nodes/keyword.js +0 -1
  69. package/dist/es/schema/nodes/{keywords_group.js → keyword_group.js} +4 -4
  70. package/dist/es/schema/nodes/{keywords_section.js → keywords.js} +5 -5
  71. package/dist/es/schema/nodes/keywords_element.js +1 -1
  72. package/dist/es/schema/nodes/manuscript.js +3 -1
  73. package/dist/es/transformer/builders.js +6 -73
  74. package/dist/es/transformer/decode.js +143 -161
  75. package/dist/es/transformer/encode.js +57 -48
  76. package/dist/es/transformer/highlight-markers.js +1 -1
  77. package/dist/es/transformer/html.js +5 -20
  78. package/dist/es/transformer/node-names.js +1 -1
  79. package/dist/es/transformer/node-title.js +1 -1
  80. package/dist/es/transformer/node-types.js +7 -6
  81. package/dist/es/transformer/object-types.js +0 -1
  82. package/dist/es/transformer/section-category.js +33 -15
  83. package/dist/types/index.d.ts +1 -1
  84. package/dist/types/jats/importer/index.d.ts +1 -1
  85. package/dist/types/jats/importer/jats-body-transformations.d.ts +16 -19
  86. package/dist/types/jats/importer/jats-comments.d.ts +13 -9
  87. package/dist/types/jats/importer/jats-front-parser.d.ts +35 -12
  88. package/dist/types/jats/importer/jats-journal-meta-parser.d.ts +4 -4
  89. package/dist/types/jats/importer/jats-parser-utils.d.ts +1 -6
  90. package/dist/types/jats/importer/jats-reference-parser.d.ts +2 -6
  91. package/dist/types/jats/importer/jats-references.d.ts +12 -0
  92. package/dist/types/jats/importer/parse-jats-article.d.ts +5 -17
  93. package/dist/types/jats/index.d.ts +1 -1
  94. package/dist/types/lib/section-group-type.d.ts +31 -0
  95. package/dist/types/lib/utils.d.ts +4 -1
  96. package/dist/types/schema/index.d.ts +4 -5
  97. package/dist/types/schema/nodes/{meta_section.d.ts → abstracts.d.ts} +1 -9
  98. package/dist/types/schema/nodes/affiliations.d.ts +17 -0
  99. package/dist/types/schema/nodes/backmatter.d.ts +17 -0
  100. package/dist/types/schema/nodes/body.d.ts +17 -0
  101. package/dist/types/schema/nodes/citation.d.ts +3 -5
  102. package/dist/types/schema/nodes/comments.d.ts +17 -0
  103. package/dist/types/schema/nodes/contributors.d.ts +17 -0
  104. package/dist/types/schema/nodes/core_section.d.ts +17 -0
  105. package/dist/types/schema/nodes/cross_reference.d.ts +1 -1
  106. package/dist/types/schema/nodes/inline_footnote.d.ts +1 -1
  107. package/dist/types/schema/nodes/keyword.d.ts +0 -1
  108. package/dist/types/schema/nodes/{contributors_element.d.ts → keyword_group.d.ts} +3 -4
  109. package/dist/types/schema/nodes/{comment_list.d.ts → keywords.d.ts} +3 -2
  110. package/dist/types/schema/nodes/manuscript.d.ts +1 -0
  111. package/dist/types/schema/types.d.ts +1 -1
  112. package/dist/types/transformer/builders.d.ts +2 -14
  113. package/dist/types/transformer/decode.d.ts +7 -9
  114. package/dist/types/transformer/encode.d.ts +1 -1
  115. package/dist/types/transformer/highlight-markers.d.ts +1 -0
  116. package/dist/types/transformer/object-types.d.ts +1 -2
  117. package/dist/types/transformer/section-category.d.ts +1 -1
  118. package/package.json +1 -1
  119. package/dist/cjs/lib/core-section-categories.js +0 -29
  120. package/dist/cjs/schema/nodes/affiliations_section.js +0 -36
  121. package/dist/cjs/schema/nodes/contributors_element.js +0 -49
  122. package/dist/cjs/schema/nodes/contributors_section.js +0 -36
  123. package/dist/es/lib/core-section-categories.js +0 -26
  124. package/dist/es/schema/nodes/affiliations_section.js +0 -32
  125. package/dist/es/schema/nodes/contributors_element.js +0 -46
  126. package/dist/es/schema/nodes/contributors_section.js +0 -32
  127. package/dist/types/lib/core-section-categories.d.ts +0 -8
  128. package/dist/types/schema/nodes/affiliations_section.d.ts +0 -11
  129. package/dist/types/schema/nodes/contributors_section.d.ts +0 -12
  130. package/dist/types/schema/nodes/keywords_group.d.ts +0 -26
  131. package/dist/types/schema/nodes/keywords_section.d.ts +0 -26
@@ -28,12 +28,13 @@ import { ObjectTypes, } from '@manuscripts/json-schema';
28
28
  import debug from 'debug';
29
29
  import { DOMParser } from 'prosemirror-model';
30
30
  import { MissingElement } from '../errors';
31
+ import { groupBy } from '../lib/utils';
31
32
  import { schema, } from '../schema';
32
33
  import { buildTitles } from './builders';
33
34
  import { insertHighlightMarkers } from './highlight-markers';
34
35
  import { generateNodeID } from './id';
35
36
  import { ExtraObjectTypes, hasObjectType, isCommentAnnotation, isManuscript, } from './object-types';
36
- import { chooseSectionLableName, chooseSectionNodeType, chooseSecType, guessSectionCategory, } from './section-category';
37
+ import { chooseCoreSectionBySection, chooseSectionLableName, chooseSectionNodeType, chooseSecType, guessSectionCategory, } from './section-category';
37
38
  import { timestamp } from './timestamp';
38
39
  const warn = debug('manuscripts-transform');
39
40
  const parser = DOMParser.fromSchema(schema);
@@ -54,78 +55,86 @@ export const sortSectionsByPriority = (a, b) => a.priority === b.priority ? 0 :
54
55
  const getSections = (modelMap) => getModelsByType(modelMap, ObjectTypes.Section).sort(sortSectionsByPriority);
55
56
  const getAffiliations = (modelMap) => getModelsByType(modelMap, ObjectTypes.Affiliation);
56
57
  const getContributors = (modelMap) => getModelsByType(modelMap, ObjectTypes.Contributor);
57
- export const isManuscriptNode = (model) => model !== null;
58
- const isParagraphElement = hasObjectType(ObjectTypes.ParagraphElement);
58
+ const getKeywordElements = (modelMap) => getModelsByType(modelMap, ObjectTypes.KeywordsElement);
59
+ const getKeywordGroups = (modelMap) => getModelsByType(modelMap, ObjectTypes.KeywordGroup);
60
+ const getKeywords = (modelMap) => getModelsByType(modelMap, ObjectTypes.Keyword);
61
+ const getTitles = (modelMap) => getModelsByType(modelMap, ObjectTypes.Titles)[0];
59
62
  const isFootnote = hasObjectType(ObjectTypes.Footnote);
60
- const isKeyword = hasObjectType(ObjectTypes.Keyword);
61
- const isKeywordsSection = (model) => model.category === 'MPSectionCategory:keywords';
62
- const isAffiliationsSection = (model) => model.category === 'MPSectionCategory:affiliations';
63
- const isContributorsSection = (model) => model.category === 'MPSectionCategory:contributors';
64
63
  const hasParentSection = (id) => (section) => section.path &&
65
64
  section.path.length > 1 &&
66
65
  section.path[section.path.length - 2] === id;
67
66
  export class Decoder {
68
- createMetaSectionNode() {
69
- const commentListNode = this.createCommentListNode();
70
- return schema.nodes.meta_section.createAndFill({}, [
71
- commentListNode,
72
- ]);
73
- }
74
- createCommentListNode() {
75
- return schema.nodes.comment_list.createAndFill({}, [
76
- ...this.comments.values(),
77
- ]);
67
+ createTitleNode() {
68
+ const titles = getTitles(this.modelMap) || buildTitles();
69
+ return this.decode(titles);
78
70
  }
79
- handleMissingRootSectionNodes(rootSectionNodes) {
80
- if (!rootSectionNodes.find((node) => node.type.name === 'affiliations_section')) {
81
- this.createAffiliationSectionNode(rootSectionNodes);
82
- }
83
- if (!rootSectionNodes.find((node) => node.type.name === 'contributors_section')) {
84
- this.createContributorSectionNode(rootSectionNodes);
85
- }
71
+ createAffiliationsNode() {
72
+ const affiliations = getAffiliations(this.modelMap)
73
+ .map((a) => this.decode(a))
74
+ .filter(Boolean);
75
+ return schema.nodes.affiliations.createAndFill({}, affiliations);
86
76
  }
87
- createAffiliationSectionNode(rootSectionNodes) {
88
- const affiliationNodes = getAffiliations(this.modelMap)
89
- .map((affiliation) => this.decode(affiliation))
77
+ createContributorsNode() {
78
+ const contributors = getContributors(this.modelMap)
79
+ .map((c) => this.decode(c))
90
80
  .filter(Boolean);
91
- if (affiliationNodes.length) {
92
- const node = schema.nodes.affiliations_section.createAndFill({
93
- id: generateNodeID(schema.nodes.section),
94
- }, affiliationNodes);
95
- rootSectionNodes.unshift(node);
96
- }
81
+ return schema.nodes.contributors.createAndFill({}, contributors);
97
82
  }
98
- createContributorSectionNode(rootSectionNodes) {
99
- const contributorNodes = getContributors(this.modelMap)
100
- .map((contributor) => this.decode(contributor))
83
+ createKeywordsNode() {
84
+ const elements = getKeywordElements(this.modelMap)
85
+ .map((e) => this.decode(e))
101
86
  .filter(Boolean);
102
- if (contributorNodes.length) {
103
- const node = schema.nodes.contributors_section.createAndFill({
104
- id: generateNodeID(schema.nodes.section),
105
- }, contributorNodes);
106
- rootSectionNodes.unshift(node);
107
- }
87
+ return schema.nodes.keywords.createAndFill({}, [
88
+ schema.nodes.section_title.create({}, schema.text('Keywords')),
89
+ ...elements,
90
+ ]);
108
91
  }
109
- createTitleNode() {
110
- const titles = getModelsByType(this.modelMap, ObjectTypes.Titles)[0] ||
111
- buildTitles();
112
- return this.decode(titles);
92
+ createCommentsNode() {
93
+ return schema.nodes.comments.createAndFill({}, [
94
+ ...this.comments.values(),
95
+ ]);
113
96
  }
114
97
  createRootSectionNodes() {
115
- let rootSections = getSections(this.modelMap).filter((section) => !section.path || section.path.length <= 1);
98
+ let rootSections = getSections(this.modelMap)
99
+ .filter((section) => !section.path || section.path.length <= 1)
100
+ .filter((section) => section.category !== 'MPSectionCategory:contributors' &&
101
+ section.category !== 'MPSectionCategory:affiliations' &&
102
+ section.category !== 'MPSectionCategory:keywords');
116
103
  rootSections = this.addGeneratedLabels(rootSections);
117
- const rootSectionNodes = rootSections
118
- .map(this.decode)
119
- .filter(isManuscriptNode);
120
- this.handleMissingRootSectionNodes(rootSectionNodes);
121
- if (!rootSectionNodes.length) {
122
- rootSectionNodes.push(schema.nodes.section.createAndFill({
123
- id: generateNodeID(schema.nodes.section),
124
- }));
104
+ const sectionGroups = groupBy(rootSections, (sec) => {
105
+ var _a;
106
+ return chooseCoreSectionBySection((_a = sec.category) !== null && _a !== void 0 ? _a : '');
107
+ });
108
+ this.ensureCoreSectionsExist(sectionGroups);
109
+ const absSectionNode = sectionGroups['MPSectionCategory:abstracts'].map((e) => this.decode(e));
110
+ const bodySectionNodes = sectionGroups['MPSectionCategory:body'].map((e) => this.decode(e));
111
+ const backmatterSectionNodes = sectionGroups['MPSectionCategory:backmatter'].map(e => this.decode(e));
112
+ const abstractCoreSectionNodes = this.createAndFill(schema.nodes.abstracts, absSectionNode);
113
+ const bodyCoreSectionNodes = this.createAndFill(schema.nodes.body, bodySectionNodes);
114
+ const backmatterCoreSectionNodes = this.createAndFill(schema.nodes.backmatter, backmatterSectionNodes);
115
+ return {
116
+ abstracts: abstractCoreSectionNodes,
117
+ body: bodyCoreSectionNodes,
118
+ backmatter: backmatterCoreSectionNodes,
119
+ };
120
+ }
121
+ ensureCoreSectionsExist(coreSections) {
122
+ if (!coreSections['MPSectionCategory:abstracts']) {
123
+ coreSections['MPSectionCategory:abstracts'] = [];
124
+ }
125
+ if (!coreSections['MPSectionCategory:body']) {
126
+ coreSections['MPSectionCategory:body'] = [];
127
+ }
128
+ if (!coreSections['MPSectionCategory:backmatter']) {
129
+ coreSections['MPSectionCategory:backmatter'] = [];
125
130
  }
126
- return rootSectionNodes;
127
131
  }
128
- createCommentsNode(model) {
132
+ createAndFill(nodeType, content) {
133
+ return nodeType.createAndFill({
134
+ id: generateNodeID(nodeType),
135
+ }, content);
136
+ }
137
+ createCommentNodes(model) {
129
138
  const comments = [];
130
139
  for (const comment of this.getComments(model)) {
131
140
  comments.push(this.decode(comment));
@@ -170,8 +179,8 @@ export class Decoder {
170
179
  },
171
180
  [ObjectTypes.BibliographyItem]: (data) => {
172
181
  const model = data;
173
- const commentNodes = this.createCommentsNode(model);
174
- commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
182
+ const comments = this.createCommentNodes(model);
183
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
175
184
  return schema.nodes.bibliography_item.create({
176
185
  id: model._id,
177
186
  type: model.type,
@@ -185,7 +194,7 @@ export class Decoder {
185
194
  page: model.page,
186
195
  title: model.title,
187
196
  literal: model.literal,
188
- comments: commentNodes.map((c) => c.attrs.id),
197
+ comments: comments.map((c) => c.attrs.id),
189
198
  });
190
199
  },
191
200
  [ExtraObjectTypes.PlaceholderElement]: (data) => {
@@ -196,14 +205,14 @@ export class Decoder {
196
205
  },
197
206
  [ObjectTypes.Figure]: (data) => {
198
207
  const model = data;
199
- const commentNodes = this.createCommentsNode(model);
200
- commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
208
+ const comments = this.createCommentNodes(model);
209
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
201
210
  return schema.nodes.figure.create({
202
211
  id: model._id,
203
212
  contentType: model.contentType,
204
213
  src: model.src,
205
214
  position: model.position,
206
- comments: commentNodes.map((c) => c.attrs.id),
215
+ comments: comments.map((c) => c.attrs.id),
207
216
  });
208
217
  },
209
218
  [ObjectTypes.FigureElement]: (data) => {
@@ -232,8 +241,8 @@ export class Decoder {
232
241
  figures.push(schema.nodes.figure.createAndFill());
233
242
  }
234
243
  const figcaption = this.getFigcaption(model);
235
- const commentNodes = this.createCommentsNode(model);
236
- commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
244
+ const comments = this.createCommentNodes(model);
245
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
237
246
  const content = [...paragraphs, ...figures, figcaption];
238
247
  const listing = this.extractListing(model);
239
248
  if (listing) {
@@ -254,7 +263,7 @@ export class Decoder {
254
263
  suppressTitle: Boolean(model.suppressTitle === undefined ? true : model.suppressTitle),
255
264
  attribution: model.attribution,
256
265
  alternatives: model.alternatives,
257
- comments: commentNodes.map((c) => c.attrs.id),
266
+ comments: comments.map((c) => c.attrs.id),
258
267
  }, content);
259
268
  },
260
269
  [ObjectTypes.Equation]: (data) => {
@@ -297,13 +306,13 @@ export class Decoder {
297
306
  if (isFootnote(model) &&
298
307
  model.kind === collateByKind &&
299
308
  model.containingObject === foonotesElementModel._id) {
300
- const commentNodes = this.createCommentsNode(model);
301
- commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
309
+ const comments = this.createCommentNodes(model);
310
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
302
311
  const footnote = this.parseContents(model.contents || '<div></div>', undefined, this.getComments(model), {
303
312
  topNode: schema.nodes.footnote.create({
304
313
  id: model._id,
305
314
  kind: model.kind,
306
- comments: commentNodes.map((c) => c.attrs.id),
315
+ comments: comments.map((c) => c.attrs.id),
307
316
  }),
308
317
  });
309
318
  footnotesOfKind.push(footnote);
@@ -317,36 +326,51 @@ export class Decoder {
317
326
  },
318
327
  [ObjectTypes.Footnote]: (data) => {
319
328
  const footnoteModel = data;
320
- const commentNodes = this.createCommentsNode(footnoteModel);
321
- commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
329
+ const comments = this.createCommentNodes(footnoteModel);
330
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
322
331
  return this.parseContents(footnoteModel.contents || '<div></div>', undefined, this.getComments(footnoteModel), {
323
332
  topNode: schema.nodes.footnote.create({
324
333
  id: footnoteModel._id,
325
334
  kind: footnoteModel.kind,
326
- comments: commentNodes.map((c) => c.attrs.id),
335
+ comments: comments.map((c) => c.attrs.id),
327
336
  }),
328
337
  });
329
338
  },
330
339
  [ObjectTypes.KeywordsElement]: (data) => {
331
340
  const model = data;
332
- const keywordGroups = this.getKeywordGroups();
341
+ const keywordGroups = getKeywordGroups(this.modelMap).map((k) => this.decode(k));
333
342
  return schema.nodes.keywords_element.create({
334
343
  id: model._id,
335
344
  paragraphStyle: model.paragraphStyle,
336
345
  }, keywordGroups);
337
346
  },
347
+ [ObjectTypes.KeywordGroup]: (data) => {
348
+ const keywordGroup = data;
349
+ const keywords = getKeywords(this.modelMap)
350
+ .filter((k) => k.containedGroup === keywordGroup._id)
351
+ .map((k) => this.decode(k));
352
+ const comments = this.createCommentNodes(keywordGroup);
353
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
354
+ return schema.nodes.keyword_group.create({
355
+ id: keywordGroup._id,
356
+ type: keywordGroup.type,
357
+ comments: comments.map((c) => c.attrs.id),
358
+ }, keywords);
359
+ },
338
360
  [ObjectTypes.Keyword]: (data) => {
339
- const model = data;
361
+ const keyword = data;
362
+ const comments = this.createCommentNodes(keyword);
363
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
340
364
  return schema.nodes.keyword.create({
341
- id: model._id,
342
- contents: model.name,
343
- comments: this.createCommentsNode(model),
344
- }, schema.text(model.name));
365
+ id: keyword._id,
366
+ contents: keyword.name,
367
+ comments: comments.map((c) => c.attrs.id),
368
+ }, schema.text(keyword.name));
345
369
  },
346
370
  [ObjectTypes.ListElement]: (data) => {
347
371
  const model = data;
348
- const commentNodes = this.createCommentsNode(model);
349
- commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
372
+ const comments = this.createCommentNodes(model);
373
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
350
374
  switch (model.elementType) {
351
375
  case 'ol':
352
376
  return this.parseContents(model.contents || '<ol></ol>', undefined, this.getComments(model), {
@@ -354,7 +378,7 @@ export class Decoder {
354
378
  id: model._id,
355
379
  listStyleType: model.listStyleType,
356
380
  paragraphStyle: model.paragraphStyle,
357
- comments: commentNodes.map((c) => c.attrs.id),
381
+ comments: comments.map((c) => c.attrs.id),
358
382
  }),
359
383
  });
360
384
  case 'ul':
@@ -370,14 +394,14 @@ export class Decoder {
370
394
  },
371
395
  [ObjectTypes.Listing]: (data) => {
372
396
  const model = data;
373
- const commentNodes = this.createCommentsNode(model);
374
- commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
397
+ const comments = this.createCommentNodes(model);
398
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
375
399
  return schema.nodes.listing.createChecked({
376
400
  id: model._id,
377
401
  contents: model.contents,
378
402
  language: model.language,
379
403
  languageKey: model.languageKey,
380
- comments: commentNodes.map((c) => c.attrs.id),
404
+ comments: comments.map((c) => c.attrs.id),
381
405
  });
382
406
  },
383
407
  [ObjectTypes.ListingElement]: (data) => {
@@ -397,13 +421,13 @@ export class Decoder {
397
421
  throw new MissingElement(model.containedObjectID);
398
422
  }
399
423
  const figcaption = this.getFigcaption(model);
400
- const commentNodes = this.createCommentsNode(model);
401
- commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
424
+ const comments = this.createCommentNodes(model);
425
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
402
426
  return schema.nodes.listing_element.createChecked({
403
427
  id: model._id,
404
428
  suppressCaption: model.suppressCaption,
405
429
  suppressTitle: Boolean(model.suppressTitle === undefined ? true : model.suppressTitle),
406
- comments: commentNodes.map((c) => c.attrs.id),
430
+ comments: comments.map((c) => c.attrs.id),
407
431
  }, [listing, figcaption]);
408
432
  },
409
433
  [ObjectTypes.MissingFigure]: (data) => {
@@ -415,14 +439,14 @@ export class Decoder {
415
439
  },
416
440
  [ObjectTypes.ParagraphElement]: (data) => {
417
441
  const model = data;
418
- const commentNodes = this.createCommentsNode(model);
419
- commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
442
+ const comments = this.createCommentNodes(model);
443
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
420
444
  return this.parseContents(model.contents || '<p></p>', undefined, this.getComments(model), {
421
445
  topNode: schema.nodes.paragraph.create({
422
446
  id: model._id,
423
447
  paragraphStyle: model.paragraphStyle,
424
448
  placeholder: model.placeholderInnerHTML,
425
- comments: commentNodes.map((c) => c.attrs.id),
449
+ comments: comments.map((c) => c.attrs.id),
426
450
  }),
427
451
  });
428
452
  },
@@ -463,9 +487,6 @@ export class Decoder {
463
487
  for (const id of model.elementIDs) {
464
488
  const element = this.getModel(id);
465
489
  if (element) {
466
- if (isKeywordsSection(model) && isParagraphElement(element)) {
467
- continue;
468
- }
469
490
  elements.push(element);
470
491
  }
471
492
  else if (this.allowMissingElements) {
@@ -484,9 +505,7 @@ export class Decoder {
484
505
  }
485
506
  }
486
507
  }
487
- const elementNodes = elements
488
- .map(this.decode)
489
- .filter(isManuscriptNode);
508
+ const elementNodes = elements.map(e => this.decode(e));
490
509
  const sectionTitle = 'section_title';
491
510
  const sectionTitleNode = model.title
492
511
  ? this.parseContents(model.title, 'h1', this.getComments(model), {
@@ -504,26 +523,20 @@ export class Decoder {
504
523
  .map(this.creators[ObjectTypes.Section]);
505
524
  const sectionCategory = model.category || guessSectionCategory(elements);
506
525
  const sectionNodeType = chooseSectionNodeType(sectionCategory);
507
- const commentNodes = this.createCommentsNode(model);
508
- commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
509
- let content;
510
- if (isAffiliationsSection(model) || isContributorsSection(model)) {
511
- content = elementNodes.concat(nestedSections);
512
- }
513
- else {
514
- content = (sectionLabelNode
515
- ? [sectionLabelNode, sectionTitleNode]
516
- : [sectionTitleNode])
517
- .concat(elementNodes)
518
- .concat(nestedSections);
519
- }
526
+ const comments = this.createCommentNodes(model);
527
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
528
+ const content = (sectionLabelNode
529
+ ? [sectionLabelNode, sectionTitleNode]
530
+ : [sectionTitleNode])
531
+ .concat(elementNodes)
532
+ .concat(nestedSections);
520
533
  const sectionNode = sectionNodeType.createAndFill({
521
534
  id: model._id,
522
535
  category: sectionCategory,
523
536
  titleSuppressed: model.titleSuppressed,
524
537
  pageBreakStyle: model.pageBreakStyle,
525
538
  generatedLabel: model.generatedLabel,
526
- comments: commentNodes.map((c) => c.attrs.id),
539
+ comments: comments.map((c) => c.attrs.id),
527
540
  }, content);
528
541
  if (!sectionNode) {
529
542
  console.error(model);
@@ -533,12 +546,12 @@ export class Decoder {
533
546
  },
534
547
  [ObjectTypes.Table]: (data) => {
535
548
  const model = data;
536
- const commentNodes = this.createCommentsNode(model);
537
- commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
549
+ const comments = this.createCommentNodes(model);
550
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
538
551
  return this.parseContents(model.contents, undefined, this.getComments(model), {
539
552
  topNode: schema.nodes.table.create({
540
553
  id: model._id,
541
- comments: commentNodes.map((c) => c.attrs.id),
554
+ comments: comments.map((c) => c.attrs.id),
542
555
  }),
543
556
  });
544
557
  },
@@ -547,8 +560,8 @@ export class Decoder {
547
560
  const table = this.createTable(model);
548
561
  const tableElementFooter = this.createTableElementFooter(model);
549
562
  const figcaption = this.getFigcaption(model);
550
- const commentNodes = this.createCommentsNode(model);
551
- commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
563
+ const comments = this.createCommentNodes(model);
564
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
552
565
  const content = tableElementFooter
553
566
  ? [table, figcaption, tableElementFooter]
554
567
  : [table, figcaption];
@@ -569,7 +582,7 @@ export class Decoder {
569
582
  suppressHeader: model.suppressHeader,
570
583
  tableStyle: model.tableStyle,
571
584
  paragraphStyle: model.paragraphStyle,
572
- comments: commentNodes.map((c) => c.attrs.id),
585
+ comments: comments.map((c) => c.attrs.id),
573
586
  }, content);
574
587
  },
575
588
  [ObjectTypes.TOCElement]: (data) => {
@@ -635,13 +648,21 @@ export class Decoder {
635
648
  };
636
649
  this.getModel = (id) => this.modelMap.get(id);
637
650
  this.createArticleNode = (manuscriptID) => {
638
- const titlesNode = this.createTitleNode();
639
- const rootSectionNodes = this.createRootSectionNodes();
640
- const metaSectionNode = this.createMetaSectionNode();
651
+ const title = this.createTitleNode();
652
+ const contributors = this.createContributorsNode();
653
+ const affiliations = this.createAffiliationsNode();
654
+ const keywords = this.createKeywordsNode();
655
+ const { abstracts, body, backmatter } = this.createRootSectionNodes();
656
+ const comments = this.createCommentsNode();
641
657
  const contents = [
642
- titlesNode,
643
- ...rootSectionNodes,
644
- metaSectionNode,
658
+ title,
659
+ contributors,
660
+ affiliations,
661
+ keywords,
662
+ abstracts,
663
+ body,
664
+ backmatter,
665
+ comments,
645
666
  ];
646
667
  return schema.nodes.manuscript.create({
647
668
  id: manuscriptID || this.getManuscriptID(),
@@ -683,23 +704,6 @@ export class Decoder {
683
704
  }
684
705
  return parser.parse(template.content.firstElementChild, options);
685
706
  };
686
- this.getKeywords = (id) => {
687
- const keywordsOfKind = [];
688
- const keywordsByGroup = [...this.modelMap.values()].filter((m) => m.objectType === ObjectTypes.Keyword &&
689
- m.containedGroup === id);
690
- for (const model of keywordsByGroup) {
691
- if (isKeyword(model)) {
692
- const keyword = this.parseContents(model.name || '', 'div', this.getComments(model), {
693
- topNode: schema.nodes.keyword.create({
694
- id: model._id,
695
- contents: model.name,
696
- }),
697
- });
698
- keywordsOfKind.push(keyword);
699
- }
700
- }
701
- return keywordsOfKind;
702
- };
703
707
  this.getManuscriptID = () => {
704
708
  for (const item of this.modelMap.values()) {
705
709
  if (isManuscript(item)) {
@@ -784,26 +788,4 @@ export class Decoder {
784
788
  }
785
789
  return listing;
786
790
  }
787
- getKeywordGroups() {
788
- const kwdGroupNodes = [];
789
- const kwdGroupsModels = [
790
- ...this.modelMap.values(),
791
- ].filter((model) => model.objectType === ObjectTypes.KeywordGroup);
792
- if (kwdGroupsModels.length > 0) {
793
- for (const kwdGroupModel of kwdGroupsModels) {
794
- const keywords = this.getKeywords(kwdGroupModel._id);
795
- const commentNodes = this.createCommentsNode(kwdGroupModel);
796
- commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
797
- const contents = [];
798
- contents.push(...keywords);
799
- const kwdGroupNode = schema.nodes.keywords_group.create({
800
- id: kwdGroupModel._id,
801
- type: kwdGroupModel.type,
802
- comments: commentNodes.map((c) => c.attrs.id),
803
- }, contents);
804
- kwdGroupNodes.push(kwdGroupNode);
805
- }
806
- }
807
- return kwdGroupNodes;
808
- }
809
791
  }