@manuscripts/transform 1.5.6 → 1.5.7-LEAN-3030-1

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 (111) 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 +32 -52
  14. package/dist/cjs/lib/section-group-type.js +30 -0
  15. package/dist/cjs/lib/utils.js +10 -1
  16. package/dist/cjs/schema/index.js +15 -11
  17. package/dist/cjs/schema/nodes/{affiliations_section.js → affiliations.js} +9 -8
  18. package/dist/cjs/schema/nodes/citation.js +10 -15
  19. package/dist/cjs/schema/nodes/{contributors_section.js → contributors.js} +8 -7
  20. package/dist/cjs/schema/nodes/core_section.js +27 -0
  21. package/dist/cjs/schema/nodes/cross_reference.js +4 -3
  22. package/dist/cjs/schema/nodes/graphical_abstract_section.js +1 -0
  23. package/dist/cjs/schema/nodes/inline_footnote.js +6 -5
  24. package/dist/cjs/schema/nodes/keyword.js +0 -1
  25. package/dist/cjs/schema/nodes/{keywords_group.js → keyword_group.js} +6 -6
  26. package/dist/cjs/schema/nodes/{keywords_section.js → keywords.js} +7 -7
  27. package/dist/cjs/schema/nodes/keywords_element.js +1 -1
  28. package/dist/cjs/schema/nodes/manuscript.js +1 -1
  29. package/dist/cjs/transformer/builders.js +9 -86
  30. package/dist/cjs/transformer/decode.js +110 -113
  31. package/dist/cjs/transformer/encode.js +46 -29
  32. package/dist/cjs/transformer/highlight-markers.js +4 -4
  33. package/dist/cjs/transformer/html.js +4 -19
  34. package/dist/cjs/transformer/node-names.js +1 -1
  35. package/dist/cjs/transformer/node-title.js +1 -1
  36. package/dist/cjs/transformer/node-types.js +7 -5
  37. package/dist/cjs/transformer/object-types.js +1 -2
  38. package/dist/cjs/transformer/section-category.js +35 -17
  39. package/dist/es/index.js +1 -1
  40. package/dist/es/jats/importer/index.js +1 -1
  41. package/dist/es/jats/importer/jats-body-dom-parser.js +23 -227
  42. package/dist/es/jats/importer/jats-body-transformations.js +111 -202
  43. package/dist/es/jats/importer/jats-comments.js +97 -96
  44. package/dist/es/jats/importer/jats-front-parser.js +88 -82
  45. package/dist/es/jats/importer/jats-journal-meta-parser.js +51 -39
  46. package/dist/es/jats/importer/jats-parser-utils.js +16 -54
  47. package/dist/es/jats/importer/jats-reference-parser.js +27 -82
  48. package/dist/es/jats/importer/jats-references.js +30 -0
  49. package/dist/es/jats/importer/parse-jats-article.js +70 -174
  50. package/dist/es/jats/index.js +1 -1
  51. package/dist/es/jats/jats-exporter.js +32 -52
  52. package/dist/es/lib/section-group-type.js +27 -0
  53. package/dist/es/lib/utils.js +8 -0
  54. package/dist/es/schema/index.js +15 -11
  55. package/dist/es/schema/nodes/{affiliations_section.js → affiliations.js} +7 -6
  56. package/dist/es/schema/nodes/citation.js +10 -15
  57. package/dist/es/schema/nodes/{contributors_section.js → contributors.js} +6 -5
  58. package/dist/es/schema/nodes/core_section.js +24 -0
  59. package/dist/es/schema/nodes/cross_reference.js +4 -3
  60. package/dist/es/schema/nodes/graphical_abstract_section.js +1 -0
  61. package/dist/es/schema/nodes/inline_footnote.js +6 -5
  62. package/dist/es/schema/nodes/keyword.js +0 -1
  63. package/dist/es/schema/nodes/{keywords_group.js → keyword_group.js} +4 -4
  64. package/dist/es/schema/nodes/{keywords_section.js → keywords.js} +5 -5
  65. package/dist/es/schema/nodes/keywords_element.js +1 -1
  66. package/dist/es/schema/nodes/manuscript.js +1 -1
  67. package/dist/es/transformer/builders.js +6 -73
  68. package/dist/es/transformer/decode.js +111 -114
  69. package/dist/es/transformer/encode.js +47 -30
  70. package/dist/es/transformer/highlight-markers.js +1 -1
  71. package/dist/es/transformer/html.js +4 -19
  72. package/dist/es/transformer/node-names.js +1 -1
  73. package/dist/es/transformer/node-title.js +1 -1
  74. package/dist/es/transformer/node-types.js +7 -5
  75. package/dist/es/transformer/object-types.js +0 -1
  76. package/dist/es/transformer/section-category.js +33 -15
  77. package/dist/types/index.d.ts +1 -1
  78. package/dist/types/jats/importer/index.d.ts +1 -1
  79. package/dist/types/jats/importer/jats-body-transformations.d.ts +16 -19
  80. package/dist/types/jats/importer/jats-comments.d.ts +13 -9
  81. package/dist/types/jats/importer/jats-front-parser.d.ts +35 -12
  82. package/dist/types/jats/importer/jats-journal-meta-parser.d.ts +4 -4
  83. package/dist/types/jats/importer/jats-parser-utils.d.ts +1 -6
  84. package/dist/types/jats/importer/jats-reference-parser.d.ts +2 -6
  85. package/dist/types/jats/importer/jats-references.d.ts +12 -0
  86. package/dist/types/jats/importer/parse-jats-article.d.ts +5 -17
  87. package/dist/types/jats/index.d.ts +1 -1
  88. package/dist/types/lib/section-group-type.d.ts +31 -0
  89. package/dist/types/lib/utils.d.ts +2 -1
  90. package/dist/types/schema/index.d.ts +3 -3
  91. package/dist/types/schema/nodes/affiliations.d.ts +11 -0
  92. package/dist/types/schema/nodes/citation.d.ts +3 -5
  93. package/dist/types/schema/nodes/contributors.d.ts +12 -0
  94. package/dist/types/schema/nodes/core_section.d.ts +17 -0
  95. package/dist/types/schema/nodes/cross_reference.d.ts +1 -1
  96. package/dist/types/schema/nodes/inline_footnote.d.ts +1 -1
  97. package/dist/types/schema/nodes/keyword.d.ts +0 -1
  98. package/dist/types/schema/nodes/{keywords_group.d.ts → keyword_group.d.ts} +3 -3
  99. package/dist/types/schema/nodes/{keywords_section.d.ts → keywords.d.ts} +3 -3
  100. package/dist/types/schema/types.d.ts +1 -1
  101. package/dist/types/transformer/builders.d.ts +2 -14
  102. package/dist/types/transformer/decode.d.ts +6 -6
  103. package/dist/types/transformer/highlight-markers.d.ts +1 -0
  104. package/dist/types/transformer/object-types.d.ts +1 -2
  105. package/dist/types/transformer/section-category.d.ts +1 -1
  106. package/package.json +1 -1
  107. package/dist/cjs/lib/core-section-categories.js +0 -29
  108. package/dist/es/lib/core-section-categories.js +0 -26
  109. package/dist/types/lib/core-section-categories.d.ts +0 -8
  110. package/dist/types/schema/nodes/affiliations_section.d.ts +0 -11
  111. package/dist/types/schema/nodes/contributors_section.d.ts +0 -12
@@ -18,8 +18,6 @@ import serializeToXML from 'w3c-xmlserializer';
18
18
  import { schema } from '../schema';
19
19
  import { generateID } from './id';
20
20
  import { timestamp } from './timestamp';
21
- export const DEFAULT_BUNDLE = 'MPBundle:www-zotero-org-styles-nature';
22
- export const DEFAULT_PAGE_LAYOUT = 'MPPageLayout:defaultA4';
23
21
  export const buildProject = (owner) => ({
24
22
  _id: generateID(ObjectTypes.Project),
25
23
  objectType: ObjectTypes.Project,
@@ -45,30 +43,12 @@ export const buildContributor = (bibliographicName, role = 'author', priority =
45
43
  export const buildBibliographyItem = (data) => (Object.assign(Object.assign({}, data), { type: data.type || 'article-journal', _id: generateID(ObjectTypes.BibliographyItem), objectType: ObjectTypes.BibliographyItem }));
46
44
  export const buildBibliographicName = (data) => (Object.assign(Object.assign({}, data), { _id: generateID(ObjectTypes.BibliographicName), objectType: ObjectTypes.BibliographicName }));
47
45
  export const buildBibliographicDate = (data) => (Object.assign(Object.assign({}, data), { _id: generateID(ObjectTypes.BibliographicDate), objectType: ObjectTypes.BibliographicDate }));
48
- export const buildAuxiliaryObjectReference = (containingObject, rids) => {
49
- const auxiliaryObjectReference = {
50
- _id: generateID(ObjectTypes.AuxiliaryObjectReference),
51
- objectType: ObjectTypes.AuxiliaryObjectReference,
52
- containingObject: containingObject || undefined,
53
- };
54
- if (rids.length < 2) {
55
- Object.assign(auxiliaryObjectReference, { referencedObject: rids[0] });
56
- }
57
- else {
58
- Object.assign(auxiliaryObjectReference, { referencedObjects: rids });
59
- }
60
- return auxiliaryObjectReference;
61
- };
62
- export const buildEmbeddedCitationItem = (bibliographyItem) => ({
63
- _id: generateID(ObjectTypes.CitationItem),
64
- objectType: ObjectTypes.CitationItem,
65
- bibliographyItem,
66
- });
67
- export const buildCitation = (containingObject, embeddedCitationItems) => ({
68
- _id: generateID(ObjectTypes.Citation),
69
- objectType: ObjectTypes.Citation,
70
- containingObject: containingObject || undefined,
71
- embeddedCitationItems: embeddedCitationItems.map(buildEmbeddedCitationItem),
46
+ export const buildBibliographyElement = (bibliographyItems) => ({
47
+ _id: generateID(ObjectTypes.BibliographyElement),
48
+ objectType: ObjectTypes.BibliographyElement,
49
+ contents: '',
50
+ elementType: 'div',
51
+ containedObjectIDs: bibliographyItems.map((b) => b._id),
72
52
  });
73
53
  export const buildKeyword = (name) => ({
74
54
  _id: generateID(ObjectTypes.Keyword),
@@ -76,19 +56,6 @@ export const buildKeyword = (name) => ({
76
56
  name,
77
57
  });
78
58
  export const buildKeywordGroup = (attributes) => (Object.assign(Object.assign(Object.assign({ _id: generateID(ObjectTypes.KeywordGroup), objectType: ObjectTypes.KeywordGroup }, (attributes.type && { type: attributes.type })), (attributes.title && { title: attributes.title })), (attributes.label && { label: attributes.label })));
79
- export const buildManuscriptKeyword = (name) => ({
80
- _id: generateID(ObjectTypes.ManuscriptKeyword),
81
- objectType: ObjectTypes.ManuscriptKeyword,
82
- name,
83
- });
84
- export const buildLibraryCollection = (owner, name) => ({
85
- _id: generateID(ObjectTypes.LibraryCollection),
86
- objectType: ObjectTypes.LibraryCollection,
87
- owners: [owner],
88
- writers: [],
89
- viewers: [],
90
- name,
91
- });
92
59
  export const buildFigure = (blob) => ({
93
60
  _id: generateID(ObjectTypes.Figure),
94
61
  objectType: ObjectTypes.Figure,
@@ -112,12 +79,6 @@ export const buildSupplementaryMaterial = (title, href) => ({
112
79
  title,
113
80
  href,
114
81
  });
115
- export const buildUserProfileAffiliation = (institution, priority = 0) => ({
116
- _id: generateID(ObjectTypes.UserProfileAffiliation),
117
- objectType: ObjectTypes.UserProfileAffiliation,
118
- institution,
119
- priority,
120
- });
121
82
  export const buildComment = (target, contents = '', selector, contributions, annotationColor) => ({
122
83
  _id: generateID(ObjectTypes.CommentAnnotation),
123
84
  objectType: ObjectTypes.CommentAnnotation,
@@ -134,11 +95,6 @@ export const buildNote = (target, source, contents = '') => ({
134
95
  source,
135
96
  contents,
136
97
  });
137
- export const buildValidation = (results) => ({
138
- _id: generateID(ObjectTypes.RequirementsValidation),
139
- objectType: ObjectTypes.RequirementsValidation,
140
- results,
141
- });
142
98
  export const buildInlineMathFragment = (containingObject, TeXRepresentation) => ({
143
99
  _id: generateID(ObjectTypes.InlineMathFragment),
144
100
  objectType: ObjectTypes.InlineMathFragment,
@@ -194,18 +150,6 @@ export const buildColor = (value, priority) => ({
194
150
  priority,
195
151
  value,
196
152
  });
197
- export const buildHighlight = () => ({
198
- _id: generateID(ObjectTypes.Highlight),
199
- objectType: ObjectTypes.Highlight,
200
- });
201
- export const buildHighlightMarker = (highlightID, start, offset, field) => ({
202
- highlightID,
203
- objectType: ObjectTypes.HighlightMarker,
204
- _id: generateID(ObjectTypes.HighlightMarker),
205
- start,
206
- offset,
207
- field,
208
- });
209
153
  export const buildContribution = (profileID) => ({
210
154
  _id: generateID(ObjectTypes.Contribution),
211
155
  objectType: ObjectTypes.Contribution,
@@ -217,12 +161,6 @@ export const buildContributorRole = (name) => ({
217
161
  objectType: ObjectTypes.ContributorRole,
218
162
  name,
219
163
  });
220
- export const buildInlineStyle = (priority, title) => ({
221
- _id: generateID(ObjectTypes.InlineStyle),
222
- objectType: ObjectTypes.InlineStyle,
223
- priority,
224
- title,
225
- });
226
164
  export const buildAttribution = () => ({
227
165
  _id: generateID(ObjectTypes.Attribution),
228
166
  objectType: ObjectTypes.Attribution,
@@ -231,11 +169,6 @@ export const buildJournal = () => ({
231
169
  _id: generateID(ObjectTypes.Journal),
232
170
  objectType: ObjectTypes.Journal,
233
171
  });
234
- export const buildStatusLabel = (name) => ({
235
- _id: generateID(ObjectTypes.StatusLabel),
236
- objectType: ObjectTypes.StatusLabel,
237
- name,
238
- });
239
172
  export const auxiliaryObjectTypes = new Set([
240
173
  schema.nodes.figure_element,
241
174
  schema.nodes.table_element,
@@ -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,17 +55,41 @@ 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);
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];
57
62
  export const isManuscriptNode = (model) => model !== null;
58
- const isParagraphElement = hasObjectType(ObjectTypes.ParagraphElement);
59
63
  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
64
  const hasParentSection = (id) => (section) => section.path &&
65
65
  section.path.length > 1 &&
66
66
  section.path[section.path.length - 2] === id;
67
67
  export class Decoder {
68
+ createTitleNode() {
69
+ const titles = getTitles(this.modelMap) || buildTitles();
70
+ return this.decode(titles);
71
+ }
72
+ createAffiliationsNode() {
73
+ const affiliations = getAffiliations(this.modelMap)
74
+ .map((a) => this.decode(a))
75
+ .filter(Boolean);
76
+ return schema.nodes.affiliations.createAndFill({}, affiliations);
77
+ }
78
+ createContributorsNode() {
79
+ const contributors = getContributors(this.modelMap)
80
+ .map((c) => this.decode(c))
81
+ .filter(Boolean);
82
+ return schema.nodes.contributors.createAndFill({}, contributors);
83
+ }
84
+ createKeywordsNode() {
85
+ const elements = getKeywordElements(this.modelMap)
86
+ .map((e) => this.decode(e))
87
+ .filter(Boolean);
88
+ return schema.nodes.keywords.createAndFill({}, [
89
+ schema.nodes.section_title.create({}, schema.text('Keywords')),
90
+ ...elements,
91
+ ]);
92
+ }
68
93
  createMetaSectionNode() {
69
94
  const commentListNode = this.createCommentListNode();
70
95
  return schema.nodes.meta_section.createAndFill({}, [
@@ -76,54 +101,51 @@ export class Decoder {
76
101
  ...this.comments.values(),
77
102
  ]);
78
103
  }
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
- }
86
- }
87
- createAffiliationSectionNode(rootSectionNodes) {
88
- const affiliationNodes = getAffiliations(this.modelMap)
89
- .map((affiliation) => this.decode(affiliation))
90
- .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
- }
97
- }
98
- createContributorSectionNode(rootSectionNodes) {
99
- const contributorNodes = getContributors(this.modelMap)
100
- .map((contributor) => this.decode(contributor))
101
- .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
- }
108
- }
109
- createTitleNode() {
110
- const titles = getModelsByType(this.modelMap, ObjectTypes.Titles)[0] ||
111
- buildTitles();
112
- return this.decode(titles);
113
- }
114
104
  createRootSectionNodes() {
115
- let rootSections = getSections(this.modelMap).filter((section) => !section.path || section.path.length <= 1);
105
+ let rootSections = getSections(this.modelMap)
106
+ .filter((section) => !section.path || section.path.length <= 1)
107
+ .filter((section) => section.category !== 'MPSectionCategory:contributors' &&
108
+ section.category !== 'MPSectionCategory:affiliations' &&
109
+ section.category !== 'MPSectionCategory:keywords');
116
110
  rootSections = this.addGeneratedLabels(rootSections);
117
- const rootSectionNodes = rootSections
111
+ const sectionGroups = groupBy(rootSections, (sec) => {
112
+ var _a;
113
+ return chooseCoreSectionBySection((_a = sec.category) !== null && _a !== void 0 ? _a : '');
114
+ });
115
+ this.ensureCoreSectionsExist(sectionGroups);
116
+ const absSectionNode = sectionGroups['MPSectionCategory:abstracts']
117
+ .map(this.decode)
118
+ .filter(isManuscriptNode);
119
+ const bodySectionNodes = sectionGroups['MPSectionCategory:body']
120
+ .map(this.decode)
121
+ .filter(isManuscriptNode);
122
+ const backmatterSectionNodes = sectionGroups['MPSectionCategory:backmatter']
118
123
  .map(this.decode)
119
124
  .filter(isManuscriptNode);
120
- this.handleMissingRootSectionNodes(rootSectionNodes);
121
- if (!rootSectionNodes.length) {
122
- rootSectionNodes.push(schema.nodes.section.createAndFill({
123
- id: generateNodeID(schema.nodes.section),
124
- }));
125
+ const abstractCoreSectionNodes = this.createAndFill(schema.nodes.abstracts, absSectionNode);
126
+ const bodyCoreSectionNodes = this.createAndFill(schema.nodes.body, bodySectionNodes);
127
+ const backmatterCoreSectionNodes = this.createAndFill(schema.nodes.backmatter, backmatterSectionNodes);
128
+ return {
129
+ abstracts: abstractCoreSectionNodes,
130
+ body: bodyCoreSectionNodes,
131
+ backmatter: backmatterCoreSectionNodes,
132
+ };
133
+ }
134
+ ensureCoreSectionsExist(coreSections) {
135
+ if (!coreSections['MPSectionCategory:abstracts']) {
136
+ coreSections['MPSectionCategory:abstracts'] = [];
137
+ }
138
+ if (!coreSections['MPSectionCategory:body']) {
139
+ coreSections['MPSectionCategory:body'] = [];
125
140
  }
126
- return rootSectionNodes;
141
+ if (!coreSections['MPSectionCategory:backmatter']) {
142
+ coreSections['MPSectionCategory:backmatter'] = [];
143
+ }
144
+ }
145
+ createAndFill(nodeType, content) {
146
+ return nodeType.createAndFill({
147
+ id: generateNodeID(nodeType),
148
+ }, content);
127
149
  }
128
150
  createCommentsNode(model) {
129
151
  const comments = [];
@@ -329,19 +351,34 @@ export class Decoder {
329
351
  },
330
352
  [ObjectTypes.KeywordsElement]: (data) => {
331
353
  const model = data;
332
- const keywordGroups = this.getKeywordGroups();
354
+ const keywordGroups = getKeywordGroups(this.modelMap).map((k) => this.decode(k));
333
355
  return schema.nodes.keywords_element.create({
334
356
  id: model._id,
335
357
  paragraphStyle: model.paragraphStyle,
336
358
  }, keywordGroups);
337
359
  },
360
+ [ObjectTypes.KeywordGroup]: (data) => {
361
+ const keywordGroup = data;
362
+ const keywords = getKeywords(this.modelMap)
363
+ .filter((k) => k.containedGroup === keywordGroup._id)
364
+ .map((k) => this.decode(k));
365
+ const comments = this.createCommentsNode(keywordGroup);
366
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
367
+ return schema.nodes.keyword_group.create({
368
+ id: keywordGroup._id,
369
+ type: keywordGroup.type,
370
+ comments: comments.map((c) => c.attrs.id),
371
+ }, keywords);
372
+ },
338
373
  [ObjectTypes.Keyword]: (data) => {
339
- const model = data;
374
+ const keyword = data;
375
+ const comments = this.createCommentsNode(keyword);
376
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
340
377
  return schema.nodes.keyword.create({
341
- id: model._id,
342
- contents: model.name,
343
- comments: this.createCommentsNode(model),
344
- }, schema.text(model.name));
378
+ id: keyword._id,
379
+ contents: keyword.name,
380
+ comments: comments.map((c) => c.attrs.id),
381
+ }, schema.text(keyword.name));
345
382
  },
346
383
  [ObjectTypes.ListElement]: (data) => {
347
384
  const model = data;
@@ -463,9 +500,6 @@ export class Decoder {
463
500
  for (const id of model.elementIDs) {
464
501
  const element = this.getModel(id);
465
502
  if (element) {
466
- if (isKeywordsSection(model) && isParagraphElement(element)) {
467
- continue;
468
- }
469
503
  elements.push(element);
470
504
  }
471
505
  else if (this.allowMissingElements) {
@@ -506,17 +540,11 @@ export class Decoder {
506
540
  const sectionNodeType = chooseSectionNodeType(sectionCategory);
507
541
  const commentNodes = this.createCommentsNode(model);
508
542
  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
- }
543
+ const content = (sectionLabelNode
544
+ ? [sectionLabelNode, sectionTitleNode]
545
+ : [sectionTitleNode])
546
+ .concat(elementNodes)
547
+ .concat(nestedSections);
520
548
  const sectionNode = sectionNodeType.createAndFill({
521
549
  id: model._id,
522
550
  category: sectionCategory,
@@ -635,13 +663,21 @@ export class Decoder {
635
663
  };
636
664
  this.getModel = (id) => this.modelMap.get(id);
637
665
  this.createArticleNode = (manuscriptID) => {
638
- const titlesNode = this.createTitleNode();
639
- const rootSectionNodes = this.createRootSectionNodes();
640
- const metaSectionNode = this.createMetaSectionNode();
666
+ const title = this.createTitleNode();
667
+ const contributors = this.createContributorsNode();
668
+ const affiliations = this.createAffiliationsNode();
669
+ const keywords = this.createKeywordsNode();
670
+ const { abstracts, body, backmatter } = this.createRootSectionNodes();
671
+ const meta = this.createMetaSectionNode();
641
672
  const contents = [
642
- titlesNode,
643
- ...rootSectionNodes,
644
- metaSectionNode,
673
+ title,
674
+ contributors,
675
+ affiliations,
676
+ keywords,
677
+ abstracts,
678
+ body,
679
+ backmatter,
680
+ meta,
645
681
  ];
646
682
  return schema.nodes.manuscript.create({
647
683
  id: manuscriptID || this.getManuscriptID(),
@@ -683,23 +719,6 @@ export class Decoder {
683
719
  }
684
720
  return parser.parse(template.content.firstElementChild, options);
685
721
  };
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
722
  this.getManuscriptID = () => {
704
723
  for (const item of this.modelMap.values()) {
705
724
  if (isManuscript(item)) {
@@ -784,26 +803,4 @@ export class Decoder {
784
803
  }
785
804
  return listing;
786
805
  }
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
806
  }
@@ -17,7 +17,7 @@ import { DOMSerializer } from 'prosemirror-model';
17
17
  import serializeToXML from 'w3c-xmlserializer';
18
18
  import { iterateChildren } from '../lib/utils';
19
19
  import { hasGroup, isHighlightMarkerNode, isSectionNode, schema, } from '../schema';
20
- import { buildAttribution } from './builders';
20
+ import { auxiliaryObjectTypes, buildAttribution, buildElementsOrder, } from './builders';
21
21
  import { extractHighlightMarkers, isHighlightableModel, } from './highlight-markers';
22
22
  import { nodeTypesMap } from './node-types';
23
23
  import { buildSectionCategory } from './section-category';
@@ -420,34 +420,9 @@ const encoders = {
420
420
  elementType: 'div',
421
421
  paragraphStyle: node.attrs.paragraphStyle || undefined,
422
422
  }),
423
- keywords_group: (node) => ({
423
+ keyword_group: (node) => ({
424
424
  type: node.attrs.type,
425
425
  }),
426
- keywords_section: (node, parent, path, priority) => ({
427
- category: buildSectionCategory(node),
428
- priority: priority.value++,
429
- title: inlineContentsOfNodeType(node, node.type.schema.nodes.section_title),
430
- path: path.concat([node.attrs.id]),
431
- elementIDs: childElements(node)
432
- .map((childNode) => childNode.attrs.id)
433
- .filter((id) => id),
434
- }),
435
- affiliations_section: (node, parent, path, priority) => ({
436
- category: buildSectionCategory(node),
437
- priority: priority.value++,
438
- path: path.concat([node.attrs.id]),
439
- elementIDs: childElements(node)
440
- .map((childNode) => childNode.attrs.id)
441
- .filter((id) => id),
442
- }),
443
- contributors_section: (node, parent, path, priority) => ({
444
- category: buildSectionCategory(node),
445
- priority: priority.value++,
446
- path: path.concat([node.attrs.id]),
447
- elementIDs: childElements(node)
448
- .map((childNode) => childNode.attrs.id)
449
- .filter((id) => id),
450
- }),
451
426
  missing_figure: (node) => ({
452
427
  position: node.attrs.position || undefined,
453
428
  }),
@@ -568,6 +543,14 @@ export const modelFromNode = (node, parent, path, priority) => {
568
543
  const comments = [...commentAnnotationsMap.values()];
569
544
  return { model, comments };
570
545
  };
546
+ function isCoreSection(child) {
547
+ return (child.type === schema.nodes.abstracts ||
548
+ child.type === schema.nodes.body ||
549
+ child.type === schema.nodes.backmatter ||
550
+ child.type === schema.nodes.affiliations ||
551
+ child.type === schema.nodes.contributors ||
552
+ child.type === schema.nodes.keywords);
553
+ }
571
554
  export const encode = (node) => {
572
555
  const models = new Map();
573
556
  const priority = {
@@ -575,6 +558,10 @@ export const encode = (node) => {
575
558
  };
576
559
  const placeholders = ['placeholder', 'placeholder_element'];
577
560
  const addModel = (path, parent) => (child) => {
561
+ if (isCoreSection(child)) {
562
+ child.forEach(addModel([], child));
563
+ return;
564
+ }
578
565
  if (!child.attrs.id) {
579
566
  return;
580
567
  }
@@ -587,6 +574,9 @@ export const encode = (node) => {
587
574
  if (placeholders.includes(child.type.name)) {
588
575
  return;
589
576
  }
577
+ if (parent.type === schema.nodes.paragraph) {
578
+ return;
579
+ }
590
580
  const { model, comments } = modelFromNode(child, parent, path, priority);
591
581
  if (models.has(model._id)) {
592
582
  throw Error(`Encountered duplicate ids in models map while encoding: ${model._id}`);
@@ -602,12 +592,20 @@ export const encode = (node) => {
602
592
  models.set(model._id, model);
603
593
  child.forEach(addModel(path.concat(child.attrs.id), child));
604
594
  };
605
- node.forEach((cNode) => {
606
- if (cNode.type === schema.nodes.meta_section) {
607
- processMetaSectionNode(cNode, models, priority);
595
+ node.forEach((child) => {
596
+ if (child.type === schema.nodes.meta_section) {
597
+ processMetaSectionNode(child, models, priority);
608
598
  }
609
599
  });
610
600
  node.forEach(addModel([], node));
601
+ if (node.type === schema.nodes.manuscript) {
602
+ auxiliaryObjectTypes.forEach((t) => {
603
+ const order = generateElementOrder(node, t);
604
+ if (order) {
605
+ models.set(order._id, order);
606
+ }
607
+ });
608
+ }
611
609
  return models;
612
610
  };
613
611
  const processMetaSectionNode = (node, models, priority) => {
@@ -619,3 +617,22 @@ const processMetaSectionNode = (node, models, priority) => {
619
617
  }
620
618
  });
621
619
  };
620
+ const generateElementOrder = (node, nodeType) => {
621
+ const ids = [];
622
+ node.descendants((n) => {
623
+ if (n.type === nodeType) {
624
+ ids.push(n.attrs.id);
625
+ }
626
+ return true;
627
+ });
628
+ if (!ids.length) {
629
+ return undefined;
630
+ }
631
+ const type = nodeTypesMap.get(nodeType);
632
+ if (!type) {
633
+ return undefined;
634
+ }
635
+ const order = buildElementsOrder(type);
636
+ order.elements = ids;
637
+ return order;
638
+ };
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
  import { buildComment } from './builders';
17
- const highlightableFields = [
17
+ export const highlightableFields = [
18
18
  'caption',
19
19
  'contents',
20
20
  'title',
@@ -194,11 +194,9 @@ export class HTMLTransformer {
194
194
  const citationNode = node;
195
195
  const element = this.document.createElement('span');
196
196
  element.setAttribute('class', 'citation');
197
- const citation = getModel(citationNode.attrs.rid);
198
- if (citation) {
199
- element.setAttribute('data-reference-ids', citation.embeddedCitationItems
200
- .map((item) => item.bibliographyItem)
201
- .join(' '));
197
+ const rids = citationNode.attrs.rids;
198
+ if (rids.length) {
199
+ element.setAttribute('data-reference-ids', rids.join(' '));
202
200
  }
203
201
  if (citationNode.attrs.contents) {
204
202
  element.innerHTML = citationNode.attrs.contents;
@@ -209,20 +207,7 @@ export class HTMLTransformer {
209
207
  const crossReferenceNode = node;
210
208
  const element = this.document.createElement('a');
211
209
  element.classList.add('cross-reference');
212
- const auxiliaryObjectReference = getModel(crossReferenceNode.attrs.rid);
213
- if (auxiliaryObjectReference &&
214
- auxiliaryObjectReference.referencedObject) {
215
- if (auxiliaryObjectReference.referencedObject.startsWith('MPFigureElement')) {
216
- const model = getModel(auxiliaryObjectReference.referencedObject);
217
- if (model && model.containedObjectIDs.length > 0) {
218
- element.setAttribute('href', `#${model.containedObjectIDs[0]}`);
219
- }
220
- }
221
- else {
222
- element.setAttribute('href', `#${auxiliaryObjectReference.referencedObject}`);
223
- }
224
- element.setAttribute('data-reference-ids', crossReferenceNode.attrs.rid);
225
- }
210
+ element.setAttribute('data-reference-ids', crossReferenceNode.attrs.rids.join(' '));
226
211
  element.textContent =
227
212
  crossReferenceNode.attrs.customLabel || crossReferenceNode.attrs.label;
228
213
  return element;
@@ -35,6 +35,6 @@ export const nodeNames = new Map([
35
35
  [schema.nodes.table_element, 'Table'],
36
36
  [schema.nodes.blockquote_element, 'Block Quote'],
37
37
  [schema.nodes.pullquote_element, 'Pull Quote'],
38
- [schema.nodes.keywords_section, 'Section'],
38
+ [schema.nodes.keywords, 'Section'],
39
39
  [schema.nodes.toc_section, 'Section'],
40
40
  ]);
@@ -47,7 +47,7 @@ export const nodeTitle = (node) => {
47
47
  case nodes.section:
48
48
  case nodes.bibliography_section:
49
49
  case nodes.footnotes_section:
50
- case nodes.keywords_section:
50
+ case nodes.keywords:
51
51
  case nodes.toc_section:
52
52
  case nodes.graphical_abstract_section:
53
53
  return snippetOfNodeType(node, nodes.section_title);
@@ -16,6 +16,9 @@
16
16
  import { ObjectTypes } from '@manuscripts/json-schema';
17
17
  import { GROUP_ELEMENT, GROUP_EXECUTABLE, GROUP_SECTION, hasGroup, schema, } from '../schema';
18
18
  export const nodeTypesMap = new Map([
19
+ [schema.nodes.abstracts, ObjectTypes.Section],
20
+ [schema.nodes.body, ObjectTypes.Section],
21
+ [schema.nodes.backmatter, ObjectTypes.Section],
19
22
  [schema.nodes.comment, ObjectTypes.CommentAnnotation],
20
23
  [schema.nodes.bibliography_item, ObjectTypes.BibliographyItem],
21
24
  [schema.nodes.bibliography_element, ObjectTypes.BibliographyElement],
@@ -23,7 +26,6 @@ export const nodeTypesMap = new Map([
23
26
  [schema.nodes.blockquote_element, ObjectTypes.QuoteElement],
24
27
  [schema.nodes.bullet_list, ObjectTypes.ListElement],
25
28
  [schema.nodes.citation, ObjectTypes.Citation],
26
- [schema.nodes.cross_reference, ObjectTypes.AuxiliaryObjectReference],
27
29
  [schema.nodes.equation, ObjectTypes.Equation],
28
30
  [schema.nodes.equation_element, ObjectTypes.EquationElement],
29
31
  [schema.nodes.figure, ObjectTypes.Figure],
@@ -37,8 +39,8 @@ export const nodeTypesMap = new Map([
37
39
  [schema.nodes.inline_equation, ObjectTypes.InlineMathFragment],
38
40
  [schema.nodes.keyword, ObjectTypes.Keyword],
39
41
  [schema.nodes.keywords_element, ObjectTypes.KeywordsElement],
40
- [schema.nodes.keywords_section, ObjectTypes.Section],
41
- [schema.nodes.keywords_group, ObjectTypes.KeywordGroup],
42
+ [schema.nodes.keywords, ObjectTypes.Section],
43
+ [schema.nodes.keyword_group, ObjectTypes.KeywordGroup],
42
44
  [schema.nodes.listing, ObjectTypes.Listing],
43
45
  [schema.nodes.listing_element, ObjectTypes.ListingElement],
44
46
  [schema.nodes.manuscript, ObjectTypes.Manuscript],
@@ -54,9 +56,9 @@ export const nodeTypesMap = new Map([
54
56
  [schema.nodes.affiliation, ObjectTypes.Affiliation],
55
57
  [schema.nodes.contributor, ObjectTypes.Contributor],
56
58
  [schema.nodes.table_element_footer, ObjectTypes.TableElementFooter],
59
+ [schema.nodes.contributors, ObjectTypes.Section],
60
+ [schema.nodes.affiliations, ObjectTypes.Section],
57
61
  [schema.nodes.title, ObjectTypes.Titles],
58
- [schema.nodes.contributors_section, ObjectTypes.Section],
59
- [schema.nodes.affiliations_section, ObjectTypes.Section],
60
62
  ]);
61
63
  export const isExecutableNodeType = (type) => hasGroup(type, GROUP_EXECUTABLE);
62
64
  export const isElementNodeType = (type) => hasGroup(type, GROUP_ELEMENT);