@manuscripts/transform 1.1.0 → 1.1.1

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,
@@ -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), {
@@ -559,6 +569,19 @@ class Decoder {
559
569
  id: (0, id_1.generateNodeID)(schema_1.schema.nodes.section),
560
570
  }));
561
571
  }
572
+ const keywordsSection = getSections(this.modelMap).filter((section) => section.category === 'MPSectionCategory:keywords');
573
+ const keywords = this.getKeywords();
574
+ if (keywordsSection.length === 0 && keywords.length > 0) {
575
+ const keywordsSection = schema_1.schema.nodes.keywords_section.createAndFill({
576
+ id: (0, id_1.generateNodeID)(schema_1.schema.nodes.keywords_section),
577
+ }, [
578
+ schema_1.schema.nodes.section_title_plain.create({}, schema_1.schema.text('Keywords')),
579
+ schema_1.schema.nodes.keywords_element.create({
580
+ id: (0, id_1.generateNodeID)(schema_1.schema.nodes.keywords_element),
581
+ }, keywords),
582
+ ]);
583
+ rootSectionNodes.unshift(keywordsSection);
584
+ }
562
585
  const contents = rootSectionNodes;
563
586
  if (this.comments.size) {
564
587
  const comments = schema_1.schema.nodes.comment_list.createAndFill({
@@ -601,10 +624,28 @@ class Decoder {
601
624
  }
602
625
  const template = document.createElement('template');
603
626
  template.innerHTML = html;
604
- if (!template.content.firstChild) {
627
+ if (!template.content.firstElementChild) {
605
628
  throw new Error('No content could be parsed');
606
629
  }
607
- return parser.parse(template.content.firstChild, options);
630
+ return parser.parse(template.content.firstElementChild, options);
631
+ };
632
+ this.getKeywords = () => {
633
+ const keywordsOfKind = [];
634
+ for (const model of this.modelMap.values()) {
635
+ const commentNodes = this.createCommentsNode(model);
636
+ commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
637
+ if (isKeyword(model)) {
638
+ const keyword = this.parseContents(model.name || '', 'div', this.getComments(model), {
639
+ topNode: schema_1.schema.nodes.keyword.create({
640
+ id: model._id,
641
+ contents: model.name,
642
+ comments: commentNodes.map((c) => c.attrs.id),
643
+ }),
644
+ });
645
+ keywordsOfKind.push(keyword);
646
+ }
647
+ }
648
+ return keywordsOfKind;
608
649
  };
609
650
  this.getManuscriptID = () => {
610
651
  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) => {
@@ -393,6 +397,10 @@ const encoders = {
393
397
  SVGRepresentation: node.attrs.SVGRepresentation,
394
398
  SVGGlyphs: svgDefs(node.attrs.SVGRepresentation),
395
399
  }),
400
+ keyword: (node, parent) => ({
401
+ containerID: parent.attrs.id,
402
+ name: keywordContents(node),
403
+ }),
396
404
  keywords_element: (node) => ({
397
405
  contents: elementContents(node),
398
406
  elementType: 'div',
@@ -401,7 +409,7 @@ const encoders = {
401
409
  keywords_section: (node, parent, path, priority) => ({
402
410
  category: (0, section_category_1.buildSectionCategory)(node),
403
411
  priority: priority.value++,
404
- title: inlineContentsOfNodeType(node, node.type.schema.nodes.section_title),
412
+ title: inlineContentsOfNodeType(node, node.type.schema.nodes.section_title_plain),
405
413
  path: path.concat([node.attrs.id]),
406
414
  elementIDs: childElements(node)
407
415
  .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,
@@ -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), {
@@ -549,6 +559,19 @@ export class Decoder {
549
559
  id: generateNodeID(schema.nodes.section),
550
560
  }));
551
561
  }
562
+ const keywordsSection = getSections(this.modelMap).filter((section) => section.category === 'MPSectionCategory:keywords');
563
+ const keywords = this.getKeywords();
564
+ if (keywordsSection.length === 0 && keywords.length > 0) {
565
+ const keywordsSection = schema.nodes.keywords_section.createAndFill({
566
+ id: generateNodeID(schema.nodes.keywords_section),
567
+ }, [
568
+ schema.nodes.section_title_plain.create({}, schema.text('Keywords')),
569
+ schema.nodes.keywords_element.create({
570
+ id: generateNodeID(schema.nodes.keywords_element),
571
+ }, keywords),
572
+ ]);
573
+ rootSectionNodes.unshift(keywordsSection);
574
+ }
552
575
  const contents = rootSectionNodes;
553
576
  if (this.comments.size) {
554
577
  const comments = schema.nodes.comment_list.createAndFill({
@@ -591,10 +614,28 @@ export class Decoder {
591
614
  }
592
615
  const template = document.createElement('template');
593
616
  template.innerHTML = html;
594
- if (!template.content.firstChild) {
617
+ if (!template.content.firstElementChild) {
595
618
  throw new Error('No content could be parsed');
596
619
  }
597
- return parser.parse(template.content.firstChild, options);
620
+ return parser.parse(template.content.firstElementChild, options);
621
+ };
622
+ this.getKeywords = () => {
623
+ const keywordsOfKind = [];
624
+ for (const model of this.modelMap.values()) {
625
+ const commentNodes = this.createCommentsNode(model);
626
+ commentNodes.forEach((c) => this.comments.set(c.attrs.id, c));
627
+ if (isKeyword(model)) {
628
+ const keyword = this.parseContents(model.name || '', 'div', this.getComments(model), {
629
+ topNode: schema.nodes.keyword.create({
630
+ id: model._id,
631
+ contents: model.name,
632
+ comments: commentNodes.map((c) => c.attrs.id),
633
+ }),
634
+ });
635
+ keywordsOfKind.push(keyword);
636
+ }
637
+ }
638
+ return keywordsOfKind;
598
639
  };
599
640
  this.getManuscriptID = () => {
600
641
  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;
@@ -385,6 +389,10 @@ const encoders = {
385
389
  SVGRepresentation: node.attrs.SVGRepresentation,
386
390
  SVGGlyphs: svgDefs(node.attrs.SVGRepresentation),
387
391
  }),
392
+ keyword: (node, parent) => ({
393
+ containerID: parent.attrs.id,
394
+ name: keywordContents(node),
395
+ }),
388
396
  keywords_element: (node) => ({
389
397
  contents: elementContents(node),
390
398
  elementType: 'div',
@@ -393,7 +401,7 @@ const encoders = {
393
401
  keywords_section: (node, parent, path, priority) => ({
394
402
  category: buildSectionCategory(node),
395
403
  priority: priority.value++,
396
- title: inlineContentsOfNodeType(node, node.type.schema.nodes.section_title),
404
+ title: inlineContentsOfNodeType(node, node.type.schema.nodes.section_title_plain),
397
405
  path: path.concat([node.attrs.id]),
398
406
  elementIDs: childElements(node)
399
407
  .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';
@@ -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",
5
5
  "repository": "github:Atypon-OpenSource/manuscripts-transform",
6
6
  "license": "Apache-2.0",
7
7
  "main": "dist/cjs",