@manuscripts/transform 1.1.0 → 1.1.1-LEAN-2322

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.
@@ -804,6 +804,7 @@ class JATSExporter {
804
804
  xref.textContent = node.attrs.contents;
805
805
  return xref;
806
806
  },
807
+ keyword: () => '',
807
808
  keywords_element: () => '',
808
809
  keywords_section: () => '',
809
810
  link: (node) => {
@@ -882,6 +883,7 @@ class JATSExporter {
882
883
  },
883
884
  section_label: () => ['label', 0],
884
885
  section_title: () => ['title', 0],
886
+ section_title_plain: () => ['title', 0],
885
887
  table: (node) => ['table', { id: normalizeID(node.attrs.id) }, 0],
886
888
  table_element: (node) => {
887
889
  const element = createFigureElement(node, 'table-wrap', node.type.schema.nodes.table);
@@ -57,6 +57,7 @@ const hard_break_1 = require("./nodes/hard_break");
57
57
  const highlight_marker_1 = require("./nodes/highlight_marker");
58
58
  const inline_equation_1 = require("./nodes/inline_equation");
59
59
  const inline_footnote_1 = require("./nodes/inline_footnote");
60
+ const keyword_1 = require("./nodes/keyword");
60
61
  const keywords_element_1 = require("./nodes/keywords_element");
61
62
  const keywords_section_1 = require("./nodes/keywords_section");
62
63
  const link_1 = require("./nodes/link");
@@ -82,6 +83,7 @@ const toc_section_1 = require("./nodes/toc_section");
82
83
  __exportStar(require("./groups"), exports);
83
84
  __exportStar(require("./types"), exports);
84
85
  __exportStar(require("./nodes/comment"), exports);
86
+ __exportStar(require("./nodes/comment_list"), exports);
85
87
  __exportStar(require("./nodes/attribution"), exports);
86
88
  __exportStar(require("./nodes/bibliography_item"), exports);
87
89
  __exportStar(require("./nodes/bibliography_element"), exports);
@@ -105,6 +107,7 @@ __exportStar(require("./nodes/hard_break"), exports);
105
107
  __exportStar(require("./nodes/highlight_marker"), exports);
106
108
  __exportStar(require("./nodes/inline_equation"), exports);
107
109
  __exportStar(require("./nodes/inline_footnote"), exports);
110
+ __exportStar(require("./nodes/keyword"), exports);
108
111
  __exportStar(require("./nodes/keywords_element"), exports);
109
112
  __exportStar(require("./nodes/keywords_section"), exports);
110
113
  __exportStar(require("./nodes/link"), exports);
@@ -167,6 +170,7 @@ exports.schema = new prosemirror_model_1.Schema({
167
170
  highlight_marker: highlight_marker_1.highlightMarker,
168
171
  inline_equation: inline_equation_1.inlineEquation,
169
172
  inline_footnote: inline_footnote_1.inlineFootnote,
173
+ keyword: keyword_1.keyword,
170
174
  keywords_element: keywords_element_1.keywordsElement,
171
175
  keywords_section: keywords_section_1.keywordsSection,
172
176
  link: link_1.link,
@@ -183,6 +187,7 @@ exports.schema = new prosemirror_model_1.Schema({
183
187
  section: section_1.section,
184
188
  section_label: section_label_1.sectionLabel,
185
189
  section_title: section_title_1.sectionTitle,
190
+ section_title_plain: section_title_1.sectionTitle,
186
191
  table: table_1.table,
187
192
  table_body: table_1.tableBody,
188
193
  table_cell: table_row_1.tableCell,
@@ -22,5 +22,8 @@ exports.comment = {
22
22
  contents: { default: '' },
23
23
  target: { default: '' },
24
24
  selector: { default: null },
25
+ resolved: { default: null },
26
+ contributions: { default: null },
27
+ originalText: { default: null },
25
28
  },
26
29
  };
@@ -0,0 +1,53 @@
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.keyword = void 0;
19
+ exports.keyword = {
20
+ atom: true,
21
+ content: 'text*',
22
+ attrs: {
23
+ id: { default: '' },
24
+ contents: { default: '' },
25
+ dataTracked: { default: null },
26
+ comments: { default: null },
27
+ },
28
+ inline: true,
29
+ group: 'inline',
30
+ selectable: false,
31
+ parseDOM: [
32
+ {
33
+ tag: 'span.keyword',
34
+ getAttrs: (node) => {
35
+ const dom = node;
36
+ return {
37
+ id: dom.getAttribute('id'),
38
+ };
39
+ },
40
+ },
41
+ ],
42
+ toDOM: (node) => {
43
+ const keywordNode = node;
44
+ return [
45
+ 'span',
46
+ {
47
+ class: 'keyword',
48
+ id: keywordNode.attrs.id,
49
+ },
50
+ 0,
51
+ ];
52
+ },
53
+ };
@@ -16,15 +16,9 @@
16
16
  */
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.keywordsElement = void 0;
19
- const html_1 = require("../../lib/html");
20
- const createBodyElement = (node) => {
21
- const dom = document.createElement('div');
22
- dom.className = 'manuscript-keywords';
23
- dom.id = node.attrs.id;
24
- return dom;
25
- };
26
19
  exports.keywordsElement = {
27
20
  atom: true,
21
+ content: 'keyword*',
28
22
  attrs: {
29
23
  id: { default: '' },
30
24
  contents: { default: '' },
@@ -46,7 +40,13 @@ exports.keywordsElement = {
46
40
  ],
47
41
  toDOM: (node) => {
48
42
  const keywordsElementNode = node;
49
- return ((0, html_1.nodeFromHTML)(keywordsElementNode.attrs.contents) ||
50
- createBodyElement(keywordsElementNode));
43
+ return [
44
+ 'div',
45
+ {
46
+ class: 'manuscript-keywords',
47
+ id: keywordsElementNode.attrs.id,
48
+ },
49
+ 0,
50
+ ];
51
51
  },
52
52
  };
@@ -17,7 +17,7 @@
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.isKeywordsSectionNode = exports.keywordsSection = void 0;
19
19
  exports.keywordsSection = {
20
- content: 'section_title (keywords_element | placeholder_element)',
20
+ content: 'section_title_plain (keywords_element | placeholder_element)',
21
21
  attrs: {
22
22
  id: { default: '' },
23
23
  dataTracked: { default: null },
@@ -26,13 +26,13 @@ exports.keywordsSection = {
26
26
  selectable: false,
27
27
  parseDOM: [
28
28
  {
29
- tag: 'section.keywords',
29
+ tag: 'div.keywords',
30
30
  },
31
31
  ],
32
32
  toDOM: (node) => {
33
33
  const keywordsSectionNode = node;
34
34
  return [
35
- 'section',
35
+ 'div',
36
36
  {
37
37
  id: keywordsSectionNode.attrs.id,
38
38
  class: 'keywords',
@@ -64,6 +64,7 @@ const isManuscriptNode = (model) => model !== null;
64
64
  exports.isManuscriptNode = isManuscriptNode;
65
65
  const isParagraphElement = (0, object_types_1.hasObjectType)(json_schema_1.ObjectTypes.ParagraphElement);
66
66
  const isFootnote = (0, object_types_1.hasObjectType)(json_schema_1.ObjectTypes.Footnote);
67
+ const isKeyword = (0, object_types_1.hasObjectType)(json_schema_1.ObjectTypes.Keyword);
67
68
  const hasParentSection = (id) => (section) => section.path &&
68
69
  section.path.length > 1 &&
69
70
  section.path[section.path.length - 2] === id;
@@ -274,13 +275,19 @@ class Decoder {
274
275
  },
275
276
  [json_schema_1.ObjectTypes.KeywordsElement]: (data) => {
276
277
  const model = data;
278
+ const keywords = this.getKeywords();
277
279
  return schema_1.schema.nodes.keywords_element.create({
278
280
  id: model._id,
279
- contents: model.contents
280
- ? model.contents.replace(/\s+xmlns=".+?"/, '')
281
- : '',
282
281
  paragraphStyle: model.paragraphStyle,
283
- });
282
+ }, keywords);
283
+ },
284
+ [json_schema_1.ObjectTypes.Keyword]: (data) => {
285
+ const model = data;
286
+ return schema_1.schema.nodes.keyword.create({
287
+ id: model._id,
288
+ contents: model.name,
289
+ comments: this.createCommentsNode(model),
290
+ }, schema_1.schema.text(model.name));
284
291
  },
285
292
  [json_schema_1.ObjectTypes.ListElement]: (data) => {
286
293
  const model = data;
@@ -419,11 +426,14 @@ class Decoder {
419
426
  const elementNodes = elements
420
427
  .map(this.decode)
421
428
  .filter(exports.isManuscriptNode);
429
+ const sectionTitle = isKeywordsSection
430
+ ? 'section_title_plain'
431
+ : 'section_title';
422
432
  const sectionTitleNode = model.title
423
433
  ? this.parseContents(model.title, 'h1', this.getComments(model), {
424
- topNode: schema_1.schema.nodes.section_title.create(),
434
+ topNode: schema_1.schema.nodes[sectionTitle].create(),
425
435
  })
426
- : schema_1.schema.nodes.section_title.create();
436
+ : schema_1.schema.nodes[sectionTitle].create();
427
437
  let sectionLabelNode = undefined;
428
438
  if (model.label) {
429
439
  sectionLabelNode = this.parseContents(model.label, 'label', this.getComments(model), {
@@ -537,6 +547,9 @@ class Decoder {
537
547
  contents: model.contents,
538
548
  selector: model.selector,
539
549
  target: model.target,
550
+ resolved: model.resolved,
551
+ contributions: model.contributions,
552
+ originalText: model.originalText,
540
553
  });
541
554
  },
542
555
  };
@@ -559,6 +572,19 @@ class Decoder {
559
572
  id: (0, id_1.generateNodeID)(schema_1.schema.nodes.section),
560
573
  }));
561
574
  }
575
+ const keywordsSection = getSections(this.modelMap).filter((section) => section.category === 'MPSectionCategory:keywords');
576
+ const keywords = this.getKeywords();
577
+ if (keywordsSection.length === 0 && keywords.length > 0) {
578
+ const keywordsSection = schema_1.schema.nodes.keywords_section.createAndFill({
579
+ id: (0, id_1.generateNodeID)(schema_1.schema.nodes.keywords_section),
580
+ }, [
581
+ schema_1.schema.nodes.section_title_plain.create({}, schema_1.schema.text('Keywords')),
582
+ schema_1.schema.nodes.keywords_element.create({
583
+ id: (0, id_1.generateNodeID)(schema_1.schema.nodes.keywords_element),
584
+ }, keywords),
585
+ ]);
586
+ rootSectionNodes.unshift(keywordsSection);
587
+ }
562
588
  const contents = rootSectionNodes;
563
589
  if (this.comments.size) {
564
590
  const comments = schema_1.schema.nodes.comment_list.createAndFill({
@@ -601,10 +627,28 @@ class Decoder {
601
627
  }
602
628
  const template = document.createElement('template');
603
629
  template.innerHTML = html;
604
- if (!template.content.firstChild) {
630
+ if (!template.content.firstElementChild) {
605
631
  throw new Error('No content could be parsed');
606
632
  }
607
- return parser.parse(template.content.firstChild, options);
633
+ return parser.parse(template.content.firstElementChild, options);
634
+ };
635
+ this.getKeywords = () => {
636
+ const keywordsOfKind = [];
637
+ for (const model of this.modelMap.values()) {
638
+ const commentNodes = this.createCommentsNode(model);
639
+ commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
640
+ if (isKeyword(model)) {
641
+ const keyword = this.parseContents(model.name || '', 'div', this.getComments(model), {
642
+ topNode: schema_1.schema.nodes.keyword.create({
643
+ id: model._id,
644
+ contents: model.name,
645
+ comments: commentNodes.map((c) => c.attrs.id),
646
+ }),
647
+ });
648
+ keywordsOfKind.push(keyword);
649
+ }
650
+ }
651
+ return keywordsOfKind;
608
652
  };
609
653
  this.getManuscriptID = () => {
610
654
  for (const item of this.modelMap.values()) {
@@ -40,6 +40,10 @@ const footnoteContents = (node) => {
40
40
  });
41
41
  return (0, w3c_xmlserializer_1.default)(output);
42
42
  };
43
+ const keywordContents = (node) => {
44
+ const text = serializer.serializeNode(node).textContent;
45
+ return text === null ? '' : text;
46
+ };
43
47
  const inlineContents = (node) => serializer.serializeNode(node).innerHTML;
44
48
  exports.inlineContents = inlineContents;
45
49
  const inlineText = (node) => {
@@ -358,6 +362,9 @@ const encoders = {
358
362
  selector: node.attrs.selector,
359
363
  target: node.attrs.target,
360
364
  contents: node.attrs.contents,
365
+ resolved: node.attrs.resolved,
366
+ contributions: node.attrs.contributions,
367
+ originalText: node.attrs.originalText,
361
368
  }),
362
369
  footnote: (node, parent) => ({
363
370
  containingObject: parent.attrs.id,
@@ -393,6 +400,10 @@ const encoders = {
393
400
  SVGRepresentation: node.attrs.SVGRepresentation,
394
401
  SVGGlyphs: svgDefs(node.attrs.SVGRepresentation),
395
402
  }),
403
+ keyword: (node, parent) => ({
404
+ containerID: parent.attrs.id,
405
+ name: keywordContents(node),
406
+ }),
396
407
  keywords_element: (node) => ({
397
408
  contents: elementContents(node),
398
409
  elementType: 'div',
@@ -401,7 +412,7 @@ const encoders = {
401
412
  keywords_section: (node, parent, path, priority) => ({
402
413
  category: (0, section_category_1.buildSectionCategory)(node),
403
414
  priority: priority.value++,
404
- title: inlineContentsOfNodeType(node, node.type.schema.nodes.section_title),
415
+ title: inlineContentsOfNodeType(node, node.type.schema.nodes.section_title_plain),
405
416
  path: path.concat([node.attrs.id]),
406
417
  elementIDs: childElements(node)
407
418
  .map((childNode) => childNode.attrs.id)
@@ -33,6 +33,7 @@ exports.nodeNames = new Map([
33
33
  [schema_1.schema.nodes.paragraph, 'Paragraph'],
34
34
  [schema_1.schema.nodes.section, 'Section'],
35
35
  [schema_1.schema.nodes.section_title, 'Section'],
36
+ [schema_1.schema.nodes.section_title_plain, 'Section'],
36
37
  [schema_1.schema.nodes.table, 'Table'],
37
38
  [schema_1.schema.nodes.table_element, 'Table'],
38
39
  [schema_1.schema.nodes.blockquote_element, 'Block Quote'],
@@ -38,6 +38,7 @@ exports.nodeTypesMap = new Map([
38
38
  [schema_1.schema.nodes.graphical_abstract_section, json_schema_1.ObjectTypes.Section],
39
39
  [schema_1.schema.nodes.highlight_marker, json_schema_1.ObjectTypes.HighlightMarker],
40
40
  [schema_1.schema.nodes.inline_equation, json_schema_1.ObjectTypes.InlineMathFragment],
41
+ [schema_1.schema.nodes.keyword, json_schema_1.ObjectTypes.Keyword],
41
42
  [schema_1.schema.nodes.keywords_element, json_schema_1.ObjectTypes.KeywordsElement],
42
43
  [schema_1.schema.nodes.keywords_section, json_schema_1.ObjectTypes.Section],
43
44
  [schema_1.schema.nodes.listing, json_schema_1.ObjectTypes.Listing],
@@ -797,6 +797,7 @@ export class JATSExporter {
797
797
  xref.textContent = node.attrs.contents;
798
798
  return xref;
799
799
  },
800
+ keyword: () => '',
800
801
  keywords_element: () => '',
801
802
  keywords_section: () => '',
802
803
  link: (node) => {
@@ -875,6 +876,7 @@ export class JATSExporter {
875
876
  },
876
877
  section_label: () => ['label', 0],
877
878
  section_title: () => ['title', 0],
879
+ section_title_plain: () => ['title', 0],
878
880
  table: (node) => ['table', { id: normalizeID(node.attrs.id) }, 0],
879
881
  table_element: (node) => {
880
882
  const element = createFigureElement(node, 'table-wrap', node.type.schema.nodes.table);
@@ -40,6 +40,7 @@ import { hardBreak } from './nodes/hard_break';
40
40
  import { highlightMarker } from './nodes/highlight_marker';
41
41
  import { inlineEquation } from './nodes/inline_equation';
42
42
  import { inlineFootnote } from './nodes/inline_footnote';
43
+ import { keyword } from './nodes/keyword';
43
44
  import { keywordsElement } from './nodes/keywords_element';
44
45
  import { keywordsSection } from './nodes/keywords_section';
45
46
  import { link } from './nodes/link';
@@ -65,6 +66,7 @@ import { tocSection } from './nodes/toc_section';
65
66
  export * from './groups';
66
67
  export * from './types';
67
68
  export * from './nodes/comment';
69
+ export * from './nodes/comment_list';
68
70
  export * from './nodes/attribution';
69
71
  export * from './nodes/bibliography_item';
70
72
  export * from './nodes/bibliography_element';
@@ -88,6 +90,7 @@ export * from './nodes/hard_break';
88
90
  export * from './nodes/highlight_marker';
89
91
  export * from './nodes/inline_equation';
90
92
  export * from './nodes/inline_footnote';
93
+ export * from './nodes/keyword';
91
94
  export * from './nodes/keywords_element';
92
95
  export * from './nodes/keywords_section';
93
96
  export * from './nodes/link';
@@ -150,6 +153,7 @@ export const schema = new Schema({
150
153
  highlight_marker: highlightMarker,
151
154
  inline_equation: inlineEquation,
152
155
  inline_footnote: inlineFootnote,
156
+ keyword,
153
157
  keywords_element: keywordsElement,
154
158
  keywords_section: keywordsSection,
155
159
  link,
@@ -166,6 +170,7 @@ export const schema = new Schema({
166
170
  section,
167
171
  section_label: sectionLabel,
168
172
  section_title: sectionTitle,
173
+ section_title_plain: sectionTitle,
169
174
  table,
170
175
  table_body: tableBody,
171
176
  table_cell: tableCell,
@@ -19,5 +19,8 @@ export const comment = {
19
19
  contents: { default: '' },
20
20
  target: { default: '' },
21
21
  selector: { default: null },
22
+ resolved: { default: null },
23
+ contributions: { default: null },
24
+ originalText: { default: null },
22
25
  },
23
26
  };
@@ -0,0 +1,50 @@
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 keyword = {
17
+ atom: true,
18
+ content: 'text*',
19
+ attrs: {
20
+ id: { default: '' },
21
+ contents: { default: '' },
22
+ dataTracked: { default: null },
23
+ comments: { default: null },
24
+ },
25
+ inline: true,
26
+ group: 'inline',
27
+ selectable: false,
28
+ parseDOM: [
29
+ {
30
+ tag: 'span.keyword',
31
+ getAttrs: (node) => {
32
+ const dom = node;
33
+ return {
34
+ id: dom.getAttribute('id'),
35
+ };
36
+ },
37
+ },
38
+ ],
39
+ toDOM: (node) => {
40
+ const keywordNode = node;
41
+ return [
42
+ 'span',
43
+ {
44
+ class: 'keyword',
45
+ id: keywordNode.attrs.id,
46
+ },
47
+ 0,
48
+ ];
49
+ },
50
+ };
@@ -13,15 +13,9 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
- import { nodeFromHTML } from '../../lib/html';
17
- const createBodyElement = (node) => {
18
- const dom = document.createElement('div');
19
- dom.className = 'manuscript-keywords';
20
- dom.id = node.attrs.id;
21
- return dom;
22
- };
23
16
  export const keywordsElement = {
24
17
  atom: true,
18
+ content: 'keyword*',
25
19
  attrs: {
26
20
  id: { default: '' },
27
21
  contents: { default: '' },
@@ -43,7 +37,13 @@ export const keywordsElement = {
43
37
  ],
44
38
  toDOM: (node) => {
45
39
  const keywordsElementNode = node;
46
- return (nodeFromHTML(keywordsElementNode.attrs.contents) ||
47
- createBodyElement(keywordsElementNode));
40
+ return [
41
+ 'div',
42
+ {
43
+ class: 'manuscript-keywords',
44
+ id: keywordsElementNode.attrs.id,
45
+ },
46
+ 0,
47
+ ];
48
48
  },
49
49
  };
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
  export const keywordsSection = {
17
- content: 'section_title (keywords_element | placeholder_element)',
17
+ content: 'section_title_plain (keywords_element | placeholder_element)',
18
18
  attrs: {
19
19
  id: { default: '' },
20
20
  dataTracked: { default: null },
@@ -23,13 +23,13 @@ export const keywordsSection = {
23
23
  selectable: false,
24
24
  parseDOM: [
25
25
  {
26
- tag: 'section.keywords',
26
+ tag: 'div.keywords',
27
27
  },
28
28
  ],
29
29
  toDOM: (node) => {
30
30
  const keywordsSectionNode = node;
31
31
  return [
32
- 'section',
32
+ 'div',
33
33
  {
34
34
  id: keywordsSectionNode.attrs.id,
35
35
  class: 'keywords',
@@ -54,6 +54,7 @@ const getSections = (modelMap) => getModelsByType(modelMap, ObjectTypes.Section)
54
54
  export const isManuscriptNode = (model) => model !== null;
55
55
  const isParagraphElement = hasObjectType(ObjectTypes.ParagraphElement);
56
56
  const isFootnote = hasObjectType(ObjectTypes.Footnote);
57
+ const isKeyword = hasObjectType(ObjectTypes.Keyword);
57
58
  const hasParentSection = (id) => (section) => section.path &&
58
59
  section.path.length > 1 &&
59
60
  section.path[section.path.length - 2] === id;
@@ -264,13 +265,19 @@ export class Decoder {
264
265
  },
265
266
  [ObjectTypes.KeywordsElement]: (data) => {
266
267
  const model = data;
268
+ const keywords = this.getKeywords();
267
269
  return schema.nodes.keywords_element.create({
268
270
  id: model._id,
269
- contents: model.contents
270
- ? model.contents.replace(/\s+xmlns=".+?"/, '')
271
- : '',
272
271
  paragraphStyle: model.paragraphStyle,
273
- });
272
+ }, keywords);
273
+ },
274
+ [ObjectTypes.Keyword]: (data) => {
275
+ const model = data;
276
+ return schema.nodes.keyword.create({
277
+ id: model._id,
278
+ contents: model.name,
279
+ comments: this.createCommentsNode(model),
280
+ }, schema.text(model.name));
274
281
  },
275
282
  [ObjectTypes.ListElement]: (data) => {
276
283
  const model = data;
@@ -409,11 +416,14 @@ export class Decoder {
409
416
  const elementNodes = elements
410
417
  .map(this.decode)
411
418
  .filter(isManuscriptNode);
419
+ const sectionTitle = isKeywordsSection
420
+ ? 'section_title_plain'
421
+ : 'section_title';
412
422
  const sectionTitleNode = model.title
413
423
  ? this.parseContents(model.title, 'h1', this.getComments(model), {
414
- topNode: schema.nodes.section_title.create(),
424
+ topNode: schema.nodes[sectionTitle].create(),
415
425
  })
416
- : schema.nodes.section_title.create();
426
+ : schema.nodes[sectionTitle].create();
417
427
  let sectionLabelNode = undefined;
418
428
  if (model.label) {
419
429
  sectionLabelNode = this.parseContents(model.label, 'label', this.getComments(model), {
@@ -527,6 +537,9 @@ export class Decoder {
527
537
  contents: model.contents,
528
538
  selector: model.selector,
529
539
  target: model.target,
540
+ resolved: model.resolved,
541
+ contributions: model.contributions,
542
+ originalText: model.originalText,
530
543
  });
531
544
  },
532
545
  };
@@ -549,6 +562,19 @@ export class Decoder {
549
562
  id: generateNodeID(schema.nodes.section),
550
563
  }));
551
564
  }
565
+ const keywordsSection = getSections(this.modelMap).filter((section) => section.category === 'MPSectionCategory:keywords');
566
+ const keywords = this.getKeywords();
567
+ if (keywordsSection.length === 0 && keywords.length > 0) {
568
+ const keywordsSection = schema.nodes.keywords_section.createAndFill({
569
+ id: generateNodeID(schema.nodes.keywords_section),
570
+ }, [
571
+ schema.nodes.section_title_plain.create({}, schema.text('Keywords')),
572
+ schema.nodes.keywords_element.create({
573
+ id: generateNodeID(schema.nodes.keywords_element),
574
+ }, keywords),
575
+ ]);
576
+ rootSectionNodes.unshift(keywordsSection);
577
+ }
552
578
  const contents = rootSectionNodes;
553
579
  if (this.comments.size) {
554
580
  const comments = schema.nodes.comment_list.createAndFill({
@@ -591,10 +617,28 @@ export class Decoder {
591
617
  }
592
618
  const template = document.createElement('template');
593
619
  template.innerHTML = html;
594
- if (!template.content.firstChild) {
620
+ if (!template.content.firstElementChild) {
595
621
  throw new Error('No content could be parsed');
596
622
  }
597
- return parser.parse(template.content.firstChild, options);
623
+ return parser.parse(template.content.firstElementChild, options);
624
+ };
625
+ this.getKeywords = () => {
626
+ const keywordsOfKind = [];
627
+ for (const model of this.modelMap.values()) {
628
+ const commentNodes = this.createCommentsNode(model);
629
+ commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
630
+ if (isKeyword(model)) {
631
+ const keyword = this.parseContents(model.name || '', 'div', this.getComments(model), {
632
+ topNode: schema.nodes.keyword.create({
633
+ id: model._id,
634
+ contents: model.name,
635
+ comments: commentNodes.map((c) => c.attrs.id),
636
+ }),
637
+ });
638
+ keywordsOfKind.push(keyword);
639
+ }
640
+ }
641
+ return keywordsOfKind;
598
642
  };
599
643
  this.getManuscriptID = () => {
600
644
  for (const item of this.modelMap.values()) {
@@ -34,6 +34,10 @@ const footnoteContents = (node) => {
34
34
  });
35
35
  return serializeToXML(output);
36
36
  };
37
+ const keywordContents = (node) => {
38
+ const text = serializer.serializeNode(node).textContent;
39
+ return text === null ? '' : text;
40
+ };
37
41
  export const inlineContents = (node) => serializer.serializeNode(node).innerHTML;
38
42
  export const inlineText = (node) => {
39
43
  const text = serializer.serializeNode(node).textContent;
@@ -350,6 +354,9 @@ const encoders = {
350
354
  selector: node.attrs.selector,
351
355
  target: node.attrs.target,
352
356
  contents: node.attrs.contents,
357
+ resolved: node.attrs.resolved,
358
+ contributions: node.attrs.contributions,
359
+ originalText: node.attrs.originalText,
353
360
  }),
354
361
  footnote: (node, parent) => ({
355
362
  containingObject: parent.attrs.id,
@@ -385,6 +392,10 @@ const encoders = {
385
392
  SVGRepresentation: node.attrs.SVGRepresentation,
386
393
  SVGGlyphs: svgDefs(node.attrs.SVGRepresentation),
387
394
  }),
395
+ keyword: (node, parent) => ({
396
+ containerID: parent.attrs.id,
397
+ name: keywordContents(node),
398
+ }),
388
399
  keywords_element: (node) => ({
389
400
  contents: elementContents(node),
390
401
  elementType: 'div',
@@ -393,7 +404,7 @@ const encoders = {
393
404
  keywords_section: (node, parent, path, priority) => ({
394
405
  category: buildSectionCategory(node),
395
406
  priority: priority.value++,
396
- title: inlineContentsOfNodeType(node, node.type.schema.nodes.section_title),
407
+ title: inlineContentsOfNodeType(node, node.type.schema.nodes.section_title_plain),
397
408
  path: path.concat([node.attrs.id]),
398
409
  elementIDs: childElements(node)
399
410
  .map((childNode) => childNode.attrs.id)
@@ -30,6 +30,7 @@ export const nodeNames = new Map([
30
30
  [schema.nodes.paragraph, 'Paragraph'],
31
31
  [schema.nodes.section, 'Section'],
32
32
  [schema.nodes.section_title, 'Section'],
33
+ [schema.nodes.section_title_plain, 'Section'],
33
34
  [schema.nodes.table, 'Table'],
34
35
  [schema.nodes.table_element, 'Table'],
35
36
  [schema.nodes.blockquote_element, 'Block Quote'],
@@ -35,6 +35,7 @@ export const nodeTypesMap = new Map([
35
35
  [schema.nodes.graphical_abstract_section, ObjectTypes.Section],
36
36
  [schema.nodes.highlight_marker, ObjectTypes.HighlightMarker],
37
37
  [schema.nodes.inline_equation, ObjectTypes.InlineMathFragment],
38
+ [schema.nodes.keyword, ObjectTypes.Keyword],
38
39
  [schema.nodes.keywords_element, ObjectTypes.KeywordsElement],
39
40
  [schema.nodes.keywords_section, ObjectTypes.Section],
40
41
  [schema.nodes.listing, ObjectTypes.Listing],
@@ -18,6 +18,7 @@ import { Marks, Nodes } from './types';
18
18
  export * from './groups';
19
19
  export * from './types';
20
20
  export * from './nodes/comment';
21
+ export * from './nodes/comment_list';
21
22
  export * from './nodes/attribution';
22
23
  export * from './nodes/bibliography_item';
23
24
  export * from './nodes/bibliography_element';
@@ -41,6 +42,7 @@ export * from './nodes/hard_break';
41
42
  export * from './nodes/highlight_marker';
42
43
  export * from './nodes/inline_equation';
43
44
  export * from './nodes/inline_footnote';
45
+ export * from './nodes/keyword';
44
46
  export * from './nodes/keywords_element';
45
47
  export * from './nodes/keywords_section';
46
48
  export * from './nodes/link';
@@ -13,6 +13,7 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
+ import { Contribution } from '@manuscripts/json-schema';
16
17
  import { NodeSpec } from 'prosemirror-model';
17
18
  import { ManuscriptNode } from '../types';
18
19
  interface Attrs {
@@ -23,6 +24,9 @@ interface Attrs {
23
24
  from: number;
24
25
  to: number;
25
26
  };
27
+ resolved?: boolean;
28
+ contributions?: Contribution[];
29
+ originalText?: string;
26
30
  }
27
31
  export interface CommentNode extends ManuscriptNode {
28
32
  attrs: Attrs;
@@ -0,0 +1,28 @@
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
+ import { CommentNode } from './comment';
19
+ interface Attrs {
20
+ id: string;
21
+ contents: string;
22
+ comments?: CommentNode[];
23
+ }
24
+ export interface KeywordNode extends ManuscriptNode {
25
+ attrs: Attrs;
26
+ }
27
+ export declare const keyword: NodeSpec;
28
+ export {};
@@ -16,9 +16,9 @@
16
16
  import { NodeSpec } from 'prosemirror-model';
17
17
  import { ManuscriptNode } from '../types';
18
18
  interface Attrs {
19
- id: string;
20
19
  contents: string;
21
- paragraphStyle: string;
20
+ id: string;
21
+ paragraphStyle?: string;
22
22
  }
23
23
  export interface KeywordsElementNode extends ManuscriptNode {
24
24
  attrs: Attrs;
@@ -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' | 'keywords_element' | 'keywords_section' | 'link' | 'list_item' | 'listing' | 'listing_element' | 'manuscript' | 'missing_figure' | 'ordered_list' | 'paragraph' | 'placeholder' | 'placeholder_element' | 'pullquote_element' | 'section' | 'section_label' | 'section_title' | 'table' | 'table_body' | 'table_cell' | 'table_element' | 'table_row' | 'table_colgroup' | 'table_col' | 'text' | 'toc_element' | 'toc_section';
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_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';
21
21
  export type ManuscriptSchema = Schema<Nodes, Marks>;
22
22
  export type ManuscriptEditorState = EditorState;
23
23
  export type ManuscriptEditorView = EditorView;
@@ -34,6 +34,7 @@ export declare class Decoder {
34
34
  createArticleNode: (manuscriptID?: string) => ManuscriptNode;
35
35
  addGeneratedLabels: (sections: Section[]) => Section[];
36
36
  parseContents: (contents: string, wrapper?: string, commentAnnotations?: CommentAnnotation[], options?: ParseOptions) => ManuscriptNode;
37
+ private getKeywords;
37
38
  private getManuscriptID;
38
39
  private getFigcaption;
39
40
  }
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.1.0",
4
+ "version": "1.1.1-LEAN-2322",
5
5
  "repository": "github:Atypon-OpenSource/manuscripts-transform",
6
6
  "license": "Apache-2.0",
7
7
  "main": "dist/cjs",