@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,304 @@
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
+ generateNodeID,
19
+ isElementNodeType,
20
+ ManuscriptEditorView,
21
+ ManuscriptSlice,
22
+ schema,
23
+ } from '@manuscripts/transform'
24
+ import { Fragment, Slice } from 'prosemirror-model'
25
+ import { NodeSelection, TextSelection } from 'prosemirror-state'
26
+ import { findParentNode } from 'prosemirror-utils'
27
+
28
+ import { allowedHref } from './url'
29
+ import { getDeepestSubsectionPosition } from '../components/toolbar/helpers'
30
+
31
+ const removeFirstParagraphIfEmpty = (slice: ManuscriptSlice) => {
32
+ const firstChild = slice.content.firstChild
33
+
34
+ if (
35
+ firstChild &&
36
+ firstChild.type === firstChild.type.schema.nodes.paragraph &&
37
+ firstChild.textContent === ''
38
+ ) {
39
+ // @ts-ignore
40
+ slice.content = slice.content.cut(firstChild.nodeSize)
41
+ }
42
+ }
43
+
44
+ const updateInlineFootnoteToNewRids = (
45
+ slice: Slice,
46
+ footnotesIdsMap: Map<string, string>
47
+ ) => {
48
+ slice.content.descendants((node) => {
49
+ if (node.type === schema.nodes.inline_footnote) {
50
+ // @ts-ignore
51
+ node.attrs.rids = node.attrs.rids.map((rid) => footnotesIdsMap.get(rid))
52
+ }
53
+ })
54
+ }
55
+
56
+ // remove `id` from pasted content
57
+ const removeIDs = (slice: ManuscriptSlice) => {
58
+ const footnotesIdsMap = new Map()
59
+ slice.content.descendants((node) => {
60
+ let id = null
61
+ if (node.type === schema.nodes.footnote) {
62
+ // will keep id for footnote to not lose connection with inline_footnote
63
+ const newId = generateNodeID(node.type)
64
+ footnotesIdsMap.set(node.attrs.id, newId)
65
+ id = newId
66
+ }
67
+
68
+ if (node.attrs.id) {
69
+ // @ts-ignore
70
+ node.attrs.id = id
71
+ }
72
+ })
73
+
74
+ updateInlineFootnoteToNewRids(slice, footnotesIdsMap)
75
+ }
76
+
77
+ const wrapInSection = (slice: ManuscriptSlice) => {
78
+ if (slice.content.firstChild?.type === schema.nodes.section_title) {
79
+ // @ts-ignore
80
+ slice.content = Fragment.from(
81
+ schema.nodes.section.create({}, slice.content)
82
+ )
83
+ }
84
+ }
85
+
86
+ const closeAtomSlice = (slice: ManuscriptSlice) => {
87
+ // close slice to prevent drop of node https://github.com/ProseMirror/prosemirror-transform/blob/137ff74738bd1b50d49416cd6cfdbbf52cb059ef/src/replace.ts#L231
88
+ if (slice.content.firstChild?.isAtom) {
89
+ // @ts-ignore
90
+ slice.openStart = 0
91
+ // @ts-ignore
92
+ slice.openEnd = 0
93
+ }
94
+ }
95
+
96
+ export const transformPasted = (slice: ManuscriptSlice): ManuscriptSlice => {
97
+ wrapInSection(slice)
98
+
99
+ removeFirstParagraphIfEmpty(slice)
100
+
101
+ removeIDs(slice)
102
+
103
+ closeAtomSlice(slice)
104
+
105
+ return slice
106
+ }
107
+
108
+ export const transformPastedHTML = (html: string) => {
109
+ const doc = new DOMParser().parseFromString(html, 'text/html')
110
+ wrapHeadingWithSection(doc)
111
+ wrapTableWithFigure(doc)
112
+ console.log(doc.body.innerHTML)
113
+ return doc.body.innerHTML
114
+ }
115
+
116
+ const wrapHeadingWithSection = (doc: Document) => {
117
+ if (!doc.body.querySelector('h1, h2, h3, h4, h5, h6')) {
118
+ return
119
+ }
120
+
121
+ const getHeadingLevel = (element: Element) => {
122
+ const level = element.tagName.match(/^H(\d)$/)
123
+ return level ? parseInt(level[1]) : -1
124
+ }
125
+
126
+ const root = doc.createElement('div')
127
+ const google_doc_document = doc.body.querySelector(
128
+ 'b[id^="docs-internal-guid"]'
129
+ )
130
+ const elements = Array.from(
131
+ google_doc_document?.children || doc.body.children
132
+ )
133
+ const stack = [{ level: 0, element: root as Element }]
134
+
135
+ for (const element of elements) {
136
+ const headingLevel = getHeadingLevel(element)
137
+ if (headingLevel > 0) {
138
+ while (
139
+ stack.length > 1 &&
140
+ stack[stack.length - 1].level >= headingLevel
141
+ ) {
142
+ stack.pop()
143
+ }
144
+ const section = doc.createElement('section')
145
+ section.appendChild(element.cloneNode(true))
146
+
147
+ stack[stack.length - 1].element.appendChild(section)
148
+ stack.push({ level: headingLevel, element: section })
149
+ } else {
150
+ stack[stack.length - 1].element.appendChild(element.cloneNode(true))
151
+ }
152
+ }
153
+
154
+ doc.body.innerHTML = root.innerHTML
155
+ }
156
+
157
+ const wrapTableWithFigure = (doc: Document) => {
158
+ // add figure which is table_element node in DOM
159
+ doc.body.querySelectorAll('table').forEach((table) => {
160
+ if (table.parentElement?.tagName !== 'FIGURE') {
161
+ const tableElement = doc.createElement('figure')
162
+ tableElement.className = 'table'
163
+ table.removeAttribute('data-pm-slice')
164
+ table.parentElement?.insertBefore(tableElement, table)
165
+ tableElement.append(table)
166
+ }
167
+ })
168
+ }
169
+
170
+ export const handlePaste = (
171
+ view: ManuscriptEditorView,
172
+ event: ClipboardEvent,
173
+ slice: Slice
174
+ ) => {
175
+ if (event.type !== 'paste') {
176
+ return false
177
+ }
178
+
179
+ const {
180
+ state: { tr, selection },
181
+ dispatch,
182
+ } = view
183
+
184
+ tr.setMeta('uiEvent', 'paste')
185
+ tr.setMeta('paste', true)
186
+
187
+ const clipboardData = event.clipboardData
188
+
189
+ const text = clipboardData?.getData('text/plain')
190
+ if (text && allowedHref(text)) {
191
+ const link = schema.nodes.link.create({ href: text }, schema.text(text))
192
+ dispatch(tr.insert(selection.from, Fragment.from(link)).scrollIntoView())
193
+ return true
194
+ }
195
+
196
+ // TODO:: all the cases below should be removed when figuring out issue of open slice sides from track-changes plugin
197
+
198
+ const parent = findParentNode(
199
+ (node) =>
200
+ node.type === schema.nodes.section || node.type === schema.nodes.body
201
+ )(selection)
202
+ if (
203
+ (slice.content.firstChild?.type === schema.nodes.section ||
204
+ slice.content.lastChild?.type === schema.nodes.section) &&
205
+ parent
206
+ ) {
207
+ const $pos = tr.doc.resolve(
208
+ getDeepestSubsectionPosition(parent.node, parent.pos)
209
+ )
210
+ const insertPos = $pos.end()
211
+ tr.insert(insertPos, slice.content)
212
+ dispatch(
213
+ tr
214
+ .setSelection(
215
+ //@ts-ignore
216
+ NodeSelection.create(tr.doc, tr.steps[0]['to'] || insertPos)
217
+ )
218
+ .scrollIntoView()
219
+ )
220
+ return true
221
+ }
222
+ if (
223
+ (slice.content.firstChild?.type === schema.nodes.body ||
224
+ slice.content.lastChild?.type === schema.nodes.backmatter) &&
225
+ parent
226
+ ) {
227
+ const $pos = tr.doc.resolve(
228
+ getDeepestSubsectionPosition(parent.node, parent.pos)
229
+ )
230
+ const insertPos = $pos.end()
231
+ tr.insert(
232
+ insertPos,
233
+ slice.content.firstChild!.content.append(slice.content.lastChild!.content)
234
+ )
235
+ dispatch(
236
+ tr
237
+ .setSelection(
238
+ NodeSelection.create(tr.doc, tr.doc.resolve(insertPos).after())
239
+ )
240
+ .scrollIntoView()
241
+ )
242
+ return true
243
+ }
244
+
245
+ if (
246
+ selection instanceof TextSelection &&
247
+ isElement(slice) &&
248
+ slice.openStart !== 1 &&
249
+ slice.openEnd !== 1 &&
250
+ selection.$anchor.parentOffset > 0 &&
251
+ selection.$head.parentOffset > 0 &&
252
+ selection.$from.node().type === schema.nodes.paragraph
253
+ ) {
254
+ const { $from, $to } = selection
255
+ const side = (
256
+ !$from.parentOffset && $to.index() < $to.parent.childCount ? $from : $to
257
+ ).pos
258
+ // will use closed sides for elements(list) as in prosemirror-transform Fitter will
259
+ // join content in the element with side we need to insert depending on the schema,
260
+ // so for list first list item will be joined and that will make it hard for us
261
+ // to tracked and required changes in the schema
262
+ tr.replace(side, side, new Slice(slice.content, 0, 0))
263
+ dispatch(
264
+ tr.setSelection(TextSelection.create(tr.doc, side + 1)).scrollIntoView()
265
+ )
266
+ return true
267
+ }
268
+
269
+ if (
270
+ selection instanceof TextSelection &&
271
+ selection.$from.depth === slice.openStart &&
272
+ selection.$anchor.parentOffset === 0 &&
273
+ selection.$head.parentOffset === 0 &&
274
+ selection.$from.node().type === schema.nodes.paragraph
275
+ ) {
276
+ const { $from, $to } = selection
277
+ const side =
278
+ (!$from.parentOffset && $to.index() < $to.parent.childCount ? $from : $to)
279
+ .pos - 1
280
+ if (isElement(slice) && slice.openStart !== 1 && slice.openEnd !== 1) {
281
+ tr.replace(side, side, new Slice(slice.content, 0, 0))
282
+ } else {
283
+ tr.replace(side, side, slice)
284
+ }
285
+ dispatch(
286
+ tr.setSelection(TextSelection.create(tr.doc, side + 1)).scrollIntoView()
287
+ )
288
+ return true
289
+ }
290
+
291
+ return false
292
+ }
293
+
294
+ const isElement = (slice: Slice) => {
295
+ const { firstChild, lastChild } = slice.content
296
+ return (
297
+ (firstChild &&
298
+ isElementNodeType(firstChild.type) &&
299
+ firstChild.type !== schema.nodes.paragraph) ||
300
+ (lastChild &&
301
+ isElementNodeType(lastChild.type) &&
302
+ lastChild.type !== schema.nodes.paragraph)
303
+ )
304
+ }
@@ -0,0 +1,32 @@
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
+ export function createPlaceholderContent(label = 'a component') {
18
+ const el = document.createElement('div')
19
+ el.innerHTML = `
20
+ <div class="placeholder-item-icon">
21
+ <svg width="24" height="24">
22
+ <path d="M12 1.5c5.799 0 10.5 4.701 10.5 10.5S17.799 22.5 12 22.5 1.5 17.799 1.5 12 6.2 1.5 12 1.5zM12 0c6.627 0 12 5.373 12 12s-5.373 12-12 12S0 18.627 0 12 5.372 0 12 0zm0 18.2a1 1 0 1 0 0-2 1 1 0 0 0 0 2zM12.02 6a.9.9 0 0 0-.9.9v7.2a.9.9 0 1 0 1.8 0V6.9a.9.9 0 0 0-.9-.9z" fill="#DC5030" fill-rule="evenodd"/>
23
+ </svg>
24
+ </div>
25
+ <div class="placeholder-item-message">
26
+ <div class="message-content">
27
+ A problem occured while loading ${label}. If the problem persists please contact support.</div>
28
+ </div>
29
+ </div>
30
+ `
31
+ return el
32
+ }
@@ -0,0 +1,18 @@
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
+ export const isMac =
18
+ typeof navigator !== 'undefined' && /Mac/.test(navigator.userAgent)
@@ -0,0 +1,22 @@
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 { Transaction } from 'prosemirror-state'
17
+
18
+ export const INIT_META = 'INIT'
19
+
20
+ export const isInit = (tr: Transaction) => {
21
+ return tr.getMeta(INIT_META)
22
+ }
@@ -0,0 +1,180 @@
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
+ createPopper,
19
+ Instance,
20
+ Placement,
21
+ StrictModifiers,
22
+ } from '@popperjs/core'
23
+ import { createKeyboardInteraction } from './navigation-utils'
24
+
25
+ export class PopperManager {
26
+ private activePopper?: Instance
27
+ private handleDocumentClick?: (e: Event) => void
28
+ private triggerElement?: Element
29
+ private container?: HTMLElement
30
+
31
+ public show(
32
+ target: Element,
33
+ contents: HTMLElement,
34
+ placement: Placement = 'bottom',
35
+ showArrow = true,
36
+ modifiers: Array<Partial<StrictModifiers>> = [],
37
+ autoFocus = true
38
+ ) {
39
+ // destroy any existing popper first
40
+ // checking activePopper is in destroy() method
41
+ this.destroy()
42
+
43
+ // Store the trigger element to return focus later
44
+ this.triggerElement = target
45
+
46
+ window.requestAnimationFrame(() => {
47
+ const container = document.createElement('div')
48
+ container.className = 'popper'
49
+ this.container = container
50
+
51
+ container.addEventListener('click', (e) => {
52
+ e.stopPropagation()
53
+ })
54
+
55
+ const closeAndRestoreFocus = (e: KeyboardEvent) => {
56
+ e.preventDefault()
57
+ e.stopPropagation()
58
+ this.destroy()
59
+ if (this.triggerElement instanceof HTMLElement) {
60
+ this.triggerElement.focus()
61
+ }
62
+ }
63
+ const isMenu =
64
+ contents.classList.contains('context-menu') ||
65
+ contents.classList.contains('menu')
66
+ createKeyboardInteraction({
67
+ container,
68
+ additionalKeys: {
69
+ Escape: closeAndRestoreFocus,
70
+ Tab: isMenu ? closeAndRestoreFocus : undefined,
71
+ },
72
+ })
73
+
74
+ if (showArrow) {
75
+ const arrow = document.createElement('div')
76
+ arrow.className = 'popper-arrow'
77
+ container.appendChild(arrow)
78
+ modifiers.push({
79
+ name: 'arrow',
80
+ options: {
81
+ element: arrow,
82
+ },
83
+ })
84
+ } else {
85
+ modifiers.push({
86
+ name: 'arrow',
87
+ options: {
88
+ element: null,
89
+ },
90
+ })
91
+ }
92
+
93
+ container.appendChild(contents)
94
+ document.body.appendChild(container)
95
+
96
+ this.activePopper = createPopper(target, container, {
97
+ placement,
98
+ modifiers,
99
+ onFirstUpdate: () => {
100
+ this.addContainerClass(target)
101
+ this.focusInput(container, autoFocus)
102
+ },
103
+ })
104
+
105
+ this.handleDocumentClick = (e) => {
106
+ const node = e.target as Node
107
+ if (!container.contains(node) && !target.contains(node)) {
108
+ this.destroy()
109
+ }
110
+ }
111
+ // add EventListener for checking if click was done outside of editor
112
+ // only if popper has class 'context-menu'
113
+ if (
114
+ contents.classList.contains('context-menu') ||
115
+ contents.classList.contains('language') ||
116
+ contents.classList.contains('section-category')
117
+ ) {
118
+ window.addEventListener('click', this.handleDocumentClick)
119
+ }
120
+ })
121
+ }
122
+
123
+ public destroy() {
124
+ if (this.activePopper) {
125
+ this.removeContainerClass(
126
+ this.activePopper.state.elements.reference as Element
127
+ )
128
+ this.activePopper.destroy()
129
+ this.activePopper.state.elements.popper.remove()
130
+ if (this.handleDocumentClick) {
131
+ window.removeEventListener('click', this.handleDocumentClick)
132
+ }
133
+
134
+ delete this.activePopper
135
+ delete this.container
136
+ }
137
+ }
138
+
139
+ public getContainer(): HTMLElement | undefined {
140
+ return this.container
141
+ }
142
+
143
+ public update() {
144
+ if (this.activePopper) {
145
+ this.activePopper.update()
146
+ }
147
+ }
148
+
149
+ public isActive = () => !!this.activePopper
150
+
151
+ private focusInput(container: HTMLDivElement, autoFocus = true) {
152
+ const input = container.querySelector('input') as HTMLElement | null
153
+ if (input) {
154
+ input.focus()
155
+ return
156
+ }
157
+ if (autoFocus) {
158
+ const button = container.querySelector(
159
+ 'button:not([disabled]), [tabindex]:not([tabindex="-1"])'
160
+ ) as HTMLElement | null
161
+ button?.focus()
162
+ }
163
+ }
164
+
165
+ private addContainerClass(referenceElement: Element) {
166
+ const container = referenceElement.closest('.ProseMirror')
167
+
168
+ if (container) {
169
+ container.classList.add('popper-open')
170
+ }
171
+ }
172
+
173
+ private removeContainerClass(referenceElement: Element) {
174
+ const container = referenceElement.closest('.ProseMirror')
175
+
176
+ if (container) {
177
+ container.classList.remove('popper-open')
178
+ }
179
+ }
180
+ }