@manuscripts/body-editor 3.12.67 → 3.13.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.
Files changed (289) hide show
  1. package/dist/cjs/components/toolbar/type-selector/styles.js +2 -1
  2. package/dist/cjs/versions.js +1 -1
  3. package/dist/es/components/toolbar/type-selector/styles.js +2 -1
  4. package/dist/es/versions.js +1 -1
  5. package/dist/types/components/toolbar/type-selector/styles.d.ts +2 -2
  6. package/dist/types/lib/footnotes.d.ts +4 -2
  7. package/dist/types/lib/utils.d.ts +5 -4
  8. package/dist/types/versions.d.ts +1 -1
  9. package/package.json +37 -36
  10. package/{dist/es/lib/statistics.js → src/__mocks__/styleMock.ts} +2 -14
  11. package/src/assets.ts +20 -0
  12. package/src/classes/collabProvider.ts +38 -0
  13. package/src/clipboard.ts +54 -0
  14. package/src/commands.ts +2109 -0
  15. package/src/components/ChangeHandlingForm.tsx +54 -0
  16. package/src/components/LanguageDropdown/index.tsx +343 -0
  17. package/src/components/affiliations/AffiliationForm.tsx +238 -0
  18. package/src/components/affiliations/AffiliationItem.tsx +151 -0
  19. package/src/components/affiliations/AffiliationList.tsx +71 -0
  20. package/src/components/affiliations/AffiliationsModal.tsx +676 -0
  21. package/src/components/affiliations/AffiliationsPanel.tsx +76 -0
  22. package/src/components/affiliations/CreateAffiliationModal.tsx +135 -0
  23. package/src/components/authors/AuthorDetailsForm.tsx +438 -0
  24. package/src/components/authors/AuthorList.tsx +81 -0
  25. package/src/components/authors/AuthorsModal.tsx +642 -0
  26. package/src/components/authors/AuthorsPanel.tsx +69 -0
  27. package/src/components/authors/CreateAuthorModal.tsx +172 -0
  28. package/src/components/authors/CreditDrawer.tsx +71 -0
  29. package/src/components/authors/DraggableAuthor.tsx +228 -0
  30. package/src/components/authors/useManageAffiliations.tsx +77 -0
  31. package/src/components/authors/useManageCredit.tsx +63 -0
  32. package/src/components/authors-affiliations/AuthorsAndAffiliationsModals.tsx +170 -0
  33. package/src/components/authors-affiliations/GenericPanel.tsx +164 -0
  34. package/src/components/authors-affiliations/ModalTabs.tsx +100 -0
  35. package/src/components/awards/AwardForm.tsx +338 -0
  36. package/src/components/awards/AwardModal.tsx +120 -0
  37. package/src/components/awards/DeleteAwardDiaolog.tsx +52 -0
  38. package/src/components/dialog/ConfirmationDialog.tsx +131 -0
  39. package/src/components/form/CreateModalStyles.tsx +37 -0
  40. package/src/components/form/FormFooter.tsx +54 -0
  41. package/src/components/form/FormPlaceholder.tsx +71 -0
  42. package/src/components/form/ModalFormActions.tsx +88 -0
  43. package/src/components/form/UnsavedLabel.tsx +49 -0
  44. package/src/components/hooks/use-debounce.ts +56 -0
  45. package/src/components/hooks/useAffiliationShowsErrorIndicator.ts +51 -0
  46. package/src/components/hooks/useAuthorShowsErrorIndicator.ts +73 -0
  47. package/src/components/keyboard-shortcuts-modal/FormattedShortcut.tsx +56 -0
  48. package/src/components/keyboard-shortcuts-modal/KeyboardShortcutsModal.tsx +283 -0
  49. package/src/components/keyboard-shortcuts-modal/keyboard-shortcuts.ts +304 -0
  50. package/src/components/keywords/AddKeywordInline.tsx +284 -0
  51. package/src/components/keywords/DeleteKeywordDialog.tsx +52 -0
  52. package/src/components/modal-drawer/GenericDrawer.tsx +65 -0
  53. package/src/components/modal-drawer/GenericDrawerGroup.tsx +125 -0
  54. package/src/components/outline/DraggableTree.tsx +438 -0
  55. package/src/components/outline/ManuscriptOutline.tsx +127 -0
  56. package/src/components/outline/Outline.tsx +141 -0
  57. package/src/components/references/BibliographyItemSource.ts +80 -0
  58. package/src/components/references/CitationEditor.tsx +301 -0
  59. package/src/components/references/CitationViewer.tsx +62 -0
  60. package/src/components/references/ImportBibliographyForm.tsx +232 -0
  61. package/src/components/references/ImportBibliographyModal.tsx +159 -0
  62. package/src/components/references/ReferenceForm/PersonDropDown.tsx +93 -0
  63. package/src/components/references/ReferenceForm/ReferenceForm.tsx +701 -0
  64. package/src/components/references/ReferenceForm/config.ts +133 -0
  65. package/src/components/references/ReferenceForm/styled-components.ts +156 -0
  66. package/src/components/references/ReferenceLine.tsx +43 -0
  67. package/src/components/references/ReferenceSearch.tsx +163 -0
  68. package/src/components/references/ReferenceSearchResults.tsx +113 -0
  69. package/src/components/references/ReferenceSearchResultsPlaceholder.tsx +71 -0
  70. package/src/components/references/ReferenceSearchSection.tsx +124 -0
  71. package/src/components/references/ReferencesEditor.tsx +61 -0
  72. package/src/components/references/ReferencesModal.tsx +352 -0
  73. package/src/components/references/SearchInput.tsx +98 -0
  74. package/src/components/toolbar/InsertEmbedDialog.tsx +222 -0
  75. package/src/components/toolbar/InsertTableDialog.tsx +208 -0
  76. package/src/components/toolbar/ListMenuItem.tsx +203 -0
  77. package/src/components/toolbar/helpers.ts +547 -0
  78. package/src/components/toolbar/type-selector/OptionComponent.tsx +89 -0
  79. package/src/components/toolbar/type-selector/TypeSelector.tsx +157 -0
  80. package/src/components/toolbar/type-selector/styles.ts +79 -0
  81. package/src/components/views/CrossReferenceItems.tsx +199 -0
  82. package/src/components/views/DeleteEmbedDialog.tsx +83 -0
  83. package/src/components/views/DeleteFootnoteDialog.tsx +54 -0
  84. package/src/components/views/FigureDropdown.tsx +423 -0
  85. package/src/components/views/FootnotesSelector.tsx +255 -0
  86. package/src/components/views/InsertSpecialCharacter.tsx +245 -0
  87. package/src/components/views/LinkForm.tsx +220 -0
  88. package/src/components/views/TableCellContextMenu.tsx +241 -0
  89. package/src/configs/ManuscriptsEditor.ts +140 -0
  90. package/src/configs/editor-plugins.ts +119 -0
  91. package/src/configs/editor-views.ts +139 -0
  92. package/src/icons.ts +62 -0
  93. package/src/index.ts +65 -0
  94. package/src/keys/highlight.ts +65 -0
  95. package/src/keys/index.ts +33 -0
  96. package/src/keys/keyword.ts +69 -0
  97. package/src/keys/list.ts +156 -0
  98. package/src/keys/misc.ts +112 -0
  99. package/src/keys/title.ts +221 -0
  100. package/src/lib/__tests__/__fixtures__/doc.json +388 -0
  101. package/src/lib/__tests__/__snapshots__/paste.test.ts.snap +24 -0
  102. package/src/lib/__tests__/authors.test.ts +202 -0
  103. package/src/lib/__tests__/helpers.test.ts +46 -0
  104. package/src/lib/__tests__/paste.test.ts +57 -0
  105. package/src/lib/__tests__/plugins.test.ts +176 -0
  106. package/src/lib/__tests__/url.test.ts +31 -0
  107. package/src/lib/array-reducer.ts +68 -0
  108. package/src/lib/authors-and-affiliations.ts +81 -0
  109. package/src/lib/authors.ts +67 -0
  110. package/src/lib/capabilities.ts +55 -0
  111. package/src/lib/codemirror.ts +37 -0
  112. package/src/lib/comments.ts +123 -0
  113. package/src/lib/context-menu.ts +745 -0
  114. package/src/lib/copy.ts +30 -0
  115. package/src/lib/crossref.ts +90 -0
  116. package/src/lib/dnd.ts +29 -0
  117. package/src/lib/doc.ts +167 -0
  118. package/src/lib/dompurify.ts +28 -0
  119. package/src/lib/files.ts +180 -0
  120. package/src/lib/footnotes.ts +83 -0
  121. package/src/lib/get-media-type.ts +105 -0
  122. package/src/lib/helpers.ts +199 -0
  123. package/src/lib/hierarchy.ts +117 -0
  124. package/src/lib/languages.ts +37 -0
  125. package/src/lib/lists.ts +56 -0
  126. package/src/lib/math.ts +111 -0
  127. package/src/lib/media.ts +334 -0
  128. package/src/lib/navigation-utils.ts +235 -0
  129. package/src/lib/normalize.ts +70 -0
  130. package/src/lib/paste.ts +304 -0
  131. package/src/lib/placeholder.ts +32 -0
  132. package/src/lib/platform.ts +18 -0
  133. package/src/lib/plugins.ts +22 -0
  134. package/src/lib/popper.ts +180 -0
  135. package/src/lib/position-menu.ts +184 -0
  136. package/src/lib/references.ts +94 -0
  137. package/src/lib/template.ts +29 -0
  138. package/src/lib/track-changes-utils.ts +34 -0
  139. package/{dist/types/lib/statistics.d.ts → src/lib/url.ts} +11 -8
  140. package/src/lib/use-do-with-debounce.ts +39 -0
  141. package/src/lib/utils.ts +323 -0
  142. package/src/lib/view.ts +100 -0
  143. package/src/menus.tsx +684 -0
  144. package/src/node-type-icons.tsx +83 -0
  145. package/src/plugins/__tests__/__fixtures__/deleted-footnote.json +140 -0
  146. package/src/plugins/__tests__/__fixtures__/inserted-footnote.json +153 -0
  147. package/src/plugins/__tests__/footnotes.test.ts +67 -0
  148. package/src/plugins/accessibility_element.ts +219 -0
  149. package/src/plugins/add-subtitle.ts +102 -0
  150. package/src/plugins/affiliations.ts +136 -0
  151. package/src/plugins/alt-titles.ts +219 -0
  152. package/src/plugins/bibliography.ts +235 -0
  153. package/src/plugins/comments.ts +328 -0
  154. package/src/plugins/cross-references.ts +70 -0
  155. package/src/plugins/detect-inconsistency/detect-inconsistency-utils.ts +102 -0
  156. package/src/plugins/detect-inconsistency/index.ts +55 -0
  157. package/src/plugins/detect-inconsistency/validators.ts +283 -0
  158. package/src/plugins/doi.ts +66 -0
  159. package/src/plugins/editor-props.ts +39 -0
  160. package/src/plugins/elements.ts +60 -0
  161. package/src/plugins/footnotes.ts +298 -0
  162. package/src/plugins/link.ts +53 -0
  163. package/src/plugins/lock-body.ts +136 -0
  164. package/src/plugins/move-node.ts +55 -0
  165. package/src/plugins/objects.ts +125 -0
  166. package/src/plugins/paragraphs.ts +90 -0
  167. package/src/plugins/persist.ts +64 -0
  168. package/src/plugins/persistent-cursor.ts +66 -0
  169. package/src/plugins/placeholder.ts +219 -0
  170. package/src/plugins/prevent-empty.ts +50 -0
  171. package/src/plugins/search-replace/index.ts +157 -0
  172. package/src/plugins/search-replace/lib.ts +95 -0
  173. package/src/plugins/section_category.ts +212 -0
  174. package/src/plugins/section_title/autocompletion.ts +87 -0
  175. package/src/plugins/section_title/index.ts +105 -0
  176. package/src/plugins/selected-suggestion.ts +243 -0
  177. package/src/plugins/tables-cursor-fix.ts +143 -0
  178. package/src/plugins/translations.ts +263 -0
  179. package/src/rules.ts +60 -0
  180. package/src/selection.ts +112 -0
  181. package/src/testing/default-capabilities.ts +48 -0
  182. package/src/testing/default-editor-data.ts +73 -0
  183. package/src/testing/empty-editor-doc.json +62 -0
  184. package/src/testing/polyfill-dom.ts +43 -0
  185. package/src/testing/section-categories.json +161 -0
  186. package/src/testing/setup-editor.ts +55 -0
  187. package/src/tests.ts +42 -0
  188. package/src/toolbar.tsx +259 -0
  189. package/src/types/@citation-js/core.d.ts +16 -0
  190. package/src/types/@citation-js/index.d.ts +16 -0
  191. package/src/types/@citation-js/plugin-bibtex.d.ts +16 -0
  192. package/src/types/@citation-js/plugin-csl.d.ts +16 -0
  193. package/src/types/@citation-js/plugin-doi.d.ts +16 -0
  194. package/src/types/@citation-js/plugin-enw.d.ts +16 -0
  195. package/src/types/@citation-js/plugin-pubmed.d.ts +16 -0
  196. package/src/types/@citation-js/plugin-ris.d.ts +16 -0
  197. package/src/types/citeproc.d.ts +124 -0
  198. package/src/types/css.d.ts +16 -0
  199. package/src/types/json.d.ts +17 -0
  200. package/src/types/prosemirror-dev-tools.d.ts +16 -0
  201. package/src/types/prosemirror-dropcursor.d.ts +16 -0
  202. package/src/types/styled-components.d.ts +23 -0
  203. package/src/types.ts +49 -0
  204. package/src/useEditor.ts +244 -0
  205. package/src/versions.ts +3 -0
  206. package/src/views/ReactSubView.tsx +145 -0
  207. package/src/views/abstracts.ts +46 -0
  208. package/src/views/accessibility_element.ts +86 -0
  209. package/src/views/affiliations.ts +254 -0
  210. package/src/views/alt_title.ts +85 -0
  211. package/src/views/alt_titles_section.ts +97 -0
  212. package/src/views/attachment.ts +160 -0
  213. package/src/views/attachments.ts +72 -0
  214. package/src/views/author_notes.ts +96 -0
  215. package/src/views/award.ts +194 -0
  216. package/src/views/awards.ts +59 -0
  217. package/src/views/base_node_view.ts +85 -0
  218. package/src/views/bibliography_element.ts +313 -0
  219. package/src/views/block_view.ts +100 -0
  220. package/src/views/blockquote_element.ts +26 -0
  221. package/src/views/blockquote_element_editable.ts +24 -0
  222. package/src/views/box_element.ts +33 -0
  223. package/src/views/caption.ts +37 -0
  224. package/src/views/caption_title.ts +33 -0
  225. package/src/views/citation.ts +67 -0
  226. package/src/views/citation_editable.ts +312 -0
  227. package/src/views/contributors.ts +341 -0
  228. package/src/views/creators.ts +82 -0
  229. package/src/views/cross_reference.ts +74 -0
  230. package/src/views/cross_reference_editable.ts +113 -0
  231. package/src/views/editable_block.ts +141 -0
  232. package/src/views/embed.ts +345 -0
  233. package/src/views/empty.ts +26 -0
  234. package/src/views/equation.ts +47 -0
  235. package/src/views/equation_editable.ts +84 -0
  236. package/src/views/equation_element.ts +29 -0
  237. package/src/views/equation_element_editable.ts +21 -0
  238. package/src/views/figure.ts +84 -0
  239. package/src/views/figure_editable.ts +361 -0
  240. package/src/views/figure_element.ts +197 -0
  241. package/src/views/figure_element_editable.ts +21 -0
  242. package/src/views/footnote.ts +236 -0
  243. package/src/views/footnotes_element.ts +54 -0
  244. package/src/views/general_table_footnote.ts +140 -0
  245. package/src/views/hero_image.ts +76 -0
  246. package/src/views/hero_image_editable.ts +21 -0
  247. package/src/views/image_element.ts +373 -0
  248. package/src/views/image_element_editable.ts +21 -0
  249. package/src/views/inline_equation.ts +47 -0
  250. package/src/views/inline_equation_editable.ts +70 -0
  251. package/src/views/inline_footnote.ts +264 -0
  252. package/src/views/inline_footnote_editable.ts +20 -0
  253. package/src/views/keyword.ts +127 -0
  254. package/src/views/keyword_group.ts +109 -0
  255. package/src/views/link.ts +27 -0
  256. package/src/views/link_editable.ts +169 -0
  257. package/src/views/list.ts +46 -0
  258. package/src/views/list_item.ts +26 -0
  259. package/src/views/paragraph.ts +26 -0
  260. package/src/views/paragraph_editable.ts +21 -0
  261. package/src/views/placeholder.ts +35 -0
  262. package/src/views/placeholder_element.ts +38 -0
  263. package/src/views/placeholder_element_editable.ts +21 -0
  264. package/src/views/pullquote_element.ts +106 -0
  265. package/src/views/pullquote_element_editable.ts +24 -0
  266. package/src/views/quote_image_editable.ts +84 -0
  267. package/src/views/section.ts +64 -0
  268. package/src/views/section_label.ts +20 -0
  269. package/src/views/section_title.ts +87 -0
  270. package/src/views/section_title_editable.ts +21 -0
  271. package/src/views/subtitle.ts +42 -0
  272. package/src/views/subtitle_editable.ts +20 -0
  273. package/src/views/subtitles.ts +34 -0
  274. package/src/views/subtitles_editable.ts +21 -0
  275. package/src/views/supplement.ts +236 -0
  276. package/src/views/supplement_editable.ts +20 -0
  277. package/src/views/supplements.ts +65 -0
  278. package/src/views/supplements_editable.ts +21 -0
  279. package/src/views/table_cell.ts +150 -0
  280. package/src/views/table_element.ts +33 -0
  281. package/src/views/table_element_editable.ts +21 -0
  282. package/src/views/table_element_footer.ts +41 -0
  283. package/src/views/title.ts +46 -0
  284. package/src/views/title_editable.ts +20 -0
  285. package/src/views/trans_graphical_abstract.ts +55 -0
  286. package/src/views/trans_graphical_abstract_editable.ts +21 -0
  287. package/src/views/translated_abstract.ts +53 -0
  288. package/src/views/translated_abstract_editable.ts +21 -0
  289. 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
+ }