@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.
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,323 @@
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 {
18
+ BibliographyItemAttrs,
19
+ BibliographyItemType,
20
+ isElementNodeType,
21
+ isSectionNodeType,
22
+ ManuscriptEditorState,
23
+ ManuscriptNode,
24
+ ManuscriptNodeType,
25
+ schema,
26
+ } from '@manuscripts/transform'
27
+ import {
28
+ Fragment,
29
+ Node as ProseMirrorNode,
30
+ NodeType,
31
+ ResolvedPos,
32
+ } from 'prosemirror-model'
33
+ import { EditorState, Selection } from 'prosemirror-state'
34
+ import {
35
+ ContentNodeWithPos,
36
+ findChildrenByType,
37
+ findParentNode,
38
+ findParentNodeOfTypeClosestToPos,
39
+ } from 'prosemirror-utils'
40
+
41
+ import { fieldConfigMap } from '../components/references/ReferenceForm/config'
42
+ import { arrowDown } from '../icons'
43
+ import { handleEnterKey } from './navigation-utils'
44
+ import { getEditorProps } from '../plugins/editor-props'
45
+
46
+ export function* iterateChildren(
47
+ node: ManuscriptNode,
48
+ recurse = false
49
+ ): Iterable<ManuscriptNode> {
50
+ for (let i = 0; i < node.childCount; i++) {
51
+ const child = node.child(i)
52
+ yield child
53
+
54
+ if (recurse) {
55
+ for (const grandchild of iterateChildren(child, true)) {
56
+ yield grandchild
57
+ }
58
+ }
59
+ }
60
+ }
61
+
62
+ export const getMatchingChild = (
63
+ parent: ManuscriptNode,
64
+ matcher: (node: ManuscriptNode) => boolean,
65
+ deep = false
66
+ ): ManuscriptNode | undefined => {
67
+ for (const node of iterateChildren(parent, deep)) {
68
+ if (matcher(node)) {
69
+ return node
70
+ }
71
+ }
72
+ }
73
+
74
+ export const getMatchingDescendant = (
75
+ parent: ManuscriptNode,
76
+ matcher: (node: ManuscriptNode) => boolean
77
+ ): ManuscriptNode | undefined => {
78
+ for (const node of iterateChildren(parent, true)) {
79
+ if (matcher(node)) {
80
+ return node
81
+ }
82
+ }
83
+ }
84
+
85
+ export const getChildOfType = (
86
+ parent: ManuscriptNode,
87
+ nodeType: ManuscriptNodeType,
88
+ deep = false
89
+ ): boolean =>
90
+ !!getMatchingChild(parent, (node) => node.type.name === nodeType.name, deep)
91
+
92
+ export const findParentNodeWithId: (selection: Selection) => ContentNodeWithPos | undefined = findParentNode((node) => 'id' in node.attrs)
93
+
94
+ export const findParentNodeWithIdValue: (selection: Selection) => ContentNodeWithPos | undefined = findParentNode((node) => node.attrs.id)
95
+
96
+ export const findParentSection: (selection: Selection) => ContentNodeWithPos | undefined = findParentNode((node) =>
97
+ isSectionNodeType(node.type)
98
+ )
99
+
100
+ export const findParentElement = (selection: Selection, validIds?: string[]): ContentNodeWithPos | undefined =>
101
+ findParentNode((node) => {
102
+ // if validIds was passed and this element is not in it, then keep looking
103
+ if (validIds && !validIds.includes(node.attrs.id)) {
104
+ return false
105
+ }
106
+ return isElementNodeType(node.type) && node.attrs.id
107
+ })(selection)
108
+
109
+ export const isChildOfNodeTypes = (
110
+ doc: ManuscriptNode,
111
+ pos: number,
112
+ parentNodeTypes: NodeType[]
113
+ ) => {
114
+ if (pos > doc.content.size) {
115
+ return false
116
+ }
117
+ const resolvedPos = doc.resolve(pos)
118
+ // Iterate through the parent nodes
119
+ for (let depth = resolvedPos.depth; depth >= 0; depth--) {
120
+ if (parentNodeTypes.includes(resolvedPos.node(depth).type)) {
121
+ return true
122
+ }
123
+ }
124
+
125
+ return false
126
+ }
127
+
128
+ export const isSelectionInNode = (
129
+ state: EditorState,
130
+ targetNode: ProseMirrorNode
131
+ ) => {
132
+ const resolvedFrom = state.doc.resolve(state.selection.from)
133
+
134
+ for (let depth = resolvedFrom.depth; depth >= 0; depth--) {
135
+ const node = resolvedFrom.node(depth)
136
+ if (node === targetNode) {
137
+ return true
138
+ }
139
+ }
140
+ return false
141
+ }
142
+
143
+ export const isSelectionInBody = (state: EditorState): boolean => {
144
+ return isSelectionInNodeByType(state, 'body')
145
+ }
146
+
147
+ const isSelectionInNodeByType = (
148
+ state: EditorState,
149
+ nodeType: string
150
+ ): boolean => {
151
+ const { $from } = state.selection
152
+
153
+ for (let depth = $from.depth; depth >= 0; depth--) {
154
+ if ($from.node(depth).type.name === nodeType) {
155
+ return true
156
+ }
157
+ }
158
+
159
+ return false
160
+ }
161
+
162
+ export const createHeader = (typeName: string, text: string) => {
163
+ const header = document.createElement('h1')
164
+ header.classList.add(`title-${typeName}`, 'authors-info-header')
165
+ header.textContent = text
166
+ return header
167
+ }
168
+
169
+ export const isNotNull = <T>(a: T | null): a is T => a !== null
170
+
171
+ export const hasParent = (
172
+ $pos: ResolvedPos,
173
+ type: ManuscriptNodeType | ManuscriptNodeType[]
174
+ ) => {
175
+ if (Array.isArray(type)) {
176
+ return type.some(
177
+ (nodeType) => !!findParentNodeOfTypeClosestToPos($pos, nodeType)
178
+ )
179
+ }
180
+ return !!findParentNodeOfTypeClosestToPos($pos, type)
181
+ }
182
+
183
+ // It will check if the field should be rendered based on selected item type
184
+ // and field name
185
+ export const shouldRenderField = (
186
+ field: string,
187
+ type: BibliographyItemType
188
+ ): boolean => {
189
+ return fieldConfigMap[type]?.has(field) ?? false
190
+ }
191
+
192
+ // It will clean unnecessary fields from the item
193
+ // id and type will be kept
194
+ export const cleanItemValues = (item: BibliographyItemAttrs) => {
195
+ const type = item.type as BibliographyItemType
196
+ const cleanedItem: BibliographyItemAttrs = { ...item }
197
+
198
+ for (const key of Object.keys(item) as (keyof BibliographyItemAttrs)[]) {
199
+ if (!shouldRenderField(key, type)) {
200
+ switch (key) {
201
+ case 'id':
202
+ case 'type':
203
+ break
204
+ case 'author':
205
+ case 'editor':
206
+ case 'issued':
207
+ case 'accessed':
208
+ case 'event-date':
209
+ cleanedItem[key] = undefined
210
+ break
211
+ default:
212
+ cleanedItem[key] = ''
213
+ }
214
+ }
215
+ }
216
+ return cleanedItem
217
+ }
218
+
219
+ export const isBodyLocked = (state: EditorState) => {
220
+ const props = getEditorProps(state)
221
+ return (
222
+ !!findChildrenByType(state.doc, schema.nodes.attachment).length &&
223
+ props.lockBody
224
+ )
225
+ }
226
+
227
+ // It checks if the selection is inside a body node and if the body is locked
228
+ // the body is locked if feature lockBody is set true and there is an attachment node in document
229
+ export const isEditAllowed = (state: EditorState) => {
230
+ return !(isBodyLocked(state) && isSelectionInBody(state))
231
+ }
232
+
233
+ export const createToggleButton = (
234
+ listener: (event: MouseEvent | KeyboardEvent) => void,
235
+ what: string
236
+ ) => {
237
+ const altTitlesButton = document.createElement('button')
238
+ altTitlesButton.classList.add('toggle-button-open', 'button-reset')
239
+ altTitlesButton.setAttribute('aria-label', `Expand ${what}`)
240
+ altTitlesButton.innerHTML = arrowDown
241
+ const activate = (e: MouseEvent | KeyboardEvent) => {
242
+ e.preventDefault()
243
+ listener(e)
244
+ }
245
+ altTitlesButton.addEventListener('click', (e) => {
246
+ activate(e)
247
+ })
248
+ altTitlesButton.addEventListener('keydown', handleEnterKey(activate))
249
+ return altTitlesButton
250
+ }
251
+
252
+ export const getInsertPos = (
253
+ type: ManuscriptNodeType,
254
+ parent: ManuscriptNode,
255
+ pos: number
256
+ ) => {
257
+ let insertPos = pos + parent.nodeSize - 1
258
+
259
+ parent.forEach((child, offset, index) => {
260
+ if (parent.canReplaceWith(index, index, type)) {
261
+ insertPos = pos + offset
262
+ }
263
+ })
264
+
265
+ return insertPos
266
+ }
267
+
268
+ // this will look just at parent node children
269
+ export const findInsertionPosition = (
270
+ type: ManuscriptNodeType,
271
+ doc: ManuscriptNode
272
+ ) => {
273
+ let insertPos = 0
274
+
275
+ doc.forEach((child, offset, index) => {
276
+ if (doc.canReplaceWith(index, index, type)) {
277
+ insertPos = offset
278
+ }
279
+ })
280
+ // this will test if we can insert target type as last child in parent node
281
+ if (
282
+ insertPos === 0 &&
283
+ doc.canReplaceWith(doc.childCount, doc.childCount, type)
284
+ ) {
285
+ insertPos = doc.content.size
286
+ }
287
+ return insertPos
288
+ }
289
+
290
+ export const filterBlockNodes = (
291
+ fragment: Fragment,
292
+ predicate?: (node: ProseMirrorNode) => boolean
293
+ ) => {
294
+ const updatedNodes: ProseMirrorNode[] = []
295
+
296
+ fragment.forEach((child) => {
297
+ if (!child.isBlock) {
298
+ updatedNodes.push(child)
299
+ return
300
+ }
301
+
302
+ const newContent = child.content.size
303
+ ? filterBlockNodes(child.content, predicate)
304
+ : child.content
305
+ if (!predicate || predicate(child)) {
306
+ updatedNodes.push(child.type.create(child.attrs, newContent, child.marks))
307
+ }
308
+ })
309
+
310
+ return Fragment.fromArray(updatedNodes)
311
+ }
312
+ export const getLastTitleNode = (state: ManuscriptEditorState) => {
313
+ const altTitleNode = findChildrenByType(
314
+ state.doc,
315
+ state.schema.nodes.alt_titles
316
+ )[0]
317
+ if (altTitleNode) {
318
+ return altTitleNode
319
+ }
320
+
321
+ const titleNode = findChildrenByType(state.doc, state.schema.nodes.title)[0]
322
+ return titleNode
323
+ }
@@ -0,0 +1,100 @@
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
+ ManuscriptEditorView,
19
+ ManuscriptNodeType,
20
+ schema,
21
+ } from '@manuscripts/transform'
22
+ import { Attrs } from 'prosemirror-model'
23
+ import { NodeSelection } from 'prosemirror-state'
24
+ import * as utils from 'prosemirror-utils'
25
+
26
+ import { isHidden } from './track-changes-utils'
27
+ import { sanitizeAttrsChange } from '@manuscripts/track-changes-plugin'
28
+
29
+ const metaNodeTypes = [
30
+ schema.nodes.bibliography_item,
31
+ schema.nodes.affiliation,
32
+ schema.nodes.contributor,
33
+ ]
34
+
35
+ const updateMetaNode = 'track-changes-update-meta-node'
36
+
37
+ export const findChildByID = (
38
+ view: ManuscriptEditorView,
39
+ id: string
40
+ ): utils.NodeWithPos | undefined => {
41
+ const doc = view.state.doc
42
+ const children = utils.findChildren(doc, (n) => n.attrs.id === id)
43
+ return children.length ? children[0] : undefined
44
+ }
45
+
46
+ export const findChildByType = (
47
+ view: ManuscriptEditorView,
48
+ type: ManuscriptNodeType
49
+ ): utils.NodeWithPos | undefined => {
50
+ const children = findChildrenByType(view, type)
51
+ return children.length ? children[0] : undefined
52
+ }
53
+
54
+ export const findChildrenByType = (
55
+ view: ManuscriptEditorView,
56
+ type: ManuscriptNodeType
57
+ ): utils.NodeWithPos[] => {
58
+ const doc = view.state.doc
59
+ return utils.findChildrenByType(doc, type).filter((n) => !isHidden(n.node))
60
+ }
61
+
62
+ export const findChildrenAttrsByType = <T extends Attrs>(
63
+ view: ManuscriptEditorView,
64
+ type: ManuscriptNodeType
65
+ ): T[] => {
66
+ return findChildrenByType(view, type).map((n) => n.node.attrs) as T[]
67
+ }
68
+
69
+ export const updateNodeAttrs = (
70
+ view: ManuscriptEditorView,
71
+ type: ManuscriptNodeType,
72
+ attrs: Attrs
73
+ ) => {
74
+ const child = findChildByID(view, attrs.id)
75
+ if (child) {
76
+ const copy = sanitizeAttrsChange(attrs, child.node.attrs)
77
+ // @ts-ignore attrs readonly - deleting from a copy
78
+ delete copy.dataTracked
79
+ const pos = child.pos
80
+ const tr = view.state.tr
81
+ tr.setNodeMarkup(pos, undefined, copy).setSelection(
82
+ NodeSelection.create(tr.doc, pos)
83
+ )
84
+ if (metaNodeTypes.includes(type)) {
85
+ tr.setMeta(updateMetaNode, true)
86
+ }
87
+ view.dispatch(tr)
88
+ return true
89
+ }
90
+ return false
91
+ }
92
+
93
+ export const deleteNode = (view: ManuscriptEditorView, id: string) => {
94
+ const child = findChildByID(view, id)
95
+ if (child) {
96
+ const pos = child.pos
97
+ const node = child.node
98
+ view.dispatch(view.state.tr.delete(pos, pos + node.nodeSize))
99
+ }
100
+ }