@stesura/react-prosemirror 3.2.11-stesura.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 (296) hide show
  1. package/LICENSE.txt +21 -0
  2. package/README.md +939 -0
  3. package/dist/cjs/AbstractEditorView.js +4 -0
  4. package/dist/cjs/ReactEditorView.js +194 -0
  5. package/dist/cjs/StaticEditorView.js +89 -0
  6. package/dist/cjs/browser.js +53 -0
  7. package/dist/cjs/commands/reorderSiblings.js +72 -0
  8. package/dist/cjs/components/ChildNodeViews.js +418 -0
  9. package/dist/cjs/components/CursorWrapper.js +84 -0
  10. package/dist/cjs/components/EditorStateSelectorsProvider.js +90 -0
  11. package/dist/cjs/components/LayoutGroup.js +112 -0
  12. package/dist/cjs/components/NativeWidgetView.js +108 -0
  13. package/dist/cjs/components/OutputSpec.js +121 -0
  14. package/dist/cjs/components/ProseMirror.js +146 -0
  15. package/dist/cjs/components/ProseMirrorDoc.js +74 -0
  16. package/dist/cjs/components/SeparatorHackView.js +99 -0
  17. package/dist/cjs/components/TextNodeView.js +113 -0
  18. package/dist/cjs/components/TrailingHackView.js +87 -0
  19. package/dist/cjs/components/WidgetView.js +94 -0
  20. package/dist/cjs/components/WidgetViewComponentProps.js +4 -0
  21. package/dist/cjs/components/marks/DefaultMarkView.js +70 -0
  22. package/dist/cjs/components/marks/MarkView.js +85 -0
  23. package/dist/cjs/components/marks/MarkViewComponentProps.js +4 -0
  24. package/dist/cjs/components/marks/MarkViewConstructorView.js +116 -0
  25. package/dist/cjs/components/marks/ReactMarkView.js +109 -0
  26. package/dist/cjs/components/nodes/DefaultNodeView.js +68 -0
  27. package/dist/cjs/components/nodes/DocNodeView.js +97 -0
  28. package/dist/cjs/components/nodes/NodeView.js +129 -0
  29. package/dist/cjs/components/nodes/NodeViewComponentProps.js +4 -0
  30. package/dist/cjs/components/nodes/NodeViewConstructorView.js +145 -0
  31. package/dist/cjs/components/nodes/ReactNodeView.js +189 -0
  32. package/dist/cjs/constants.js +33 -0
  33. package/dist/cjs/contexts/ChildDescriptionsContext.js +19 -0
  34. package/dist/cjs/contexts/EditorContext.js +12 -0
  35. package/dist/cjs/contexts/EditorStateContext.js +12 -0
  36. package/dist/cjs/contexts/EditorStateStoreContext.js +45 -0
  37. package/dist/cjs/contexts/IgnoreMutationContext.js +12 -0
  38. package/dist/cjs/contexts/LayoutGroupContext.js +12 -0
  39. package/dist/cjs/contexts/NodeViewContext.js +12 -0
  40. package/dist/cjs/contexts/RenderStoreContext.js +54 -0
  41. package/dist/cjs/contexts/SelectNodeContext.js +12 -0
  42. package/dist/cjs/contexts/StopEventContext.js +12 -0
  43. package/dist/cjs/decorations/ReactWidgetType.js +58 -0
  44. package/dist/cjs/decorations/computeDocDeco.js +44 -0
  45. package/dist/cjs/decorations/internalTypes.js +4 -0
  46. package/dist/cjs/decorations/iterDeco.js +91 -0
  47. package/dist/cjs/decorations/viewDecorations.js +155 -0
  48. package/dist/cjs/dom.js +147 -0
  49. package/dist/cjs/findDOMNode.js +46 -0
  50. package/dist/cjs/hooks/useClientLayoutEffect.js +19 -0
  51. package/dist/cjs/hooks/useComponentEventListeners.js +72 -0
  52. package/dist/cjs/hooks/useEditor.js +130 -0
  53. package/dist/cjs/hooks/useEditorEffect.js +39 -0
  54. package/dist/cjs/hooks/useEditorEventCallback.js +38 -0
  55. package/dist/cjs/hooks/useEditorEventListener.js +34 -0
  56. package/dist/cjs/hooks/useEditorState.js +18 -0
  57. package/dist/cjs/hooks/useEditorStateSelector.js +17 -0
  58. package/dist/cjs/hooks/useEffectEvent.js +34 -0
  59. package/dist/cjs/hooks/useForceUpdate.js +15 -0
  60. package/dist/cjs/hooks/useIgnoreMutation.js +24 -0
  61. package/dist/cjs/hooks/useIsComposingIn.js +25 -0
  62. package/dist/cjs/hooks/useIsEditorStatic.js +15 -0
  63. package/dist/cjs/hooks/useIsNodeSelected.js +21 -0
  64. package/dist/cjs/hooks/useLayoutGroupEffect.js +20 -0
  65. package/dist/cjs/hooks/useMarkViewDescription.js +134 -0
  66. package/dist/cjs/hooks/useNodePos.js +18 -0
  67. package/dist/cjs/hooks/useNodeViewDescription.js +154 -0
  68. package/dist/cjs/hooks/useReactKeys.js +17 -0
  69. package/dist/cjs/hooks/useSelectNode.js +30 -0
  70. package/dist/cjs/hooks/useSetDom.js +57 -0
  71. package/dist/cjs/hooks/useStopEvent.js +24 -0
  72. package/dist/cjs/index.js +85 -0
  73. package/dist/cjs/package.json +3 -0
  74. package/dist/cjs/plugins/beforeInputPlugin.js +356 -0
  75. package/dist/cjs/plugins/reactKeys.js +121 -0
  76. package/dist/cjs/props.js +283 -0
  77. package/dist/cjs/refs.js +28 -0
  78. package/dist/cjs/testing/editorViewTestHelpers.js +109 -0
  79. package/dist/cjs/testing/setupProseMirrorView.js +94 -0
  80. package/dist/cjs/tiptap/ReactProseMirrorNodeView.js +26 -0
  81. package/dist/cjs/tiptap/TiptapEditor.js +34 -0
  82. package/dist/cjs/tiptap/TiptapEditorContent.js +143 -0
  83. package/dist/cjs/tiptap/TiptapEditorView.js +130 -0
  84. package/dist/cjs/tiptap/contexts/TiptapEditorContext.js +12 -0
  85. package/dist/cjs/tiptap/extensions/ReactProseMirror.js +40 -0
  86. package/dist/cjs/tiptap/extensions/ReactProseMirrorCommands.js +21 -0
  87. package/dist/cjs/tiptap/extensions/commands/updateAttributes.js +104 -0
  88. package/dist/cjs/tiptap/hooks/useEditor.js +318 -0
  89. package/dist/cjs/tiptap/hooks/useIsInReactProseMirror.js +15 -0
  90. package/dist/cjs/tiptap/hooks/useTiptapEditor.js +35 -0
  91. package/dist/cjs/tiptap/hooks/useTiptapEditorEffect.js +35 -0
  92. package/dist/cjs/tiptap/hooks/useTiptapEditorEventCallback.js +35 -0
  93. package/dist/cjs/tiptap/index.js +48 -0
  94. package/dist/cjs/tiptap/tiptapNodeView.js +245 -0
  95. package/dist/cjs/viewdesc.js +862 -0
  96. package/dist/esm/AbstractEditorView.js +1 -0
  97. package/dist/esm/ReactEditorView.js +194 -0
  98. package/dist/esm/StaticEditorView.js +79 -0
  99. package/dist/esm/browser.js +43 -0
  100. package/dist/esm/commands/reorderSiblings.js +63 -0
  101. package/dist/esm/components/ChildNodeViews.js +359 -0
  102. package/dist/esm/components/CursorWrapper.js +33 -0
  103. package/dist/esm/components/EditorStateSelectorsProvider.js +31 -0
  104. package/dist/esm/components/LayoutGroup.js +67 -0
  105. package/dist/esm/components/NativeWidgetView.js +57 -0
  106. package/dist/esm/components/OutputSpec.js +71 -0
  107. package/dist/esm/components/ProseMirror.js +95 -0
  108. package/dist/esm/components/ProseMirrorDoc.js +15 -0
  109. package/dist/esm/components/SeparatorHackView.js +48 -0
  110. package/dist/esm/components/TextNodeView.js +103 -0
  111. package/dist/esm/components/TrailingHackView.js +36 -0
  112. package/dist/esm/components/WidgetView.js +43 -0
  113. package/dist/esm/components/WidgetViewComponentProps.js +1 -0
  114. package/dist/esm/components/marks/DefaultMarkView.js +19 -0
  115. package/dist/esm/components/marks/MarkView.js +34 -0
  116. package/dist/esm/components/marks/MarkViewComponentProps.js +1 -0
  117. package/dist/esm/components/marks/MarkViewConstructorView.js +65 -0
  118. package/dist/esm/components/marks/ReactMarkView.js +58 -0
  119. package/dist/esm/components/nodes/DefaultNodeView.js +17 -0
  120. package/dist/esm/components/nodes/DocNodeView.js +46 -0
  121. package/dist/esm/components/nodes/NodeView.js +67 -0
  122. package/dist/esm/components/nodes/NodeViewComponentProps.js +1 -0
  123. package/dist/esm/components/nodes/NodeViewConstructorView.js +94 -0
  124. package/dist/esm/components/nodes/ReactNodeView.js +138 -0
  125. package/dist/esm/constants.js +15 -0
  126. package/dist/esm/contexts/ChildDescriptionsContext.js +9 -0
  127. package/dist/esm/contexts/EditorContext.js +7 -0
  128. package/dist/esm/contexts/EditorStateContext.js +2 -0
  129. package/dist/esm/contexts/EditorStateStoreContext.js +27 -0
  130. package/dist/esm/contexts/IgnoreMutationContext.js +2 -0
  131. package/dist/esm/contexts/LayoutGroupContext.js +2 -0
  132. package/dist/esm/contexts/NodeViewContext.js +2 -0
  133. package/dist/esm/contexts/RenderStoreContext.js +33 -0
  134. package/dist/esm/contexts/SelectNodeContext.js +2 -0
  135. package/dist/esm/contexts/StopEventContext.js +2 -0
  136. package/dist/esm/decorations/ReactWidgetType.js +40 -0
  137. package/dist/esm/decorations/computeDocDeco.js +44 -0
  138. package/dist/esm/decorations/internalTypes.js +1 -0
  139. package/dist/esm/decorations/iterDeco.js +85 -0
  140. package/dist/esm/decorations/viewDecorations.js +155 -0
  141. package/dist/esm/dom.js +110 -0
  142. package/dist/esm/findDOMNode.js +31 -0
  143. package/dist/esm/hooks/useClientLayoutEffect.js +9 -0
  144. package/dist/esm/hooks/useComponentEventListeners.js +87 -0
  145. package/dist/esm/hooks/useEditor.js +128 -0
  146. package/dist/esm/hooks/useEditorEffect.js +46 -0
  147. package/dist/esm/hooks/useEditorEventCallback.js +38 -0
  148. package/dist/esm/hooks/useEditorEventListener.js +28 -0
  149. package/dist/esm/hooks/useEditorState.js +10 -0
  150. package/dist/esm/hooks/useEditorStateSelector.js +14 -0
  151. package/dist/esm/hooks/useEffectEvent.js +24 -0
  152. package/dist/esm/hooks/useForceUpdate.js +8 -0
  153. package/dist/esm/hooks/useIgnoreMutation.js +14 -0
  154. package/dist/esm/hooks/useIsComposingIn.js +17 -0
  155. package/dist/esm/hooks/useIsEditorStatic.js +8 -0
  156. package/dist/esm/hooks/useIsNodeSelected.js +11 -0
  157. package/dist/esm/hooks/useLayoutGroupEffect.js +10 -0
  158. package/dist/esm/hooks/useMarkViewDescription.js +124 -0
  159. package/dist/esm/hooks/useNodePos.js +15 -0
  160. package/dist/esm/hooks/useNodeViewDescription.js +144 -0
  161. package/dist/esm/hooks/useReactKeys.js +7 -0
  162. package/dist/esm/hooks/useSelectNode.js +20 -0
  163. package/dist/esm/hooks/useSetDom.js +47 -0
  164. package/dist/esm/hooks/useStopEvent.js +14 -0
  165. package/dist/esm/index.js +19 -0
  166. package/dist/esm/plugins/beforeInputPlugin.js +346 -0
  167. package/dist/esm/plugins/reactKeys.js +106 -0
  168. package/dist/esm/props.js +267 -0
  169. package/dist/esm/refs.js +18 -0
  170. package/dist/esm/testing/editorViewTestHelpers.js +86 -0
  171. package/dist/esm/testing/setupProseMirrorView.js +76 -0
  172. package/dist/esm/tiptap/ReactProseMirrorNodeView.js +22 -0
  173. package/dist/esm/tiptap/TiptapEditor.js +24 -0
  174. package/dist/esm/tiptap/TiptapEditorContent.js +99 -0
  175. package/dist/esm/tiptap/TiptapEditorView.js +76 -0
  176. package/dist/esm/tiptap/contexts/TiptapEditorContext.js +2 -0
  177. package/dist/esm/tiptap/extensions/ReactProseMirror.js +30 -0
  178. package/dist/esm/tiptap/extensions/ReactProseMirrorCommands.js +11 -0
  179. package/dist/esm/tiptap/extensions/commands/updateAttributes.js +96 -0
  180. package/dist/esm/tiptap/hooks/useEditor.js +308 -0
  181. package/dist/esm/tiptap/hooks/useIsInReactProseMirror.js +9 -0
  182. package/dist/esm/tiptap/hooks/useTiptapEditor.js +31 -0
  183. package/dist/esm/tiptap/hooks/useTiptapEditorEffect.js +42 -0
  184. package/dist/esm/tiptap/hooks/useTiptapEditorEventCallback.js +35 -0
  185. package/dist/esm/tiptap/index.js +9 -0
  186. package/dist/esm/tiptap/tiptapNodeView.js +211 -0
  187. package/dist/esm/viewdesc.js +844 -0
  188. package/dist/tsconfig.tsbuildinfo +1 -0
  189. package/dist/types/AbstractEditorView.d.ts +28 -0
  190. package/dist/types/ReactEditorView.d.ts +102 -0
  191. package/dist/types/StaticEditorView.d.ts +26 -0
  192. package/dist/types/__tests__/viewdesc.test.d.ts +1 -0
  193. package/dist/types/browser.d.ts +15 -0
  194. package/dist/types/commands/__tests__/reorderSiblings.test.d.ts +1 -0
  195. package/dist/types/commands/reorderSiblings.d.ts +14 -0
  196. package/dist/types/components/ChildNodeViews.d.ts +9 -0
  197. package/dist/types/components/CursorWrapper.d.ts +3 -0
  198. package/dist/types/components/EditorStateSelectorsProvider.d.ts +10 -0
  199. package/dist/types/components/LayoutGroup.d.ts +12 -0
  200. package/dist/types/components/NativeWidgetView.d.ts +8 -0
  201. package/dist/types/components/OutputSpec.d.ts +10 -0
  202. package/dist/types/components/ProseMirror.d.ts +14 -0
  203. package/dist/types/components/ProseMirrorDoc.d.ts +16 -0
  204. package/dist/types/components/SeparatorHackView.d.ts +6 -0
  205. package/dist/types/components/TextNodeView.d.ts +27 -0
  206. package/dist/types/components/TrailingHackView.d.ts +6 -0
  207. package/dist/types/components/WidgetView.d.ts +8 -0
  208. package/dist/types/components/WidgetViewComponentProps.d.ts +7 -0
  209. package/dist/types/components/__tests__/ProseMirror.composition.test.d.ts +17 -0
  210. package/dist/types/components/__tests__/ProseMirror.domchange.test.d.ts +1 -0
  211. package/dist/types/components/__tests__/ProseMirror.draw-decoration.test.d.ts +1 -0
  212. package/dist/types/components/__tests__/ProseMirror.draw.test.d.ts +1 -0
  213. package/dist/types/components/__tests__/ProseMirror.memory-leak.test.d.ts +6 -0
  214. package/dist/types/components/__tests__/ProseMirror.mobile.test.d.ts +1 -0
  215. package/dist/types/components/__tests__/ProseMirror.node-view.test.d.ts +1 -0
  216. package/dist/types/components/__tests__/ProseMirror.selection.test.d.ts +1 -0
  217. package/dist/types/components/__tests__/ProseMirror.test.d.ts +1 -0
  218. package/dist/types/components/__tests__/stableContexts.test.d.ts +10 -0
  219. package/dist/types/components/marks/DefaultMarkView.d.ts +3 -0
  220. package/dist/types/components/marks/MarkView.d.ts +10 -0
  221. package/dist/types/components/marks/MarkViewComponentProps.d.ts +11 -0
  222. package/dist/types/components/marks/MarkViewConstructorView.d.ts +12 -0
  223. package/dist/types/components/marks/ReactMarkView.d.ts +12 -0
  224. package/dist/types/components/nodes/DefaultNodeView.d.ts +3 -0
  225. package/dist/types/components/nodes/DocNodeView.d.ts +12 -0
  226. package/dist/types/components/nodes/NodeView.d.ts +14 -0
  227. package/dist/types/components/nodes/NodeViewComponentProps.d.ts +13 -0
  228. package/dist/types/components/nodes/NodeViewConstructorView.d.ts +12 -0
  229. package/dist/types/components/nodes/ReactNodeView.d.ts +13 -0
  230. package/dist/types/constants.d.ts +4 -0
  231. package/dist/types/contexts/ChildDescriptionsContext.d.ts +7 -0
  232. package/dist/types/contexts/EditorContext.d.ts +18 -0
  233. package/dist/types/contexts/EditorStateContext.d.ts +2 -0
  234. package/dist/types/contexts/EditorStateStoreContext.d.ts +9 -0
  235. package/dist/types/contexts/IgnoreMutationContext.d.ts +5 -0
  236. package/dist/types/contexts/LayoutGroupContext.d.ts +5 -0
  237. package/dist/types/contexts/NodeViewContext.d.ts +9 -0
  238. package/dist/types/contexts/RenderStoreContext.d.ts +24 -0
  239. package/dist/types/contexts/SelectNodeContext.d.ts +5 -0
  240. package/dist/types/contexts/StopEventContext.d.ts +5 -0
  241. package/dist/types/contexts/__tests__/DeferredLayoutEffects.test.d.ts +1 -0
  242. package/dist/types/decorations/ReactWidgetType.d.ts +40 -0
  243. package/dist/types/decorations/computeDocDeco.d.ts +14 -0
  244. package/dist/types/decorations/internalTypes.d.ts +20 -0
  245. package/dist/types/decorations/iterDeco.d.ts +3 -0
  246. package/dist/types/decorations/viewDecorations.d.ts +14 -0
  247. package/dist/types/dom.d.ts +22 -0
  248. package/dist/types/findDOMNode.d.ts +3 -0
  249. package/dist/types/hooks/__tests__/useEditorEffect.test.d.ts +1 -0
  250. package/dist/types/hooks/useClientLayoutEffect.d.ts +2 -0
  251. package/dist/types/hooks/useComponentEventListeners.d.ts +34 -0
  252. package/dist/types/hooks/useEditor.d.ts +37 -0
  253. package/dist/types/hooks/useEditorEffect.d.ts +21 -0
  254. package/dist/types/hooks/useEditorEventCallback.d.ts +13 -0
  255. package/dist/types/hooks/useEditorEventListener.d.ts +8 -0
  256. package/dist/types/hooks/useEditorState.d.ts +5 -0
  257. package/dist/types/hooks/useEditorStateSelector.d.ts +10 -0
  258. package/dist/types/hooks/useEffectEvent.d.ts +1 -0
  259. package/dist/types/hooks/useForceUpdate.d.ts +5 -0
  260. package/dist/types/hooks/useIgnoreMutation.d.ts +2 -0
  261. package/dist/types/hooks/useIsComposingIn.d.ts +4 -0
  262. package/dist/types/hooks/useIsEditorStatic.d.ts +5 -0
  263. package/dist/types/hooks/useIsNodeSelected.d.ts +1 -0
  264. package/dist/types/hooks/useLayoutGroupEffect.d.ts +3 -0
  265. package/dist/types/hooks/useMarkViewDescription.d.ts +15 -0
  266. package/dist/types/hooks/useNodePos.d.ts +9 -0
  267. package/dist/types/hooks/useNodeViewDescription.d.ts +16 -0
  268. package/dist/types/hooks/useReactKeys.d.ts +2 -0
  269. package/dist/types/hooks/useSelectNode.d.ts +2 -0
  270. package/dist/types/hooks/useSetDom.d.ts +2 -0
  271. package/dist/types/hooks/useStopEvent.d.ts +2 -0
  272. package/dist/types/index.d.ts +21 -0
  273. package/dist/types/plugins/__tests__/reactKeys.test.d.ts +1 -0
  274. package/dist/types/plugins/beforeInputPlugin.d.ts +2 -0
  275. package/dist/types/plugins/reactKeys.d.ts +23 -0
  276. package/dist/types/props.d.ts +1173 -0
  277. package/dist/types/refs.d.ts +2 -0
  278. package/dist/types/testing/editorViewTestHelpers.d.ts +24 -0
  279. package/dist/types/testing/setupProseMirrorView.d.ts +2 -0
  280. package/dist/types/tiptap/ReactProseMirrorNodeView.d.ts +15 -0
  281. package/dist/types/tiptap/TiptapEditor.d.ts +6 -0
  282. package/dist/types/tiptap/TiptapEditorContent.d.ts +28 -0
  283. package/dist/types/tiptap/TiptapEditorView.d.ts +16 -0
  284. package/dist/types/tiptap/contexts/TiptapEditorContext.d.ts +6 -0
  285. package/dist/types/tiptap/extensions/ReactProseMirror.d.ts +9 -0
  286. package/dist/types/tiptap/extensions/ReactProseMirrorCommands.d.ts +2 -0
  287. package/dist/types/tiptap/extensions/commands/updateAttributes.d.ts +24 -0
  288. package/dist/types/tiptap/hooks/useEditor.d.ts +38 -0
  289. package/dist/types/tiptap/hooks/useIsInReactProseMirror.d.ts +6 -0
  290. package/dist/types/tiptap/hooks/useTiptapEditor.d.ts +11 -0
  291. package/dist/types/tiptap/hooks/useTiptapEditorEffect.d.ts +21 -0
  292. package/dist/types/tiptap/hooks/useTiptapEditorEventCallback.d.ts +13 -0
  293. package/dist/types/tiptap/index.d.ts +9 -0
  294. package/dist/types/tiptap/tiptapNodeView.d.ts +50 -0
  295. package/dist/types/viewdesc.d.ts +179 -0
  296. package/package.json +167 -0
@@ -0,0 +1,844 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-non-null-assertion */ import { Fragment } from "prosemirror-model";
2
+ import { browser } from "./browser.js";
3
+ import { domIndex, isEquivalentPosition } from "./dom.js";
4
+ // View descriptions are data structures that describe the DOM that is
5
+ // used to represent the editor's content. They are used for:
6
+ //
7
+ // - Incremental redrawing when the document changes
8
+ //
9
+ // - Figuring out what part of the document a given DOM position
10
+ // corresponds to
11
+ //
12
+ // - Wiring in custom implementations of the editing interface for a
13
+ // given node
14
+ //
15
+ // They form a doubly-linked mutable tree, starting at `view.docView`.
16
+ export function sortViewDescs(a, b) {
17
+ if (a instanceof TrailingHackViewDesc) return 1;
18
+ if (b instanceof TrailingHackViewDesc) return -1;
19
+ const posDiff = a.getPos() - b.getPos();
20
+ if (posDiff !== 0) return posDiff;
21
+ // When two descs share the same PM position (e.g. a zero-width widget
22
+ // and a text node that starts at the same position), fall back to DOM
23
+ // order so that the viewdesc children match the actual DOM layout.
24
+ // Without this, position computations like `posBeforeChild` can return
25
+ // the wrong PM position for the widget's container.
26
+ const cmp = a.dom.compareDocumentPosition(b.dom);
27
+ if (cmp & 4 /* DOCUMENT_POSITION_FOLLOWING */ ) return -1;
28
+ if (cmp & 2 /* DOCUMENT_POSITION_PRECEDING */ ) return 1;
29
+ return 0;
30
+ }
31
+ // Adds `desc` to `siblings` if missing and moves it into sorted order.
32
+ // Every child used to sort the whole sibling list from its own layout
33
+ // effect, which made mounting n siblings O(n²). Only `desc` can be out of
34
+ // place here; the parent's own `children.sort` remains the full pass for
35
+ // siblings that move without re-rendering (reorderSiblings).
36
+ export const placeViewDesc = (siblings, desc)=>{
37
+ let index = siblings.lastIndexOf(desc);
38
+ if (index === -1) index = siblings.push(desc) - 1;
39
+ const prev = siblings[index - 1];
40
+ const next = siblings[index + 1];
41
+ if ((!prev || sortViewDescs(prev, desc) <= 0) && (!next || sortViewDescs(desc, next) <= 0)) {
42
+ return;
43
+ }
44
+ siblings.splice(index, 1);
45
+ let low = 0;
46
+ let high = siblings.length;
47
+ while(low < high){
48
+ const mid = low + high >> 1;
49
+ const sibling = siblings[mid];
50
+ if (sibling && sortViewDescs(sibling, desc) <= 0) low = mid + 1;
51
+ else high = mid;
52
+ }
53
+ siblings.splice(low, 0, desc);
54
+ };
55
+ const NOT_DIRTY = 0, CHILD_DIRTY = 1, CONTENT_DIRTY = 2, NODE_DIRTY = 3;
56
+ // Superclass for the various kinds of descriptions. Defines their
57
+ // basic structure and shared methods.
58
+ export class ViewDesc {
59
+ parent;
60
+ children;
61
+ getPos;
62
+ dom;
63
+ contentDOM;
64
+ dirty;
65
+ node;
66
+ constructor(parent, children, getPos, dom, // This is the node that holds the child views. It may be null for
67
+ // descs that don't have children.
68
+ contentDOM){
69
+ this.parent = parent;
70
+ this.children = children;
71
+ this.getPos = getPos;
72
+ this.dom = dom;
73
+ this.contentDOM = contentDOM;
74
+ this.dirty = NOT_DIRTY;
75
+ // An expando property on the DOM node provides a link back to its
76
+ // description.
77
+ dom.pmViewDesc = this;
78
+ }
79
+ // Used to check whether a given description corresponds to a
80
+ // widget/mark/node.
81
+ matchesWidget(_widget) {
82
+ return false;
83
+ }
84
+ matchesMark(_mark) {
85
+ return false;
86
+ }
87
+ matchesNode(_node, _outerDeco, _innerDeco) {
88
+ return false;
89
+ }
90
+ // @ts-expect-error ...
91
+ matchesHack(nodeName) {
92
+ return false;
93
+ }
94
+ // When parsing in-editor content (in domchange.js), we allow
95
+ // descriptions to determine the parse rules that should be used to
96
+ // parse them.
97
+ parseRule() {
98
+ return null;
99
+ }
100
+ // Used by the editor's event handler to ignore events that come
101
+ // from certain descs.
102
+ // @ts-expect-error ...
103
+ stopEvent(event) {
104
+ return false;
105
+ }
106
+ // The size of the content represented by this desc.
107
+ get size() {
108
+ let size = 0;
109
+ for(let i = 0; i < this.children.length; i++)// @ts-expect-error ...
110
+ size += this.children[i].size;
111
+ return size;
112
+ }
113
+ // For block nodes, this represents the space taken up by their
114
+ // start/end tokens.
115
+ get border() {
116
+ return 0;
117
+ }
118
+ destroy() {
119
+ this.parent = undefined;
120
+ if (this.dom.pmViewDesc == this) this.dom.pmViewDesc = undefined;
121
+ for(let i = 0; i < this.children.length; i++)this.children[i].destroy();
122
+ }
123
+ posBeforeChild(child) {
124
+ for(let i = 0, pos = this.posAtStart;; i++){
125
+ const cur = this.children[i];
126
+ if (cur == child) return pos;
127
+ // @ts-expect-error ...
128
+ pos += cur.size;
129
+ }
130
+ }
131
+ get posBefore() {
132
+ return this.parent.posBeforeChild(this);
133
+ }
134
+ get posAtStart() {
135
+ return this.parent ? this.parent.posBeforeChild(this) + this.border : 0;
136
+ }
137
+ get posAfter() {
138
+ return this.posBefore + this.size;
139
+ }
140
+ get posAtEnd() {
141
+ return this.posAtStart + this.size - 2 * this.border;
142
+ }
143
+ localPosFromDOM(dom, offset, bias) {
144
+ // If the DOM position is in the content, use the child desc after
145
+ // it to figure out a position.
146
+ if (this.contentDOM && this.contentDOM.contains(dom.nodeType == 1 ? dom : dom.parentNode)) {
147
+ if (bias < 0) {
148
+ let domBefore, desc;
149
+ if (dom == this.contentDOM) {
150
+ domBefore = dom.childNodes[offset - 1];
151
+ } else {
152
+ while(dom.parentNode != this.contentDOM)dom = dom.parentNode;
153
+ domBefore = dom.previousSibling;
154
+ }
155
+ while(domBefore && !((desc = domBefore.pmViewDesc) && desc.parent == this))domBefore = domBefore.previousSibling;
156
+ return domBefore ? this.posBeforeChild(desc) + desc.size : this.posAtStart;
157
+ } else {
158
+ let domAfter, desc;
159
+ if (dom == this.contentDOM) {
160
+ domAfter = dom.childNodes[offset];
161
+ } else {
162
+ while(dom.parentNode != this.contentDOM)dom = dom.parentNode;
163
+ domAfter = dom.nextSibling;
164
+ }
165
+ while(domAfter && !((desc = domAfter.pmViewDesc) && desc.parent == this))domAfter = domAfter.nextSibling;
166
+ return domAfter ? this.posBeforeChild(desc) : this.posAtEnd;
167
+ }
168
+ }
169
+ // Otherwise, use various heuristics, falling back on the bias
170
+ // parameter, to determine whether to return the position at the
171
+ // start or at the end of this view desc.
172
+ let atEnd;
173
+ if (dom == this.dom && this.contentDOM) {
174
+ atEnd = offset > domIndex(this.contentDOM);
175
+ } else if (this.contentDOM && this.contentDOM != this.dom && this.dom.contains(this.contentDOM)) {
176
+ atEnd = dom.compareDocumentPosition(this.contentDOM) & 2;
177
+ } else if (this.dom.firstChild) {
178
+ if (offset == 0) for(let search = dom;; search = search.parentNode){
179
+ if (search == this.dom) {
180
+ atEnd = false;
181
+ break;
182
+ }
183
+ if (search.previousSibling) break;
184
+ }
185
+ if (atEnd == null && offset == dom.childNodes.length) for(let search = dom;; search = search.parentNode){
186
+ if (search == this.dom) {
187
+ atEnd = true;
188
+ break;
189
+ }
190
+ if (search.nextSibling) break;
191
+ }
192
+ }
193
+ return (atEnd == null ? bias > 0 : atEnd) ? this.posAtEnd : this.posAtStart;
194
+ }
195
+ nearestDesc(dom) {
196
+ let onlyNodes = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : false;
197
+ for(let first = true, cur = dom; cur; cur = cur.parentNode){
198
+ const desc = this.getDesc(cur);
199
+ let nodeDOM;
200
+ if (desc && (!onlyNodes || desc.node)) {
201
+ // If dom is outside of this desc's nodeDOM, don't count it.
202
+ if (first && (nodeDOM = desc.nodeDOM) && !(nodeDOM.nodeType == 1 ? nodeDOM.contains(dom.nodeType == 1 ? dom : dom.parentNode) : nodeDOM == dom)) first = false;
203
+ else return desc;
204
+ }
205
+ }
206
+ return;
207
+ }
208
+ getDesc(dom) {
209
+ const desc = dom.pmViewDesc;
210
+ for(let cur = desc; cur; cur = cur.parent)if (cur == this) return desc;
211
+ return;
212
+ }
213
+ posFromDOM(dom, offset, bias) {
214
+ for(let scan = dom; scan; scan = scan.parentNode){
215
+ const desc = this.getDesc(scan);
216
+ if (desc) return desc.localPosFromDOM(dom, offset, bias);
217
+ }
218
+ return -1;
219
+ }
220
+ // Find the desc for the node after the given pos, if any. (When a
221
+ // parent node overrode rendering, there might not be one.)
222
+ descAt(pos) {
223
+ for(let i = 0, offset = 0; i < this.children.length; i++){
224
+ let child = this.children[i];
225
+ const end = offset + child.size;
226
+ if (offset == pos && end != offset) {
227
+ while(!child.border && child.children.length){
228
+ for(let i = 0; i < child.children.length; i++){
229
+ const inner = child.children[i];
230
+ if (inner.size) {
231
+ child = inner;
232
+ break;
233
+ }
234
+ }
235
+ }
236
+ return child;
237
+ }
238
+ if (pos < end) return child.descAt(pos - offset - child.border);
239
+ offset = end;
240
+ }
241
+ return;
242
+ }
243
+ domFromPos(pos, side) {
244
+ if (!this.contentDOM) return {
245
+ node: this.dom,
246
+ offset: 0,
247
+ atom: pos + 1
248
+ };
249
+ // First find the position in the child array
250
+ let i = 0, offset = 0;
251
+ for(let curPos = 0; i < this.children.length; i++){
252
+ const child = this.children[i], end = curPos + child.size;
253
+ if (end > pos || child instanceof TrailingHackViewDesc) {
254
+ offset = pos - curPos;
255
+ break;
256
+ }
257
+ curPos = end;
258
+ }
259
+ // If this points into the middle of a child, call through
260
+ if (offset) return this.children[i].domFromPos(offset - this.children[i].border, side);
261
+ // Go back if there were any zero-length widgets with side >= 0 before this point
262
+ for(let prev; i && !(prev = this.children[i - 1]).size && prev instanceof WidgetViewDesc && prev.side >= 0; i--){
263
+ // ...
264
+ }
265
+ // Scan towards the first useable node
266
+ if (side <= 0) {
267
+ let prev, enter = true;
268
+ for(;; i--, enter = false){
269
+ prev = i ? this.children[i - 1] : null;
270
+ if (!prev || prev.dom.parentNode == this.contentDOM) break;
271
+ }
272
+ if (prev && side && enter && !prev.border && !prev.domAtom) {
273
+ return prev.domFromPos(prev.size, side);
274
+ }
275
+ return {
276
+ node: this.contentDOM,
277
+ offset: prev ? domIndex(prev.dom) + 1 : 0
278
+ };
279
+ } else {
280
+ let next, enter = true;
281
+ for(;; i++, enter = false){
282
+ next = i < this.children.length ? this.children[i] : null;
283
+ if (!next || next.dom.parentNode == this.contentDOM) break;
284
+ }
285
+ if (next && enter && !next.border && !next.domAtom) return next.domFromPos(0, side);
286
+ return {
287
+ node: this.contentDOM,
288
+ offset: next ? domIndex(next.dom) : this.contentDOM.childNodes.length
289
+ };
290
+ }
291
+ }
292
+ // Used to find a DOM range in a single parent for a given changed
293
+ // range.
294
+ parseRange(from, to) {
295
+ let base = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : 0;
296
+ if (this.children.length == 0) return {
297
+ node: this.contentDOM,
298
+ from,
299
+ to,
300
+ fromOffset: 0,
301
+ toOffset: this.contentDOM.childNodes.length
302
+ };
303
+ let fromOffset = -1, toOffset = -1;
304
+ for(let offset = base, i = 0;; i++){
305
+ const child = this.children[i], end = offset + child.size;
306
+ if (fromOffset == -1 && from <= end) {
307
+ const childBase = offset + child.border;
308
+ // FIXME maybe descend mark views to parse a narrower range?
309
+ if (from >= childBase && to <= end - child.border && child.node && child.contentDOM && this.contentDOM.contains(child.contentDOM)) return child.parseRange(from, to, childBase);
310
+ from = offset;
311
+ for(let j = i; j > 0; j--){
312
+ const prev = this.children[j - 1];
313
+ if (prev.size && prev.dom.parentNode == this.contentDOM && !prev.emptyChildAt(1)) {
314
+ fromOffset = domIndex(prev.dom) + 1;
315
+ break;
316
+ }
317
+ from -= prev.size;
318
+ }
319
+ if (fromOffset == -1) fromOffset = 0;
320
+ }
321
+ if (fromOffset > -1 && (end > to || i == this.children.length - 1)) {
322
+ to = end;
323
+ for(let j = i + 1; j < this.children.length; j++){
324
+ const next = this.children[j];
325
+ if (next.size && next.dom.parentNode == this.contentDOM && !next.emptyChildAt(-1)) {
326
+ toOffset = domIndex(next.dom);
327
+ break;
328
+ }
329
+ to += next.size;
330
+ }
331
+ if (toOffset == -1) toOffset = this.contentDOM.childNodes.length;
332
+ break;
333
+ }
334
+ offset = end;
335
+ }
336
+ return {
337
+ node: this.contentDOM,
338
+ from,
339
+ to,
340
+ fromOffset,
341
+ toOffset
342
+ };
343
+ }
344
+ emptyChildAt(side) {
345
+ if (this.border || !this.contentDOM || !this.children.length) return false;
346
+ const child = this.children[side < 0 ? 0 : this.children.length - 1];
347
+ // @ts-expect-error ...
348
+ return child.size == 0 || child.emptyChildAt(side);
349
+ }
350
+ domAfterPos(pos) {
351
+ const { node, offset } = this.domFromPos(pos, 0);
352
+ if (node.nodeType != 1 || offset == node.childNodes.length) throw new RangeError("No node after pos " + pos);
353
+ // @ts-expect-error ...
354
+ return node.childNodes[offset];
355
+ }
356
+ // View descs are responsible for setting any selection that falls
357
+ // entirely inside of them, so that custom implementations can do
358
+ // custom things with the selection. Note that this falls apart when
359
+ // a selection starts in such a node and ends in another, in which
360
+ // case we just use whatever domFromPos produces as a best effort.
361
+ setSelection(anchor, head, view) {
362
+ let force = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : false;
363
+ if (view.composing) return;
364
+ // If the selection falls entirely in a child, give it to that child
365
+ const from = Math.min(anchor, head), to = Math.max(anchor, head);
366
+ for(let i = 0, offset = 0; i < this.children.length; i++){
367
+ const child = this.children[i], end = offset + child.size;
368
+ if (from > offset && to < end) return child.setSelection(anchor - offset - child.border, head - offset - child.border, view, force);
369
+ offset = end;
370
+ }
371
+ let anchorDOM = this.domFromPos(anchor, anchor ? -1 : 1);
372
+ let headDOM = head == anchor ? anchorDOM : this.domFromPos(head, head ? -1 : 1);
373
+ const domSel = view.root.getSelection();
374
+ const selRange = view.domSelectionRange();
375
+ let brKludge = false;
376
+ // On Firefox, using Selection.collapse to put the cursor after a
377
+ // BR node for some reason doesn't always work (#1073). On Safari,
378
+ // the cursor sometimes inexplicable visually lags behind its
379
+ // reported position in such situations (#1092).
380
+ if ((browser.gecko || browser.safari) && anchor == head) {
381
+ const { node, offset } = anchorDOM;
382
+ if (node.nodeType == 3) {
383
+ brKludge = !!(offset && node.nodeValue?.[offset - 1] == "\n");
384
+ // Issue #1128
385
+ if (brKludge && offset == node.nodeValue.length) {
386
+ for(let scan = node, after; scan; scan = scan.parentNode){
387
+ if (after = scan.nextSibling) {
388
+ if (after.nodeName == "BR") anchorDOM = headDOM = {
389
+ node: after.parentNode,
390
+ offset: domIndex(after) + 1
391
+ };
392
+ break;
393
+ }
394
+ const desc = scan.pmViewDesc;
395
+ if (desc && desc.node && desc.node.isBlock) break;
396
+ }
397
+ }
398
+ } else {
399
+ const prev = node.childNodes[offset - 1];
400
+ // @ts-expect-error ...
401
+ brKludge = prev && (prev.nodeName == "BR" || prev.contentEditable == "false");
402
+ }
403
+ }
404
+ // Firefox can act strangely when the selection is in front of an
405
+ // uneditable node. See #1163 and https://bugzilla.mozilla.org/show_bug.cgi?id=1709536
406
+ if (browser.gecko && selRange.focusNode && selRange.focusNode != headDOM.node && selRange.focusNode.nodeType == 1) {
407
+ const after = selRange.focusNode.childNodes[selRange.focusOffset];
408
+ if (after && after.contentEditable == "false") force = true;
409
+ }
410
+ if (view.cursorWrapped || !(force || brKludge && browser.safari) && isEquivalentPosition(anchorDOM.node, anchorDOM.offset, selRange.anchorNode, selRange.anchorOffset) && isEquivalentPosition(headDOM.node, headDOM.offset, selRange.focusNode, selRange.focusOffset)) {
411
+ return;
412
+ }
413
+ // Selection.extend can be used to create an 'inverted' selection
414
+ // (one where the focus is before the anchor), but not all
415
+ // browsers support it yet.
416
+ let domSelExtended = false;
417
+ if ((domSel.extend || anchor == head) && !brKludge) {
418
+ domSel.collapse(anchorDOM.node, anchorDOM.offset);
419
+ try {
420
+ if (anchor != head) domSel.extend(headDOM.node, headDOM.offset);
421
+ domSelExtended = true;
422
+ } catch (_) {
423
+ // In some cases with Chrome the selection is empty after calling
424
+ // collapse, even when it should be valid. This appears to be a bug, but
425
+ // it is difficult to isolate. If this happens fallback to the old path
426
+ // without using extend.
427
+ // Similarly, this could crash on Safari if the editor is hidden, and
428
+ // there was no selection.
429
+ }
430
+ }
431
+ if (!domSelExtended) {
432
+ if (anchor > head) {
433
+ const tmp = anchorDOM;
434
+ anchorDOM = headDOM;
435
+ headDOM = tmp;
436
+ }
437
+ const range = document.createRange();
438
+ range.setEnd(headDOM.node, headDOM.offset);
439
+ range.setStart(anchorDOM.node, anchorDOM.offset);
440
+ domSel.removeAllRanges();
441
+ domSel.addRange(range);
442
+ }
443
+ }
444
+ ignoreMutation(mutation) {
445
+ return !this.contentDOM && mutation.type != "selection";
446
+ }
447
+ get contentLost() {
448
+ return this.contentDOM && this.contentDOM != this.dom && !this.dom.contains(this.contentDOM);
449
+ }
450
+ // Remove a subtree of the element tree that has been touched
451
+ // by a DOM change, so that the next update will redraw it.
452
+ markDirty(from, to) {
453
+ for(let offset = 0, i = 0; i < this.children.length; i++){
454
+ const child = this.children[i], end = offset + child.size;
455
+ if (offset == end ? from <= end && to >= offset : from < end && to > offset) {
456
+ const startInside = offset + child.border, endInside = end - child.border;
457
+ if (from >= startInside && to <= endInside) {
458
+ this.dirty = from == offset || to == end ? CONTENT_DIRTY : CHILD_DIRTY;
459
+ if (from == startInside && to == endInside && (child.contentLost || child.dom.parentNode != this.contentDOM)) child.dirty = NODE_DIRTY;
460
+ else child.markDirty(from - startInside, to - startInside);
461
+ return;
462
+ } else {
463
+ child.dirty = child.dom == child.contentDOM && child.dom.parentNode == this.contentDOM && !child.children.length ? CONTENT_DIRTY : NODE_DIRTY;
464
+ }
465
+ }
466
+ offset = end;
467
+ }
468
+ this.dirty = CONTENT_DIRTY;
469
+ }
470
+ markParentsDirty() {
471
+ let level = 1;
472
+ for(let node = this.parent; node; node = node.parent, level++){
473
+ const dirty = level == 1 ? CONTENT_DIRTY : CHILD_DIRTY;
474
+ if (node.dirty < dirty) node.dirty = dirty;
475
+ }
476
+ }
477
+ get domAtom() {
478
+ return false;
479
+ }
480
+ get ignoreForCoords() {
481
+ return false;
482
+ }
483
+ get ignoreForSelection() {
484
+ return false;
485
+ }
486
+ isText(_text) {
487
+ return false;
488
+ }
489
+ }
490
+ // A widget desc represents a widget decoration, which is a DOM node
491
+ // drawn between the document nodes.
492
+ export class WidgetViewDesc extends ViewDesc {
493
+ widget;
494
+ constructor(parent, getPos, widget, dom){
495
+ super(parent, [], getPos, dom, null), this.widget = widget;
496
+ this.widget = widget;
497
+ }
498
+ matchesWidget(widget) {
499
+ return this.dirty == NOT_DIRTY && widget.type.eq(this.widget.type);
500
+ }
501
+ parseRule() {
502
+ return {
503
+ ignore: true
504
+ };
505
+ }
506
+ stopEvent(event) {
507
+ const stop = this.widget.spec.stopEvent;
508
+ return stop ? stop(event) : false;
509
+ }
510
+ ignoreMutation(mutation) {
511
+ return mutation.type != "selection" || this.widget.spec.ignoreSelection;
512
+ }
513
+ get domAtom() {
514
+ return true;
515
+ }
516
+ get ignoreForSelection() {
517
+ return !!this.widget.type.spec.relaxedSide;
518
+ }
519
+ get side() {
520
+ return this.widget.type.side;
521
+ }
522
+ }
523
+ export class CompositionViewDesc extends ViewDesc {
524
+ textDOM;
525
+ text;
526
+ constructor(parent, getPos, dom, textDOM, text){
527
+ super(parent, [], getPos, dom, null), this.textDOM = textDOM, this.text = text;
528
+ }
529
+ get size() {
530
+ return this.text.length;
531
+ }
532
+ localPosFromDOM(dom, offset) {
533
+ if (dom != this.textDOM) return this.posAtStart + (offset ? this.size : 0);
534
+ return this.posAtStart + offset;
535
+ }
536
+ domFromPos(pos) {
537
+ return {
538
+ node: this.textDOM,
539
+ offset: pos
540
+ };
541
+ }
542
+ ignoreMutation(mut) {
543
+ return mut.type === "characterData" && mut.target.nodeValue == mut.oldValue;
544
+ }
545
+ }
546
+ // A mark desc represents a mark. May have multiple children,
547
+ // depending on how the mark is split. Note that marks are drawn using
548
+ // a fixed nesting order, for simplicity and predictability, so in
549
+ // some cases they will be split more often than would appear
550
+ // necessary.
551
+ export class MarkViewDesc extends ViewDesc {
552
+ mark;
553
+ spec;
554
+ constructor(parent, children, getPos, mark, dom, contentDOM, spec){
555
+ super(parent, children, getPos, dom, contentDOM), this.mark = mark, this.spec = spec;
556
+ }
557
+ parseRule() {
558
+ if (this.dirty & NODE_DIRTY || this.mark.type.spec.reparseInView) return null;
559
+ return {
560
+ mark: this.mark.type.name,
561
+ attrs: this.mark.attrs,
562
+ contentElement: this.contentDOM
563
+ };
564
+ }
565
+ matchesMark(mark) {
566
+ return this.dirty != NODE_DIRTY && this.mark.eq(mark);
567
+ }
568
+ markDirty(from, to) {
569
+ super.markDirty(from, to);
570
+ // Move dirty info to nearest node view
571
+ if (this.dirty != NOT_DIRTY) {
572
+ let parent = this.parent;
573
+ while(!parent.node)parent = parent.parent;
574
+ if (parent.dirty < this.dirty) parent.dirty = this.dirty;
575
+ this.dirty = NOT_DIRTY;
576
+ }
577
+ }
578
+ ignoreMutation(mutation) {
579
+ return this.spec.ignoreMutation ? this.spec.ignoreMutation(mutation) : super.ignoreMutation(mutation);
580
+ }
581
+ destroy() {
582
+ if (this.spec.destroy) this.spec.destroy();
583
+ super.destroy();
584
+ }
585
+ }
586
+ // Node view descs are the main, most common type of view desc, and
587
+ // correspond to an actual node in the document. Unlike mark descs,
588
+ // they populate their child array themselves.
589
+ export class NodeViewDesc extends ViewDesc {
590
+ node;
591
+ outerDeco;
592
+ innerDeco;
593
+ nodeDOM;
594
+ constructor(parent, children, getPos, node, outerDeco, innerDeco, dom, contentDOM, nodeDOM){
595
+ super(parent, children, getPos, dom, contentDOM), this.node = node, this.outerDeco = outerDeco, this.innerDeco = innerDeco, this.nodeDOM = nodeDOM;
596
+ }
597
+ parseRule(addedNodes) {
598
+ // Experimental kludge to allow opt-in re-parsing of nodes
599
+ if (this.node.type.spec.reparseInView) return null;
600
+ // FIXME the assumption that this can always return the current
601
+ // attrs means that if the user somehow manages to change the
602
+ // attrs in the dom, that won't be picked up. Not entirely sure
603
+ // whether this is a problem
604
+ const rule = {
605
+ node: this.node.type.name,
606
+ attrs: this.node.attrs
607
+ };
608
+ if (this.node.type.whitespace == "pre") rule.preserveWhitespace = "full";
609
+ if (!this.contentDOM) {
610
+ rule.getContent = ()=>this.node.content;
611
+ } else if (!this.contentLost) {
612
+ rule.contentElement = this.contentDOM;
613
+ } else {
614
+ // Chrome likes to randomly recreate parent nodes when
615
+ // backspacing things. When that happens, this tries to find the
616
+ // new parent.
617
+ for(let i = this.children.length - 1; i >= 0; i--){
618
+ const child = this.children[i];
619
+ // @ts-expect-error ...
620
+ if (this.dom.contains(child.dom.parentNode)) {
621
+ // @ts-expect-error ...
622
+ rule.contentElement = child.dom.parentNode;
623
+ break;
624
+ }
625
+ }
626
+ if (!rule.contentElement) {
627
+ const found = addedNodes && addedNodes.find((n)=>n.nodeType == 1 && addedNodes.indexOf(n.parentNode) < 0 && this.dom.contains(n));
628
+ if (found) rule.contentElement = found;
629
+ else rule.getContent = ()=>Fragment.empty;
630
+ }
631
+ }
632
+ return rule;
633
+ }
634
+ matchesNode(node, outerDeco, innerDeco) {
635
+ return this.dirty == NOT_DIRTY && node.eq(this.node) && sameOuterDeco(outerDeco, this.outerDeco) && innerDeco.eq(this.innerDeco);
636
+ }
637
+ get size() {
638
+ return this.node.nodeSize;
639
+ }
640
+ get border() {
641
+ return this.node.isLeaf ? 0 : 1;
642
+ }
643
+ updateChildren(_view, _pos) {
644
+ // Omitted to avoid reproducing lots of unused code.
645
+ // Overidden elsewhere in case this is ever vendored.
646
+ }
647
+ // If this desc must be updated to match the given node decoration,
648
+ // do so and return true.
649
+ update(node, outerDeco, innerDeco, view) {
650
+ if (this.dirty == NODE_DIRTY || !node.sameMarkup(this.node)) return false;
651
+ this.updateInner(node, outerDeco, innerDeco, view);
652
+ return true;
653
+ }
654
+ updateInner(node, outerDeco, innerDeco, view) {
655
+ this.updateOuterDeco(outerDeco);
656
+ this.node = node;
657
+ this.innerDeco = innerDeco;
658
+ if (this.contentDOM) this.updateChildren(view, this.posAtStart);
659
+ this.dirty = NOT_DIRTY;
660
+ }
661
+ updateOuterDeco(outerDeco) {
662
+ this.outerDeco = outerDeco;
663
+ }
664
+ // Mark this node as being the selected node.
665
+ selectNode() {
666
+ if (this.nodeDOM.nodeType == 1) this.nodeDOM.classList.add("ProseMirror-selectednode");
667
+ if (this.contentDOM || !this.node.type.spec.draggable) this.dom.draggable = true;
668
+ }
669
+ // Remove selected node marking from this node.
670
+ deselectNode() {
671
+ if (this.nodeDOM.nodeType == 1) {
672
+ this.nodeDOM.classList.remove("ProseMirror-selectednode");
673
+ if (this.contentDOM || !this.node.type.spec.draggable) this.dom.removeAttribute("draggable");
674
+ }
675
+ }
676
+ get domAtom() {
677
+ return this.node.isAtom;
678
+ }
679
+ }
680
+ export class TextViewDesc extends NodeViewDesc {
681
+ constructor(parent, children, getPos, node, outerDeco, innerDeco, dom, nodeDOM){
682
+ super(parent, children, getPos, node, outerDeco, innerDeco, dom, null, nodeDOM);
683
+ }
684
+ parseRule() {
685
+ let skip = this.nodeDOM.parentNode;
686
+ while(skip && skip != this.dom && !skip.pmIsDeco)skip = skip.parentNode;
687
+ return {
688
+ skip: skip || true
689
+ };
690
+ }
691
+ update(node, outerDeco, _innerDeco, _view) {
692
+ if (this.dirty == NODE_DIRTY || this.dirty != NOT_DIRTY && !this.inParent() || !node.sameMarkup(this.node)) return false;
693
+ this.updateOuterDeco(outerDeco);
694
+ this.node = node;
695
+ this.dirty = NOT_DIRTY;
696
+ return true;
697
+ }
698
+ inParent() {
699
+ const parentDOM = this.parent.contentDOM;
700
+ for(let n = this.nodeDOM; n; n = n.parentNode)if (n == parentDOM) return true;
701
+ return false;
702
+ }
703
+ domFromPos(pos) {
704
+ return {
705
+ node: this.nodeDOM,
706
+ offset: pos
707
+ };
708
+ }
709
+ localPosFromDOM(dom, offset, bias) {
710
+ if (dom == this.nodeDOM) return this.posAtStart + Math.min(offset, this.node.text.length);
711
+ return super.localPosFromDOM(dom, offset, bias);
712
+ }
713
+ markDirty(from, to) {
714
+ super.markDirty(from, to);
715
+ if (this.dom != this.nodeDOM && (from == 0 || to == this.nodeDOM.nodeValue.length)) this.dirty = NODE_DIRTY;
716
+ }
717
+ get domAtom() {
718
+ return false;
719
+ }
720
+ isText(text) {
721
+ return this.node.text == text;
722
+ }
723
+ ignoreMutation(mutation) {
724
+ return mutation.type !== "characterData" && mutation.type !== "selection";
725
+ }
726
+ }
727
+ // A dummy desc used to tag trailing BR or IMG nodes created to work
728
+ // around contentEditable terribleness.
729
+ export class TrailingHackViewDesc extends ViewDesc {
730
+ parseRule() {
731
+ return {
732
+ ignore: true
733
+ };
734
+ }
735
+ matchesHack(nodeName) {
736
+ return this.dirty == NOT_DIRTY && this.dom.nodeName == nodeName;
737
+ }
738
+ get domAtom() {
739
+ return true;
740
+ }
741
+ get ignoreForCoords() {
742
+ return this.dom.nodeName == "IMG";
743
+ }
744
+ }
745
+ // A separate subclass is used for customized node views, so that the
746
+ // extra checks only have to be made for nodes that are actually
747
+ // customized.
748
+ let CustomNodeViewDesc = class CustomNodeViewDesc extends NodeViewDesc {
749
+ spec;
750
+ constructor(parent, children, getPos, node, outerDeco, innerDeco, dom, contentDOM, nodeDOM, spec){
751
+ super(parent, children, getPos, node, outerDeco, innerDeco, dom, contentDOM, nodeDOM), this.spec = spec;
752
+ }
753
+ // A custom `update` method gets to decide whether the update goes
754
+ // through. If it does, and there's a `contentDOM` node, our logic
755
+ // updates the children.
756
+ update(node, outerDeco, innerDeco, view) {
757
+ if (this.dirty == NODE_DIRTY) return false;
758
+ if (this.spec.update && (this.node.type == node.type || this.spec.multiType)) {
759
+ const result = this.spec.update(node, outerDeco, innerDeco);
760
+ if (result) this.updateInner(node, outerDeco, innerDeco, view);
761
+ return result;
762
+ } else if (!this.contentDOM && !node.isLeaf) {
763
+ return false;
764
+ } else {
765
+ return super.update(node, outerDeco, innerDeco, view);
766
+ }
767
+ }
768
+ selectNode() {
769
+ this.spec.selectNode ? this.spec.selectNode.call(this) : super.selectNode();
770
+ }
771
+ deselectNode() {
772
+ this.spec.deselectNode ? this.spec.deselectNode.call(this) : super.deselectNode();
773
+ }
774
+ setSelection(anchor, head, view, force) {
775
+ this.spec.setSelection ? this.spec.setSelection.call(this, anchor, head, view.root) : super.setSelection(anchor, head, view, force);
776
+ }
777
+ destroy() {
778
+ if (this.spec.destroy) this.spec.destroy();
779
+ super.destroy();
780
+ }
781
+ stopEvent(event) {
782
+ return this.spec.stopEvent ? this.spec.stopEvent(event) : false;
783
+ }
784
+ ignoreMutation(mutation) {
785
+ return this.spec.ignoreMutation ? this.spec.ignoreMutation(mutation) : super.ignoreMutation(mutation);
786
+ }
787
+ };
788
+ export class ReactMarkViewDesc extends MarkViewDesc {
789
+ destroy() {
790
+ // React has already destroyed the children (if needed).
791
+ this.children = [];
792
+ super.destroy();
793
+ }
794
+ }
795
+ export class ReactNodeViewDesc extends CustomNodeViewDesc {
796
+ updateChildren(_view, _pos) {
797
+ // React has already updated the children.
798
+ }
799
+ updateOuterDeco(outerDeco) {
800
+ // React has already updated the decorations.
801
+ this.outerDeco = outerDeco;
802
+ }
803
+ destroy() {
804
+ // React has already destroyed the children (if needed).
805
+ this.children = [];
806
+ super.destroy();
807
+ }
808
+ }
809
+ export function sameOuterDeco(a, b) {
810
+ if (a.length != b.length) return false;
811
+ // @ts-expect-error ...
812
+ for(let i = 0; i < a.length; i++)if (!a[i].type.eq(b[i].type)) return false;
813
+ return true;
814
+ }
815
+ // Find a piece of text in an inline fragment, overlapping from-to.
816
+ // Ported from prosemirror-view's findTextInFragment.
817
+ export function findTextInFragment(frag, text, from, to) {
818
+ for(let i = 0, pos = 0; i < frag.childCount && pos <= to;){
819
+ const child = frag.child(i++);
820
+ const childStart = pos;
821
+ pos += child.nodeSize;
822
+ if (!child.isText) continue;
823
+ let str = child.text;
824
+ while(i < frag.childCount){
825
+ const next = frag.child(i++);
826
+ pos += next.nodeSize;
827
+ if (!next.isText) break;
828
+ str += next.text;
829
+ }
830
+ if (pos >= from) {
831
+ if (pos >= to && str.slice(to - text.length - childStart, to - childStart) === text) {
832
+ return to - text.length;
833
+ }
834
+ const found = childStart < to ? str.lastIndexOf(text, to - childStart - 1) : -1;
835
+ if (found >= 0 && found + text.length + childStart >= from) {
836
+ return childStart + found;
837
+ }
838
+ if (from === to && str.length >= to + text.length - childStart && str.slice(to - childStart, to - childStart + text.length) === text) {
839
+ return to;
840
+ }
841
+ }
842
+ }
843
+ return -1;
844
+ }