@manuscripts/body-editor 3.12.67 → 3.13.0
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/components/toolbar/type-selector/styles.js +2 -1
- package/dist/cjs/versions.js +1 -1
- package/dist/es/components/toolbar/type-selector/styles.js +2 -1
- package/dist/es/versions.js +1 -1
- package/dist/types/components/toolbar/type-selector/styles.d.ts +2 -2
- package/dist/types/lib/footnotes.d.ts +4 -2
- package/dist/types/lib/utils.d.ts +5 -4
- package/dist/types/versions.d.ts +1 -1
- package/package.json +37 -36
- package/{dist/es/lib/statistics.js → src/__mocks__/styleMock.ts} +2 -14
- package/src/assets.ts +20 -0
- package/src/classes/collabProvider.ts +38 -0
- package/src/clipboard.ts +54 -0
- package/src/commands.ts +2109 -0
- package/src/components/ChangeHandlingForm.tsx +54 -0
- package/src/components/LanguageDropdown/index.tsx +343 -0
- package/src/components/affiliations/AffiliationForm.tsx +238 -0
- package/src/components/affiliations/AffiliationItem.tsx +151 -0
- package/src/components/affiliations/AffiliationList.tsx +71 -0
- package/src/components/affiliations/AffiliationsModal.tsx +676 -0
- package/src/components/affiliations/AffiliationsPanel.tsx +76 -0
- package/src/components/affiliations/CreateAffiliationModal.tsx +135 -0
- package/src/components/authors/AuthorDetailsForm.tsx +438 -0
- package/src/components/authors/AuthorList.tsx +81 -0
- package/src/components/authors/AuthorsModal.tsx +642 -0
- package/src/components/authors/AuthorsPanel.tsx +69 -0
- package/src/components/authors/CreateAuthorModal.tsx +172 -0
- package/src/components/authors/CreditDrawer.tsx +71 -0
- package/src/components/authors/DraggableAuthor.tsx +228 -0
- package/src/components/authors/useManageAffiliations.tsx +77 -0
- package/src/components/authors/useManageCredit.tsx +63 -0
- package/src/components/authors-affiliations/AuthorsAndAffiliationsModals.tsx +170 -0
- package/src/components/authors-affiliations/GenericPanel.tsx +164 -0
- package/src/components/authors-affiliations/ModalTabs.tsx +100 -0
- package/src/components/awards/AwardForm.tsx +338 -0
- package/src/components/awards/AwardModal.tsx +120 -0
- package/src/components/awards/DeleteAwardDiaolog.tsx +52 -0
- package/src/components/dialog/ConfirmationDialog.tsx +131 -0
- package/src/components/form/CreateModalStyles.tsx +37 -0
- package/src/components/form/FormFooter.tsx +54 -0
- package/src/components/form/FormPlaceholder.tsx +71 -0
- package/src/components/form/ModalFormActions.tsx +88 -0
- package/src/components/form/UnsavedLabel.tsx +49 -0
- package/src/components/hooks/use-debounce.ts +56 -0
- package/src/components/hooks/useAffiliationShowsErrorIndicator.ts +51 -0
- package/src/components/hooks/useAuthorShowsErrorIndicator.ts +73 -0
- package/src/components/keyboard-shortcuts-modal/FormattedShortcut.tsx +56 -0
- package/src/components/keyboard-shortcuts-modal/KeyboardShortcutsModal.tsx +283 -0
- package/src/components/keyboard-shortcuts-modal/keyboard-shortcuts.ts +304 -0
- package/src/components/keywords/AddKeywordInline.tsx +284 -0
- package/src/components/keywords/DeleteKeywordDialog.tsx +52 -0
- package/src/components/modal-drawer/GenericDrawer.tsx +65 -0
- package/src/components/modal-drawer/GenericDrawerGroup.tsx +125 -0
- package/src/components/outline/DraggableTree.tsx +438 -0
- package/src/components/outline/ManuscriptOutline.tsx +127 -0
- package/src/components/outline/Outline.tsx +141 -0
- package/src/components/references/BibliographyItemSource.ts +80 -0
- package/src/components/references/CitationEditor.tsx +301 -0
- package/src/components/references/CitationViewer.tsx +62 -0
- package/src/components/references/ImportBibliographyForm.tsx +232 -0
- package/src/components/references/ImportBibliographyModal.tsx +159 -0
- package/src/components/references/ReferenceForm/PersonDropDown.tsx +93 -0
- package/src/components/references/ReferenceForm/ReferenceForm.tsx +701 -0
- package/src/components/references/ReferenceForm/config.ts +133 -0
- package/src/components/references/ReferenceForm/styled-components.ts +156 -0
- package/src/components/references/ReferenceLine.tsx +43 -0
- package/src/components/references/ReferenceSearch.tsx +163 -0
- package/src/components/references/ReferenceSearchResults.tsx +113 -0
- package/src/components/references/ReferenceSearchResultsPlaceholder.tsx +71 -0
- package/src/components/references/ReferenceSearchSection.tsx +124 -0
- package/src/components/references/ReferencesEditor.tsx +61 -0
- package/src/components/references/ReferencesModal.tsx +352 -0
- package/src/components/references/SearchInput.tsx +98 -0
- package/src/components/toolbar/InsertEmbedDialog.tsx +222 -0
- package/src/components/toolbar/InsertTableDialog.tsx +208 -0
- package/src/components/toolbar/ListMenuItem.tsx +203 -0
- package/src/components/toolbar/helpers.ts +547 -0
- package/src/components/toolbar/type-selector/OptionComponent.tsx +89 -0
- package/src/components/toolbar/type-selector/TypeSelector.tsx +157 -0
- package/src/components/toolbar/type-selector/styles.ts +79 -0
- package/src/components/views/CrossReferenceItems.tsx +199 -0
- package/src/components/views/DeleteEmbedDialog.tsx +83 -0
- package/src/components/views/DeleteFootnoteDialog.tsx +54 -0
- package/src/components/views/FigureDropdown.tsx +423 -0
- package/src/components/views/FootnotesSelector.tsx +255 -0
- package/src/components/views/InsertSpecialCharacter.tsx +245 -0
- package/src/components/views/LinkForm.tsx +220 -0
- package/src/components/views/TableCellContextMenu.tsx +241 -0
- package/src/configs/ManuscriptsEditor.ts +140 -0
- package/src/configs/editor-plugins.ts +119 -0
- package/src/configs/editor-views.ts +139 -0
- package/src/icons.ts +62 -0
- package/src/index.ts +65 -0
- package/src/keys/highlight.ts +65 -0
- package/src/keys/index.ts +33 -0
- package/src/keys/keyword.ts +69 -0
- package/src/keys/list.ts +156 -0
- package/src/keys/misc.ts +112 -0
- package/src/keys/title.ts +221 -0
- package/src/lib/__tests__/__fixtures__/doc.json +388 -0
- package/src/lib/__tests__/__snapshots__/paste.test.ts.snap +24 -0
- package/src/lib/__tests__/authors.test.ts +202 -0
- package/src/lib/__tests__/helpers.test.ts +46 -0
- package/src/lib/__tests__/paste.test.ts +57 -0
- package/src/lib/__tests__/plugins.test.ts +176 -0
- package/src/lib/__tests__/url.test.ts +31 -0
- package/src/lib/array-reducer.ts +68 -0
- package/src/lib/authors-and-affiliations.ts +81 -0
- package/src/lib/authors.ts +67 -0
- package/src/lib/capabilities.ts +55 -0
- package/src/lib/codemirror.ts +37 -0
- package/src/lib/comments.ts +123 -0
- package/src/lib/context-menu.ts +745 -0
- package/src/lib/copy.ts +30 -0
- package/src/lib/crossref.ts +90 -0
- package/src/lib/dnd.ts +29 -0
- package/src/lib/doc.ts +167 -0
- package/src/lib/dompurify.ts +28 -0
- package/src/lib/files.ts +180 -0
- package/src/lib/footnotes.ts +83 -0
- package/src/lib/get-media-type.ts +105 -0
- package/src/lib/helpers.ts +199 -0
- package/src/lib/hierarchy.ts +117 -0
- package/src/lib/languages.ts +37 -0
- package/src/lib/lists.ts +56 -0
- package/src/lib/math.ts +111 -0
- package/src/lib/media.ts +334 -0
- package/src/lib/navigation-utils.ts +235 -0
- package/src/lib/normalize.ts +70 -0
- package/src/lib/paste.ts +304 -0
- package/src/lib/placeholder.ts +32 -0
- package/src/lib/platform.ts +18 -0
- package/src/lib/plugins.ts +22 -0
- package/src/lib/popper.ts +180 -0
- package/src/lib/position-menu.ts +184 -0
- package/src/lib/references.ts +94 -0
- package/src/lib/template.ts +29 -0
- package/src/lib/track-changes-utils.ts +34 -0
- package/{dist/types/lib/statistics.d.ts → src/lib/url.ts} +11 -8
- package/src/lib/use-do-with-debounce.ts +39 -0
- package/src/lib/utils.ts +323 -0
- package/src/lib/view.ts +100 -0
- package/src/menus.tsx +684 -0
- package/src/node-type-icons.tsx +83 -0
- package/src/plugins/__tests__/__fixtures__/deleted-footnote.json +140 -0
- package/src/plugins/__tests__/__fixtures__/inserted-footnote.json +153 -0
- package/src/plugins/__tests__/footnotes.test.ts +67 -0
- package/src/plugins/accessibility_element.ts +219 -0
- package/src/plugins/add-subtitle.ts +102 -0
- package/src/plugins/affiliations.ts +136 -0
- package/src/plugins/alt-titles.ts +219 -0
- package/src/plugins/bibliography.ts +235 -0
- package/src/plugins/comments.ts +328 -0
- package/src/plugins/cross-references.ts +70 -0
- package/src/plugins/detect-inconsistency/detect-inconsistency-utils.ts +102 -0
- package/src/plugins/detect-inconsistency/index.ts +55 -0
- package/src/plugins/detect-inconsistency/validators.ts +283 -0
- package/src/plugins/doi.ts +66 -0
- package/src/plugins/editor-props.ts +39 -0
- package/src/plugins/elements.ts +60 -0
- package/src/plugins/footnotes.ts +298 -0
- package/src/plugins/link.ts +53 -0
- package/src/plugins/lock-body.ts +136 -0
- package/src/plugins/move-node.ts +55 -0
- package/src/plugins/objects.ts +125 -0
- package/src/plugins/paragraphs.ts +90 -0
- package/src/plugins/persist.ts +64 -0
- package/src/plugins/persistent-cursor.ts +66 -0
- package/src/plugins/placeholder.ts +219 -0
- package/src/plugins/prevent-empty.ts +50 -0
- package/src/plugins/search-replace/index.ts +157 -0
- package/src/plugins/search-replace/lib.ts +95 -0
- package/src/plugins/section_category.ts +212 -0
- package/src/plugins/section_title/autocompletion.ts +87 -0
- package/src/plugins/section_title/index.ts +105 -0
- package/src/plugins/selected-suggestion.ts +243 -0
- package/src/plugins/tables-cursor-fix.ts +143 -0
- package/src/plugins/translations.ts +263 -0
- package/src/rules.ts +60 -0
- package/src/selection.ts +112 -0
- package/src/testing/default-capabilities.ts +48 -0
- package/src/testing/default-editor-data.ts +73 -0
- package/src/testing/empty-editor-doc.json +62 -0
- package/src/testing/polyfill-dom.ts +43 -0
- package/src/testing/section-categories.json +161 -0
- package/src/testing/setup-editor.ts +55 -0
- package/src/tests.ts +42 -0
- package/src/toolbar.tsx +259 -0
- package/src/types/@citation-js/core.d.ts +16 -0
- package/src/types/@citation-js/index.d.ts +16 -0
- package/src/types/@citation-js/plugin-bibtex.d.ts +16 -0
- package/src/types/@citation-js/plugin-csl.d.ts +16 -0
- package/src/types/@citation-js/plugin-doi.d.ts +16 -0
- package/src/types/@citation-js/plugin-enw.d.ts +16 -0
- package/src/types/@citation-js/plugin-pubmed.d.ts +16 -0
- package/src/types/@citation-js/plugin-ris.d.ts +16 -0
- package/src/types/citeproc.d.ts +124 -0
- package/src/types/css.d.ts +16 -0
- package/src/types/json.d.ts +17 -0
- package/src/types/prosemirror-dev-tools.d.ts +16 -0
- package/src/types/prosemirror-dropcursor.d.ts +16 -0
- package/src/types/styled-components.d.ts +23 -0
- package/src/types.ts +49 -0
- package/src/useEditor.ts +244 -0
- package/src/versions.ts +3 -0
- package/src/views/ReactSubView.tsx +145 -0
- package/src/views/abstracts.ts +46 -0
- package/src/views/accessibility_element.ts +86 -0
- package/src/views/affiliations.ts +254 -0
- package/src/views/alt_title.ts +85 -0
- package/src/views/alt_titles_section.ts +97 -0
- package/src/views/attachment.ts +160 -0
- package/src/views/attachments.ts +72 -0
- package/src/views/author_notes.ts +96 -0
- package/src/views/award.ts +194 -0
- package/src/views/awards.ts +59 -0
- package/src/views/base_node_view.ts +85 -0
- package/src/views/bibliography_element.ts +313 -0
- package/src/views/block_view.ts +100 -0
- package/src/views/blockquote_element.ts +26 -0
- package/src/views/blockquote_element_editable.ts +24 -0
- package/src/views/box_element.ts +33 -0
- package/src/views/caption.ts +37 -0
- package/src/views/caption_title.ts +33 -0
- package/src/views/citation.ts +67 -0
- package/src/views/citation_editable.ts +312 -0
- package/src/views/contributors.ts +341 -0
- package/src/views/creators.ts +82 -0
- package/src/views/cross_reference.ts +74 -0
- package/src/views/cross_reference_editable.ts +113 -0
- package/src/views/editable_block.ts +141 -0
- package/src/views/embed.ts +345 -0
- package/src/views/empty.ts +26 -0
- package/src/views/equation.ts +47 -0
- package/src/views/equation_editable.ts +84 -0
- package/src/views/equation_element.ts +29 -0
- package/src/views/equation_element_editable.ts +21 -0
- package/src/views/figure.ts +84 -0
- package/src/views/figure_editable.ts +361 -0
- package/src/views/figure_element.ts +197 -0
- package/src/views/figure_element_editable.ts +21 -0
- package/src/views/footnote.ts +236 -0
- package/src/views/footnotes_element.ts +54 -0
- package/src/views/general_table_footnote.ts +140 -0
- package/src/views/hero_image.ts +76 -0
- package/src/views/hero_image_editable.ts +21 -0
- package/src/views/image_element.ts +373 -0
- package/src/views/image_element_editable.ts +21 -0
- package/src/views/inline_equation.ts +47 -0
- package/src/views/inline_equation_editable.ts +70 -0
- package/src/views/inline_footnote.ts +264 -0
- package/src/views/inline_footnote_editable.ts +20 -0
- package/src/views/keyword.ts +127 -0
- package/src/views/keyword_group.ts +109 -0
- package/src/views/link.ts +27 -0
- package/src/views/link_editable.ts +169 -0
- package/src/views/list.ts +46 -0
- package/src/views/list_item.ts +26 -0
- package/src/views/paragraph.ts +26 -0
- package/src/views/paragraph_editable.ts +21 -0
- package/src/views/placeholder.ts +35 -0
- package/src/views/placeholder_element.ts +38 -0
- package/src/views/placeholder_element_editable.ts +21 -0
- package/src/views/pullquote_element.ts +106 -0
- package/src/views/pullquote_element_editable.ts +24 -0
- package/src/views/quote_image_editable.ts +84 -0
- package/src/views/section.ts +64 -0
- package/src/views/section_label.ts +20 -0
- package/src/views/section_title.ts +87 -0
- package/src/views/section_title_editable.ts +21 -0
- package/src/views/subtitle.ts +42 -0
- package/src/views/subtitle_editable.ts +20 -0
- package/src/views/subtitles.ts +34 -0
- package/src/views/subtitles_editable.ts +21 -0
- package/src/views/supplement.ts +236 -0
- package/src/views/supplement_editable.ts +20 -0
- package/src/views/supplements.ts +65 -0
- package/src/views/supplements_editable.ts +21 -0
- package/src/views/table_cell.ts +150 -0
- package/src/views/table_element.ts +33 -0
- package/src/views/table_element_editable.ts +21 -0
- package/src/views/table_element_footer.ts +41 -0
- package/src/views/title.ts +46 -0
- package/src/views/title_editable.ts +20 -0
- package/src/views/trans_graphical_abstract.ts +55 -0
- package/src/views/trans_graphical_abstract_editable.ts +21 -0
- package/src/views/translated_abstract.ts +53 -0
- package/src/views/translated_abstract_editable.ts +21 -0
- package/dist/cjs/lib/statistics.js +0 -38
package/src/lib/copy.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* © 2024 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 { Slice } from 'prosemirror-model'
|
|
17
|
+
|
|
18
|
+
// TODO: checking the ability to remove the following logic, after the following ticket LEAN-4118 is resolved
|
|
19
|
+
export const transformCopied = (slice: Slice) => {
|
|
20
|
+
if (
|
|
21
|
+
slice.openStart !== slice.openEnd &&
|
|
22
|
+
(slice.content.firstChild?.type.isBlock ||
|
|
23
|
+
slice.content.lastChild?.type.isBlock)
|
|
24
|
+
) {
|
|
25
|
+
const cutDepth = Math.min(slice.openStart, slice.openEnd)
|
|
26
|
+
// rebalance slice sides to be digestible for track changes plugin
|
|
27
|
+
return new Slice(slice.content, cutDepth, cutDepth)
|
|
28
|
+
}
|
|
29
|
+
return slice
|
|
30
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
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
|
+
|
|
17
|
+
import { generateNodeID, schema } from '@manuscripts/transform'
|
|
18
|
+
|
|
19
|
+
import {
|
|
20
|
+
BibliographyItemSearch,
|
|
21
|
+
BibliographyItemSource,
|
|
22
|
+
} from '../components/references/BibliographyItemSource'
|
|
23
|
+
|
|
24
|
+
type CrossrefItem = {
|
|
25
|
+
[key: string]: unknown
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
type CrossrefResponse = {
|
|
29
|
+
message: {
|
|
30
|
+
items: CrossrefItem[]
|
|
31
|
+
'total-results': number
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const search = (query: string, limit: number): BibliographyItemSearch => {
|
|
36
|
+
const controller = new AbortController()
|
|
37
|
+
const params = new URLSearchParams({
|
|
38
|
+
filter: 'type:journal-article',
|
|
39
|
+
query,
|
|
40
|
+
rows: String(limit),
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
const promise = searchAsync(params, controller)
|
|
44
|
+
|
|
45
|
+
return new BibliographyItemSearch((resolve, reject) => {
|
|
46
|
+
promise.then(resolve).catch(reject)
|
|
47
|
+
}, controller)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const searchAsync = async (
|
|
51
|
+
params: URLSearchParams,
|
|
52
|
+
controller: AbortController
|
|
53
|
+
) => {
|
|
54
|
+
const response = await fetch(`https://api.crossref.org/works?${params}`, {
|
|
55
|
+
signal: controller.signal,
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
if (!response.ok) {
|
|
59
|
+
throw new Error('There was a problem searching for this query.')
|
|
60
|
+
}
|
|
61
|
+
const data = (await response.json()) as CrossrefResponse
|
|
62
|
+
const items = data.message.items.map(fixItem)
|
|
63
|
+
const total = data.message['total-results']
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
items,
|
|
67
|
+
total,
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export const Crossref: BibliographyItemSource = {
|
|
72
|
+
id: 'crossref',
|
|
73
|
+
label: 'External sources',
|
|
74
|
+
search,
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const fixItem = (item: CrossrefItem): CSL.Data => {
|
|
78
|
+
for (const key in item) {
|
|
79
|
+
if (key === 'author' || key === 'editor') {
|
|
80
|
+
continue
|
|
81
|
+
}
|
|
82
|
+
const value = item[key]
|
|
83
|
+
if (Array.isArray(value)) {
|
|
84
|
+
const [data] = item[key] as string[]
|
|
85
|
+
item[key] = data || undefined
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
item.id = generateNodeID(schema.nodes.bibliography_item)
|
|
89
|
+
return item as CSL.Data
|
|
90
|
+
}
|
package/src/lib/dnd.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* © 2024 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 { DropTargetMonitor, XYCoord } from 'react-dnd'
|
|
17
|
+
|
|
18
|
+
export type DropSide = 'before' | 'after'
|
|
19
|
+
|
|
20
|
+
export const getDropSide = (element: Element, monitor: DropTargetMonitor) => {
|
|
21
|
+
const rect = element.getBoundingClientRect()
|
|
22
|
+
|
|
23
|
+
// Get vertical middle
|
|
24
|
+
const middle = (rect.bottom - rect.top) / 2
|
|
25
|
+
|
|
26
|
+
const offset = monitor.getClientOffset() as XYCoord
|
|
27
|
+
|
|
28
|
+
return offset.y > middle + rect.top ? 'after' : 'before'
|
|
29
|
+
}
|
package/src/lib/doc.ts
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* © 2024 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 {
|
|
17
|
+
AwardsNode,
|
|
18
|
+
generateNodeID,
|
|
19
|
+
ManuscriptNode,
|
|
20
|
+
ManuscriptTransaction,
|
|
21
|
+
schema,
|
|
22
|
+
SupplementNode,
|
|
23
|
+
SupplementsNode,
|
|
24
|
+
} from '@manuscripts/transform'
|
|
25
|
+
import { findChildren, findChildrenByType } from 'prosemirror-utils'
|
|
26
|
+
|
|
27
|
+
import { findInsertionPosition } from './utils'
|
|
28
|
+
|
|
29
|
+
export const insertAwardsNode = (tr: ManuscriptTransaction) => {
|
|
30
|
+
const doc = tr.doc
|
|
31
|
+
const awards = findChildrenByType(doc, schema.nodes.awards)[0]
|
|
32
|
+
if (awards) {
|
|
33
|
+
return awards
|
|
34
|
+
}
|
|
35
|
+
const pos = findInsertionPosition(schema.nodes.awards, doc)
|
|
36
|
+
// const node = schema.nodes.awards.create() as AwardsNode
|
|
37
|
+
const node = schema.nodes.awards.createAndFill() as AwardsNode
|
|
38
|
+
tr.insert(pos, node)
|
|
39
|
+
return {
|
|
40
|
+
node,
|
|
41
|
+
pos,
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export const upsertSupplementsSection = (
|
|
46
|
+
tr: ManuscriptTransaction,
|
|
47
|
+
supplement: SupplementNode
|
|
48
|
+
) => {
|
|
49
|
+
const doc = tr.doc
|
|
50
|
+
const supplements = findChildrenByType(doc, schema.nodes.supplements)[0]
|
|
51
|
+
if (supplements) {
|
|
52
|
+
// Section exists -> insert inside it
|
|
53
|
+
const pos = supplements.pos + supplements.node.nodeSize - 1
|
|
54
|
+
tr.insert(pos, supplement)
|
|
55
|
+
return { node: supplements.node, pos }
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Section missing -> create new with supplement inside
|
|
59
|
+
const pos = findInsertionPosition(schema.nodes.supplements, doc)
|
|
60
|
+
const node = schema.nodes.supplements.createAndFill(
|
|
61
|
+
{ id: generateNodeID(schema.nodes.supplements) },
|
|
62
|
+
[
|
|
63
|
+
schema.nodes.section_title.create(undefined, schema.text('Supplements')),
|
|
64
|
+
supplement,
|
|
65
|
+
]
|
|
66
|
+
) as SupplementsNode
|
|
67
|
+
|
|
68
|
+
tr.insert(pos, node)
|
|
69
|
+
return {
|
|
70
|
+
node,
|
|
71
|
+
pos,
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export const insertAttachmentsNode = (tr: ManuscriptTransaction) => {
|
|
76
|
+
const attachmentsNodes = findChildrenByType(tr.doc, schema.nodes.attachments)
|
|
77
|
+
if (attachmentsNodes.length) {
|
|
78
|
+
return {
|
|
79
|
+
node: attachmentsNodes[0].node,
|
|
80
|
+
pos: attachmentsNodes[0].pos,
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const pos = findInsertionPosition(schema.nodes.attachments, tr.doc)
|
|
84
|
+
const node = schema.nodes.attachments.create({
|
|
85
|
+
id: generateNodeID(schema.nodes.attachments),
|
|
86
|
+
})
|
|
87
|
+
tr.insert(pos, node)
|
|
88
|
+
return { node, pos }
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export const insertFootnotesSection = (tr: ManuscriptTransaction) => {
|
|
92
|
+
const doc = tr.doc
|
|
93
|
+
const section = findChildrenByType(doc, schema.nodes.footnotes_section)[0]
|
|
94
|
+
if (section) {
|
|
95
|
+
return section
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const backmatter = findChildrenByType(doc, schema.nodes.backmatter, true)
|
|
99
|
+
|
|
100
|
+
const backmatterNode = backmatter[0].node
|
|
101
|
+
const backmatterPos = backmatter[0].pos
|
|
102
|
+
|
|
103
|
+
// Find the last child node in the backmatter (references section)
|
|
104
|
+
const lastChild =
|
|
105
|
+
backmatterNode.content.childCount > 0
|
|
106
|
+
? backmatterNode.content.child(backmatterNode.content.childCount - 1)
|
|
107
|
+
: null
|
|
108
|
+
|
|
109
|
+
const insertPos =
|
|
110
|
+
lastChild && lastChild.type === schema.nodes.bibliography_section
|
|
111
|
+
? backmatterPos + backmatterNode.content.size - lastChild.nodeSize // Insert before last child (refernces section)
|
|
112
|
+
: backmatterPos + backmatterNode.content.size // Insert at the end of backmatter
|
|
113
|
+
|
|
114
|
+
const pos = tr.mapping.map(insertPos)
|
|
115
|
+
|
|
116
|
+
const node = schema.nodes.footnotes_section.create({}, [
|
|
117
|
+
schema.nodes.section_title.create({}, schema.text('Footnotes')),
|
|
118
|
+
])
|
|
119
|
+
tr.insert(pos, node)
|
|
120
|
+
return {
|
|
121
|
+
node,
|
|
122
|
+
pos,
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export const findAbstractsNode = (doc: ManuscriptNode) => {
|
|
127
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
128
|
+
return findChildrenByType(doc, schema.nodes.abstracts)[0]!
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export const findBody = (doc: ManuscriptNode) => {
|
|
132
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
133
|
+
return findChildrenByType(doc, schema.nodes.body)[0]!
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export const findBackmatter = (doc: ManuscriptNode) => {
|
|
137
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
138
|
+
return findChildrenByType(doc, schema.nodes.backmatter)[0]!
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export const findBibliographySection = (doc: ManuscriptNode) => {
|
|
142
|
+
return findChildrenByType(doc, schema.nodes.bibliography_section)[0]
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export const findFootnotesSection = (doc: ManuscriptNode) => {
|
|
146
|
+
return findChildrenByType(doc, schema.nodes.footnotes_section)[0]
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export const findGraphicalAbstractFigureElement = (doc: ManuscriptNode) => {
|
|
150
|
+
const ga = findChildrenByType(doc, schema.nodes.graphical_abstract_section)[0]
|
|
151
|
+
if (!ga) {
|
|
152
|
+
return
|
|
153
|
+
}
|
|
154
|
+
const element = findChildrenByType(ga.node, schema.nodes.figure_element)[0]
|
|
155
|
+
if (!element) {
|
|
156
|
+
return
|
|
157
|
+
}
|
|
158
|
+
return {
|
|
159
|
+
node: element.node,
|
|
160
|
+
pos: ga.pos + element.pos + 1,
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export const findNodeByID = (doc: ManuscriptNode, id: string) => {
|
|
165
|
+
const children = findChildren(doc, (n) => n.attrs.id === id)
|
|
166
|
+
return children[0]
|
|
167
|
+
}
|
|
@@ -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
|
+
|
|
17
|
+
import purify, { Config } from 'dompurify'
|
|
18
|
+
|
|
19
|
+
type Sanitize = (
|
|
20
|
+
dirty: string,
|
|
21
|
+
config?: Pick<Config, 'USE_PROFILES' | 'ALLOWED_TAGS'>
|
|
22
|
+
) => DocumentFragment
|
|
23
|
+
|
|
24
|
+
export const sanitize: Sanitize = (dirty, config) =>
|
|
25
|
+
purify.sanitize(dirty, {
|
|
26
|
+
RETURN_DOM_FRAGMENT: true,
|
|
27
|
+
...config,
|
|
28
|
+
})
|
package/src/lib/files.ts
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* © 2024 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 { ManuscriptNode, schema } from '@manuscripts/transform'
|
|
17
|
+
import { findChildrenByType } from 'prosemirror-utils'
|
|
18
|
+
|
|
19
|
+
import { isHidden } from './track-changes-utils'
|
|
20
|
+
|
|
21
|
+
export type FileAttachment = {
|
|
22
|
+
id: string
|
|
23
|
+
name: string
|
|
24
|
+
link?: string
|
|
25
|
+
createdDate?: Date
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type NodeFile = {
|
|
29
|
+
node: ManuscriptNode
|
|
30
|
+
pos: number
|
|
31
|
+
file: FileAttachment
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export type ElementFiles = {
|
|
35
|
+
node: ManuscriptNode
|
|
36
|
+
pos: number
|
|
37
|
+
files: NodeFile[]
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export type ManuscriptFiles = {
|
|
41
|
+
figures: ElementFiles[]
|
|
42
|
+
supplements: NodeFile[]
|
|
43
|
+
attachments: NodeFile[]
|
|
44
|
+
linkedFiles: NodeFile[]
|
|
45
|
+
others: FileAttachment[]
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const MISSING_FILE: FileAttachment = {
|
|
49
|
+
id: '',
|
|
50
|
+
name: '',
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export type Upload = (
|
|
54
|
+
file: File,
|
|
55
|
+
OnProgress?: (percentage: number) => void
|
|
56
|
+
) => Promise<FileAttachment>
|
|
57
|
+
|
|
58
|
+
export type Download = (file: FileAttachment) => void
|
|
59
|
+
|
|
60
|
+
export type PreviewLink = (file: FileAttachment) => string | undefined
|
|
61
|
+
|
|
62
|
+
export type FileManagement = {
|
|
63
|
+
upload: Upload
|
|
64
|
+
download: Download
|
|
65
|
+
previewLink: PreviewLink
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const figureTypes = [
|
|
69
|
+
schema.nodes.figure_element,
|
|
70
|
+
schema.nodes.image_element,
|
|
71
|
+
schema.nodes.hero_image,
|
|
72
|
+
schema.nodes.embed,
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
export function memoGroupFiles() {
|
|
76
|
+
let prevFiles: FileAttachment[] = []
|
|
77
|
+
let prevDoc: ManuscriptNode | undefined = undefined
|
|
78
|
+
let result: ManuscriptFiles | undefined
|
|
79
|
+
|
|
80
|
+
return function (doc: ManuscriptNode, files: FileAttachment[]) {
|
|
81
|
+
if (result && prevDoc === doc && prevFiles === files) {
|
|
82
|
+
return result
|
|
83
|
+
}
|
|
84
|
+
prevDoc = doc
|
|
85
|
+
prevFiles = files
|
|
86
|
+
return groupFiles(doc, files)
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export const groupFiles = (
|
|
91
|
+
doc: ManuscriptNode,
|
|
92
|
+
files: FileAttachment[]
|
|
93
|
+
): ManuscriptFiles => {
|
|
94
|
+
const fileMap = new Map(files.map((f) => [f.id, f]))
|
|
95
|
+
const figures: ElementFiles[] = []
|
|
96
|
+
const supplements: NodeFile[] = []
|
|
97
|
+
const linkedFiles: NodeFile[] = []
|
|
98
|
+
const attachments: NodeFile[] = []
|
|
99
|
+
|
|
100
|
+
const getFile = (href: string) => {
|
|
101
|
+
const file = fileMap.get(href)
|
|
102
|
+
if (file) {
|
|
103
|
+
fileMap.delete(href)
|
|
104
|
+
return file
|
|
105
|
+
} else {
|
|
106
|
+
return MISSING_FILE
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const getFigureElementFiles = (node: ManuscriptNode, pos: number) => {
|
|
111
|
+
const figureFiles = []
|
|
112
|
+
|
|
113
|
+
if (node.type === schema.nodes.embed) {
|
|
114
|
+
if (node.attrs.href) {
|
|
115
|
+
figureFiles.push({
|
|
116
|
+
node,
|
|
117
|
+
pos,
|
|
118
|
+
file: getFile(node.attrs.href),
|
|
119
|
+
})
|
|
120
|
+
}
|
|
121
|
+
} else {
|
|
122
|
+
for (const figure of findChildrenByType(node, schema.nodes.figure)) {
|
|
123
|
+
if (isHidden(figure.node)) {
|
|
124
|
+
continue
|
|
125
|
+
}
|
|
126
|
+
figureFiles.push({
|
|
127
|
+
node: figure.node,
|
|
128
|
+
pos: pos + figure.pos + 1,
|
|
129
|
+
file: getFile(figure.node.attrs.src),
|
|
130
|
+
})
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
node,
|
|
136
|
+
pos,
|
|
137
|
+
files: figureFiles,
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
doc.descendants((node, pos) => {
|
|
142
|
+
if (isHidden(node)) {
|
|
143
|
+
return
|
|
144
|
+
}
|
|
145
|
+
if (figureTypes.includes(node.type)) {
|
|
146
|
+
figures.push(getFigureElementFiles(node, pos))
|
|
147
|
+
}
|
|
148
|
+
if (node.type === schema.nodes.image_element) {
|
|
149
|
+
if (node.attrs.extLink) {
|
|
150
|
+
linkedFiles.push({
|
|
151
|
+
node,
|
|
152
|
+
pos,
|
|
153
|
+
file: getFile(node.attrs.extLink),
|
|
154
|
+
})
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
if (node.type === schema.nodes.supplement) {
|
|
158
|
+
supplements.push({
|
|
159
|
+
node,
|
|
160
|
+
pos,
|
|
161
|
+
file: getFile(node.attrs.href),
|
|
162
|
+
})
|
|
163
|
+
}
|
|
164
|
+
if (node.type === schema.nodes.attachment) {
|
|
165
|
+
attachments.push({
|
|
166
|
+
node,
|
|
167
|
+
pos,
|
|
168
|
+
file: getFile(node.attrs.href),
|
|
169
|
+
})
|
|
170
|
+
}
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
return {
|
|
174
|
+
figures,
|
|
175
|
+
supplements,
|
|
176
|
+
attachments,
|
|
177
|
+
linkedFiles,
|
|
178
|
+
others: [...fileMap.values()],
|
|
179
|
+
}
|
|
180
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* © 2024 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 {
|
|
18
|
+
FootnoteNode,
|
|
19
|
+
generateNodeID,
|
|
20
|
+
ManuscriptEditorState,
|
|
21
|
+
ManuscriptNode,
|
|
22
|
+
schema,
|
|
23
|
+
} from '@manuscripts/transform'
|
|
24
|
+
import { Selection } from 'prosemirror-state'
|
|
25
|
+
import {
|
|
26
|
+
ContentNodeWithPos,
|
|
27
|
+
findParentNodeOfType,
|
|
28
|
+
findParentNodeOfTypeClosestToPos,
|
|
29
|
+
} from 'prosemirror-utils'
|
|
30
|
+
|
|
31
|
+
import { footnotesKey } from '../plugins/footnotes'
|
|
32
|
+
|
|
33
|
+
export const findFootnotesContainerNode = (
|
|
34
|
+
doc: ManuscriptNode,
|
|
35
|
+
pos: number
|
|
36
|
+
) => {
|
|
37
|
+
const $pos = doc.resolve(pos)
|
|
38
|
+
return (
|
|
39
|
+
findParentNodeOfTypeClosestToPos($pos, schema.nodes.table_element) || {
|
|
40
|
+
node: doc,
|
|
41
|
+
pos: 0,
|
|
42
|
+
}
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const findParentFootnote: (selection: Selection) => ContentNodeWithPos | undefined = findParentNodeOfType([
|
|
47
|
+
schema.nodes.footnote,
|
|
48
|
+
schema.nodes.general_table_footnote,
|
|
49
|
+
])
|
|
50
|
+
|
|
51
|
+
export const getFootnotesElementState = (
|
|
52
|
+
state: ManuscriptEditorState,
|
|
53
|
+
id: string
|
|
54
|
+
) => {
|
|
55
|
+
const fns = footnotesKey.getState(state)
|
|
56
|
+
if (!fns) {
|
|
57
|
+
return
|
|
58
|
+
}
|
|
59
|
+
const elementID = fns.footnotesElementIDs.get(id)
|
|
60
|
+
if (!elementID) {
|
|
61
|
+
return
|
|
62
|
+
}
|
|
63
|
+
return fns.footnotesElements.get(elementID)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export const getFootnoteLabel = (
|
|
67
|
+
state: ManuscriptEditorState,
|
|
68
|
+
footnote: FootnoteNode
|
|
69
|
+
) => {
|
|
70
|
+
const id = footnote.attrs.id
|
|
71
|
+
const fns = getFootnotesElementState(state, id)
|
|
72
|
+
return fns?.labels.get(id) || ''
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export const createFootnote = () => {
|
|
76
|
+
return schema.nodes.footnote.createAndFill(
|
|
77
|
+
{
|
|
78
|
+
id: generateNodeID(schema.nodes.footnote),
|
|
79
|
+
kind: 'footnote',
|
|
80
|
+
},
|
|
81
|
+
[schema.nodes.paragraph.create({})]
|
|
82
|
+
) as FootnoteNode
|
|
83
|
+
}
|