@manuscripts/transform 4.4.0 → 4.4.2

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 (67) hide show
  1. package/dist/cjs/jats/exporter/jats-exporter.js +20 -6
  2. package/dist/cjs/jats/importer/jats-dom-parser.js +51 -2
  3. package/dist/cjs/jats/importer/jats-transformations.js +1 -1
  4. package/dist/cjs/schema/index.js +9 -0
  5. package/dist/cjs/schema/migration/migration-scripts/4.4.2.js +44 -0
  6. package/dist/cjs/schema/migration/migration-scripts/index.js +2 -0
  7. package/dist/cjs/schema/nodes/box_element.js +4 -0
  8. package/dist/cjs/schema/nodes/headshot_element.js +38 -0
  9. package/dist/cjs/schema/nodes/headshot_grid.js +37 -0
  10. package/dist/cjs/schema/nodes/headshot_image.js +51 -0
  11. package/dist/cjs/schema/nodes/hero_image.js +2 -0
  12. package/dist/cjs/schema/nodes/pullquote_element.js +4 -0
  13. package/dist/cjs/schema/nodes/table_element.js +9 -8
  14. package/dist/cjs/transformer/node-names.js +2 -0
  15. package/dist/cjs/transformer/node-title.js +6 -0
  16. package/dist/cjs/version.js +1 -1
  17. package/dist/es/jats/exporter/jats-exporter.js +20 -6
  18. package/dist/es/jats/importer/jats-dom-parser.js +51 -2
  19. package/dist/es/jats/importer/jats-transformations.js +1 -1
  20. package/dist/es/schema/index.js +9 -0
  21. package/dist/es/schema/migration/migration-scripts/4.4.2.js +42 -0
  22. package/dist/es/schema/migration/migration-scripts/index.js +2 -0
  23. package/dist/es/schema/nodes/box_element.js +4 -0
  24. package/dist/es/schema/nodes/headshot_element.js +34 -0
  25. package/dist/es/schema/nodes/headshot_grid.js +33 -0
  26. package/dist/es/schema/nodes/headshot_image.js +48 -0
  27. package/dist/es/schema/nodes/hero_image.js +2 -0
  28. package/dist/es/schema/nodes/pullquote_element.js +4 -0
  29. package/dist/es/schema/nodes/table_element.js +9 -8
  30. package/dist/es/transformer/node-names.js +2 -0
  31. package/dist/es/transformer/node-title.js +6 -0
  32. package/dist/es/version.js +1 -1
  33. package/dist/types/schema/index.d.ts +3 -0
  34. package/dist/types/schema/migration/migration-scripts/4.4.2.d.ts +8 -0
  35. package/dist/types/schema/migration/migration-scripts/index.d.ts +2 -1
  36. package/dist/types/schema/nodes/blockquote_element.d.ts +2 -3
  37. package/dist/types/schema/nodes/box_element.d.ts +1 -0
  38. package/dist/types/schema/nodes/headshot_element.d.ts +25 -0
  39. package/dist/types/schema/nodes/headshot_grid.d.ts +24 -0
  40. package/dist/types/schema/nodes/headshot_image.d.ts +26 -0
  41. package/dist/types/schema/nodes/hero_image.d.ts +1 -0
  42. package/dist/types/schema/nodes/pullquote_element.d.ts +3 -2
  43. package/dist/types/schema/nodes/table_element.d.ts +1 -0
  44. package/dist/types/schema/types.d.ts +1 -1
  45. package/dist/types/version.d.ts +1 -1
  46. package/package.json +2 -1
  47. package/src/jats/__tests__/__fixtures__/jats-import.xml +34 -2
  48. package/src/jats/__tests__/__snapshots__/jats-importer.test.ts.snap +350 -0
  49. package/src/jats/__tests__/__snapshots__/jats-roundtrip.test.ts.snap +1 -1
  50. package/src/jats/exporter/jats-exporter.ts +24 -6
  51. package/src/jats/importer/jats-dom-parser.ts +57 -3
  52. package/src/jats/importer/jats-transformations.ts +1 -1
  53. package/src/schema/index.ts +10 -1
  54. package/src/schema/migration/migration-scripts/4.4.2.ts +60 -0
  55. package/src/schema/migration/migration-scripts/index.ts +2 -0
  56. package/src/schema/nodes/blockquote_element.ts +3 -3
  57. package/src/schema/nodes/box_element.ts +6 -0
  58. package/src/schema/nodes/headshot_element.ts +48 -0
  59. package/src/schema/nodes/headshot_grid.ts +46 -0
  60. package/src/schema/nodes/headshot_image.ts +65 -0
  61. package/src/schema/nodes/hero_image.ts +3 -0
  62. package/src/schema/nodes/pullquote_element.ts +9 -3
  63. package/src/schema/nodes/table_element.ts +12 -8
  64. package/src/schema/types.ts +3 -0
  65. package/src/transformer/node-names.ts +2 -0
  66. package/src/transformer/node-title.ts +5 -0
  67. package/src/version.ts +1 -1
@@ -0,0 +1,60 @@
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
+ class Migration442 implements MigrationScript {
20
+ fromVersion = '4.4.1'
21
+ toVersion = '4.4.2'
22
+
23
+ migrateNode(node: JSONProsemirrorNode): JSONProsemirrorNode {
24
+ switch (node.type) {
25
+ case 'hero_image':
26
+ if (!node.attrs || node.attrs.type === undefined) {
27
+ return {
28
+ ...node,
29
+ attrs: { ...(node.attrs ?? {}), type: 'leading' },
30
+ }
31
+ }
32
+ return node
33
+ case 'pullquote_element':
34
+ if (!node.attrs || node.attrs.type === undefined) {
35
+ const hasImage = node.content?.[0]?.type === 'quote_image'
36
+ return {
37
+ ...node,
38
+ attrs: {
39
+ ...(node.attrs ?? {}),
40
+ type: hasImage ? 'quote-with-image' : 'pullquote',
41
+ },
42
+ }
43
+ }
44
+ return node
45
+ case 'box_element':
46
+ case 'table_element':
47
+ if (!node.attrs || node.attrs.type === undefined) {
48
+ return {
49
+ ...node,
50
+ attrs: { ...(node.attrs ?? {}), type: '' },
51
+ }
52
+ }
53
+ return node
54
+ default:
55
+ return node
56
+ }
57
+ }
58
+ }
59
+
60
+ export default Migration442
@@ -28,6 +28,7 @@ import Migration4215 from './4.2.15'
28
28
  import Migration4323 from './4.3.23'
29
29
  import Migration4334 from './4.3.34'
30
30
  import Migration4335 from './4.3.35'
31
+ import Migration442 from './4.4.2'
31
32
 
32
33
  const migrations = [
33
34
  new Migration125(),
@@ -44,6 +45,7 @@ const migrations = [
44
45
  new Migration4323(),
45
46
  new Migration4334(),
46
47
  new Migration4335(),
48
+ new Migration442(),
47
49
  ]
48
50
 
49
51
  export default migrations
@@ -18,13 +18,13 @@ import { NodeSpec } from 'prosemirror-model'
18
18
 
19
19
  import { ManuscriptNode } from '../types'
20
20
 
21
- interface Attrs {
21
+ export interface BlockquoteElementAttrs {
22
22
  id: string
23
23
  placeholder: string
24
24
  }
25
25
 
26
26
  export interface BlockquoteElementNode extends ManuscriptNode {
27
- attrs: Attrs
27
+ attrs: BlockquoteElementAttrs
28
28
  }
29
29
 
30
30
  export const blockquoteElement: NodeSpec = {
@@ -42,7 +42,7 @@ export const blockquoteElement: NodeSpec = {
42
42
  getAttrs: (blockquote) => {
43
43
  const dom = blockquote as HTMLQuoteElement
44
44
 
45
- const attrs: Partial<Attrs> = {
45
+ const attrs: Partial<BlockquoteElementAttrs> = {
46
46
  id: dom.getAttribute('id') || undefined,
47
47
  }
48
48
 
@@ -20,6 +20,7 @@ import { ManuscriptNode } from '../types'
20
20
 
21
21
  export interface BoxElementAttrs {
22
22
  id: string
23
+ type: string
23
24
  }
24
25
 
25
26
  export interface BoxElementNode extends ManuscriptNode {
@@ -30,6 +31,7 @@ export const box_element: NodeSpec = {
30
31
  content: 'caption_title? caption? section?',
31
32
  attrs: {
32
33
  id: { default: '' },
34
+ type: { default: '' },
33
35
  dataTracked: { default: null },
34
36
  },
35
37
  group: 'block element',
@@ -56,6 +58,10 @@ export const box_element: NodeSpec = {
56
58
  attrs.id = boxElementNode.attrs.id
57
59
  }
58
60
 
61
+ if (boxElementNode.attrs.type) {
62
+ attrs['data-content-type'] = boxElementNode.attrs.type
63
+ }
64
+
59
65
  return [
60
66
  'div',
61
67
  {
@@ -0,0 +1,48 @@
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 HeadshotElementNode extends ManuscriptNode {
22
+ attrs: {
23
+ id: string
24
+ type: string
25
+ }
26
+ }
27
+
28
+ export const headshotElement: NodeSpec = {
29
+ content: 'headshot_image caption_title caption alt_text long_desc',
30
+ attrs: {
31
+ id: { default: '' },
32
+ type: { default: '' },
33
+ dataTracked: { default: null },
34
+ },
35
+ group: 'block',
36
+ toDOM: (node) => {
37
+ return [
38
+ 'div',
39
+ {
40
+ class: 'headshot_element',
41
+ id: node.attrs.id,
42
+ },
43
+ ]
44
+ },
45
+ }
46
+
47
+ export const isHeadshotElementNode = (node: ManuscriptNode): node is HeadshotElementNode =>
48
+ node.type === node.type.schema.nodes.headshot_element
@@ -0,0 +1,46 @@
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 HeadshotGridNode extends ManuscriptNode {
22
+ attrs: {
23
+ id: string
24
+ }
25
+ }
26
+
27
+ export const headshotGrid: NodeSpec = {
28
+ content: 'headshot_element*',
29
+ attrs: {
30
+ id: { default: '' },
31
+ dataTracked: { default: null },
32
+ },
33
+ group: 'block element',
34
+ toDOM: (node) => {
35
+ return [
36
+ 'div',
37
+ {
38
+ class: 'headshot_grid',
39
+ id: node.attrs.id,
40
+ },
41
+ ]
42
+ },
43
+ }
44
+
45
+ export const isHeadshotGridNode = (node: ManuscriptNode): node is HeadshotGridNode =>
46
+ node.type === node.type.schema.nodes.headshot_grid
@@ -0,0 +1,65 @@
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 HeadshotImageAttrs {
22
+ id: string
23
+ src: string
24
+ type: string
25
+ }
26
+
27
+ export interface HeadshotImageNode extends ManuscriptNode {
28
+ attrs: HeadshotImageAttrs
29
+ }
30
+
31
+ export const headshotImage: NodeSpec = {
32
+ attrs: {
33
+ id: { default: '' },
34
+ src: { default: '' },
35
+ type: { default: '' },
36
+ dataTracked: { default: null },
37
+ },
38
+ selectable: false,
39
+ group: 'block',
40
+ parseDOM: [
41
+ {
42
+ tag: 'figure',
43
+ context: 'headshot_element/',
44
+ getAttrs: (dom) => {
45
+ const element = dom as HTMLElement
46
+
47
+ return {
48
+ id: element.getAttribute('id'),
49
+ src: element.getAttribute('src'),
50
+ }
51
+ },
52
+ },
53
+ ],
54
+ toDOM: (node) => {
55
+ const imageNode = node as HeadshotImageNode
56
+
57
+ return [
58
+ 'figure',
59
+ {
60
+ class: 'headshot-figure',
61
+ id: imageNode.attrs.id,
62
+ },
63
+ ]
64
+ },
65
+ }
@@ -21,6 +21,7 @@ import { ManuscriptNode } from '../types'
21
21
  export interface HeroImageNode extends ManuscriptNode {
22
22
  attrs: {
23
23
  id: string
24
+ type: string
24
25
  }
25
26
  }
26
27
 
@@ -28,6 +29,7 @@ export const heroImage: NodeSpec = {
28
29
  content: 'figure? alt_text long_desc',
29
30
  attrs: {
30
31
  id: { default: '' },
32
+ type: { default: 'leading' },
31
33
  dataTracked: { default: null },
32
34
  },
33
35
  group: 'block element',
@@ -37,6 +39,7 @@ export const heroImage: NodeSpec = {
37
39
  {
38
40
  class: 'hero_image',
39
41
  id: node.attrs.id,
42
+ 'data-content-type': node.attrs.type,
40
43
  },
41
44
  ]
42
45
  },
@@ -18,13 +18,14 @@ import { NodeSpec } from 'prosemirror-model'
18
18
 
19
19
  import { ManuscriptNode } from '../types'
20
20
 
21
- interface Attrs {
21
+ interface PullquoteElementAttrs {
22
22
  id: string
23
23
  placeholder: string
24
+ type: string
24
25
  }
25
26
 
26
27
  export interface PullquoteElementNode extends ManuscriptNode {
27
- attrs: Attrs
28
+ attrs: PullquoteElementAttrs
28
29
  }
29
30
 
30
31
  export const pullquoteElement: NodeSpec = {
@@ -32,6 +33,7 @@ export const pullquoteElement: NodeSpec = {
32
33
  attrs: {
33
34
  id: { default: '' },
34
35
  placeholder: { default: '' },
36
+ type: { default: '' },
35
37
  dataTracked: { default: null },
36
38
  },
37
39
  group: 'block element',
@@ -42,7 +44,7 @@ export const pullquoteElement: NodeSpec = {
42
44
  getAttrs: (aside) => {
43
45
  const dom = aside as HTMLElement
44
46
 
45
- const attrs: Partial<Attrs> = {
47
+ const attrs: Partial<PullquoteElementAttrs> = {
46
48
  id: dom.getAttribute('id') || undefined,
47
49
  }
48
50
 
@@ -71,6 +73,10 @@ export const pullquoteElement: NodeSpec = {
71
73
  attrs['data-placeholder-text'] = pullquoteElementNode.attrs.placeholder
72
74
  }
73
75
 
76
+ if (pullquoteElementNode.attrs.type) {
77
+ attrs['data-content-type'] = pullquoteElementNode.attrs.type
78
+ }
79
+
74
80
  return ['aside', attrs, 0]
75
81
  },
76
82
  }
@@ -20,6 +20,7 @@ import { ManuscriptNode } from '../types'
20
20
 
21
21
  export interface TableAttrs {
22
22
  id: string
23
+ type: string
23
24
  }
24
25
 
25
26
  export interface TableElementNode extends ManuscriptNode {
@@ -31,6 +32,7 @@ export const tableElement: NodeSpec = {
31
32
  'caption_title (table | placeholder) table_colgroup? table_element_footer? alt_text long_desc (listing | placeholder)',
32
33
  attrs: {
33
34
  id: { default: '' },
35
+ type: { default: '' },
34
36
  dataTracked: { default: null },
35
37
  },
36
38
  selectable: false,
@@ -50,14 +52,16 @@ export const tableElement: NodeSpec = {
50
52
  toDOM: (node) => {
51
53
  const tableElementNode = node as TableElementNode
52
54
 
53
- return [
54
- 'figure',
55
- {
56
- class: 'table', // TODO: suppress-header, suppress-footer?
57
- id: tableElementNode.attrs.id,
58
- },
59
- 0,
60
- ]
55
+ const attrs: { [key: string]: string } = {
56
+ class: 'table',
57
+ id: tableElementNode.attrs.id,
58
+ }
59
+
60
+ if (tableElementNode.attrs.type) {
61
+ attrs['data-content-type'] = tableElementNode.attrs.type
62
+ }
63
+
64
+ return ['figure', attrs, 0]
61
65
  },
62
66
  }
63
67
 
@@ -128,6 +128,9 @@ export type Nodes =
128
128
  | 'alt_titles'
129
129
  | 'long_desc'
130
130
  | 'hero_image'
131
+ | 'headshot_grid'
132
+ | 'headshot_element'
133
+ | 'headshot_image'
131
134
  | 'trans_abstract'
132
135
  | 'trans_graphical_abstract'
133
136
  | 'subtitle'
@@ -32,6 +32,8 @@ export const nodeNames: Map<ManuscriptNodeType, string> = new Map([
32
32
  [schema.nodes.figure_element, 'Figure'],
33
33
  [schema.nodes.image_element, 'Image'],
34
34
  [schema.nodes.hero_image, 'Hero Image'],
35
+ [schema.nodes.headshot_grid, 'Headshot Panel'],
36
+ [schema.nodes.headshot_element, 'Headshot'],
35
37
  [schema.nodes.table_element, 'Table'],
36
38
  [schema.nodes.table_cell, 'Table Cell'],
37
39
  [schema.nodes.table_col, 'Table Column'],
@@ -29,6 +29,10 @@ const textSnippet = (node: ManuscriptNode, max = 100) => {
29
29
  text += child.text
30
30
  } else if (isHighlightMarkerNode(node)) {
31
31
  text += ''
32
+ } else if (node.type === schema.nodes.headshot_element) {
33
+ if (child.type === schema.nodes.caption_title) {
34
+ text += child.textContent
35
+ }
32
36
  } else {
33
37
  text += ' '
34
38
  }
@@ -82,6 +86,7 @@ export const nodeTitle = (node: ManuscriptNode) => {
82
86
  case nodes.multi_graphic_figure_element:
83
87
  case nodes.image_element:
84
88
  case nodes.hero_image:
89
+ case nodes.headshot_grid:
85
90
  case nodes.box_element:
86
91
  case nodes.supplements:
87
92
  case nodes.attachments:
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const VERSION = "4.4.0";
1
+ export const VERSION = "4.4.2";