@manuscripts/transform 4.5.6 → 4.5.8

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.
@@ -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
21
  const libxmljs2_1 = require("libxmljs2");
22
+ const w3c_xmlserializer_1 = __importDefault(require("w3c-xmlserializer"));
19
23
  const jats_exporter_1 = require("../exporter/jats-exporter");
20
24
  const parse_jats_article_1 = require("../importer/parse-jats-article");
21
25
  const citations_1 = require("./citations");
@@ -32,10 +36,10 @@ describe('JATS exporter', () => {
32
36
  const transformer = new jats_exporter_1.JATSExporter();
33
37
  const input = await (0, files_1.readAndParseFixture)('jats-example-full.xml');
34
38
  const node = (0, parse_jats_article_1.parseJATSArticle)(input, section_categories_1.sectionCategories);
35
- const result = await transformer.serializeToJATS(node, {
39
+ const document = await transformer.export(node, {
36
40
  csl: citations_1.DEFAULT_CSL_OPTIONS,
37
41
  });
38
- expect(result).toMatchSnapshot('jats-export');
42
+ expect((0, w3c_xmlserializer_1.default)(document)).toMatchSnapshot('jats-export');
39
43
  });
40
44
  test('export with & and < in bibliography metadata', async () => {
41
45
  const transformer = new jats_exporter_1.JATSExporter();
@@ -48,27 +52,27 @@ describe('JATS exporter', () => {
48
52
  }
49
53
  });
50
54
  biblio.attrs.title += ' & Sons 55 < 135';
51
- const result = await transformer.serializeToJATS(node, {
55
+ const document = await transformer.export(node, {
52
56
  csl: citations_1.DEFAULT_CSL_OPTIONS,
53
57
  });
54
- expect(result).toMatchSnapshot('jats-export-with-xml-unsafe-in-biblios');
58
+ expect((0, w3c_xmlserializer_1.default)(document)).toMatchSnapshot('jats-export-with-xml-unsafe-in-biblios');
55
59
  });
56
60
  test('export v1.1', async () => {
57
61
  const transformer = new jats_exporter_1.JATSExporter();
58
62
  const input = await (0, files_1.readAndParseFixture)('jats-example-full.xml');
59
63
  const node = (0, parse_jats_article_1.parseJATSArticle)(input, section_categories_1.sectionCategories);
60
- const result = await transformer.serializeToJATS(node, {
64
+ const document = await transformer.export(node, {
61
65
  csl: citations_1.DEFAULT_CSL_OPTIONS,
62
66
  version: '1.1',
63
67
  });
64
- expect(result).toMatchSnapshot('jats-export-1.1');
68
+ expect((0, w3c_xmlserializer_1.default)(document)).toMatchSnapshot('jats-export-1.1');
65
69
  });
66
70
  test('export unknown version', async () => {
67
71
  const transformer = new jats_exporter_1.JATSExporter();
68
72
  const input = await (0, files_1.readAndParseFixture)('jats-example-full.xml');
69
73
  const node = (0, parse_jats_article_1.parseJATSArticle)(input, section_categories_1.sectionCategories);
70
74
  await expect(async () => {
71
- await transformer.serializeToJATS(node, {
75
+ await transformer.export(node, {
72
76
  csl: citations_1.DEFAULT_CSL_OPTIONS,
73
77
  version: '1.0',
74
78
  });
@@ -78,9 +82,10 @@ describe('JATS exporter', () => {
78
82
  const transformer = new jats_exporter_1.JATSExporter();
79
83
  const input = await (0, files_1.readAndParseFixture)('jats-tables-example.xml');
80
84
  const node = (0, parse_jats_article_1.parseJATSArticle)(input, section_categories_1.sectionCategories);
81
- const xml = await transformer.serializeToJATS(node, {
85
+ const document = await transformer.export(node, {
82
86
  csl: citations_1.DEFAULT_CSL_OPTIONS,
83
87
  });
88
+ const xml = (0, w3c_xmlserializer_1.default)(document);
84
89
  const resultDoc = parseXMLWithDTD(xml);
85
90
  const tableWrapFoot = resultDoc.get('//table-wrap/table-wrap-foot');
86
91
  const paragraph = resultDoc.get('//table-wrap/table-wrap-foot/p');
@@ -91,30 +96,30 @@ describe('JATS exporter', () => {
91
96
  const transformer = new jats_exporter_1.JATSExporter();
92
97
  const input = await (0, files_1.readAndParseFixture)('jats-import.xml');
93
98
  const node = (0, parse_jats_article_1.parseJATSArticle)(input, section_categories_1.sectionCategories);
94
- const xml = await transformer.serializeToJATS(node, {
99
+ const document = await transformer.export(node, {
95
100
  csl: citations_1.DEFAULT_CSL_OPTIONS,
96
101
  });
97
- const { errors } = parseXMLWithDTD(xml);
102
+ const { errors } = parseXMLWithDTD((0, w3c_xmlserializer_1.default)(document));
98
103
  expect(errors).toHaveLength(0);
99
104
  });
100
105
  test('DTD validation: article with title markup and citations', async () => {
101
106
  const transformer = new jats_exporter_1.JATSExporter();
102
107
  const input = await (0, files_1.readAndParseFixture)('jats-document.xml');
103
108
  const node = (0, parse_jats_article_1.parseJATSArticle)(input, section_categories_1.sectionCategories);
104
- const xml = await transformer.serializeToJATS(node, {
109
+ const document = await transformer.export(node, {
105
110
  csl: citations_1.DEFAULT_CSL_OPTIONS,
106
111
  });
107
- const { errors } = parseXMLWithDTD(xml);
112
+ const { errors } = parseXMLWithDTD((0, w3c_xmlserializer_1.default)(document));
108
113
  expect(errors).toHaveLength(0);
109
114
  });
110
115
  test('Export link', async () => {
111
116
  const transformer = new jats_exporter_1.JATSExporter();
112
117
  const input = await (0, files_1.readAndParseFixture)('jats-import.xml');
113
118
  const node = (0, parse_jats_article_1.parseJATSArticle)(input, section_categories_1.sectionCategories);
114
- const xml = await transformer.serializeToJATS(node, {
119
+ const document = await transformer.export(node, {
115
120
  csl: citations_1.DEFAULT_CSL_OPTIONS,
116
121
  });
117
- const output = parseXMLWithDTD(xml);
122
+ const output = parseXMLWithDTD((0, w3c_xmlserializer_1.default)(document));
118
123
  const link = output.get('//ext-link[@ext-link-type="uri"]');
119
124
  expect(link).not.toBeNull();
120
125
  expect(link.text()).toBe('https//orcid.org/0000-0003-2217-5904');
@@ -129,20 +134,20 @@ describe('JATS exporter', () => {
129
134
  const transformer = new jats_exporter_1.JATSExporter();
130
135
  const input = await (0, files_1.readAndParseFixture)('jats-example-doc.xml');
131
136
  const node = (0, parse_jats_article_1.parseJATSArticle)(input, section_categories_1.sectionCategories);
132
- const xml = await transformer.serializeToJATS(node, {
137
+ const document = await transformer.export(node, {
133
138
  csl: citations_1.DEFAULT_CSL_OPTIONS,
134
139
  });
135
- const { errors } = parseXMLWithDTD(xml);
140
+ const { errors } = parseXMLWithDTD((0, w3c_xmlserializer_1.default)(document));
136
141
  expect(errors).toHaveLength(0);
137
142
  });
138
143
  test('export with supplement', async () => {
139
144
  const transformer = new jats_exporter_1.JATSExporter();
140
145
  const input = await (0, files_1.readAndParseFixture)('jats-import.xml');
141
146
  const node = (0, parse_jats_article_1.parseJATSArticle)(input, section_categories_1.sectionCategories);
142
- const xml = await transformer.serializeToJATS(node, {
147
+ const document = await transformer.export(node, {
143
148
  csl: citations_1.DEFAULT_CSL_OPTIONS,
144
149
  });
145
- const resultDoc = parseXMLWithDTD(xml);
150
+ const resultDoc = parseXMLWithDTD((0, w3c_xmlserializer_1.default)(document));
146
151
  const supplementaryMaterial = resultDoc.get('//supplementary-material');
147
152
  if (!supplementaryMaterial) {
148
153
  throw new Error('No supplementary material found');
@@ -169,9 +174,10 @@ describe('JATS exporter', () => {
169
174
  n.attrs.rids.forEach((rid) => citedIDs.add(rid));
170
175
  }
171
176
  });
172
- const xml = await new jats_exporter_1.JATSExporter().serializeToJATS(node, {
177
+ const document = await new jats_exporter_1.JATSExporter().export(node, {
173
178
  csl: citations_1.DEFAULT_CSL_OPTIONS,
174
179
  });
180
+ const xml = (0, w3c_xmlserializer_1.default)(document);
175
181
  const refCount = parseXMLWithDTD(xml).find('//ref-list/ref').length;
176
182
  expect(refCount).toBe(bibliographyItemIDs.size);
177
183
  const { errors } = parseXMLWithDTD(xml);
@@ -181,9 +187,10 @@ describe('JATS exporter', () => {
181
187
  const transformer = new jats_exporter_1.JATSExporter();
182
188
  const input = await (0, files_1.readAndParseFixture)('jats-fn-group.xml');
183
189
  const node = (0, parse_jats_article_1.parseJATSArticle)(input, section_categories_1.sectionCategories);
184
- const xml = await transformer.serializeToJATS(node, {
190
+ const document = await transformer.export(node, {
185
191
  csl: citations_1.DEFAULT_CSL_OPTIONS,
186
192
  });
193
+ const xml = (0, w3c_xmlserializer_1.default)(document);
187
194
  const footnoteCategories = [
188
195
  'con',
189
196
  'deceased',
@@ -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
21
  const libxmljs2_1 = require("libxmljs2");
22
+ const w3c_xmlserializer_1 = __importDefault(require("w3c-xmlserializer"));
19
23
  const jats_exporter_1 = require("../exporter/jats-exporter");
20
24
  const parse_jats_article_1 = require("../importer/parse-jats-article");
21
25
  const citations_1 = require("./citations");
@@ -31,9 +35,10 @@ const roundtrip = async (filename) => {
31
35
  const doc = new DOMParser().parseFromString(input, 'application/xml');
32
36
  const node = (0, parse_jats_article_1.parseJATSArticle)(doc, section_categories_1.sectionCategories);
33
37
  const exporter = new jats_exporter_1.JATSExporter();
34
- return await exporter.serializeToJATS(node, {
38
+ const document = await exporter.export(node, {
35
39
  csl: citations_1.DEFAULT_CSL_OPTIONS,
36
40
  });
41
+ return (0, w3c_xmlserializer_1.default)(document);
37
42
  };
38
43
  describe('JATS roundtrip', () => {
39
44
  test('jats-import.xml roundtrip', async () => {
@@ -47,15 +47,11 @@ var __importStar = (this && this.__importStar) || (function () {
47
47
  return result;
48
48
  };
49
49
  })();
50
- var __importDefault = (this && this.__importDefault) || function (mod) {
51
- return (mod && mod.__esModule) ? mod : { "default": mod };
52
- };
53
50
  Object.defineProperty(exports, "__esModule", { value: true });
54
51
  exports.JATSExporter = exports.createCounter = void 0;
55
52
  const Citeproc = __importStar(require("citeproc"));
56
53
  const prosemirror_model_1 = require("prosemirror-model");
57
54
  const prosemirror_utils_1 = require("prosemirror-utils");
58
- const w3c_xmlserializer_1 = __importDefault(require("w3c-xmlserializer"));
59
55
  const citeproc_1 = require("../../lib/citeproc");
60
56
  const credit_roles_1 = require("../../lib/credit-roles");
61
57
  const footnotes_1 = require("../../lib/footnotes");
@@ -118,7 +114,7 @@ class JATSExporter {
118
114
  this.nodesMap.set(type, nodes);
119
115
  });
120
116
  };
121
- this.serializeToJATS = async (manuscriptNode, options) => {
117
+ this.export = async (manuscriptNode, options) => {
122
118
  this.manuscriptNode = manuscriptNode;
123
119
  this.populateNodesMap();
124
120
  this.initCiteprocEngine(options);
@@ -149,7 +145,7 @@ class JATSExporter {
149
145
  $article.appendChild($floatsGroup);
150
146
  }
151
147
  await this.rewriteIDs();
152
- return (0, w3c_xmlserializer_1.default)(this.document);
148
+ return this.document;
153
149
  };
154
150
  this.appendChildNodeOfType = ($element, node, type) => {
155
151
  const childNode = this.getFirstChildOfType(type, node);
@@ -440,7 +436,7 @@ class JATSExporter {
440
436
  const [, bibliography] = this.engine.makeBibliography();
441
437
  const parser = new DOMParser();
442
438
  bibliography.forEach((item) => {
443
- const fragment = `<template xmlns:xlink="${xml_1.XLINK_NAMESPACE}">${(0, xml_1.sanitizeXmlString)(item)}</template>`;
439
+ const fragment = `<wrapper xmlns:xlink="${xml_1.XLINK_NAMESPACE}">${(0, xml_1.sanitizeXmlString)(item)}</wrapper>`;
444
440
  const $ref = parser
445
441
  .parseFromString(fragment, 'text/xml')
446
442
  .querySelector('ref');
@@ -502,7 +498,7 @@ class JATSExporter {
502
498
  attachments: () => '',
503
499
  image_element: (node) => createImage(node),
504
500
  embed: (node) => {
505
- const { id, href, mimetype, mimeSubtype } = node.attrs;
501
+ const { id, href, mimetype, mimeSubtype, extLinks } = node.attrs;
506
502
  if (!href) {
507
503
  return '';
508
504
  }
@@ -520,6 +516,22 @@ class JATSExporter {
520
516
  this.appendChildNodeOfType($media, node, schema_1.schema.nodes.alt_text);
521
517
  this.appendChildNodeOfType($media, node, schema_1.schema.nodes.long_desc);
522
518
  this.appendCaption($media, node);
519
+ if (extLinks && extLinks.length > 0) {
520
+ extLinks.forEach((extLink) => {
521
+ if (extLink.href) {
522
+ const extLinkElement = this.createElement('ext-link');
523
+ extLinkElement.setAttribute('ext-link-type', extLink.type);
524
+ extLinkElement.setAttributeNS(xml_1.XLINK_NAMESPACE, 'href', extLink.href);
525
+ if (extLink.lang) {
526
+ extLinkElement.setAttributeNS(xml_1.XML_NAMESPACE, 'lang', extLink.lang);
527
+ }
528
+ if (extLink.label) {
529
+ extLinkElement.textContent = extLink.label;
530
+ }
531
+ $media.appendChild(extLinkElement);
532
+ }
533
+ });
534
+ }
523
535
  return $media;
524
536
  },
525
537
  awards: () => ['funding-group', 0],
@@ -566,6 +566,11 @@ class JATSDOMParser {
566
566
  context: 'pullquote_element/',
567
567
  getAttrs: this.getFigAttrs,
568
568
  },
569
+ {
570
+ tag: 'ext-link',
571
+ context: 'embed/',
572
+ ignore: true,
573
+ },
569
574
  {
570
575
  tag: 'ext-link',
571
576
  node: 'link',
@@ -592,11 +597,21 @@ class JATSDOMParser {
592
597
  node: 'embed',
593
598
  getAttrs: (node) => {
594
599
  const element = node;
600
+ const extLinkElements = element.querySelectorAll('ext-link');
601
+ const extLinks = Array.from(extLinkElements)
602
+ .map((extLinkElement) => ({
603
+ type: extLinkElement.getAttribute('ext-link-type') || '',
604
+ href: extLinkElement.getAttributeNS(xml_1.XLINK_NAMESPACE, 'href') || '',
605
+ lang: extLinkElement.getAttributeNS(xml_1.XML_NAMESPACE, 'lang') || '',
606
+ label: (0, utils_1.getTrimmedTextContent)(extLinkElement) || undefined,
607
+ }))
608
+ .filter((extLink) => extLink.href);
595
609
  return {
596
610
  id: element.getAttribute('id'),
597
611
  href: element.getAttributeNS(xml_1.XLINK_NAMESPACE, 'href'),
598
612
  mimetype: element.getAttribute('mimetype'),
599
613
  mimeSubtype: element.getAttribute('mime-subtype'),
614
+ extLinks: extLinks.length > 0 ? extLinks : undefined,
600
615
  };
601
616
  },
602
617
  },
@@ -25,6 +25,7 @@ exports.embed = {
25
25
  mimetype: { default: undefined },
26
26
  mimeSubtype: { default: undefined },
27
27
  longDesc: { default: '' },
28
+ extLinks: { default: [] },
28
29
  },
29
30
  group: 'block element',
30
31
  toDOM: (node) => {
@@ -1,4 +1,4 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VERSION = void 0;
4
- exports.VERSION = "4.5.6";
4
+ exports.VERSION = "4.5.8";
@@ -14,6 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
  import { parseXml } from 'libxmljs2';
17
+ import serializeToXML from 'w3c-xmlserializer';
17
18
  import { JATSExporter } from '../exporter/jats-exporter';
18
19
  import { parseJATSArticle } from '../importer/parse-jats-article';
19
20
  import { DEFAULT_CSL_OPTIONS } from './citations';
@@ -30,10 +31,10 @@ describe('JATS exporter', () => {
30
31
  const transformer = new JATSExporter();
31
32
  const input = await readAndParseFixture('jats-example-full.xml');
32
33
  const node = parseJATSArticle(input, sectionCategories);
33
- const result = await transformer.serializeToJATS(node, {
34
+ const document = await transformer.export(node, {
34
35
  csl: DEFAULT_CSL_OPTIONS,
35
36
  });
36
- expect(result).toMatchSnapshot('jats-export');
37
+ expect(serializeToXML(document)).toMatchSnapshot('jats-export');
37
38
  });
38
39
  test('export with & and < in bibliography metadata', async () => {
39
40
  const transformer = new JATSExporter();
@@ -46,27 +47,27 @@ describe('JATS exporter', () => {
46
47
  }
47
48
  });
48
49
  biblio.attrs.title += ' & Sons 55 < 135';
49
- const result = await transformer.serializeToJATS(node, {
50
+ const document = await transformer.export(node, {
50
51
  csl: DEFAULT_CSL_OPTIONS,
51
52
  });
52
- expect(result).toMatchSnapshot('jats-export-with-xml-unsafe-in-biblios');
53
+ expect(serializeToXML(document)).toMatchSnapshot('jats-export-with-xml-unsafe-in-biblios');
53
54
  });
54
55
  test('export v1.1', async () => {
55
56
  const transformer = new JATSExporter();
56
57
  const input = await readAndParseFixture('jats-example-full.xml');
57
58
  const node = parseJATSArticle(input, sectionCategories);
58
- const result = await transformer.serializeToJATS(node, {
59
+ const document = await transformer.export(node, {
59
60
  csl: DEFAULT_CSL_OPTIONS,
60
61
  version: '1.1',
61
62
  });
62
- expect(result).toMatchSnapshot('jats-export-1.1');
63
+ expect(serializeToXML(document)).toMatchSnapshot('jats-export-1.1');
63
64
  });
64
65
  test('export unknown version', async () => {
65
66
  const transformer = new JATSExporter();
66
67
  const input = await readAndParseFixture('jats-example-full.xml');
67
68
  const node = parseJATSArticle(input, sectionCategories);
68
69
  await expect(async () => {
69
- await transformer.serializeToJATS(node, {
70
+ await transformer.export(node, {
70
71
  csl: DEFAULT_CSL_OPTIONS,
71
72
  version: '1.0',
72
73
  });
@@ -76,9 +77,10 @@ describe('JATS exporter', () => {
76
77
  const transformer = new JATSExporter();
77
78
  const input = await readAndParseFixture('jats-tables-example.xml');
78
79
  const node = parseJATSArticle(input, sectionCategories);
79
- const xml = await transformer.serializeToJATS(node, {
80
+ const document = await transformer.export(node, {
80
81
  csl: DEFAULT_CSL_OPTIONS,
81
82
  });
83
+ const xml = serializeToXML(document);
82
84
  const resultDoc = parseXMLWithDTD(xml);
83
85
  const tableWrapFoot = resultDoc.get('//table-wrap/table-wrap-foot');
84
86
  const paragraph = resultDoc.get('//table-wrap/table-wrap-foot/p');
@@ -89,30 +91,30 @@ describe('JATS exporter', () => {
89
91
  const transformer = new JATSExporter();
90
92
  const input = await readAndParseFixture('jats-import.xml');
91
93
  const node = parseJATSArticle(input, sectionCategories);
92
- const xml = await transformer.serializeToJATS(node, {
94
+ const document = await transformer.export(node, {
93
95
  csl: DEFAULT_CSL_OPTIONS,
94
96
  });
95
- const { errors } = parseXMLWithDTD(xml);
97
+ const { errors } = parseXMLWithDTD(serializeToXML(document));
96
98
  expect(errors).toHaveLength(0);
97
99
  });
98
100
  test('DTD validation: article with title markup and citations', async () => {
99
101
  const transformer = new JATSExporter();
100
102
  const input = await readAndParseFixture('jats-document.xml');
101
103
  const node = parseJATSArticle(input, sectionCategories);
102
- const xml = await transformer.serializeToJATS(node, {
104
+ const document = await transformer.export(node, {
103
105
  csl: DEFAULT_CSL_OPTIONS,
104
106
  });
105
- const { errors } = parseXMLWithDTD(xml);
107
+ const { errors } = parseXMLWithDTD(serializeToXML(document));
106
108
  expect(errors).toHaveLength(0);
107
109
  });
108
110
  test('Export link', async () => {
109
111
  const transformer = new JATSExporter();
110
112
  const input = await readAndParseFixture('jats-import.xml');
111
113
  const node = parseJATSArticle(input, sectionCategories);
112
- const xml = await transformer.serializeToJATS(node, {
114
+ const document = await transformer.export(node, {
113
115
  csl: DEFAULT_CSL_OPTIONS,
114
116
  });
115
- const output = parseXMLWithDTD(xml);
117
+ const output = parseXMLWithDTD(serializeToXML(document));
116
118
  const link = output.get('//ext-link[@ext-link-type="uri"]');
117
119
  expect(link).not.toBeNull();
118
120
  expect(link.text()).toBe('https//orcid.org/0000-0003-2217-5904');
@@ -127,20 +129,20 @@ describe('JATS exporter', () => {
127
129
  const transformer = new JATSExporter();
128
130
  const input = await readAndParseFixture('jats-example-doc.xml');
129
131
  const node = parseJATSArticle(input, sectionCategories);
130
- const xml = await transformer.serializeToJATS(node, {
132
+ const document = await transformer.export(node, {
131
133
  csl: DEFAULT_CSL_OPTIONS,
132
134
  });
133
- const { errors } = parseXMLWithDTD(xml);
135
+ const { errors } = parseXMLWithDTD(serializeToXML(document));
134
136
  expect(errors).toHaveLength(0);
135
137
  });
136
138
  test('export with supplement', async () => {
137
139
  const transformer = new JATSExporter();
138
140
  const input = await readAndParseFixture('jats-import.xml');
139
141
  const node = parseJATSArticle(input, sectionCategories);
140
- const xml = await transformer.serializeToJATS(node, {
142
+ const document = await transformer.export(node, {
141
143
  csl: DEFAULT_CSL_OPTIONS,
142
144
  });
143
- const resultDoc = parseXMLWithDTD(xml);
145
+ const resultDoc = parseXMLWithDTD(serializeToXML(document));
144
146
  const supplementaryMaterial = resultDoc.get('//supplementary-material');
145
147
  if (!supplementaryMaterial) {
146
148
  throw new Error('No supplementary material found');
@@ -167,9 +169,10 @@ describe('JATS exporter', () => {
167
169
  n.attrs.rids.forEach((rid) => citedIDs.add(rid));
168
170
  }
169
171
  });
170
- const xml = await new JATSExporter().serializeToJATS(node, {
172
+ const document = await new JATSExporter().export(node, {
171
173
  csl: DEFAULT_CSL_OPTIONS,
172
174
  });
175
+ const xml = serializeToXML(document);
173
176
  const refCount = parseXMLWithDTD(xml).find('//ref-list/ref').length;
174
177
  expect(refCount).toBe(bibliographyItemIDs.size);
175
178
  const { errors } = parseXMLWithDTD(xml);
@@ -179,9 +182,10 @@ describe('JATS exporter', () => {
179
182
  const transformer = new JATSExporter();
180
183
  const input = await readAndParseFixture('jats-fn-group.xml');
181
184
  const node = parseJATSArticle(input, sectionCategories);
182
- const xml = await transformer.serializeToJATS(node, {
185
+ const document = await transformer.export(node, {
183
186
  csl: DEFAULT_CSL_OPTIONS,
184
187
  });
188
+ const xml = serializeToXML(document);
185
189
  const footnoteCategories = [
186
190
  'con',
187
191
  'deceased',
@@ -14,6 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
  import { parseXml } from 'libxmljs2';
17
+ import serializeToXML from 'w3c-xmlserializer';
17
18
  import { JATSExporter } from '../exporter/jats-exporter';
18
19
  import { parseJATSArticle } from '../importer/parse-jats-article';
19
20
  import { DEFAULT_CSL_OPTIONS } from './citations';
@@ -29,9 +30,10 @@ const roundtrip = async (filename) => {
29
30
  const doc = new DOMParser().parseFromString(input, 'application/xml');
30
31
  const node = parseJATSArticle(doc, sectionCategories);
31
32
  const exporter = new JATSExporter();
32
- return await exporter.serializeToJATS(node, {
33
+ const document = await exporter.export(node, {
33
34
  csl: DEFAULT_CSL_OPTIONS,
34
35
  });
36
+ return serializeToXML(document);
35
37
  };
36
38
  describe('JATS roundtrip', () => {
37
39
  test('jats-import.xml roundtrip', async () => {
@@ -16,7 +16,6 @@
16
16
  import * as Citeproc from 'citeproc';
17
17
  import { DOMSerializer } from 'prosemirror-model';
18
18
  import { findChildrenByAttr, findChildrenByType } from 'prosemirror-utils';
19
- import serializeToXML from 'w3c-xmlserializer';
20
19
  import { buildCiteprocCitation } from '../../lib/citeproc';
21
20
  import { CreditRoleUrls } from '../../lib/credit-roles';
22
21
  import { generateFootnoteLabels } from '../../lib/footnotes';
@@ -78,7 +77,7 @@ export class JATSExporter {
78
77
  this.nodesMap.set(type, nodes);
79
78
  });
80
79
  };
81
- this.serializeToJATS = async (manuscriptNode, options) => {
80
+ this.export = async (manuscriptNode, options) => {
82
81
  this.manuscriptNode = manuscriptNode;
83
82
  this.populateNodesMap();
84
83
  this.initCiteprocEngine(options);
@@ -109,7 +108,7 @@ export class JATSExporter {
109
108
  $article.appendChild($floatsGroup);
110
109
  }
111
110
  await this.rewriteIDs();
112
- return serializeToXML(this.document);
111
+ return this.document;
113
112
  };
114
113
  this.appendChildNodeOfType = ($element, node, type) => {
115
114
  const childNode = this.getFirstChildOfType(type, node);
@@ -400,7 +399,7 @@ export class JATSExporter {
400
399
  const [, bibliography] = this.engine.makeBibliography();
401
400
  const parser = new DOMParser();
402
401
  bibliography.forEach((item) => {
403
- const fragment = `<template xmlns:xlink="${XLINK_NAMESPACE}">${sanitizeXmlString(item)}</template>`;
402
+ const fragment = `<wrapper xmlns:xlink="${XLINK_NAMESPACE}">${sanitizeXmlString(item)}</wrapper>`;
404
403
  const $ref = parser
405
404
  .parseFromString(fragment, 'text/xml')
406
405
  .querySelector('ref');
@@ -462,7 +461,7 @@ export class JATSExporter {
462
461
  attachments: () => '',
463
462
  image_element: (node) => createImage(node),
464
463
  embed: (node) => {
465
- const { id, href, mimetype, mimeSubtype } = node.attrs;
464
+ const { id, href, mimetype, mimeSubtype, extLinks } = node.attrs;
466
465
  if (!href) {
467
466
  return '';
468
467
  }
@@ -480,6 +479,22 @@ export class JATSExporter {
480
479
  this.appendChildNodeOfType($media, node, schema.nodes.alt_text);
481
480
  this.appendChildNodeOfType($media, node, schema.nodes.long_desc);
482
481
  this.appendCaption($media, node);
482
+ if (extLinks && extLinks.length > 0) {
483
+ extLinks.forEach((extLink) => {
484
+ if (extLink.href) {
485
+ const extLinkElement = this.createElement('ext-link');
486
+ extLinkElement.setAttribute('ext-link-type', extLink.type);
487
+ extLinkElement.setAttributeNS(XLINK_NAMESPACE, 'href', extLink.href);
488
+ if (extLink.lang) {
489
+ extLinkElement.setAttributeNS(XML_NAMESPACE, 'lang', extLink.lang);
490
+ }
491
+ if (extLink.label) {
492
+ extLinkElement.textContent = extLink.label;
493
+ }
494
+ $media.appendChild(extLinkElement);
495
+ }
496
+ });
497
+ }
483
498
  return $media;
484
499
  },
485
500
  awards: () => ['funding-group', 0],
@@ -563,6 +563,11 @@ export class JATSDOMParser {
563
563
  context: 'pullquote_element/',
564
564
  getAttrs: this.getFigAttrs,
565
565
  },
566
+ {
567
+ tag: 'ext-link',
568
+ context: 'embed/',
569
+ ignore: true,
570
+ },
566
571
  {
567
572
  tag: 'ext-link',
568
573
  node: 'link',
@@ -589,11 +594,21 @@ export class JATSDOMParser {
589
594
  node: 'embed',
590
595
  getAttrs: (node) => {
591
596
  const element = node;
597
+ const extLinkElements = element.querySelectorAll('ext-link');
598
+ const extLinks = Array.from(extLinkElements)
599
+ .map((extLinkElement) => ({
600
+ type: extLinkElement.getAttribute('ext-link-type') || '',
601
+ href: extLinkElement.getAttributeNS(XLINK_NAMESPACE, 'href') || '',
602
+ lang: extLinkElement.getAttributeNS(XML_NAMESPACE, 'lang') || '',
603
+ label: getTrimmedTextContent(extLinkElement) || undefined,
604
+ }))
605
+ .filter((extLink) => extLink.href);
592
606
  return {
593
607
  id: element.getAttribute('id'),
594
608
  href: element.getAttributeNS(XLINK_NAMESPACE, 'href'),
595
609
  mimetype: element.getAttribute('mimetype'),
596
610
  mimeSubtype: element.getAttribute('mime-subtype'),
611
+ extLinks: extLinks.length > 0 ? extLinks : undefined,
597
612
  };
598
613
  },
599
614
  },
@@ -22,6 +22,7 @@ export const embed = {
22
22
  mimetype: { default: undefined },
23
23
  mimeSubtype: { default: undefined },
24
24
  longDesc: { default: '' },
25
+ extLinks: { default: [] },
25
26
  },
26
27
  group: 'block element',
27
28
  toDOM: (node) => {
@@ -1 +1 @@
1
- export const VERSION = "4.5.6";
1
+ export const VERSION = "4.5.8";
@@ -42,7 +42,7 @@ export declare class JATSExporter {
42
42
  private populateNodesMap;
43
43
  protected getFirstChildOfType<T extends ManuscriptNode>(type: NodeType, node?: ManuscriptNode): T | undefined;
44
44
  protected getChildrenOfType<T extends ManuscriptNode>(type: NodeType, node?: ManuscriptNode): T[];
45
- serializeToJATS: (manuscriptNode: ActualManuscriptNode, options: ExportOptions) => Promise<string>;
45
+ export: (manuscriptNode: ActualManuscriptNode, options: ExportOptions) => Promise<Document>;
46
46
  private appendChildNodeOfType;
47
47
  private appendChildrenNodeOfType;
48
48
  protected appendCaption: ($element: Element, node: ManuscriptNode) => void;
@@ -15,11 +15,18 @@
15
15
  */
16
16
  import { NodeSpec } from 'prosemirror-model';
17
17
  import { ManuscriptNode } from '../types';
18
+ export interface ExtLink {
19
+ type: string;
20
+ href: string;
21
+ lang: string;
22
+ label?: string;
23
+ }
18
24
  export interface EmbedAttrs {
19
25
  id: string;
20
26
  href: string;
21
27
  mimetype: string;
22
28
  mimeSubtype: string;
29
+ extLinks?: ExtLink[];
23
30
  }
24
31
  export interface EmbedNode extends ManuscriptNode {
25
32
  attrs: EmbedAttrs;
@@ -1 +1 @@
1
- export declare const VERSION = "4.5.6";
1
+ export declare const VERSION = "4.5.8";