@manuscripts/body-editor 3.12.66 → 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
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* © 2025 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
|
+
BibliographyItemAttrs,
|
|
19
|
+
ManuscriptNode,
|
|
20
|
+
nodeNames,
|
|
21
|
+
schema,
|
|
22
|
+
Target,
|
|
23
|
+
} from '@manuscripts/transform'
|
|
24
|
+
import { Decoration } from 'prosemirror-view'
|
|
25
|
+
|
|
26
|
+
import { EditorProps } from '../../configs/ManuscriptsEditor'
|
|
27
|
+
import { allowedHref } from '../../lib/url'
|
|
28
|
+
import { isChildOfNodeTypes } from '../../lib/utils'
|
|
29
|
+
import { FootnotesElementState } from '../footnotes'
|
|
30
|
+
import { createDecoration, Inconsistency } from './detect-inconsistency-utils'
|
|
31
|
+
|
|
32
|
+
export type ValidatorContext = {
|
|
33
|
+
pluginStates: {
|
|
34
|
+
affiliations: Map<string, number> | undefined
|
|
35
|
+
bibliography: Map<string, BibliographyItemAttrs> | undefined
|
|
36
|
+
objects: Map<string, Target> | undefined
|
|
37
|
+
footnotes: Map<string, string> | undefined
|
|
38
|
+
footnotesElements: Map<string, FootnotesElementState> | undefined
|
|
39
|
+
}
|
|
40
|
+
showDecorations: boolean
|
|
41
|
+
selectedPos: number | null
|
|
42
|
+
decorations: Decoration[]
|
|
43
|
+
props: EditorProps
|
|
44
|
+
doc: ManuscriptNode
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export type NodeValidator = (
|
|
48
|
+
node: ManuscriptNode,
|
|
49
|
+
pos: number,
|
|
50
|
+
context: ValidatorContext
|
|
51
|
+
) => Inconsistency[]
|
|
52
|
+
|
|
53
|
+
const getNodeDescription = (node: ManuscriptNode): string => {
|
|
54
|
+
return nodeNames.get(node.type) || node.type?.name || 'node'
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const createWarning = (
|
|
58
|
+
node: ManuscriptNode,
|
|
59
|
+
pos: number,
|
|
60
|
+
category: Inconsistency['category'],
|
|
61
|
+
severity: Inconsistency['severity'],
|
|
62
|
+
customNodeDescription?: string
|
|
63
|
+
): Inconsistency => {
|
|
64
|
+
const nodeDescription = customNodeDescription || getNodeDescription(node)
|
|
65
|
+
const message = (() => {
|
|
66
|
+
switch (node.type) {
|
|
67
|
+
case schema.nodes.figure_element:
|
|
68
|
+
case schema.nodes.image_element:
|
|
69
|
+
return 'Has no uploaded file'
|
|
70
|
+
case schema.nodes.embed:
|
|
71
|
+
return 'Has no link or uploaded file'
|
|
72
|
+
case schema.nodes.link:
|
|
73
|
+
return 'Url is empty'
|
|
74
|
+
case schema.nodes.footnote:
|
|
75
|
+
return 'Is not used'
|
|
76
|
+
case schema.nodes.affiliation:
|
|
77
|
+
return 'Is not corresponding to any Author'
|
|
78
|
+
default:
|
|
79
|
+
return category === 'empty-content'
|
|
80
|
+
? 'Is empty'
|
|
81
|
+
: 'Has no linked reference'
|
|
82
|
+
}
|
|
83
|
+
})()
|
|
84
|
+
|
|
85
|
+
return {
|
|
86
|
+
type: 'warning',
|
|
87
|
+
category,
|
|
88
|
+
severity,
|
|
89
|
+
message,
|
|
90
|
+
nodeDescription,
|
|
91
|
+
node,
|
|
92
|
+
pos,
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const validateTitle: NodeValidator = (node, pos, context) => {
|
|
97
|
+
const inconsistencies: Inconsistency[] = []
|
|
98
|
+
const isEmpty = node.content.size === 0
|
|
99
|
+
|
|
100
|
+
if (isEmpty) {
|
|
101
|
+
const inconsistency = createWarning(node, pos, 'empty-content', 'error')
|
|
102
|
+
inconsistencies.push(inconsistency)
|
|
103
|
+
|
|
104
|
+
if (context.showDecorations) {
|
|
105
|
+
context.decorations.push(createDecoration(node, pos, context.selectedPos))
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return inconsistencies
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const validateCrossReference: NodeValidator = (node, pos, context) => {
|
|
113
|
+
const inconsistencies: Inconsistency[] = []
|
|
114
|
+
const figures = Array.from(context.pluginStates.objects?.keys() ?? [])
|
|
115
|
+
|
|
116
|
+
const isInFigures = node.attrs.rids.every((rid: string) =>
|
|
117
|
+
figures.includes(rid)
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
if (!isInFigures) {
|
|
121
|
+
const inconsistency = createWarning(node, pos, 'missing-reference', 'error')
|
|
122
|
+
inconsistencies.push(inconsistency)
|
|
123
|
+
|
|
124
|
+
if (context.showDecorations) {
|
|
125
|
+
context.decorations.push(createDecoration(node, pos, context.selectedPos))
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return inconsistencies
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const validateCitation: NodeValidator = (node, pos, context) => {
|
|
133
|
+
const inconsistencies: Inconsistency[] = []
|
|
134
|
+
|
|
135
|
+
if (context.pluginStates.bibliography) {
|
|
136
|
+
const isInBibliography = node.attrs.rids.every((rid: string) =>
|
|
137
|
+
context.pluginStates.bibliography?.get(rid)
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
if (!isInBibliography || node.attrs.rids.length === 0) {
|
|
141
|
+
const inconsistency = createWarning(
|
|
142
|
+
node,
|
|
143
|
+
pos,
|
|
144
|
+
'missing-reference',
|
|
145
|
+
'error'
|
|
146
|
+
)
|
|
147
|
+
inconsistencies.push(inconsistency)
|
|
148
|
+
|
|
149
|
+
if (context.showDecorations) {
|
|
150
|
+
context.decorations.push(
|
|
151
|
+
createDecoration(node, pos, context.selectedPos)
|
|
152
|
+
)
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return inconsistencies
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const validateInlineFootnote: NodeValidator = (node, pos, context) => {
|
|
161
|
+
const inconsistencies: Inconsistency[] = []
|
|
162
|
+
if (context.pluginStates.footnotes) {
|
|
163
|
+
const isInFootnote = node.attrs.rids.every((rid: string) =>
|
|
164
|
+
context.pluginStates.footnotes?.get(rid)
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
if (!isInFootnote) {
|
|
168
|
+
const inconsistency = createWarning(
|
|
169
|
+
node,
|
|
170
|
+
pos,
|
|
171
|
+
'missing-reference',
|
|
172
|
+
'error'
|
|
173
|
+
)
|
|
174
|
+
inconsistencies.push(inconsistency)
|
|
175
|
+
|
|
176
|
+
if (context.showDecorations) {
|
|
177
|
+
context.decorations.push(
|
|
178
|
+
createDecoration(node, pos, context.selectedPos)
|
|
179
|
+
)
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return inconsistencies
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const validateFigure: NodeValidator = (node, pos, context) => {
|
|
188
|
+
const inconsistencies: Inconsistency[] = []
|
|
189
|
+
const files = new Set(context.props.getFiles().map((f) => f.id))
|
|
190
|
+
|
|
191
|
+
if (!files.has(node.attrs.src)) {
|
|
192
|
+
const inconsistency = createWarning(node, pos, 'missing-reference', 'error')
|
|
193
|
+
inconsistencies.push(inconsistency)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return inconsistencies
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const validateMedia: NodeValidator = (node, pos, context) => {
|
|
200
|
+
const inconsistencies: Inconsistency[] = []
|
|
201
|
+
const files = new Set(context.props.getFiles().map((f) => f.id))
|
|
202
|
+
|
|
203
|
+
if (!(files.has(node.attrs.href) || allowedHref(node.attrs.href))) {
|
|
204
|
+
const inconsistency = createWarning(node, pos, 'missing-reference', 'error')
|
|
205
|
+
inconsistencies.push(inconsistency)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return inconsistencies
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const validateLink: NodeValidator = (node, pos) => {
|
|
212
|
+
const inconsistencies: Inconsistency[] = []
|
|
213
|
+
|
|
214
|
+
if (!allowedHref(node.attrs.href)) {
|
|
215
|
+
const inconsistency = createWarning(node, pos, 'missing-reference', 'error')
|
|
216
|
+
inconsistencies.push(inconsistency)
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return inconsistencies
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const validateFootnote: NodeValidator = (node, pos, context) => {
|
|
223
|
+
const inconsistencies: Inconsistency[] = []
|
|
224
|
+
const id = context.pluginStates.footnotes?.get(node.attrs.id)
|
|
225
|
+
const footnoteState = id
|
|
226
|
+
? context.pluginStates.footnotesElements?.get(id)
|
|
227
|
+
: undefined
|
|
228
|
+
|
|
229
|
+
const unused = footnoteState?.unusedFootnoteIDs?.has(node.attrs.id)
|
|
230
|
+
|
|
231
|
+
if (unused) {
|
|
232
|
+
const isTableFootnote = isChildOfNodeTypes(context.doc, pos, [
|
|
233
|
+
schema.nodes.table_element,
|
|
234
|
+
])
|
|
235
|
+
|
|
236
|
+
const inconsistency = createWarning(
|
|
237
|
+
node,
|
|
238
|
+
pos,
|
|
239
|
+
'not-used',
|
|
240
|
+
'warning',
|
|
241
|
+
isTableFootnote ? 'table_footnote' : undefined
|
|
242
|
+
)
|
|
243
|
+
inconsistencies.push(inconsistency)
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return inconsistencies
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
const validateAffiliation: NodeValidator = (node, pos, context) => {
|
|
250
|
+
const inconsistencies: Inconsistency[] = []
|
|
251
|
+
const unused = !context.pluginStates.affiliations?.get(node.attrs.id)
|
|
252
|
+
|
|
253
|
+
if (unused) {
|
|
254
|
+
// Use the start position of the parent 'affiliations' node instead of the individual
|
|
255
|
+
// 'affiliation' node position because the DOM for individual affiliation nodes is
|
|
256
|
+
// rendered manually inside AffiliationsView. ProseMirror decorations only apply to
|
|
257
|
+
// nodes that it directly renders in the document DOM, so to ensure the warning
|
|
258
|
+
// decoration appears (or can be scrolled to), we must attach it to the parent node.
|
|
259
|
+
const $pos = context.doc.resolve(pos)
|
|
260
|
+
const affiliationsNodePos = $pos.before($pos.depth)
|
|
261
|
+
const inconsistency = createWarning(
|
|
262
|
+
node,
|
|
263
|
+
affiliationsNodePos,
|
|
264
|
+
'not-used',
|
|
265
|
+
'warning'
|
|
266
|
+
)
|
|
267
|
+
inconsistencies.push(inconsistency)
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
return inconsistencies
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export const validators: Record<string, NodeValidator> = {
|
|
274
|
+
[schema.nodes.title.name]: validateTitle,
|
|
275
|
+
[schema.nodes.cross_reference.name]: validateCrossReference,
|
|
276
|
+
[schema.nodes.citation.name]: validateCitation,
|
|
277
|
+
[schema.nodes.inline_footnote.name]: validateInlineFootnote,
|
|
278
|
+
[schema.nodes.figure.name]: validateFigure,
|
|
279
|
+
[schema.nodes.embed.name]: validateMedia,
|
|
280
|
+
[schema.nodes.link.name]: validateLink,
|
|
281
|
+
[schema.nodes.footnote.name]: validateFootnote,
|
|
282
|
+
[schema.nodes.affiliation.name]: validateAffiliation,
|
|
283
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
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 { Node } from 'prosemirror-model'
|
|
18
|
+
import { Plugin } from 'prosemirror-state'
|
|
19
|
+
import { Decoration, DecorationSet } from 'prosemirror-view'
|
|
20
|
+
|
|
21
|
+
export default () => {
|
|
22
|
+
return new Plugin({
|
|
23
|
+
state: {
|
|
24
|
+
init(_, { doc }) {
|
|
25
|
+
if (doc.attrs.doi) {
|
|
26
|
+
const decorations = createDecoration(doc)
|
|
27
|
+
return DecorationSet.create(doc, decorations)
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
apply(tr, oldDecorationSet, oldState, newState) {
|
|
31
|
+
if (tr.docChanged && newState.doc.attrs.doi) {
|
|
32
|
+
const decorations = createDecoration(newState.doc)
|
|
33
|
+
return DecorationSet.create(newState.doc, decorations)
|
|
34
|
+
}
|
|
35
|
+
return oldDecorationSet
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
props: {
|
|
39
|
+
decorations(state) {
|
|
40
|
+
return this.getState(state)
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function getPosition(doc: Node) {
|
|
47
|
+
const positions: number[] = []
|
|
48
|
+
const possibleNodesTypes = ['keywords', 'supplements', 'abstracts', 'body']
|
|
49
|
+
doc.descendants((node, pos) => {
|
|
50
|
+
if (possibleNodesTypes.includes(node.type.name)) {
|
|
51
|
+
positions.push(pos)
|
|
52
|
+
}
|
|
53
|
+
})
|
|
54
|
+
const position = positions.length === 0 ? 0 : Math.min(...positions)
|
|
55
|
+
return position
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function createDecoration(doc: Node) {
|
|
59
|
+
const decoration = Decoration.widget(getPosition(doc), () => {
|
|
60
|
+
const doiContainer = document.createElement('div')
|
|
61
|
+
doiContainer.classList.add('doi-container', 'block')
|
|
62
|
+
doiContainer.innerHTML = `<p>DOI: https://doi.org/${doc.attrs.doi}</p>`
|
|
63
|
+
return doiContainer
|
|
64
|
+
})
|
|
65
|
+
return [decoration]
|
|
66
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
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 { ManuscriptEditorState } from '@manuscripts/transform'
|
|
17
|
+
import { Plugin, PluginKey } from 'prosemirror-state'
|
|
18
|
+
|
|
19
|
+
import { EditorProps } from '../configs/ManuscriptsEditor'
|
|
20
|
+
|
|
21
|
+
export const editorPropsKey = new PluginKey<EditorProps>('editor-props')
|
|
22
|
+
|
|
23
|
+
export default (props: EditorProps) => {
|
|
24
|
+
return new Plugin<EditorProps>({
|
|
25
|
+
key: editorPropsKey,
|
|
26
|
+
state: {
|
|
27
|
+
init: () => {
|
|
28
|
+
return props
|
|
29
|
+
},
|
|
30
|
+
apply: () => {
|
|
31
|
+
return props
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
})
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const getEditorProps = (state: ManuscriptEditorState) => {
|
|
38
|
+
return editorPropsKey.getState(state) as EditorProps
|
|
39
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
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 { isSectionNodeType, schema } from '@manuscripts/transform'
|
|
18
|
+
import { Plugin } from 'prosemirror-state'
|
|
19
|
+
import { Decoration, DecorationSet } from 'prosemirror-view'
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* This plugin simply sets `element: true` in a Decoration spec for each element (a non-section node that is a child of a section).
|
|
23
|
+
* `createNodeOrElementView` uses this to decide whether to create a NodeView or just a regular DOM element.
|
|
24
|
+
* This is useful for paragraphs and lists, for example, which may be nested inside top-level elements of the same node type.
|
|
25
|
+
*/
|
|
26
|
+
export default () => {
|
|
27
|
+
return new Plugin<null>({
|
|
28
|
+
props: {
|
|
29
|
+
decorations: (state) => {
|
|
30
|
+
const { section } = state.schema.nodes
|
|
31
|
+
|
|
32
|
+
const decorations: Decoration[] = []
|
|
33
|
+
|
|
34
|
+
// TODO: only calculate these when something changes
|
|
35
|
+
|
|
36
|
+
state.doc.descendants((node, pos, parent) => {
|
|
37
|
+
if (
|
|
38
|
+
parent &&
|
|
39
|
+
(isSectionNodeType(parent.type) ||
|
|
40
|
+
parent.type === schema.nodes.body) &&
|
|
41
|
+
node.type !== section
|
|
42
|
+
) {
|
|
43
|
+
decorations.push(
|
|
44
|
+
Decoration.node(
|
|
45
|
+
pos,
|
|
46
|
+
pos + node.nodeSize,
|
|
47
|
+
{},
|
|
48
|
+
{
|
|
49
|
+
element: true,
|
|
50
|
+
}
|
|
51
|
+
)
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
return DecorationSet.create(state.doc, decorations)
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
})
|
|
60
|
+
}
|