@manuscripts/transform 2.3.38-LEAN-3911.0 → 2.4.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 (126) hide show
  1. package/dist/cjs/__tests__/data/project-dump.json +825 -0
  2. package/dist/cjs/index.js +6 -6
  3. package/dist/cjs/jats/importer/index.js +22 -0
  4. package/dist/cjs/jats/importer/{jats-dom-parser.js → jats-body-dom-parser.js} +34 -273
  5. package/dist/cjs/jats/importer/jats-body-transformations.js +22 -74
  6. package/dist/cjs/jats/importer/jats-comments.js +104 -27
  7. package/dist/cjs/jats/importer/jats-front-parser.js +321 -0
  8. package/dist/cjs/jats/importer/jats-journal-meta-parser.js +1 -8
  9. package/dist/cjs/jats/importer/jats-parser-utils.js +5 -43
  10. package/dist/cjs/jats/importer/jats-reference-parser.js +23 -16
  11. package/dist/cjs/jats/importer/jats-references.js +18 -18
  12. package/dist/cjs/jats/importer/parse-jats-article.js +79 -40
  13. package/dist/cjs/jats/index.js +7 -7
  14. package/dist/cjs/jats/{exporter/jats-exporter.js → jats-exporter.js} +398 -264
  15. package/dist/cjs/jats/{exporter/jats-versions.js → jats-versions.js} +3 -1
  16. package/dist/cjs/lib/utils.js +1 -12
  17. package/dist/cjs/transformer/__tests__/__helpers__/doc.js +37 -0
  18. package/dist/cjs/transformer/builders.js +219 -0
  19. package/dist/cjs/transformer/decode.js +898 -0
  20. package/dist/cjs/transformer/document-object-types.js +31 -0
  21. package/dist/cjs/transformer/encode.js +674 -0
  22. package/dist/cjs/{jats/importer/create-article-node.js → transformer/filename.js} +9 -10
  23. package/dist/cjs/transformer/footnote-category.js +20 -0
  24. package/dist/cjs/transformer/footnotes-order.js +60 -0
  25. package/dist/cjs/transformer/highlight-markers.js +138 -0
  26. package/dist/cjs/transformer/html.js +400 -0
  27. package/dist/cjs/transformer/id.js +5 -10
  28. package/dist/cjs/transformer/index.js +18 -0
  29. package/dist/cjs/{jats/exporter → transformer}/labels.js +5 -4
  30. package/dist/cjs/transformer/manuscript-dependencies.js +21 -0
  31. package/dist/cjs/transformer/model-map.js +26 -0
  32. package/dist/cjs/{lib/deafults.js → transformer/models.js} +1 -3
  33. package/dist/cjs/transformer/node-names.js +1 -0
  34. package/dist/cjs/transformer/object-types.js +57 -0
  35. package/dist/cjs/transformer/project-bundle.js +94 -0
  36. package/dist/cjs/transformer/serializer.js +23 -0
  37. package/dist/cjs/transformer/timestamp.js +20 -0
  38. package/dist/cjs/transformer/update-identifiers.js +93 -0
  39. package/dist/cjs/version.js +1 -1
  40. package/dist/es/__tests__/data/project-dump.json +825 -0
  41. package/dist/es/index.js +5 -5
  42. package/dist/{types/jats/importer/create-article-node.d.ts → es/jats/importer/index.js} +2 -3
  43. package/dist/es/jats/importer/{jats-dom-parser.js → jats-body-dom-parser.js} +35 -274
  44. package/dist/es/jats/importer/jats-body-transformations.js +22 -74
  45. package/dist/es/jats/importer/jats-comments.js +101 -26
  46. package/dist/es/jats/importer/jats-front-parser.js +315 -0
  47. package/dist/es/jats/importer/jats-journal-meta-parser.js +0 -6
  48. package/dist/es/jats/importer/jats-parser-utils.js +6 -44
  49. package/dist/es/jats/importer/jats-reference-parser.js +23 -16
  50. package/dist/es/jats/importer/jats-references.js +18 -18
  51. package/dist/es/jats/importer/parse-jats-article.js +78 -41
  52. package/dist/es/jats/index.js +3 -5
  53. package/dist/es/jats/{exporter/jats-exporter.js → jats-exporter.js} +392 -258
  54. package/dist/es/jats/{exporter/jats-versions.js → jats-versions.js} +1 -0
  55. package/dist/es/lib/utils.js +0 -9
  56. package/dist/es/transformer/__tests__/__helpers__/doc.js +29 -0
  57. package/dist/es/transformer/builders.js +186 -0
  58. package/dist/es/transformer/decode.js +888 -0
  59. package/dist/es/transformer/document-object-types.js +28 -0
  60. package/dist/es/transformer/encode.js +664 -0
  61. package/dist/es/transformer/filename.js +23 -0
  62. package/dist/es/transformer/footnote-category.js +16 -0
  63. package/dist/es/transformer/footnotes-order.js +55 -0
  64. package/dist/es/transformer/highlight-markers.js +132 -0
  65. package/dist/es/transformer/html.js +393 -0
  66. package/dist/es/transformer/id.js +3 -8
  67. package/dist/es/transformer/index.js +16 -0
  68. package/dist/es/{jats/exporter → transformer}/labels.js +5 -4
  69. package/dist/es/transformer/manuscript-dependencies.js +17 -0
  70. package/dist/es/transformer/model-map.js +22 -0
  71. package/dist/es/{lib/deafults.js → transformer/models.js} +2 -2
  72. package/dist/es/transformer/node-names.js +1 -0
  73. package/dist/es/transformer/object-types.js +52 -0
  74. package/dist/es/transformer/project-bundle.js +85 -0
  75. package/dist/es/transformer/serializer.js +17 -0
  76. package/dist/es/transformer/timestamp.js +16 -0
  77. package/dist/es/transformer/update-identifiers.js +87 -0
  78. package/dist/es/version.js +1 -1
  79. package/dist/types/index.d.ts +6 -6
  80. package/dist/types/jats/importer/index.d.ts +16 -0
  81. package/dist/types/jats/importer/{jats-dom-parser.d.ts → jats-body-dom-parser.d.ts} +1 -1
  82. package/dist/types/jats/importer/jats-body-transformations.d.ts +1 -5
  83. package/dist/types/jats/importer/jats-comments.d.ts +10 -4
  84. package/dist/types/jats/importer/jats-front-parser.d.ts +84 -0
  85. package/dist/types/jats/importer/jats-journal-meta-parser.d.ts +0 -10
  86. package/dist/types/jats/importer/jats-references.d.ts +8 -19
  87. package/dist/types/jats/importer/parse-jats-article.d.ts +5 -12
  88. package/dist/types/jats/index.d.ts +3 -5
  89. package/dist/types/jats/{exporter/jats-exporter.d.ts → jats-exporter.d.ts} +29 -15
  90. package/dist/types/jats/{exporter/jats-versions.d.ts → jats-versions.d.ts} +1 -0
  91. package/dist/types/lib/utils.d.ts +0 -2
  92. package/dist/types/schema/nodes/bibliography_item.d.ts +3 -3
  93. package/dist/types/schema/nodes/contributor.d.ts +0 -10
  94. package/dist/types/schema/nodes/keyword_group.d.ts +0 -1
  95. package/dist/types/schema/nodes/manuscript.d.ts +7 -8
  96. package/dist/types/schema/nodes/title.d.ts +3 -0
  97. package/dist/types/transformer/__tests__/__helpers__/doc.d.ts +18 -0
  98. package/dist/types/transformer/builders.d.ts +61 -0
  99. package/dist/types/transformer/decode.d.ts +52 -0
  100. package/dist/types/transformer/document-object-types.d.ts +17 -0
  101. package/dist/types/transformer/encode.d.ts +29 -0
  102. package/dist/types/transformer/filename.d.ts +16 -0
  103. package/dist/types/transformer/footnote-category.d.ts +17 -0
  104. package/dist/{es/jats/importer/create-article-node.js → types/transformer/footnotes-order.d.ts} +8 -10
  105. package/dist/types/transformer/highlight-markers.d.ts +31 -0
  106. package/dist/types/transformer/html.d.ts +36 -0
  107. package/dist/types/transformer/id.d.ts +2 -5
  108. package/dist/types/transformer/index.d.ts +16 -0
  109. package/dist/types/{jats/exporter → transformer}/labels.d.ts +2 -2
  110. package/dist/types/transformer/manuscript-dependencies.d.ts +4 -0
  111. package/dist/types/transformer/model-map.d.ts +19 -0
  112. package/dist/types/transformer/models.d.ts +48 -0
  113. package/dist/types/transformer/object-types.d.ts +30 -0
  114. package/dist/types/transformer/project-bundle.d.ts +30 -0
  115. package/dist/types/transformer/serializer.d.ts +19 -0
  116. package/dist/types/{lib/deafults.d.ts → transformer/timestamp.d.ts} +2 -2
  117. package/dist/types/transformer/update-identifiers.d.ts +23 -0
  118. package/dist/types/types.d.ts +2 -0
  119. package/dist/types/version.d.ts +1 -1
  120. package/package.json +1 -2
  121. package/dist/cjs/jats/importer/jats-front-transformations.js +0 -79
  122. package/dist/es/jats/importer/jats-front-transformations.js +0 -76
  123. package/dist/types/jats/importer/jats-front-transformations.d.ts +0 -22
  124. package/dist/types/jats/types.d.ts +0 -1
  125. /package/dist/cjs/{jats/types.js → types.js} +0 -0
  126. /package/dist/es/{jats/types.js → types.js} +0 -0
@@ -0,0 +1,888 @@
1
+ /*!
2
+ * © 2019 Atypon Systems LLC
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ var __rest = (this && this.__rest) || function (s, e) {
17
+ var t = {};
18
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
19
+ t[p] = s[p];
20
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
21
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
22
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
23
+ t[p[i]] = s[p[i]];
24
+ }
25
+ return t;
26
+ };
27
+ import { ObjectTypes, } from '@manuscripts/json-schema';
28
+ import debug from 'debug';
29
+ import { DOMParser } from 'prosemirror-model';
30
+ import { MissingElement } from '../errors';
31
+ import { abstractsType, backmatterType, bodyType, } from '../lib/section-group-type';
32
+ import { schema, } from '../schema';
33
+ import { buildTitles } from './builders';
34
+ import { insertHighlightMarkers } from './highlight-markers';
35
+ import { generateID } from './id';
36
+ import { ExtraObjectTypes, isCommentAnnotation, isManuscript, } from './object-types';
37
+ import { chooseSectionLableName, chooseSectionNodeType, chooseSecType, getSectionGroupType, guessSectionCategory, } from './section-category';
38
+ import { timestamp } from './timestamp';
39
+ const warn = debug('manuscripts-transform');
40
+ const parser = DOMParser.fromSchema(schema);
41
+ export const getModelData = (model) => {
42
+ const { updatedAt, createdAt } = model, data = __rest(model, ["updatedAt", "createdAt"]);
43
+ return data;
44
+ };
45
+ export const getModelsByType = (modelMap, objectType) => {
46
+ const output = [];
47
+ for (const model of modelMap.values()) {
48
+ if (model.objectType === objectType) {
49
+ output.push(model);
50
+ }
51
+ }
52
+ return output;
53
+ };
54
+ export const sortSectionsByPriority = (a, b) => a.priority === b.priority ? 0 : Number(a.priority) - Number(b.priority);
55
+ const getSections = (modelMap) => getModelsByType(modelMap, ObjectTypes.Section).sort(sortSectionsByPriority);
56
+ const getAffiliations = (modelMap) => getModelsByType(modelMap, ObjectTypes.Affiliation);
57
+ const getContributors = (modelMap) => getModelsByType(modelMap, ObjectTypes.Contributor);
58
+ const getAuthorNotes = (modelMap) => getModelsByType(modelMap, ObjectTypes.AuthorNotes);
59
+ const getKeywordElements = (modelMap) => getModelsByType(modelMap, ObjectTypes.KeywordsElement);
60
+ const getSupplements = (modelMap) => getModelsByType(modelMap, ObjectTypes.Supplement);
61
+ const getKeywordGroups = (modelMap) => getModelsByType(modelMap, ObjectTypes.KeywordGroup);
62
+ const getKeywords = (modelMap) => getModelsByType(modelMap, ObjectTypes.Keyword);
63
+ const getTitles = (modelMap) => getModelsByType(modelMap, ObjectTypes.Titles)[0];
64
+ const hasParentSection = (id) => (section) => section.path &&
65
+ section.path.length > 1 &&
66
+ section.path[section.path.length - 2] === id;
67
+ const deprecatedCategories = [
68
+ 'MPSectionCategory:contributors',
69
+ 'MPSectionCategory:affiliations',
70
+ 'MPSectionCategory:keywords',
71
+ ];
72
+ export class Decoder {
73
+ createTitleNode() {
74
+ const titles = getTitles(this.modelMap) || buildTitles();
75
+ return this.decode(titles);
76
+ }
77
+ createAffiliationsNode() {
78
+ const affiliations = getAffiliations(this.modelMap)
79
+ .map((a) => this.decode(a))
80
+ .filter(Boolean);
81
+ if (!affiliations.length) {
82
+ return false;
83
+ }
84
+ return schema.nodes.affiliations.createAndFill({}, affiliations);
85
+ }
86
+ createContributorsNode() {
87
+ const contributors = getContributors(this.modelMap)
88
+ .map((c) => this.decode(c))
89
+ .filter(Boolean);
90
+ const content = [...contributors];
91
+ if (!content.length) {
92
+ return false;
93
+ }
94
+ return schema.nodes.contributors.createAndFill({}, content);
95
+ }
96
+ createAuthorNotesNode() {
97
+ return getAuthorNotes(this.modelMap)
98
+ .map((authorNote) => this.decode(authorNote))
99
+ .filter(Boolean);
100
+ }
101
+ createKeywordsNode() {
102
+ const elements = getKeywordElements(this.modelMap)
103
+ .map((e) => this.decode(e))
104
+ .filter(Boolean);
105
+ if (!elements.length) {
106
+ return false;
107
+ }
108
+ return schema.nodes.keywords.createAndFill({}, [
109
+ schema.nodes.section_title.create({}, schema.text('Keywords')),
110
+ ...elements,
111
+ ]);
112
+ }
113
+ createSupplementsNode() {
114
+ const elements = getSupplements(this.modelMap)
115
+ .map((e) => this.decode(e))
116
+ .filter(Boolean);
117
+ if (!elements.length) {
118
+ return false;
119
+ }
120
+ return schema.nodes.supplements.createAndFill({}, [
121
+ schema.nodes.section_title.create({}, schema.text('SupplementaryMaterials')),
122
+ ...elements,
123
+ ]);
124
+ }
125
+ createCommentsNode() {
126
+ return schema.nodes.comments.createAndFill({}, [
127
+ ...this.comments.values(),
128
+ ]);
129
+ }
130
+ createContentSections() {
131
+ let sections = getSections(this.modelMap);
132
+ sections = this.addGeneratedLabels(sections);
133
+ const groups = {
134
+ abstracts: [],
135
+ body: [],
136
+ backmatter: [],
137
+ };
138
+ for (const section of sections) {
139
+ if (section.path.length > 1) {
140
+ continue;
141
+ }
142
+ const category = section.category;
143
+ if (category && deprecatedCategories.includes(category)) {
144
+ continue;
145
+ }
146
+ const group = category ? getSectionGroupType(category) : bodyType;
147
+ groups[group._id].push(this.decode(section));
148
+ }
149
+ const abstracts = schema.nodes.abstracts.createAndFill({}, groups[abstractsType._id]);
150
+ const body = schema.nodes.body.createAndFill({}, groups[bodyType._id]);
151
+ const backmatter = schema.nodes.backmatter.createAndFill({}, groups[backmatterType._id]);
152
+ return [abstracts, body, backmatter];
153
+ }
154
+ createCommentNodes(model) {
155
+ const comments = [];
156
+ for (const comment of this.getComments(model)) {
157
+ comments.push(this.decode(comment));
158
+ }
159
+ return comments;
160
+ }
161
+ getComments(model) {
162
+ return Array.from(this.modelMap.values()).filter((c) => isCommentAnnotation(c) && c.target === model._id);
163
+ }
164
+ extractListing(model) {
165
+ if (model.listingID) {
166
+ return this.createListing(model.listingID);
167
+ }
168
+ }
169
+ constructor(modelMap, allowMissingElements = false) {
170
+ this.comments = new Map();
171
+ this.creators = {
172
+ [ObjectTypes.Titles]: (data) => {
173
+ const model = data;
174
+ const comments = this.createCommentNodes(model);
175
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
176
+ return this.parseContents(model.title, 'div', this.getComments(model), {
177
+ topNode: schema.nodes.title.create({
178
+ id: model._id,
179
+ }),
180
+ });
181
+ },
182
+ [ObjectTypes.BibliographyElement]: (data) => {
183
+ var _a;
184
+ const model = data;
185
+ const referenceIDs = (_a = model.containedObjectIDs) === null || _a === void 0 ? void 0 : _a.filter((i) => i.startsWith('MPBibliographyItem'));
186
+ const references = [];
187
+ referenceIDs === null || referenceIDs === void 0 ? void 0 : referenceIDs.forEach((id) => {
188
+ const referenceModel = this.getModel(id);
189
+ if (referenceModel) {
190
+ return references.push(this.decode(referenceModel));
191
+ }
192
+ });
193
+ return schema.nodes.bibliography_element.createChecked({
194
+ id: model._id,
195
+ contents: '',
196
+ paragraphStyle: model.paragraphStyle,
197
+ }, references);
198
+ },
199
+ [ObjectTypes.BibliographyItem]: (data) => {
200
+ const model = data;
201
+ const comments = this.createCommentNodes(model);
202
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
203
+ return schema.nodes.bibliography_item.create({
204
+ id: model._id,
205
+ type: model.type,
206
+ author: model.author,
207
+ issued: model.issued,
208
+ containerTitle: model['container-title'],
209
+ volume: model.volume,
210
+ issue: model.issue,
211
+ supplement: model.supplement,
212
+ doi: model.DOI,
213
+ page: model.page,
214
+ title: model.title,
215
+ literal: model.literal,
216
+ });
217
+ },
218
+ [ExtraObjectTypes.PlaceholderElement]: (data) => {
219
+ const model = data;
220
+ return schema.nodes.placeholder_element.create({
221
+ id: model._id,
222
+ });
223
+ },
224
+ [ObjectTypes.Figure]: (data) => {
225
+ const model = data;
226
+ const comments = this.createCommentNodes(model);
227
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
228
+ return schema.nodes.figure.create({
229
+ id: model._id,
230
+ contentType: model.contentType,
231
+ src: model.src,
232
+ position: model.position,
233
+ });
234
+ },
235
+ [ObjectTypes.FigureElement]: (data) => {
236
+ const model = data;
237
+ const paragraphIDs = model.containedObjectIDs.filter((i) => i.startsWith('MPParagraphElement'));
238
+ const figureIDs = model.containedObjectIDs.filter((i) => i.startsWith('MPFigure') || i.startsWith('MPMissingFigure'));
239
+ const paragraphs = [];
240
+ paragraphIDs.forEach((id) => {
241
+ const paragraphModel = this.getModel(id);
242
+ if (paragraphModel) {
243
+ return paragraphs.push(this.decode(paragraphModel));
244
+ }
245
+ });
246
+ const figures = [];
247
+ figureIDs.forEach((id) => {
248
+ const figureModel = this.getModel(id);
249
+ if (!figureModel) {
250
+ return figures.push(schema.nodes.placeholder.create({
251
+ id,
252
+ label: 'A figure',
253
+ }));
254
+ }
255
+ return figures.push(this.decode(figureModel));
256
+ });
257
+ if (!figures.length) {
258
+ figures.push(schema.nodes.figure.createAndFill());
259
+ }
260
+ const figcaption = this.getFigcaption(model);
261
+ const comments = this.createCommentNodes(model);
262
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
263
+ const content = [...paragraphs, ...figures, figcaption];
264
+ const listing = this.extractListing(model);
265
+ if (listing) {
266
+ content.push(listing);
267
+ }
268
+ else {
269
+ const listing = schema.nodes.listing.create();
270
+ content.push(listing);
271
+ }
272
+ return schema.nodes.figure_element.createChecked({
273
+ id: model._id,
274
+ figureLayout: model.figureLayout,
275
+ label: model.label,
276
+ figureStyle: model.figureStyle,
277
+ alignment: model.alignment,
278
+ sizeFraction: model.sizeFraction,
279
+ suppressCaption: Boolean(model.suppressCaption),
280
+ suppressTitle: Boolean(model.suppressTitle === undefined ? true : model.suppressTitle),
281
+ attribution: model.attribution,
282
+ alternatives: model.alternatives,
283
+ }, content);
284
+ },
285
+ [ObjectTypes.Equation]: (data) => {
286
+ const model = data;
287
+ return schema.nodes.equation.createChecked({
288
+ id: model._id,
289
+ contents: model.contents,
290
+ format: model.format,
291
+ });
292
+ },
293
+ [ObjectTypes.EquationElement]: (data) => {
294
+ const model = data;
295
+ const equationModel = this.getModel(model.containedObjectID);
296
+ let equation;
297
+ if (equationModel) {
298
+ equation = this.decode(equationModel);
299
+ }
300
+ else if (this.allowMissingElements) {
301
+ equation = schema.nodes.placeholder.create({
302
+ id: model.containedObjectID,
303
+ label: 'An equation',
304
+ });
305
+ }
306
+ else {
307
+ throw new MissingElement(model.containedObjectID);
308
+ }
309
+ return schema.nodes.equation_element.createChecked({
310
+ id: model._id,
311
+ label: model.label,
312
+ }, [equation]);
313
+ },
314
+ [ObjectTypes.FootnotesElement]: (data) => {
315
+ const foonotesElementModel = data;
316
+ const footnotesOfKind = [];
317
+ const footnoteOrder = getModelsByType(this.modelMap, ObjectTypes.FootnotesOrder).find((model) => model.containedObjectID === data._id);
318
+ if (footnoteOrder) {
319
+ footnoteOrder.footnotesList.map(({ id }) => {
320
+ const model = this.modelMap.get(id);
321
+ const collateByKind = foonotesElementModel.collateByKind || 'footnote';
322
+ if (model.kind === collateByKind) {
323
+ const comments = this.createCommentNodes(model);
324
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
325
+ const footnote = this.parseContents(model.contents || '<div></div>', undefined, this.getComments(model), {
326
+ topNode: schema.nodes.footnote.create({
327
+ id: model._id,
328
+ kind: model.kind,
329
+ }),
330
+ });
331
+ footnotesOfKind.push(footnote);
332
+ }
333
+ });
334
+ }
335
+ return schema.nodes.footnotes_element.create({
336
+ id: foonotesElementModel._id,
337
+ kind: foonotesElementModel.collateByKind,
338
+ paragraphStyle: foonotesElementModel.paragraphStyle,
339
+ }, footnotesOfKind);
340
+ },
341
+ [ObjectTypes.Footnote]: (data) => {
342
+ const footnoteModel = data;
343
+ const comments = this.createCommentNodes(footnoteModel);
344
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
345
+ return this.parseContents(footnoteModel.contents || '<div></div>', undefined, this.getComments(footnoteModel), {
346
+ topNode: schema.nodes.footnote.create({
347
+ id: footnoteModel._id,
348
+ kind: footnoteModel.kind,
349
+ }),
350
+ });
351
+ },
352
+ [ObjectTypes.KeywordsElement]: (data) => {
353
+ const model = data;
354
+ const keywordGroups = getKeywordGroups(this.modelMap).map((k) => this.decode(k));
355
+ return schema.nodes.keywords_element.create({
356
+ id: model._id,
357
+ paragraphStyle: model.paragraphStyle,
358
+ }, keywordGroups);
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.createCommentNodes(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
+ }, keywords);
371
+ },
372
+ [ObjectTypes.Keyword]: (data) => {
373
+ const keyword = data;
374
+ const comments = this.createCommentNodes(keyword);
375
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
376
+ return schema.nodes.keyword.create({
377
+ id: keyword._id,
378
+ contents: keyword.name,
379
+ }, schema.text(keyword.name));
380
+ },
381
+ [ObjectTypes.ListElement]: (data) => {
382
+ const model = data;
383
+ const comments = this.createCommentNodes(model);
384
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
385
+ switch (model.elementType) {
386
+ case 'ol':
387
+ return this.parseContents(model.contents || '<ol></ol>', undefined, this.getComments(model), {
388
+ topNode: schema.nodes.list.create({
389
+ id: model._id,
390
+ listStyleType: model.listStyleType || 'order',
391
+ paragraphStyle: model.paragraphStyle,
392
+ }),
393
+ });
394
+ case 'ul':
395
+ return this.parseContents(model.contents || '<ul></ul>', undefined, this.getComments(model), {
396
+ topNode: schema.nodes.list.create({
397
+ id: model._id,
398
+ listStyleType: model.listStyleType || 'bullet',
399
+ paragraphStyle: model.paragraphStyle,
400
+ }),
401
+ });
402
+ default:
403
+ throw new Error('Unknown list element type');
404
+ }
405
+ },
406
+ [ObjectTypes.Listing]: (data) => {
407
+ const model = data;
408
+ const comments = this.createCommentNodes(model);
409
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
410
+ return schema.nodes.listing.createChecked({
411
+ id: model._id,
412
+ contents: model.contents,
413
+ language: model.language,
414
+ languageKey: model.languageKey,
415
+ });
416
+ },
417
+ [ObjectTypes.ListingElement]: (data) => {
418
+ const model = data;
419
+ const listingModel = this.getModel(model.containedObjectID);
420
+ let listing;
421
+ if (listingModel) {
422
+ listing = this.decode(listingModel);
423
+ }
424
+ else if (this.allowMissingElements) {
425
+ listing = schema.nodes.placeholder.create({
426
+ id: model.containedObjectID,
427
+ label: 'A listing',
428
+ });
429
+ }
430
+ else {
431
+ throw new MissingElement(model.containedObjectID);
432
+ }
433
+ const figcaption = this.getFigcaption(model);
434
+ const comments = this.createCommentNodes(model);
435
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
436
+ return schema.nodes.listing_element.createChecked({
437
+ id: model._id,
438
+ suppressCaption: model.suppressCaption,
439
+ suppressTitle: Boolean(model.suppressTitle === undefined ? true : model.suppressTitle),
440
+ }, [listing, figcaption]);
441
+ },
442
+ [ObjectTypes.MissingFigure]: (data) => {
443
+ const model = data;
444
+ return schema.nodes.missing_figure.create({
445
+ id: model._id,
446
+ position: model.position,
447
+ });
448
+ },
449
+ [ObjectTypes.ParagraphElement]: (data) => {
450
+ const model = data;
451
+ const comments = this.createCommentNodes(model);
452
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
453
+ return this.parseContents(model.contents || '<p></p>', undefined, this.getComments(model), {
454
+ topNode: schema.nodes.paragraph.create({
455
+ id: model._id,
456
+ paragraphStyle: model.paragraphStyle,
457
+ placeholder: model.placeholderInnerHTML,
458
+ }),
459
+ });
460
+ },
461
+ [ObjectTypes.QuoteElement]: (data) => {
462
+ const model = data;
463
+ switch (model.quoteType) {
464
+ case 'block':
465
+ return this.parseContents(model.contents || '<p></p>', undefined, this.getComments(model), {
466
+ topNode: schema.nodes.blockquote_element.create({
467
+ id: model._id,
468
+ paragraphStyle: model.paragraphStyle,
469
+ placeholder: model.placeholderInnerHTML,
470
+ }),
471
+ });
472
+ case 'pull':
473
+ return this.parseContents(model.contents || '<p></p>', undefined, this.getComments(model), {
474
+ topNode: schema.nodes.pullquote_element.create({
475
+ id: model._id,
476
+ paragraphStyle: model.paragraphStyle,
477
+ placeholder: model.placeholderInnerHTML,
478
+ }),
479
+ });
480
+ default:
481
+ throw new Error('Unknown block type');
482
+ }
483
+ },
484
+ [ObjectTypes.TableElementFooter]: (data) => {
485
+ const model = data;
486
+ const contents = [];
487
+ const generalTableFootnotes = [];
488
+ const footnotesElements = [];
489
+ for (const containedObjectID of model.containedObjectIDs) {
490
+ const model = this.modelMap.get(containedObjectID);
491
+ if (model.objectType === ObjectTypes.ParagraphElement) {
492
+ const paragraph = this.decode(model);
493
+ if (paragraph) {
494
+ generalTableFootnotes.push(paragraph);
495
+ }
496
+ }
497
+ else {
498
+ footnotesElements.push(this.decode(model));
499
+ }
500
+ }
501
+ if (generalTableFootnotes && generalTableFootnotes.length) {
502
+ contents.push(schema.nodes.general_table_footnote.create({ id: generateID(ExtraObjectTypes.GeneralTableFootnote) }, [...generalTableFootnotes]));
503
+ }
504
+ if (footnotesElements && footnotesElements.length) {
505
+ contents.push(...footnotesElements);
506
+ }
507
+ return schema.nodes.table_element_footer.create({
508
+ id: model._id,
509
+ }, contents);
510
+ },
511
+ [ObjectTypes.AuthorNotes]: (data) => {
512
+ const model = data;
513
+ const content = model.containedObjectIDs.map((id) => this.decode(this.modelMap.get(id)));
514
+ if (content.length == 0) {
515
+ return null;
516
+ }
517
+ return schema.nodes.author_notes.createAndFill({
518
+ id: model._id,
519
+ }, [...content]);
520
+ },
521
+ [ObjectTypes.Corresponding]: (data) => {
522
+ const model = data;
523
+ return this.parseContents(model.contents, 'corresp', [], {
524
+ topNode: schema.nodes.corresp.create({
525
+ id: model._id,
526
+ label: model.label,
527
+ }),
528
+ });
529
+ },
530
+ [ObjectTypes.Section]: (data) => {
531
+ const model = data;
532
+ const elements = [];
533
+ if (model.elementIDs) {
534
+ for (const id of model.elementIDs) {
535
+ const element = this.getModel(id);
536
+ if (element) {
537
+ elements.push(element);
538
+ }
539
+ else if (this.allowMissingElements) {
540
+ const placeholderElement = {
541
+ _id: id,
542
+ containerID: model._id,
543
+ elementType: 'p',
544
+ objectType: ExtraObjectTypes.PlaceholderElement,
545
+ createdAt: timestamp(),
546
+ updatedAt: timestamp(),
547
+ };
548
+ elements.push(placeholderElement);
549
+ }
550
+ else {
551
+ throw new MissingElement(id);
552
+ }
553
+ }
554
+ }
555
+ const elementNodes = elements.map((e) => this.decode(e));
556
+ const sectionTitle = 'section_title';
557
+ const sectionTitleNode = model.title
558
+ ? this.parseContents(model.title, 'h1', this.getComments(model), {
559
+ topNode: schema.nodes[sectionTitle].create(),
560
+ })
561
+ : schema.nodes[sectionTitle].create();
562
+ let sectionLabelNode = undefined;
563
+ if (model.label) {
564
+ sectionLabelNode = this.parseContents(model.label, 'label', this.getComments(model), {
565
+ topNode: schema.nodes.section_label.create(),
566
+ });
567
+ }
568
+ const nestedSections = getSections(this.modelMap)
569
+ .filter(hasParentSection(model._id))
570
+ .filter((s) => s.category !== 'MPSectionCategory:box-element')
571
+ .map(this.creators[ObjectTypes.Section]);
572
+ const sectionCategory = model.category || guessSectionCategory(elements);
573
+ const sectionNodeType = chooseSectionNodeType(sectionCategory);
574
+ const comments = this.createCommentNodes(model);
575
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
576
+ let content = [];
577
+ if (sectionLabelNode &&
578
+ model.category !== 'MPSectionCategory:box-element') {
579
+ content.push(sectionLabelNode);
580
+ }
581
+ const attrs = {
582
+ id: model._id,
583
+ category: sectionCategory,
584
+ titleSuppressed: model.titleSuppressed,
585
+ pageBreakStyle: model.pageBreakStyle,
586
+ generatedLabel: model.generatedLabel,
587
+ };
588
+ if (model.category === 'MPSectionCategory:box-element') {
589
+ const figCaption = this.getBoxElementFigCaption(model);
590
+ if (figCaption) {
591
+ content.push(figCaption);
592
+ }
593
+ if (model.label) {
594
+ attrs.label = model.label;
595
+ }
596
+ }
597
+ else {
598
+ content.push(sectionTitleNode);
599
+ }
600
+ content = content.concat(elementNodes).concat(nestedSections);
601
+ const sectionNode = sectionNodeType.createAndFill(attrs, content);
602
+ if (!sectionNode) {
603
+ console.error(model);
604
+ throw new Error('Invalid content for section ' + model._id);
605
+ }
606
+ return sectionNode;
607
+ },
608
+ [ObjectTypes.Table]: (data) => {
609
+ const model = data;
610
+ return this.parseContents(model.contents, undefined, [], {
611
+ topNode: schema.nodes.table.create({
612
+ id: model._id,
613
+ }),
614
+ });
615
+ },
616
+ [ObjectTypes.TableElement]: (data) => {
617
+ const model = data;
618
+ const table = this.createTable(model);
619
+ const tableColGroup = this.createTableColGroup(model);
620
+ const tableElementFooter = this.createTableElementFooter(model);
621
+ const figcaption = this.getFigcaption(model);
622
+ const comments = this.createCommentNodes(model);
623
+ comments.forEach((c) => this.comments.set(c.attrs.id, c));
624
+ const content = [figcaption, table];
625
+ if (tableColGroup) {
626
+ content.push(tableColGroup);
627
+ }
628
+ if (tableElementFooter) {
629
+ content.push(tableElementFooter);
630
+ }
631
+ const listing = model.listingID
632
+ ? this.createListing(model.listingID)
633
+ : schema.nodes.listing.create();
634
+ content.push(listing);
635
+ return schema.nodes.table_element.createChecked({
636
+ id: model._id,
637
+ table: model.containedObjectID,
638
+ suppressCaption: model.suppressCaption,
639
+ suppressTitle: Boolean(model.suppressTitle === undefined ? true : model.suppressTitle),
640
+ suppressFooter: model.suppressFooter,
641
+ suppressHeader: model.suppressHeader,
642
+ tableStyle: model.tableStyle,
643
+ paragraphStyle: model.paragraphStyle,
644
+ }, content);
645
+ },
646
+ [ObjectTypes.TOCElement]: (data) => {
647
+ const model = data;
648
+ return schema.nodes.toc_element.create({
649
+ id: model._id,
650
+ contents: model.contents
651
+ ? model.contents.replace(/\s+xmlns=".+?"/, '')
652
+ : '',
653
+ paragraphStyle: model.paragraphStyle,
654
+ });
655
+ },
656
+ [ObjectTypes.CommentAnnotation]: (data) => {
657
+ const model = data;
658
+ return schema.nodes.comment.create({
659
+ id: model._id,
660
+ contents: model.contents,
661
+ selector: model.selector,
662
+ target: model.target,
663
+ resolved: model.resolved,
664
+ contributions: model.contributions,
665
+ originalText: model.originalText,
666
+ });
667
+ },
668
+ [ObjectTypes.Affiliation]: (data) => {
669
+ const model = data;
670
+ return schema.nodes.affiliation.create({
671
+ id: model._id,
672
+ institution: model.institution,
673
+ addressLine1: model.addressLine1,
674
+ addressLine2: model.addressLine2,
675
+ addressLine3: model.addressLine3,
676
+ postCode: model.postCode,
677
+ country: model.country,
678
+ county: model.county,
679
+ city: model.city,
680
+ email: model.email,
681
+ department: model.department,
682
+ priority: model.priority,
683
+ }, schema.text('_'));
684
+ },
685
+ [ObjectTypes.Contributor]: (data) => {
686
+ const model = data;
687
+ return schema.nodes.contributor.create({
688
+ id: model._id,
689
+ role: model.role,
690
+ affiliations: model.affiliations,
691
+ email: model.email,
692
+ isJointContributor: model.isJointContributor,
693
+ bibliographicName: model.bibliographicName,
694
+ userID: model.userID,
695
+ invitationID: model.invitationID,
696
+ isCorresponding: model.isCorresponding,
697
+ ORCIDIdentifier: model.ORCIDIdentifier,
698
+ footnote: model.footnote,
699
+ corresp: model.corresp,
700
+ priority: model.priority,
701
+ }, schema.text('_'));
702
+ },
703
+ [ObjectTypes.Supplement]: (data) => {
704
+ var _a, _b;
705
+ const model = data;
706
+ return schema.nodes.supplement.create({
707
+ id: model._id,
708
+ href: model.href,
709
+ mimeType: (_a = model.MIME) === null || _a === void 0 ? void 0 : _a.split('/')[0],
710
+ mimeSubType: (_b = model.MIME) === null || _b === void 0 ? void 0 : _b.split('/')[1],
711
+ title: model.title,
712
+ });
713
+ },
714
+ };
715
+ this.decode = (model) => {
716
+ if (!this.creators[model.objectType]) {
717
+ warn(`No converter for ${model.objectType}`);
718
+ return null;
719
+ }
720
+ return this.creators[model.objectType](model);
721
+ };
722
+ this.getModel = (id) => this.modelMap.get(id);
723
+ this.createArticleNode = (manuscriptID) => {
724
+ const nodes = [
725
+ this.createTitleNode(),
726
+ this.createContributorsNode(),
727
+ this.createAffiliationsNode(),
728
+ ...this.createAuthorNotesNode(),
729
+ this.createKeywordsNode(),
730
+ this.createSupplementsNode(),
731
+ ...this.createContentSections(),
732
+ this.createCommentsNode(),
733
+ ];
734
+ const contents = nodes.filter((node) => node !== false);
735
+ const props = this.getManuscript();
736
+ return schema.nodes.manuscript.create({
737
+ id: manuscriptID || this.getManuscriptID(),
738
+ doi: (props === null || props === void 0 ? void 0 : props.DOI) || '',
739
+ articleType: props === null || props === void 0 ? void 0 : props.articleType,
740
+ prototype: props === null || props === void 0 ? void 0 : props.prototype,
741
+ primaryLanguageCode: props === null || props === void 0 ? void 0 : props.primaryLanguageCode,
742
+ }, contents);
743
+ };
744
+ this.addGeneratedLabels = (sections) => {
745
+ const nextLableCount = { Appendix: 1 };
746
+ return sections.map((section) => {
747
+ if (section.generatedLabel) {
748
+ const secType = section.category
749
+ ? chooseSecType(section.category)
750
+ : undefined;
751
+ if (secType === 'appendices') {
752
+ section.label = `${chooseSectionLableName(secType)} ${nextLableCount['Appendix']}`;
753
+ nextLableCount['Appendix'] += 1;
754
+ }
755
+ else {
756
+ delete section.label;
757
+ }
758
+ }
759
+ return section;
760
+ });
761
+ };
762
+ this.parseContents = (contents, wrapper, commentAnnotations = [], options) => {
763
+ const contentsWithComments = commentAnnotations.length
764
+ ? insertHighlightMarkers(contents, commentAnnotations)
765
+ : contents;
766
+ const wrappedContents = wrapper
767
+ ? `<${wrapper}>${contentsWithComments}</${wrapper}>`
768
+ : contentsWithComments;
769
+ const html = wrappedContents.trim();
770
+ if (!html.length) {
771
+ throw new Error('No HTML to parse');
772
+ }
773
+ const template = document.createElement('template');
774
+ template.innerHTML = html;
775
+ if (!template.content.firstElementChild) {
776
+ throw new Error('No content could be parsed');
777
+ }
778
+ return parser.parse(template.content.firstElementChild, options);
779
+ };
780
+ this.getManuscriptID = () => {
781
+ for (const item of this.modelMap.values()) {
782
+ if (isManuscript(item)) {
783
+ return item._id;
784
+ }
785
+ }
786
+ };
787
+ this.getManuscript = () => {
788
+ for (const item of this.modelMap.values()) {
789
+ if (isManuscript(item)) {
790
+ return item;
791
+ }
792
+ }
793
+ };
794
+ this.getBoxElementFigCaption = (model) => {
795
+ const titleNode = schema.nodes.caption_title.create();
796
+ const captionTitle = model.title
797
+ ? this.parseContents(model.title, 'caption_title', this.getComments(model), {
798
+ topNode: titleNode,
799
+ })
800
+ : titleNode;
801
+ return schema.nodes.figcaption.create({}, captionTitle);
802
+ };
803
+ this.getFigcaption = (model) => {
804
+ const titleNode = schema.nodes.caption_title.create();
805
+ const captionTitle = model.title
806
+ ? this.parseContents(model.title, 'caption_title', this.getComments(model), {
807
+ topNode: titleNode,
808
+ })
809
+ : titleNode;
810
+ if (model.caption && /<\/?[a-z][\s\S]*>/i.test(model.caption)) {
811
+ const captionDoc = document.createElement('div');
812
+ captionDoc.innerHTML = model.caption;
813
+ const content = [captionTitle];
814
+ const paragraphs = captionDoc.querySelectorAll('p');
815
+ for (const paragraph of paragraphs) {
816
+ const captionNode = schema.nodes.caption.create();
817
+ const caption = this.parseContents(paragraph.outerHTML, 'caption', this.getComments(model), {
818
+ topNode: captionNode,
819
+ });
820
+ content.push(caption);
821
+ }
822
+ return schema.nodes.figcaption.create({}, content);
823
+ }
824
+ const captionNode = schema.nodes.caption.create();
825
+ const caption = model.caption
826
+ ? this.parseContents(model.caption, 'caption', this.getComments(model), {
827
+ topNode: captionNode,
828
+ })
829
+ : captionNode;
830
+ return schema.nodes.figcaption.create({}, [captionTitle, caption]);
831
+ };
832
+ this.modelMap = modelMap;
833
+ this.allowMissingElements = allowMissingElements;
834
+ }
835
+ createTable(model) {
836
+ const tableID = model.containedObjectID;
837
+ const tableModel = this.getModel(tableID);
838
+ let table;
839
+ if (tableModel) {
840
+ table = this.decode(tableModel);
841
+ }
842
+ else if (this.allowMissingElements) {
843
+ table = schema.nodes.placeholder.create({
844
+ id: tableID,
845
+ label: 'A table',
846
+ });
847
+ }
848
+ else {
849
+ throw new MissingElement(tableID);
850
+ }
851
+ return table;
852
+ }
853
+ createTableColGroup(model) {
854
+ const tableID = model.containedObjectID;
855
+ const tableModel = this.getModel(tableID);
856
+ if (!tableModel || !tableModel.contents.includes('<colgroup>')) {
857
+ return undefined;
858
+ }
859
+ return this.parseContents(tableModel.contents, undefined, [], {
860
+ topNode: schema.nodes.table_colgroup.create(),
861
+ });
862
+ }
863
+ createTableElementFooter(model) {
864
+ const tableElementFooterID = model.tableElementFooterID;
865
+ if (!tableElementFooterID) {
866
+ return undefined;
867
+ }
868
+ const tableElementFooterModel = this.getModel(tableElementFooterID);
869
+ return tableElementFooterModel
870
+ ? this.decode(tableElementFooterModel)
871
+ : undefined;
872
+ }
873
+ createListing(id) {
874
+ const listing = this.getModel(id);
875
+ if (listing) {
876
+ return this.decode(listing);
877
+ }
878
+ else if (this.allowMissingElements) {
879
+ return schema.nodes.placeholder.create({
880
+ id,
881
+ label: 'A listing',
882
+ });
883
+ }
884
+ else {
885
+ throw new MissingElement(id);
886
+ }
887
+ }
888
+ }