@manuscripts/transform 4.5.2 → 4.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/dist/cjs/jats/__tests__/data/section-categories.js +5 -5
  2. package/dist/cjs/jats/__tests__/jats-importer.test.js +19 -5
  3. package/dist/cjs/jats/exporter/jats-exporter.js +725 -910
  4. package/dist/cjs/jats/exporter/jats-versions.js +9 -9
  5. package/dist/cjs/jats/importer/jats-dom-parser.js +25 -24
  6. package/dist/cjs/jats/importer/jats-transformations.js +14 -30
  7. package/dist/cjs/lib/section-categories.js +31 -1
  8. package/dist/cjs/schema/index.js +3 -0
  9. package/dist/cjs/schema/migration/migration-scripts/4.5.3.js +37 -0
  10. package/dist/cjs/schema/migration/migration-scripts/index.js +2 -0
  11. package/dist/cjs/schema/nodes/abstract.js +51 -0
  12. package/dist/cjs/schema/nodes/abstracts.js +1 -1
  13. package/dist/cjs/transformer/node-names.js +1 -0
  14. package/dist/cjs/transformer/node-title.js +2 -0
  15. package/dist/cjs/version.js +1 -1
  16. package/dist/es/jats/__tests__/data/section-categories.js +5 -5
  17. package/dist/es/jats/__tests__/jats-importer.test.js +19 -5
  18. package/dist/es/jats/exporter/jats-exporter.js +728 -913
  19. package/dist/es/jats/exporter/jats-versions.js +7 -7
  20. package/dist/es/jats/importer/jats-dom-parser.js +25 -24
  21. package/dist/es/jats/importer/jats-transformations.js +14 -30
  22. package/dist/es/lib/section-categories.js +28 -0
  23. package/dist/es/schema/index.js +3 -0
  24. package/dist/es/schema/migration/migration-scripts/4.5.3.js +35 -0
  25. package/dist/es/schema/migration/migration-scripts/index.js +2 -0
  26. package/dist/es/schema/nodes/abstract.js +47 -0
  27. package/dist/es/schema/nodes/abstracts.js +1 -1
  28. package/dist/es/transformer/node-names.js +1 -0
  29. package/dist/es/transformer/node-title.js +2 -0
  30. package/dist/es/version.js +1 -1
  31. package/dist/types/jats/exporter/jats-exporter.d.ts +31 -27
  32. package/dist/types/jats/exporter/jats-versions.d.ts +4 -4
  33. package/dist/types/jats/importer/jats-dom-parser.d.ts +0 -1
  34. package/dist/types/lib/section-categories.d.ts +3 -0
  35. package/dist/types/schema/index.d.ts +1 -0
  36. package/dist/types/schema/migration/migration-scripts/4.5.3.d.ts +8 -0
  37. package/dist/types/schema/migration/migration-scripts/index.d.ts +2 -1
  38. package/dist/types/schema/nodes/abstract.d.ts +26 -0
  39. package/dist/types/schema/types.d.ts +1 -1
  40. package/dist/types/version.d.ts +1 -1
  41. package/package.json +1 -1
  42. package/src/jats/__tests__/__snapshots__/jats-exporter.test.ts.snap +3 -3
  43. package/src/jats/__tests__/__snapshots__/jats-importer.test.ts.snap +86 -132
  44. package/src/jats/__tests__/__snapshots__/jats-roundtrip.test.ts.snap +3 -3
  45. package/src/jats/__tests__/data/section-categories.ts +5 -5
  46. package/src/jats/__tests__/jats-importer.test.ts +22 -6
  47. package/src/jats/exporter/jats-exporter.ts +855 -1126
  48. package/src/jats/exporter/jats-versions.ts +11 -11
  49. package/src/jats/importer/jats-dom-parser.ts +34 -34
  50. package/src/jats/importer/jats-transformations.ts +21 -37
  51. package/src/lib/section-categories.ts +36 -0
  52. package/src/schema/index.ts +3 -0
  53. package/src/schema/migration/migration-scripts/4.5.3.ts +57 -0
  54. package/src/schema/migration/migration-scripts/index.ts +2 -0
  55. package/src/schema/nodes/abstract.ts +66 -0
  56. package/src/schema/nodes/abstracts.ts +2 -1
  57. package/src/schema/types.ts +1 -0
  58. package/src/transformer/node-names.ts +1 -0
  59. package/src/transformer/node-title.ts +2 -0
  60. package/src/version.ts +1 -1
@@ -14,35 +14,35 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- interface VersionIds {
18
- publicId: string
19
- systemId: string
17
+ interface VersionIDs {
18
+ publicID: string
19
+ systemID: string
20
20
  }
21
21
 
22
22
  export type Version = '1.1' | '1.2d1' | '1.2'
23
23
 
24
- const versions: { [key in Version]: VersionIds } = {
24
+ const versions: { [key in Version]: VersionIDs } = {
25
25
  '1.1': {
26
- publicId:
26
+ publicID:
27
27
  '-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD with OASIS Tables with MathML3 v1.1 20151215//EN',
28
- systemId:
28
+ systemID:
29
29
  'http://jats.nlm.nih.gov/archiving/1.1/JATS-archive-oasis-article1-mathml3.dtd',
30
30
  },
31
31
  '1.2d1': {
32
- publicId:
32
+ publicID:
33
33
  '-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD with OASIS Tables with MathML3 v1.2d1 20170631//EN',
34
- systemId:
34
+ systemID:
35
35
  'http://jats.nlm.nih.gov/archiving/1.2d1/JATS-archive-oasis-article1-mathml3.dtd',
36
36
  },
37
37
  '1.2': {
38
- publicId:
38
+ publicID:
39
39
  '-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD with OASIS Tables with MathML3 v1.2 20190208//EN',
40
- systemId:
40
+ systemID:
41
41
  'http://jats.nlm.nih.gov/archiving/1.2/JATS-archive-oasis-article1-mathml3.dtd',
42
42
  },
43
43
  }
44
44
 
45
- export const selectVersionIds = (version: Version): VersionIds => {
45
+ export const selectVersionIDs = (version: Version): VersionIDs => {
46
46
  if (!(version in versions)) {
47
47
  throw new Error(`Unknown version ${version}`)
48
48
  }
@@ -15,6 +15,10 @@
15
15
  */
16
16
  import { DOMParser, Fragment, ParseOptions, Schema } from 'prosemirror-model'
17
17
 
18
+ import {
19
+ abstractTypeToCategory,
20
+ findMatchingCategory,
21
+ } from '../../lib/section-categories'
18
22
  import {
19
23
  dateToTimestamp,
20
24
  getCreditRole,
@@ -46,38 +50,19 @@ export class JATSDOMParser {
46
50
  return this.parser.parse(doc, options)
47
51
  }
48
52
 
49
- private isMatchingCategory(
50
- secType: string | null,
51
- titleNode: Element | null,
52
- category: SectionCategory
53
- ) {
54
- if (
55
- (secType && category.synonyms.includes(secType)) ||
56
- category.id === secType
57
- ) {
58
- return true
59
- }
60
- if (titleNode && titleNode.nodeName === 'title' && titleNode.textContent) {
61
- const textContent = titleNode.textContent.trim().toLowerCase()
62
- if (category.synonyms.includes(textContent)) {
63
- return true
64
- }
65
- }
66
- return false
67
- }
68
-
69
53
  private chooseSectionCategory(section: HTMLElement) {
70
54
  const secType = section.getAttribute('sec-type')
71
55
  const abstractType = section.getAttribute('abstract-type')
72
- const effectiveSecType =
73
- secType || (abstractType ? `abstract-${abstractType}` : null)
56
+ const effectiveSecType = secType ?? abstractType
74
57
  const titleNode = section.firstElementChild
58
+ const titleText =
59
+ titleNode?.nodeName === 'title' ? titleNode.textContent : null
75
60
 
76
- for (const category of this.sectionCategories) {
77
- if (this.isMatchingCategory(effectiveSecType, titleNode, category)) {
78
- return category.id
79
- }
80
- }
61
+ return findMatchingCategory(
62
+ this.sectionCategories,
63
+ effectiveSecType,
64
+ titleText
65
+ )?.id
81
66
  }
82
67
 
83
68
  private parsePriority = (priority: string | null) => {
@@ -636,6 +621,10 @@ export class JATSDOMParser {
636
621
  tag: 'history',
637
622
  ignore: true,
638
623
  },
624
+ {
625
+ tag: 'statement',
626
+ ignore: true,
627
+ },
639
628
  {
640
629
  tag: 'break',
641
630
  node: 'hard_break',
@@ -995,10 +984,8 @@ export class JATSDOMParser {
995
984
  node: 'footnotes_section', // NOTE: higher priority than 'section'
996
985
  getAttrs: (node) => {
997
986
  const element = node as HTMLElement
998
-
999
987
  return {
1000
988
  id: element.getAttribute('id'),
1001
- // category: chooseSectionCategory(element), // 'MPSectionCategory:endnotes',
1002
989
  }
1003
990
  },
1004
991
  },
@@ -1024,7 +1011,7 @@ export class JATSDOMParser {
1024
1011
  },
1025
1012
  },
1026
1013
  {
1027
- tag: 'trans-abstract[sec-type="abstract-graphical"]',
1014
+ tag: 'trans-abstract[abstract-type="graphical"]',
1028
1015
  node: 'trans_graphical_abstract',
1029
1016
  getAttrs: (node) => {
1030
1017
  const element = node as HTMLElement
@@ -1035,7 +1022,7 @@ export class JATSDOMParser {
1035
1022
  },
1036
1023
  },
1037
1024
  {
1038
- tag: 'trans-abstract[sec-type="abstract-key-image"]',
1025
+ tag: 'trans-abstract[abstract-type="key-image"]',
1039
1026
  node: 'trans_graphical_abstract',
1040
1027
  getAttrs: (node) => {
1041
1028
  const element = node as HTMLElement
@@ -1095,7 +1082,7 @@ export class JATSDOMParser {
1095
1082
  getAttrs: (node) => this.parseRef(node as Element),
1096
1083
  },
1097
1084
  {
1098
- tag: 'sec[sec-type="abstract-graphical"]',
1085
+ tag: 'abstract[abstract-type="graphical"]',
1099
1086
  node: 'graphical_abstract_section',
1100
1087
  getAttrs: (node) => {
1101
1088
  const element = node as HTMLElement
@@ -1105,7 +1092,7 @@ export class JATSDOMParser {
1105
1092
  },
1106
1093
  },
1107
1094
  {
1108
- tag: 'sec[sec-type="abstract-key-image"]',
1095
+ tag: 'abstract[abstract-type="key-image"]',
1109
1096
  node: 'graphical_abstract_section',
1110
1097
  getAttrs: (node) => {
1111
1098
  const element = node as HTMLElement
@@ -1114,6 +1101,19 @@ export class JATSDOMParser {
1114
1101
  }
1115
1102
  },
1116
1103
  },
1104
+ {
1105
+ tag: 'abstract',
1106
+ node: 'abstract',
1107
+ getAttrs: (node) => {
1108
+ const element = node as HTMLElement
1109
+ return {
1110
+ id: element.getAttribute('id'),
1111
+ category:
1112
+ this.chooseSectionCategory(element) ||
1113
+ abstractTypeToCategory(element.getAttribute('abstract-type')),
1114
+ }
1115
+ },
1116
+ },
1117
1117
  {
1118
1118
  tag: 'sec',
1119
1119
  node: 'section',
@@ -1179,7 +1179,7 @@ export class JATSDOMParser {
1179
1179
  tag: 'title',
1180
1180
  node: 'section_title',
1181
1181
  context:
1182
- 'section/|footnotes_section/|bibliography_section/|keywords/|supplements/|author_notes/|graphical_abstract_section/|trans_abstract/|trans_graphical_abstract/',
1182
+ 'section/|footnotes_section/|bibliography_section/|keywords/|supplements/|author_notes/|abstract/|graphical_abstract_section/|trans_abstract/|trans_graphical_abstract/',
1183
1183
  },
1184
1184
  {
1185
1185
  tag: 'tr',
@@ -15,7 +15,10 @@
15
15
  */
16
16
 
17
17
  import { defaultTitle } from '../../lib/deafults'
18
- import { XML_NAMESPACE } from '../../lib/xml'
18
+ import {
19
+ abstractTypeToCategory,
20
+ findMatchingCategory,
21
+ } from '../../lib/section-categories'
19
22
  import { SectionCategory, SectionGroup } from '../../schema'
20
23
  import { htmlFromJatsNode } from './jats-parser-utils'
21
24
 
@@ -160,12 +163,7 @@ export const moveAbstracts = (
160
163
  'article-meta > abstract, article-meta > trans-abstract'
161
164
  )
162
165
  abstracts.forEach((abstract) => {
163
- const sec = createAbstractSection(
164
- abstract,
165
- createElement,
166
- sectionCategories
167
- )
168
- removeNodeFromParent(abstract)
166
+ const sec = prepareAbstract(abstract, createElement, sectionCategories)
169
167
  group.appendChild(sec)
170
168
  })
171
169
  }
@@ -259,9 +257,7 @@ const moveSpecialFootnotes = (
259
257
  const fns = [...doc.querySelectorAll('fn[fn-type]')]
260
258
  for (const fn of fns) {
261
259
  const type = fn.getAttribute('fn-type') || '' //Cannot be null since it is queried above
262
- const category = sectionCategories.find((category) =>
263
- category.synonyms.includes(type)
264
- )
260
+ const category = findMatchingCategory(sectionCategories, type)
265
261
  if (category) {
266
262
  const section = createElement('sec')
267
263
  const fnTitle =
@@ -300,41 +296,29 @@ export const moveCaptionsToEnd = (body: Element) => {
300
296
  }
301
297
  }
302
298
 
303
- const createAbstractSection = (
299
+ const prepareAbstract = (
304
300
  abstract: Element,
305
301
  createElement: CreateElement,
306
302
  sectionCategories?: SectionCategory[]
307
303
  ) => {
308
- const abstractType = abstract.getAttribute('abstract-type')
309
- const sectionType = abstractType ? `abstract-${abstractType}` : 'abstract'
310
- let section = createElement('sec')
311
- if (abstract.nodeName === 'trans-abstract') {
312
- section = createElement('trans-abstract')
313
- const lang = abstract.getAttributeNS(XML_NAMESPACE, 'lang')
314
- if (lang) {
315
- section.setAttributeNS(XML_NAMESPACE, 'lang', lang)
316
- }
317
- }
318
- section.setAttribute('sec-type', sectionType)
304
+ const rawType = abstract.getAttribute('abstract-type')
305
+ const category = abstractTypeToCategory(rawType)
306
+
319
307
  if (!abstract.querySelector(':scope > title')) {
308
+ const matched =
309
+ sectionCategories && findMatchingCategory(sectionCategories, category)
320
310
  const title = createElement('title')
321
- const category = sectionCategories?.find(
322
- (c) => c.id === sectionType || c.synonyms.includes(sectionType)
323
- )
324
- if (category?.titles[0]) {
325
- title.textContent = category.titles[0]
326
- } else {
327
- title.textContent = abstractType
328
- ? `${capitalizeFirstLetter(abstractType.split('-').join(' '))} Abstract`
329
- : 'Abstract'
330
- }
331
- section.appendChild(title)
332
- }
333
311
 
334
- while (abstract.firstChild) {
335
- section.appendChild(abstract.firstChild)
312
+ title.textContent =
313
+ matched?.titles[0] ??
314
+ (rawType
315
+ ? `${capitalizeFirstLetter(rawType.split('-').join(' '))} Abstract`
316
+ : 'Abstract')
317
+
318
+ abstract.insertBefore(title, abstract.firstChild)
336
319
  }
337
- return section
320
+
321
+ return abstract
338
322
  }
339
323
 
340
324
  const createAcknowledgmentsSection = (
@@ -25,3 +25,39 @@ export const getGroupCategories = (
25
25
  : Array.from(sections.values())
26
26
  return sectionsArray.filter((section) => section.group === group)
27
27
  }
28
+
29
+ export const findMatchingCategory = (
30
+ categories: SectionCategory[],
31
+ type?: string | null,
32
+ titleText?: string | null
33
+ ): SectionCategory | undefined => {
34
+ return categories.find((category) => {
35
+ if (type && (category.id === type || category.synonyms.includes(type))) {
36
+ return true
37
+ }
38
+ if (titleText) {
39
+ const normalizedTitle = titleText.trim().toLowerCase()
40
+ if (category.synonyms.includes(normalizedTitle)) {
41
+ return true
42
+ }
43
+ }
44
+ return false
45
+ })
46
+ }
47
+
48
+ export const abstractTypeToCategory = (abstractType: string | null) =>
49
+ abstractType || 'abstract'
50
+
51
+ export const FOOTNOTE_SECTION_CATEGORY_IDS = [
52
+ 'con',
53
+ 'conflict',
54
+ 'deceased',
55
+ 'equal',
56
+ 'present-address',
57
+ 'presented-at',
58
+ 'previously-at',
59
+ 'supplementary-material',
60
+ 'supported-by',
61
+ 'financial-disclosure',
62
+ 'coi-statement',
63
+ ]
@@ -30,6 +30,7 @@ import {
30
30
  tracked_insert,
31
31
  underline,
32
32
  } from './marks'
33
+ import { abstract } from './nodes/abstract'
33
34
  import { abstracts } from './nodes/abstracts'
34
35
  import { affiliation } from './nodes/affiliation'
35
36
  import { affiliations } from './nodes/affiliations'
@@ -112,6 +113,7 @@ import { transGraphicalAbstract } from './nodes/trans_graphical_abstract'
112
113
  import { Marks, Nodes } from './types'
113
114
 
114
115
  export * from './groups'
116
+ export * from './nodes/abstract'
115
117
  export * from './nodes/affiliation'
116
118
  export * from './nodes/affiliations'
117
119
  export * from './nodes/alt_text'
@@ -215,6 +217,7 @@ export const schema = new Schema<Nodes, Marks>({
215
217
  caption,
216
218
  caption_title: captionTitle,
217
219
  citation,
220
+ abstract,
218
221
  abstracts,
219
222
  body,
220
223
  backmatter,
@@ -0,0 +1,57 @@
1
+ /*!
2
+ * © 2026 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 { JSONProsemirrorNode } from '../../../types'
17
+ import { MigrationScript } from '../migration-script'
18
+
19
+ const TRANS_ABSTRACT_TYPES = ['trans_abstract', 'trans_graphical_abstract']
20
+
21
+ class Migration453 implements MigrationScript {
22
+ fromVersion = '4.5.2'
23
+ toVersion = '4.5.3'
24
+
25
+ migrateNode(node: JSONProsemirrorNode): JSONProsemirrorNode {
26
+ if (node.type !== 'abstracts' || !node.content) {
27
+ return node
28
+ }
29
+
30
+ const children = node.content.map((child) => {
31
+ const type = child.type === 'section' ? 'abstract' : child.type
32
+ const category = child.attrs?.category
33
+ const attrs =
34
+ category && category.startsWith('abstract-')
35
+ ? { ...child.attrs, category: category.slice('abstract-'.length) }
36
+ : child.attrs
37
+ return { ...child, type, attrs }
38
+ })
39
+
40
+ const regular: JSONProsemirrorNode[] = []
41
+ const translated: JSONProsemirrorNode[] = []
42
+ for (const child of children) {
43
+ if (TRANS_ABSTRACT_TYPES.includes(child.type)) {
44
+ translated.push(child)
45
+ } else {
46
+ regular.push(child)
47
+ }
48
+ }
49
+
50
+ return {
51
+ ...node,
52
+ content: [...regular, ...translated],
53
+ }
54
+ }
55
+ }
56
+
57
+ export default Migration453
@@ -30,6 +30,7 @@ import Migration4334 from './4.3.34'
30
30
  import Migration4335 from './4.3.35'
31
31
  import Migration442 from './4.4.2'
32
32
  import Migration447 from './4.4.7'
33
+ import Migration453 from './4.5.3'
33
34
 
34
35
  const migrations = [
35
36
  new Migration125(),
@@ -48,6 +49,7 @@ const migrations = [
48
49
  new Migration4335(),
49
50
  new Migration442(),
50
51
  new Migration447(),
52
+ new Migration453(),
51
53
  ]
52
54
 
53
55
  export default migrations
@@ -0,0 +1,66 @@
1
+ /*!
2
+ * © 2026 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
+
17
+ import { NodeSpec } from 'prosemirror-model'
18
+
19
+ import { ManuscriptNode } from '../types'
20
+
21
+ export interface AbstractAttrs {
22
+ id: string
23
+ category: string
24
+ }
25
+
26
+ export interface AbstractNode extends ManuscriptNode {
27
+ attrs: AbstractAttrs
28
+ }
29
+
30
+ export const abstract: NodeSpec = {
31
+ content: 'section_label? section_title (paragraph | element)* sections*',
32
+ attrs: {
33
+ id: { default: '' },
34
+ category: { default: '' },
35
+ dataTracked: { default: null },
36
+ },
37
+ group: 'block sections',
38
+ selectable: false,
39
+ parseDOM: [
40
+ {
41
+ tag: 'section.abstract',
42
+ getAttrs: (dom) => {
43
+ const element = dom as HTMLElement
44
+ return {
45
+ id: element.getAttribute('id') || '',
46
+ category: element.getAttribute('data-category') || '',
47
+ }
48
+ },
49
+ },
50
+ ],
51
+ toDOM: (node) => {
52
+ const abstractNode = node as AbstractNode
53
+ const { id, category } = abstractNode.attrs
54
+
55
+ const attrs: { [key: string]: string } = { id, class: 'abstract' }
56
+
57
+ if (category) {
58
+ attrs['data-category'] = category
59
+ }
60
+
61
+ return ['section', attrs, 0]
62
+ },
63
+ }
64
+
65
+ export const isAbstractNode = (node: ManuscriptNode): node is AbstractNode =>
66
+ node.type === node.type.schema.nodes.abstract
@@ -20,7 +20,8 @@ import { NodeSpec } from 'prosemirror-model'
20
20
  // It exists for the purpose of styling in the UI
21
21
 
22
22
  export const abstracts: NodeSpec = {
23
- content: 'sections* (trans_abstract | trans_graphical_abstract)*',
23
+ content:
24
+ '(abstract | graphical_abstract_section)* (trans_abstract | trans_graphical_abstract)*',
24
25
  attrs: {
25
26
  id: { default: '' },
26
27
  },
@@ -84,6 +84,7 @@ export type Nodes =
84
84
  | 'listing'
85
85
  | 'listing_element'
86
86
  | 'manuscript'
87
+ | 'abstract'
87
88
  | 'abstracts'
88
89
  | 'body'
89
90
  | 'backmatter'
@@ -54,6 +54,7 @@ export const nodeNames: Map<ManuscriptNodeType, string> = new Map([
54
54
  [schema.nodes.paragraph, 'Paragraph'],
55
55
  [schema.nodes.text_block, 'Paragraph'],
56
56
  [schema.nodes.section, 'Section'],
57
+ [schema.nodes.abstract, 'Abstract'],
57
58
  [schema.nodes.graphical_abstract_section, 'Graphical Abstract'],
58
59
  [schema.nodes.trans_abstract, 'Trans Abstract'],
59
60
  [schema.nodes.trans_graphical_abstract, 'Trans Graphical Abstract'],
@@ -62,6 +62,7 @@ export const nodeTitle = (node: ManuscriptNode) => {
62
62
  return snippetOfNodeType(node, nodes.title)
63
63
 
64
64
  case nodes.section:
65
+ case nodes.abstract:
65
66
  case nodes.bibliography_section:
66
67
  case nodes.footnotes_section:
67
68
  case nodes.keywords:
@@ -105,6 +106,7 @@ export const nodeTitlePlaceholder = (nodeType: NodeType) => {
105
106
  return 'Untitled Manuscript'
106
107
 
107
108
  case nodes.section:
109
+ case nodes.abstract:
108
110
  return 'Untitled Section'
109
111
 
110
112
  case nodes.bibliography_section:
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const VERSION = "4.5.2";
1
+ export const VERSION = "4.5.4";