@manuscripts/transform 1.5.8 → 2.0.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.
Files changed (133) 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 +34 -55
  14. package/dist/cjs/lib/section-group-type.js +30 -0
  15. package/dist/cjs/lib/utils.js +1 -25
  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 +147 -176
  34. package/dist/cjs/transformer/encode.js +66 -67
  35. package/dist/cjs/transformer/highlight-markers.js +48 -36
  36. package/dist/cjs/transformer/html.js +7 -23
  37. package/dist/cjs/transformer/labels.js +3 -17
  38. package/dist/cjs/transformer/node-names.js +1 -1
  39. package/dist/cjs/transformer/node-title.js +1 -1
  40. package/dist/cjs/transformer/node-types.js +7 -6
  41. package/dist/cjs/transformer/object-types.js +1 -2
  42. package/dist/cjs/transformer/section-category.js +31 -31
  43. package/dist/es/index.js +1 -1
  44. package/dist/es/jats/importer/index.js +1 -1
  45. package/dist/es/jats/importer/jats-body-dom-parser.js +23 -227
  46. package/dist/es/jats/importer/jats-body-transformations.js +111 -202
  47. package/dist/es/jats/importer/jats-comments.js +97 -96
  48. package/dist/es/jats/importer/jats-front-parser.js +88 -82
  49. package/dist/es/jats/importer/jats-journal-meta-parser.js +51 -39
  50. package/dist/es/jats/importer/jats-parser-utils.js +16 -54
  51. package/dist/es/jats/importer/jats-reference-parser.js +27 -82
  52. package/dist/es/jats/importer/jats-references.js +30 -0
  53. package/dist/es/jats/importer/parse-jats-article.js +70 -174
  54. package/dist/es/jats/index.js +1 -1
  55. package/dist/es/jats/jats-exporter.js +34 -55
  56. package/dist/es/lib/section-group-type.js +27 -0
  57. package/dist/es/lib/utils.js +0 -22
  58. package/dist/es/schema/index.js +21 -18
  59. package/dist/es/schema/nodes/abstracts.js +24 -0
  60. package/dist/es/schema/nodes/affiliations.js +24 -0
  61. package/dist/es/schema/nodes/backmatter.js +24 -0
  62. package/dist/es/schema/nodes/body.js +24 -0
  63. package/dist/es/schema/nodes/citation.js +10 -15
  64. package/dist/es/schema/nodes/{comment_list.js → comments.js} +3 -3
  65. package/dist/es/schema/nodes/contributors.js +24 -0
  66. package/dist/es/schema/nodes/{meta_section.js → core_section.js} +5 -4
  67. package/dist/es/schema/nodes/cross_reference.js +4 -3
  68. package/dist/es/schema/nodes/inline_footnote.js +6 -5
  69. package/dist/es/schema/nodes/keyword.js +0 -1
  70. package/dist/es/schema/nodes/{keywords_group.js → keyword_group.js} +4 -4
  71. package/dist/es/schema/nodes/{keywords_section.js → keywords.js} +5 -5
  72. package/dist/es/schema/nodes/keywords_element.js +1 -1
  73. package/dist/es/schema/nodes/manuscript.js +3 -1
  74. package/dist/es/transformer/builders.js +6 -73
  75. package/dist/es/transformer/decode.js +147 -175
  76. package/dist/es/transformer/encode.js +70 -71
  77. package/dist/es/transformer/highlight-markers.js +44 -32
  78. package/dist/es/transformer/html.js +7 -23
  79. package/dist/es/transformer/labels.js +3 -17
  80. package/dist/es/transformer/node-names.js +1 -1
  81. package/dist/es/transformer/node-title.js +1 -1
  82. package/dist/es/transformer/node-types.js +7 -6
  83. package/dist/es/transformer/object-types.js +0 -1
  84. package/dist/es/transformer/section-category.js +29 -29
  85. package/dist/types/index.d.ts +1 -1
  86. package/dist/types/jats/importer/index.d.ts +1 -1
  87. package/dist/types/jats/importer/jats-body-transformations.d.ts +16 -19
  88. package/dist/types/jats/importer/jats-comments.d.ts +13 -9
  89. package/dist/types/jats/importer/jats-front-parser.d.ts +35 -12
  90. package/dist/types/jats/importer/jats-journal-meta-parser.d.ts +4 -4
  91. package/dist/types/jats/importer/jats-parser-utils.d.ts +1 -6
  92. package/dist/types/jats/importer/jats-reference-parser.d.ts +2 -6
  93. package/dist/types/jats/importer/jats-references.d.ts +12 -0
  94. package/dist/types/jats/importer/parse-jats-article.d.ts +5 -17
  95. package/dist/types/jats/index.d.ts +1 -1
  96. package/dist/types/lib/section-group-type.d.ts +23 -0
  97. package/dist/types/lib/utils.d.ts +1 -4
  98. package/dist/types/schema/index.d.ts +4 -5
  99. package/dist/types/schema/nodes/{meta_section.d.ts → abstracts.d.ts} +1 -9
  100. package/dist/types/schema/nodes/affiliations.d.ts +17 -0
  101. package/dist/types/schema/nodes/backmatter.d.ts +17 -0
  102. package/dist/types/schema/nodes/body.d.ts +17 -0
  103. package/dist/types/schema/nodes/citation.d.ts +3 -5
  104. package/dist/types/schema/nodes/comments.d.ts +17 -0
  105. package/dist/types/schema/nodes/contributors.d.ts +17 -0
  106. package/dist/types/schema/nodes/core_section.d.ts +17 -0
  107. package/dist/types/schema/nodes/cross_reference.d.ts +1 -1
  108. package/dist/types/schema/nodes/inline_footnote.d.ts +1 -1
  109. package/dist/types/schema/nodes/keyword.d.ts +0 -1
  110. package/dist/types/schema/nodes/{contributors_element.d.ts → keyword_group.d.ts} +3 -4
  111. package/dist/types/schema/nodes/{comment_list.d.ts → keywords.d.ts} +3 -2
  112. package/dist/types/schema/nodes/manuscript.d.ts +1 -0
  113. package/dist/types/schema/types.d.ts +1 -1
  114. package/dist/types/transformer/builders.d.ts +2 -14
  115. package/dist/types/transformer/decode.d.ts +5 -9
  116. package/dist/types/transformer/encode.d.ts +4 -4
  117. package/dist/types/transformer/highlight-markers.d.ts +7 -2
  118. package/dist/types/transformer/object-types.d.ts +1 -2
  119. package/dist/types/transformer/section-category.d.ts +4 -3
  120. package/package.json +1 -6
  121. package/dist/cjs/lib/core-section-categories.js +0 -29
  122. package/dist/cjs/schema/nodes/affiliations_section.js +0 -36
  123. package/dist/cjs/schema/nodes/contributors_element.js +0 -49
  124. package/dist/cjs/schema/nodes/contributors_section.js +0 -36
  125. package/dist/es/lib/core-section-categories.js +0 -26
  126. package/dist/es/schema/nodes/affiliations_section.js +0 -32
  127. package/dist/es/schema/nodes/contributors_element.js +0 -46
  128. package/dist/es/schema/nodes/contributors_section.js +0 -32
  129. package/dist/types/lib/core-section-categories.d.ts +0 -8
  130. package/dist/types/schema/nodes/affiliations_section.d.ts +0 -11
  131. package/dist/types/schema/nodes/contributors_section.d.ts +0 -12
  132. package/dist/types/schema/nodes/keywords_group.d.ts +0 -26
  133. package/dist/types/schema/nodes/keywords_section.d.ts +0 -26
@@ -28,12 +28,12 @@ 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 { abstractsType, backmatterType, bodyType, } from '../lib/section-group-type';
31
32
  import { schema, } from '../schema';
32
33
  import { buildTitles } from './builders';
33
34
  import { insertHighlightMarkers } from './highlight-markers';
34
- import { generateNodeID } from './id';
35
35
  import { ExtraObjectTypes, hasObjectType, isCommentAnnotation, isManuscript, } from './object-types';
36
- import { chooseSectionLableName, chooseSectionNodeType, chooseSecType, guessSectionCategory, } from './section-category';
36
+ import { chooseSectionLableName, chooseSectionNodeType, chooseSecType, getSectionGroupType, guessSectionCategory, } from './section-category';
37
37
  import { timestamp } from './timestamp';
38
38
  const warn = debug('manuscripts-transform');
39
39
  const parser = DOMParser.fromSchema(schema);
@@ -54,78 +54,79 @@ export const sortSectionsByPriority = (a, b) => a.priority === b.priority ? 0 :
54
54
  const getSections = (modelMap) => getModelsByType(modelMap, ObjectTypes.Section).sort(sortSectionsByPriority);
55
55
  const getAffiliations = (modelMap) => getModelsByType(modelMap, ObjectTypes.Affiliation);
56
56
  const getContributors = (modelMap) => getModelsByType(modelMap, ObjectTypes.Contributor);
57
- export const isManuscriptNode = (model) => model !== null;
58
- const isParagraphElement = hasObjectType(ObjectTypes.ParagraphElement);
57
+ const getKeywordElements = (modelMap) => getModelsByType(modelMap, ObjectTypes.KeywordsElement);
58
+ const getKeywordGroups = (modelMap) => getModelsByType(modelMap, ObjectTypes.KeywordGroup);
59
+ const getKeywords = (modelMap) => getModelsByType(modelMap, ObjectTypes.Keyword);
60
+ const getTitles = (modelMap) => getModelsByType(modelMap, ObjectTypes.Titles)[0];
59
61
  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
62
  const hasParentSection = (id) => (section) => section.path &&
65
63
  section.path.length > 1 &&
66
64
  section.path[section.path.length - 2] === id;
65
+ const deprecatedCategories = [
66
+ 'MPSectionCategory:contributors',
67
+ 'MPSectionCategory:affiliations',
68
+ 'MPSectionCategory:keywords',
69
+ ];
67
70
  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
- ]);
71
+ createTitleNode() {
72
+ const titles = getTitles(this.modelMap) || buildTitles();
73
+ return this.decode(titles);
78
74
  }
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
- }
75
+ createAffiliationsNode() {
76
+ const affiliations = getAffiliations(this.modelMap)
77
+ .map((a) => this.decode(a))
78
+ .filter(Boolean);
79
+ return schema.nodes.affiliations.createAndFill({}, affiliations);
86
80
  }
87
- createAffiliationSectionNode(rootSectionNodes) {
88
- const affiliationNodes = getAffiliations(this.modelMap)
89
- .map((affiliation) => this.decode(affiliation))
81
+ createContributorsNode() {
82
+ const contributors = getContributors(this.modelMap)
83
+ .map((c) => this.decode(c))
90
84
  .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
- }
85
+ return schema.nodes.contributors.createAndFill({}, contributors);
97
86
  }
98
- createContributorSectionNode(rootSectionNodes) {
99
- const contributorNodes = getContributors(this.modelMap)
100
- .map((contributor) => this.decode(contributor))
87
+ createKeywordsNode() {
88
+ const elements = getKeywordElements(this.modelMap)
89
+ .map((e) => this.decode(e))
101
90
  .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
- }
91
+ return schema.nodes.keywords.createAndFill({}, [
92
+ schema.nodes.section_title.create({}, schema.text('Keywords')),
93
+ ...elements,
94
+ ]);
108
95
  }
109
- createTitleNode() {
110
- const titles = getModelsByType(this.modelMap, ObjectTypes.Titles)[0] ||
111
- buildTitles();
112
- return this.decode(titles);
96
+ createCommentsNode() {
97
+ return schema.nodes.comments.createAndFill({}, [
98
+ ...this.comments.values(),
99
+ ]);
113
100
  }
114
- createRootSectionNodes() {
115
- let rootSections = getSections(this.modelMap).filter((section) => !section.path || section.path.length <= 1);
116
- 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
- }));
101
+ createContentSections() {
102
+ let sections = getSections(this.modelMap);
103
+ sections = this.addGeneratedLabels(sections);
104
+ const groups = {
105
+ abstracts: [],
106
+ body: [],
107
+ backmatter: [],
108
+ };
109
+ for (const section of sections) {
110
+ if (section.path.length > 1) {
111
+ continue;
112
+ }
113
+ const category = section.category;
114
+ if (category && deprecatedCategories.includes(category)) {
115
+ continue;
116
+ }
117
+ const group = category ? getSectionGroupType(category) : bodyType;
118
+ groups[group._id].push(this.decode(section));
125
119
  }
126
- return rootSectionNodes;
120
+ const abstracts = schema.nodes.abstracts.createAndFill({}, groups[abstractsType._id]);
121
+ const body = schema.nodes.body.createAndFill({}, groups[bodyType._id]);
122
+ const backmatter = schema.nodes.backmatter.createAndFill({}, groups[backmatterType._id]);
123
+ return {
124
+ abstracts,
125
+ body,
126
+ backmatter,
127
+ };
127
128
  }
128
- createCommentsNode(model) {
129
+ createCommentNodes(model) {
129
130
  const comments = [];
130
131
  for (const comment of this.getComments(model)) {
131
132
  comments.push(this.decode(comment));
@@ -137,7 +138,7 @@ export class Decoder {
137
138
  }
138
139
  extractListing(model) {
139
140
  if (model.listingID) {
140
- return this.createListing(model);
141
+ return this.createListing(model.listingID);
141
142
  }
142
143
  }
143
144
  constructor(modelMap, allowMissingElements = false) {
@@ -170,8 +171,8 @@ export class Decoder {
170
171
  },
171
172
  [ObjectTypes.BibliographyItem]: (data) => {
172
173
  const model = data;
173
- const commentNodes = this.createCommentsNode(model);
174
- commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
174
+ const comments = this.createCommentNodes(model);
175
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
175
176
  return schema.nodes.bibliography_item.create({
176
177
  id: model._id,
177
178
  type: model.type,
@@ -185,7 +186,7 @@ export class Decoder {
185
186
  page: model.page,
186
187
  title: model.title,
187
188
  literal: model.literal,
188
- comments: commentNodes.map((c) => c.attrs.id),
189
+ comments: comments.map((c) => c.attrs.id),
189
190
  });
190
191
  },
191
192
  [ExtraObjectTypes.PlaceholderElement]: (data) => {
@@ -196,14 +197,14 @@ export class Decoder {
196
197
  },
197
198
  [ObjectTypes.Figure]: (data) => {
198
199
  const model = data;
199
- const commentNodes = this.createCommentsNode(model);
200
- commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
200
+ const comments = this.createCommentNodes(model);
201
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
201
202
  return schema.nodes.figure.create({
202
203
  id: model._id,
203
204
  contentType: model.contentType,
204
205
  src: model.src,
205
206
  position: model.position,
206
- comments: commentNodes.map((c) => c.attrs.id),
207
+ comments: comments.map((c) => c.attrs.id),
207
208
  });
208
209
  },
209
210
  [ObjectTypes.FigureElement]: (data) => {
@@ -232,8 +233,8 @@ export class Decoder {
232
233
  figures.push(schema.nodes.figure.createAndFill());
233
234
  }
234
235
  const figcaption = this.getFigcaption(model);
235
- const commentNodes = this.createCommentsNode(model);
236
- commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
236
+ const comments = this.createCommentNodes(model);
237
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
237
238
  const content = [...paragraphs, ...figures, figcaption];
238
239
  const listing = this.extractListing(model);
239
240
  if (listing) {
@@ -254,7 +255,7 @@ export class Decoder {
254
255
  suppressTitle: Boolean(model.suppressTitle === undefined ? true : model.suppressTitle),
255
256
  attribution: model.attribution,
256
257
  alternatives: model.alternatives,
257
- comments: commentNodes.map((c) => c.attrs.id),
258
+ comments: comments.map((c) => c.attrs.id),
258
259
  }, content);
259
260
  },
260
261
  [ObjectTypes.Equation]: (data) => {
@@ -297,13 +298,13 @@ export class Decoder {
297
298
  if (isFootnote(model) &&
298
299
  model.kind === collateByKind &&
299
300
  model.containingObject === foonotesElementModel._id) {
300
- const commentNodes = this.createCommentsNode(model);
301
- commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
301
+ const comments = this.createCommentNodes(model);
302
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
302
303
  const footnote = this.parseContents(model.contents || '<div></div>', undefined, this.getComments(model), {
303
304
  topNode: schema.nodes.footnote.create({
304
305
  id: model._id,
305
306
  kind: model.kind,
306
- comments: commentNodes.map((c) => c.attrs.id),
307
+ comments: comments.map((c) => c.attrs.id),
307
308
  }),
308
309
  });
309
310
  footnotesOfKind.push(footnote);
@@ -317,36 +318,51 @@ export class Decoder {
317
318
  },
318
319
  [ObjectTypes.Footnote]: (data) => {
319
320
  const footnoteModel = data;
320
- const commentNodes = this.createCommentsNode(footnoteModel);
321
- commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
321
+ const comments = this.createCommentNodes(footnoteModel);
322
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
322
323
  return this.parseContents(footnoteModel.contents || '<div></div>', undefined, this.getComments(footnoteModel), {
323
324
  topNode: schema.nodes.footnote.create({
324
325
  id: footnoteModel._id,
325
326
  kind: footnoteModel.kind,
326
- comments: commentNodes.map((c) => c.attrs.id),
327
+ comments: comments.map((c) => c.attrs.id),
327
328
  }),
328
329
  });
329
330
  },
330
331
  [ObjectTypes.KeywordsElement]: (data) => {
331
332
  const model = data;
332
- const keywordGroups = this.getKeywordGroups();
333
+ const keywordGroups = getKeywordGroups(this.modelMap).map((k) => this.decode(k));
333
334
  return schema.nodes.keywords_element.create({
334
335
  id: model._id,
335
336
  paragraphStyle: model.paragraphStyle,
336
337
  }, keywordGroups);
337
338
  },
339
+ [ObjectTypes.KeywordGroup]: (data) => {
340
+ const keywordGroup = data;
341
+ const keywords = getKeywords(this.modelMap)
342
+ .filter((k) => k.containedGroup === keywordGroup._id)
343
+ .map((k) => this.decode(k));
344
+ const comments = this.createCommentNodes(keywordGroup);
345
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
346
+ return schema.nodes.keyword_group.create({
347
+ id: keywordGroup._id,
348
+ type: keywordGroup.type,
349
+ comments: comments.map((c) => c.attrs.id),
350
+ }, keywords);
351
+ },
338
352
  [ObjectTypes.Keyword]: (data) => {
339
- const model = data;
353
+ const keyword = data;
354
+ const comments = this.createCommentNodes(keyword);
355
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
340
356
  return schema.nodes.keyword.create({
341
- id: model._id,
342
- contents: model.name,
343
- comments: this.createCommentsNode(model),
344
- }, schema.text(model.name));
357
+ id: keyword._id,
358
+ contents: keyword.name,
359
+ comments: comments.map((c) => c.attrs.id),
360
+ }, schema.text(keyword.name));
345
361
  },
346
362
  [ObjectTypes.ListElement]: (data) => {
347
363
  const model = data;
348
- const commentNodes = this.createCommentsNode(model);
349
- commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
364
+ const comments = this.createCommentNodes(model);
365
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
350
366
  switch (model.elementType) {
351
367
  case 'ol':
352
368
  return this.parseContents(model.contents || '<ol></ol>', undefined, this.getComments(model), {
@@ -354,7 +370,7 @@ export class Decoder {
354
370
  id: model._id,
355
371
  listStyleType: model.listStyleType,
356
372
  paragraphStyle: model.paragraphStyle,
357
- comments: commentNodes.map((c) => c.attrs.id),
373
+ comments: comments.map((c) => c.attrs.id),
358
374
  }),
359
375
  });
360
376
  case 'ul':
@@ -370,14 +386,14 @@ export class Decoder {
370
386
  },
371
387
  [ObjectTypes.Listing]: (data) => {
372
388
  const model = data;
373
- const commentNodes = this.createCommentsNode(model);
374
- commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
389
+ const comments = this.createCommentNodes(model);
390
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
375
391
  return schema.nodes.listing.createChecked({
376
392
  id: model._id,
377
393
  contents: model.contents,
378
394
  language: model.language,
379
395
  languageKey: model.languageKey,
380
- comments: commentNodes.map((c) => c.attrs.id),
396
+ comments: comments.map((c) => c.attrs.id),
381
397
  });
382
398
  },
383
399
  [ObjectTypes.ListingElement]: (data) => {
@@ -397,13 +413,13 @@ export class Decoder {
397
413
  throw new MissingElement(model.containedObjectID);
398
414
  }
399
415
  const figcaption = this.getFigcaption(model);
400
- const commentNodes = this.createCommentsNode(model);
401
- commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
416
+ const comments = this.createCommentNodes(model);
417
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
402
418
  return schema.nodes.listing_element.createChecked({
403
419
  id: model._id,
404
420
  suppressCaption: model.suppressCaption,
405
421
  suppressTitle: Boolean(model.suppressTitle === undefined ? true : model.suppressTitle),
406
- comments: commentNodes.map((c) => c.attrs.id),
422
+ comments: comments.map((c) => c.attrs.id),
407
423
  }, [listing, figcaption]);
408
424
  },
409
425
  [ObjectTypes.MissingFigure]: (data) => {
@@ -415,14 +431,14 @@ export class Decoder {
415
431
  },
416
432
  [ObjectTypes.ParagraphElement]: (data) => {
417
433
  const model = data;
418
- const commentNodes = this.createCommentsNode(model);
419
- commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
434
+ const comments = this.createCommentNodes(model);
435
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
420
436
  return this.parseContents(model.contents || '<p></p>', undefined, this.getComments(model), {
421
437
  topNode: schema.nodes.paragraph.create({
422
438
  id: model._id,
423
439
  paragraphStyle: model.paragraphStyle,
424
440
  placeholder: model.placeholderInnerHTML,
425
- comments: commentNodes.map((c) => c.attrs.id),
441
+ comments: comments.map((c) => c.attrs.id),
426
442
  }),
427
443
  });
428
444
  },
@@ -463,9 +479,6 @@ export class Decoder {
463
479
  for (const id of model.elementIDs) {
464
480
  const element = this.getModel(id);
465
481
  if (element) {
466
- if (isKeywordsSection(model) && isParagraphElement(element)) {
467
- continue;
468
- }
469
482
  elements.push(element);
470
483
  }
471
484
  else if (this.allowMissingElements) {
@@ -484,9 +497,7 @@ export class Decoder {
484
497
  }
485
498
  }
486
499
  }
487
- const elementNodes = elements
488
- .map(this.decode)
489
- .filter(isManuscriptNode);
500
+ const elementNodes = elements.map((e) => this.decode(e));
490
501
  const sectionTitle = 'section_title';
491
502
  const sectionTitleNode = model.title
492
503
  ? this.parseContents(model.title, 'h1', this.getComments(model), {
@@ -504,26 +515,20 @@ export class Decoder {
504
515
  .map(this.creators[ObjectTypes.Section]);
505
516
  const sectionCategory = model.category || guessSectionCategory(elements);
506
517
  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
- }
518
+ const comments = this.createCommentNodes(model);
519
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
520
+ const content = (sectionLabelNode
521
+ ? [sectionLabelNode, sectionTitleNode]
522
+ : [sectionTitleNode])
523
+ .concat(elementNodes)
524
+ .concat(nestedSections);
520
525
  const sectionNode = sectionNodeType.createAndFill({
521
526
  id: model._id,
522
527
  category: sectionCategory,
523
528
  titleSuppressed: model.titleSuppressed,
524
529
  pageBreakStyle: model.pageBreakStyle,
525
530
  generatedLabel: model.generatedLabel,
526
- comments: commentNodes.map((c) => c.attrs.id),
531
+ comments: comments.map((c) => c.attrs.id),
527
532
  }, content);
528
533
  if (!sectionNode) {
529
534
  console.error(model);
@@ -533,12 +538,12 @@ export class Decoder {
533
538
  },
534
539
  [ObjectTypes.Table]: (data) => {
535
540
  const model = data;
536
- const commentNodes = this.createCommentsNode(model);
537
- commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
541
+ const comments = this.createCommentNodes(model);
542
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
538
543
  return this.parseContents(model.contents, undefined, this.getComments(model), {
539
544
  topNode: schema.nodes.table.create({
540
545
  id: model._id,
541
- comments: commentNodes.map((c) => c.attrs.id),
546
+ comments: comments.map((c) => c.attrs.id),
542
547
  }),
543
548
  });
544
549
  },
@@ -547,13 +552,13 @@ export class Decoder {
547
552
  const table = this.createTable(model);
548
553
  const tableElementFooter = this.createTableElementFooter(model);
549
554
  const figcaption = this.getFigcaption(model);
550
- const commentNodes = this.createCommentsNode(model);
551
- commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
555
+ const comments = this.createCommentNodes(model);
556
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
552
557
  const content = tableElementFooter
553
558
  ? [table, figcaption, tableElementFooter]
554
559
  : [table, figcaption];
555
560
  if (model.listingID) {
556
- const listing = this.createListing(model);
561
+ const listing = this.createListing(model.listingID);
557
562
  content.push(listing);
558
563
  }
559
564
  else {
@@ -569,7 +574,7 @@ export class Decoder {
569
574
  suppressHeader: model.suppressHeader,
570
575
  tableStyle: model.tableStyle,
571
576
  paragraphStyle: model.paragraphStyle,
572
- comments: commentNodes.map((c) => c.attrs.id),
577
+ comments: comments.map((c) => c.attrs.id),
573
578
  }, content);
574
579
  },
575
580
  [ObjectTypes.TOCElement]: (data) => {
@@ -635,13 +640,21 @@ export class Decoder {
635
640
  };
636
641
  this.getModel = (id) => this.modelMap.get(id);
637
642
  this.createArticleNode = (manuscriptID) => {
638
- const titlesNode = this.createTitleNode();
639
- const rootSectionNodes = this.createRootSectionNodes();
640
- const metaSectionNode = this.createMetaSectionNode();
643
+ const title = this.createTitleNode();
644
+ const contributors = this.createContributorsNode();
645
+ const affiliations = this.createAffiliationsNode();
646
+ const keywords = this.createKeywordsNode();
647
+ const { abstracts, body, backmatter } = this.createContentSections();
648
+ const comments = this.createCommentsNode();
641
649
  const contents = [
642
- titlesNode,
643
- ...rootSectionNodes,
644
- metaSectionNode,
650
+ title,
651
+ contributors,
652
+ affiliations,
653
+ keywords,
654
+ abstracts,
655
+ body,
656
+ backmatter,
657
+ comments,
645
658
  ];
646
659
  return schema.nodes.manuscript.create({
647
660
  id: manuscriptID || this.getManuscriptID(),
@@ -683,23 +696,6 @@ export class Decoder {
683
696
  }
684
697
  return parser.parse(template.content.firstElementChild, options);
685
698
  };
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
699
  this.getManuscriptID = () => {
704
700
  for (const item of this.modelMap.values()) {
705
701
  if (isManuscript(item)) {
@@ -767,43 +763,19 @@ export class Decoder {
767
763
  ? this.decode(tableElementFooterModel)
768
764
  : undefined;
769
765
  }
770
- createListing(model) {
771
- const listingModel = this.getModel(model.listingID);
772
- let listing;
773
- if (listingModel) {
774
- listing = this.decode(listingModel);
766
+ createListing(id) {
767
+ const listing = this.getModel(id);
768
+ if (listing) {
769
+ return this.decode(listing);
775
770
  }
776
771
  else if (this.allowMissingElements) {
777
- listing = schema.nodes.placeholder.create({
778
- id: model.listingID,
772
+ return schema.nodes.placeholder.create({
773
+ id,
779
774
  label: 'A listing',
780
775
  });
781
776
  }
782
777
  else {
783
- throw new MissingElement(model.listingID);
784
- }
785
- return listing;
786
- }
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
- }
778
+ throw new MissingElement(id);
806
779
  }
807
- return kwdGroupNodes;
808
780
  }
809
781
  }