@manuscripts/transform 1.3.11-LEAN-2745 → 1.3.12

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.
@@ -410,7 +410,7 @@ const nodes = [
410
410
  {
411
411
  tag: 'fn-group',
412
412
  node: 'footnotes_element',
413
- context: 'footnotes_section/',
413
+ context: 'footnotes_section/|table_element_footer/',
414
414
  getAttrs: (node) => {
415
415
  const element = node;
416
416
  return {
@@ -421,19 +421,18 @@ const nodes = [
421
421
  },
422
422
  {
423
423
  tag: 'table-wrap-foot',
424
- node: 'footnotes_element',
424
+ node: 'table_element_footer',
425
425
  getAttrs: (node) => {
426
426
  const element = node;
427
427
  return {
428
428
  id: element.getAttribute('id'),
429
- kind: 'table_footnote',
430
429
  };
431
430
  },
432
431
  },
433
432
  {
434
433
  tag: 'fn',
435
434
  node: 'footnote',
436
- context: 'footnotes_element/',
435
+ context: 'footnotes_element/|table_element_footer/',
437
436
  getAttrs: (node) => {
438
437
  const element = node;
439
438
  return {
@@ -240,7 +240,7 @@ exports.jatsBodyTransformations = {
240
240
  backmatterContainer.append(section);
241
241
  }
242
242
  }
243
- const footnotes = [...doc.querySelectorAll('fn')];
243
+ const footnotes = [...doc.querySelectorAll('fn:not(table-wrap-foot fn)')];
244
244
  const footnotesSection = doc.querySelector('sec[sec-type="endnotes"]');
245
245
  const footnotesSectionGroup = footnotesSection === null || footnotesSection === void 0 ? void 0 : footnotesSection.querySelector('fn-group');
246
246
  const containingGroup = footnotesSectionGroup || createElement('fn-group');
@@ -598,6 +598,7 @@ class JATSExporter {
598
598
  this.createSerializer = () => {
599
599
  const getModel = (id) => id ? this.modelMap.get(id) : undefined;
600
600
  const nodes = {
601
+ table_element_footer: () => ['table-wrap-foot', 0],
601
602
  contributor_list: () => '',
602
603
  contributor: () => '',
603
604
  affiliation_list: () => '',
@@ -870,7 +871,7 @@ class JATSExporter {
870
871
  section_title_plain: () => ['title', 0],
871
872
  table: (node) => ['table', { id: normalizeID(node.attrs.id) }, 0],
872
873
  table_element: (node) => {
873
- const element = createFigureElement(node, 'table-wrap', node.type.schema.nodes.table);
874
+ const element = createTableElement(node);
874
875
  element.setAttribute('position', 'anchor');
875
876
  return element;
876
877
  },
@@ -909,12 +910,27 @@ class JATSExporter {
909
910
  tracked_delete: () => ['del'],
910
911
  };
911
912
  this.serializer = new prosemirror_model_1.DOMSerializer(nodes, marks);
912
- const createFigureElement = (node, nodeName, contentNodeType, figType) => {
913
+ const processChildNodes = (element, node, contentNodeType) => {
914
+ node.forEach((childNode) => {
915
+ if (childNode.type === contentNodeType) {
916
+ if (childNode.attrs.id) {
917
+ element.appendChild(this.serializeNode(childNode));
918
+ }
919
+ }
920
+ else if (childNode.type === node.type.schema.nodes.paragraph) {
921
+ element.appendChild(this.serializeNode(childNode));
922
+ }
923
+ else if (childNode.type === node.type.schema.nodes.missing_figure) {
924
+ element.appendChild(this.serializeNode(childNode));
925
+ }
926
+ });
927
+ };
928
+ const createElement = (node, nodeName) => {
913
929
  const element = this.document.createElement(nodeName);
914
930
  element.setAttribute('id', normalizeID(node.attrs.id));
915
- if (figType) {
916
- element.setAttribute('fig-type', figType);
917
- }
931
+ return element;
932
+ };
933
+ const appendLabels = (element, node) => {
918
934
  if (node.attrs.label) {
919
935
  const label = this.document.createElement('label');
920
936
  label.textContent = node.attrs.label;
@@ -928,32 +944,42 @@ class JATSExporter {
928
944
  element.appendChild(label);
929
945
  }
930
946
  }
931
- const figcaptionNode = findChildNodeOfType(node, node.type.schema.nodes.figcaption);
932
- if (figcaptionNode) {
933
- element.appendChild(this.serializeNode(figcaptionNode));
934
- }
935
- const footnotesNode = findChildNodeOfType(node, node.type.schema.nodes.footnotes_element);
936
- if (footnotesNode) {
937
- element.appendChild(this.serializeNode(footnotesNode));
938
- }
939
- node.forEach((childNode) => {
940
- if (childNode.type === contentNodeType) {
941
- if (childNode.attrs.id) {
942
- element.appendChild(this.serializeNode(childNode));
943
- }
944
- }
945
- else if (childNode.type === node.type.schema.nodes.paragraph) {
946
- element.appendChild(this.serializeNode(childNode));
947
- }
948
- else if (childNode.type === node.type.schema.nodes.missing_figure) {
949
- element.appendChild(this.serializeNode(childNode));
950
- }
951
- });
947
+ };
948
+ const appendAttributions = (element, node) => {
952
949
  if (node.attrs.attribution) {
953
950
  const attribution = this.document.createElement('attrib');
954
951
  attribution.textContent = node.attrs.attribution.literal;
955
952
  element.appendChild(attribution);
956
953
  }
954
+ };
955
+ const appendChildNodeOfType = (element, node, type) => {
956
+ const childNode = findChildNodeOfType(node, type);
957
+ if (childNode) {
958
+ element.appendChild(this.serializeNode(childNode));
959
+ }
960
+ };
961
+ const createFigureElement = (node, nodeName, contentNodeType, figType) => {
962
+ const element = createElement(node, nodeName);
963
+ if (figType) {
964
+ element.setAttribute('fig-type', figType);
965
+ }
966
+ appendLabels(element, node);
967
+ appendChildNodeOfType(element, node, node.type.schema.nodes.figcaption);
968
+ appendChildNodeOfType(element, node, node.type.schema.nodes.footnotes_element);
969
+ processChildNodes(element, node, contentNodeType);
970
+ appendAttributions(element, node);
971
+ if ((0, node_types_1.isExecutableNodeType)(node.type)) {
972
+ processExecutableNode(node, element);
973
+ }
974
+ return element;
975
+ };
976
+ const createTableElement = (node) => {
977
+ const nodeName = 'table-wrap';
978
+ const element = createElement(node, nodeName);
979
+ appendLabels(element, node);
980
+ appendChildNodeOfType(element, node, node.type.schema.nodes.figcaption);
981
+ appendChildNodeOfType(element, node, node.type.schema.nodes.table);
982
+ appendChildNodeOfType(element, node, node.type.schema.nodes.table_element_footer);
957
983
  if ((0, node_types_1.isExecutableNodeType)(node.type)) {
958
984
  processExecutableNode(node, element);
959
985
  }
@@ -82,6 +82,7 @@ const section_title_1 = require("./nodes/section_title");
82
82
  const table_1 = require("./nodes/table");
83
83
  const table_col_1 = require("./nodes/table_col");
84
84
  const table_element_1 = require("./nodes/table_element");
85
+ const table_element_footer_1 = require("./nodes/table_element_footer");
85
86
  const table_row_1 = require("./nodes/table_row");
86
87
  const text_1 = require("./nodes/text");
87
88
  const toc_element_1 = require("./nodes/toc_element");
@@ -140,6 +141,7 @@ __exportStar(require("./nodes/affiliation_list"), exports);
140
141
  __exportStar(require("./nodes/meta_section"), exports);
141
142
  __exportStar(require("./nodes/contributor_list"), exports);
142
143
  __exportStar(require("./nodes/contributor"), exports);
144
+ __exportStar(require("./nodes/table_element_footer"), exports);
143
145
  exports.schema = new prosemirror_model_1.Schema({
144
146
  marks: {
145
147
  bold: marks_1.bold,
@@ -215,5 +217,6 @@ exports.schema = new prosemirror_model_1.Schema({
215
217
  affiliation_list: affiliation_list_1.affiliationList,
216
218
  contributor_list: contributor_list_1.contributorList,
217
219
  contributor: contributor_1.contributor,
220
+ table_element_footer: table_element_footer_1.tableElementFooter,
218
221
  },
219
222
  });
@@ -17,7 +17,7 @@
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.tableElement = void 0;
19
19
  exports.tableElement = {
20
- content: '(table | placeholder) figcaption? footnotes_element? (listing | placeholder)',
20
+ content: '(table | placeholder) figcaption? table_element_footer? (listing | placeholder)',
21
21
  attrs: {
22
22
  id: { default: '' },
23
23
  paragraphStyle: { default: '' },
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ /*!
3
+ * © 2019 Atypon Systems LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.tableElementFooter = void 0;
19
+ exports.tableElementFooter = {
20
+ attrs: {
21
+ id: { default: '' },
22
+ },
23
+ content: '(paragraph | footnotes_element)+',
24
+ group: 'block element',
25
+ toDOM: () => ['table-wrap-foot', 0],
26
+ };
@@ -123,21 +123,7 @@ class Decoder {
123
123
  }
124
124
  extractListing(model) {
125
125
  if (model.listingID) {
126
- const listingModel = this.getModel(model.listingID);
127
- let listing;
128
- if (listingModel) {
129
- listing = this.decode(listingModel);
130
- }
131
- else if (this.allowMissingElements) {
132
- listing = schema_1.schema.nodes.placeholder.create({
133
- id: model.listingID,
134
- label: 'A listing',
135
- });
136
- }
137
- else {
138
- throw new errors_1.MissingElement(model.listingID);
139
- }
140
- return listing;
126
+ return this.createListing(model);
141
127
  }
142
128
  }
143
129
  constructor(modelMap, allowMissingElements = false) {
@@ -165,8 +151,6 @@ class Decoder {
165
151
  },
166
152
  [json_schema_1.ObjectTypes.BibliographyItem]: (data) => {
167
153
  const model = data;
168
- const commentNodes = this.createCommentsNode(model);
169
- commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
170
154
  return schema_1.schema.nodes.bibliography_item.create({
171
155
  id: model._id,
172
156
  type: model.type,
@@ -180,7 +164,6 @@ class Decoder {
180
164
  page: model.page,
181
165
  title: model.title,
182
166
  literal: model.literal,
183
- comments: commentNodes.map((c) => c.attrs.id),
184
167
  });
185
168
  },
186
169
  [object_types_1.ExtraObjectTypes.PlaceholderElement]: (data) => {
@@ -285,11 +268,13 @@ class Decoder {
285
268
  }, [equation, figcaption]);
286
269
  },
287
270
  [json_schema_1.ObjectTypes.FootnotesElement]: (data) => {
288
- const model = data;
289
- const collateByKind = model.collateByKind || 'footnote';
271
+ const foonotesElementModel = data;
272
+ const collateByKind = foonotesElementModel.collateByKind || 'footnote';
290
273
  const footnotesOfKind = [];
291
274
  for (const model of this.modelMap.values()) {
292
- if (isFootnote(model) && model.kind === collateByKind) {
275
+ if (isFootnote(model) &&
276
+ model.kind === collateByKind &&
277
+ model.containingObject === foonotesElementModel._id) {
293
278
  const commentNodes = this.createCommentsNode(model);
294
279
  commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
295
280
  const footnote = this.parseContents(model.contents || '<div></div>', undefined, this.getComments(model), {
@@ -303,19 +288,21 @@ class Decoder {
303
288
  }
304
289
  }
305
290
  return schema_1.schema.nodes.footnotes_element.create({
306
- id: model._id,
307
- kind: model.collateByKind,
308
- paragraphStyle: model.paragraphStyle,
291
+ id: foonotesElementModel._id,
292
+ kind: foonotesElementModel.collateByKind,
293
+ paragraphStyle: foonotesElementModel.paragraphStyle,
309
294
  }, footnotesOfKind);
310
295
  },
311
296
  [json_schema_1.ObjectTypes.Footnote]: (data) => {
312
- const model = data;
313
- const commentNodes = this.createCommentsNode(model);
297
+ const footnoteModel = data;
298
+ const commentNodes = this.createCommentsNode(footnoteModel);
314
299
  commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
315
- return schema_1.schema.nodes.footnote.create({
316
- id: model._id,
317
- kind: model.kind,
318
- comments: commentNodes.map((c) => c.attrs.id),
300
+ return this.parseContents(footnoteModel.contents || '<div></div>', undefined, this.getComments(footnoteModel), {
301
+ topNode: schema_1.schema.nodes.footnote.create({
302
+ id: footnoteModel._id,
303
+ kind: footnoteModel.kind,
304
+ comments: commentNodes.map((c) => c.attrs.id),
305
+ }),
319
306
  });
320
307
  },
321
308
  [json_schema_1.ObjectTypes.KeywordsElement]: (data) => {
@@ -439,6 +426,13 @@ class Decoder {
439
426
  throw new Error('Unknown block type');
440
427
  }
441
428
  },
429
+ [json_schema_1.ObjectTypes.TableElementFooter]: (data) => {
430
+ const model = data;
431
+ const content = model.containedObjectIDs.map((id) => this.decode(this.modelMap.get(id)));
432
+ return schema_1.schema.nodes.table_element_footer.create({
433
+ id: model._id,
434
+ }, content);
435
+ },
442
436
  [json_schema_1.ObjectTypes.Section]: (data) => {
443
437
  const model = data;
444
438
  const isKeywordsSection = model.category === 'MPSectionCategory:keywords';
@@ -522,39 +516,16 @@ class Decoder {
522
516
  },
523
517
  [json_schema_1.ObjectTypes.TableElement]: (data) => {
524
518
  const model = data;
525
- const tableModel = this.getModel(model.containedObjectID);
526
- let table;
527
- if (tableModel) {
528
- table = this.decode(tableModel);
529
- }
530
- else if (this.allowMissingElements) {
531
- table = schema_1.schema.nodes.placeholder.create({
532
- id: model.containedObjectID,
533
- label: 'A table',
534
- });
535
- }
536
- else {
537
- throw new errors_1.MissingElement(model.containedObjectID);
538
- }
519
+ const table = this.createTable(model);
520
+ const tableElementFooter = this.createTableElementFooter(model);
539
521
  const figcaption = this.getFigcaption(model);
540
522
  const commentNodes = this.createCommentsNode(model);
541
523
  commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
542
- const content = [table, figcaption];
524
+ const content = tableElementFooter
525
+ ? [table, figcaption, tableElementFooter]
526
+ : [table, figcaption];
543
527
  if (model.listingID) {
544
- const listingModel = this.getModel(model.listingID);
545
- let listing;
546
- if (listingModel) {
547
- listing = this.decode(listingModel);
548
- }
549
- else if (this.allowMissingElements) {
550
- listing = schema_1.schema.nodes.placeholder.create({
551
- id: model.listingID,
552
- label: 'A listing',
553
- });
554
- }
555
- else {
556
- throw new errors_1.MissingElement(model.listingID);
557
- }
528
+ const listing = this.createListing(model);
558
529
  content.push(listing);
559
530
  }
560
531
  else {
@@ -730,6 +701,51 @@ class Decoder {
730
701
  this.modelMap = modelMap;
731
702
  this.allowMissingElements = allowMissingElements;
732
703
  }
704
+ createTable(model) {
705
+ const tableId = model.containedObjectID;
706
+ const tableModel = this.getModel(tableId);
707
+ let table;
708
+ if (tableModel) {
709
+ table = this.decode(tableModel);
710
+ }
711
+ else if (this.allowMissingElements) {
712
+ table = schema_1.schema.nodes.placeholder.create({
713
+ id: tableId,
714
+ label: 'A table',
715
+ });
716
+ }
717
+ else {
718
+ throw new errors_1.MissingElement(tableId);
719
+ }
720
+ return table;
721
+ }
722
+ createTableElementFooter(model) {
723
+ const tableElementFooterID = model.tableElementFooterID;
724
+ if (!tableElementFooterID) {
725
+ return undefined;
726
+ }
727
+ const tableElementFooterModel = this.getModel(tableElementFooterID);
728
+ return tableElementFooterModel
729
+ ? this.decode(tableElementFooterModel)
730
+ : undefined;
731
+ }
732
+ createListing(model) {
733
+ const listingModel = this.getModel(model.listingID);
734
+ let listing;
735
+ if (listingModel) {
736
+ listing = this.decode(listingModel);
737
+ }
738
+ else if (this.allowMissingElements) {
739
+ listing = schema_1.schema.nodes.placeholder.create({
740
+ id: model.listingID,
741
+ label: 'A listing',
742
+ });
743
+ }
744
+ else {
745
+ throw new errors_1.MissingElement(model.listingID);
746
+ }
747
+ return listing;
748
+ }
733
749
  getKeywordGroups() {
734
750
  const kwdGroupNodes = [];
735
751
  const kwdGroupsModels = [
@@ -219,7 +219,7 @@ const containedObjectIDs = (node, nodeTypes) => {
219
219
  const ids = [];
220
220
  for (let i = 0; i < node.childCount; i++) {
221
221
  const childNode = node.child(i);
222
- if (nodeTypes.includes(childNode.type)) {
222
+ if (!nodeTypes || nodeTypes.includes(childNode.type)) {
223
223
  ids.push(childNode.attrs.id);
224
224
  }
225
225
  }
@@ -385,6 +385,9 @@ const encoders = {
385
385
  elementType: 'div',
386
386
  paragraphStyle: node.attrs.paragraphStyle || undefined,
387
387
  }),
388
+ table_element_footer: (node) => ({
389
+ containedObjectIDs: containedObjectIDs(node),
390
+ }),
388
391
  footnotes_section: (node, parent, path, priority) => ({
389
392
  category: (0, section_category_1.buildSectionCategory)(node),
390
393
  priority: priority.value++,
@@ -472,6 +475,7 @@ const encoders = {
472
475
  }),
473
476
  table_element: (node) => ({
474
477
  containedObjectID: attributeOfNodeType(node, 'table', 'id'),
478
+ tableElementFooterID: attributeOfNodeType(node, 'table_element_footer', 'id'),
475
479
  caption: inlineContentOfChildNodeType(node, node.type.schema.nodes.figcaption, node.type.schema.nodes.caption),
476
480
  title: inlineContentOfChildNodeType(node, node.type.schema.nodes.figcaption, node.type.schema.nodes.caption_title, false),
477
481
  elementType: 'table',
@@ -21,6 +21,9 @@ const createOrderedFootnotesIDs = (doc) => {
21
21
  const footnotesRefs = [...doc.querySelectorAll('xref[ref-type="fn"][rid]')];
22
22
  const footnotes = [...doc.querySelectorAll('fn:not([fn-type])')];
23
23
  const authorNotesIDs = [...doc.querySelectorAll('author-notes > fn')].map((an) => an.getAttribute('id'));
24
+ const tableElementFooters = [
25
+ ...doc.querySelectorAll('table-wrap-foot > fn'),
26
+ ].map((footer) => footer.getAttribute('id'));
24
27
  const orderedFootnotesIDs = [];
25
28
  footnotesRefs.forEach((ref) => {
26
29
  const refID = ref.getAttribute('rid');
@@ -32,7 +35,8 @@ const createOrderedFootnotesIDs = (doc) => {
32
35
  const id = footnote.getAttribute('id');
33
36
  if (id &&
34
37
  !authorNotesIDs.includes(id) &&
35
- !orderedFootnotesIDs.includes(id)) {
38
+ !orderedFootnotesIDs.includes(id) &&
39
+ !tableElementFooters.includes(id)) {
36
40
  orderedFootnotesIDs.push(id);
37
41
  }
38
42
  });
@@ -56,6 +56,7 @@ exports.nodeTypesMap = new Map([
56
56
  [schema_1.schema.nodes.meta_section, json_schema_1.ObjectTypes.MetaSection],
57
57
  [schema_1.schema.nodes.affiliation, json_schema_1.ObjectTypes.Affiliation],
58
58
  [schema_1.schema.nodes.contributor, json_schema_1.ObjectTypes.Contributor],
59
+ [schema_1.schema.nodes.table_element_footer, json_schema_1.ObjectTypes.TableElementFooter],
59
60
  ]);
60
61
  const isExecutableNodeType = (type) => (0, schema_1.hasGroup)(type, schema_1.GROUP_EXECUTABLE);
61
62
  exports.isExecutableNodeType = isExecutableNodeType;
@@ -404,7 +404,7 @@ const nodes = [
404
404
  {
405
405
  tag: 'fn-group',
406
406
  node: 'footnotes_element',
407
- context: 'footnotes_section/',
407
+ context: 'footnotes_section/|table_element_footer/',
408
408
  getAttrs: (node) => {
409
409
  const element = node;
410
410
  return {
@@ -415,19 +415,18 @@ const nodes = [
415
415
  },
416
416
  {
417
417
  tag: 'table-wrap-foot',
418
- node: 'footnotes_element',
418
+ node: 'table_element_footer',
419
419
  getAttrs: (node) => {
420
420
  const element = node;
421
421
  return {
422
422
  id: element.getAttribute('id'),
423
- kind: 'table_footnote',
424
423
  };
425
424
  },
426
425
  },
427
426
  {
428
427
  tag: 'fn',
429
428
  node: 'footnote',
430
- context: 'footnotes_element/',
429
+ context: 'footnotes_element/|table_element_footer/',
431
430
  getAttrs: (node) => {
432
431
  const element = node;
433
432
  return {
@@ -237,7 +237,7 @@ export const jatsBodyTransformations = {
237
237
  backmatterContainer.append(section);
238
238
  }
239
239
  }
240
- const footnotes = [...doc.querySelectorAll('fn')];
240
+ const footnotes = [...doc.querySelectorAll('fn:not(table-wrap-foot fn)')];
241
241
  const footnotesSection = doc.querySelector('sec[sec-type="endnotes"]');
242
242
  const footnotesSectionGroup = footnotesSection === null || footnotesSection === void 0 ? void 0 : footnotesSection.querySelector('fn-group');
243
243
  const containingGroup = footnotesSectionGroup || createElement('fn-group');
@@ -591,6 +591,7 @@ export class JATSExporter {
591
591
  this.createSerializer = () => {
592
592
  const getModel = (id) => id ? this.modelMap.get(id) : undefined;
593
593
  const nodes = {
594
+ table_element_footer: () => ['table-wrap-foot', 0],
594
595
  contributor_list: () => '',
595
596
  contributor: () => '',
596
597
  affiliation_list: () => '',
@@ -863,7 +864,7 @@ export class JATSExporter {
863
864
  section_title_plain: () => ['title', 0],
864
865
  table: (node) => ['table', { id: normalizeID(node.attrs.id) }, 0],
865
866
  table_element: (node) => {
866
- const element = createFigureElement(node, 'table-wrap', node.type.schema.nodes.table);
867
+ const element = createTableElement(node);
867
868
  element.setAttribute('position', 'anchor');
868
869
  return element;
869
870
  },
@@ -902,12 +903,27 @@ export class JATSExporter {
902
903
  tracked_delete: () => ['del'],
903
904
  };
904
905
  this.serializer = new DOMSerializer(nodes, marks);
905
- const createFigureElement = (node, nodeName, contentNodeType, figType) => {
906
+ const processChildNodes = (element, node, contentNodeType) => {
907
+ node.forEach((childNode) => {
908
+ if (childNode.type === contentNodeType) {
909
+ if (childNode.attrs.id) {
910
+ element.appendChild(this.serializeNode(childNode));
911
+ }
912
+ }
913
+ else if (childNode.type === node.type.schema.nodes.paragraph) {
914
+ element.appendChild(this.serializeNode(childNode));
915
+ }
916
+ else if (childNode.type === node.type.schema.nodes.missing_figure) {
917
+ element.appendChild(this.serializeNode(childNode));
918
+ }
919
+ });
920
+ };
921
+ const createElement = (node, nodeName) => {
906
922
  const element = this.document.createElement(nodeName);
907
923
  element.setAttribute('id', normalizeID(node.attrs.id));
908
- if (figType) {
909
- element.setAttribute('fig-type', figType);
910
- }
924
+ return element;
925
+ };
926
+ const appendLabels = (element, node) => {
911
927
  if (node.attrs.label) {
912
928
  const label = this.document.createElement('label');
913
929
  label.textContent = node.attrs.label;
@@ -921,32 +937,42 @@ export class JATSExporter {
921
937
  element.appendChild(label);
922
938
  }
923
939
  }
924
- const figcaptionNode = findChildNodeOfType(node, node.type.schema.nodes.figcaption);
925
- if (figcaptionNode) {
926
- element.appendChild(this.serializeNode(figcaptionNode));
927
- }
928
- const footnotesNode = findChildNodeOfType(node, node.type.schema.nodes.footnotes_element);
929
- if (footnotesNode) {
930
- element.appendChild(this.serializeNode(footnotesNode));
931
- }
932
- node.forEach((childNode) => {
933
- if (childNode.type === contentNodeType) {
934
- if (childNode.attrs.id) {
935
- element.appendChild(this.serializeNode(childNode));
936
- }
937
- }
938
- else if (childNode.type === node.type.schema.nodes.paragraph) {
939
- element.appendChild(this.serializeNode(childNode));
940
- }
941
- else if (childNode.type === node.type.schema.nodes.missing_figure) {
942
- element.appendChild(this.serializeNode(childNode));
943
- }
944
- });
940
+ };
941
+ const appendAttributions = (element, node) => {
945
942
  if (node.attrs.attribution) {
946
943
  const attribution = this.document.createElement('attrib');
947
944
  attribution.textContent = node.attrs.attribution.literal;
948
945
  element.appendChild(attribution);
949
946
  }
947
+ };
948
+ const appendChildNodeOfType = (element, node, type) => {
949
+ const childNode = findChildNodeOfType(node, type);
950
+ if (childNode) {
951
+ element.appendChild(this.serializeNode(childNode));
952
+ }
953
+ };
954
+ const createFigureElement = (node, nodeName, contentNodeType, figType) => {
955
+ const element = createElement(node, nodeName);
956
+ if (figType) {
957
+ element.setAttribute('fig-type', figType);
958
+ }
959
+ appendLabels(element, node);
960
+ appendChildNodeOfType(element, node, node.type.schema.nodes.figcaption);
961
+ appendChildNodeOfType(element, node, node.type.schema.nodes.footnotes_element);
962
+ processChildNodes(element, node, contentNodeType);
963
+ appendAttributions(element, node);
964
+ if (isExecutableNodeType(node.type)) {
965
+ processExecutableNode(node, element);
966
+ }
967
+ return element;
968
+ };
969
+ const createTableElement = (node) => {
970
+ const nodeName = 'table-wrap';
971
+ const element = createElement(node, nodeName);
972
+ appendLabels(element, node);
973
+ appendChildNodeOfType(element, node, node.type.schema.nodes.figcaption);
974
+ appendChildNodeOfType(element, node, node.type.schema.nodes.table);
975
+ appendChildNodeOfType(element, node, node.type.schema.nodes.table_element_footer);
950
976
  if (isExecutableNodeType(node.type)) {
951
977
  processExecutableNode(node, element);
952
978
  }
@@ -65,6 +65,7 @@ import { sectionTitle } from './nodes/section_title';
65
65
  import { table, tableBody } from './nodes/table';
66
66
  import { tableCol, tableColGroup } from './nodes/table_col';
67
67
  import { tableElement } from './nodes/table_element';
68
+ import { tableElementFooter } from './nodes/table_element_footer';
68
69
  import { tableCell, tableRow } from './nodes/table_row';
69
70
  import { text } from './nodes/text';
70
71
  import { tocElement } from './nodes/toc_element';
@@ -123,6 +124,7 @@ export * from './nodes/affiliation_list';
123
124
  export * from './nodes/meta_section';
124
125
  export * from './nodes/contributor_list';
125
126
  export * from './nodes/contributor';
127
+ export * from './nodes/table_element_footer';
126
128
  export const schema = new Schema({
127
129
  marks: {
128
130
  bold,
@@ -198,5 +200,6 @@ export const schema = new Schema({
198
200
  affiliation_list: affiliationList,
199
201
  contributor_list: contributorList,
200
202
  contributor: contributor,
203
+ table_element_footer: tableElementFooter,
201
204
  },
202
205
  });
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
  export const tableElement = {
17
- content: '(table | placeholder) figcaption? footnotes_element? (listing | placeholder)',
17
+ content: '(table | placeholder) figcaption? table_element_footer? (listing | placeholder)',
18
18
  attrs: {
19
19
  id: { default: '' },
20
20
  paragraphStyle: { default: '' },
@@ -0,0 +1,23 @@
1
+ /*!
2
+ * © 2019 Atypon Systems LLC
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ export const tableElementFooter = {
17
+ attrs: {
18
+ id: { default: '' },
19
+ },
20
+ content: '(paragraph | footnotes_element)+',
21
+ group: 'block element',
22
+ toDOM: () => ['table-wrap-foot', 0],
23
+ };
@@ -113,21 +113,7 @@ export class Decoder {
113
113
  }
114
114
  extractListing(model) {
115
115
  if (model.listingID) {
116
- const listingModel = this.getModel(model.listingID);
117
- let listing;
118
- if (listingModel) {
119
- listing = this.decode(listingModel);
120
- }
121
- else if (this.allowMissingElements) {
122
- listing = schema.nodes.placeholder.create({
123
- id: model.listingID,
124
- label: 'A listing',
125
- });
126
- }
127
- else {
128
- throw new MissingElement(model.listingID);
129
- }
130
- return listing;
116
+ return this.createListing(model);
131
117
  }
132
118
  }
133
119
  constructor(modelMap, allowMissingElements = false) {
@@ -155,8 +141,6 @@ export class Decoder {
155
141
  },
156
142
  [ObjectTypes.BibliographyItem]: (data) => {
157
143
  const model = data;
158
- const commentNodes = this.createCommentsNode(model);
159
- commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
160
144
  return schema.nodes.bibliography_item.create({
161
145
  id: model._id,
162
146
  type: model.type,
@@ -170,7 +154,6 @@ export class Decoder {
170
154
  page: model.page,
171
155
  title: model.title,
172
156
  literal: model.literal,
173
- comments: commentNodes.map((c) => c.attrs.id),
174
157
  });
175
158
  },
176
159
  [ExtraObjectTypes.PlaceholderElement]: (data) => {
@@ -275,11 +258,13 @@ export class Decoder {
275
258
  }, [equation, figcaption]);
276
259
  },
277
260
  [ObjectTypes.FootnotesElement]: (data) => {
278
- const model = data;
279
- const collateByKind = model.collateByKind || 'footnote';
261
+ const foonotesElementModel = data;
262
+ const collateByKind = foonotesElementModel.collateByKind || 'footnote';
280
263
  const footnotesOfKind = [];
281
264
  for (const model of this.modelMap.values()) {
282
- if (isFootnote(model) && model.kind === collateByKind) {
265
+ if (isFootnote(model) &&
266
+ model.kind === collateByKind &&
267
+ model.containingObject === foonotesElementModel._id) {
283
268
  const commentNodes = this.createCommentsNode(model);
284
269
  commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
285
270
  const footnote = this.parseContents(model.contents || '<div></div>', undefined, this.getComments(model), {
@@ -293,19 +278,21 @@ export class Decoder {
293
278
  }
294
279
  }
295
280
  return schema.nodes.footnotes_element.create({
296
- id: model._id,
297
- kind: model.collateByKind,
298
- paragraphStyle: model.paragraphStyle,
281
+ id: foonotesElementModel._id,
282
+ kind: foonotesElementModel.collateByKind,
283
+ paragraphStyle: foonotesElementModel.paragraphStyle,
299
284
  }, footnotesOfKind);
300
285
  },
301
286
  [ObjectTypes.Footnote]: (data) => {
302
- const model = data;
303
- const commentNodes = this.createCommentsNode(model);
287
+ const footnoteModel = data;
288
+ const commentNodes = this.createCommentsNode(footnoteModel);
304
289
  commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
305
- return schema.nodes.footnote.create({
306
- id: model._id,
307
- kind: model.kind,
308
- comments: commentNodes.map((c) => c.attrs.id),
290
+ return this.parseContents(footnoteModel.contents || '<div></div>', undefined, this.getComments(footnoteModel), {
291
+ topNode: schema.nodes.footnote.create({
292
+ id: footnoteModel._id,
293
+ kind: footnoteModel.kind,
294
+ comments: commentNodes.map((c) => c.attrs.id),
295
+ }),
309
296
  });
310
297
  },
311
298
  [ObjectTypes.KeywordsElement]: (data) => {
@@ -429,6 +416,13 @@ export class Decoder {
429
416
  throw new Error('Unknown block type');
430
417
  }
431
418
  },
419
+ [ObjectTypes.TableElementFooter]: (data) => {
420
+ const model = data;
421
+ const content = model.containedObjectIDs.map((id) => this.decode(this.modelMap.get(id)));
422
+ return schema.nodes.table_element_footer.create({
423
+ id: model._id,
424
+ }, content);
425
+ },
432
426
  [ObjectTypes.Section]: (data) => {
433
427
  const model = data;
434
428
  const isKeywordsSection = model.category === 'MPSectionCategory:keywords';
@@ -512,39 +506,16 @@ export class Decoder {
512
506
  },
513
507
  [ObjectTypes.TableElement]: (data) => {
514
508
  const model = data;
515
- const tableModel = this.getModel(model.containedObjectID);
516
- let table;
517
- if (tableModel) {
518
- table = this.decode(tableModel);
519
- }
520
- else if (this.allowMissingElements) {
521
- table = schema.nodes.placeholder.create({
522
- id: model.containedObjectID,
523
- label: 'A table',
524
- });
525
- }
526
- else {
527
- throw new MissingElement(model.containedObjectID);
528
- }
509
+ const table = this.createTable(model);
510
+ const tableElementFooter = this.createTableElementFooter(model);
529
511
  const figcaption = this.getFigcaption(model);
530
512
  const commentNodes = this.createCommentsNode(model);
531
513
  commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
532
- const content = [table, figcaption];
514
+ const content = tableElementFooter
515
+ ? [table, figcaption, tableElementFooter]
516
+ : [table, figcaption];
533
517
  if (model.listingID) {
534
- const listingModel = this.getModel(model.listingID);
535
- let listing;
536
- if (listingModel) {
537
- listing = this.decode(listingModel);
538
- }
539
- else if (this.allowMissingElements) {
540
- listing = schema.nodes.placeholder.create({
541
- id: model.listingID,
542
- label: 'A listing',
543
- });
544
- }
545
- else {
546
- throw new MissingElement(model.listingID);
547
- }
518
+ const listing = this.createListing(model);
548
519
  content.push(listing);
549
520
  }
550
521
  else {
@@ -720,6 +691,51 @@ export class Decoder {
720
691
  this.modelMap = modelMap;
721
692
  this.allowMissingElements = allowMissingElements;
722
693
  }
694
+ createTable(model) {
695
+ const tableId = model.containedObjectID;
696
+ const tableModel = this.getModel(tableId);
697
+ let table;
698
+ if (tableModel) {
699
+ table = this.decode(tableModel);
700
+ }
701
+ else if (this.allowMissingElements) {
702
+ table = schema.nodes.placeholder.create({
703
+ id: tableId,
704
+ label: 'A table',
705
+ });
706
+ }
707
+ else {
708
+ throw new MissingElement(tableId);
709
+ }
710
+ return table;
711
+ }
712
+ createTableElementFooter(model) {
713
+ const tableElementFooterID = model.tableElementFooterID;
714
+ if (!tableElementFooterID) {
715
+ return undefined;
716
+ }
717
+ const tableElementFooterModel = this.getModel(tableElementFooterID);
718
+ return tableElementFooterModel
719
+ ? this.decode(tableElementFooterModel)
720
+ : undefined;
721
+ }
722
+ createListing(model) {
723
+ const listingModel = this.getModel(model.listingID);
724
+ let listing;
725
+ if (listingModel) {
726
+ listing = this.decode(listingModel);
727
+ }
728
+ else if (this.allowMissingElements) {
729
+ listing = schema.nodes.placeholder.create({
730
+ id: model.listingID,
731
+ label: 'A listing',
732
+ });
733
+ }
734
+ else {
735
+ throw new MissingElement(model.listingID);
736
+ }
737
+ return listing;
738
+ }
723
739
  getKeywordGroups() {
724
740
  const kwdGroupNodes = [];
725
741
  const kwdGroupsModels = [
@@ -211,7 +211,7 @@ const containedObjectIDs = (node, nodeTypes) => {
211
211
  const ids = [];
212
212
  for (let i = 0; i < node.childCount; i++) {
213
213
  const childNode = node.child(i);
214
- if (nodeTypes.includes(childNode.type)) {
214
+ if (!nodeTypes || nodeTypes.includes(childNode.type)) {
215
215
  ids.push(childNode.attrs.id);
216
216
  }
217
217
  }
@@ -377,6 +377,9 @@ const encoders = {
377
377
  elementType: 'div',
378
378
  paragraphStyle: node.attrs.paragraphStyle || undefined,
379
379
  }),
380
+ table_element_footer: (node) => ({
381
+ containedObjectIDs: containedObjectIDs(node),
382
+ }),
380
383
  footnotes_section: (node, parent, path, priority) => ({
381
384
  category: buildSectionCategory(node),
382
385
  priority: priority.value++,
@@ -464,6 +467,7 @@ const encoders = {
464
467
  }),
465
468
  table_element: (node) => ({
466
469
  containedObjectID: attributeOfNodeType(node, 'table', 'id'),
470
+ tableElementFooterID: attributeOfNodeType(node, 'table_element_footer', 'id'),
467
471
  caption: inlineContentOfChildNodeType(node, node.type.schema.nodes.figcaption, node.type.schema.nodes.caption),
468
472
  title: inlineContentOfChildNodeType(node, node.type.schema.nodes.figcaption, node.type.schema.nodes.caption_title, false),
469
473
  elementType: 'table',
@@ -18,6 +18,9 @@ export const createOrderedFootnotesIDs = (doc) => {
18
18
  const footnotesRefs = [...doc.querySelectorAll('xref[ref-type="fn"][rid]')];
19
19
  const footnotes = [...doc.querySelectorAll('fn:not([fn-type])')];
20
20
  const authorNotesIDs = [...doc.querySelectorAll('author-notes > fn')].map((an) => an.getAttribute('id'));
21
+ const tableElementFooters = [
22
+ ...doc.querySelectorAll('table-wrap-foot > fn'),
23
+ ].map((footer) => footer.getAttribute('id'));
21
24
  const orderedFootnotesIDs = [];
22
25
  footnotesRefs.forEach((ref) => {
23
26
  const refID = ref.getAttribute('rid');
@@ -29,7 +32,8 @@ export const createOrderedFootnotesIDs = (doc) => {
29
32
  const id = footnote.getAttribute('id');
30
33
  if (id &&
31
34
  !authorNotesIDs.includes(id) &&
32
- !orderedFootnotesIDs.includes(id)) {
35
+ !orderedFootnotesIDs.includes(id) &&
36
+ !tableElementFooters.includes(id)) {
33
37
  orderedFootnotesIDs.push(id);
34
38
  }
35
39
  });
@@ -53,6 +53,7 @@ export const nodeTypesMap = new Map([
53
53
  [schema.nodes.meta_section, ObjectTypes.MetaSection],
54
54
  [schema.nodes.affiliation, ObjectTypes.Affiliation],
55
55
  [schema.nodes.contributor, ObjectTypes.Contributor],
56
+ [schema.nodes.table_element_footer, ObjectTypes.TableElementFooter],
56
57
  ]);
57
58
  export const isExecutableNodeType = (type) => hasGroup(type, GROUP_EXECUTABLE);
58
59
  export const isElementNodeType = (type) => hasGroup(type, GROUP_ELEMENT);
@@ -69,4 +69,5 @@ export * from './nodes/affiliation_list';
69
69
  export * from './nodes/meta_section';
70
70
  export * from './nodes/contributor_list';
71
71
  export * from './nodes/contributor';
72
+ export * from './nodes/table_element_footer';
72
73
  export declare const schema: Schema<Nodes, Marks>;
@@ -0,0 +1,25 @@
1
+ /*!
2
+ * © 2019 Atypon Systems LLC
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import { NodeSpec } from 'prosemirror-model';
17
+ import { ManuscriptNode } from '../types';
18
+ interface Attrs {
19
+ id: string;
20
+ }
21
+ export interface TableElementFooterNode extends ManuscriptNode {
22
+ attrs: Attrs;
23
+ }
24
+ export declare const tableElementFooter: NodeSpec;
25
+ export {};
@@ -17,7 +17,7 @@ import { Fragment, Mark as ProsemirrorMark, MarkType, Node as ProsemirrorNode, N
17
17
  import { EditorState, NodeSelection, Plugin, TextSelection, Transaction } from 'prosemirror-state';
18
18
  import { EditorView, NodeView } from 'prosemirror-view';
19
19
  export type Marks = 'bold' | 'code' | 'italic' | 'smallcaps' | 'strikethrough' | 'styled' | 'subscript' | 'superscript' | 'underline' | 'tracked_insert' | 'tracked_delete';
20
- export type Nodes = 'attribution' | 'bibliography_item' | 'bibliography_element' | 'bibliography_section' | 'blockquote_element' | 'bullet_list' | 'caption' | 'caption_title' | 'comment' | 'comment_list' | 'citation' | 'cross_reference' | 'doc' | 'equation' | 'equation_element' | 'figcaption' | 'figure' | 'graphical_abstract_section' | 'figure_element' | 'footnote' | 'footnotes_element' | 'footnotes_section' | 'hard_break' | 'highlight_marker' | 'inline_equation' | 'inline_footnote' | 'keyword' | 'keywords_element' | 'keywords_group' | 'keywords_section' | 'link' | 'list_item' | 'listing' | 'listing_element' | 'manuscript' | 'missing_figure' | 'ordered_list' | 'paragraph' | 'placeholder' | 'placeholder_element' | 'pullquote_element' | 'section' | 'section_label' | 'section_title' | 'section_title_plain' | 'table' | 'table_body' | 'table_cell' | 'table_element' | 'table_row' | 'table_colgroup' | 'table_col' | 'text' | 'toc_element' | 'toc_section' | 'affiliation' | 'meta_section' | 'affiliation_list' | 'contributor_list' | 'contributor';
20
+ export type Nodes = 'attribution' | 'bibliography_item' | 'bibliography_element' | 'bibliography_section' | 'blockquote_element' | 'bullet_list' | 'caption' | 'caption_title' | 'comment' | 'comment_list' | 'citation' | 'cross_reference' | 'doc' | 'equation' | 'equation_element' | 'figcaption' | 'figure' | 'graphical_abstract_section' | 'figure_element' | 'footnote' | 'footnotes_element' | 'footnotes_section' | 'hard_break' | 'highlight_marker' | 'inline_equation' | 'inline_footnote' | 'keyword' | 'keywords_element' | 'keywords_group' | 'keywords_section' | 'link' | 'list_item' | 'listing' | 'listing_element' | 'manuscript' | 'missing_figure' | 'ordered_list' | 'paragraph' | 'placeholder' | 'placeholder_element' | 'pullquote_element' | 'section' | 'section_label' | 'section_title' | 'section_title_plain' | 'table' | 'table_body' | 'table_cell' | 'table_element' | 'table_row' | 'table_colgroup' | 'table_col' | 'text' | 'toc_element' | 'toc_section' | 'affiliation' | 'meta_section' | 'affiliation_list' | 'contributor_list' | 'contributor' | 'table_element_footer';
21
21
  export type ManuscriptSchema = Schema<Nodes, Marks>;
22
22
  export type ManuscriptEditorState = EditorState;
23
23
  export type ManuscriptEditorView = EditorView;
@@ -42,5 +42,8 @@ export declare class Decoder {
42
42
  private getKeywords;
43
43
  private getManuscriptID;
44
44
  private getFigcaption;
45
+ private createTable;
46
+ private createTableElementFooter;
47
+ private createListing;
45
48
  private getKeywordGroups;
46
49
  }
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.3.11-LEAN-2745",
4
+ "version": "1.3.12",
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.1.1",
32
+ "@manuscripts/json-schema": "^2.1.2",
33
33
  "debug": "^4.3.4",
34
34
  "jszip": "^3.10.1",
35
35
  "mathjax-full": "^3.2.2",
@@ -82,4 +82,4 @@
82
82
  "prosemirror-state": "^1.4.2",
83
83
  "prosemirror-view": "^1.29.1"
84
84
  }
85
- }
85
+ }