@manuscripts/transform 4.3.53 → 4.4.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.
- package/dist/cjs/jats/__tests__/jats-roundtrip.test.js +3 -3
- package/dist/cjs/jats/exporter/jats-exporter.js +3 -0
- package/dist/cjs/jats/importer/jats-dom-parser.js +41 -1
- package/dist/cjs/schema/index.js +9 -0
- package/dist/cjs/schema/nodes/headshot_element.js +38 -0
- package/dist/cjs/schema/nodes/headshot_grid.js +37 -0
- package/dist/cjs/schema/nodes/headshot_image.js +51 -0
- package/dist/cjs/transformer/node-names.js +2 -0
- package/dist/cjs/transformer/node-title.js +6 -0
- package/dist/cjs/version.js +1 -1
- package/dist/es/jats/__tests__/jats-roundtrip.test.js +3 -3
- package/dist/es/jats/exporter/jats-exporter.js +3 -0
- package/dist/es/jats/importer/jats-dom-parser.js +41 -1
- package/dist/es/schema/index.js +9 -0
- package/dist/es/schema/nodes/headshot_element.js +34 -0
- package/dist/es/schema/nodes/headshot_grid.js +33 -0
- package/dist/es/schema/nodes/headshot_image.js +48 -0
- package/dist/es/transformer/node-names.js +2 -0
- package/dist/es/transformer/node-title.js +6 -0
- package/dist/es/version.js +1 -1
- package/dist/types/jats/__tests__/utils.d.ts +1 -1
- package/dist/types/schema/index.d.ts +3 -0
- package/dist/types/schema/nodes/headshot_element.d.ts +25 -0
- package/dist/types/schema/nodes/headshot_grid.d.ts +24 -0
- package/dist/types/schema/nodes/headshot_image.d.ts +26 -0
- package/dist/types/schema/types.d.ts +1 -1
- package/dist/types/version.d.ts +1 -1
- package/package.json +22 -21
- package/src/errors.ts +28 -0
- package/src/getVersion.ts +21 -0
- package/src/index.ts +28 -0
- package/src/jats/__tests__/__fixtures__/debug-example.xml +136 -0
- package/src/jats/__tests__/__fixtures__/jats-abstract-no-body.xml +163 -0
- package/src/jats/__tests__/__fixtures__/jats-citations.xml +472 -0
- package/src/jats/__tests__/__fixtures__/jats-comments.xml +46 -0
- package/src/jats/__tests__/__fixtures__/jats-document.xml +134 -0
- package/src/jats/__tests__/__fixtures__/jats-example-doc.xml +1235 -0
- package/src/jats/__tests__/__fixtures__/jats-example-front-only.xml +26 -0
- package/src/jats/__tests__/__fixtures__/jats-example-full.xml +209 -0
- package/src/jats/__tests__/__fixtures__/jats-example-no-back.xml +156 -0
- package/src/jats/__tests__/__fixtures__/jats-example-no-body.xml +91 -0
- package/src/jats/__tests__/__fixtures__/jats-example.xml +221 -0
- package/src/jats/__tests__/__fixtures__/jats-fn-group.xml +60 -0
- package/src/jats/__tests__/__fixtures__/jats-import-no-refs.xml +1077 -0
- package/src/jats/__tests__/__fixtures__/jats-import.xml +1578 -0
- package/src/jats/__tests__/__fixtures__/jats-roundtrip.xml +133 -0
- package/src/jats/__tests__/__fixtures__/jats-tables-example.xml +2043 -0
- package/src/jats/__tests__/__fixtures__/math-fragment.xml +12 -0
- package/src/jats/__tests__/__snapshots__/citeproc.test.ts.snap +57 -0
- package/src/jats/__tests__/__snapshots__/create-article-node.test.ts.snap +65 -0
- package/src/jats/__tests__/__snapshots__/jats-exporter.test.ts.snap +7 -0
- package/src/jats/__tests__/__snapshots__/jats-importer.test.ts.snap +59796 -0
- package/src/jats/__tests__/__snapshots__/jats-roundtrip.test.ts.snap +18 -0
- package/src/jats/__tests__/citations.ts +25 -0
- package/src/jats/__tests__/citeproc.test.ts +195 -0
- package/src/jats/__tests__/create-article-node.test.ts +29 -0
- package/src/jats/__tests__/data/section-categories.ts +212 -0
- package/src/jats/__tests__/files.ts +24 -0
- package/src/jats/__tests__/jats-exporter.test.ts +223 -0
- package/src/jats/__tests__/jats-importer.test.ts +567 -0
- package/src/jats/__tests__/jats-roundtrip.test.ts +66 -0
- package/src/jats/__tests__/utils.ts +90 -0
- package/src/jats/exporter/citeproc.ts +265 -0
- package/src/jats/exporter/jats-exporter.ts +2093 -0
- package/src/jats/exporter/jats-versions.ts +50 -0
- package/src/jats/exporter/labels.ts +101 -0
- package/src/jats/importer/create-article-node.ts +52 -0
- package/src/jats/importer/jats-comments.ts +111 -0
- package/src/jats/importer/jats-dom-parser.ts +1306 -0
- package/src/jats/importer/jats-parser-utils.ts +234 -0
- package/src/jats/importer/jats-transformations.ts +591 -0
- package/src/jats/importer/parse-jats-article.ts +106 -0
- package/src/jats/index.ts +21 -0
- package/src/jats/types.ts +16 -0
- package/src/lib/__tests__/footnotes.test.ts +36 -0
- package/src/lib/citeproc.ts +30 -0
- package/src/lib/credit-roles.ts +91 -0
- package/src/lib/deafults.ts +17 -0
- package/src/lib/footnotes.ts +85 -0
- package/src/lib/html.ts +56 -0
- package/src/lib/section-categories.ts +27 -0
- package/src/lib/utils.ts +145 -0
- package/src/lib/xml.ts +28 -0
- package/src/schema/__tests__/docs.ts +1911 -0
- package/src/schema/__tests__/groups.test.ts +61 -0
- package/src/schema/__tests__/migration.test.ts +23 -0
- package/src/schema/groups.ts +36 -0
- package/src/schema/index.ts +295 -0
- package/src/schema/marks.ts +254 -0
- package/src/schema/migration/migrate.ts +77 -0
- package/src/schema/migration/migration-script.ts +26 -0
- package/src/schema/migration/migration-scripts/1.2.5.ts +44 -0
- package/src/schema/migration/migration-scripts/2.3.22.ts +52 -0
- package/src/schema/migration/migration-scripts/3.0.12.ts +33 -0
- package/src/schema/migration/migration-scripts/3.0.21.ts +50 -0
- package/src/schema/migration/migration-scripts/3.0.30.ts +65 -0
- package/src/schema/migration/migration-scripts/3.0.31.ts +40 -0
- package/src/schema/migration/migration-scripts/3.0.41.ts +37 -0
- package/src/schema/migration/migration-scripts/3.0.55.ts +42 -0
- package/src/schema/migration/migration-scripts/3.0.56.ts +114 -0
- package/src/schema/migration/migration-scripts/4.2.13.ts +37 -0
- package/src/schema/migration/migration-scripts/4.2.15.ts +48 -0
- package/src/schema/migration/migration-scripts/4.3.23.ts +55 -0
- package/src/schema/migration/migration-scripts/4.3.34.ts +132 -0
- package/src/schema/migration/migration-scripts/4.3.35.ts +41 -0
- package/src/schema/migration/migration-scripts/index.ts +49 -0
- package/src/schema/nodes/abstracts.ts +29 -0
- package/src/schema/nodes/affiliation.ts +88 -0
- package/src/schema/nodes/affiliations.ts +30 -0
- package/src/schema/nodes/alt_text.ts +36 -0
- package/src/schema/nodes/alt_title.ts +40 -0
- package/src/schema/nodes/alt_titles_section.ts +58 -0
- package/src/schema/nodes/attachment.ts +46 -0
- package/src/schema/nodes/attachments.ts +45 -0
- package/src/schema/nodes/attribution.ts +38 -0
- package/src/schema/nodes/author_notes.ts +44 -0
- package/src/schema/nodes/award.ts +52 -0
- package/src/schema/nodes/awards.ts +45 -0
- package/src/schema/nodes/backmatter.ts +31 -0
- package/src/schema/nodes/bibliography_element.ts +58 -0
- package/src/schema/nodes/bibliography_item.ts +108 -0
- package/src/schema/nodes/bibliography_section.ts +60 -0
- package/src/schema/nodes/blockquote_element.ts +79 -0
- package/src/schema/nodes/body.ts +29 -0
- package/src/schema/nodes/box_element.ts +67 -0
- package/src/schema/nodes/caption.ts +67 -0
- package/src/schema/nodes/caption_title.ts +67 -0
- package/src/schema/nodes/citation.ts +70 -0
- package/src/schema/nodes/comment.ts +50 -0
- package/src/schema/nodes/comments.ts +28 -0
- package/src/schema/nodes/contributor.ts +87 -0
- package/src/schema/nodes/contributors.ts +40 -0
- package/src/schema/nodes/core_section.ts +27 -0
- package/src/schema/nodes/corresp.ts +49 -0
- package/src/schema/nodes/cross_reference.ts +64 -0
- package/src/schema/nodes/doc.ts +21 -0
- package/src/schema/nodes/embed.ts +55 -0
- package/src/schema/nodes/equation.ts +65 -0
- package/src/schema/nodes/equation_element.ts +61 -0
- package/src/schema/nodes/figure.ts +65 -0
- package/src/schema/nodes/figure_element.ts +73 -0
- package/src/schema/nodes/footnote.ts +95 -0
- package/src/schema/nodes/footnotes_element.ts +69 -0
- package/src/schema/nodes/footnotes_section.ts +61 -0
- package/src/schema/nodes/general_table_footnote.ts +42 -0
- package/src/schema/nodes/graphical_abstract_section.ts +62 -0
- package/src/schema/nodes/hard_break.ts +36 -0
- package/src/schema/nodes/headshot_element.ts +48 -0
- package/src/schema/nodes/headshot_grid.ts +46 -0
- package/src/schema/nodes/headshot_image.ts +65 -0
- package/src/schema/nodes/hero_image.ts +46 -0
- package/src/schema/nodes/highlight_marker.ts +68 -0
- package/src/schema/nodes/image_element.ts +49 -0
- package/src/schema/nodes/inline_equation.ts +68 -0
- package/src/schema/nodes/inline_footnote.ts +66 -0
- package/src/schema/nodes/keyword.ts +61 -0
- package/src/schema/nodes/keyword_group.ts +63 -0
- package/src/schema/nodes/keywords.ts +59 -0
- package/src/schema/nodes/keywords_element.ts +64 -0
- package/src/schema/nodes/link.ts +79 -0
- package/src/schema/nodes/list.ts +134 -0
- package/src/schema/nodes/listing.ts +91 -0
- package/src/schema/nodes/listing_element.ts +61 -0
- package/src/schema/nodes/long_desc.ts +36 -0
- package/src/schema/nodes/manuscript.ts +86 -0
- package/src/schema/nodes/missing_figure.ts +59 -0
- package/src/schema/nodes/paragraph.ts +77 -0
- package/src/schema/nodes/placeholder.ts +62 -0
- package/src/schema/nodes/placeholder_element.ts +60 -0
- package/src/schema/nodes/pullquote_element.ts +81 -0
- package/src/schema/nodes/quote_image.ts +64 -0
- package/src/schema/nodes/section.ts +69 -0
- package/src/schema/nodes/section_label.ts +39 -0
- package/src/schema/nodes/section_title.ts +58 -0
- package/src/schema/nodes/subtitle.ts +40 -0
- package/src/schema/nodes/subtitles.ts +51 -0
- package/src/schema/nodes/supplement.ts +77 -0
- package/src/schema/nodes/supplements.ts +60 -0
- package/src/schema/nodes/table.ts +144 -0
- package/src/schema/nodes/table_col.ts +76 -0
- package/src/schema/nodes/table_element.ts +67 -0
- package/src/schema/nodes/table_element_footer.ts +42 -0
- package/src/schema/nodes/text.ts +31 -0
- package/src/schema/nodes/title.ts +43 -0
- package/src/schema/nodes/trans_abstract.ts +58 -0
- package/src/schema/nodes/trans_graphical_abstract.ts +67 -0
- package/src/schema/types.ts +243 -0
- package/src/tests.ts +33 -0
- package/src/transformer/id.ts +23 -0
- package/src/transformer/index.ts +21 -0
- package/src/transformer/node-names.ts +75 -0
- package/src/transformer/node-title.ts +116 -0
- package/src/transformer/node-types.ts +39 -0
- package/src/transformer/node-validator.ts +82 -0
- package/src/types.ts +25 -0
- package/src/version.ts +1 -0
|
@@ -0,0 +1,591 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* © 2020 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 { defaultTitle } from '../../lib/deafults'
|
|
18
|
+
import { XML_NAMESPACE } from '../../lib/xml'
|
|
19
|
+
import { SectionCategory, SectionGroup } from '../../schema'
|
|
20
|
+
import { htmlFromJatsNode } from './jats-parser-utils'
|
|
21
|
+
|
|
22
|
+
export type CreateElement = (tagName: string) => HTMLElement
|
|
23
|
+
|
|
24
|
+
const removeNodeFromParent = (node: Element) =>
|
|
25
|
+
node.parentNode && node.parentNode.removeChild(node)
|
|
26
|
+
|
|
27
|
+
const capitalizeFirstLetter = (str: string) =>
|
|
28
|
+
str.charAt(0).toUpperCase() + str.slice(1)
|
|
29
|
+
|
|
30
|
+
const createSectionGroup = (
|
|
31
|
+
type: SectionGroup,
|
|
32
|
+
createElement: CreateElement
|
|
33
|
+
) => {
|
|
34
|
+
const sec = createElement('sec')
|
|
35
|
+
sec.setAttribute('sec-type', type)
|
|
36
|
+
return sec
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export const addMissingCaptions = (
|
|
40
|
+
doc: Document,
|
|
41
|
+
createElement: CreateElement
|
|
42
|
+
) => {
|
|
43
|
+
const elements = doc.querySelectorAll(
|
|
44
|
+
'fig, table-wrap, media, supplementary-material, boxed-text'
|
|
45
|
+
)
|
|
46
|
+
for (const element of elements) {
|
|
47
|
+
let caption: Element | null = element.querySelector('caption')
|
|
48
|
+
if (!caption) {
|
|
49
|
+
caption = createElement('caption')
|
|
50
|
+
element.nodeName === 'fig'
|
|
51
|
+
? element.appendChild(caption)
|
|
52
|
+
: element.prepend(caption)
|
|
53
|
+
}
|
|
54
|
+
if (!caption.querySelector('title') && element.nodeName !== 'fig') {
|
|
55
|
+
caption.prepend(createElement('title'))
|
|
56
|
+
}
|
|
57
|
+
if (
|
|
58
|
+
!caption.querySelector('p') &&
|
|
59
|
+
element.nodeName !== 'boxed-text' &&
|
|
60
|
+
element.nodeName !== 'table-wrap'
|
|
61
|
+
) {
|
|
62
|
+
caption.appendChild(createElement('p'))
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
export const createBoxedElementSection = (
|
|
67
|
+
doc: Document,
|
|
68
|
+
createElement: CreateElement
|
|
69
|
+
) => {
|
|
70
|
+
const boxedTexts = doc.querySelectorAll('boxed-text')
|
|
71
|
+
for (const boxedText of boxedTexts) {
|
|
72
|
+
const containerSec = createElement('sec')
|
|
73
|
+
const children = Array.from(boxedText.children).filter(
|
|
74
|
+
(child) => child.localName !== 'label' && child.localName !== 'caption'
|
|
75
|
+
)
|
|
76
|
+
containerSec.append(...children)
|
|
77
|
+
boxedText.appendChild(containerSec)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export const createTitles = (front: Element, createElement: CreateElement) => {
|
|
82
|
+
const titles = createElement('titles')
|
|
83
|
+
let title = front.querySelector('article-meta > title-group > article-title')
|
|
84
|
+
if (title) {
|
|
85
|
+
title.innerHTML = htmlFromJatsNode(title, createElement) ?? defaultTitle
|
|
86
|
+
} else {
|
|
87
|
+
title = createElement('article-title')
|
|
88
|
+
title.innerHTML = defaultTitle
|
|
89
|
+
}
|
|
90
|
+
titles.appendChild(title)
|
|
91
|
+
|
|
92
|
+
const subtitles = front.querySelectorAll('subtitle')
|
|
93
|
+
subtitles.forEach((subtitle) => {
|
|
94
|
+
subtitle.innerHTML = htmlFromJatsNode(subtitle, createElement) ?? ''
|
|
95
|
+
titles.appendChild(subtitle)
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
const altTitles = front.querySelectorAll(
|
|
99
|
+
'article-meta > title-group > alt-title'
|
|
100
|
+
)
|
|
101
|
+
altTitles.forEach((altTitle) => {
|
|
102
|
+
altTitle.innerHTML = htmlFromJatsNode(altTitle, createElement) ?? ''
|
|
103
|
+
titles.appendChild(altTitle)
|
|
104
|
+
})
|
|
105
|
+
front.parentNode?.insertBefore(titles, front)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export const moveAuthorNotes = (
|
|
109
|
+
front: Element,
|
|
110
|
+
createElement: CreateElement
|
|
111
|
+
) => {
|
|
112
|
+
const authorNotes = front.querySelector('article-meta > author-notes')
|
|
113
|
+
if (authorNotes) {
|
|
114
|
+
const sectionTitle = createElement('title')
|
|
115
|
+
authorNotes.prepend(sectionTitle)
|
|
116
|
+
front.parentNode?.insertBefore(authorNotes, front)
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
export const moveAwards = (front: Element) => {
|
|
120
|
+
const awards = front.querySelector('article-meta > funding-group')
|
|
121
|
+
if (awards) {
|
|
122
|
+
front.parentNode?.insertBefore(awards, front)
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export const moveContributors = (
|
|
127
|
+
front: Element,
|
|
128
|
+
createElement: CreateElement
|
|
129
|
+
) => {
|
|
130
|
+
const contribs = front.querySelectorAll(
|
|
131
|
+
'contrib-group > contrib[contrib-type="author"]'
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
if (contribs.length) {
|
|
135
|
+
const contributors = createElement('contributors')
|
|
136
|
+
contribs.forEach((c) => contributors.appendChild(c))
|
|
137
|
+
front.parentNode?.insertBefore(contributors, front)
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export const moveAffiliations = (
|
|
142
|
+
front: Element,
|
|
143
|
+
createElement: CreateElement
|
|
144
|
+
) => {
|
|
145
|
+
const affs = front.querySelectorAll('article-meta > contrib-group > aff')
|
|
146
|
+
if (affs.length) {
|
|
147
|
+
const affiliations = createElement('affiliations')
|
|
148
|
+
affs.forEach((a) => affiliations.appendChild(a))
|
|
149
|
+
front.parentNode?.insertBefore(affiliations, front)
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export const moveAbstracts = (
|
|
154
|
+
front: Element,
|
|
155
|
+
group: Element,
|
|
156
|
+
createElement: CreateElement,
|
|
157
|
+
sectionCategories?: SectionCategory[]
|
|
158
|
+
) => {
|
|
159
|
+
const abstracts = front.querySelectorAll(
|
|
160
|
+
'article-meta > abstract, article-meta > trans-abstract'
|
|
161
|
+
)
|
|
162
|
+
abstracts.forEach((abstract) => {
|
|
163
|
+
const sec = createAbstractSection(
|
|
164
|
+
abstract,
|
|
165
|
+
createElement,
|
|
166
|
+
sectionCategories
|
|
167
|
+
)
|
|
168
|
+
removeNodeFromParent(abstract)
|
|
169
|
+
group.appendChild(sec)
|
|
170
|
+
})
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export const moveHeroImage = (doc: Document) => {
|
|
174
|
+
const heroImage = doc.querySelector('graphic[content-type="leading"]')
|
|
175
|
+
if (!heroImage) {
|
|
176
|
+
return
|
|
177
|
+
}
|
|
178
|
+
const back = doc.querySelector('back')
|
|
179
|
+
if (back) {
|
|
180
|
+
back.parentNode?.insertBefore(heroImage, back.nextSibling)
|
|
181
|
+
} else {
|
|
182
|
+
doc.documentElement.appendChild(heroImage)
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export const createBody = (
|
|
187
|
+
doc: Document,
|
|
188
|
+
body: Element,
|
|
189
|
+
createElement: CreateElement
|
|
190
|
+
) => {
|
|
191
|
+
const group = createSectionGroup('body', createElement)
|
|
192
|
+
const elements = body.querySelectorAll(
|
|
193
|
+
':scope > *:not(sec), :scope > sec:not([sec-type="backmatter"]), :scope > sec:not([sec-type])'
|
|
194
|
+
)
|
|
195
|
+
elements.forEach((element) => {
|
|
196
|
+
removeNodeFromParent(element)
|
|
197
|
+
group.appendChild(element)
|
|
198
|
+
})
|
|
199
|
+
body.append(group)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export const createAbstracts = (
|
|
203
|
+
front: Element,
|
|
204
|
+
body: Element,
|
|
205
|
+
createElement: CreateElement,
|
|
206
|
+
sectionCategories?: SectionCategory[]
|
|
207
|
+
) => {
|
|
208
|
+
const group = createSectionGroup('abstracts', createElement)
|
|
209
|
+
moveAbstracts(front, group, createElement, sectionCategories)
|
|
210
|
+
body.insertBefore(group, body.lastElementChild)
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export const createBackmatter = (
|
|
214
|
+
doc: Document,
|
|
215
|
+
body: Element,
|
|
216
|
+
sectionCategories: SectionCategory[],
|
|
217
|
+
createElement: CreateElement
|
|
218
|
+
) => {
|
|
219
|
+
const group = createSectionGroup('backmatter', createElement)
|
|
220
|
+
moveBackSections(doc, group)
|
|
221
|
+
moveAppendices(doc, group, createElement)
|
|
222
|
+
moveSpecialFootnotes(doc, group, sectionCategories, createElement)
|
|
223
|
+
moveAcknowledgments(doc, group, createElement)
|
|
224
|
+
moveFootnotes(doc, group, createElement)
|
|
225
|
+
body.append(group)
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const moveFootnotes = (
|
|
229
|
+
doc: Document,
|
|
230
|
+
group: Element,
|
|
231
|
+
createElement: CreateElement
|
|
232
|
+
) => {
|
|
233
|
+
const fns = [
|
|
234
|
+
...doc.querySelectorAll('fn:not(table-wrap-foot fn, author-notes fn)'),
|
|
235
|
+
]
|
|
236
|
+
let section = doc.querySelector('sec[sec-type="endnotes"]')
|
|
237
|
+
const fnGroup =
|
|
238
|
+
section?.querySelector('fn-group') || createElement('fn-group')
|
|
239
|
+
fns.forEach((fn) => {
|
|
240
|
+
if (!fn.getAttribute('fn-type')) {
|
|
241
|
+
fnGroup.appendChild(fn)
|
|
242
|
+
}
|
|
243
|
+
})
|
|
244
|
+
if (!section && fnGroup.innerHTML) {
|
|
245
|
+
section = createFootnotesSection([fnGroup], createElement)
|
|
246
|
+
}
|
|
247
|
+
if (section) {
|
|
248
|
+
group.appendChild(section)
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// process footnotes with special meaning to
|
|
253
|
+
const moveSpecialFootnotes = (
|
|
254
|
+
doc: Document,
|
|
255
|
+
group: Element,
|
|
256
|
+
sectionCategories: SectionCategory[],
|
|
257
|
+
createElement: CreateElement
|
|
258
|
+
) => {
|
|
259
|
+
const fns = [...doc.querySelectorAll('fn[fn-type]')]
|
|
260
|
+
for (const fn of fns) {
|
|
261
|
+
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
|
+
)
|
|
265
|
+
if (category) {
|
|
266
|
+
const section = createElement('sec')
|
|
267
|
+
const fnTitle =
|
|
268
|
+
fn.querySelector('label') ||
|
|
269
|
+
fn.querySelector('p[content-type="fn-title"]')
|
|
270
|
+
const title = createElement('title')
|
|
271
|
+
if (fnTitle) {
|
|
272
|
+
const titleText = fnTitle.textContent?.trim()
|
|
273
|
+
if (titleText) {
|
|
274
|
+
title.textContent = titleText
|
|
275
|
+
}
|
|
276
|
+
removeNodeFromParent(fnTitle)
|
|
277
|
+
} else {
|
|
278
|
+
title.textContent = category.titles[0]
|
|
279
|
+
}
|
|
280
|
+
section.append(title)
|
|
281
|
+
section.append(...fn.children)
|
|
282
|
+
removeNodeFromParent(fn)
|
|
283
|
+
section.setAttribute('sec-type', category.id)
|
|
284
|
+
group.append(section)
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
// move captions to the end of their containers
|
|
289
|
+
export const moveCaptionsToEnd = (body: Element) => {
|
|
290
|
+
const captions = body.querySelectorAll('caption')
|
|
291
|
+
|
|
292
|
+
for (const caption of captions) {
|
|
293
|
+
if (
|
|
294
|
+
caption.parentNode &&
|
|
295
|
+
caption.parentNode.nodeName !== 'table-wrap' &&
|
|
296
|
+
caption.parentNode.nodeName !== 'boxed-text'
|
|
297
|
+
) {
|
|
298
|
+
caption.parentNode.appendChild(caption)
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const createAbstractSection = (
|
|
304
|
+
abstract: Element,
|
|
305
|
+
createElement: CreateElement,
|
|
306
|
+
sectionCategories?: SectionCategory[]
|
|
307
|
+
) => {
|
|
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)
|
|
319
|
+
if (!abstract.querySelector(':scope > title')) {
|
|
320
|
+
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
|
+
|
|
334
|
+
while (abstract.firstChild) {
|
|
335
|
+
section.appendChild(abstract.firstChild)
|
|
336
|
+
}
|
|
337
|
+
return section
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
const createAcknowledgmentsSection = (
|
|
341
|
+
ack: Element,
|
|
342
|
+
createElement: CreateElement
|
|
343
|
+
) => {
|
|
344
|
+
const section = createElement('sec')
|
|
345
|
+
section.setAttribute('sec-type', 'acknowledgments')
|
|
346
|
+
|
|
347
|
+
if (!ack.querySelector('title')) {
|
|
348
|
+
const title = createElement('title')
|
|
349
|
+
title.textContent = 'Acknowledgements'
|
|
350
|
+
section.appendChild(title)
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
while (ack.firstChild) {
|
|
354
|
+
section.appendChild(ack.firstChild)
|
|
355
|
+
}
|
|
356
|
+
return section
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
const createFootnotesSection = (
|
|
360
|
+
fnGroups: Element[],
|
|
361
|
+
createElement: CreateElement
|
|
362
|
+
) => {
|
|
363
|
+
const section = createElement('sec')
|
|
364
|
+
section.setAttribute('sec-type', 'endnotes')
|
|
365
|
+
|
|
366
|
+
const titleNode = fnGroups
|
|
367
|
+
.map((g) => g.querySelector('title'))
|
|
368
|
+
.filter((t) => t !== null)[0]
|
|
369
|
+
|
|
370
|
+
if (titleNode) {
|
|
371
|
+
section.appendChild(titleNode)
|
|
372
|
+
} else {
|
|
373
|
+
const title = createElement('title')
|
|
374
|
+
title.textContent = 'Footnotes'
|
|
375
|
+
section.appendChild(title)
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
for (const fnGroup of fnGroups) {
|
|
379
|
+
section.appendChild(fnGroup)
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
return section
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
const createAppendicesSection = (
|
|
386
|
+
app: Element,
|
|
387
|
+
createElement: CreateElement
|
|
388
|
+
) => {
|
|
389
|
+
const section = createElement('sec')
|
|
390
|
+
section.setAttribute('sec-type', 'appendices')
|
|
391
|
+
section.append(...app.children)
|
|
392
|
+
return section
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
const moveBackSections = (doc: Document, group: Element) => {
|
|
396
|
+
for (const section of doc.querySelectorAll('back > sec')) {
|
|
397
|
+
removeNodeFromParent(section)
|
|
398
|
+
group.appendChild(section)
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
const moveAcknowledgments = (
|
|
403
|
+
doc: Document,
|
|
404
|
+
group: Element,
|
|
405
|
+
createElement: CreateElement
|
|
406
|
+
) => {
|
|
407
|
+
const ack = doc.querySelector('back > ack')
|
|
408
|
+
if (ack) {
|
|
409
|
+
const section = createAcknowledgmentsSection(ack, createElement)
|
|
410
|
+
removeNodeFromParent(ack)
|
|
411
|
+
group.appendChild(section)
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
const moveAppendices = (
|
|
415
|
+
doc: Document,
|
|
416
|
+
group: Element,
|
|
417
|
+
createElement: CreateElement
|
|
418
|
+
) => {
|
|
419
|
+
const apps = doc.querySelectorAll('back > app-group > app')
|
|
420
|
+
for (const app of apps) {
|
|
421
|
+
const section = createAppendicesSection(app, createElement)
|
|
422
|
+
removeNodeFromParent(app)
|
|
423
|
+
group.appendChild(section)
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
export const createKeywordsSection = (
|
|
428
|
+
document: Document,
|
|
429
|
+
body: Element,
|
|
430
|
+
createElement: CreateElement
|
|
431
|
+
) => {
|
|
432
|
+
const kwdGroups = [...document.querySelectorAll('kwd-group')]
|
|
433
|
+
if (kwdGroups.length > 0) {
|
|
434
|
+
const section = createElement('sec')
|
|
435
|
+
section.setAttribute('sec-type', 'keywords')
|
|
436
|
+
const title = createElement('title')
|
|
437
|
+
title.textContent = 'Keywords'
|
|
438
|
+
section.append(title)
|
|
439
|
+
const kwdGroupList = createElement('kwd-group-list')
|
|
440
|
+
// Using the first kwd-group since for the moment we only support single kwd-group
|
|
441
|
+
kwdGroupList.append(kwdGroups[0])
|
|
442
|
+
section.append(kwdGroupList)
|
|
443
|
+
body.prepend(section)
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
export const createSupplementaryMaterialsSection = (
|
|
448
|
+
document: Document,
|
|
449
|
+
body: Element,
|
|
450
|
+
createElement: CreateElement
|
|
451
|
+
) => {
|
|
452
|
+
const suppls = [
|
|
453
|
+
...document.querySelectorAll('article-meta > supplementary-material'),
|
|
454
|
+
]
|
|
455
|
+
if (suppls.length) {
|
|
456
|
+
const section = createElement('sec')
|
|
457
|
+
section.setAttribute('sec-type', 'supplementary-material')
|
|
458
|
+
const title = createElement('title')
|
|
459
|
+
title.textContent = 'Supplements'
|
|
460
|
+
section.append(title)
|
|
461
|
+
section.append(...suppls)
|
|
462
|
+
body.append(section)
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
export const createAccessibilityItems = (
|
|
467
|
+
doc: Document,
|
|
468
|
+
createElement: CreateElement
|
|
469
|
+
) => {
|
|
470
|
+
const resolveA11yNode = (item: Element, tagName: string) => {
|
|
471
|
+
if (item.nodeName.toLowerCase() === 'fig') {
|
|
472
|
+
const graphicNode = item.querySelector(`graphic ${tagName}`)
|
|
473
|
+
const figNode = item.querySelector(`:scope > ${tagName}`)
|
|
474
|
+
if (graphicNode && figNode) {
|
|
475
|
+
figNode.remove()
|
|
476
|
+
}
|
|
477
|
+
return graphicNode || figNode || createElement(tagName)
|
|
478
|
+
}
|
|
479
|
+
return item.querySelector(tagName) || createElement(tagName)
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
doc
|
|
483
|
+
.querySelectorAll('media, fig, table-wrap, graphic:not(fig graphic)')
|
|
484
|
+
.forEach((item) => {
|
|
485
|
+
item.appendChild(resolveA11yNode(item, 'alt-text'))
|
|
486
|
+
item.appendChild(resolveA11yNode(item, 'long-desc'))
|
|
487
|
+
})
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
export const moveReferencesToBackmatter = (
|
|
491
|
+
body: Element,
|
|
492
|
+
back: Element,
|
|
493
|
+
createElement: CreateElement
|
|
494
|
+
) => {
|
|
495
|
+
const backmatter = body.querySelector('sec[sec-type="backmatter"]')
|
|
496
|
+
const refList = back.querySelector('ref-list')
|
|
497
|
+
if (!backmatter || !refList) {
|
|
498
|
+
return
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
removeNodeFromParent(refList)
|
|
502
|
+
|
|
503
|
+
const section = createElement('sec')
|
|
504
|
+
section.setAttribute('sec-type', 'bibliography')
|
|
505
|
+
const title = createElement('title')
|
|
506
|
+
title.textContent = 'References'
|
|
507
|
+
section.appendChild(title)
|
|
508
|
+
section.appendChild(refList)
|
|
509
|
+
|
|
510
|
+
backmatter.appendChild(section)
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
export const orderTableFootnote = (doc: Document, body: Element) => {
|
|
514
|
+
const rids = new Set(
|
|
515
|
+
[...body.querySelectorAll('tbody > xref[ref-type="fn"]')].map((xref) =>
|
|
516
|
+
xref.getAttribute('rid')
|
|
517
|
+
)
|
|
518
|
+
)
|
|
519
|
+
|
|
520
|
+
const fnGroups = doc.querySelectorAll('table-wrap-foot > fn-group')
|
|
521
|
+
fnGroups.forEach((fnGroup) => {
|
|
522
|
+
// sort the un-cited table footnote at the end of list
|
|
523
|
+
const fns = [...fnGroup.querySelectorAll('fn')].sort((fn) =>
|
|
524
|
+
rids.has(fn.getAttribute('id')) ? -1 : 0
|
|
525
|
+
)
|
|
526
|
+
fnGroup.replaceChildren(...fns)
|
|
527
|
+
})
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
export const createAttachments = (
|
|
531
|
+
doc: Document,
|
|
532
|
+
createElement: CreateElement
|
|
533
|
+
) => {
|
|
534
|
+
const attachments = createElement('attachments')
|
|
535
|
+
doc
|
|
536
|
+
.querySelectorAll('self-uri')
|
|
537
|
+
.forEach((attachment) => attachments.appendChild(attachment))
|
|
538
|
+
if (attachments.children.length > 0) {
|
|
539
|
+
doc.documentElement.appendChild(attachments)
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
export const fixTables = (
|
|
544
|
+
doc: Document,
|
|
545
|
+
body: Element,
|
|
546
|
+
createElement: CreateElement
|
|
547
|
+
) => {
|
|
548
|
+
const tableWraps = body.querySelectorAll('table-wrap')
|
|
549
|
+
tableWraps.forEach((tableWrap) => {
|
|
550
|
+
// Move cols into a colgroup if they are not already
|
|
551
|
+
// This more closely maps how they exist in HTML and, subsequently, in ManuscriptJSON
|
|
552
|
+
const table = tableWrap.querySelector('table')
|
|
553
|
+
if (!table) {
|
|
554
|
+
return
|
|
555
|
+
}
|
|
556
|
+
// Merge tfoot rows into tbody to preserve correct row order when parsing.
|
|
557
|
+
// In JATS, tfoot appears before tbody in the DOM, which would
|
|
558
|
+
// cause the last row to appear first after roundtripping.
|
|
559
|
+
const tfoot = table.querySelector('tfoot')
|
|
560
|
+
const tbody = table.querySelector('tbody')
|
|
561
|
+
if (tfoot && tbody) {
|
|
562
|
+
const tfootRows = Array.from(tfoot.querySelectorAll(':scope > tr'))
|
|
563
|
+
for (const row of tfootRows) {
|
|
564
|
+
removeNodeFromParent(row)
|
|
565
|
+
tbody.appendChild(row)
|
|
566
|
+
}
|
|
567
|
+
removeNodeFromParent(tfoot)
|
|
568
|
+
}
|
|
569
|
+
const colgroup = table.querySelector('colgroup')
|
|
570
|
+
const cols = table.querySelectorAll('col')
|
|
571
|
+
if (!colgroup && table.firstChild && cols.length > 0) {
|
|
572
|
+
const colgroup = createElement('colgroup')
|
|
573
|
+
for (const col of cols) {
|
|
574
|
+
colgroup.appendChild(col)
|
|
575
|
+
}
|
|
576
|
+
tableWrap.insertBefore(colgroup, table.nextSibling)
|
|
577
|
+
}
|
|
578
|
+
const tableFootWrap = tableWrap.querySelector('table-wrap-foot')
|
|
579
|
+
if (tableFootWrap) {
|
|
580
|
+
const paragraphs = tableFootWrap.querySelectorAll(':scope > p')
|
|
581
|
+
if (paragraphs.length) {
|
|
582
|
+
const generalTableFootnote = createElement('general-table-footnote')
|
|
583
|
+
for (const paragraph of paragraphs) {
|
|
584
|
+
removeNodeFromParent(paragraph)
|
|
585
|
+
generalTableFootnote.append(paragraph)
|
|
586
|
+
}
|
|
587
|
+
tableFootWrap.prepend(generalTableFootnote)
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
})
|
|
591
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* © 2020 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 { ActualManuscriptNode, schema, SectionCategory } from '../../schema'
|
|
18
|
+
import { markComments } from './jats-comments'
|
|
19
|
+
import { JATSDOMParser } from './jats-dom-parser'
|
|
20
|
+
import { updateDocumentIDs } from './jats-parser-utils'
|
|
21
|
+
import {
|
|
22
|
+
addMissingCaptions,
|
|
23
|
+
createAbstracts,
|
|
24
|
+
createAccessibilityItems,
|
|
25
|
+
createAttachments,
|
|
26
|
+
createBackmatter,
|
|
27
|
+
createBody,
|
|
28
|
+
createBoxedElementSection,
|
|
29
|
+
createKeywordsSection,
|
|
30
|
+
createSupplementaryMaterialsSection,
|
|
31
|
+
createTitles,
|
|
32
|
+
fixTables,
|
|
33
|
+
moveAffiliations,
|
|
34
|
+
moveAuthorNotes,
|
|
35
|
+
moveAwards,
|
|
36
|
+
moveCaptionsToEnd,
|
|
37
|
+
moveContributors,
|
|
38
|
+
moveHeroImage,
|
|
39
|
+
moveReferencesToBackmatter,
|
|
40
|
+
orderTableFootnote,
|
|
41
|
+
} from './jats-transformations'
|
|
42
|
+
|
|
43
|
+
const processJATS = (doc: Document, sectionCategories: SectionCategory[]) => {
|
|
44
|
+
const createElement = createElementFn(doc)
|
|
45
|
+
markComments(doc)
|
|
46
|
+
|
|
47
|
+
const front = doc.querySelector('front')
|
|
48
|
+
if (!front) {
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
addMissingCaptions(doc, createElement)
|
|
52
|
+
createBoxedElementSection(doc, createElement)
|
|
53
|
+
createTitles(front, createElement)
|
|
54
|
+
moveContributors(front, createElement)
|
|
55
|
+
moveAffiliations(front, createElement)
|
|
56
|
+
moveAuthorNotes(front, createElement)
|
|
57
|
+
moveAwards(front)
|
|
58
|
+
|
|
59
|
+
let body = doc.querySelector('body')
|
|
60
|
+
if (!body) {
|
|
61
|
+
body = createElement('body') as HTMLBodyElement
|
|
62
|
+
const article = doc.querySelector('article')
|
|
63
|
+
if (!article) {
|
|
64
|
+
return
|
|
65
|
+
}
|
|
66
|
+
article.append(body)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
moveCaptionsToEnd(body)
|
|
70
|
+
createBody(doc, body, createElement)
|
|
71
|
+
createAbstracts(front, body, createElement, sectionCategories)
|
|
72
|
+
createBackmatter(doc, body, sectionCategories, createElement)
|
|
73
|
+
createSupplementaryMaterialsSection(doc, body, createElement)
|
|
74
|
+
createKeywordsSection(doc, body, createElement)
|
|
75
|
+
fixTables(doc, body, createElement)
|
|
76
|
+
orderTableFootnote(doc, body)
|
|
77
|
+
moveHeroImage(doc)
|
|
78
|
+
createAttachments(doc, createElement)
|
|
79
|
+
const back = doc.querySelector('back')
|
|
80
|
+
if (!back) {
|
|
81
|
+
return
|
|
82
|
+
}
|
|
83
|
+
moveReferencesToBackmatter(body, back, createElement)
|
|
84
|
+
createAccessibilityItems(doc, createElement)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const createElementFn = (doc: Document) => (tagName: string) =>
|
|
88
|
+
doc.createElement(tagName)
|
|
89
|
+
|
|
90
|
+
export const parseJATSArticle = (
|
|
91
|
+
doc: Document,
|
|
92
|
+
sectionCategories: SectionCategory[],
|
|
93
|
+
template?: string
|
|
94
|
+
) => {
|
|
95
|
+
processJATS(doc, sectionCategories)
|
|
96
|
+
const node = new JATSDOMParser(sectionCategories, schema).parse(doc)
|
|
97
|
+
.firstChild as ActualManuscriptNode
|
|
98
|
+
if (!node) {
|
|
99
|
+
throw new Error('No content was parsed from the JATS article body')
|
|
100
|
+
}
|
|
101
|
+
updateDocumentIDs(node)
|
|
102
|
+
if (template) {
|
|
103
|
+
node.attrs.prototype = template
|
|
104
|
+
}
|
|
105
|
+
return node
|
|
106
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* © 2020 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
|
+
export * from './exporter/jats-exporter'
|
|
18
|
+
export * from './exporter/jats-versions'
|
|
19
|
+
export * from './exporter/labels'
|
|
20
|
+
export * from './importer/create-article-node'
|
|
21
|
+
export { parseJATSArticle } from './importer/parse-jats-article'
|