@manuscripts/transform 4.5.8 → 4.6.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 (60) hide show
  1. package/dist/cjs/jats/__tests__/jats-exporter.test.js +23 -0
  2. package/dist/cjs/jats/__tests__/jats-importer.test.js +26 -0
  3. package/dist/cjs/jats/exporter/JATSExporterBase.js +118 -0
  4. package/dist/cjs/jats/exporter/jats-exporter.js +224 -342
  5. package/dist/cjs/jats/exporter/lib.js +62 -0
  6. package/dist/cjs/jats/importer/jats-dom-parser.js +11 -3
  7. package/dist/cjs/schema/index.js +4 -1
  8. package/dist/cjs/schema/migration/migration-scripts/4.5.9.js +30 -0
  9. package/dist/cjs/schema/migration/migration-scripts/index.js +3 -1
  10. package/dist/cjs/schema/nodes/bibliography_element.js +0 -1
  11. package/dist/cjs/schema/nodes/bio.js +24 -0
  12. package/dist/cjs/schema/nodes/contributor.js +1 -2
  13. package/dist/cjs/schema/nodes/keywords_element.js +0 -1
  14. package/dist/cjs/types.js +1 -1
  15. package/dist/cjs/version.js +1 -1
  16. package/dist/es/jats/__tests__/jats-exporter.test.js +23 -0
  17. package/dist/es/jats/__tests__/jats-importer.test.js +26 -0
  18. package/dist/es/jats/exporter/JATSExporterBase.js +114 -0
  19. package/dist/es/jats/exporter/jats-exporter.js +198 -315
  20. package/dist/es/jats/exporter/lib.js +55 -0
  21. package/dist/es/jats/importer/jats-dom-parser.js +11 -3
  22. package/dist/es/schema/index.js +4 -1
  23. package/dist/es/schema/migration/migration-scripts/4.5.9.js +28 -0
  24. package/dist/es/schema/migration/migration-scripts/index.js +3 -1
  25. package/dist/es/schema/nodes/bibliography_element.js +0 -1
  26. package/dist/es/schema/nodes/bio.js +20 -0
  27. package/dist/es/schema/nodes/contributor.js +1 -2
  28. package/dist/es/schema/nodes/keywords_element.js +0 -1
  29. package/dist/es/types.js +1 -1
  30. package/dist/es/version.js +1 -1
  31. package/dist/types/jats/exporter/JATSExporterBase.d.ts +35 -0
  32. package/dist/types/jats/exporter/jats-exporter.d.ts +22 -18
  33. package/dist/types/jats/exporter/lib.d.ts +23 -0
  34. package/dist/types/schema/index.d.ts +2 -1
  35. package/dist/types/schema/migration/migration-scripts/4.5.9.d.ts +8 -0
  36. package/dist/types/schema/migration/migration-scripts/index.d.ts +3 -2
  37. package/dist/types/schema/nodes/bio.d.ts +10 -0
  38. package/dist/types/schema/types.d.ts +1 -1
  39. package/dist/types/types.d.ts +1 -1
  40. package/dist/types/version.d.ts +1 -1
  41. package/package.json +1 -1
  42. package/src/jats/__tests__/__fixtures__/jats-import.xml +7 -0
  43. package/src/jats/__tests__/__snapshots__/jats-importer.test.ts.snap +272 -151
  44. package/src/jats/__tests__/__snapshots__/jats-roundtrip.test.ts.snap +2 -2
  45. package/src/jats/__tests__/jats-exporter.test.ts +34 -0
  46. package/src/jats/__tests__/jats-importer.test.ts +37 -0
  47. package/src/jats/exporter/JATSExporterBase.ts +164 -0
  48. package/src/jats/exporter/jats-exporter.ts +212 -380
  49. package/src/jats/exporter/lib.ts +69 -0
  50. package/src/jats/importer/jats-dom-parser.ts +15 -5
  51. package/src/schema/index.ts +4 -1
  52. package/src/schema/migration/migration-scripts/4.5.9.ts +62 -0
  53. package/src/schema/migration/migration-scripts/index.ts +3 -1
  54. package/src/schema/nodes/bibliography_element.ts +0 -1
  55. package/src/schema/nodes/bio.ts +48 -0
  56. package/src/schema/nodes/contributor.ts +1 -2
  57. package/src/schema/nodes/keywords_element.ts +0 -1
  58. package/src/schema/types.ts +1 -0
  59. package/src/types.ts +1 -1
  60. package/src/version.ts +1 -1
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  /*!
3
- * © 2019 Atypon Systems LLC
3
+ * © 2026 Atypon Systems LLC
4
4
  *
5
5
  * Licensed under the Apache License, Version 2.0 (the "License");
6
6
  * you may not use this file except in compliance with the License.
@@ -48,7 +48,7 @@ var __importStar = (this && this.__importStar) || (function () {
48
48
  };
49
49
  })();
50
50
  Object.defineProperty(exports, "__esModule", { value: true });
51
- exports.JATSExporter = exports.createCounter = void 0;
51
+ exports.JATSExporter = void 0;
52
52
  const Citeproc = __importStar(require("citeproc"));
53
53
  const prosemirror_model_1 = require("prosemirror-model");
54
54
  const prosemirror_utils_1 = require("prosemirror-utils");
@@ -62,58 +62,12 @@ const transformer_1 = require("../../transformer");
62
62
  const citeproc_2 = require("./citeproc");
63
63
  const jats_versions_1 = require("./jats-versions");
64
64
  const labels_1 = require("./labels");
65
- const normalizeID = (id) => id.replace(/:/g, '_');
66
- const createCounter = () => {
67
- const counts = new Map();
68
- return {
69
- increment: (field) => {
70
- const value = counts.get(field);
71
- const newValue = value === undefined ? 1 : value + 1;
72
- counts.set(field, newValue);
73
- return newValue;
74
- },
75
- };
76
- };
77
- exports.createCounter = createCounter;
78
- const createDefaultIDGenerator = () => {
79
- const counter = (0, exports.createCounter)();
80
- return async (element) => {
81
- const value = String(counter.increment(element.nodeName));
82
- return `${element.localName}-${value}`;
83
- };
84
- };
85
- const chooseRefType = (type) => {
86
- switch (type) {
87
- case schema_1.schema.nodes.figure:
88
- case schema_1.schema.nodes.figure_element:
89
- return 'fig';
90
- case schema_1.schema.nodes.footnote:
91
- return 'fn';
92
- case schema_1.schema.nodes.table:
93
- case schema_1.schema.nodes.table_element:
94
- return 'table';
95
- case schema_1.schema.nodes.section:
96
- case schema_1.schema.nodes.abstract:
97
- return 'sec';
98
- case schema_1.schema.nodes.equation:
99
- case schema_1.schema.nodes.equation_element:
100
- return 'disp-formula';
101
- case schema_1.schema.nodes.supplement:
102
- return 'supplementary-material';
103
- }
104
- };
105
- class JATSExporter {
65
+ const JATSExporterBase_1 = require("./JATSExporterBase");
66
+ const lib_1 = require("./lib");
67
+ class JATSExporter extends JATSExporterBase_1.JATSExporterBase {
106
68
  constructor() {
107
- this.nodesMap = new Map();
69
+ super(...arguments);
108
70
  this.contributorLabels = new Map();
109
- this.populateNodesMap = () => {
110
- this.manuscriptNode.descendants((node) => {
111
- const type = node.type;
112
- const nodes = this.nodesMap.get(type) ?? [];
113
- nodes.push(node);
114
- this.nodesMap.set(type, nodes);
115
- });
116
- };
117
71
  this.export = async (manuscriptNode, options) => {
118
72
  this.manuscriptNode = manuscriptNode;
119
73
  this.populateNodesMap();
@@ -209,7 +163,7 @@ class JATSExporter {
209
163
  $template.innerHTML = fragment;
210
164
  return $template.firstChild;
211
165
  };
212
- this.rewriteIDs = async (generator = createDefaultIDGenerator()) => {
166
+ this.rewriteIDs = async (generator = (0, lib_1.createDefaultIDGenerator)()) => {
213
167
  const ids = new Map();
214
168
  for (const $element of this.document.querySelectorAll('[id]')) {
215
169
  const oldID = $element.getAttribute('id');
@@ -446,32 +400,13 @@ class JATSExporter {
446
400
  });
447
401
  return $refList;
448
402
  };
449
- this.createElement = (tag, content, attrs) => {
450
- const $element = this.document.createElement(tag);
451
- if (content) {
452
- $element.textContent = content;
453
- }
454
- if (attrs) {
455
- Object.entries(attrs).forEach(([k, v]) => {
456
- if (v) {
457
- $element.setAttribute(k, v);
458
- }
459
- });
460
- }
461
- return $element;
462
- };
463
- this.appendElement = ($parent, tag, content, attrs) => {
464
- const $element = this.createElement(tag, content, attrs);
465
- $parent.appendChild($element);
466
- return $element;
467
- };
468
403
  this.createSerializer = () => {
469
404
  const nodes = {
470
- trans_abstract: (node) => createTransAbstract(node),
471
- trans_graphical_abstract: (node) => createTransAbstract(node),
405
+ trans_abstract: (node) => this.createTransAbstract(node),
406
+ trans_graphical_abstract: (node) => this.createTransAbstract(node),
472
407
  hero_image: () => '',
473
408
  headshot_grid: () => ['p', { 'content-type': 'headshots' }, 0],
474
- headshot_element: (node) => createImage(node),
409
+ headshot_element: (node) => this.createImage(node),
475
410
  headshot_image: () => '',
476
411
  alt_text: (node) => {
477
412
  if (node.textContent) {
@@ -496,14 +431,14 @@ class JATSExporter {
496
431
  return $selfUri;
497
432
  },
498
433
  attachments: () => '',
499
- image_element: (node) => createImage(node),
434
+ image_element: (node) => this.createImage(node),
500
435
  embed: (node) => {
501
436
  const { id, href, mimetype, mimeSubtype, extLinks } = node.attrs;
502
437
  if (!href) {
503
438
  return '';
504
439
  }
505
440
  const $media = this.createElement('media');
506
- $media.setAttribute('id', normalizeID(id));
441
+ $media.setAttribute('id', (0, lib_1.normalizeID)(id));
507
442
  $media.setAttributeNS(xml_1.XLINK_NAMESPACE, 'show', 'embed');
508
443
  $media.setAttributeNS(xml_1.XLINK_NAMESPACE, 'href', href);
509
444
  if (mimetype) {
@@ -512,7 +447,7 @@ class JATSExporter {
512
447
  if (mimeSubtype) {
513
448
  $media.setAttribute('mime-subtype', node.attrs.mimeSubtype);
514
449
  }
515
- appendLabels($media, node);
450
+ this.appendLabels($media, node);
516
451
  this.appendChildNodeOfType($media, node, schema_1.schema.nodes.alt_text);
517
452
  this.appendChildNodeOfType($media, node, schema_1.schema.nodes.long_desc);
518
453
  this.appendCaption($media, node);
@@ -538,15 +473,15 @@ class JATSExporter {
538
473
  award: (node) => {
539
474
  const awardGroup = node;
540
475
  const $awardGroup = this.createElement('award-group');
541
- $awardGroup.setAttribute('id', normalizeID(awardGroup.attrs.id));
542
- appendChildIfPresent($awardGroup, 'funding-source', awardGroup.attrs.source);
476
+ $awardGroup.setAttribute('id', (0, lib_1.normalizeID)(awardGroup.attrs.id));
477
+ this.appendChildIfPresent($awardGroup, 'funding-source', awardGroup.attrs.source);
543
478
  awardGroup.attrs.code
544
479
  ?.split(';')
545
- .forEach((code) => appendChildIfPresent($awardGroup, 'award-id', code));
546
- appendChildIfPresent($awardGroup, 'principal-award-recipient', awardGroup.attrs.recipient);
480
+ .forEach((code) => this.appendChildIfPresent($awardGroup, 'award-id', code));
481
+ this.appendChildIfPresent($awardGroup, 'principal-award-recipient', awardGroup.attrs.recipient);
547
482
  return $awardGroup;
548
483
  },
549
- box_element: (node) => createBoxElement(node),
484
+ box_element: (node) => this.createBoxElement(node),
550
485
  author_notes: () => '',
551
486
  corresp: () => '',
552
487
  title: () => ['article-title', 0],
@@ -565,6 +500,7 @@ class JATSExporter {
565
500
  ? ['table-wrap-foot', ['fn-group', ['fn', ['p']]]]
566
501
  : ['table-wrap-foot', 0],
567
502
  contributor: (node) => this.buildContributorElement(node),
503
+ bio: () => ['bio', 0],
568
504
  affiliation: (node) => this.buildAffiliationElement(node),
569
505
  attribution: () => ['attrib', 0],
570
506
  bibliography_element: () => '',
@@ -582,11 +518,11 @@ class JATSExporter {
582
518
  backmatter: () => ['backmatter', 0],
583
519
  supplement: (node) => {
584
520
  const $supplementaryMaterial = this.createElement('supplementary-material');
585
- $supplementaryMaterial.setAttribute('id', normalizeID(node.attrs.id));
521
+ $supplementaryMaterial.setAttribute('id', (0, lib_1.normalizeID)(node.attrs.id));
586
522
  $supplementaryMaterial.setAttributeNS(xml_1.XLINK_NAMESPACE, 'href', node.attrs.href ?? '');
587
523
  $supplementaryMaterial.setAttribute('mimetype', node.attrs.mimeType ?? '');
588
524
  $supplementaryMaterial.setAttribute('mime-subtype', node.attrs.mimeSubType ?? '');
589
- appendLabels($supplementaryMaterial, node);
525
+ this.appendLabels($supplementaryMaterial, node);
590
526
  this.appendCaption($supplementaryMaterial, node);
591
527
  return $supplementaryMaterial;
592
528
  },
@@ -615,7 +551,7 @@ class JATSExporter {
615
551
  }
616
552
  const $xref = this.createElement('xref');
617
553
  $xref.setAttribute('ref-type', 'bibr');
618
- $xref.setAttribute('rid', normalizeID(rids.join(' ')));
554
+ $xref.setAttribute('rid', (0, lib_1.normalizeID)(rids.join(' ')));
619
555
  const fragment = this.renderedCitations.get(node.attrs.id);
620
556
  if (fragment) {
621
557
  $xref.innerHTML = fragment;
@@ -641,11 +577,11 @@ class JATSExporter {
641
577
  return text;
642
578
  }
643
579
  const $xref = this.createElement('xref');
644
- const type = chooseRefType(target.type);
580
+ const type = (0, lib_1.chooseRefType)(target.type);
645
581
  if (type) {
646
582
  $xref.setAttribute('ref-type', type);
647
583
  }
648
- $xref.setAttribute('rid', normalizeID(rids.join(' ')));
584
+ $xref.setAttribute('rid', (0, lib_1.normalizeID)(rids.join(' ')));
649
585
  $xref.textContent = text ?? '';
650
586
  return $xref;
651
587
  },
@@ -671,17 +607,17 @@ class JATSExporter {
671
607
  },
672
608
  equation_element: (node) => {
673
609
  const $dispFormula = this.createElement('disp-formula');
674
- $dispFormula.setAttribute('id', normalizeID(node.attrs.id));
675
- appendLabels($dispFormula, node);
676
- processChildNodes($dispFormula, node, schema_1.schema.nodes.equation);
610
+ $dispFormula.setAttribute('id', (0, lib_1.normalizeID)(node.attrs.id));
611
+ this.appendLabels($dispFormula, node);
612
+ this.processChildNodes($dispFormula, node, schema_1.schema.nodes.equation);
677
613
  return $dispFormula;
678
614
  },
679
- figure: (node) => createGraphic(node),
680
- figure_element: (node) => createFigureElement(node, node.type.schema.nodes.figure),
615
+ figure: (node) => this.createGraphic(node),
616
+ figure_element: (node) => this.createFigureElement(node, node.type.schema.nodes.figure),
681
617
  footnote: (node) => {
682
618
  const attrs = {};
683
619
  if (node.attrs.id) {
684
- attrs.id = normalizeID(node.attrs.id);
620
+ attrs.id = (0, lib_1.normalizeID)(node.attrs.id);
685
621
  }
686
622
  if (node.attrs.category) {
687
623
  attrs['fn-type'] = node.attrs.category;
@@ -689,11 +625,11 @@ class JATSExporter {
689
625
  return ['fn', attrs, 0];
690
626
  },
691
627
  footnotes_element: (node) => node.childCount == 0
692
- ? ['fn-group', { id: normalizeID(node.attrs.id) }, ['fn', ['p']]]
693
- : ['fn-group', { id: normalizeID(node.attrs.id) }, 0],
628
+ ? ['fn-group', { id: (0, lib_1.normalizeID)(node.attrs.id) }, ['fn', ['p']]]
629
+ : ['fn-group', { id: (0, lib_1.normalizeID)(node.attrs.id) }, 0],
694
630
  footnotes_section: (node) => {
695
631
  const $fnGroup = this.createElement('fn-group', undefined, {
696
- id: normalizeID(node.attrs.id),
632
+ id: (0, lib_1.normalizeID)(node.attrs.id),
697
633
  });
698
634
  const titleNode = this.getFirstChildOfType(schema_1.schema.nodes.section_title, node);
699
635
  if (titleNode) {
@@ -718,7 +654,7 @@ class JATSExporter {
718
654
  const rids = node.attrs.rids;
719
655
  const $xref = this.createElement('xref');
720
656
  $xref.setAttribute('ref-type', 'fn');
721
- $xref.setAttribute('rid', normalizeID(rids.join(' ')));
657
+ $xref.setAttribute('rid', (0, lib_1.normalizeID)(rids.join(' ')));
722
658
  $xref.textContent = rids
723
659
  .map((rid) => this.footnoteLabels.get(rid))
724
660
  .join(', ');
@@ -747,13 +683,13 @@ class JATSExporter {
747
683
  list_item: () => ['list-item', 0],
748
684
  listing: (node) => {
749
685
  const $code = this.createElement('code');
750
- $code.setAttribute('id', normalizeID(node.attrs.id));
686
+ $code.setAttribute('id', (0, lib_1.normalizeID)(node.attrs.id));
751
687
  $code.setAttribute('language', node.attrs.languageKey);
752
688
  $code.textContent = node.attrs.contents;
753
689
  return $code;
754
690
  },
755
- listing_element: (node) => createFigureElement(node, node.type.schema.nodes.listing),
756
- manuscript: (node) => ['article', { id: normalizeID(node.attrs.id) }, 0],
691
+ listing_element: (node) => this.createFigureElement(node, node.type.schema.nodes.listing),
692
+ manuscript: (node) => ['article', { id: (0, lib_1.normalizeID)(node.attrs.id) }, 0],
757
693
  missing_figure: () => {
758
694
  const $graphic = this.createElement('graphic');
759
695
  $graphic.setAttribute('specific-use', 'MISSING');
@@ -766,7 +702,7 @@ class JATSExporter {
766
702
  }
767
703
  const attrs = {};
768
704
  if (node.attrs.id) {
769
- attrs.id = normalizeID(node.attrs.id);
705
+ attrs.id = (0, lib_1.normalizeID)(node.attrs.id);
770
706
  }
771
707
  if (node.attrs.contentType) {
772
708
  attrs['content-type'] = node.attrs.contentType;
@@ -789,27 +725,27 @@ class JATSExporter {
789
725
  quote_image: (node) => {
790
726
  const img = node;
791
727
  if (img.attrs.src) {
792
- return createGraphic(node);
728
+ return this.createGraphic(node);
793
729
  }
794
730
  return '';
795
731
  },
796
- graphical_abstract_section: (node) => createAbstract(node),
732
+ graphical_abstract_section: (node) => this.createAbstract(node),
797
733
  section: (node) => {
798
734
  const attrs = {
799
- id: normalizeID(node.attrs.id),
735
+ id: (0, lib_1.normalizeID)(node.attrs.id),
800
736
  };
801
737
  if (node.attrs.category) {
802
738
  attrs['sec-type'] = node.attrs.category;
803
739
  }
804
740
  return ['sec', attrs, 0];
805
741
  },
806
- abstract: (node) => createAbstract(node),
742
+ abstract: (node) => this.createAbstract(node),
807
743
  section_label: () => ['label', 0],
808
744
  section_title: () => ['title', 0],
809
745
  section_title_plain: () => ['title', 0],
810
- table: (node) => ['table', { id: normalizeID(node.attrs.id) }, 0],
746
+ table: (node) => ['table', { id: (0, lib_1.normalizeID)(node.attrs.id) }, 0],
811
747
  table_element: (node) => {
812
- const $tableWrap = createTableElement(node);
748
+ const $tableWrap = this.createTableElement(node);
813
749
  $tableWrap.setAttribute('position', 'anchor');
814
750
  if (node.attrs.type) {
815
751
  $tableWrap.setAttribute('content-type', node.attrs.type);
@@ -860,210 +796,7 @@ class JATSExporter {
860
796
  tracked_delete: () => ['del'],
861
797
  };
862
798
  this.serializer = new prosemirror_model_1.DOMSerializer(nodes, marks);
863
- const appendChildIfPresent = ($parent, tagName, textContent) => {
864
- if (!textContent) {
865
- return;
866
- }
867
- const $element = this.createElement(tagName);
868
- $element.textContent = textContent;
869
- $parent.appendChild($element);
870
- };
871
- const processChildNodes = ($element, node, contentNodeType) => {
872
- node.forEach((childNode) => {
873
- if (childNode.type === contentNodeType) {
874
- if (childNode.attrs.id) {
875
- $element.appendChild(this.serializeNode(childNode));
876
- }
877
- }
878
- else if (childNode.type === node.type.schema.nodes.paragraph) {
879
- $element.appendChild(this.serializeNode(childNode));
880
- }
881
- else if (childNode.type === node.type.schema.nodes.missing_figure) {
882
- $element.appendChild(this.serializeNode(childNode));
883
- }
884
- });
885
- };
886
- const createElement = (node, nodeName) => {
887
- const $element = this.createElement(nodeName);
888
- $element.setAttribute('id', normalizeID(node.attrs.id));
889
- return $element;
890
- };
891
- const appendLabels = ($element, node) => {
892
- if (this.labelTargets) {
893
- const target = this.labelTargets.get(node.attrs.id);
894
- if (target) {
895
- const $label = this.createElement('label');
896
- $label.textContent = target.label;
897
- $element.appendChild($label);
898
- }
899
- }
900
- };
901
- const appendAttributions = ($element, node) => {
902
- if (node.attrs.attribution) {
903
- const $attrib = this.createElement('attrib');
904
- $attrib.textContent = node.attrs.attribution.literal;
905
- $element.appendChild($attrib);
906
- }
907
- };
908
- const appendTable = ($element, node) => {
909
- const tableNode = this.getFirstChildOfType(schema_1.schema.nodes.table, node);
910
- const colGroupNode = this.getFirstChildOfType(schema_1.schema.nodes.table_colgroup, node);
911
- if (!tableNode) {
912
- return;
913
- }
914
- const $table = this.serializeNode(tableNode);
915
- const $tbody = this.createElement('tbody');
916
- while ($table.firstChild) {
917
- const $child = $table.firstChild;
918
- $table.removeChild($child);
919
- $tbody.appendChild($child);
920
- }
921
- $table.appendChild($tbody);
922
- this.normalizeTable($table);
923
- if (colGroupNode) {
924
- const $colGroup = this.serializeNode(colGroupNode);
925
- $table.insertBefore($colGroup, $table.firstChild);
926
- }
927
- $element.appendChild($table);
928
- };
929
- const createBoxElement = (node) => {
930
- const $boxedText = createElement(node, 'boxed-text');
931
- if (node.attrs.type) {
932
- $boxedText.setAttribute('content-type', node.attrs.type);
933
- }
934
- appendLabels($boxedText, node);
935
- const child = node.firstChild;
936
- if (child?.type === schema_1.schema.nodes.caption_title) {
937
- this.appendCaption($boxedText, node);
938
- }
939
- processChildNodes($boxedText, node, node.type.schema.nodes.section);
940
- return $boxedText;
941
- };
942
- const abstractTypeAttrs = (category) => category && category !== 'abstract' ? { 'abstract-type': category } : {};
943
- const createAbstract = (node) => [
944
- 'abstract',
945
- abstractTypeAttrs(node.attrs.category),
946
- 0,
947
- ];
948
- const createTransAbstract = (node) => [
949
- 'trans-abstract',
950
- {
951
- [`${xml_1.XML_NAMESPACE} lang`]: node.attrs.lang ?? '',
952
- ...abstractTypeAttrs(node.attrs.category),
953
- },
954
- 0,
955
- ];
956
- const isChildOfNodeType = (targetID, type, descend = false) => {
957
- const nodes = this.getChildrenOfType(type);
958
- return nodes.some((node) => {
959
- const result = (0, prosemirror_utils_1.findChildrenByAttr)(node, (attrs) => attrs.id === targetID, descend)[0];
960
- return !!result;
961
- });
962
- };
963
- const findParentHeroImage = (targetID) => {
964
- const heroes = this.getChildrenOfType(schema_1.schema.nodes.hero_image);
965
- return heroes.find((hero) => !!(0, prosemirror_utils_1.findChildrenByAttr)(hero, (attrs) => attrs.id === targetID)[0]);
966
- };
967
- const createImage = (node) => {
968
- const graphicNode = node.content.firstChild;
969
- if (!graphicNode) {
970
- return '';
971
- }
972
- const $graphic = createGraphic(graphicNode);
973
- if (node.attrs.extLink) {
974
- const $extLink = this.appendElement($graphic, 'ext-link');
975
- $extLink.setAttributeNS(xml_1.XLINK_NAMESPACE, 'href', node.attrs.extLink);
976
- }
977
- this.appendCaption($graphic, node);
978
- this.appendChildNodeOfType($graphic, node, schema_1.schema.nodes.alt_text);
979
- this.appendChildNodeOfType($graphic, node, schema_1.schema.nodes.long_desc);
980
- return $graphic;
981
- };
982
- const createGraphic = (node) => {
983
- const $graphic = this.createElement('graphic');
984
- $graphic.setAttributeNS(xml_1.XLINK_NAMESPACE, 'xlink:href', node.attrs.src);
985
- const hero = findParentHeroImage(node.attrs.id);
986
- if (hero) {
987
- $graphic.setAttribute('content-type', hero.attrs.type || 'leading');
988
- }
989
- else if (!isChildOfNodeType(node.attrs.id, schema_1.schema.nodes.figure_element) &&
990
- node.attrs.type) {
991
- $graphic.setAttribute('content-type', node.attrs.type);
992
- }
993
- return $graphic;
994
- };
995
- const createFigureElement = (node, contentNodeType) => {
996
- const $fig = createElement(node, 'fig');
997
- const figNode = this.getFirstChildOfType(schema_1.schema.nodes.figure, node);
998
- const figType = figNode?.attrs.type;
999
- if (figType) {
1000
- $fig.setAttribute('fig-type', figType);
1001
- }
1002
- appendLabels($fig, node);
1003
- this.appendCaption($fig, node);
1004
- this.appendChildNodeOfType($fig, node, schema_1.schema.nodes.alt_text);
1005
- this.appendChildNodeOfType($fig, node, schema_1.schema.nodes.long_desc);
1006
- this.appendChildNodeOfType($fig, node, node.type.schema.nodes.footnotes_element);
1007
- processChildNodes($fig, node, contentNodeType);
1008
- appendAttributions($fig, node);
1009
- if ((0, transformer_1.isExecutableNodeType)(node.type)) {
1010
- processExecutableNode(node, $fig);
1011
- }
1012
- moveAltTextAndLongDescToGraphics($fig);
1013
- return $fig;
1014
- };
1015
- const moveAltTextAndLongDescToGraphics = ($element) => {
1016
- const $altText = $element.querySelector('alt-text');
1017
- const $longDesc = $element.querySelector('long-desc');
1018
- const $graphics = $element.querySelectorAll('graphic');
1019
- if ($graphics.length === 0) {
1020
- return;
1021
- }
1022
- $graphics.forEach(($graphic) => {
1023
- if ($longDesc) {
1024
- $graphic.prepend($longDesc.cloneNode(true));
1025
- }
1026
- if ($altText) {
1027
- $graphic.prepend($altText.cloneNode(true));
1028
- }
1029
- });
1030
- $altText?.remove();
1031
- $longDesc?.remove();
1032
- };
1033
- const createTableElement = (node) => {
1034
- const nodeName = 'table-wrap';
1035
- const $tableWrap = createElement(node, nodeName);
1036
- appendLabels($tableWrap, node);
1037
- this.appendCaption($tableWrap, node);
1038
- this.appendChildNodeOfType($tableWrap, node, schema_1.schema.nodes.alt_text);
1039
- this.appendChildNodeOfType($tableWrap, node, schema_1.schema.nodes.long_desc);
1040
- appendTable($tableWrap, node);
1041
- this.appendChildNodeOfType($tableWrap, node, node.type.schema.nodes.table_element_footer);
1042
- if ((0, transformer_1.isExecutableNodeType)(node.type)) {
1043
- processExecutableNode(node, $tableWrap);
1044
- }
1045
- return $tableWrap;
1046
- };
1047
- const processExecutableNode = (node, $element) => {
1048
- const listingNode = this.getFirstChildOfType(schema_1.schema.nodes.listing, node);
1049
- if (listingNode) {
1050
- const { contents, languageKey } = listingNode.attrs;
1051
- if (contents && languageKey) {
1052
- const $fig = this.createElement('fig');
1053
- $fig.setAttribute('specific-use', 'source');
1054
- $element.appendChild($fig);
1055
- const $code = this.createElement('code');
1056
- $code.setAttribute('executable', 'true');
1057
- $code.setAttribute('language', languageKey);
1058
- $code.textContent = contents;
1059
- $fig.appendChild($code);
1060
- }
1061
- }
1062
- };
1063
799
  };
1064
- this.serializeNode = (node) => this.serializer.serializeNode(node, {
1065
- document: this.document,
1066
- });
1067
800
  this.buildContributorGroup = (contributors) => {
1068
801
  if (!contributors.length) {
1069
802
  return;
@@ -1122,7 +855,7 @@ class JATSExporter {
1122
855
  this.buildContributorElement = (contributor) => {
1123
856
  const $contrib = this.createElement('contrib');
1124
857
  $contrib.setAttribute('contrib-type', 'author');
1125
- $contrib.setAttribute('id', normalizeID(contributor.attrs.id));
858
+ $contrib.setAttribute('id', (0, lib_1.normalizeID)(contributor.attrs.id));
1126
859
  if (contributor.attrs.isCorresponding) {
1127
860
  $contrib.setAttribute('corresp', 'yes');
1128
861
  }
@@ -1152,21 +885,21 @@ class JATSExporter {
1152
885
  contributor.attrs.affiliationIDs?.forEach((rid) => {
1153
886
  const $xref = this.appendElement($contrib, 'xref', '', {
1154
887
  'ref-type': 'aff',
1155
- rid: normalizeID(rid),
888
+ rid: (0, lib_1.normalizeID)(rid),
1156
889
  });
1157
890
  $xref.appendChild(this.createLabelSup(rid));
1158
891
  });
1159
892
  contributor.attrs.footnoteIDs?.forEach((rid) => {
1160
893
  const $xref = this.appendElement($contrib, 'xref', '', {
1161
894
  'ref-type': 'fn',
1162
- rid: normalizeID(rid),
895
+ rid: (0, lib_1.normalizeID)(rid),
1163
896
  });
1164
897
  $xref.appendChild(this.createLabelSup(rid));
1165
898
  });
1166
899
  contributor.attrs.correspIDs?.forEach((rid) => {
1167
900
  const $xref = this.appendElement($contrib, 'xref', '', {
1168
901
  'ref-type': 'corresp',
1169
- rid: normalizeID(rid),
902
+ rid: (0, lib_1.normalizeID)(rid),
1170
903
  });
1171
904
  $xref.appendChild(this.createLabelSup(rid));
1172
905
  });
@@ -1182,6 +915,10 @@ class JATSExporter {
1182
915
  'vocab-term-identifier': url,
1183
916
  });
1184
917
  });
918
+ const bio = this.getFirstChildOfType(schema_1.schema.nodes.bio, contributor);
919
+ if (bio?.childCount) {
920
+ $contrib.appendChild(this.serializeNode(bio));
921
+ }
1185
922
  return $contrib;
1186
923
  };
1187
924
  this.buildAffiliationElement = (affiliation) => {
@@ -1216,7 +953,7 @@ class JATSExporter {
1216
953
  $content.push(this.createElement('postal-code', affiliation.attrs.postCode));
1217
954
  }
1218
955
  const $aff = this.createElement('aff');
1219
- $aff.setAttribute('id', normalizeID(affiliation.attrs.id));
956
+ $aff.setAttribute('id', (0, lib_1.normalizeID)(affiliation.attrs.id));
1220
957
  const label = this.contributorLabels.get(affiliation.attrs.id);
1221
958
  if (label) {
1222
959
  this.appendElement($aff, 'label', String(label));
@@ -1248,7 +985,7 @@ class JATSExporter {
1248
985
  };
1249
986
  this.writeCorresp = (corresp) => {
1250
987
  const $corresp = this.createElement('corresp');
1251
- $corresp.setAttribute('id', normalizeID(corresp.attrs.id));
988
+ $corresp.setAttribute('id', (0, lib_1.normalizeID)(corresp.attrs.id));
1252
989
  if (corresp.attrs.label) {
1253
990
  this.appendElement($corresp, 'label', corresp.attrs.label);
1254
991
  }
@@ -1258,7 +995,7 @@ class JATSExporter {
1258
995
  this.writeParagraph = (paragraph) => {
1259
996
  const dom = new DOMParser().parseFromString(paragraph.textContent, 'text/html');
1260
997
  const $p = this.createElement('p');
1261
- $p.setAttribute('id', normalizeID(paragraph.attrs.id));
998
+ $p.setAttribute('id', (0, lib_1.normalizeID)(paragraph.attrs.id));
1262
999
  if (dom.body.innerHTML.length) {
1263
1000
  $p.innerHTML = dom.body.innerHTML;
1264
1001
  }
@@ -1266,7 +1003,7 @@ class JATSExporter {
1266
1003
  };
1267
1004
  this.writeFootnote = (footnote) => {
1268
1005
  const $fn = this.createElement('fn');
1269
- $fn.setAttribute('id', normalizeID(footnote.attrs.id));
1006
+ $fn.setAttribute('id', (0, lib_1.normalizeID)(footnote.attrs.id));
1270
1007
  let content = footnote.textContent;
1271
1008
  if (!content.includes('<p>')) {
1272
1009
  content = `<p>${content}</p>`;
@@ -1296,17 +1033,6 @@ class JATSExporter {
1296
1033
  });
1297
1034
  };
1298
1035
  this.buildKeywords = () => this.getChildrenOfType(schema_1.schema.nodes.keyword_group).map((group) => this.serializeNode(group));
1299
- this.changeTag = ($node, tag) => {
1300
- const $clone = this.createElement(tag);
1301
- for (const attr of $node.attributes) {
1302
- $clone.setAttributeNS(null, attr.name, attr.value);
1303
- }
1304
- while ($node.firstChild) {
1305
- $clone.appendChild($node.firstChild);
1306
- }
1307
- $node.replaceWith($clone);
1308
- return $clone;
1309
- };
1310
1036
  this.normalizeTable = ($table) => {
1311
1037
  let $tbody;
1312
1038
  Array.from($table.childNodes).forEach(($child) => {
@@ -1391,14 +1117,174 @@ class JATSExporter {
1391
1117
  }
1392
1118
  };
1393
1119
  }
1394
- getFirstChildOfType(type, node) {
1395
- return this.getChildrenOfType(type, node)[0];
1120
+ appendLabels($element, node) {
1121
+ if (this.labelTargets) {
1122
+ const target = this.labelTargets.get(node.attrs.id);
1123
+ if (target) {
1124
+ const $label = this.createElement('label');
1125
+ $label.textContent = target.label;
1126
+ $element.appendChild($label);
1127
+ }
1128
+ }
1129
+ }
1130
+ appendAttributions($element, node) {
1131
+ if (node.attrs.attribution) {
1132
+ const $attrib = this.createElement('attrib');
1133
+ $attrib.textContent = node.attrs.attribution.literal;
1134
+ $element.appendChild($attrib);
1135
+ }
1136
+ }
1137
+ appendTable($element, node) {
1138
+ const tableNode = this.getFirstChildOfType(schema_1.schema.nodes.table, node);
1139
+ const colGroupNode = this.getFirstChildOfType(schema_1.schema.nodes.table_colgroup, node);
1140
+ if (!tableNode) {
1141
+ return;
1142
+ }
1143
+ const $table = this.serializeNode(tableNode);
1144
+ const $tbody = this.createElement('tbody');
1145
+ while ($table.firstChild) {
1146
+ const $child = $table.firstChild;
1147
+ $table.removeChild($child);
1148
+ $tbody.appendChild($child);
1149
+ }
1150
+ $table.appendChild($tbody);
1151
+ this.normalizeTable($table);
1152
+ if (colGroupNode) {
1153
+ const $colGroup = this.serializeNode(colGroupNode);
1154
+ $table.insertBefore($colGroup, $table.firstChild);
1155
+ }
1156
+ $element.appendChild($table);
1157
+ }
1158
+ createBoxElement(node) {
1159
+ const $boxedText = this.createElementWithID(node, 'boxed-text');
1160
+ if (node.attrs.type) {
1161
+ $boxedText.setAttribute('content-type', node.attrs.type);
1162
+ }
1163
+ this.appendLabels($boxedText, node);
1164
+ const child = node.firstChild;
1165
+ if (child?.type === schema_1.schema.nodes.caption_title) {
1166
+ this.appendCaption($boxedText, node);
1167
+ }
1168
+ this.processChildNodes($boxedText, node, node.type.schema.nodes.section);
1169
+ return $boxedText;
1170
+ }
1171
+ abstractTypeAttrs(category) {
1172
+ return category && category !== 'abstract'
1173
+ ? { 'abstract-type': category }
1174
+ : {};
1175
+ }
1176
+ createAbstract(node) {
1177
+ return ['abstract', this.abstractTypeAttrs(node.attrs.category), 0];
1178
+ }
1179
+ createTransAbstract(node) {
1180
+ return [
1181
+ 'trans-abstract',
1182
+ {
1183
+ [`${xml_1.XML_NAMESPACE} lang`]: node.attrs.lang ?? '',
1184
+ ...this.abstractTypeAttrs(node.attrs.category),
1185
+ },
1186
+ 0,
1187
+ ];
1188
+ }
1189
+ createGraphic(node) {
1190
+ const $graphic = this.createElement('graphic');
1191
+ $graphic.setAttributeNS(xml_1.XLINK_NAMESPACE, 'xlink:href', node.attrs.src);
1192
+ const findParentHeroImage = (targetID) => {
1193
+ const heroes = this.getChildrenOfType(schema_1.schema.nodes.hero_image);
1194
+ return heroes.find((hero) => !!(0, prosemirror_utils_1.findChildrenByAttr)(hero, (attrs) => attrs.id === targetID)[0]);
1195
+ };
1196
+ const hero = findParentHeroImage(node.attrs.id);
1197
+ if (hero) {
1198
+ $graphic.setAttribute('content-type', hero.attrs.type || 'leading');
1199
+ }
1200
+ else if (!this.isChildOfNodeType(node.attrs.id, schema_1.schema.nodes.figure_element) &&
1201
+ node.attrs.type) {
1202
+ $graphic.setAttribute('content-type', node.attrs.type);
1203
+ }
1204
+ return $graphic;
1205
+ }
1206
+ createImage(node) {
1207
+ const graphicNode = node.content.firstChild;
1208
+ if (!graphicNode) {
1209
+ return '';
1210
+ }
1211
+ const $graphic = this.createGraphic(graphicNode);
1212
+ if (node.attrs.extLink) {
1213
+ const $extLink = this.appendElement($graphic, 'ext-link');
1214
+ $extLink.setAttributeNS(xml_1.XLINK_NAMESPACE, 'href', node.attrs.extLink);
1215
+ }
1216
+ this.appendCaption($graphic, node);
1217
+ this.appendChildNodeOfType($graphic, node, schema_1.schema.nodes.alt_text);
1218
+ this.appendChildNodeOfType($graphic, node, schema_1.schema.nodes.long_desc);
1219
+ return $graphic;
1396
1220
  }
1397
- getChildrenOfType(type, node) {
1398
- const nodes = node
1399
- ? (0, prosemirror_utils_1.findChildrenByType)(node, type).map(({ node }) => node)
1400
- : this.nodesMap.get(type);
1401
- return (nodes ?? []).filter((n) => (0, schema_1.isNodeOfType)(n, type));
1221
+ createFigureElement(node, contentNodeType) {
1222
+ const $fig = this.createElementWithID(node, 'fig');
1223
+ const figNode = this.getFirstChildOfType(schema_1.schema.nodes.figure, node);
1224
+ const figType = figNode?.attrs.type;
1225
+ if (figType) {
1226
+ $fig.setAttribute('fig-type', figType);
1227
+ }
1228
+ this.appendLabels($fig, node);
1229
+ this.appendCaption($fig, node);
1230
+ this.appendChildNodeOfType($fig, node, schema_1.schema.nodes.alt_text);
1231
+ this.appendChildNodeOfType($fig, node, schema_1.schema.nodes.long_desc);
1232
+ this.appendChildNodeOfType($fig, node, node.type.schema.nodes.footnotes_element);
1233
+ this.processChildNodes($fig, node, contentNodeType);
1234
+ this.appendAttributions($fig, node);
1235
+ if ((0, transformer_1.isExecutableNodeType)(node.type)) {
1236
+ this.processExecutableNode(node, $fig);
1237
+ }
1238
+ this.moveAltTextAndLongDescToGraphics($fig);
1239
+ return $fig;
1240
+ }
1241
+ moveAltTextAndLongDescToGraphics($element) {
1242
+ const $altText = $element.querySelector('alt-text');
1243
+ const $longDesc = $element.querySelector('long-desc');
1244
+ const $graphics = $element.querySelectorAll('graphic');
1245
+ if ($graphics.length === 0) {
1246
+ return;
1247
+ }
1248
+ $graphics.forEach(($graphic) => {
1249
+ if ($longDesc) {
1250
+ $graphic.prepend($longDesc.cloneNode(true));
1251
+ }
1252
+ if ($altText) {
1253
+ $graphic.prepend($altText.cloneNode(true));
1254
+ }
1255
+ });
1256
+ $altText?.remove();
1257
+ $longDesc?.remove();
1258
+ }
1259
+ createTableElement(node) {
1260
+ const nodeName = 'table-wrap';
1261
+ const $tableWrap = this.createElementWithID(node, nodeName);
1262
+ this.appendLabels($tableWrap, node);
1263
+ this.appendCaption($tableWrap, node);
1264
+ this.appendChildNodeOfType($tableWrap, node, schema_1.schema.nodes.alt_text);
1265
+ this.appendChildNodeOfType($tableWrap, node, schema_1.schema.nodes.long_desc);
1266
+ this.appendTable($tableWrap, node);
1267
+ this.appendChildNodeOfType($tableWrap, node, node.type.schema.nodes.table_element_footer);
1268
+ if ((0, transformer_1.isExecutableNodeType)(node.type)) {
1269
+ this.processExecutableNode(node, $tableWrap);
1270
+ }
1271
+ return $tableWrap;
1272
+ }
1273
+ processExecutableNode(node, $element) {
1274
+ const listingNode = this.getFirstChildOfType(schema_1.schema.nodes.listing, node);
1275
+ if (listingNode) {
1276
+ const { contents, languageKey } = listingNode.attrs;
1277
+ if (contents && languageKey) {
1278
+ const $fig = this.createElement('fig');
1279
+ $fig.setAttribute('specific-use', 'source');
1280
+ $element.appendChild($fig);
1281
+ const $code = this.createElement('code');
1282
+ $code.setAttribute('executable', 'true');
1283
+ $code.setAttribute('language', languageKey);
1284
+ $code.textContent = contents;
1285
+ $fig.appendChild($code);
1286
+ }
1287
+ }
1402
1288
  }
1403
1289
  createEquation(node, isInline = false) {
1404
1290
  if (node.attrs.format === 'tex') {
@@ -1417,15 +1303,11 @@ class JATSExporter {
1417
1303
  const math = this.nodeFromJATS(node.attrs.contents);
1418
1304
  const $mathml = math;
1419
1305
  if (!isInline) {
1420
- $mathml.setAttribute('id', normalizeID(node.attrs.id));
1306
+ $mathml.setAttribute('id', (0, lib_1.normalizeID)(node.attrs.id));
1421
1307
  }
1422
1308
  return $mathml;
1423
1309
  }
1424
1310
  }
1425
- fillEmptyElements($article, selector, tagName = 'p') {
1426
- const $empty = Array.from($article.querySelectorAll(selector)).filter(($el) => !$el.innerHTML);
1427
- $empty.forEach(($element) => $element.appendChild(this.createElement(tagName)));
1428
- }
1429
1311
  addParagraphsToSections($article) {
1430
1312
  const $sections = $article.querySelectorAll('sec, abstract');
1431
1313
  const TITLE_TAGS = new Set(['title', 'label', 'sec-meta']);