@portabletext/editor 3.3.3 → 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 (306) hide show
  1. package/package.json +11 -12
  2. package/src/behaviors/_exports/index.ts +0 -1
  3. package/src/behaviors/behavior.abstract.annotation.ts +0 -77
  4. package/src/behaviors/behavior.abstract.decorator.ts +0 -39
  5. package/src/behaviors/behavior.abstract.delete.ts +0 -273
  6. package/src/behaviors/behavior.abstract.deserialize.ts +0 -232
  7. package/src/behaviors/behavior.abstract.insert.ts +0 -525
  8. package/src/behaviors/behavior.abstract.keyboard.ts +0 -189
  9. package/src/behaviors/behavior.abstract.list-item.ts +0 -70
  10. package/src/behaviors/behavior.abstract.move.ts +0 -79
  11. package/src/behaviors/behavior.abstract.select.ts +0 -118
  12. package/src/behaviors/behavior.abstract.serialize.ts +0 -96
  13. package/src/behaviors/behavior.abstract.split.ts +0 -170
  14. package/src/behaviors/behavior.abstract.style.ts +0 -55
  15. package/src/behaviors/behavior.abstract.ts +0 -139
  16. package/src/behaviors/behavior.config.ts +0 -7
  17. package/src/behaviors/behavior.core.annotations.ts +0 -62
  18. package/src/behaviors/behavior.core.block-element.ts +0 -116
  19. package/src/behaviors/behavior.core.block-objects.ts +0 -285
  20. package/src/behaviors/behavior.core.decorators.ts +0 -44
  21. package/src/behaviors/behavior.core.dnd.ts +0 -356
  22. package/src/behaviors/behavior.core.insert-break.ts +0 -266
  23. package/src/behaviors/behavior.core.insert.ts +0 -52
  24. package/src/behaviors/behavior.core.lists.ts +0 -691
  25. package/src/behaviors/behavior.core.ts +0 -44
  26. package/src/behaviors/behavior.perform-event.ts +0 -354
  27. package/src/behaviors/behavior.types.action.ts +0 -102
  28. package/src/behaviors/behavior.types.behavior.ts +0 -83
  29. package/src/behaviors/behavior.types.event.ts +0 -667
  30. package/src/behaviors/behavior.types.guard.ts +0 -11
  31. package/src/behaviors/index.ts +0 -17
  32. package/src/converters/converter.json.ts +0 -53
  33. package/src/converters/converter.portable-text.deserialize.test.ts +0 -680
  34. package/src/converters/converter.portable-text.ts +0 -75
  35. package/src/converters/converter.text-html.deserialize.test.ts +0 -406
  36. package/src/converters/converter.text-html.serialize.test.ts +0 -246
  37. package/src/converters/converter.text-html.ts +0 -87
  38. package/src/converters/converter.text-markdown.ts +0 -67
  39. package/src/converters/converter.text-plain.test.ts +0 -245
  40. package/src/converters/converter.text-plain.ts +0 -126
  41. package/src/converters/converter.types.ts +0 -72
  42. package/src/converters/converters.core.ts +0 -18
  43. package/src/editor/Editable.tsx +0 -1012
  44. package/src/editor/PortableTextEditor.tsx +0 -791
  45. package/src/editor/components/drop-indicator.tsx +0 -17
  46. package/src/editor/components/render-block-object.tsx +0 -121
  47. package/src/editor/components/render-default-object.tsx +0 -21
  48. package/src/editor/components/render-element.tsx +0 -88
  49. package/src/editor/components/render-inline-object.tsx +0 -129
  50. package/src/editor/components/render-leaf.tsx +0 -64
  51. package/src/editor/components/render-span.tsx +0 -303
  52. package/src/editor/components/render-text-block.tsx +0 -265
  53. package/src/editor/components/render-text.tsx +0 -18
  54. package/src/editor/components/use-core-block-element-behaviors.ts +0 -39
  55. package/src/editor/create-editor.ts +0 -323
  56. package/src/editor/create-slate-editor.tsx +0 -64
  57. package/src/editor/editor-actor-context.ts +0 -4
  58. package/src/editor/editor-context.tsx +0 -7
  59. package/src/editor/editor-dom.ts +0 -220
  60. package/src/editor/editor-machine.ts +0 -751
  61. package/src/editor/editor-provider.tsx +0 -111
  62. package/src/editor/editor-schema.ts +0 -6
  63. package/src/editor/editor-selector.ts +0 -89
  64. package/src/editor/editor-snapshot.ts +0 -68
  65. package/src/editor/event-to-change.tsx +0 -49
  66. package/src/editor/hooks/usePortableTextEditor.ts +0 -25
  67. package/src/editor/hooks/usePortableTextEditorSelection.tsx +0 -28
  68. package/src/editor/mutation-machine.ts +0 -322
  69. package/src/editor/plugins/create-with-event-listeners.ts +0 -271
  70. package/src/editor/plugins/createWithEditableAPI.ts +0 -529
  71. package/src/editor/plugins/createWithHotKeys.ts +0 -68
  72. package/src/editor/plugins/createWithObjectKeys.ts +0 -289
  73. package/src/editor/plugins/createWithPatches.ts +0 -272
  74. package/src/editor/plugins/createWithPortableTextMarkModel.ts +0 -559
  75. package/src/editor/plugins/createWithSchemaTypes.ts +0 -121
  76. package/src/editor/plugins/slate-plugin.update-selection.ts +0 -51
  77. package/src/editor/plugins/slate-plugin.update-value.ts +0 -46
  78. package/src/editor/plugins/with-plugins.ts +0 -69
  79. package/src/editor/range-decorations-machine.ts +0 -421
  80. package/src/editor/relay-actor-context.ts +0 -4
  81. package/src/editor/relay-machine.ts +0 -152
  82. package/src/editor/sync-machine.ts +0 -961
  83. package/src/editor/use-editor.ts +0 -27
  84. package/src/editor/validate-selection-machine.test.ts +0 -47
  85. package/src/editor/validate-selection-machine.ts +0 -149
  86. package/src/editor/weakMaps.ts +0 -15
  87. package/src/editor/with-normalizing-node.ts +0 -14
  88. package/src/editor/with-performing-behavior-operation.ts +0 -21
  89. package/src/editor/withChanges.ts +0 -13
  90. package/src/editor/without-normalizing-conditional.ts +0 -13
  91. package/src/editor/withoutPatching.ts +0 -14
  92. package/src/editor.ts +0 -59
  93. package/src/history/behavior.operation.history.redo.ts +0 -67
  94. package/src/history/behavior.operation.history.undo.ts +0 -71
  95. package/src/history/event.history.undo.test.tsx +0 -672
  96. package/src/history/history.preserving-keys.test.tsx +0 -112
  97. package/src/history/remote-patches.ts +0 -20
  98. package/src/history/slate-plugin.history.ts +0 -142
  99. package/src/history/slate-plugin.redoing.ts +0 -21
  100. package/src/history/slate-plugin.undoing.ts +0 -21
  101. package/src/history/slate-plugin.without-history.ts +0 -23
  102. package/src/history/transform-operation.ts +0 -245
  103. package/src/history/undo-redo-collaboration.test.tsx +0 -541
  104. package/src/history/undo-redo.feature +0 -125
  105. package/src/history/undo-redo.test.tsx +0 -195
  106. package/src/history/undo-step.ts +0 -148
  107. package/src/index.ts +0 -107
  108. package/src/internal-utils/__tests__/ranges.test.ts +0 -23
  109. package/src/internal-utils/__tests__/values.test.ts +0 -110
  110. package/src/internal-utils/apply-operation-to-portable-text.test.ts +0 -1861
  111. package/src/internal-utils/apply-operation-to-portable-text.ts +0 -615
  112. package/src/internal-utils/applyPatch.ts +0 -644
  113. package/src/internal-utils/block-keys.ts +0 -9
  114. package/src/internal-utils/build-index-maps.test.ts +0 -464
  115. package/src/internal-utils/build-index-maps.ts +0 -131
  116. package/src/internal-utils/collapse-selection.ts +0 -36
  117. package/src/internal-utils/compound-client-rect.ts +0 -28
  118. package/src/internal-utils/create-placeholder-block.ts +0 -21
  119. package/src/internal-utils/create-test-snapshot.ts +0 -28
  120. package/src/internal-utils/debug.ts +0 -12
  121. package/src/internal-utils/editor-selection.test.ts +0 -44
  122. package/src/internal-utils/editor-selection.ts +0 -56
  123. package/src/internal-utils/event-position.ts +0 -318
  124. package/src/internal-utils/global-scope.ts +0 -27
  125. package/src/internal-utils/globally-scoped-context.ts +0 -39
  126. package/src/internal-utils/is-hotkey.test.ts +0 -114
  127. package/src/internal-utils/is-hotkey.ts +0 -209
  128. package/src/internal-utils/mime-type.ts +0 -1
  129. package/src/internal-utils/move-range-by-operation.ts +0 -19
  130. package/src/internal-utils/operation-to-patches.test.ts +0 -522
  131. package/src/internal-utils/operation-to-patches.ts +0 -571
  132. package/src/internal-utils/portable-text-node.ts +0 -209
  133. package/src/internal-utils/schema.ts +0 -8
  134. package/src/internal-utils/selection-block-keys.ts +0 -20
  135. package/src/internal-utils/selection-focus-text.ts +0 -40
  136. package/src/internal-utils/selection-text.test.ts +0 -32
  137. package/src/internal-utils/selection-text.ts +0 -21
  138. package/src/internal-utils/selection.ts +0 -77
  139. package/src/internal-utils/sibling-utils.ts +0 -55
  140. package/src/internal-utils/slate-utils.test.tsx +0 -121
  141. package/src/internal-utils/slate-utils.ts +0 -417
  142. package/src/internal-utils/split-string.ts +0 -12
  143. package/src/internal-utils/stop-actor.ts +0 -43
  144. package/src/internal-utils/string-overlap.test.ts +0 -14
  145. package/src/internal-utils/string-overlap.ts +0 -28
  146. package/src/internal-utils/string-utils.ts +0 -7
  147. package/src/internal-utils/text-block-key.test.ts +0 -41
  148. package/src/internal-utils/text-block-key.ts +0 -26
  149. package/src/internal-utils/text-marks.test.ts +0 -41
  150. package/src/internal-utils/text-marks.ts +0 -22
  151. package/src/internal-utils/text-selection.test.ts +0 -211
  152. package/src/internal-utils/text-selection.ts +0 -121
  153. package/src/internal-utils/to-slate-range.test.ts +0 -278
  154. package/src/internal-utils/to-slate-range.ts +0 -171
  155. package/src/internal-utils/validateValue.ts +0 -443
  156. package/src/internal-utils/value-annotations.ts +0 -33
  157. package/src/internal-utils/values.test.ts +0 -282
  158. package/src/internal-utils/values.ts +0 -266
  159. package/src/keyboard-shortcuts/default-keyboard-shortcuts.ts +0 -146
  160. package/src/operations/behavior.operation.annotation.add.ts +0 -99
  161. package/src/operations/behavior.operation.annotation.remove.ts +0 -150
  162. package/src/operations/behavior.operation.block.set.ts +0 -104
  163. package/src/operations/behavior.operation.block.unset.ts +0 -54
  164. package/src/operations/behavior.operation.child.set.ts +0 -107
  165. package/src/operations/behavior.operation.child.unset.ts +0 -116
  166. package/src/operations/behavior.operation.decorator.add.ts +0 -131
  167. package/src/operations/behavior.operation.delete.ts +0 -294
  168. package/src/operations/behavior.operation.insert.block.ts +0 -495
  169. package/src/operations/behavior.operation.insert.child.ts +0 -129
  170. package/src/operations/behavior.operation.insert.text.ts +0 -8
  171. package/src/operations/behavior.operation.move.backward.ts +0 -12
  172. package/src/operations/behavior.operation.move.block.ts +0 -44
  173. package/src/operations/behavior.operation.move.forward.ts +0 -11
  174. package/src/operations/behavior.operation.select.ts +0 -27
  175. package/src/operations/behavior.operations.ts +0 -221
  176. package/src/plugins/_exports/index.ts +0 -1
  177. package/src/plugins/index.ts +0 -3
  178. package/src/plugins/plugin.behavior.tsx +0 -24
  179. package/src/plugins/plugin.editor-ref.tsx +0 -17
  180. package/src/plugins/plugin.event-listener.tsx +0 -68
  181. package/src/plugins/plugin.internal.auto-close-brackets.test.tsx +0 -71
  182. package/src/plugins/plugin.internal.auto-close-brackets.ts +0 -62
  183. package/src/plugins/plugin.internal.change-ref.tsx +0 -19
  184. package/src/plugins/plugin.internal.portable-text-editor-ref.tsx +0 -16
  185. package/src/plugins/plugin.internal.slate-editor-ref.tsx +0 -15
  186. package/src/priority/priority.core.ts +0 -3
  187. package/src/priority/priority.sort.test.ts +0 -319
  188. package/src/priority/priority.sort.ts +0 -123
  189. package/src/priority/priority.types.ts +0 -24
  190. package/src/selectors/_exports/index.ts +0 -1
  191. package/src/selectors/drag-selection.test.ts +0 -578
  192. package/src/selectors/drag-selection.ts +0 -118
  193. package/src/selectors/index.ts +0 -54
  194. package/src/selectors/selector.get-active-annotation-marks.ts +0 -12
  195. package/src/selectors/selector.get-active-annotations.ts +0 -36
  196. package/src/selectors/selector.get-active-decorators.ts +0 -29
  197. package/src/selectors/selector.get-active-list-item.ts +0 -38
  198. package/src/selectors/selector.get-active-style.ts +0 -38
  199. package/src/selectors/selector.get-anchor-block.ts +0 -22
  200. package/src/selectors/selector.get-anchor-child.ts +0 -36
  201. package/src/selectors/selector.get-anchor-span.ts +0 -17
  202. package/src/selectors/selector.get-anchor-text-block.ts +0 -18
  203. package/src/selectors/selector.get-block-offsets.ts +0 -34
  204. package/src/selectors/selector.get-caret-word-selection.test.ts +0 -284
  205. package/src/selectors/selector.get-caret-word-selection.ts +0 -134
  206. package/src/selectors/selector.get-first-block.ts +0 -14
  207. package/src/selectors/selector.get-focus-block-object.ts +0 -18
  208. package/src/selectors/selector.get-focus-block.ts +0 -23
  209. package/src/selectors/selector.get-focus-child.ts +0 -36
  210. package/src/selectors/selector.get-focus-inline-object.ts +0 -17
  211. package/src/selectors/selector.get-focus-list-block.ts +0 -18
  212. package/src/selectors/selector.get-focus-span.ts +0 -18
  213. package/src/selectors/selector.get-focus-text-block.ts +0 -18
  214. package/src/selectors/selector.get-last-block.ts +0 -16
  215. package/src/selectors/selector.get-mark-state.test.ts +0 -325
  216. package/src/selectors/selector.get-mark-state.ts +0 -263
  217. package/src/selectors/selector.get-next-block.ts +0 -29
  218. package/src/selectors/selector.get-next-inline-object.ts +0 -53
  219. package/src/selectors/selector.get-next-inline-objects.ts +0 -50
  220. package/src/selectors/selector.get-next-span.ts +0 -56
  221. package/src/selectors/selector.get-previous-block.ts +0 -29
  222. package/src/selectors/selector.get-previous-inline-object.ts +0 -50
  223. package/src/selectors/selector.get-previous-inline-objects.ts +0 -47
  224. package/src/selectors/selector.get-previous-span.ts +0 -53
  225. package/src/selectors/selector.get-selected-blocks.ts +0 -61
  226. package/src/selectors/selector.get-selected-spans.test.ts +0 -347
  227. package/src/selectors/selector.get-selected-spans.ts +0 -155
  228. package/src/selectors/selector.get-selected-text-blocks.ts +0 -73
  229. package/src/selectors/selector.get-selected-value.test.ts +0 -834
  230. package/src/selectors/selector.get-selected-value.ts +0 -66
  231. package/src/selectors/selector.get-selection-end-block.ts +0 -33
  232. package/src/selectors/selector.get-selection-end-child.ts +0 -33
  233. package/src/selectors/selector.get-selection-end-point.ts +0 -17
  234. package/src/selectors/selector.get-selection-start-block.ts +0 -33
  235. package/src/selectors/selector.get-selection-start-child.ts +0 -33
  236. package/src/selectors/selector.get-selection-start-point.ts +0 -17
  237. package/src/selectors/selector.get-selection-text.test.ts +0 -421
  238. package/src/selectors/selector.get-selection-text.ts +0 -27
  239. package/src/selectors/selector.get-selection.ts +0 -9
  240. package/src/selectors/selector.get-text-after.ts +0 -46
  241. package/src/selectors/selector.get-text-before.ts +0 -46
  242. package/src/selectors/selector.get-value.ts +0 -11
  243. package/src/selectors/selector.is-active-annotation.test.ts +0 -320
  244. package/src/selectors/selector.is-active-annotation.ts +0 -52
  245. package/src/selectors/selector.is-active-decorator.test.ts +0 -136
  246. package/src/selectors/selector.is-active-decorator.ts +0 -24
  247. package/src/selectors/selector.is-active-list-item.ts +0 -13
  248. package/src/selectors/selector.is-active-style.ts +0 -13
  249. package/src/selectors/selector.is-at-the-end-of-block.ts +0 -30
  250. package/src/selectors/selector.is-at-the-start-of-block.ts +0 -30
  251. package/src/selectors/selector.is-overlapping-selection.test.ts +0 -304
  252. package/src/selectors/selector.is-overlapping-selection.ts +0 -181
  253. package/src/selectors/selector.is-point-after-selection.ts +0 -97
  254. package/src/selectors/selector.is-point-before-selection.ts +0 -97
  255. package/src/selectors/selector.is-selecting-entire-blocks.ts +0 -43
  256. package/src/selectors/selector.is-selection-collapsed.ts +0 -17
  257. package/src/selectors/selector.is-selection-expanded.test.ts +0 -63
  258. package/src/selectors/selector.is-selection-expanded.ts +0 -9
  259. package/src/test/_exports/index.ts +0 -1
  260. package/src/test/gherkin-parameter-types.ts +0 -112
  261. package/src/test/index.ts +0 -1
  262. package/src/test/vitest/_exports/index.ts +0 -1
  263. package/src/test/vitest/index.ts +0 -3
  264. package/src/test/vitest/step-context.ts +0 -13
  265. package/src/test/vitest/step-definitions.tsx +0 -960
  266. package/src/test/vitest/test-editor.tsx +0 -198
  267. package/src/type-utils.ts +0 -29
  268. package/src/types/block-offset.ts +0 -9
  269. package/src/types/block-with-optional-key.ts +0 -25
  270. package/src/types/editor.ts +0 -509
  271. package/src/types/options.ts +0 -13
  272. package/src/types/paths.ts +0 -35
  273. package/src/types/slate-editor.ts +0 -50
  274. package/src/types/slate.ts +0 -27
  275. package/src/utils/_exports/index.ts +0 -1
  276. package/src/utils/asserters.ts +0 -9
  277. package/src/utils/index.ts +0 -24
  278. package/src/utils/key-generator.ts +0 -33
  279. package/src/utils/parse-blocks.test.ts +0 -836
  280. package/src/utils/parse-blocks.ts +0 -504
  281. package/src/utils/util.at-the-beginning-of-block.ts +0 -32
  282. package/src/utils/util.block-offset-to-block-selection-point.ts +0 -28
  283. package/src/utils/util.block-offset-to-selection-point.ts +0 -33
  284. package/src/utils/util.block-offset.test.ts +0 -375
  285. package/src/utils/util.block-offset.ts +0 -136
  286. package/src/utils/util.block-offsets-to-selection.ts +0 -38
  287. package/src/utils/util.child-selection-point-to-block-offset.ts +0 -51
  288. package/src/utils/util.get-block-end-point.ts +0 -35
  289. package/src/utils/util.get-block-start-point.ts +0 -31
  290. package/src/utils/util.get-selection-end-point.ts +0 -20
  291. package/src/utils/util.get-selection-start-point.ts +0 -20
  292. package/src/utils/util.get-text-block-text.ts +0 -8
  293. package/src/utils/util.is-empty-text-block.ts +0 -21
  294. package/src/utils/util.is-equal-selection-points.ts +0 -13
  295. package/src/utils/util.is-equal-selections.ts +0 -20
  296. package/src/utils/util.is-keyed-segment.ts +0 -8
  297. package/src/utils/util.is-selection-collapsed.ts +0 -16
  298. package/src/utils/util.is-selection-expanded.ts +0 -13
  299. package/src/utils/util.merge-text-blocks.ts +0 -40
  300. package/src/utils/util.reverse-selection.ts +0 -26
  301. package/src/utils/util.selection-point-to-block-offset.ts +0 -30
  302. package/src/utils/util.selection-point.ts +0 -22
  303. package/src/utils/util.slice-blocks.ts +0 -221
  304. package/src/utils/util.slice-text-block.test.ts +0 -190
  305. package/src/utils/util.slice-text-block.ts +0 -89
  306. 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
- }