@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.
- package/lib/_chunks-dts/index.d.ts +7 -1
- package/package.json +16 -19
- package/src/behaviors/_exports/index.ts +0 -1
- package/src/behaviors/behavior.abstract.annotation.ts +0 -77
- package/src/behaviors/behavior.abstract.decorator.ts +0 -39
- package/src/behaviors/behavior.abstract.delete.ts +0 -273
- package/src/behaviors/behavior.abstract.deserialize.ts +0 -232
- package/src/behaviors/behavior.abstract.insert.ts +0 -525
- package/src/behaviors/behavior.abstract.keyboard.ts +0 -189
- package/src/behaviors/behavior.abstract.list-item.ts +0 -70
- package/src/behaviors/behavior.abstract.move.ts +0 -79
- package/src/behaviors/behavior.abstract.select.ts +0 -118
- package/src/behaviors/behavior.abstract.serialize.ts +0 -96
- package/src/behaviors/behavior.abstract.split.ts +0 -170
- package/src/behaviors/behavior.abstract.style.ts +0 -55
- package/src/behaviors/behavior.abstract.ts +0 -139
- package/src/behaviors/behavior.config.ts +0 -7
- package/src/behaviors/behavior.core.annotations.ts +0 -62
- package/src/behaviors/behavior.core.block-element.ts +0 -116
- package/src/behaviors/behavior.core.block-objects.ts +0 -285
- package/src/behaviors/behavior.core.decorators.ts +0 -44
- package/src/behaviors/behavior.core.dnd.ts +0 -356
- package/src/behaviors/behavior.core.insert-break.ts +0 -266
- package/src/behaviors/behavior.core.insert.ts +0 -52
- package/src/behaviors/behavior.core.lists.ts +0 -691
- package/src/behaviors/behavior.core.ts +0 -44
- package/src/behaviors/behavior.perform-event.ts +0 -354
- package/src/behaviors/behavior.types.action.ts +0 -102
- package/src/behaviors/behavior.types.behavior.ts +0 -83
- package/src/behaviors/behavior.types.event.ts +0 -667
- package/src/behaviors/behavior.types.guard.ts +0 -11
- package/src/behaviors/index.ts +0 -17
- package/src/converters/converter.json.ts +0 -53
- package/src/converters/converter.portable-text.deserialize.test.ts +0 -680
- package/src/converters/converter.portable-text.ts +0 -75
- package/src/converters/converter.text-html.deserialize.test.ts +0 -406
- package/src/converters/converter.text-html.serialize.test.ts +0 -246
- package/src/converters/converter.text-html.ts +0 -87
- package/src/converters/converter.text-markdown.ts +0 -67
- package/src/converters/converter.text-plain.test.ts +0 -245
- package/src/converters/converter.text-plain.ts +0 -126
- package/src/converters/converter.types.ts +0 -72
- package/src/converters/converters.core.ts +0 -18
- package/src/editor/Editable.tsx +0 -1012
- package/src/editor/PortableTextEditor.tsx +0 -791
- package/src/editor/components/drop-indicator.tsx +0 -17
- package/src/editor/components/render-block-object.tsx +0 -121
- package/src/editor/components/render-default-object.tsx +0 -21
- package/src/editor/components/render-element.tsx +0 -88
- package/src/editor/components/render-inline-object.tsx +0 -129
- package/src/editor/components/render-leaf.tsx +0 -64
- package/src/editor/components/render-span.tsx +0 -303
- package/src/editor/components/render-text-block.tsx +0 -265
- package/src/editor/components/render-text.tsx +0 -18
- package/src/editor/components/use-core-block-element-behaviors.ts +0 -39
- package/src/editor/create-editor.ts +0 -323
- package/src/editor/create-slate-editor.tsx +0 -64
- package/src/editor/editor-actor-context.ts +0 -4
- package/src/editor/editor-context.tsx +0 -7
- package/src/editor/editor-dom.ts +0 -220
- package/src/editor/editor-machine.ts +0 -751
- package/src/editor/editor-provider.tsx +0 -111
- package/src/editor/editor-schema.ts +0 -6
- package/src/editor/editor-selector.ts +0 -89
- package/src/editor/editor-snapshot.ts +0 -68
- package/src/editor/event-to-change.tsx +0 -49
- package/src/editor/hooks/usePortableTextEditor.ts +0 -25
- package/src/editor/hooks/usePortableTextEditorSelection.tsx +0 -28
- package/src/editor/mutation-machine.ts +0 -322
- package/src/editor/plugins/create-with-event-listeners.ts +0 -271
- package/src/editor/plugins/createWithEditableAPI.ts +0 -529
- package/src/editor/plugins/createWithHotKeys.ts +0 -68
- package/src/editor/plugins/createWithObjectKeys.ts +0 -289
- package/src/editor/plugins/createWithPatches.ts +0 -272
- package/src/editor/plugins/createWithPortableTextMarkModel.ts +0 -559
- package/src/editor/plugins/createWithSchemaTypes.ts +0 -121
- package/src/editor/plugins/slate-plugin.update-selection.ts +0 -51
- package/src/editor/plugins/slate-plugin.update-value.ts +0 -46
- package/src/editor/plugins/with-plugins.ts +0 -69
- package/src/editor/range-decorations-machine.ts +0 -421
- package/src/editor/relay-actor-context.ts +0 -4
- package/src/editor/relay-machine.ts +0 -152
- package/src/editor/sync-machine.ts +0 -961
- package/src/editor/use-editor.ts +0 -27
- package/src/editor/validate-selection-machine.test.ts +0 -47
- package/src/editor/validate-selection-machine.ts +0 -149
- package/src/editor/weakMaps.ts +0 -15
- package/src/editor/with-normalizing-node.ts +0 -14
- package/src/editor/with-performing-behavior-operation.ts +0 -21
- package/src/editor/withChanges.ts +0 -13
- package/src/editor/without-normalizing-conditional.ts +0 -13
- package/src/editor/withoutPatching.ts +0 -14
- package/src/editor.ts +0 -59
- package/src/history/behavior.operation.history.redo.ts +0 -67
- package/src/history/behavior.operation.history.undo.ts +0 -71
- package/src/history/event.history.undo.test.tsx +0 -672
- package/src/history/history.preserving-keys.test.tsx +0 -112
- package/src/history/remote-patches.ts +0 -20
- package/src/history/slate-plugin.history.ts +0 -142
- package/src/history/slate-plugin.redoing.ts +0 -21
- package/src/history/slate-plugin.undoing.ts +0 -21
- package/src/history/slate-plugin.without-history.ts +0 -23
- package/src/history/transform-operation.ts +0 -245
- package/src/history/undo-redo-collaboration.test.tsx +0 -541
- package/src/history/undo-redo.feature +0 -125
- package/src/history/undo-redo.test.tsx +0 -195
- package/src/history/undo-step.ts +0 -148
- package/src/index.ts +0 -98
- package/src/internal-utils/__tests__/ranges.test.ts +0 -23
- package/src/internal-utils/__tests__/values.test.ts +0 -110
- package/src/internal-utils/apply-operation-to-portable-text.test.ts +0 -1861
- package/src/internal-utils/apply-operation-to-portable-text.ts +0 -615
- package/src/internal-utils/applyPatch.ts +0 -644
- package/src/internal-utils/block-keys.ts +0 -9
- package/src/internal-utils/build-index-maps.test.ts +0 -464
- package/src/internal-utils/build-index-maps.ts +0 -131
- package/src/internal-utils/collapse-selection.ts +0 -36
- package/src/internal-utils/compound-client-rect.ts +0 -28
- package/src/internal-utils/create-placeholder-block.ts +0 -21
- package/src/internal-utils/create-test-snapshot.ts +0 -28
- package/src/internal-utils/debug.ts +0 -12
- package/src/internal-utils/editor-selection.test.ts +0 -44
- package/src/internal-utils/editor-selection.ts +0 -56
- package/src/internal-utils/event-position.ts +0 -318
- package/src/internal-utils/global-scope.ts +0 -27
- package/src/internal-utils/globally-scoped-context.ts +0 -39
- package/src/internal-utils/is-hotkey.test.ts +0 -114
- package/src/internal-utils/is-hotkey.ts +0 -209
- package/src/internal-utils/mime-type.ts +0 -1
- package/src/internal-utils/move-range-by-operation.ts +0 -19
- package/src/internal-utils/operation-to-patches.test.ts +0 -522
- package/src/internal-utils/operation-to-patches.ts +0 -571
- package/src/internal-utils/portable-text-node.ts +0 -209
- package/src/internal-utils/schema.ts +0 -8
- package/src/internal-utils/selection-block-keys.ts +0 -20
- package/src/internal-utils/selection-focus-text.ts +0 -40
- package/src/internal-utils/selection-text.test.ts +0 -32
- package/src/internal-utils/selection-text.ts +0 -21
- package/src/internal-utils/selection.ts +0 -77
- package/src/internal-utils/sibling-utils.ts +0 -55
- package/src/internal-utils/slate-utils.test.tsx +0 -121
- package/src/internal-utils/slate-utils.ts +0 -417
- package/src/internal-utils/split-string.ts +0 -12
- package/src/internal-utils/stop-actor.ts +0 -43
- package/src/internal-utils/string-overlap.test.ts +0 -14
- package/src/internal-utils/string-overlap.ts +0 -28
- package/src/internal-utils/string-utils.ts +0 -7
- package/src/internal-utils/text-block-key.test.ts +0 -41
- package/src/internal-utils/text-block-key.ts +0 -26
- package/src/internal-utils/text-marks.test.ts +0 -41
- package/src/internal-utils/text-marks.ts +0 -22
- package/src/internal-utils/text-selection.test.ts +0 -211
- package/src/internal-utils/text-selection.ts +0 -121
- package/src/internal-utils/to-slate-range.test.ts +0 -278
- package/src/internal-utils/to-slate-range.ts +0 -171
- package/src/internal-utils/validateValue.ts +0 -443
- package/src/internal-utils/value-annotations.ts +0 -33
- package/src/internal-utils/values.test.ts +0 -282
- package/src/internal-utils/values.ts +0 -266
- package/src/keyboard-shortcuts/default-keyboard-shortcuts.ts +0 -146
- package/src/operations/behavior.operation.annotation.add.ts +0 -99
- package/src/operations/behavior.operation.annotation.remove.ts +0 -150
- package/src/operations/behavior.operation.block.set.ts +0 -104
- package/src/operations/behavior.operation.block.unset.ts +0 -54
- package/src/operations/behavior.operation.child.set.ts +0 -107
- package/src/operations/behavior.operation.child.unset.ts +0 -116
- package/src/operations/behavior.operation.decorator.add.ts +0 -131
- package/src/operations/behavior.operation.delete.ts +0 -294
- package/src/operations/behavior.operation.insert.block.ts +0 -495
- package/src/operations/behavior.operation.insert.child.ts +0 -129
- package/src/operations/behavior.operation.insert.text.ts +0 -8
- package/src/operations/behavior.operation.move.backward.ts +0 -12
- package/src/operations/behavior.operation.move.block.ts +0 -44
- package/src/operations/behavior.operation.move.forward.ts +0 -11
- package/src/operations/behavior.operation.select.ts +0 -27
- package/src/operations/behavior.operations.ts +0 -221
- package/src/plugins/_exports/index.ts +0 -1
- package/src/plugins/index.ts +0 -3
- package/src/plugins/plugin.behavior.tsx +0 -24
- package/src/plugins/plugin.editor-ref.tsx +0 -17
- package/src/plugins/plugin.event-listener.tsx +0 -68
- package/src/plugins/plugin.internal.auto-close-brackets.test.tsx +0 -71
- package/src/plugins/plugin.internal.auto-close-brackets.ts +0 -62
- package/src/plugins/plugin.internal.change-ref.tsx +0 -19
- package/src/plugins/plugin.internal.portable-text-editor-ref.tsx +0 -16
- package/src/plugins/plugin.internal.slate-editor-ref.tsx +0 -15
- package/src/priority/priority.core.ts +0 -3
- package/src/priority/priority.sort.test.ts +0 -319
- package/src/priority/priority.sort.ts +0 -123
- package/src/priority/priority.types.ts +0 -24
- package/src/selectors/_exports/index.ts +0 -1
- package/src/selectors/drag-selection.test.ts +0 -578
- package/src/selectors/drag-selection.ts +0 -118
- package/src/selectors/index.ts +0 -54
- package/src/selectors/selector.get-active-annotation-marks.ts +0 -12
- package/src/selectors/selector.get-active-annotations.ts +0 -36
- package/src/selectors/selector.get-active-decorators.ts +0 -29
- package/src/selectors/selector.get-active-list-item.ts +0 -38
- package/src/selectors/selector.get-active-style.ts +0 -38
- package/src/selectors/selector.get-anchor-block.ts +0 -22
- package/src/selectors/selector.get-anchor-child.ts +0 -36
- package/src/selectors/selector.get-anchor-span.ts +0 -17
- package/src/selectors/selector.get-anchor-text-block.ts +0 -18
- package/src/selectors/selector.get-block-offsets.ts +0 -34
- package/src/selectors/selector.get-caret-word-selection.test.ts +0 -284
- package/src/selectors/selector.get-caret-word-selection.ts +0 -134
- package/src/selectors/selector.get-first-block.ts +0 -14
- package/src/selectors/selector.get-focus-block-object.ts +0 -18
- package/src/selectors/selector.get-focus-block.ts +0 -23
- package/src/selectors/selector.get-focus-child.ts +0 -36
- package/src/selectors/selector.get-focus-inline-object.ts +0 -17
- package/src/selectors/selector.get-focus-list-block.ts +0 -18
- package/src/selectors/selector.get-focus-span.ts +0 -18
- package/src/selectors/selector.get-focus-text-block.ts +0 -18
- package/src/selectors/selector.get-last-block.ts +0 -16
- package/src/selectors/selector.get-mark-state.test.ts +0 -325
- package/src/selectors/selector.get-mark-state.ts +0 -263
- package/src/selectors/selector.get-next-block.ts +0 -29
- package/src/selectors/selector.get-next-inline-object.ts +0 -53
- package/src/selectors/selector.get-next-inline-objects.ts +0 -50
- package/src/selectors/selector.get-next-span.ts +0 -56
- package/src/selectors/selector.get-previous-block.ts +0 -29
- package/src/selectors/selector.get-previous-inline-object.ts +0 -50
- package/src/selectors/selector.get-previous-inline-objects.ts +0 -47
- package/src/selectors/selector.get-previous-span.ts +0 -53
- package/src/selectors/selector.get-selected-blocks.ts +0 -61
- package/src/selectors/selector.get-selected-spans.test.ts +0 -347
- package/src/selectors/selector.get-selected-spans.ts +0 -155
- package/src/selectors/selector.get-selected-text-blocks.ts +0 -73
- package/src/selectors/selector.get-selected-value.test.ts +0 -834
- package/src/selectors/selector.get-selected-value.ts +0 -66
- package/src/selectors/selector.get-selection-end-block.ts +0 -33
- package/src/selectors/selector.get-selection-end-child.ts +0 -33
- package/src/selectors/selector.get-selection-end-point.ts +0 -17
- package/src/selectors/selector.get-selection-start-block.ts +0 -33
- package/src/selectors/selector.get-selection-start-child.ts +0 -33
- package/src/selectors/selector.get-selection-start-point.ts +0 -17
- package/src/selectors/selector.get-selection-text.test.ts +0 -421
- package/src/selectors/selector.get-selection-text.ts +0 -27
- package/src/selectors/selector.get-selection.ts +0 -9
- package/src/selectors/selector.get-text-after.ts +0 -46
- package/src/selectors/selector.get-text-before.ts +0 -46
- package/src/selectors/selector.get-value.ts +0 -11
- package/src/selectors/selector.is-active-annotation.test.ts +0 -320
- package/src/selectors/selector.is-active-annotation.ts +0 -52
- package/src/selectors/selector.is-active-decorator.test.ts +0 -136
- package/src/selectors/selector.is-active-decorator.ts +0 -24
- package/src/selectors/selector.is-active-list-item.ts +0 -13
- package/src/selectors/selector.is-active-style.ts +0 -13
- package/src/selectors/selector.is-at-the-end-of-block.ts +0 -30
- package/src/selectors/selector.is-at-the-start-of-block.ts +0 -30
- package/src/selectors/selector.is-overlapping-selection.test.ts +0 -304
- package/src/selectors/selector.is-overlapping-selection.ts +0 -181
- package/src/selectors/selector.is-point-after-selection.ts +0 -97
- package/src/selectors/selector.is-point-before-selection.ts +0 -97
- package/src/selectors/selector.is-selecting-entire-blocks.ts +0 -43
- package/src/selectors/selector.is-selection-collapsed.ts +0 -17
- package/src/selectors/selector.is-selection-expanded.test.ts +0 -63
- package/src/selectors/selector.is-selection-expanded.ts +0 -9
- package/src/test/_exports/index.ts +0 -1
- package/src/test/gherkin-parameter-types.ts +0 -112
- package/src/test/index.ts +0 -1
- package/src/test/vitest/_exports/index.ts +0 -1
- package/src/test/vitest/index.ts +0 -3
- package/src/test/vitest/step-context.ts +0 -13
- package/src/test/vitest/step-definitions.tsx +0 -960
- package/src/test/vitest/test-editor.tsx +0 -198
- package/src/type-utils.ts +0 -29
- package/src/types/block-offset.ts +0 -9
- package/src/types/block-with-optional-key.ts +0 -25
- package/src/types/editor.ts +0 -509
- package/src/types/options.ts +0 -13
- package/src/types/paths.ts +0 -35
- package/src/types/slate-editor.ts +0 -50
- package/src/types/slate.ts +0 -27
- package/src/utils/_exports/index.ts +0 -1
- package/src/utils/asserters.ts +0 -9
- package/src/utils/index.ts +0 -24
- package/src/utils/key-generator.ts +0 -33
- package/src/utils/parse-blocks.test.ts +0 -836
- package/src/utils/parse-blocks.ts +0 -504
- package/src/utils/util.at-the-beginning-of-block.ts +0 -32
- package/src/utils/util.block-offset-to-block-selection-point.ts +0 -28
- package/src/utils/util.block-offset-to-selection-point.ts +0 -33
- package/src/utils/util.block-offset.test.ts +0 -375
- package/src/utils/util.block-offset.ts +0 -136
- package/src/utils/util.block-offsets-to-selection.ts +0 -38
- package/src/utils/util.child-selection-point-to-block-offset.ts +0 -51
- package/src/utils/util.get-block-end-point.ts +0 -35
- package/src/utils/util.get-block-start-point.ts +0 -31
- package/src/utils/util.get-selection-end-point.ts +0 -20
- package/src/utils/util.get-selection-start-point.ts +0 -20
- package/src/utils/util.get-text-block-text.ts +0 -8
- package/src/utils/util.is-empty-text-block.ts +0 -21
- package/src/utils/util.is-equal-selection-points.ts +0 -13
- package/src/utils/util.is-equal-selections.ts +0 -20
- package/src/utils/util.is-keyed-segment.ts +0 -8
- package/src/utils/util.is-selection-collapsed.ts +0 -16
- package/src/utils/util.is-selection-expanded.ts +0 -13
- package/src/utils/util.merge-text-blocks.ts +0 -40
- package/src/utils/util.reverse-selection.ts +0 -26
- package/src/utils/util.selection-point-to-block-offset.ts +0 -30
- package/src/utils/util.selection-point.ts +0 -22
- package/src/utils/util.slice-blocks.ts +0 -221
- package/src/utils/util.slice-text-block.test.ts +0 -190
- package/src/utils/util.slice-text-block.ts +0 -89
- package/src/utils/util.split-text-block.ts +0 -54
|
@@ -1,615 +0,0 @@
|
|
|
1
|
-
import type {PortableTextBlock} from '@sanity/types'
|
|
2
|
-
import {Element, Path, type Node, type Operation} from 'slate'
|
|
3
|
-
import type {EditorSchema} from '../editor/editor-schema'
|
|
4
|
-
import type {EditorContext} from '../editor/editor-snapshot'
|
|
5
|
-
import type {OmitFromUnion} from '../type-utils'
|
|
6
|
-
import {
|
|
7
|
-
getBlock,
|
|
8
|
-
getNode,
|
|
9
|
-
getParent,
|
|
10
|
-
getSpan,
|
|
11
|
-
isEditorNode,
|
|
12
|
-
isObjectNode,
|
|
13
|
-
isPartialSpanNode,
|
|
14
|
-
isSpanNode,
|
|
15
|
-
isTextBlockNode,
|
|
16
|
-
type EditorNode,
|
|
17
|
-
type ObjectNode,
|
|
18
|
-
type SpanNode,
|
|
19
|
-
type TextBlockNode,
|
|
20
|
-
} from './portable-text-node'
|
|
21
|
-
|
|
22
|
-
export function applyOperationToPortableText(
|
|
23
|
-
context: Pick<EditorContext, 'schema'>,
|
|
24
|
-
value: Array<PortableTextBlock>,
|
|
25
|
-
operation: OmitFromUnion<Operation, 'type', 'set_selection'>,
|
|
26
|
-
): Array<PortableTextBlock> {
|
|
27
|
-
const root = {children: value} as EditorNode<EditorSchema>
|
|
28
|
-
|
|
29
|
-
try {
|
|
30
|
-
const newRoot = applyOperationToPortableTextImmutable(
|
|
31
|
-
context,
|
|
32
|
-
root,
|
|
33
|
-
operation,
|
|
34
|
-
)
|
|
35
|
-
return newRoot.children as Array<PortableTextBlock>
|
|
36
|
-
} catch (e) {
|
|
37
|
-
console.error(e)
|
|
38
|
-
return value
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function applyOperationToPortableTextImmutable(
|
|
43
|
-
context: Pick<EditorContext, 'schema'>,
|
|
44
|
-
root: EditorNode<EditorSchema>,
|
|
45
|
-
operation: OmitFromUnion<Operation, 'type', 'set_selection'>,
|
|
46
|
-
): EditorNode<EditorSchema> {
|
|
47
|
-
switch (operation.type) {
|
|
48
|
-
case 'insert_node': {
|
|
49
|
-
const {path, node: insertedNode} = operation
|
|
50
|
-
const parent = getParent(context, root, path)
|
|
51
|
-
const index = path[path.length - 1]
|
|
52
|
-
|
|
53
|
-
if (!parent) {
|
|
54
|
-
return root
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
if (index > parent.children.length) {
|
|
58
|
-
return root
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (path.length === 1) {
|
|
62
|
-
// Inserting block at the root
|
|
63
|
-
|
|
64
|
-
if (isTextBlockNode(context, insertedNode)) {
|
|
65
|
-
// Text blocks can be inserted as is
|
|
66
|
-
const newBlock = {
|
|
67
|
-
...insertedNode,
|
|
68
|
-
children: insertedNode.children.map((child) => {
|
|
69
|
-
if ('__inline' in child) {
|
|
70
|
-
// Except for inline object children which need to have their
|
|
71
|
-
// `value` spread onto the block
|
|
72
|
-
return {
|
|
73
|
-
_key: child._key,
|
|
74
|
-
_type: child._type,
|
|
75
|
-
...('value' in child && typeof child.value === 'object'
|
|
76
|
-
? child.value
|
|
77
|
-
: {}),
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return child
|
|
82
|
-
}),
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
return {
|
|
86
|
-
...root,
|
|
87
|
-
children: insertChildren(root.children, index, newBlock),
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if (Element.isElement(insertedNode) && !('__inline' in insertedNode)) {
|
|
92
|
-
// Void blocks have to have their `value` spread onto the block
|
|
93
|
-
const newBlock = {
|
|
94
|
-
_key: insertedNode._key,
|
|
95
|
-
_type: insertedNode._type,
|
|
96
|
-
...('value' in insertedNode &&
|
|
97
|
-
typeof insertedNode.value === 'object'
|
|
98
|
-
? insertedNode.value
|
|
99
|
-
: {}),
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
return {
|
|
103
|
-
...root,
|
|
104
|
-
children: insertChildren(root.children, index, newBlock),
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
if (path.length === 2) {
|
|
110
|
-
// Inserting children into blocks
|
|
111
|
-
const blockIndex = path[0]
|
|
112
|
-
|
|
113
|
-
if (!isTextBlockNode(context, parent)) {
|
|
114
|
-
// Only text blocks can have children
|
|
115
|
-
return root
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
let newChild: SpanNode<EditorSchema> | ObjectNode | undefined
|
|
119
|
-
|
|
120
|
-
if (isPartialSpanNode(insertedNode)) {
|
|
121
|
-
// Text nodes can be inserted as is
|
|
122
|
-
newChild = insertedNode
|
|
123
|
-
} else if ('__inline' in insertedNode) {
|
|
124
|
-
// Void children have to have their `value` spread onto the block
|
|
125
|
-
newChild = {
|
|
126
|
-
_key: insertedNode._key,
|
|
127
|
-
_type: insertedNode._type,
|
|
128
|
-
...('value' in insertedNode &&
|
|
129
|
-
typeof insertedNode.value === 'object'
|
|
130
|
-
? insertedNode.value
|
|
131
|
-
: {}),
|
|
132
|
-
}
|
|
133
|
-
} else {
|
|
134
|
-
return root
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
return updateTextBlockAtIndex(context, root, blockIndex, (block) => ({
|
|
138
|
-
...block,
|
|
139
|
-
children: insertChildren(block.children, index, newChild),
|
|
140
|
-
}))
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
return root
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
case 'insert_text': {
|
|
147
|
-
const {path, offset, text} = operation
|
|
148
|
-
if (text.length === 0) {
|
|
149
|
-
return root
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
const span = getSpan(context, root, path)
|
|
153
|
-
if (!span) {
|
|
154
|
-
return root
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const blockIndex = path[0]
|
|
158
|
-
const childIndex = path[1]
|
|
159
|
-
const before = span.text.slice(0, offset)
|
|
160
|
-
const after = span.text.slice(offset)
|
|
161
|
-
const newSpan = {...span, text: before + text + after}
|
|
162
|
-
|
|
163
|
-
return updateTextBlockAtIndex(context, root, blockIndex, (block) => ({
|
|
164
|
-
...block,
|
|
165
|
-
children: replaceChild(block.children, childIndex, newSpan),
|
|
166
|
-
}))
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
case 'merge_node': {
|
|
170
|
-
const {path} = operation
|
|
171
|
-
|
|
172
|
-
const lastPathIndex = path.at(-1)
|
|
173
|
-
|
|
174
|
-
if (lastPathIndex === 0) {
|
|
175
|
-
return root
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
const node = getNode(context, root, path)
|
|
179
|
-
const prevPath = Path.previous(path)
|
|
180
|
-
const prev = getNode(context, root, prevPath)
|
|
181
|
-
const parent = getParent(context, root, path)
|
|
182
|
-
|
|
183
|
-
if (!node || !prev || !parent) {
|
|
184
|
-
return root
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
const index = path[path.length - 1]
|
|
188
|
-
|
|
189
|
-
if (isPartialSpanNode(node) && isPartialSpanNode(prev)) {
|
|
190
|
-
// Merging spans
|
|
191
|
-
const blockIndex = path[0]
|
|
192
|
-
const newPrev = {...prev, text: prev.text + node.text}
|
|
193
|
-
|
|
194
|
-
return updateTextBlockAtIndex(context, root, blockIndex, (block) => {
|
|
195
|
-
const newChildren = replaceChild(
|
|
196
|
-
block.children,
|
|
197
|
-
index - 1,
|
|
198
|
-
newPrev as never,
|
|
199
|
-
)
|
|
200
|
-
return {
|
|
201
|
-
...block,
|
|
202
|
-
children: removeChildren(newChildren, index),
|
|
203
|
-
}
|
|
204
|
-
})
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
if (isTextBlockNode(context, node) && isTextBlockNode(context, prev)) {
|
|
208
|
-
// Merging blocks
|
|
209
|
-
const newPrev = {
|
|
210
|
-
...prev,
|
|
211
|
-
children: [...prev.children, ...node.children],
|
|
212
|
-
}
|
|
213
|
-
const newChildren = replaceChild(root.children, index - 1, newPrev)
|
|
214
|
-
return {
|
|
215
|
-
...root,
|
|
216
|
-
children: removeChildren(newChildren, index),
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
return root
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
case 'move_node': {
|
|
224
|
-
const {path, newPath} = operation
|
|
225
|
-
|
|
226
|
-
if (Path.isAncestor(path, newPath)) {
|
|
227
|
-
return root
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
const node = getNode(context, root, path)
|
|
231
|
-
const parent = getParent(context, root, path)
|
|
232
|
-
const index = path[path.length - 1]
|
|
233
|
-
|
|
234
|
-
if (!node || !parent) {
|
|
235
|
-
return root
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
// First, remove the node from its current position
|
|
239
|
-
let newRoot: EditorNode<EditorSchema>
|
|
240
|
-
|
|
241
|
-
if (path.length === 1) {
|
|
242
|
-
// Removing block from root
|
|
243
|
-
newRoot = {
|
|
244
|
-
...root,
|
|
245
|
-
children: removeChildren(root.children, index),
|
|
246
|
-
}
|
|
247
|
-
} else if (path.length === 2) {
|
|
248
|
-
// Removing child from block
|
|
249
|
-
const blockIndex = path[0]
|
|
250
|
-
newRoot = updateTextBlockAtIndex(
|
|
251
|
-
context,
|
|
252
|
-
root,
|
|
253
|
-
blockIndex,
|
|
254
|
-
(block) => ({
|
|
255
|
-
...block,
|
|
256
|
-
children: removeChildren(block.children, index),
|
|
257
|
-
}),
|
|
258
|
-
)
|
|
259
|
-
} else {
|
|
260
|
-
return root
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
// This is tricky, but since the `path` and `newPath` both refer to
|
|
264
|
-
// the same snapshot in time, there's a mismatch. After either
|
|
265
|
-
// removing the original position, the second step's path can be out
|
|
266
|
-
// of date. So instead of using the `op.newPath` directly, we
|
|
267
|
-
// transform `op.path` to ascertain what the `newPath` would be after
|
|
268
|
-
// the operation was applied.
|
|
269
|
-
const truePath = Path.transform(path, operation)!
|
|
270
|
-
const newIndex = truePath[truePath.length - 1]
|
|
271
|
-
|
|
272
|
-
if (truePath.length === 1) {
|
|
273
|
-
// Inserting block at root
|
|
274
|
-
return {
|
|
275
|
-
...newRoot,
|
|
276
|
-
children: insertChildren(newRoot.children, newIndex, node as never),
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
if (truePath.length === 2) {
|
|
281
|
-
// Inserting child into block
|
|
282
|
-
const newBlockIndex = truePath[0]
|
|
283
|
-
const newParent = newRoot.children[newBlockIndex]
|
|
284
|
-
|
|
285
|
-
if (!newParent || !isTextBlockNode(context, newParent)) {
|
|
286
|
-
return root
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
return updateTextBlockAtIndex(
|
|
290
|
-
context,
|
|
291
|
-
newRoot,
|
|
292
|
-
newBlockIndex,
|
|
293
|
-
(block) => ({
|
|
294
|
-
...block,
|
|
295
|
-
children: insertChildren(block.children, newIndex, node as never),
|
|
296
|
-
}),
|
|
297
|
-
)
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
return root
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
case 'remove_node': {
|
|
304
|
-
const {path} = operation
|
|
305
|
-
const index = path[path.length - 1]
|
|
306
|
-
const parent = getParent(context, root, path)
|
|
307
|
-
|
|
308
|
-
if (!parent) {
|
|
309
|
-
return root
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
if (path.length === 1) {
|
|
313
|
-
// Removing block from root
|
|
314
|
-
return {
|
|
315
|
-
...root,
|
|
316
|
-
children: removeChildren(root.children, index),
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
if (path.length === 2) {
|
|
321
|
-
// Removing child from block
|
|
322
|
-
const blockIndex = path[0]
|
|
323
|
-
return updateTextBlockAtIndex(context, root, blockIndex, (block) => ({
|
|
324
|
-
...block,
|
|
325
|
-
children: removeChildren(block.children, index),
|
|
326
|
-
}))
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
return root
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
case 'remove_text': {
|
|
333
|
-
const {path, offset, text} = operation
|
|
334
|
-
|
|
335
|
-
if (text.length === 0) {
|
|
336
|
-
return root
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
const span = getSpan(context, root, path)
|
|
340
|
-
|
|
341
|
-
if (!span) {
|
|
342
|
-
return root
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
const blockIndex = path[0]
|
|
346
|
-
const childIndex = path[1]
|
|
347
|
-
const before = span.text.slice(0, offset)
|
|
348
|
-
const after = span.text.slice(offset + text.length)
|
|
349
|
-
const newSpan = {...span, text: before + after}
|
|
350
|
-
|
|
351
|
-
return updateTextBlockAtIndex(context, root, blockIndex, (block) => ({
|
|
352
|
-
...block,
|
|
353
|
-
children: replaceChild(block.children, childIndex, newSpan as never),
|
|
354
|
-
}))
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
case 'set_node': {
|
|
358
|
-
const {path, properties, newProperties} = operation
|
|
359
|
-
|
|
360
|
-
const node = getNode(context, root, path)
|
|
361
|
-
|
|
362
|
-
if (!node) {
|
|
363
|
-
return root
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
if (isEditorNode(node)) {
|
|
367
|
-
return root
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
if (isObjectNode(context, node)) {
|
|
371
|
-
const valueBefore = (
|
|
372
|
-
'value' in properties && typeof properties.value === 'object'
|
|
373
|
-
? properties.value
|
|
374
|
-
: {}
|
|
375
|
-
) as Partial<Node>
|
|
376
|
-
const valueAfter = (
|
|
377
|
-
'value' in newProperties && typeof newProperties.value === 'object'
|
|
378
|
-
? newProperties.value
|
|
379
|
-
: {}
|
|
380
|
-
) as Partial<Node>
|
|
381
|
-
|
|
382
|
-
const newNode = {...node}
|
|
383
|
-
|
|
384
|
-
for (const key in newProperties) {
|
|
385
|
-
if (key === 'value') {
|
|
386
|
-
continue
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
const value = newProperties[key as keyof Partial<Node>]
|
|
390
|
-
|
|
391
|
-
if (value == null) {
|
|
392
|
-
delete newNode[key]
|
|
393
|
-
} else {
|
|
394
|
-
newNode[key] = value
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
for (const key in properties) {
|
|
399
|
-
if (key === 'value') {
|
|
400
|
-
continue
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
if (!newProperties.hasOwnProperty(key)) {
|
|
404
|
-
delete newNode[key]
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
for (const key in valueAfter) {
|
|
409
|
-
const value = valueAfter[key as keyof Partial<Node>]
|
|
410
|
-
|
|
411
|
-
if (value == null) {
|
|
412
|
-
delete newNode[key]
|
|
413
|
-
} else {
|
|
414
|
-
newNode[key] = value
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
for (const key in valueBefore) {
|
|
419
|
-
if (!valueAfter.hasOwnProperty(key)) {
|
|
420
|
-
delete newNode[key]
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
if (path.length === 1) {
|
|
425
|
-
return {
|
|
426
|
-
...root,
|
|
427
|
-
children: replaceChild(root.children, path[0], newNode),
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
if (path.length === 2) {
|
|
432
|
-
return updateTextBlockAtIndex(context, root, path[0], (block) => ({
|
|
433
|
-
...block,
|
|
434
|
-
children: replaceChild(block.children, path[1], newNode),
|
|
435
|
-
}))
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
return root
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
if (isTextBlockNode(context, node)) {
|
|
442
|
-
const newNode = {...node}
|
|
443
|
-
|
|
444
|
-
for (const key in newProperties) {
|
|
445
|
-
if (key === 'children' || key === 'text') {
|
|
446
|
-
continue
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
const value = newProperties[key as keyof Partial<Node>]
|
|
450
|
-
|
|
451
|
-
if (value == null) {
|
|
452
|
-
delete newNode[key]
|
|
453
|
-
} else {
|
|
454
|
-
newNode[key] = value
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
// properties that were previously defined, but are now missing, must be deleted
|
|
459
|
-
for (const key in properties) {
|
|
460
|
-
if (!newProperties.hasOwnProperty(key)) {
|
|
461
|
-
delete newNode[key]
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
return {
|
|
466
|
-
...root,
|
|
467
|
-
children: replaceChild(root.children, path[0], newNode),
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
if (isPartialSpanNode(node)) {
|
|
472
|
-
const newNode = {...node}
|
|
473
|
-
|
|
474
|
-
for (const key in newProperties) {
|
|
475
|
-
if (key === 'text') {
|
|
476
|
-
continue
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
const value = newProperties[key as keyof Partial<Node>]
|
|
480
|
-
|
|
481
|
-
if (value == null) {
|
|
482
|
-
delete newNode[key]
|
|
483
|
-
} else {
|
|
484
|
-
newNode[key] = value
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
// properties that were previously defined, but are now missing, must be deleted
|
|
489
|
-
for (const key in properties) {
|
|
490
|
-
if (!newProperties.hasOwnProperty(key)) {
|
|
491
|
-
delete newNode[key]
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
return updateTextBlockAtIndex(context, root, path[0], (block) => ({
|
|
496
|
-
...block,
|
|
497
|
-
children: replaceChild(block.children, path[1], newNode),
|
|
498
|
-
}))
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
return root
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
case 'split_node': {
|
|
505
|
-
const {path, position, properties} = operation
|
|
506
|
-
|
|
507
|
-
if (path.length === 0) {
|
|
508
|
-
return root
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
const parent = getParent(context, root, path)
|
|
512
|
-
const index = path[path.length - 1]
|
|
513
|
-
|
|
514
|
-
if (!parent) {
|
|
515
|
-
return root
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
if (isEditorNode(parent)) {
|
|
519
|
-
const block = getBlock(root, path)
|
|
520
|
-
|
|
521
|
-
if (!block || !isTextBlockNode(context, block)) {
|
|
522
|
-
return root
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
const before = block.children.slice(0, position)
|
|
526
|
-
const after = block.children.slice(position)
|
|
527
|
-
const updatedTextBlockNode = {...block, children: before}
|
|
528
|
-
|
|
529
|
-
// _key is deliberately left out
|
|
530
|
-
const newTextBlockNode = {
|
|
531
|
-
...properties,
|
|
532
|
-
children: after,
|
|
533
|
-
_type: context.schema.block.name,
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
return {
|
|
537
|
-
...root,
|
|
538
|
-
children: insertChildren(
|
|
539
|
-
replaceChild(root.children, index, updatedTextBlockNode),
|
|
540
|
-
index + 1,
|
|
541
|
-
newTextBlockNode,
|
|
542
|
-
),
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
if (isTextBlockNode(context, parent)) {
|
|
547
|
-
const node = getNode(context, root, path)
|
|
548
|
-
|
|
549
|
-
if (!node || !isSpanNode(context, node)) {
|
|
550
|
-
return root
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
const blockIndex = path[0]
|
|
554
|
-
const before = node.text.slice(0, position)
|
|
555
|
-
const after = node.text.slice(position)
|
|
556
|
-
const updatedSpanNode = {...node, text: before}
|
|
557
|
-
|
|
558
|
-
// _key is deliberately left out
|
|
559
|
-
const newSpanNode = {
|
|
560
|
-
...properties,
|
|
561
|
-
text: after,
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
return updateTextBlockAtIndex(context, root, blockIndex, (block) => {
|
|
565
|
-
return {
|
|
566
|
-
...block,
|
|
567
|
-
children: insertChildren(
|
|
568
|
-
replaceChild(block.children, index, updatedSpanNode),
|
|
569
|
-
index + 1,
|
|
570
|
-
newSpanNode,
|
|
571
|
-
),
|
|
572
|
-
}
|
|
573
|
-
})
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
return root
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
function insertChildren<T>(children: T[], index: number, ...nodes: T[]): T[] {
|
|
582
|
-
return [...children.slice(0, index), ...nodes, ...children.slice(index)]
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
function removeChildren<T>(children: T[], index: number, count = 1): T[] {
|
|
586
|
-
return [...children.slice(0, index), ...children.slice(index + count)]
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
function replaceChild<T>(children: T[], index: number, newChild: T): T[] {
|
|
590
|
-
return [...children.slice(0, index), newChild, ...children.slice(index + 1)]
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
function updateTextBlockAtIndex(
|
|
594
|
-
context: Pick<EditorContext, 'schema'>,
|
|
595
|
-
root: EditorNode<EditorSchema>,
|
|
596
|
-
blockIndex: number,
|
|
597
|
-
updater: (block: TextBlockNode<EditorSchema>) => TextBlockNode<EditorSchema>,
|
|
598
|
-
): EditorNode<EditorSchema> {
|
|
599
|
-
const block = root.children.at(blockIndex)
|
|
600
|
-
|
|
601
|
-
if (!block) {
|
|
602
|
-
return root
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
if (!isTextBlockNode(context, block)) {
|
|
606
|
-
return root
|
|
607
|
-
}
|
|
608
|
-
|
|
609
|
-
const newBlock = updater(block)
|
|
610
|
-
|
|
611
|
-
return {
|
|
612
|
-
...root,
|
|
613
|
-
children: replaceChild(root.children, blockIndex, newBlock),
|
|
614
|
-
}
|
|
615
|
-
}
|