@portabletext/editor 3.3.2 → 3.3.4

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 (307) hide show
  1. package/lib/_chunks-dts/index.d.ts +7 -1
  2. package/package.json +16 -19
  3. package/src/behaviors/_exports/index.ts +0 -1
  4. package/src/behaviors/behavior.abstract.annotation.ts +0 -77
  5. package/src/behaviors/behavior.abstract.decorator.ts +0 -39
  6. package/src/behaviors/behavior.abstract.delete.ts +0 -273
  7. package/src/behaviors/behavior.abstract.deserialize.ts +0 -232
  8. package/src/behaviors/behavior.abstract.insert.ts +0 -525
  9. package/src/behaviors/behavior.abstract.keyboard.ts +0 -189
  10. package/src/behaviors/behavior.abstract.list-item.ts +0 -70
  11. package/src/behaviors/behavior.abstract.move.ts +0 -79
  12. package/src/behaviors/behavior.abstract.select.ts +0 -118
  13. package/src/behaviors/behavior.abstract.serialize.ts +0 -96
  14. package/src/behaviors/behavior.abstract.split.ts +0 -170
  15. package/src/behaviors/behavior.abstract.style.ts +0 -55
  16. package/src/behaviors/behavior.abstract.ts +0 -139
  17. package/src/behaviors/behavior.config.ts +0 -7
  18. package/src/behaviors/behavior.core.annotations.ts +0 -62
  19. package/src/behaviors/behavior.core.block-element.ts +0 -116
  20. package/src/behaviors/behavior.core.block-objects.ts +0 -285
  21. package/src/behaviors/behavior.core.decorators.ts +0 -44
  22. package/src/behaviors/behavior.core.dnd.ts +0 -356
  23. package/src/behaviors/behavior.core.insert-break.ts +0 -266
  24. package/src/behaviors/behavior.core.insert.ts +0 -52
  25. package/src/behaviors/behavior.core.lists.ts +0 -691
  26. package/src/behaviors/behavior.core.ts +0 -44
  27. package/src/behaviors/behavior.perform-event.ts +0 -354
  28. package/src/behaviors/behavior.types.action.ts +0 -102
  29. package/src/behaviors/behavior.types.behavior.ts +0 -83
  30. package/src/behaviors/behavior.types.event.ts +0 -667
  31. package/src/behaviors/behavior.types.guard.ts +0 -11
  32. package/src/behaviors/index.ts +0 -17
  33. package/src/converters/converter.json.ts +0 -53
  34. package/src/converters/converter.portable-text.deserialize.test.ts +0 -680
  35. package/src/converters/converter.portable-text.ts +0 -75
  36. package/src/converters/converter.text-html.deserialize.test.ts +0 -406
  37. package/src/converters/converter.text-html.serialize.test.ts +0 -246
  38. package/src/converters/converter.text-html.ts +0 -87
  39. package/src/converters/converter.text-markdown.ts +0 -67
  40. package/src/converters/converter.text-plain.test.ts +0 -245
  41. package/src/converters/converter.text-plain.ts +0 -126
  42. package/src/converters/converter.types.ts +0 -72
  43. package/src/converters/converters.core.ts +0 -18
  44. package/src/editor/Editable.tsx +0 -1012
  45. package/src/editor/PortableTextEditor.tsx +0 -791
  46. package/src/editor/components/drop-indicator.tsx +0 -17
  47. package/src/editor/components/render-block-object.tsx +0 -121
  48. package/src/editor/components/render-default-object.tsx +0 -21
  49. package/src/editor/components/render-element.tsx +0 -88
  50. package/src/editor/components/render-inline-object.tsx +0 -129
  51. package/src/editor/components/render-leaf.tsx +0 -64
  52. package/src/editor/components/render-span.tsx +0 -303
  53. package/src/editor/components/render-text-block.tsx +0 -265
  54. package/src/editor/components/render-text.tsx +0 -18
  55. package/src/editor/components/use-core-block-element-behaviors.ts +0 -39
  56. package/src/editor/create-editor.ts +0 -323
  57. package/src/editor/create-slate-editor.tsx +0 -64
  58. package/src/editor/editor-actor-context.ts +0 -4
  59. package/src/editor/editor-context.tsx +0 -7
  60. package/src/editor/editor-dom.ts +0 -220
  61. package/src/editor/editor-machine.ts +0 -751
  62. package/src/editor/editor-provider.tsx +0 -111
  63. package/src/editor/editor-schema.ts +0 -6
  64. package/src/editor/editor-selector.ts +0 -89
  65. package/src/editor/editor-snapshot.ts +0 -68
  66. package/src/editor/event-to-change.tsx +0 -49
  67. package/src/editor/hooks/usePortableTextEditor.ts +0 -25
  68. package/src/editor/hooks/usePortableTextEditorSelection.tsx +0 -28
  69. package/src/editor/mutation-machine.ts +0 -322
  70. package/src/editor/plugins/create-with-event-listeners.ts +0 -271
  71. package/src/editor/plugins/createWithEditableAPI.ts +0 -529
  72. package/src/editor/plugins/createWithHotKeys.ts +0 -68
  73. package/src/editor/plugins/createWithObjectKeys.ts +0 -289
  74. package/src/editor/plugins/createWithPatches.ts +0 -272
  75. package/src/editor/plugins/createWithPortableTextMarkModel.ts +0 -559
  76. package/src/editor/plugins/createWithSchemaTypes.ts +0 -121
  77. package/src/editor/plugins/slate-plugin.update-selection.ts +0 -51
  78. package/src/editor/plugins/slate-plugin.update-value.ts +0 -46
  79. package/src/editor/plugins/with-plugins.ts +0 -69
  80. package/src/editor/range-decorations-machine.ts +0 -421
  81. package/src/editor/relay-actor-context.ts +0 -4
  82. package/src/editor/relay-machine.ts +0 -152
  83. package/src/editor/sync-machine.ts +0 -961
  84. package/src/editor/use-editor.ts +0 -27
  85. package/src/editor/validate-selection-machine.test.ts +0 -47
  86. package/src/editor/validate-selection-machine.ts +0 -149
  87. package/src/editor/weakMaps.ts +0 -15
  88. package/src/editor/with-normalizing-node.ts +0 -14
  89. package/src/editor/with-performing-behavior-operation.ts +0 -21
  90. package/src/editor/withChanges.ts +0 -13
  91. package/src/editor/without-normalizing-conditional.ts +0 -13
  92. package/src/editor/withoutPatching.ts +0 -14
  93. package/src/editor.ts +0 -59
  94. package/src/history/behavior.operation.history.redo.ts +0 -67
  95. package/src/history/behavior.operation.history.undo.ts +0 -71
  96. package/src/history/event.history.undo.test.tsx +0 -672
  97. package/src/history/history.preserving-keys.test.tsx +0 -112
  98. package/src/history/remote-patches.ts +0 -20
  99. package/src/history/slate-plugin.history.ts +0 -142
  100. package/src/history/slate-plugin.redoing.ts +0 -21
  101. package/src/history/slate-plugin.undoing.ts +0 -21
  102. package/src/history/slate-plugin.without-history.ts +0 -23
  103. package/src/history/transform-operation.ts +0 -245
  104. package/src/history/undo-redo-collaboration.test.tsx +0 -541
  105. package/src/history/undo-redo.feature +0 -125
  106. package/src/history/undo-redo.test.tsx +0 -195
  107. package/src/history/undo-step.ts +0 -148
  108. package/src/index.ts +0 -98
  109. package/src/internal-utils/__tests__/ranges.test.ts +0 -23
  110. package/src/internal-utils/__tests__/values.test.ts +0 -110
  111. package/src/internal-utils/apply-operation-to-portable-text.test.ts +0 -1861
  112. package/src/internal-utils/apply-operation-to-portable-text.ts +0 -615
  113. package/src/internal-utils/applyPatch.ts +0 -644
  114. package/src/internal-utils/block-keys.ts +0 -9
  115. package/src/internal-utils/build-index-maps.test.ts +0 -464
  116. package/src/internal-utils/build-index-maps.ts +0 -131
  117. package/src/internal-utils/collapse-selection.ts +0 -36
  118. package/src/internal-utils/compound-client-rect.ts +0 -28
  119. package/src/internal-utils/create-placeholder-block.ts +0 -21
  120. package/src/internal-utils/create-test-snapshot.ts +0 -28
  121. package/src/internal-utils/debug.ts +0 -12
  122. package/src/internal-utils/editor-selection.test.ts +0 -44
  123. package/src/internal-utils/editor-selection.ts +0 -56
  124. package/src/internal-utils/event-position.ts +0 -318
  125. package/src/internal-utils/global-scope.ts +0 -27
  126. package/src/internal-utils/globally-scoped-context.ts +0 -39
  127. package/src/internal-utils/is-hotkey.test.ts +0 -114
  128. package/src/internal-utils/is-hotkey.ts +0 -209
  129. package/src/internal-utils/mime-type.ts +0 -1
  130. package/src/internal-utils/move-range-by-operation.ts +0 -19
  131. package/src/internal-utils/operation-to-patches.test.ts +0 -522
  132. package/src/internal-utils/operation-to-patches.ts +0 -571
  133. package/src/internal-utils/portable-text-node.ts +0 -209
  134. package/src/internal-utils/schema.ts +0 -8
  135. package/src/internal-utils/selection-block-keys.ts +0 -20
  136. package/src/internal-utils/selection-focus-text.ts +0 -40
  137. package/src/internal-utils/selection-text.test.ts +0 -32
  138. package/src/internal-utils/selection-text.ts +0 -21
  139. package/src/internal-utils/selection.ts +0 -77
  140. package/src/internal-utils/sibling-utils.ts +0 -55
  141. package/src/internal-utils/slate-utils.test.tsx +0 -121
  142. package/src/internal-utils/slate-utils.ts +0 -417
  143. package/src/internal-utils/split-string.ts +0 -12
  144. package/src/internal-utils/stop-actor.ts +0 -43
  145. package/src/internal-utils/string-overlap.test.ts +0 -14
  146. package/src/internal-utils/string-overlap.ts +0 -28
  147. package/src/internal-utils/string-utils.ts +0 -7
  148. package/src/internal-utils/text-block-key.test.ts +0 -41
  149. package/src/internal-utils/text-block-key.ts +0 -26
  150. package/src/internal-utils/text-marks.test.ts +0 -41
  151. package/src/internal-utils/text-marks.ts +0 -22
  152. package/src/internal-utils/text-selection.test.ts +0 -211
  153. package/src/internal-utils/text-selection.ts +0 -121
  154. package/src/internal-utils/to-slate-range.test.ts +0 -278
  155. package/src/internal-utils/to-slate-range.ts +0 -171
  156. package/src/internal-utils/validateValue.ts +0 -443
  157. package/src/internal-utils/value-annotations.ts +0 -33
  158. package/src/internal-utils/values.test.ts +0 -282
  159. package/src/internal-utils/values.ts +0 -266
  160. package/src/keyboard-shortcuts/default-keyboard-shortcuts.ts +0 -146
  161. package/src/operations/behavior.operation.annotation.add.ts +0 -99
  162. package/src/operations/behavior.operation.annotation.remove.ts +0 -150
  163. package/src/operations/behavior.operation.block.set.ts +0 -104
  164. package/src/operations/behavior.operation.block.unset.ts +0 -54
  165. package/src/operations/behavior.operation.child.set.ts +0 -107
  166. package/src/operations/behavior.operation.child.unset.ts +0 -116
  167. package/src/operations/behavior.operation.decorator.add.ts +0 -131
  168. package/src/operations/behavior.operation.delete.ts +0 -294
  169. package/src/operations/behavior.operation.insert.block.ts +0 -495
  170. package/src/operations/behavior.operation.insert.child.ts +0 -129
  171. package/src/operations/behavior.operation.insert.text.ts +0 -8
  172. package/src/operations/behavior.operation.move.backward.ts +0 -12
  173. package/src/operations/behavior.operation.move.block.ts +0 -44
  174. package/src/operations/behavior.operation.move.forward.ts +0 -11
  175. package/src/operations/behavior.operation.select.ts +0 -27
  176. package/src/operations/behavior.operations.ts +0 -221
  177. package/src/plugins/_exports/index.ts +0 -1
  178. package/src/plugins/index.ts +0 -3
  179. package/src/plugins/plugin.behavior.tsx +0 -24
  180. package/src/plugins/plugin.editor-ref.tsx +0 -17
  181. package/src/plugins/plugin.event-listener.tsx +0 -68
  182. package/src/plugins/plugin.internal.auto-close-brackets.test.tsx +0 -71
  183. package/src/plugins/plugin.internal.auto-close-brackets.ts +0 -62
  184. package/src/plugins/plugin.internal.change-ref.tsx +0 -19
  185. package/src/plugins/plugin.internal.portable-text-editor-ref.tsx +0 -16
  186. package/src/plugins/plugin.internal.slate-editor-ref.tsx +0 -15
  187. package/src/priority/priority.core.ts +0 -3
  188. package/src/priority/priority.sort.test.ts +0 -319
  189. package/src/priority/priority.sort.ts +0 -123
  190. package/src/priority/priority.types.ts +0 -24
  191. package/src/selectors/_exports/index.ts +0 -1
  192. package/src/selectors/drag-selection.test.ts +0 -578
  193. package/src/selectors/drag-selection.ts +0 -118
  194. package/src/selectors/index.ts +0 -54
  195. package/src/selectors/selector.get-active-annotation-marks.ts +0 -12
  196. package/src/selectors/selector.get-active-annotations.ts +0 -36
  197. package/src/selectors/selector.get-active-decorators.ts +0 -29
  198. package/src/selectors/selector.get-active-list-item.ts +0 -38
  199. package/src/selectors/selector.get-active-style.ts +0 -38
  200. package/src/selectors/selector.get-anchor-block.ts +0 -22
  201. package/src/selectors/selector.get-anchor-child.ts +0 -36
  202. package/src/selectors/selector.get-anchor-span.ts +0 -17
  203. package/src/selectors/selector.get-anchor-text-block.ts +0 -18
  204. package/src/selectors/selector.get-block-offsets.ts +0 -34
  205. package/src/selectors/selector.get-caret-word-selection.test.ts +0 -284
  206. package/src/selectors/selector.get-caret-word-selection.ts +0 -134
  207. package/src/selectors/selector.get-first-block.ts +0 -14
  208. package/src/selectors/selector.get-focus-block-object.ts +0 -18
  209. package/src/selectors/selector.get-focus-block.ts +0 -23
  210. package/src/selectors/selector.get-focus-child.ts +0 -36
  211. package/src/selectors/selector.get-focus-inline-object.ts +0 -17
  212. package/src/selectors/selector.get-focus-list-block.ts +0 -18
  213. package/src/selectors/selector.get-focus-span.ts +0 -18
  214. package/src/selectors/selector.get-focus-text-block.ts +0 -18
  215. package/src/selectors/selector.get-last-block.ts +0 -16
  216. package/src/selectors/selector.get-mark-state.test.ts +0 -325
  217. package/src/selectors/selector.get-mark-state.ts +0 -263
  218. package/src/selectors/selector.get-next-block.ts +0 -29
  219. package/src/selectors/selector.get-next-inline-object.ts +0 -53
  220. package/src/selectors/selector.get-next-inline-objects.ts +0 -50
  221. package/src/selectors/selector.get-next-span.ts +0 -56
  222. package/src/selectors/selector.get-previous-block.ts +0 -29
  223. package/src/selectors/selector.get-previous-inline-object.ts +0 -50
  224. package/src/selectors/selector.get-previous-inline-objects.ts +0 -47
  225. package/src/selectors/selector.get-previous-span.ts +0 -53
  226. package/src/selectors/selector.get-selected-blocks.ts +0 -61
  227. package/src/selectors/selector.get-selected-spans.test.ts +0 -347
  228. package/src/selectors/selector.get-selected-spans.ts +0 -155
  229. package/src/selectors/selector.get-selected-text-blocks.ts +0 -73
  230. package/src/selectors/selector.get-selected-value.test.ts +0 -834
  231. package/src/selectors/selector.get-selected-value.ts +0 -66
  232. package/src/selectors/selector.get-selection-end-block.ts +0 -33
  233. package/src/selectors/selector.get-selection-end-child.ts +0 -33
  234. package/src/selectors/selector.get-selection-end-point.ts +0 -17
  235. package/src/selectors/selector.get-selection-start-block.ts +0 -33
  236. package/src/selectors/selector.get-selection-start-child.ts +0 -33
  237. package/src/selectors/selector.get-selection-start-point.ts +0 -17
  238. package/src/selectors/selector.get-selection-text.test.ts +0 -421
  239. package/src/selectors/selector.get-selection-text.ts +0 -27
  240. package/src/selectors/selector.get-selection.ts +0 -9
  241. package/src/selectors/selector.get-text-after.ts +0 -46
  242. package/src/selectors/selector.get-text-before.ts +0 -46
  243. package/src/selectors/selector.get-value.ts +0 -11
  244. package/src/selectors/selector.is-active-annotation.test.ts +0 -320
  245. package/src/selectors/selector.is-active-annotation.ts +0 -52
  246. package/src/selectors/selector.is-active-decorator.test.ts +0 -136
  247. package/src/selectors/selector.is-active-decorator.ts +0 -24
  248. package/src/selectors/selector.is-active-list-item.ts +0 -13
  249. package/src/selectors/selector.is-active-style.ts +0 -13
  250. package/src/selectors/selector.is-at-the-end-of-block.ts +0 -30
  251. package/src/selectors/selector.is-at-the-start-of-block.ts +0 -30
  252. package/src/selectors/selector.is-overlapping-selection.test.ts +0 -304
  253. package/src/selectors/selector.is-overlapping-selection.ts +0 -181
  254. package/src/selectors/selector.is-point-after-selection.ts +0 -97
  255. package/src/selectors/selector.is-point-before-selection.ts +0 -97
  256. package/src/selectors/selector.is-selecting-entire-blocks.ts +0 -43
  257. package/src/selectors/selector.is-selection-collapsed.ts +0 -17
  258. package/src/selectors/selector.is-selection-expanded.test.ts +0 -63
  259. package/src/selectors/selector.is-selection-expanded.ts +0 -9
  260. package/src/test/_exports/index.ts +0 -1
  261. package/src/test/gherkin-parameter-types.ts +0 -112
  262. package/src/test/index.ts +0 -1
  263. package/src/test/vitest/_exports/index.ts +0 -1
  264. package/src/test/vitest/index.ts +0 -3
  265. package/src/test/vitest/step-context.ts +0 -13
  266. package/src/test/vitest/step-definitions.tsx +0 -960
  267. package/src/test/vitest/test-editor.tsx +0 -198
  268. package/src/type-utils.ts +0 -29
  269. package/src/types/block-offset.ts +0 -9
  270. package/src/types/block-with-optional-key.ts +0 -25
  271. package/src/types/editor.ts +0 -509
  272. package/src/types/options.ts +0 -13
  273. package/src/types/paths.ts +0 -35
  274. package/src/types/slate-editor.ts +0 -50
  275. package/src/types/slate.ts +0 -27
  276. package/src/utils/_exports/index.ts +0 -1
  277. package/src/utils/asserters.ts +0 -9
  278. package/src/utils/index.ts +0 -24
  279. package/src/utils/key-generator.ts +0 -33
  280. package/src/utils/parse-blocks.test.ts +0 -836
  281. package/src/utils/parse-blocks.ts +0 -504
  282. package/src/utils/util.at-the-beginning-of-block.ts +0 -32
  283. package/src/utils/util.block-offset-to-block-selection-point.ts +0 -28
  284. package/src/utils/util.block-offset-to-selection-point.ts +0 -33
  285. package/src/utils/util.block-offset.test.ts +0 -375
  286. package/src/utils/util.block-offset.ts +0 -136
  287. package/src/utils/util.block-offsets-to-selection.ts +0 -38
  288. package/src/utils/util.child-selection-point-to-block-offset.ts +0 -51
  289. package/src/utils/util.get-block-end-point.ts +0 -35
  290. package/src/utils/util.get-block-start-point.ts +0 -31
  291. package/src/utils/util.get-selection-end-point.ts +0 -20
  292. package/src/utils/util.get-selection-start-point.ts +0 -20
  293. package/src/utils/util.get-text-block-text.ts +0 -8
  294. package/src/utils/util.is-empty-text-block.ts +0 -21
  295. package/src/utils/util.is-equal-selection-points.ts +0 -13
  296. package/src/utils/util.is-equal-selections.ts +0 -20
  297. package/src/utils/util.is-keyed-segment.ts +0 -8
  298. package/src/utils/util.is-selection-collapsed.ts +0 -16
  299. package/src/utils/util.is-selection-expanded.ts +0 -13
  300. package/src/utils/util.merge-text-blocks.ts +0 -40
  301. package/src/utils/util.reverse-selection.ts +0 -26
  302. package/src/utils/util.selection-point-to-block-offset.ts +0 -30
  303. package/src/utils/util.selection-point.ts +0 -22
  304. package/src/utils/util.slice-blocks.ts +0 -221
  305. package/src/utils/util.slice-text-block.test.ts +0 -190
  306. package/src/utils/util.slice-text-block.ts +0 -89
  307. package/src/utils/util.split-text-block.ts +0 -54
@@ -1,559 +0,0 @@
1
- /**
2
- *
3
- * This plugin will change Slate's default marks model (every prop is a mark) with the Portable Text model (marks is an array of strings on prop .marks).
4
- *
5
- */
6
-
7
- import {isTextBlock} from '@portabletext/schema'
8
- import type {PortableTextObject, PortableTextSpan} from '@sanity/types'
9
- import {isEqual, uniq} from 'lodash'
10
- import {Editor, Element, Node, Path, Range, Text, Transforms} from 'slate'
11
- import {isRedoing} from '../../history/slate-plugin.redoing'
12
- import {isUndoing} from '../../history/slate-plugin.undoing'
13
- import {createPlaceholderBlock} from '../../internal-utils/create-placeholder-block'
14
- import {debugWithName} from '../../internal-utils/debug'
15
- import {getNextSpan, getPreviousSpan} from '../../internal-utils/sibling-utils'
16
- import type {BehaviorOperationImplementation} from '../../operations/behavior.operations'
17
- import {getActiveDecorators} from '../../selectors/selector.get-active-decorators'
18
- import type {PortableTextSlateEditor} from '../../types/slate-editor'
19
- import type {EditorActor} from '../editor-machine'
20
- import {getEditorSnapshot} from '../editor-selector'
21
- import {withNormalizeNode} from '../with-normalizing-node'
22
- import {isChangingRemotely} from '../withChanges'
23
- import {withoutPatching} from '../withoutPatching'
24
-
25
- const debug = debugWithName('plugin:withPortableTextMarkModel')
26
-
27
- export function createWithPortableTextMarkModel(
28
- editorActor: EditorActor,
29
- ): (editor: PortableTextSlateEditor) => PortableTextSlateEditor {
30
- return function withPortableTextMarkModel(editor: PortableTextSlateEditor) {
31
- const {apply, normalizeNode} = editor
32
- const decorators = editorActor
33
- .getSnapshot()
34
- .context.schema.decorators.map((t) => t.name)
35
- const defaultStyle = editorActor
36
- .getSnapshot()
37
- .context.schema.styles.at(0)?.name
38
-
39
- // Extend Slate's default normalization. Merge spans with same set of .marks when doing merge_node operations, and clean up markDefs / marks
40
- editor.normalizeNode = (nodeEntry) => {
41
- const [node, path] = nodeEntry
42
-
43
- if (Editor.isEditor(node) && node.children.length === 0) {
44
- withoutPatching(editor, () => {
45
- withNormalizeNode(editor, () => {
46
- Transforms.insertNodes(
47
- editor,
48
- createPlaceholderBlock(editorActor.getSnapshot().context),
49
- {at: [0], select: true},
50
- )
51
- })
52
- })
53
- }
54
-
55
- if (editor.isTextBlock(node)) {
56
- const children = Node.children(editor, path)
57
-
58
- for (const [child, childPath] of children) {
59
- const nextNode = node.children[childPath[1] + 1]
60
-
61
- if (
62
- editor.isTextSpan(child) &&
63
- editor.isTextSpan(nextNode) &&
64
- child.marks?.every((mark) => nextNode.marks?.includes(mark)) &&
65
- nextNode.marks?.every((mark) => child.marks?.includes(mark))
66
- ) {
67
- debug(
68
- 'Merging spans',
69
- JSON.stringify(child, null, 2),
70
- JSON.stringify(nextNode, null, 2),
71
- )
72
- withNormalizeNode(editor, () => {
73
- Transforms.mergeNodes(editor, {
74
- at: [childPath[0], childPath[1] + 1],
75
- voids: true,
76
- })
77
- })
78
- return
79
- }
80
- }
81
- }
82
-
83
- /**
84
- * Add missing .markDefs to block nodes
85
- */
86
- if (editor.isTextBlock(node) && !Array.isArray(node.markDefs)) {
87
- debug('Adding .markDefs to block node')
88
- withNormalizeNode(editor, () => {
89
- Transforms.setNodes(editor, {markDefs: []}, {at: path})
90
- })
91
- return
92
- }
93
-
94
- /**
95
- * Add missing .style to block nodes
96
- */
97
- if (
98
- defaultStyle &&
99
- editor.isTextBlock(node) &&
100
- typeof node.style === 'undefined'
101
- ) {
102
- debug('Adding .style to block node')
103
-
104
- withNormalizeNode(editor, () => {
105
- Transforms.setNodes(editor, {style: defaultStyle}, {at: path})
106
- })
107
- return
108
- }
109
-
110
- /**
111
- * Add missing .marks to span nodes
112
- */
113
- if (editor.isTextSpan(node) && !Array.isArray(node.marks)) {
114
- debug('Adding .marks to span node')
115
- withNormalizeNode(editor, () => {
116
- Transforms.setNodes(editor, {marks: []}, {at: path})
117
- })
118
- return
119
- }
120
-
121
- /**
122
- * Remove annotations from empty spans
123
- */
124
- if (editor.isTextSpan(node)) {
125
- const blockPath = Path.parent(path)
126
- const [block] = Editor.node(editor, blockPath)
127
- const decorators = editorActor
128
- .getSnapshot()
129
- .context.schema.decorators.map((decorator) => decorator.name)
130
- const annotations = node.marks?.filter(
131
- (mark) => !decorators.includes(mark),
132
- )
133
-
134
- if (editor.isTextBlock(block)) {
135
- if (node.text === '' && annotations && annotations.length > 0) {
136
- debug('Removing annotations from empty span node')
137
- withNormalizeNode(editor, () => {
138
- Transforms.setNodes(
139
- editor,
140
- {
141
- marks: node.marks?.filter((mark) =>
142
- decorators.includes(mark),
143
- ),
144
- },
145
- {at: path},
146
- )
147
- })
148
- return
149
- }
150
- }
151
- }
152
-
153
- /**
154
- * Remove orphaned annotations from child spans of block nodes
155
- */
156
- if (editor.isTextBlock(node)) {
157
- const decorators = editorActor
158
- .getSnapshot()
159
- .context.schema.decorators.map((decorator) => decorator.name)
160
-
161
- for (const [child, childPath] of Node.children(editor, path)) {
162
- if (editor.isTextSpan(child)) {
163
- const marks = child.marks ?? []
164
- const orphanedAnnotations = marks.filter((mark) => {
165
- return (
166
- !decorators.includes(mark) &&
167
- !node.markDefs?.find((def) => def._key === mark)
168
- )
169
- })
170
-
171
- if (orphanedAnnotations.length > 0) {
172
- debug('Removing orphaned annotations from span node')
173
- withNormalizeNode(editor, () => {
174
- Transforms.setNodes(
175
- editor,
176
- {
177
- marks: marks.filter(
178
- (mark) => !orphanedAnnotations.includes(mark),
179
- ),
180
- },
181
- {at: childPath},
182
- )
183
- })
184
- return
185
- }
186
- }
187
- }
188
- }
189
-
190
- /**
191
- * Remove orphaned annotations from span nodes
192
- */
193
- if (editor.isTextSpan(node)) {
194
- const blockPath = Path.parent(path)
195
- const [block] = Editor.node(editor, blockPath)
196
-
197
- if (editor.isTextBlock(block)) {
198
- const decorators = editorActor
199
- .getSnapshot()
200
- .context.schema.decorators.map((decorator) => decorator.name)
201
- const marks = node.marks ?? []
202
- const orphanedAnnotations = marks.filter((mark) => {
203
- return (
204
- !decorators.includes(mark) &&
205
- !block.markDefs?.find((def) => def._key === mark)
206
- )
207
- })
208
-
209
- if (orphanedAnnotations.length > 0) {
210
- debug('Removing orphaned annotations from span node')
211
- withNormalizeNode(editor, () => {
212
- Transforms.setNodes(
213
- editor,
214
- {
215
- marks: marks.filter(
216
- (mark) => !orphanedAnnotations.includes(mark),
217
- ),
218
- },
219
- {at: path},
220
- )
221
- })
222
- return
223
- }
224
- }
225
- }
226
-
227
- // Remove duplicate markDefs
228
- if (editor.isTextBlock(node)) {
229
- const markDefs = node.markDefs ?? []
230
- const markDefKeys = new Set<string>()
231
- const newMarkDefs: Array<PortableTextObject> = []
232
-
233
- for (const markDef of markDefs) {
234
- if (!markDefKeys.has(markDef._key)) {
235
- markDefKeys.add(markDef._key)
236
- newMarkDefs.push(markDef)
237
- }
238
- }
239
-
240
- if (markDefs.length !== newMarkDefs.length) {
241
- debug('Removing duplicate markDefs')
242
- withNormalizeNode(editor, () => {
243
- Transforms.setNodes(editor, {markDefs: newMarkDefs}, {at: path})
244
- })
245
- return
246
- }
247
- }
248
-
249
- // Check consistency of markDefs (unless we are merging two nodes)
250
- if (
251
- editor.isTextBlock(node) &&
252
- !editor.operations.some(
253
- (op) =>
254
- op.type === 'merge_node' &&
255
- 'markDefs' in op.properties &&
256
- op.path.length === 1,
257
- )
258
- ) {
259
- const newMarkDefs = (node.markDefs || []).filter((def) => {
260
- return node.children.find((child) => {
261
- return (
262
- Text.isText(child) &&
263
- Array.isArray(child.marks) &&
264
- child.marks.includes(def._key)
265
- )
266
- })
267
- })
268
- if (node.markDefs && !isEqual(newMarkDefs, node.markDefs)) {
269
- debug('Removing markDef not in use')
270
- withNormalizeNode(editor, () => {
271
- Transforms.setNodes(
272
- editor,
273
- {
274
- markDefs: newMarkDefs,
275
- },
276
- {at: path},
277
- )
278
- })
279
- return
280
- }
281
- }
282
-
283
- withNormalizeNode(editor, () => {
284
- normalizeNode(nodeEntry)
285
- })
286
- }
287
-
288
- editor.apply = (op) => {
289
- /**
290
- * We don't want to run any side effects when the editor is processing
291
- * remote changes.
292
- */
293
- if (isChangingRemotely(editor)) {
294
- apply(op)
295
- return
296
- }
297
-
298
- /**
299
- * We don't want to run any side effects when the editor is undoing or
300
- * redoing operations.
301
- */
302
- if (isUndoing(editor) || isRedoing(editor)) {
303
- apply(op)
304
- return
305
- }
306
-
307
- if (op.type === 'set_selection') {
308
- if (
309
- op.properties &&
310
- op.newProperties &&
311
- op.properties.anchor &&
312
- op.properties.focus &&
313
- op.newProperties.anchor &&
314
- op.newProperties.focus
315
- ) {
316
- const previousSelectionIsCollapsed = Range.isCollapsed({
317
- anchor: op.properties.anchor,
318
- focus: op.properties.focus,
319
- })
320
- const newSelectionIsCollapsed = Range.isCollapsed({
321
- anchor: op.newProperties.anchor,
322
- focus: op.newProperties.focus,
323
- })
324
-
325
- if (previousSelectionIsCollapsed && newSelectionIsCollapsed) {
326
- const focusSpan: PortableTextSpan | undefined = Array.from(
327
- Editor.nodes(editor, {
328
- mode: 'lowest',
329
- at: op.properties.focus,
330
- match: (n) => editor.isTextSpan(n),
331
- voids: false,
332
- }),
333
- )[0]?.[0]
334
- const newFocusSpan: PortableTextSpan | undefined = Array.from(
335
- Editor.nodes(editor, {
336
- mode: 'lowest',
337
- at: op.newProperties.focus,
338
- match: (n) => editor.isTextSpan(n),
339
- voids: false,
340
- }),
341
- )[0]?.[0]
342
- const movedToNextSpan =
343
- focusSpan &&
344
- newFocusSpan &&
345
- op.newProperties.focus.path[0] === op.properties.focus.path[0] &&
346
- op.newProperties.focus.path[1] ===
347
- op.properties.focus.path[1] + 1 &&
348
- focusSpan.text.length === op.properties.focus.offset &&
349
- op.newProperties.focus.offset === 0
350
- const movedToPreviousSpan =
351
- focusSpan &&
352
- newFocusSpan &&
353
- op.newProperties.focus.path[0] === op.properties.focus.path[0] &&
354
- op.newProperties.focus.path[1] ===
355
- op.properties.focus.path[1] - 1 &&
356
- op.properties.focus.offset === 0 &&
357
- newFocusSpan.text.length === op.newProperties.focus.offset
358
-
359
- // In the case of a collapsed selection moving to another collapsed
360
- // selection, we only want to clear the decorator state if the
361
- // caret is visually moving to a different span.
362
- if (!movedToNextSpan && !movedToPreviousSpan) {
363
- editor.decoratorState = {}
364
- }
365
- }
366
- } else {
367
- // In any other case, we want to clear the decorator state.
368
- editor.decoratorState = {}
369
- }
370
- }
371
-
372
- if (op.type === 'remove_text') {
373
- const {selection} = editor
374
-
375
- if (selection && Range.isExpanded(selection)) {
376
- const [block, blockPath] = Editor.node(editor, selection, {
377
- depth: 1,
378
- })
379
- const [span, spanPath] =
380
- Array.from(
381
- Editor.nodes(editor, {
382
- mode: 'lowest',
383
- at: {path: op.path, offset: op.offset},
384
- match: (n) => editor.isTextSpan(n),
385
- voids: false,
386
- }),
387
- )[0] ?? ([undefined, undefined] as const)
388
-
389
- if (
390
- span &&
391
- block &&
392
- isTextBlock(editorActor.getSnapshot().context, block)
393
- ) {
394
- const markDefs = block.markDefs ?? []
395
- const marks = span.marks ?? []
396
- const spanHasAnnotations = marks.some((mark) =>
397
- markDefs.find((markDef) => markDef._key === mark),
398
- )
399
- const deletingFromTheEnd =
400
- op.offset + op.text.length === span.text.length
401
- const deletingAllText = op.offset === 0 && deletingFromTheEnd
402
-
403
- const previousSpan = getPreviousSpan({editor, blockPath, spanPath})
404
- const nextSpan = getNextSpan({editor, blockPath, spanPath})
405
-
406
- const previousSpanHasSameAnnotation = previousSpan
407
- ? previousSpan.marks?.some(
408
- (mark) => !decorators.includes(mark) && marks.includes(mark),
409
- )
410
- : false
411
- const nextSpanHasSameAnnotation = nextSpan
412
- ? nextSpan.marks?.some(
413
- (mark) => !decorators.includes(mark) && marks.includes(mark),
414
- )
415
- : false
416
-
417
- if (
418
- spanHasAnnotations &&
419
- deletingAllText &&
420
- !previousSpanHasSameAnnotation &&
421
- !nextSpanHasSameAnnotation
422
- ) {
423
- const snapshot = getEditorSnapshot({
424
- editorActorSnapshot: editorActor.getSnapshot(),
425
- slateEditorInstance: editor,
426
- })
427
-
428
- Editor.withoutNormalizing(editor, () => {
429
- apply(op)
430
- Transforms.setNodes(
431
- editor,
432
- {marks: getActiveDecorators(snapshot)},
433
- {at: op.path},
434
- )
435
- })
436
-
437
- editor.onChange()
438
- return
439
- }
440
- }
441
- }
442
- }
443
-
444
- /**
445
- * Copy over markDefs when merging blocks
446
- */
447
- if (
448
- op.type === 'merge_node' &&
449
- op.path.length === 1 &&
450
- 'markDefs' in op.properties &&
451
- op.properties._type ===
452
- editorActor.getSnapshot().context.schema.block.name &&
453
- Array.isArray(op.properties.markDefs) &&
454
- op.properties.markDefs.length > 0 &&
455
- op.path[0] - 1 >= 0
456
- ) {
457
- const [targetBlock, targetPath] = Editor.node(editor, [op.path[0] - 1])
458
-
459
- if (editor.isTextBlock(targetBlock)) {
460
- const oldDefs =
461
- (Array.isArray(targetBlock.markDefs) && targetBlock.markDefs) || []
462
- const newMarkDefs = uniq([...oldDefs, ...op.properties.markDefs])
463
-
464
- debug(`Copying markDefs over to merged block`, op)
465
- Transforms.setNodes(
466
- editor,
467
- {markDefs: newMarkDefs},
468
- {at: targetPath, voids: false},
469
- )
470
- apply(op)
471
- return
472
- }
473
- }
474
-
475
- apply(op)
476
- }
477
-
478
- return editor
479
- }
480
- }
481
-
482
- export const removeDecoratorOperationImplementation: BehaviorOperationImplementation<
483
- 'decorator.remove'
484
- > = ({operation}) => {
485
- const editor = operation.editor
486
- const mark = operation.decorator
487
- const {selection} = editor
488
-
489
- if (selection) {
490
- if (Range.isExpanded(selection)) {
491
- // Split if needed
492
- Transforms.setNodes(
493
- editor,
494
- {},
495
- {match: Text.isText, split: true, hanging: true},
496
- )
497
- if (editor.selection) {
498
- const splitTextNodes = [
499
- ...Editor.nodes(editor, {
500
- at: editor.selection,
501
- match: Text.isText,
502
- }),
503
- ]
504
- splitTextNodes.forEach(([node, path]) => {
505
- const block = editor.children[path[0]]
506
- if (Element.isElement(block) && block.children.includes(node)) {
507
- Transforms.setNodes(
508
- editor,
509
- {
510
- marks: (Array.isArray(node.marks) ? node.marks : []).filter(
511
- (eMark: string) => eMark !== mark,
512
- ),
513
- _type: 'span',
514
- },
515
- {at: path},
516
- )
517
- }
518
- })
519
- }
520
- } else {
521
- const [block, blockPath] = Editor.node(editor, selection, {
522
- depth: 1,
523
- })
524
- const lonelyEmptySpan =
525
- editor.isTextBlock(block) &&
526
- block.children.length === 1 &&
527
- editor.isTextSpan(block.children[0]) &&
528
- block.children[0].text === ''
529
- ? block.children[0]
530
- : undefined
531
-
532
- if (lonelyEmptySpan) {
533
- const existingMarks = lonelyEmptySpan.marks ?? []
534
- const existingMarksWithoutDecorator = existingMarks.filter(
535
- (existingMark) => existingMark !== mark,
536
- )
537
-
538
- Transforms.setNodes(
539
- editor,
540
- {
541
- marks: existingMarksWithoutDecorator,
542
- },
543
- {
544
- at: blockPath,
545
- match: (node) => editor.isTextSpan(node),
546
- },
547
- )
548
- } else {
549
- editor.decoratorState[mark] = false
550
- }
551
- }
552
-
553
- if (editor.selection) {
554
- // Reselect
555
- const selection = editor.selection
556
- editor.selection = {...selection}
557
- }
558
- }
559
- }
@@ -1,121 +0,0 @@
1
- import {isSpan, isTextBlock} from '@portabletext/schema'
2
- import type {
3
- PortableTextListBlock,
4
- PortableTextSpan,
5
- PortableTextTextBlock,
6
- } from '@sanity/types'
7
- import {Editor, Transforms, type Element} from 'slate'
8
- import {debugWithName} from '../../internal-utils/debug'
9
- import type {PortableTextSlateEditor} from '../../types/slate-editor'
10
- import {isListBlock} from '../../utils/parse-blocks'
11
- import type {EditorActor} from '../editor-machine'
12
- import {withNormalizeNode} from '../with-normalizing-node'
13
-
14
- const debug = debugWithName('plugin:withSchemaTypes')
15
- /**
16
- * This plugin makes sure that schema types are recognized properly by Slate as blocks, voids, inlines
17
- *
18
- */
19
- export function createWithSchemaTypes({
20
- editorActor,
21
- }: {
22
- editorActor: EditorActor
23
- }) {
24
- return function withSchemaTypes(
25
- editor: PortableTextSlateEditor,
26
- ): PortableTextSlateEditor {
27
- editor.isTextBlock = (value: unknown): value is PortableTextTextBlock => {
28
- if (Editor.isEditor(value)) {
29
- return false
30
- }
31
-
32
- return isTextBlock(editorActor.getSnapshot().context, value)
33
- }
34
- editor.isTextSpan = (value: unknown): value is PortableTextSpan => {
35
- if (Editor.isEditor(value)) {
36
- return false
37
- }
38
-
39
- return isSpan(editorActor.getSnapshot().context, value)
40
- }
41
- editor.isListBlock = (value: unknown): value is PortableTextListBlock => {
42
- if (Editor.isEditor(value)) {
43
- return false
44
- }
45
-
46
- return isListBlock(editorActor.getSnapshot().context, value)
47
- }
48
- editor.isVoid = (element: Element): boolean => {
49
- if (Editor.isEditor(element)) {
50
- return false
51
- }
52
-
53
- return (
54
- editorActor.getSnapshot().context.schema.block.name !== element._type &&
55
- (editorActor
56
- .getSnapshot()
57
- .context.schema.blockObjects.map((obj) => obj.name)
58
- .includes(element._type) ||
59
- editorActor
60
- .getSnapshot()
61
- .context.schema.inlineObjects.map((obj) => obj.name)
62
- .includes(element._type))
63
- )
64
- }
65
- editor.isInline = (element: Element): boolean => {
66
- if (Editor.isEditor(element)) {
67
- return false
68
- }
69
-
70
- const inlineSchemaTypes = editorActor
71
- .getSnapshot()
72
- .context.schema.inlineObjects.map((obj) => obj.name)
73
- return (
74
- inlineSchemaTypes.includes(element._type) &&
75
- '__inline' in element &&
76
- element.__inline === true
77
- )
78
- }
79
-
80
- // Extend Slate's default normalization
81
- const {normalizeNode} = editor
82
- editor.normalizeNode = (entry) => {
83
- const [node, path] = entry
84
-
85
- // If text block children node is missing _type, set it to the span type
86
- if (node._type === undefined && path.length === 2) {
87
- debug('Setting span type on text node without a type')
88
- const span = node as PortableTextSpan
89
- const key =
90
- span._key || editorActor.getSnapshot().context.keyGenerator()
91
- withNormalizeNode(editor, () => {
92
- Transforms.setNodes(
93
- editor,
94
- {
95
- ...span,
96
- _type: editorActor.getSnapshot().context.schema.span.name,
97
- _key: key,
98
- },
99
- {at: path},
100
- )
101
- })
102
- return
103
- }
104
-
105
- // catches cases when the children are missing keys but excludes it when the normalize is running the node as the editor object
106
- if (node._key === undefined && (path.length === 1 || path.length === 2)) {
107
- debug('Setting missing key on child node without a key')
108
- const key = editorActor.getSnapshot().context.keyGenerator()
109
- withNormalizeNode(editor, () => {
110
- Transforms.setNodes(editor, {_key: key}, {at: path})
111
- })
112
- return
113
- }
114
-
115
- withNormalizeNode(editor, () => {
116
- normalizeNode(entry)
117
- })
118
- }
119
- return editor
120
- }
121
- }