@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,171 +0,0 @@
1
- import {isSpan, isTextBlock} from '@portabletext/schema'
2
- import type {PortableTextObject, PortableTextSpan} from '@sanity/types'
3
- import type {Path, Range} from 'slate'
4
- import type {EditorContext, EditorSnapshot} from '../editor/editor-snapshot'
5
- import type {EditorSelectionPoint} from '../types/editor'
6
- import {blockOffsetToSpanSelectionPoint} from '../utils/util.block-offset'
7
- import {isEqualSelectionPoints} from '../utils/util.is-equal-selection-points'
8
- import {
9
- getBlockKeyFromSelectionPoint,
10
- getChildKeyFromSelectionPoint,
11
- } from '../utils/util.selection-point'
12
-
13
- export function toSlateRange(
14
- snapshot: {
15
- context: Pick<EditorContext, 'schema' | 'value' | 'selection'>
16
- } & Pick<EditorSnapshot, 'blockIndexMap'>,
17
- ): Range | null {
18
- if (!snapshot.context.selection) {
19
- return null
20
- }
21
-
22
- if (
23
- isEqualSelectionPoints(
24
- snapshot.context.selection.anchor,
25
- snapshot.context.selection.focus,
26
- )
27
- ) {
28
- const anchorPoint = toSlateSelectionPoint(
29
- snapshot,
30
- snapshot.context.selection.anchor,
31
- snapshot.context.selection.backward ? 'backward' : 'forward',
32
- )
33
-
34
- if (!anchorPoint) {
35
- return null
36
- }
37
-
38
- return {
39
- anchor: anchorPoint,
40
- focus: anchorPoint,
41
- }
42
- }
43
-
44
- const anchorPoint = toSlateSelectionPoint(
45
- snapshot,
46
- snapshot.context.selection.anchor,
47
- snapshot.context.selection.backward ? 'forward' : 'backward',
48
- )
49
- const focusPoint = toSlateSelectionPoint(
50
- snapshot,
51
- snapshot.context.selection.focus,
52
- snapshot.context.selection.backward ? 'backward' : 'forward',
53
- )
54
-
55
- if (!anchorPoint || !focusPoint) {
56
- return null
57
- }
58
-
59
- return {
60
- anchor: anchorPoint,
61
- focus: focusPoint,
62
- }
63
- }
64
-
65
- function toSlateSelectionPoint(
66
- snapshot: {
67
- context: Pick<EditorContext, 'schema' | 'value'>
68
- } & Pick<EditorSnapshot, 'blockIndexMap'>,
69
- selectionPoint: EditorSelectionPoint,
70
- direction: 'forward' | 'backward',
71
- ):
72
- | {
73
- path: Path
74
- offset: number
75
- }
76
- | undefined {
77
- const blockKey = getBlockKeyFromSelectionPoint(selectionPoint)
78
-
79
- if (!blockKey) {
80
- return undefined
81
- }
82
-
83
- const blockIndex = snapshot.blockIndexMap.get(blockKey)
84
-
85
- if (blockIndex === undefined) {
86
- return undefined
87
- }
88
-
89
- const block = snapshot.context.value.at(blockIndex)
90
-
91
- if (!block) {
92
- return undefined
93
- }
94
-
95
- if (!isTextBlock(snapshot.context, block)) {
96
- return {
97
- path: [blockIndex, 0],
98
- offset: 0,
99
- }
100
- }
101
-
102
- let childKey = getChildKeyFromSelectionPoint({
103
- path: selectionPoint.path,
104
- offset: 0,
105
- })
106
-
107
- // If the block is a text block, but there is no child key in the selection
108
- // point path, then we can try to find a span selection point by the offset.
109
- const spanSelectionPoint = !childKey
110
- ? blockOffsetToSpanSelectionPoint({
111
- context: {
112
- schema: snapshot.context.schema,
113
- value: [block],
114
- },
115
- blockOffset: {
116
- path: [{_key: blockKey}],
117
- offset: selectionPoint.offset,
118
- },
119
- direction,
120
- })
121
- : undefined
122
-
123
- childKey = spanSelectionPoint
124
- ? getChildKeyFromSelectionPoint(spanSelectionPoint)
125
- : childKey
126
-
127
- // If we still don't have a child key, then we have to resort to selecting
128
- // the first child of the block (which by Slate convention is a span).
129
- if (!childKey) {
130
- return {
131
- path: [blockIndex, 0],
132
- offset: 0,
133
- }
134
- }
135
-
136
- let offset = spanSelectionPoint?.offset ?? selectionPoint.offset
137
- let childPath: Array<number> = []
138
- let childIndex = -1
139
- let pathChild: PortableTextSpan | PortableTextObject | undefined
140
-
141
- for (const child of block.children) {
142
- childIndex++
143
- if (child._key === childKey) {
144
- pathChild = child
145
- if (isSpan(snapshot.context, child)) {
146
- childPath = [childIndex]
147
- } else {
148
- childPath = [childIndex, 0]
149
- offset = 0
150
- }
151
- break
152
- }
153
- }
154
-
155
- // If we for some unforeseen reason didn't manage to produce a child path,
156
- // then we have to resort to selecting the first child of the block (which
157
- // by Slate convention is a span).
158
- if (childPath.length === 0) {
159
- return {
160
- path: [blockIndex, 0],
161
- offset: 0,
162
- }
163
- }
164
-
165
- return {
166
- path: [blockIndex].concat(childPath),
167
- offset: isSpan(snapshot.context, pathChild)
168
- ? Math.min(pathChild.text.length, offset)
169
- : offset,
170
- }
171
- }
@@ -1,443 +0,0 @@
1
- import {insert, set, setIfMissing, unset} from '@portabletext/patches'
2
- import {isSpan, isTextBlock} from '@portabletext/schema'
3
- import type {
4
- PortableTextBlock,
5
- PortableTextSpan,
6
- PortableTextTextBlock,
7
- } from '@sanity/types'
8
- import {flatten, isPlainObject, uniq} from 'lodash'
9
- import type {EditorSchema} from '../editor/editor-schema'
10
- import type {InvalidValueResolution} from '../types/editor'
11
-
12
- export interface Validation {
13
- valid: boolean
14
- resolution: InvalidValueResolution | null
15
- value: PortableTextBlock[] | undefined
16
- }
17
-
18
- export function validateValue(
19
- value: PortableTextBlock[] | undefined,
20
- types: EditorSchema,
21
- keyGenerator: () => string,
22
- ): Validation {
23
- let resolution: InvalidValueResolution | null = null
24
- let valid = true
25
- const validChildTypes = [
26
- types.span.name,
27
- ...types.inlineObjects.map((t) => t.name),
28
- ]
29
- const validBlockTypes = [
30
- types.block.name,
31
- ...types.blockObjects.map((t) => t.name),
32
- ]
33
-
34
- // Undefined is allowed
35
- if (value === undefined) {
36
- return {valid: true, resolution: null, value}
37
- }
38
- // Only lengthy arrays are allowed in the editor.
39
- if (!Array.isArray(value) || value.length === 0) {
40
- return {
41
- valid: false,
42
- resolution: {
43
- patches: [unset([])],
44
- description:
45
- 'Editor value must be an array of Portable Text blocks, or undefined.',
46
- action: 'Unset the value',
47
- item: value,
48
-
49
- i18n: {
50
- description:
51
- 'inputs.portable-text.invalid-value.not-an-array.description',
52
- action: 'inputs.portable-text.invalid-value.not-an-array.action',
53
- },
54
- },
55
- value,
56
- }
57
- }
58
- if (
59
- value.some((blk: PortableTextBlock, index: number): boolean => {
60
- // Is the block an object?
61
- if (!isPlainObject(blk)) {
62
- resolution = {
63
- patches: [unset([index])],
64
- description: `Block must be an object, got ${String(blk)}`,
65
- action: `Unset invalid item`,
66
- item: blk,
67
-
68
- i18n: {
69
- description:
70
- 'inputs.portable-text.invalid-value.not-an-object.description',
71
- action: 'inputs.portable-text.invalid-value.not-an-object.action',
72
- values: {index},
73
- },
74
- }
75
- return true
76
- }
77
- // Test that every block has a _key prop
78
- if (!blk._key || typeof blk._key !== 'string') {
79
- resolution = {
80
- patches: [set({...blk, _key: keyGenerator()}, [index])],
81
- description: `Block at index ${index} is missing required _key.`,
82
- action: 'Set the block with a random _key value',
83
- item: blk,
84
-
85
- i18n: {
86
- description:
87
- 'inputs.portable-text.invalid-value.missing-key.description',
88
- action: 'inputs.portable-text.invalid-value.missing-key.action',
89
- values: {index},
90
- },
91
- }
92
- return true
93
- }
94
- // Test that every block has valid _type
95
- if (!blk._type || !validBlockTypes.includes(blk._type)) {
96
- // Special case where block type is set to default 'block', but the block type is named something else according to the schema.
97
- if (blk._type === 'block') {
98
- const currentBlockTypeName = types.block.name
99
- resolution = {
100
- patches: [
101
- set({...blk, _type: currentBlockTypeName}, [{_key: blk._key}]),
102
- ],
103
- description: `Block with _key '${blk._key}' has invalid type name '${blk._type}'. According to the schema, the block type name is '${currentBlockTypeName}'`,
104
- action: `Use type '${currentBlockTypeName}'`,
105
- item: blk,
106
-
107
- i18n: {
108
- description:
109
- 'inputs.portable-text.invalid-value.incorrect-block-type.description',
110
- action:
111
- 'inputs.portable-text.invalid-value.incorrect-block-type.action',
112
- values: {key: blk._key, expectedTypeName: currentBlockTypeName},
113
- },
114
- }
115
- return true
116
- }
117
-
118
- // If the block has no `_type`, but aside from that is a valid Portable Text block
119
- if (
120
- !blk._type &&
121
- isTextBlock({schema: types}, {...blk, _type: types.block.name})
122
- ) {
123
- resolution = {
124
- patches: [
125
- set({...blk, _type: types.block.name}, [{_key: blk._key}]),
126
- ],
127
- description: `Block with _key '${blk._key}' is missing a type name. According to the schema, the block type name is '${types.block.name}'`,
128
- action: `Use type '${types.block.name}'`,
129
- item: blk,
130
-
131
- i18n: {
132
- description:
133
- 'inputs.portable-text.invalid-value.missing-block-type.description',
134
- action:
135
- 'inputs.portable-text.invalid-value.missing-block-type.action',
136
- values: {key: blk._key, expectedTypeName: types.block.name},
137
- },
138
- }
139
- return true
140
- }
141
-
142
- if (!blk._type) {
143
- resolution = {
144
- patches: [unset([{_key: blk._key}])],
145
- description: `Block with _key '${blk._key}' is missing an _type property`,
146
- action: 'Remove the block',
147
- item: blk,
148
-
149
- i18n: {
150
- description:
151
- 'inputs.portable-text.invalid-value.missing-type.description',
152
- action: 'inputs.portable-text.invalid-value.missing-type.action',
153
- values: {key: blk._key},
154
- },
155
- }
156
- return true
157
- }
158
-
159
- resolution = {
160
- patches: [unset([{_key: blk._key}])],
161
- description: `Block with _key '${blk._key}' has invalid _type '${blk._type}'`,
162
- action: 'Remove the block',
163
- item: blk,
164
-
165
- i18n: {
166
- description:
167
- 'inputs.portable-text.invalid-value.disallowed-type.description',
168
- action: 'inputs.portable-text.invalid-value.disallowed-type.action',
169
- values: {key: blk._key, typeName: blk._type},
170
- },
171
- }
172
- return true
173
- }
174
-
175
- // Test regular text blocks
176
- if (blk._type === types.block.name) {
177
- const textBlock = blk as PortableTextTextBlock
178
- // Test that it has a valid children property (array)
179
- if (textBlock.children && !Array.isArray(textBlock.children)) {
180
- resolution = {
181
- patches: [set({children: []}, [{_key: textBlock._key}])],
182
- description: `Text block with _key '${textBlock._key}' has a invalid required property 'children'.`,
183
- action: 'Reset the children property',
184
- item: textBlock,
185
-
186
- i18n: {
187
- description:
188
- 'inputs.portable-text.invalid-value.missing-or-invalid-children.description',
189
- action:
190
- 'inputs.portable-text.invalid-value.missing-or-invalid-children.action',
191
- values: {key: textBlock._key},
192
- },
193
- }
194
- return true
195
- }
196
- // Test that children is set and lengthy
197
- if (
198
- textBlock.children === undefined ||
199
- (Array.isArray(textBlock.children) && textBlock.children.length === 0)
200
- ) {
201
- const newSpan = {
202
- _type: types.span.name,
203
- _key: keyGenerator(),
204
- text: '',
205
- marks: [],
206
- }
207
- resolution = {
208
- autoResolve: true,
209
- patches: [
210
- setIfMissing([], [{_key: blk._key}, 'children']),
211
- insert([newSpan], 'after', [{_key: blk._key}, 'children', 0]),
212
- ],
213
- description: `Children for text block with _key '${blk._key}' is empty.`,
214
- action: 'Insert an empty text',
215
- item: blk,
216
-
217
- i18n: {
218
- description:
219
- 'inputs.portable-text.invalid-value.empty-children.description',
220
- action:
221
- 'inputs.portable-text.invalid-value.empty-children.action',
222
- values: {key: blk._key},
223
- },
224
- }
225
- return true
226
- }
227
-
228
- const allUsedMarks = uniq(
229
- flatten(
230
- textBlock.children
231
- .filter((child) => isSpan({schema: types}, child))
232
- .map((cld) => cld.marks || []),
233
- ),
234
- )
235
-
236
- // Test that all markDefs are in use (remove orphaned markDefs)
237
- if (Array.isArray(blk.markDefs) && blk.markDefs.length > 0) {
238
- const unusedMarkDefs: string[] = uniq(
239
- blk.markDefs
240
- .map((def) => def._key)
241
- .filter((key) => !allUsedMarks.includes(key)),
242
- )
243
- if (unusedMarkDefs.length > 0) {
244
- resolution = {
245
- autoResolve: true,
246
- patches: unusedMarkDefs.map((markDefKey) =>
247
- unset([{_key: blk._key}, 'markDefs', {_key: markDefKey}]),
248
- ),
249
- description: `Block contains orphaned data (unused mark definitions): ${unusedMarkDefs.join(
250
- ', ',
251
- )}.`,
252
- action: 'Remove unused mark definition item',
253
- item: blk,
254
- i18n: {
255
- description:
256
- 'inputs.portable-text.invalid-value.orphaned-mark-defs.description',
257
- action:
258
- 'inputs.portable-text.invalid-value.orphaned-mark-defs.action',
259
- values: {
260
- key: blk._key,
261
- unusedMarkDefs: unusedMarkDefs.map((m) => m.toString()),
262
- },
263
- },
264
- }
265
- return true
266
- }
267
- }
268
-
269
- // Test that every annotation mark used has a definition
270
- const annotationMarks = allUsedMarks.filter(
271
- (mark) => !types.decorators.map((dec) => dec.name).includes(mark),
272
- )
273
- const orphanedMarks = annotationMarks.filter(
274
- (mark) =>
275
- textBlock.markDefs === undefined ||
276
- !textBlock.markDefs.find((def) => def._key === mark),
277
- )
278
- if (orphanedMarks.length > 0) {
279
- const spanChildren = textBlock.children.filter(
280
- (cld) =>
281
- cld._type === types.span.name &&
282
- Array.isArray(cld.marks) &&
283
- cld.marks.some((mark) => orphanedMarks.includes(mark)),
284
- ) as PortableTextSpan[]
285
- if (spanChildren) {
286
- const orphaned = orphanedMarks.join(', ')
287
- resolution = {
288
- autoResolve: true,
289
- patches: spanChildren.map((child) => {
290
- return set(
291
- (child.marks || []).filter(
292
- (cMrk) => !orphanedMarks.includes(cMrk),
293
- ),
294
- [{_key: blk._key}, 'children', {_key: child._key}, 'marks'],
295
- )
296
- }),
297
- description: `Block with _key '${blk._key}' contains marks (${orphaned}) not supported by the current content model.`,
298
- action: 'Remove invalid marks',
299
- item: blk,
300
-
301
- i18n: {
302
- description:
303
- 'inputs.portable-text.invalid-value.orphaned-marks.description',
304
- action:
305
- 'inputs.portable-text.invalid-value.orphaned-marks.action',
306
- values: {
307
- key: blk._key,
308
- orphanedMarks: orphanedMarks.map((m) => m.toString()),
309
- },
310
- },
311
- }
312
- return true
313
- }
314
- }
315
-
316
- // Test every child
317
- if (
318
- textBlock.children.some((child, cIndex: number) => {
319
- if (!isPlainObject(child)) {
320
- resolution = {
321
- patches: [unset([{_key: blk._key}, 'children', cIndex])],
322
- description: `Child at index '${cIndex}' in block with key '${blk._key}' is not an object.`,
323
- action: 'Remove the item',
324
- item: blk,
325
-
326
- i18n: {
327
- description:
328
- 'inputs.portable-text.invalid-value.non-object-child.description',
329
- action:
330
- 'inputs.portable-text.invalid-value.non-object-child.action',
331
- values: {key: blk._key, index: cIndex},
332
- },
333
- }
334
- return true
335
- }
336
-
337
- if (!child._key || typeof child._key !== 'string') {
338
- const newChild = {...child, _key: keyGenerator()}
339
- resolution = {
340
- autoResolve: true,
341
- patches: [
342
- set(newChild, [{_key: blk._key}, 'children', cIndex]),
343
- ],
344
- description: `Child at index ${cIndex} is missing required _key in block with _key ${blk._key}.`,
345
- action: 'Set a new random _key on the object',
346
- item: blk,
347
-
348
- i18n: {
349
- description:
350
- 'inputs.portable-text.invalid-value.missing-child-key.description',
351
- action:
352
- 'inputs.portable-text.invalid-value.missing-child-key.action',
353
- values: {key: blk._key, index: cIndex},
354
- },
355
- }
356
- return true
357
- }
358
-
359
- // Verify that children have valid types
360
- if (!child._type) {
361
- resolution = {
362
- patches: [
363
- unset([{_key: blk._key}, 'children', {_key: child._key}]),
364
- ],
365
- description: `Child with _key '${child._key}' in block with key '${blk._key}' is missing '_type' property.`,
366
- action: 'Remove the object',
367
- item: blk,
368
-
369
- i18n: {
370
- description:
371
- 'inputs.portable-text.invalid-value.missing-child-type.description',
372
- action:
373
- 'inputs.portable-text.invalid-value.missing-child-type.action',
374
- values: {key: blk._key, childKey: child._key},
375
- },
376
- }
377
- return true
378
- }
379
-
380
- if (!validChildTypes.includes(child._type)) {
381
- resolution = {
382
- patches: [
383
- unset([{_key: blk._key}, 'children', {_key: child._key}]),
384
- ],
385
- description: `Child with _key '${child._key}' in block with key '${blk._key}' has invalid '_type' property (${child._type}).`,
386
- action: 'Remove the object',
387
- item: blk,
388
-
389
- i18n: {
390
- description:
391
- 'inputs.portable-text.invalid-value.disallowed-child-type.description',
392
- action:
393
- 'inputs.portable-text.invalid-value.disallowed-child-type.action',
394
- values: {
395
- key: blk._key,
396
- childKey: child._key,
397
- childType: child._type,
398
- },
399
- },
400
- }
401
- return true
402
- }
403
-
404
- // Verify that spans have .text property that is a string
405
- if (
406
- child._type === types.span.name &&
407
- typeof child.text !== 'string'
408
- ) {
409
- resolution = {
410
- patches: [
411
- set({...child, text: ''}, [
412
- {_key: blk._key},
413
- 'children',
414
- {_key: child._key},
415
- ]),
416
- ],
417
- description: `Child with _key '${child._key}' in block with key '${blk._key}' has missing or invalid text property!`,
418
- action: `Write an empty text property to the object`,
419
- item: blk,
420
-
421
- i18n: {
422
- description:
423
- 'inputs.portable-text.invalid-value.invalid-span-text.description',
424
- action:
425
- 'inputs.portable-text.invalid-value.invalid-span-text.action',
426
- values: {key: blk._key, childKey: child._key},
427
- },
428
- }
429
- return true
430
- }
431
- return false
432
- })
433
- ) {
434
- valid = false
435
- }
436
- }
437
- return false
438
- })
439
- ) {
440
- valid = false
441
- }
442
- return {valid, resolution, value}
443
- }
@@ -1,33 +0,0 @@
1
- import {isSpan, isTextBlock} from '@portabletext/schema'
2
- import type {PortableTextBlock} from '@sanity/types'
3
- import type {EditorSchema} from '../editor/editor-schema'
4
-
5
- export function getValueAnnotations(
6
- schema: EditorSchema,
7
- value: Array<PortableTextBlock> | undefined,
8
- ): Array<string> {
9
- if (!value) {
10
- return []
11
- }
12
-
13
- const annotations: Array<string> = []
14
-
15
- for (const block of value) {
16
- if (isTextBlock({schema}, block)) {
17
- for (const child of block.children) {
18
- if (isSpan({schema}, child) && child.marks) {
19
- for (const mark of child.marks) {
20
- if (
21
- block.markDefs?.some((markDef) => markDef._key === mark) &&
22
- !annotations.includes(mark)
23
- ) {
24
- annotations.push(mark)
25
- }
26
- }
27
- }
28
- }
29
- }
30
- }
31
-
32
- return annotations
33
- }