@manuscripts/transform 1.2.4 → 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.
- package/dist/cjs/jats/importer/jats-body-transformations.js +53 -12
- package/dist/cjs/jats/importer/parse-jats-article.js +0 -1
- package/dist/cjs/jats/jats-exporter.js +47 -14
- package/dist/cjs/schema/nodes/section.js +1 -1
- package/dist/cjs/transformer/encode.js +10 -3
- package/dist/cjs/transformer/section-category.js +23 -1
- package/dist/es/jats/importer/jats-body-transformations.js +54 -13
- package/dist/es/jats/importer/parse-jats-article.js +0 -1
- package/dist/es/jats/jats-exporter.js +47 -14
- package/dist/es/schema/nodes/section.js +1 -1
- package/dist/es/transformer/encode.js +11 -4
- package/dist/es/transformer/section-category.js +19 -1
- package/dist/types/jats/importer/jats-body-transformations.d.ts +7 -1
- package/dist/types/jats/jats-exporter.d.ts +2 -0
- package/dist/types/transformer/section-category.d.ts +3 -2
- package/package.json +2 -2
|
@@ -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
|
-
|
|
160
|
+
moveAbstractsIntoContainer(doc, abstractsContainer, createElement) {
|
|
150
161
|
const abstractNodes = doc.querySelectorAll('front > article-meta > abstract');
|
|
151
|
-
|
|
162
|
+
abstractNodes.forEach((abstractNode) => {
|
|
152
163
|
const abstract = this.createAbstract(abstractNode, createElement);
|
|
153
164
|
removeNodeFromParent(abstractNode);
|
|
154
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
194
|
+
backmatterContainer.appendChild(appendix);
|
|
171
195
|
}
|
|
196
|
+
},
|
|
197
|
+
moveBibliographyIntoContainer(doc, backmatterContainer, references, createElement) {
|
|
172
198
|
if (references) {
|
|
173
|
-
|
|
199
|
+
backmatterContainer.appendChild(this.createBibliography(doc, references, createElement));
|
|
174
200
|
}
|
|
175
201
|
},
|
|
176
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
262
|
+
backmatterContainer.appendChild(footnotes);
|
|
222
263
|
}
|
|
223
264
|
},
|
|
224
265
|
moveCaptionsToEnd(body) {
|
|
@@ -116,7 +116,6 @@ const parseJATSBody = (document, body, bibliographyItems, refModels, referenceId
|
|
|
116
116
|
const orderedFootnotesIDs = (0, footnotes_order_1.createOrderedFootnotesIDs)(document);
|
|
117
117
|
jats_body_transformations_1.jatsBodyTransformations.moveFloatsGroupToBody(document, body, createElement);
|
|
118
118
|
jats_body_transformations_1.jatsBodyTransformations.ensureSection(body, createElement);
|
|
119
|
-
jats_body_transformations_1.jatsBodyTransformations.mapFootnotesToSections(document, body, createElement);
|
|
120
119
|
jats_body_transformations_1.jatsBodyTransformations.moveSectionsToBody(document, body, bibliographyItems, createElement);
|
|
121
120
|
jats_body_transformations_1.jatsBodyTransformations.moveCaptionsToEnd(body);
|
|
122
121
|
jats_body_transformations_1.jatsBodyTransformations.moveTableFooterToEnd(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) {
|
|
@@ -1392,21 +1394,49 @@ class JATSExporter {
|
|
|
1392
1394
|
table.insertBefore(tfoot, tbody);
|
|
1393
1395
|
}
|
|
1394
1396
|
};
|
|
1395
|
-
this.
|
|
1396
|
-
const
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
}
|
|
1404
|
-
const sectionTitle = section.querySelector(':scope > title');
|
|
1405
|
-
if (!sectionTitle) {
|
|
1406
|
-
return false;
|
|
1407
|
-
}
|
|
1408
|
-
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));
|
|
1409
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
|
+
}
|
|
1410
1440
|
if (abstractSections.length) {
|
|
1411
1441
|
for (const abstractSection of abstractSections) {
|
|
1412
1442
|
const abstractNode = this.document.createElement('abstract');
|
|
@@ -1427,6 +1457,9 @@ class JATSExporter {
|
|
|
1427
1457
|
}
|
|
1428
1458
|
}
|
|
1429
1459
|
}
|
|
1460
|
+
if (container) {
|
|
1461
|
+
body.removeChild(container);
|
|
1462
|
+
}
|
|
1430
1463
|
};
|
|
1431
1464
|
this.moveSectionsToBack = (back, body) => {
|
|
1432
1465
|
const availabilitySection = body.querySelector('sec[sec-type="availability"]');
|
|
@@ -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)*
|
|
38
|
+
content: 'section_label? section_title (paragraph | element)* sections*',
|
|
39
39
|
attrs: {
|
|
40
40
|
id: { default: '' },
|
|
41
41
|
category: { default: '' },
|
|
@@ -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) {
|
|
@@ -449,9 +458,7 @@ const encoders = {
|
|
|
449
458
|
label: inlineContentsOfNodeType(node, node.type.schema.nodes.section_label) ||
|
|
450
459
|
undefined,
|
|
451
460
|
path: path.concat([node.attrs.id]),
|
|
452
|
-
elementIDs:
|
|
453
|
-
.map((childNode) => childNode.attrs.id)
|
|
454
|
-
.filter((id) => id),
|
|
461
|
+
elementIDs: sectionChildElementIds(node),
|
|
455
462
|
titleSuppressed: node.attrs.titleSuppressed || undefined,
|
|
456
463
|
generatedLabel: node.attrs.generatedLabel || undefined,
|
|
457
464
|
pageBreakStyle: node.attrs.pageBreakStyle || undefined,
|
|
@@ -14,8 +14,12 @@
|
|
|
14
14
|
* See the License for the specific language governing permissions and
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
18
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
19
|
+
};
|
|
17
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
-
exports.chooseSectionCategoryFromTitle = exports.chooseSectionCategory = exports.chooseSectionCategoryByType = exports.chooseSecType = exports.buildSectionCategory = exports.guessSectionCategory = exports.chooseSectionLableName = exports.chooseSectionNodeType = exports.isAnySectionNode = void 0;
|
|
21
|
+
exports.chooseSectionCategoryFromTitle = exports.chooseSectionCategory = exports.chooseSectionCategoryByType = exports.chooseSecType = exports.buildSectionCategory = exports.guessSectionCategory = exports.chooseSectionLableName = exports.chooseSectionNodeType = exports.isAnySectionNode = exports.getSectionTitles = void 0;
|
|
22
|
+
const section_categories_json_1 = __importDefault(require("@manuscripts/data/dist/shared/section-categories.json"));
|
|
19
23
|
const json_schema_1 = require("@manuscripts/json-schema");
|
|
20
24
|
const schema_1 = require("../schema");
|
|
21
25
|
const sectionNodeTypes = [
|
|
@@ -25,6 +29,18 @@ const sectionNodeTypes = [
|
|
|
25
29
|
schema_1.schema.nodes.section,
|
|
26
30
|
schema_1.schema.nodes.toc_section,
|
|
27
31
|
];
|
|
32
|
+
const sectionCategoriesMap = new Map(section_categories_json_1.default.map((section) => [
|
|
33
|
+
section._id,
|
|
34
|
+
section,
|
|
35
|
+
]));
|
|
36
|
+
const getSectionTitles = (sectionCategory) => {
|
|
37
|
+
const category = sectionCategoriesMap.get(sectionCategory);
|
|
38
|
+
if (category) {
|
|
39
|
+
return category.titles.length ? category.titles : [' '];
|
|
40
|
+
}
|
|
41
|
+
throw new Error(`${sectionCategory} not found in section categories`);
|
|
42
|
+
};
|
|
43
|
+
exports.getSectionTitles = getSectionTitles;
|
|
28
44
|
const isAnySectionNode = (node) => sectionNodeTypes.includes(node.type);
|
|
29
45
|
exports.isAnySectionNode = isAnySectionNode;
|
|
30
46
|
const chooseSectionNodeType = (category) => {
|
|
@@ -161,6 +177,12 @@ const chooseSectionCategoryByType = (secType) => {
|
|
|
161
177
|
return 'MPSectionCategory:supported-by';
|
|
162
178
|
case 'ethics-statement':
|
|
163
179
|
return 'MPSectionCategory:ethics-statement';
|
|
180
|
+
case 'body':
|
|
181
|
+
return 'MPSectionCategory:body';
|
|
182
|
+
case 'backmatter':
|
|
183
|
+
return 'MPSectionCategory:backmatter';
|
|
184
|
+
case 'abstracts':
|
|
185
|
+
return 'MPSectionCategory:abstracts';
|
|
164
186
|
default:
|
|
165
187
|
return undefined;
|
|
166
188
|
}
|
|
@@ -13,9 +13,20 @@
|
|
|
13
13
|
* See the License for the specific language governing permissions and
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
|
-
import { chooseSectionCategoryByType, chooseSecType } from '../../transformer';
|
|
16
|
+
import { chooseSectionCategoryByType, chooseSecType, getSectionTitles, } from '../../transformer';
|
|
17
17
|
const removeNodeFromParent = (node) => node.parentNode && node.parentNode.removeChild(node);
|
|
18
18
|
const capitalizeFirstLetter = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
|
19
|
+
const createSectionContainer = (type, createElement) => {
|
|
20
|
+
const sectionContainer = createElement('sec');
|
|
21
|
+
const sectionCategory = chooseSectionCategoryByType(type);
|
|
22
|
+
sectionContainer.setAttribute('sec-type', sectionCategory ? chooseSecType(sectionCategory) : '');
|
|
23
|
+
const title = createElement('title');
|
|
24
|
+
title.textContent = sectionCategory
|
|
25
|
+
? getSectionTitles(sectionCategory)[0]
|
|
26
|
+
: ' ';
|
|
27
|
+
sectionContainer.appendChild(title);
|
|
28
|
+
return sectionContainer;
|
|
29
|
+
};
|
|
19
30
|
export const jatsBodyTransformations = {
|
|
20
31
|
ensureSection(body, createElement) {
|
|
21
32
|
let section = createElement('sec');
|
|
@@ -143,34 +154,64 @@ export const jatsBodyTransformations = {
|
|
|
143
154
|
section.append(...floatsGroup.children);
|
|
144
155
|
return section;
|
|
145
156
|
},
|
|
146
|
-
|
|
157
|
+
moveAbstractsIntoContainer(doc, abstractsContainer, createElement) {
|
|
147
158
|
const abstractNodes = doc.querySelectorAll('front > article-meta > abstract');
|
|
148
|
-
|
|
159
|
+
abstractNodes.forEach((abstractNode) => {
|
|
149
160
|
const abstract = this.createAbstract(abstractNode, createElement);
|
|
150
161
|
removeNodeFromParent(abstractNode);
|
|
151
|
-
|
|
152
|
-
}
|
|
162
|
+
abstractsContainer.appendChild(abstract);
|
|
163
|
+
});
|
|
164
|
+
},
|
|
165
|
+
wrapBodySections(doc, bodyContainer) {
|
|
166
|
+
const bodySections = doc.querySelectorAll('body > sec:not([sec-type="backmatter"]), body > sec:not([sec-type])');
|
|
167
|
+
bodySections.forEach((section) => {
|
|
168
|
+
removeNodeFromParent(section);
|
|
169
|
+
bodyContainer.appendChild(section);
|
|
170
|
+
});
|
|
171
|
+
},
|
|
172
|
+
moveBackSectionsIntoContainer(doc, backmatterContainer) {
|
|
153
173
|
for (const section of doc.querySelectorAll('back > sec')) {
|
|
154
174
|
removeNodeFromParent(section);
|
|
155
|
-
|
|
175
|
+
backmatterContainer.appendChild(section);
|
|
156
176
|
}
|
|
177
|
+
},
|
|
178
|
+
moveAcknowledgmentsIntoContainer(doc, backmatterContainer, createElement) {
|
|
157
179
|
const ackNode = doc.querySelector('back > ack');
|
|
158
180
|
if (ackNode) {
|
|
159
181
|
const acknowledgements = this.createAcknowledgments(ackNode, createElement);
|
|
160
182
|
removeNodeFromParent(ackNode);
|
|
161
|
-
|
|
183
|
+
backmatterContainer.appendChild(acknowledgements);
|
|
162
184
|
}
|
|
185
|
+
},
|
|
186
|
+
moveAppendicesIntoContainer(doc, backmatterContainer, createElement) {
|
|
163
187
|
const appGroup = doc.querySelectorAll('back > app-group > app');
|
|
164
188
|
for (const app of appGroup) {
|
|
165
189
|
const appendix = this.createAppendixSection(app, createElement);
|
|
166
190
|
removeNodeFromParent(app);
|
|
167
|
-
|
|
191
|
+
backmatterContainer.appendChild(appendix);
|
|
168
192
|
}
|
|
193
|
+
},
|
|
194
|
+
moveBibliographyIntoContainer(doc, backmatterContainer, references, createElement) {
|
|
169
195
|
if (references) {
|
|
170
|
-
|
|
196
|
+
backmatterContainer.appendChild(this.createBibliography(doc, references, createElement));
|
|
171
197
|
}
|
|
172
198
|
},
|
|
173
|
-
|
|
199
|
+
moveSectionsToBody(doc, body, references, createElement) {
|
|
200
|
+
const bodyContainer = createSectionContainer('body', createElement);
|
|
201
|
+
const abstractsContainer = createSectionContainer('abstracts', createElement);
|
|
202
|
+
const backmatterContainer = createSectionContainer('backmatter', createElement);
|
|
203
|
+
this.mapFootnotesToSections(doc, backmatterContainer, createElement);
|
|
204
|
+
this.wrapBodySections(doc, bodyContainer);
|
|
205
|
+
this.moveAbstractsIntoContainer(doc, abstractsContainer, createElement);
|
|
206
|
+
this.moveBackSectionsIntoContainer(doc, backmatterContainer);
|
|
207
|
+
this.moveAcknowledgmentsIntoContainer(doc, backmatterContainer, createElement);
|
|
208
|
+
this.moveAppendicesIntoContainer(doc, backmatterContainer, createElement);
|
|
209
|
+
this.moveBibliographyIntoContainer(doc, backmatterContainer, references, createElement);
|
|
210
|
+
body.insertBefore(abstractsContainer, body.firstChild);
|
|
211
|
+
body.insertBefore(bodyContainer, abstractsContainer.nextSibling);
|
|
212
|
+
body.append(backmatterContainer);
|
|
213
|
+
},
|
|
214
|
+
mapFootnotesToSections(doc, backmatterContainer, createElement) {
|
|
174
215
|
const footnoteGroups = [...doc.querySelectorAll('fn[fn-type]')];
|
|
175
216
|
for (const footnote of footnoteGroups) {
|
|
176
217
|
const type = footnote.getAttribute('fn-type') || '';
|
|
@@ -187,7 +228,7 @@ export const jatsBodyTransformations = {
|
|
|
187
228
|
section.append(...footnote.children);
|
|
188
229
|
removeNodeFromParent(footnote);
|
|
189
230
|
section.setAttribute('sec-type', chooseSecType(category));
|
|
190
|
-
|
|
231
|
+
backmatterContainer.append(section);
|
|
191
232
|
}
|
|
192
233
|
}
|
|
193
234
|
const footnotes = [...doc.querySelectorAll('fn')];
|
|
@@ -202,7 +243,7 @@ export const jatsBodyTransformations = {
|
|
|
202
243
|
}
|
|
203
244
|
if (!footnotesSection && containingGroup.innerHTML) {
|
|
204
245
|
const section = this.createFootnotes([containingGroup], createElement);
|
|
205
|
-
|
|
246
|
+
backmatterContainer.append(section);
|
|
206
247
|
}
|
|
207
248
|
let regularFootnoteGroups = [
|
|
208
249
|
...doc.querySelectorAll('back > fn-group:not([fn-type])'),
|
|
@@ -215,7 +256,7 @@ export const jatsBodyTransformations = {
|
|
|
215
256
|
if (regularFootnoteGroups.length > 0) {
|
|
216
257
|
regularFootnoteGroups.map((g) => removeNodeFromParent(g));
|
|
217
258
|
const footnotes = this.createFootnotes(regularFootnoteGroups, createElement);
|
|
218
|
-
|
|
259
|
+
backmatterContainer.appendChild(footnotes);
|
|
219
260
|
}
|
|
220
261
|
},
|
|
221
262
|
moveCaptionsToEnd(body) {
|
|
@@ -111,7 +111,6 @@ export const parseJATSBody = (document, body, bibliographyItems, refModels, refe
|
|
|
111
111
|
const orderedFootnotesIDs = createOrderedFootnotesIDs(document);
|
|
112
112
|
jatsBodyTransformations.moveFloatsGroupToBody(document, body, createElement);
|
|
113
113
|
jatsBodyTransformations.ensureSection(body, createElement);
|
|
114
|
-
jatsBodyTransformations.mapFootnotesToSections(document, body, createElement);
|
|
115
114
|
jatsBodyTransformations.moveSectionsToBody(document, body, bibliographyItems, createElement);
|
|
116
115
|
jatsBodyTransformations.moveCaptionsToEnd(body);
|
|
117
116
|
jatsBodyTransformations.moveTableFooterToEnd(body);
|
|
@@ -129,8 +129,10 @@ export class JATSExporter {
|
|
|
129
129
|
article.appendChild(body);
|
|
130
130
|
const back = this.buildBack(body);
|
|
131
131
|
article.appendChild(back);
|
|
132
|
+
this.unwrapBody(body);
|
|
132
133
|
this.moveAbstracts(front, body);
|
|
133
134
|
this.moveFloatsGroup(body, article);
|
|
135
|
+
this.removeBackContainer(body);
|
|
134
136
|
}
|
|
135
137
|
await this.rewriteIDs(idGenerator);
|
|
136
138
|
if (mediaPathGenerator) {
|
|
@@ -1385,21 +1387,49 @@ export class JATSExporter {
|
|
|
1385
1387
|
table.insertBefore(tfoot, tbody);
|
|
1386
1388
|
}
|
|
1387
1389
|
};
|
|
1388
|
-
this.
|
|
1389
|
-
const
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
}
|
|
1397
|
-
const sectionTitle = section.querySelector(':scope > title');
|
|
1398
|
-
if (!sectionTitle) {
|
|
1399
|
-
return false;
|
|
1400
|
-
}
|
|
1401
|
-
return sectionTitle.textContent === 'Abstract';
|
|
1390
|
+
this.unwrapBody = (body) => {
|
|
1391
|
+
const container = body.querySelector(':scope > sec[sec-type="body"]');
|
|
1392
|
+
if (!container) {
|
|
1393
|
+
return;
|
|
1394
|
+
}
|
|
1395
|
+
const sections = container.querySelectorAll(':scope > sec');
|
|
1396
|
+
sections.forEach((section) => {
|
|
1397
|
+
body.appendChild(section.cloneNode(true));
|
|
1402
1398
|
});
|
|
1399
|
+
body.removeChild(container);
|
|
1400
|
+
};
|
|
1401
|
+
this.removeBackContainer = (body) => {
|
|
1402
|
+
const container = body.querySelector(':scope > sec[sec-type="backmatter"]');
|
|
1403
|
+
if (!container) {
|
|
1404
|
+
return;
|
|
1405
|
+
}
|
|
1406
|
+
const isContainerEmpty = container.children.length === 0;
|
|
1407
|
+
if (!isContainerEmpty) {
|
|
1408
|
+
warn('Backmatter section is not empty.');
|
|
1409
|
+
}
|
|
1410
|
+
body.removeChild(container);
|
|
1411
|
+
};
|
|
1412
|
+
this.moveAbstracts = (front, body) => {
|
|
1413
|
+
const container = body.querySelector(':scope > sec[sec-type="abstracts"]');
|
|
1414
|
+
let abstractSections;
|
|
1415
|
+
if (container) {
|
|
1416
|
+
abstractSections = Array.from(container.querySelectorAll(':scope > sec'));
|
|
1417
|
+
}
|
|
1418
|
+
else {
|
|
1419
|
+
abstractSections = Array.from(body.querySelectorAll(':scope > sec')).filter((section) => {
|
|
1420
|
+
const sectionType = section.getAttribute('sec-type');
|
|
1421
|
+
if (sectionType === 'abstract' ||
|
|
1422
|
+
sectionType === 'abstract-teaser' ||
|
|
1423
|
+
sectionType === 'abstract-graphical') {
|
|
1424
|
+
return true;
|
|
1425
|
+
}
|
|
1426
|
+
const sectionTitle = section.querySelector(':scope > title');
|
|
1427
|
+
if (!sectionTitle) {
|
|
1428
|
+
return false;
|
|
1429
|
+
}
|
|
1430
|
+
return sectionTitle.textContent === 'Abstract';
|
|
1431
|
+
});
|
|
1432
|
+
}
|
|
1403
1433
|
if (abstractSections.length) {
|
|
1404
1434
|
for (const abstractSection of abstractSections) {
|
|
1405
1435
|
const abstractNode = this.document.createElement('abstract');
|
|
@@ -1420,6 +1450,9 @@ export class JATSExporter {
|
|
|
1420
1450
|
}
|
|
1421
1451
|
}
|
|
1422
1452
|
}
|
|
1453
|
+
if (container) {
|
|
1454
|
+
body.removeChild(container);
|
|
1455
|
+
}
|
|
1423
1456
|
};
|
|
1424
1457
|
this.moveSectionsToBack = (back, body) => {
|
|
1425
1458
|
const availabilitySection = body.querySelector('sec[sec-type="availability"]');
|
|
@@ -32,7 +32,7 @@ const choosePageBreakStyle = (element) => {
|
|
|
32
32
|
return PAGE_BREAK_NONE;
|
|
33
33
|
};
|
|
34
34
|
export const section = {
|
|
35
|
-
content: 'section_label? section_title (paragraph | element)*
|
|
35
|
+
content: 'section_label? section_title (paragraph | element)* sections*',
|
|
36
36
|
attrs: {
|
|
37
37
|
id: { default: '' },
|
|
38
38
|
category: { default: '' },
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
import { DOMSerializer } from 'prosemirror-model';
|
|
17
17
|
import serializeToXML from 'w3c-xmlserializer';
|
|
18
18
|
import { iterateChildren } from '../lib/utils';
|
|
19
|
-
import { isHighlightMarkerNode, isSectionNode, schema, } from '../schema';
|
|
19
|
+
import { hasGroup, isHighlightMarkerNode, isSectionNode, schema, } from '../schema';
|
|
20
20
|
import { buildAttribution } from './builders';
|
|
21
21
|
import { extractHighlightMarkers, isHighlightableModel, } from './highlight-markers';
|
|
22
22
|
import { nodeTypesMap } from './node-types';
|
|
@@ -154,6 +154,15 @@ const childElements = (node) => {
|
|
|
154
154
|
});
|
|
155
155
|
return nodes;
|
|
156
156
|
};
|
|
157
|
+
const sectionChildElementIds = (node) => {
|
|
158
|
+
const nodes = [];
|
|
159
|
+
node.forEach((childNode) => {
|
|
160
|
+
if (!hasGroup(childNode.type, 'sections')) {
|
|
161
|
+
nodes.push(childNode);
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
return nodes.map((childNode) => childNode.attrs.id).filter((id) => id);
|
|
165
|
+
};
|
|
157
166
|
const attributeOfNodeType = (node, type, attribute) => {
|
|
158
167
|
for (const child of iterateChildren(node)) {
|
|
159
168
|
if (child.type.name === type) {
|
|
@@ -441,9 +450,7 @@ const encoders = {
|
|
|
441
450
|
label: inlineContentsOfNodeType(node, node.type.schema.nodes.section_label) ||
|
|
442
451
|
undefined,
|
|
443
452
|
path: path.concat([node.attrs.id]),
|
|
444
|
-
elementIDs:
|
|
445
|
-
.map((childNode) => childNode.attrs.id)
|
|
446
|
-
.filter((id) => id),
|
|
453
|
+
elementIDs: sectionChildElementIds(node),
|
|
447
454
|
titleSuppressed: node.attrs.titleSuppressed || undefined,
|
|
448
455
|
generatedLabel: node.attrs.generatedLabel || undefined,
|
|
449
456
|
pageBreakStyle: node.attrs.pageBreakStyle || undefined,
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
* See the License for the specific language governing permissions and
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
|
-
import
|
|
16
|
+
import sectionCategories from '@manuscripts/data/dist/shared/section-categories.json';
|
|
17
|
+
import { ObjectTypes, } from '@manuscripts/json-schema';
|
|
17
18
|
import { schema } from '../schema';
|
|
18
19
|
const sectionNodeTypes = [
|
|
19
20
|
schema.nodes.bibliography_section,
|
|
@@ -22,6 +23,17 @@ const sectionNodeTypes = [
|
|
|
22
23
|
schema.nodes.section,
|
|
23
24
|
schema.nodes.toc_section,
|
|
24
25
|
];
|
|
26
|
+
const sectionCategoriesMap = new Map(sectionCategories.map((section) => [
|
|
27
|
+
section._id,
|
|
28
|
+
section,
|
|
29
|
+
]));
|
|
30
|
+
export const getSectionTitles = (sectionCategory) => {
|
|
31
|
+
const category = sectionCategoriesMap.get(sectionCategory);
|
|
32
|
+
if (category) {
|
|
33
|
+
return category.titles.length ? category.titles : [' '];
|
|
34
|
+
}
|
|
35
|
+
throw new Error(`${sectionCategory} not found in section categories`);
|
|
36
|
+
};
|
|
25
37
|
export const isAnySectionNode = (node) => sectionNodeTypes.includes(node.type);
|
|
26
38
|
export const chooseSectionNodeType = (category) => {
|
|
27
39
|
switch (category) {
|
|
@@ -152,6 +164,12 @@ export const chooseSectionCategoryByType = (secType) => {
|
|
|
152
164
|
return 'MPSectionCategory:supported-by';
|
|
153
165
|
case 'ethics-statement':
|
|
154
166
|
return 'MPSectionCategory:ethics-statement';
|
|
167
|
+
case 'body':
|
|
168
|
+
return 'MPSectionCategory:body';
|
|
169
|
+
case 'backmatter':
|
|
170
|
+
return 'MPSectionCategory:backmatter';
|
|
171
|
+
case 'abstracts':
|
|
172
|
+
return 'MPSectionCategory:abstracts';
|
|
155
173
|
default:
|
|
156
174
|
return undefined;
|
|
157
175
|
}
|
|
@@ -22,8 +22,14 @@ export declare const jatsBodyTransformations: {
|
|
|
22
22
|
createFootnotes(footnoteGroups: Element[], createElement: (tagName: string) => HTMLElement): HTMLElement;
|
|
23
23
|
createAppendixSection(app: Element, createElement: (tagName: string) => HTMLElement): HTMLElement;
|
|
24
24
|
createFloatsGroupSection(floatsGroup: Element, createElement: (tagName: string) => HTMLElement): HTMLElement;
|
|
25
|
+
moveAbstractsIntoContainer(doc: Document, abstractsContainer: Element, createElement: (tagName: string) => HTMLElement): void;
|
|
26
|
+
wrapBodySections(doc: Document, bodyContainer: Element): void;
|
|
27
|
+
moveBackSectionsIntoContainer(doc: Document, backmatterContainer: Element): void;
|
|
28
|
+
moveAcknowledgmentsIntoContainer(doc: Document, backmatterContainer: Element, createElement: (tagName: string) => HTMLElement): void;
|
|
29
|
+
moveAppendicesIntoContainer(doc: Document, backmatterContainer: Element, createElement: (tagName: string) => HTMLElement): void;
|
|
30
|
+
moveBibliographyIntoContainer(doc: Document, backmatterContainer: Element, references: BibliographyItem[] | null, createElement: (tagName: string) => HTMLElement): void;
|
|
25
31
|
moveSectionsToBody(doc: Document, body: Element, references: BibliographyItem[] | null, createElement: (tagName: string) => HTMLElement): void;
|
|
26
|
-
mapFootnotesToSections(doc: Document,
|
|
32
|
+
mapFootnotesToSections(doc: Document, backmatterContainer: Element, createElement: (tagName: string) => HTMLElement): void;
|
|
27
33
|
moveCaptionsToEnd(body: Element): void;
|
|
28
34
|
moveTableFooterToEnd(body: Element): void;
|
|
29
35
|
moveFloatsGroupToBody(doc: Document, body: Element, createElement: (tagName: string) => HTMLElement): void;
|
|
@@ -63,6 +63,8 @@ export declare class JATSExporter {
|
|
|
63
63
|
private fixBody;
|
|
64
64
|
private changeTag;
|
|
65
65
|
private fixTable;
|
|
66
|
+
private unwrapBody;
|
|
67
|
+
private removeBackContainer;
|
|
66
68
|
private moveAbstracts;
|
|
67
69
|
private moveSectionsToBack;
|
|
68
70
|
sectionToFootnote: (section: Element, fnType: string) => HTMLElement;
|
|
@@ -15,9 +15,10 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import { Element } from '@manuscripts/json-schema';
|
|
17
17
|
import { ManuscriptNode, ManuscriptNodeType } from '../schema';
|
|
18
|
+
export declare const getSectionTitles: (sectionCategory: SectionCategory) => string[];
|
|
18
19
|
export declare const isAnySectionNode: (node: ManuscriptNode) => boolean;
|
|
19
|
-
export type SectionCategory = 'MPSectionCategory:abstract' | 'MPSectionCategory:abstract-teaser' | 'MPSectionCategory:abstract-graphical' | 'MPSectionCategory:acknowledgement' | 'MPSectionCategory:availability' | 'MPSectionCategory:bibliography' | 'MPSectionCategory:conclusions' | 'MPSectionCategory:discussion' | 'MPSectionCategory:endnotes' | 'MPSectionCategory:introduction' | 'MPSectionCategory:keywords' | 'MPSectionCategory:materials-method' | 'MPSectionCategory:results' | 'MPSectionCategory:toc' | 'MPSectionCategory:floating-element' | 'MPSectionCategory:appendices' | 'MPSectionCategory:competing-interests' | 'MPSectionCategory:financial-disclosure' | 'MPSectionCategory:con' | 'MPSectionCategory:deceased' | 'MPSectionCategory:equal' | 'MPSectionCategory:present-address' | 'MPSectionCategory:presented-at' | 'MPSectionCategory:previously-at' | 'MPSectionCategory:supplementary-material' | 'MPSectionCategory:supported-by' | 'MPSectionCategory:ethics-statement';
|
|
20
|
-
export type SecType = 'abstract' | 'abstract-teaser' | 'abstract-graphical' | 'acknowledgments' | 'availability' | 'bibliography' | 'conclusions' | 'data-availability' | 'discussion' | 'endnotes' | 'intro' | 'keywords' | 'materials' | 'methods' | 'results' | 'toc' | 'floating-element' | 'appendices' | 'competing-interests' | 'financial-disclosure' | 'con' | 'deceased' | 'equal' | 'present-address' | 'presented-at' | 'previously-at' | 'supplementary-material' | 'supported-by' | 'ethics-statement';
|
|
20
|
+
export type SectionCategory = 'MPSectionCategory:abstract' | 'MPSectionCategory:abstract-teaser' | 'MPSectionCategory:abstract-graphical' | 'MPSectionCategory:acknowledgement' | 'MPSectionCategory:availability' | 'MPSectionCategory:bibliography' | 'MPSectionCategory:conclusions' | 'MPSectionCategory:discussion' | 'MPSectionCategory:endnotes' | 'MPSectionCategory:introduction' | 'MPSectionCategory:keywords' | 'MPSectionCategory:materials-method' | 'MPSectionCategory:results' | 'MPSectionCategory:toc' | 'MPSectionCategory:floating-element' | 'MPSectionCategory:appendices' | 'MPSectionCategory:competing-interests' | 'MPSectionCategory:financial-disclosure' | 'MPSectionCategory:con' | 'MPSectionCategory:deceased' | 'MPSectionCategory:equal' | 'MPSectionCategory:present-address' | 'MPSectionCategory:presented-at' | 'MPSectionCategory:previously-at' | 'MPSectionCategory:supplementary-material' | 'MPSectionCategory:supported-by' | 'MPSectionCategory:ethics-statement' | 'MPSectionCategory:body' | 'MPSectionCategory:abstracts' | 'MPSectionCategory:backmatter';
|
|
21
|
+
export type SecType = 'abstract' | 'abstract-teaser' | 'abstract-graphical' | 'acknowledgments' | 'availability' | 'bibliography' | 'conclusions' | 'data-availability' | 'discussion' | 'endnotes' | 'intro' | 'keywords' | 'materials' | 'methods' | 'results' | 'toc' | 'floating-element' | 'appendices' | 'competing-interests' | 'financial-disclosure' | 'con' | 'deceased' | 'equal' | 'present-address' | 'presented-at' | 'previously-at' | 'supplementary-material' | 'supported-by' | 'ethics-statement' | 'abstracts' | 'body' | 'backmatter';
|
|
21
22
|
export declare const chooseSectionNodeType: (category?: SectionCategory) => ManuscriptNodeType;
|
|
22
23
|
export declare const chooseSectionLableName: (type?: SecType) => string;
|
|
23
24
|
export declare const guessSectionCategory: (elements: Element[]) => SectionCategory | undefined;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@manuscripts/transform",
|
|
3
3
|
"description": "ProseMirror transformer for Manuscripts applications",
|
|
4
|
-
"version": "1.2.
|
|
4
|
+
"version": "1.2.5",
|
|
5
5
|
"repository": "github:Atypon-OpenSource/manuscripts-transform",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"main": "dist/cjs",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"version": "yarn build"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@manuscripts/json-schema": "^2.0.
|
|
32
|
+
"@manuscripts/json-schema": "^2.0.2",
|
|
33
33
|
"debug": "^4.3.4",
|
|
34
34
|
"jszip": "^3.10.1",
|
|
35
35
|
"mathjax-full": "^3.2.2",
|