@manuscripts/transform 1.2.4-LEAN-2066 → 1.2.5

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 (43) hide show
  1. package/dist/cjs/jats/importer/jats-body-dom-parser.js +1 -33
  2. package/dist/cjs/jats/importer/jats-body-transformations.js +53 -26
  3. package/dist/cjs/jats/importer/jats-comments.js +0 -24
  4. package/dist/cjs/jats/importer/jats-front-parser.js +25 -0
  5. package/dist/cjs/jats/importer/parse-jats-article.js +6 -3
  6. package/dist/cjs/jats/jats-exporter.js +54 -19
  7. package/dist/cjs/schema/index.js +0 -2
  8. package/dist/cjs/schema/nodes/keyword.js +2 -1
  9. package/dist/cjs/schema/nodes/keywords_element.js +1 -2
  10. package/dist/cjs/schema/nodes/keywords_section.js +1 -1
  11. package/dist/cjs/schema/nodes/section.js +1 -1
  12. package/dist/cjs/transformer/decode.js +23 -29
  13. package/dist/cjs/transformer/encode.js +13 -9
  14. package/dist/cjs/transformer/node-types.js +0 -1
  15. package/dist/cjs/transformer/object-types.js +1 -2
  16. package/dist/cjs/transformer/section-category.js +23 -1
  17. package/dist/es/jats/importer/jats-body-dom-parser.js +1 -33
  18. package/dist/es/jats/importer/jats-body-transformations.js +54 -27
  19. package/dist/es/jats/importer/jats-comments.js +1 -25
  20. package/dist/es/jats/importer/jats-front-parser.js +26 -1
  21. package/dist/es/jats/importer/parse-jats-article.js +6 -3
  22. package/dist/es/jats/jats-exporter.js +54 -19
  23. package/dist/es/schema/index.js +0 -2
  24. package/dist/es/schema/nodes/keyword.js +2 -1
  25. package/dist/es/schema/nodes/keywords_element.js +1 -2
  26. package/dist/es/schema/nodes/keywords_section.js +1 -1
  27. package/dist/es/schema/nodes/section.js +1 -1
  28. package/dist/es/transformer/decode.js +23 -29
  29. package/dist/es/transformer/encode.js +14 -10
  30. package/dist/es/transformer/node-types.js +0 -1
  31. package/dist/es/transformer/object-types.js +0 -1
  32. package/dist/es/transformer/section-category.js +19 -1
  33. package/dist/types/jats/importer/jats-body-transformations.d.ts +7 -2
  34. package/dist/types/jats/importer/jats-front-parser.d.ts +11 -6
  35. package/dist/types/jats/jats-exporter.d.ts +2 -0
  36. package/dist/types/schema/types.d.ts +1 -1
  37. package/dist/types/transformer/decode.d.ts +0 -1
  38. package/dist/types/transformer/object-types.d.ts +1 -2
  39. package/dist/types/transformer/section-category.d.ts +3 -2
  40. package/package.json +2 -2
  41. package/dist/cjs/schema/nodes/keywords_group.js +0 -48
  42. package/dist/es/schema/nodes/keywords_group.js +0 -44
  43. package/dist/types/schema/nodes/keywords_group.d.ts +0 -26
@@ -505,22 +505,6 @@ const nodes = [
505
505
  };
506
506
  },
507
507
  },
508
- {
509
- tag: 'sec[sec-type="keywords"]',
510
- node: 'keywords_section',
511
- getAttrs: (node) => {
512
- const element = node;
513
- return {
514
- id: element.getAttribute('id'),
515
- category: (0, transformer_1.chooseSectionCategory)(element),
516
- };
517
- },
518
- },
519
- {
520
- tag: 'kwd-group-list',
521
- context: 'keywords_section/',
522
- node: 'keywords_element',
523
- },
524
508
  {
525
509
  tag: 'sec',
526
510
  node: 'section',
@@ -532,22 +516,6 @@ const nodes = [
532
516
  };
533
517
  },
534
518
  },
535
- {
536
- tag: 'kwd-group',
537
- context: 'keywords_element/',
538
- node: 'keywords_group',
539
- getAttrs: (node) => {
540
- const element = node;
541
- return {
542
- type: element.getAttribute('kwd-group-type'),
543
- };
544
- },
545
- },
546
- {
547
- tag: 'kwd',
548
- context: 'keywords_group//',
549
- node: 'keyword',
550
- },
551
519
  {
552
520
  tag: 'label',
553
521
  context: 'section/',
@@ -600,7 +568,7 @@ const nodes = [
600
568
  {
601
569
  tag: 'title',
602
570
  node: 'section_title',
603
- context: 'section/|footnotes_section/|bibliography_section/|keywords_section/',
571
+ context: 'section/|footnotes_section/|bibliography_section/',
604
572
  },
605
573
  {
606
574
  tag: 'title',
@@ -19,6 +19,17 @@ exports.jatsBodyTransformations = void 0;
19
19
  const transformer_1 = require("../../transformer");
20
20
  const removeNodeFromParent = (node) => node.parentNode && node.parentNode.removeChild(node);
21
21
  const capitalizeFirstLetter = (str) => str.charAt(0).toUpperCase() + str.slice(1);
22
+ const createSectionContainer = (type, createElement) => {
23
+ const sectionContainer = createElement('sec');
24
+ const sectionCategory = (0, transformer_1.chooseSectionCategoryByType)(type);
25
+ sectionContainer.setAttribute('sec-type', sectionCategory ? (0, transformer_1.chooseSecType)(sectionCategory) : '');
26
+ const title = createElement('title');
27
+ title.textContent = sectionCategory
28
+ ? (0, transformer_1.getSectionTitles)(sectionCategory)[0]
29
+ : ' ';
30
+ sectionContainer.appendChild(title);
31
+ return sectionContainer;
32
+ };
22
33
  exports.jatsBodyTransformations = {
23
34
  ensureSection(body, createElement) {
24
35
  let section = createElement('sec');
@@ -146,34 +157,64 @@ exports.jatsBodyTransformations = {
146
157
  section.append(...floatsGroup.children);
147
158
  return section;
148
159
  },
149
- moveSectionsToBody(doc, body, references, createElement) {
160
+ moveAbstractsIntoContainer(doc, abstractsContainer, createElement) {
150
161
  const abstractNodes = doc.querySelectorAll('front > article-meta > abstract');
151
- for (const abstractNode of abstractNodes) {
162
+ abstractNodes.forEach((abstractNode) => {
152
163
  const abstract = this.createAbstract(abstractNode, createElement);
153
164
  removeNodeFromParent(abstractNode);
154
- body.insertBefore(abstract, body.firstChild);
155
- }
165
+ abstractsContainer.appendChild(abstract);
166
+ });
167
+ },
168
+ wrapBodySections(doc, bodyContainer) {
169
+ const bodySections = doc.querySelectorAll('body > sec:not([sec-type="backmatter"]), body > sec:not([sec-type])');
170
+ bodySections.forEach((section) => {
171
+ removeNodeFromParent(section);
172
+ bodyContainer.appendChild(section);
173
+ });
174
+ },
175
+ moveBackSectionsIntoContainer(doc, backmatterContainer) {
156
176
  for (const section of doc.querySelectorAll('back > sec')) {
157
177
  removeNodeFromParent(section);
158
- body.appendChild(section);
178
+ backmatterContainer.appendChild(section);
159
179
  }
180
+ },
181
+ moveAcknowledgmentsIntoContainer(doc, backmatterContainer, createElement) {
160
182
  const ackNode = doc.querySelector('back > ack');
161
183
  if (ackNode) {
162
184
  const acknowledgements = this.createAcknowledgments(ackNode, createElement);
163
185
  removeNodeFromParent(ackNode);
164
- body.appendChild(acknowledgements);
186
+ backmatterContainer.appendChild(acknowledgements);
165
187
  }
188
+ },
189
+ moveAppendicesIntoContainer(doc, backmatterContainer, createElement) {
166
190
  const appGroup = doc.querySelectorAll('back > app-group > app');
167
191
  for (const app of appGroup) {
168
192
  const appendix = this.createAppendixSection(app, createElement);
169
193
  removeNodeFromParent(app);
170
- body.appendChild(appendix);
194
+ backmatterContainer.appendChild(appendix);
171
195
  }
196
+ },
197
+ moveBibliographyIntoContainer(doc, backmatterContainer, references, createElement) {
172
198
  if (references) {
173
- body.appendChild(this.createBibliography(doc, references, createElement));
199
+ backmatterContainer.appendChild(this.createBibliography(doc, references, createElement));
174
200
  }
175
201
  },
176
- mapFootnotesToSections(doc, body, createElement) {
202
+ moveSectionsToBody(doc, body, references, createElement) {
203
+ const bodyContainer = createSectionContainer('body', createElement);
204
+ const abstractsContainer = createSectionContainer('abstracts', createElement);
205
+ const backmatterContainer = createSectionContainer('backmatter', createElement);
206
+ this.mapFootnotesToSections(doc, backmatterContainer, createElement);
207
+ this.wrapBodySections(doc, bodyContainer);
208
+ this.moveAbstractsIntoContainer(doc, abstractsContainer, createElement);
209
+ this.moveBackSectionsIntoContainer(doc, backmatterContainer);
210
+ this.moveAcknowledgmentsIntoContainer(doc, backmatterContainer, createElement);
211
+ this.moveAppendicesIntoContainer(doc, backmatterContainer, createElement);
212
+ this.moveBibliographyIntoContainer(doc, backmatterContainer, references, createElement);
213
+ body.insertBefore(abstractsContainer, body.firstChild);
214
+ body.insertBefore(bodyContainer, abstractsContainer.nextSibling);
215
+ body.append(backmatterContainer);
216
+ },
217
+ mapFootnotesToSections(doc, backmatterContainer, createElement) {
177
218
  const footnoteGroups = [...doc.querySelectorAll('fn[fn-type]')];
178
219
  for (const footnote of footnoteGroups) {
179
220
  const type = footnote.getAttribute('fn-type') || '';
@@ -190,7 +231,7 @@ exports.jatsBodyTransformations = {
190
231
  section.append(...footnote.children);
191
232
  removeNodeFromParent(footnote);
192
233
  section.setAttribute('sec-type', (0, transformer_1.chooseSecType)(category));
193
- body.append(section);
234
+ backmatterContainer.append(section);
194
235
  }
195
236
  }
196
237
  const footnotes = [...doc.querySelectorAll('fn')];
@@ -205,7 +246,7 @@ exports.jatsBodyTransformations = {
205
246
  }
206
247
  if (!footnotesSection && containingGroup.innerHTML) {
207
248
  const section = this.createFootnotes([containingGroup], createElement);
208
- body.append(section);
249
+ backmatterContainer.append(section);
209
250
  }
210
251
  let regularFootnoteGroups = [
211
252
  ...doc.querySelectorAll('back > fn-group:not([fn-type])'),
@@ -218,7 +259,7 @@ exports.jatsBodyTransformations = {
218
259
  if (regularFootnoteGroups.length > 0) {
219
260
  regularFootnoteGroups.map((g) => removeNodeFromParent(g));
220
261
  const footnotes = this.createFootnotes(regularFootnoteGroups, createElement);
221
- body.appendChild(footnotes);
262
+ backmatterContainer.appendChild(footnotes);
222
263
  }
223
264
  },
224
265
  moveCaptionsToEnd(body) {
@@ -266,18 +307,4 @@ exports.jatsBodyTransformations = {
266
307
  paragraph === null || paragraph === void 0 ? void 0 : paragraph.replaceWith(parent);
267
308
  });
268
309
  },
269
- moveKeywordsToBody(document, body, createElement) {
270
- const keywordGroups = [...document.querySelectorAll('kwd-group')];
271
- if (keywordGroups.length > 0) {
272
- const section = createElement('sec');
273
- section.setAttribute('sec-type', 'keywords');
274
- const title = createElement('title');
275
- title.textContent = 'Keywords';
276
- section.append(title);
277
- const kwdGroupsEl = createElement('kwd-group-list');
278
- kwdGroupsEl.append(keywordGroups[0]);
279
- section.append(kwdGroupsEl);
280
- body.prepend(section);
281
- }
282
- },
283
310
  };
@@ -63,21 +63,6 @@ const insertToken = (doc, processingInstructionNode, authorQueriesMap) => {
63
63
  return parentElement.insertBefore(tokenNode, processingInstructionNode);
64
64
  }
65
65
  };
66
- const extractCommentsFromKeywords = (tokens, model, authorQueriesMap) => {
67
- var _a;
68
- const commentAnnotations = [];
69
- const name = model.name;
70
- const filteredTokens = filterAndSortTokens(tokens, name);
71
- let content = name;
72
- for (const token of filteredTokens) {
73
- content = name.replace(token, '');
74
- const query = authorQueriesMap.get(token);
75
- const commentAnnotation = (0, transformer_1.buildComment)((_a = model.containedGroup) !== null && _a !== void 0 ? _a : (0, uuid_1.v4)(), `${query}`, undefined, [(0, transformer_1.buildContribution)(DEFAULT_PROFILE_ID)], DEFAULT_ANNOTATION_COLOR);
76
- model['name'] = content;
77
- commentAnnotations.push(commentAnnotation);
78
- }
79
- return commentAnnotations;
80
- };
81
66
  const createComments = (authorQueriesMap, manuscriptModels) => {
82
67
  const tokens = [...authorQueriesMap.keys()];
83
68
  const commentAnnotations = [];
@@ -86,19 +71,10 @@ const createComments = (authorQueriesMap, manuscriptModels) => {
86
71
  const comments = addCommentsFromMarkedProcessingInstructions(tokens, model, authorQueriesMap);
87
72
  commentAnnotations.push(...comments);
88
73
  }
89
- else if ((0, transformer_1.isKeyword)(model)) {
90
- const comments = extractCommentsFromKeywords(tokens, model, authorQueriesMap);
91
- commentAnnotations.push(...comments);
92
- }
93
74
  }
94
75
  return commentAnnotations;
95
76
  };
96
77
  exports.createComments = createComments;
97
- function filterAndSortTokens(tokens, content) {
98
- return tokens
99
- .filter((token) => content.indexOf(token) >= 0)
100
- .sort((a, b) => content.indexOf(a) - content.indexOf(b));
101
- }
102
78
  const addCommentsFromMarkedProcessingInstructions = (tokens, model, authorQueriesMap) => {
103
79
  const commentAnnotations = [];
104
80
  for (const field of ['contents', 'caption', 'title']) {
@@ -68,6 +68,31 @@ exports.jatsFrontParser = {
68
68
  }
69
69
  return (0, jats_journal_meta_parser_1.parseJournalMeta)(journalMeta);
70
70
  },
71
+ parseKeywords(keywordGroupNodes) {
72
+ var _a, _b;
73
+ if (!keywordGroupNodes) {
74
+ return { groups: [], keywords: [] };
75
+ }
76
+ let keywordPriority = 1;
77
+ const keywordGroups = { groups: [], keywords: [] };
78
+ for (const keywordGroupNode of keywordGroupNodes) {
79
+ const manuscriptKeywordGroup = (0, builders_1.buildKeywordGroup)({
80
+ title: ((_a = keywordGroupNode.querySelector('title')) === null || _a === void 0 ? void 0 : _a.textContent) || undefined,
81
+ label: ((_b = keywordGroupNode.querySelector('label')) === null || _b === void 0 ? void 0 : _b.textContent) || undefined,
82
+ type: keywordGroupNode.getAttribute('kwd-group-type') || undefined,
83
+ });
84
+ keywordGroups.groups.push(manuscriptKeywordGroup);
85
+ for (const keywordNode of keywordGroupNode.querySelectorAll('kwd')) {
86
+ if (keywordNode.textContent) {
87
+ const keyword = (0, builders_1.buildKeyword)(keywordNode.textContent);
88
+ keyword.priority = keywordPriority++;
89
+ keyword.containedGroup = manuscriptKeywordGroup._id;
90
+ keywordGroups.keywords.push(keyword);
91
+ }
92
+ }
93
+ }
94
+ return keywordGroups;
95
+ },
71
96
  parseDates(historyNode) {
72
97
  if (!historyNode) {
73
98
  return undefined;
@@ -54,6 +54,9 @@ const parseJATSFront = async (front) => {
54
54
  const manuscriptMeta = Object.assign({ title: title ? inlineContentsFromJATSTitle(title) : undefined, subtitle: subtitle ? inlineContentsFromJATSTitle(subtitle) : undefined, runningTitle: runningTitle
55
55
  ? inlineContentsFromJATSTitle(runningTitle)
56
56
  : undefined }, jats_front_parser_1.jatsFrontParser.parseCounts(articleMeta === null || articleMeta === void 0 ? void 0 : articleMeta.querySelector('counts')));
57
+ const keywordGroupNodes = articleMeta === null || articleMeta === void 0 ? void 0 : articleMeta.querySelectorAll('kwd-group');
58
+ const { keywords, groups: keywordGroups } = jats_front_parser_1.jatsFrontParser.parseKeywords(keywordGroupNodes);
59
+ const manuscript_keywordIDs = keywords.length > 0 ? keywords.map((k) => k._id) : undefined;
57
60
  const { affiliations, affiliationIDs } = jats_front_parser_1.jatsFrontParser.parseAffiliationNodes([
58
61
  ...front.querySelectorAll('article-meta > contrib-group > aff'),
59
62
  ]);
@@ -70,12 +73,14 @@ const parseJATSFront = async (front) => {
70
73
  const supplements = jats_front_parser_1.jatsFrontParser.parseSupplements([
71
74
  ...front.querySelectorAll('article-meta > supplementary-material'),
72
75
  ]);
73
- const manuscript = Object.assign(Object.assign(Object.assign({}, (0, builders_1.buildManuscript)()), manuscriptMeta), history);
76
+ const manuscript = Object.assign(Object.assign(Object.assign(Object.assign({}, (0, builders_1.buildManuscript)()), manuscriptMeta), { keywordIDs: manuscript_keywordIDs }), history);
74
77
  return {
75
78
  models: generateModelIDs([
76
79
  manuscript,
80
+ ...keywords,
77
81
  ...affiliations,
78
82
  ...authors,
83
+ ...keywordGroups,
79
84
  ...footnotes,
80
85
  ...correspondingList,
81
86
  journal,
@@ -111,12 +116,10 @@ const parseJATSBody = (document, body, bibliographyItems, refModels, referenceId
111
116
  const orderedFootnotesIDs = (0, footnotes_order_1.createOrderedFootnotesIDs)(document);
112
117
  jats_body_transformations_1.jatsBodyTransformations.moveFloatsGroupToBody(document, body, createElement);
113
118
  jats_body_transformations_1.jatsBodyTransformations.ensureSection(body, createElement);
114
- jats_body_transformations_1.jatsBodyTransformations.mapFootnotesToSections(document, body, createElement);
115
119
  jats_body_transformations_1.jatsBodyTransformations.moveSectionsToBody(document, body, bibliographyItems, createElement);
116
120
  jats_body_transformations_1.jatsBodyTransformations.moveCaptionsToEnd(body);
117
121
  jats_body_transformations_1.jatsBodyTransformations.moveTableFooterToEnd(body);
118
122
  jats_body_transformations_1.jatsBodyTransformations.moveBlockNodesFromParagraph(document, body, createElement);
119
- jats_body_transformations_1.jatsBodyTransformations.moveKeywordsToBody(document, body, createElement);
120
123
  const node = jats_body_dom_parser_1.jatsBodyDOMParser.parse(body);
121
124
  if (!node.firstChild) {
122
125
  throw new Error('No content was parsed from the JATS article body');
@@ -136,8 +136,10 @@ class JATSExporter {
136
136
  article.appendChild(body);
137
137
  const back = this.buildBack(body);
138
138
  article.appendChild(back);
139
+ this.unwrapBody(body);
139
140
  this.moveAbstracts(front, body);
140
141
  this.moveFloatsGroup(body, article);
142
+ this.removeBackContainer(body);
141
143
  }
142
144
  await this.rewriteIDs(idGenerator);
143
145
  if (mediaPathGenerator) {
@@ -398,7 +400,9 @@ class JATSExporter {
398
400
  if (history.childElementCount) {
399
401
  articleMeta.appendChild(history);
400
402
  }
401
- this.buildKeywords(articleMeta);
403
+ if (manuscript.keywordIDs) {
404
+ this.buildKeywords(articleMeta, manuscript.keywordIDs);
405
+ }
402
406
  let countingElements = [];
403
407
  if (manuscript.genericCounts) {
404
408
  const elements = manuscript.genericCounts.map((el) => {
@@ -622,7 +626,6 @@ class JATSExporter {
622
626
  bibliography_element: () => '',
623
627
  bibliography_item: () => '',
624
628
  comment_list: () => '',
625
- keywords_group: () => '',
626
629
  bibliography_section: (node) => [
627
630
  'ref-list',
628
631
  { id: normalizeID(node.attrs.id) },
@@ -1391,21 +1394,49 @@ class JATSExporter {
1391
1394
  table.insertBefore(tfoot, tbody);
1392
1395
  }
1393
1396
  };
1394
- this.moveAbstracts = (front, body) => {
1395
- const sections = body.querySelectorAll(':scope > sec');
1396
- const abstractSections = Array.from(sections).filter((section) => {
1397
- const sectionType = section.getAttribute('sec-type');
1398
- if (sectionType === 'abstract' ||
1399
- sectionType === 'abstract-teaser' ||
1400
- sectionType === 'abstract-graphical') {
1401
- return true;
1402
- }
1403
- const sectionTitle = section.querySelector(':scope > title');
1404
- if (!sectionTitle) {
1405
- return false;
1406
- }
1407
- return sectionTitle.textContent === 'Abstract';
1397
+ this.unwrapBody = (body) => {
1398
+ const container = body.querySelector(':scope > sec[sec-type="body"]');
1399
+ if (!container) {
1400
+ return;
1401
+ }
1402
+ const sections = container.querySelectorAll(':scope > sec');
1403
+ sections.forEach((section) => {
1404
+ body.appendChild(section.cloneNode(true));
1408
1405
  });
1406
+ body.removeChild(container);
1407
+ };
1408
+ this.removeBackContainer = (body) => {
1409
+ const container = body.querySelector(':scope > sec[sec-type="backmatter"]');
1410
+ if (!container) {
1411
+ return;
1412
+ }
1413
+ const isContainerEmpty = container.children.length === 0;
1414
+ if (!isContainerEmpty) {
1415
+ warn('Backmatter section is not empty.');
1416
+ }
1417
+ body.removeChild(container);
1418
+ };
1419
+ this.moveAbstracts = (front, body) => {
1420
+ const container = body.querySelector(':scope > sec[sec-type="abstracts"]');
1421
+ let abstractSections;
1422
+ if (container) {
1423
+ abstractSections = Array.from(container.querySelectorAll(':scope > sec'));
1424
+ }
1425
+ else {
1426
+ abstractSections = Array.from(body.querySelectorAll(':scope > sec')).filter((section) => {
1427
+ const sectionType = section.getAttribute('sec-type');
1428
+ if (sectionType === 'abstract' ||
1429
+ sectionType === 'abstract-teaser' ||
1430
+ sectionType === 'abstract-graphical') {
1431
+ return true;
1432
+ }
1433
+ const sectionTitle = section.querySelector(':scope > title');
1434
+ if (!sectionTitle) {
1435
+ return false;
1436
+ }
1437
+ return sectionTitle.textContent === 'Abstract';
1438
+ });
1439
+ }
1409
1440
  if (abstractSections.length) {
1410
1441
  for (const abstractSection of abstractSections) {
1411
1442
  const abstractNode = this.document.createElement('abstract');
@@ -1426,6 +1457,9 @@ class JATSExporter {
1426
1457
  }
1427
1458
  }
1428
1459
  }
1460
+ if (container) {
1461
+ body.removeChild(container);
1462
+ }
1429
1463
  };
1430
1464
  this.moveSectionsToBack = (back, body) => {
1431
1465
  const availabilitySection = body.querySelector('sec[sec-type="availability"]');
@@ -1528,8 +1562,10 @@ class JATSExporter {
1528
1562
  return name;
1529
1563
  };
1530
1564
  }
1531
- buildKeywords(articleMeta) {
1532
- const keywords = [...this.modelMap.values()].filter((model) => model.objectType === json_schema_1.ObjectTypes.Keyword);
1565
+ buildKeywords(articleMeta, keywordIDs) {
1566
+ const keywords = keywordIDs
1567
+ .map((id) => this.modelMap.get(id))
1568
+ .filter((model) => model && model.name);
1533
1569
  const keywordGroups = new Map();
1534
1570
  keywords.forEach((keyword) => {
1535
1571
  const containedGroup = keyword.containedGroup || '';
@@ -1563,7 +1599,6 @@ class JATSExporter {
1563
1599
  kwd.textContent = keyword.name;
1564
1600
  kwdGroup.appendChild(kwd);
1565
1601
  }
1566
- articleMeta.appendChild(kwdGroup);
1567
1602
  }
1568
1603
  }
1569
1604
  }
@@ -59,7 +59,6 @@ const inline_equation_1 = require("./nodes/inline_equation");
59
59
  const inline_footnote_1 = require("./nodes/inline_footnote");
60
60
  const keyword_1 = require("./nodes/keyword");
61
61
  const keywords_element_1 = require("./nodes/keywords_element");
62
- const keywords_group_1 = require("./nodes/keywords_group");
63
62
  const keywords_section_1 = require("./nodes/keywords_section");
64
63
  const link_1 = require("./nodes/link");
65
64
  const list_1 = require("./nodes/list");
@@ -174,7 +173,6 @@ exports.schema = new prosemirror_model_1.Schema({
174
173
  keyword: keyword_1.keyword,
175
174
  keywords_element: keywords_element_1.keywordsElement,
176
175
  keywords_section: keywords_section_1.keywordsSection,
177
- keywords_group: keywords_group_1.keywordsGroup,
178
176
  link: link_1.link,
179
177
  list_item: list_1.listItem,
180
178
  listing: listing_1.listing,
@@ -25,7 +25,8 @@ exports.keyword = {
25
25
  dataTracked: { default: null },
26
26
  comments: { default: null },
27
27
  },
28
- group: 'block',
28
+ inline: true,
29
+ group: 'inline',
29
30
  selectable: false,
30
31
  parseDOM: [
31
32
  {
@@ -18,12 +18,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.keywordsElement = void 0;
19
19
  exports.keywordsElement = {
20
20
  atom: true,
21
- content: 'keywords_group*',
21
+ content: 'keyword*',
22
22
  attrs: {
23
23
  id: { default: '' },
24
24
  contents: { default: '' },
25
25
  paragraphStyle: { default: '' },
26
- type: { default: '' },
27
26
  dataTracked: { default: null },
28
27
  },
29
28
  group: 'block element',
@@ -17,7 +17,7 @@
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.isKeywordsSectionNode = exports.keywordsSection = void 0;
19
19
  exports.keywordsSection = {
20
- content: 'section_title (keywords_element | placeholder_element)',
20
+ content: 'section_title_plain (keywords_element | placeholder_element)',
21
21
  attrs: {
22
22
  id: { default: '' },
23
23
  dataTracked: { default: null },
@@ -35,7 +35,7 @@ const choosePageBreakStyle = (element) => {
35
35
  return exports.PAGE_BREAK_NONE;
36
36
  };
37
37
  exports.section = {
38
- content: 'section_label? section_title (paragraph | element)* section*',
38
+ content: 'section_label? section_title (paragraph | element)* sections*',
39
39
  attrs: {
40
40
  id: { default: '' },
41
41
  category: { default: '' },
@@ -275,11 +275,11 @@ class Decoder {
275
275
  },
276
276
  [json_schema_1.ObjectTypes.KeywordsElement]: (data) => {
277
277
  const model = data;
278
- const keywordGroups = this.getKeywordGroups();
278
+ const keywords = this.getKeywords();
279
279
  return schema_1.schema.nodes.keywords_element.create({
280
280
  id: model._id,
281
281
  paragraphStyle: model.paragraphStyle,
282
- }, keywordGroups);
282
+ }, keywords);
283
283
  },
284
284
  [json_schema_1.ObjectTypes.Keyword]: (data) => {
285
285
  const model = data;
@@ -426,7 +426,9 @@ class Decoder {
426
426
  const elementNodes = elements
427
427
  .map(this.decode)
428
428
  .filter(exports.isManuscriptNode);
429
- const sectionTitle = 'section_title';
429
+ const sectionTitle = isKeywordsSection
430
+ ? 'section_title_plain'
431
+ : 'section_title';
430
432
  const sectionTitleNode = model.title
431
433
  ? this.parseContents(model.title, 'h1', this.getComments(model), {
432
434
  topNode: schema_1.schema.nodes[sectionTitle].create(),
@@ -570,6 +572,19 @@ class Decoder {
570
572
  id: (0, id_1.generateNodeID)(schema_1.schema.nodes.section),
571
573
  }));
572
574
  }
575
+ const keywordsSection = getSections(this.modelMap).filter((section) => section.category === 'MPSectionCategory:keywords');
576
+ const keywords = this.getKeywords();
577
+ if (keywordsSection.length === 0 && keywords.length > 0) {
578
+ const keywordsSection = schema_1.schema.nodes.keywords_section.createAndFill({
579
+ id: (0, id_1.generateNodeID)(schema_1.schema.nodes.keywords_section),
580
+ }, [
581
+ schema_1.schema.nodes.section_title_plain.create({}, schema_1.schema.text('Keywords')),
582
+ schema_1.schema.nodes.keywords_element.create({
583
+ id: (0, id_1.generateNodeID)(schema_1.schema.nodes.keywords_element),
584
+ }, keywords),
585
+ ]);
586
+ rootSectionNodes.unshift(keywordsSection);
587
+ }
573
588
  const contents = rootSectionNodes;
574
589
  if (this.comments.size) {
575
590
  const comments = schema_1.schema.nodes.comment_list.createAndFill({
@@ -617,16 +632,17 @@ class Decoder {
617
632
  }
618
633
  return parser.parse(template.content.firstElementChild, options);
619
634
  };
620
- this.getKeywords = (id) => {
635
+ this.getKeywords = () => {
621
636
  const keywordsOfKind = [];
622
- const keywordsByGroup = [...this.modelMap.values()].filter((m) => m.objectType === json_schema_1.ObjectTypes.Keyword &&
623
- m.containedGroup === id);
624
- for (const model of keywordsByGroup) {
637
+ for (const model of this.modelMap.values()) {
638
+ const commentNodes = this.createCommentsNode(model);
639
+ commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
625
640
  if (isKeyword(model)) {
626
641
  const keyword = this.parseContents(model.name || '', 'div', this.getComments(model), {
627
642
  topNode: schema_1.schema.nodes.keyword.create({
628
643
  id: model._id,
629
644
  contents: model.name,
645
+ comments: commentNodes.map((c) => c.attrs.id),
630
646
  }),
631
647
  });
632
648
  keywordsOfKind.push(keyword);
@@ -673,27 +689,5 @@ class Decoder {
673
689
  this.modelMap = modelMap;
674
690
  this.allowMissingElements = allowMissingElements;
675
691
  }
676
- getKeywordGroups() {
677
- const kwdGroupNodes = [];
678
- const kwdGroupsModels = [
679
- ...this.modelMap.values(),
680
- ].filter((model) => model.objectType === json_schema_1.ObjectTypes.KeywordGroup);
681
- if (kwdGroupsModels.length > 0) {
682
- for (const kwdGroupModel of kwdGroupsModels) {
683
- const keywords = this.getKeywords(kwdGroupModel._id);
684
- const commentNodes = this.createCommentsNode(kwdGroupModel);
685
- commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
686
- const contents = [];
687
- contents.push(...keywords);
688
- const kwdGroupNode = schema_1.schema.nodes.keywords_group.create({
689
- id: kwdGroupModel._id,
690
- type: kwdGroupModel.type,
691
- comments: commentNodes.map((c) => c.attrs.id),
692
- }, contents);
693
- kwdGroupNodes.push(kwdGroupNode);
694
- }
695
- }
696
- return kwdGroupNodes;
697
- }
698
692
  }
699
693
  exports.Decoder = Decoder;
@@ -162,6 +162,15 @@ const childElements = (node) => {
162
162
  });
163
163
  return nodes;
164
164
  };
165
+ const sectionChildElementIds = (node) => {
166
+ const nodes = [];
167
+ node.forEach((childNode) => {
168
+ if (!(0, schema_1.hasGroup)(childNode.type, 'sections')) {
169
+ nodes.push(childNode);
170
+ }
171
+ });
172
+ return nodes.map((childNode) => childNode.attrs.id).filter((id) => id);
173
+ };
165
174
  const attributeOfNodeType = (node, type, attribute) => {
166
175
  for (const child of (0, utils_1.iterateChildren)(node)) {
167
176
  if (child.type.name === type) {
@@ -401,21 +410,18 @@ const encoders = {
401
410
  SVGGlyphs: svgDefs(node.attrs.SVGRepresentation),
402
411
  }),
403
412
  keyword: (node, parent) => ({
404
- containedGroup: parent.attrs.id,
413
+ containerID: parent.attrs.id,
405
414
  name: keywordContents(node),
406
415
  }),
407
416
  keywords_element: (node) => ({
408
- contents: '<div></div>',
417
+ contents: elementContents(node),
409
418
  elementType: 'div',
410
419
  paragraphStyle: node.attrs.paragraphStyle || undefined,
411
420
  }),
412
- keywords_group: (node) => ({
413
- type: node.attrs.type,
414
- }),
415
421
  keywords_section: (node, parent, path, priority) => ({
416
422
  category: (0, section_category_1.buildSectionCategory)(node),
417
423
  priority: priority.value++,
418
- title: inlineContentsOfNodeType(node, node.type.schema.nodes.section_title),
424
+ title: inlineContentsOfNodeType(node, node.type.schema.nodes.section_title_plain),
419
425
  path: path.concat([node.attrs.id]),
420
426
  elementIDs: childElements(node)
421
427
  .map((childNode) => childNode.attrs.id)
@@ -452,9 +458,7 @@ const encoders = {
452
458
  label: inlineContentsOfNodeType(node, node.type.schema.nodes.section_label) ||
453
459
  undefined,
454
460
  path: path.concat([node.attrs.id]),
455
- elementIDs: childElements(node)
456
- .map((childNode) => childNode.attrs.id)
457
- .filter((id) => id),
461
+ elementIDs: sectionChildElementIds(node),
458
462
  titleSuppressed: node.attrs.titleSuppressed || undefined,
459
463
  generatedLabel: node.attrs.generatedLabel || undefined,
460
464
  pageBreakStyle: node.attrs.pageBreakStyle || undefined,
@@ -41,7 +41,6 @@ exports.nodeTypesMap = new Map([
41
41
  [schema_1.schema.nodes.keyword, json_schema_1.ObjectTypes.Keyword],
42
42
  [schema_1.schema.nodes.keywords_element, json_schema_1.ObjectTypes.KeywordsElement],
43
43
  [schema_1.schema.nodes.keywords_section, json_schema_1.ObjectTypes.Section],
44
- [schema_1.schema.nodes.keywords_group, json_schema_1.ObjectTypes.KeywordGroup],
45
44
  [schema_1.schema.nodes.listing, json_schema_1.ObjectTypes.Listing],
46
45
  [schema_1.schema.nodes.listing_element, json_schema_1.ObjectTypes.ListingElement],
47
46
  [schema_1.schema.nodes.manuscript, json_schema_1.ObjectTypes.Manuscript],
@@ -15,7 +15,7 @@
15
15
  * limitations under the License.
16
16
  */
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.isKeyword = exports.isCommentAnnotation = exports.isUserProfile = exports.isTable = exports.isManuscript = exports.isFigure = exports.hasObjectType = exports.isManuscriptModel = exports.manuscriptObjects = exports.elementObjects = exports.ExtraObjectTypes = void 0;
18
+ exports.isCommentAnnotation = exports.isUserProfile = exports.isTable = exports.isManuscript = exports.isFigure = exports.hasObjectType = exports.isManuscriptModel = exports.manuscriptObjects = exports.elementObjects = exports.ExtraObjectTypes = void 0;
19
19
  const json_schema_1 = require("@manuscripts/json-schema");
20
20
  var ExtraObjectTypes;
21
21
  (function (ExtraObjectTypes) {
@@ -55,4 +55,3 @@ exports.isManuscript = (0, exports.hasObjectType)(json_schema_1.ObjectTypes.Manu
55
55
  exports.isTable = (0, exports.hasObjectType)(json_schema_1.ObjectTypes.Table);
56
56
  exports.isUserProfile = (0, exports.hasObjectType)(json_schema_1.ObjectTypes.UserProfile);
57
57
  exports.isCommentAnnotation = (0, exports.hasObjectType)(json_schema_1.ObjectTypes.CommentAnnotation);
58
- exports.isKeyword = (0, exports.hasObjectType)(json_schema_1.ObjectTypes.Keyword);