@portabletext/editor 1.55.13 → 1.55.15
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-cjs/{selector.is-selection-expanded.cjs → selector.get-focus-span.cjs} +27 -27
- package/lib/_chunks-cjs/selector.get-focus-span.cjs.map +1 -0
- package/lib/_chunks-cjs/selector.get-text-before.cjs +3 -3
- package/lib/_chunks-cjs/selector.get-text-before.cjs.map +1 -1
- package/lib/_chunks-cjs/selector.is-selecting-entire-blocks.cjs +291 -168
- package/lib/_chunks-cjs/selector.is-selecting-entire-blocks.cjs.map +1 -1
- package/lib/_chunks-cjs/util.child-selection-point-to-block-offset.cjs +1 -1
- package/lib/_chunks-cjs/util.child-selection-point-to-block-offset.cjs.map +1 -1
- package/lib/_chunks-cjs/{util.is-equal-selection-points.cjs → util.is-selection-collapsed.cjs} +7 -3
- package/lib/_chunks-cjs/util.is-selection-collapsed.cjs.map +1 -0
- package/lib/_chunks-cjs/util.slice-blocks.cjs +2 -2
- package/lib/_chunks-cjs/util.slice-text-block.cjs +2 -6
- package/lib/_chunks-cjs/util.slice-text-block.cjs.map +1 -1
- package/lib/_chunks-es/{selector.is-selection-expanded.js → selector.get-focus-span.js} +27 -27
- package/lib/_chunks-es/selector.get-focus-span.js.map +1 -0
- package/lib/_chunks-es/selector.get-text-before.js +1 -1
- package/lib/_chunks-es/selector.is-selecting-entire-blocks.js +266 -143
- package/lib/_chunks-es/selector.is-selecting-entire-blocks.js.map +1 -1
- package/lib/_chunks-es/util.child-selection-point-to-block-offset.js +1 -1
- package/lib/_chunks-es/{util.is-equal-selection-points.js → util.is-selection-collapsed.js} +7 -3
- package/lib/_chunks-es/util.is-selection-collapsed.js.map +1 -0
- package/lib/_chunks-es/util.slice-blocks.js +2 -2
- package/lib/_chunks-es/util.slice-text-block.js +1 -5
- package/lib/_chunks-es/util.slice-text-block.js.map +1 -1
- package/lib/behaviors/index.d.cts +3 -6
- package/lib/behaviors/index.d.ts +3 -6
- package/lib/index.cjs +357 -322
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +11 -20
- package/lib/index.d.ts +11 -20
- package/lib/index.js +296 -261
- package/lib/index.js.map +1 -1
- package/lib/plugins/index.cjs +16 -16
- package/lib/plugins/index.cjs.map +1 -1
- package/lib/plugins/index.d.cts +3 -6
- package/lib/plugins/index.d.ts +3 -6
- package/lib/plugins/index.js +1 -1
- package/lib/selectors/index.cjs +14 -14
- package/lib/selectors/index.cjs.map +1 -1
- package/lib/selectors/index.d.cts +3 -6
- package/lib/selectors/index.d.ts +3 -6
- package/lib/selectors/index.js +2 -2
- package/lib/utils/index.cjs +9 -9
- package/lib/utils/index.cjs.map +1 -1
- package/lib/utils/index.d.cts +3 -6
- package/lib/utils/index.d.ts +3 -6
- package/lib/utils/index.js +5 -5
- package/package.json +3 -3
- package/src/behaviors/behavior.abstract.ts +2 -1
- package/src/behaviors/behavior.core.dnd.ts +4 -4
- package/src/editor/Editable.tsx +8 -1
- package/src/editor/create-slate-editor.tsx +0 -1
- package/src/editor/editor-dom.ts +3 -3
- package/src/editor/editor-selector.ts +1 -13
- package/src/editor/editor-snapshot.ts +4 -19
- package/src/editor/plugins/createWithEditableAPI.ts +52 -13
- package/src/editor/plugins/createWithPortableTextMarkModel.ts +13 -4
- package/src/editor/plugins/with-plugins.ts +4 -8
- package/src/editor/range-decorations-machine.ts +24 -12
- package/src/internal-utils/create-test-snapshot.ts +2 -5
- package/src/internal-utils/paths.ts +65 -17
- package/src/internal-utils/ranges.test.ts +179 -0
- package/src/internal-utils/ranges.ts +39 -22
- package/src/internal-utils/test-editor.tsx +16 -1
- package/src/operations/behavior.operation.block.set.ts +10 -6
- package/src/operations/behavior.operation.block.unset.ts +10 -6
- package/src/operations/behavior.operation.child.set.ts +10 -6
- package/src/operations/behavior.operation.child.unset.ts +10 -6
- package/src/operations/behavior.operation.decorator.add.ts +17 -6
- package/src/operations/behavior.operation.delete.ts +8 -1
- package/src/operations/behavior.operation.insert.text.ts +34 -20
- package/src/operations/behavior.operation.move.block.ts +25 -3
- package/src/operations/behavior.operation.select.ts +9 -2
- package/src/selectors/selector.get-active-annotation-marks.ts +12 -0
- package/src/selectors/selector.get-active-annotations.ts +8 -20
- package/src/{editor/get-active-decorators.ts → selectors/selector.get-active-decorators.ts} +6 -11
- package/src/{internal-utils/mark-state.ts → selectors/selector.get-mark-state.ts} +41 -67
- package/src/selectors/selector.get-next-span.ts +56 -0
- package/src/selectors/selector.get-previous-span.ts +53 -0
- package/src/selectors/selector.is-active-annotation.ts +3 -1
- package/src/selectors/selector.is-active-decorator.ts +4 -1
- package/src/types/editor.ts +0 -2
- package/src/utils/util.is-selection-expanded.ts +13 -0
- package/lib/_chunks-cjs/selector.is-selection-expanded.cjs.map +0 -1
- package/lib/_chunks-cjs/util.is-equal-selection-points.cjs.map +0 -1
- package/lib/_chunks-es/selector.is-selection-expanded.js.map +0 -1
- package/lib/_chunks-es/util.is-equal-selection-points.js.map +0 -1
- package/src/editor/get-active-annotations.ts +0 -15
- package/src/editor/plugins/slate-plugin.update-mark-state.ts +0 -21
|
@@ -91,10 +91,14 @@ export const rangeDecorationsMachine = setup({
|
|
|
91
91
|
const rangeDecorationState: Array<DecoratedRange> = []
|
|
92
92
|
|
|
93
93
|
for (const rangeDecoration of context.pendingRangeDecorations) {
|
|
94
|
-
const slateRange = toSlateRange(
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
94
|
+
const slateRange = toSlateRange({
|
|
95
|
+
context: {
|
|
96
|
+
schema: context.schema,
|
|
97
|
+
value: context.slateEditor.value,
|
|
98
|
+
selection: rangeDecoration.selection,
|
|
99
|
+
},
|
|
100
|
+
blockIndexMap: context.slateEditor.blockIndexMap,
|
|
101
|
+
})
|
|
98
102
|
|
|
99
103
|
if (!Range.isRange(slateRange)) {
|
|
100
104
|
rangeDecoration.onMoved?.({
|
|
@@ -121,10 +125,14 @@ export const rangeDecorationsMachine = setup({
|
|
|
121
125
|
const rangeDecorationState: Array<DecoratedRange> = []
|
|
122
126
|
|
|
123
127
|
for (const rangeDecoration of event.rangeDecorations) {
|
|
124
|
-
const slateRange = toSlateRange(
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
+
const slateRange = toSlateRange({
|
|
129
|
+
context: {
|
|
130
|
+
schema: context.schema,
|
|
131
|
+
value: context.slateEditor.value,
|
|
132
|
+
selection: rangeDecoration.selection,
|
|
133
|
+
},
|
|
134
|
+
blockIndexMap: context.slateEditor.blockIndexMap,
|
|
135
|
+
})
|
|
128
136
|
|
|
129
137
|
if (!Range.isRange(slateRange)) {
|
|
130
138
|
rangeDecoration.onMoved?.({
|
|
@@ -152,10 +160,14 @@ export const rangeDecorationsMachine = setup({
|
|
|
152
160
|
const rangeDecorationState: Array<DecoratedRange> = []
|
|
153
161
|
|
|
154
162
|
for (const decoratedRange of context.slateEditor.decoratedRanges) {
|
|
155
|
-
const slateRange = toSlateRange(
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
163
|
+
const slateRange = toSlateRange({
|
|
164
|
+
context: {
|
|
165
|
+
schema: context.schema,
|
|
166
|
+
value: context.slateEditor.value,
|
|
167
|
+
selection: decoratedRange.rangeDecoration.selection,
|
|
168
|
+
},
|
|
169
|
+
blockIndexMap: context.slateEditor.blockIndexMap,
|
|
170
|
+
})
|
|
159
171
|
|
|
160
172
|
if (!Range.isRange(slateRange)) {
|
|
161
173
|
decoratedRange.rangeDecoration.onMoved?.({
|
|
@@ -5,7 +5,7 @@ import {createTestKeyGenerator} from './test-key-generator'
|
|
|
5
5
|
|
|
6
6
|
export function createTestSnapshot(snapshot: {
|
|
7
7
|
context?: Partial<EditorSnapshot['context']>
|
|
8
|
-
|
|
8
|
+
decoratorState?: Partial<EditorSnapshot['decoratorState']>
|
|
9
9
|
}): EditorSnapshot {
|
|
10
10
|
const context = {
|
|
11
11
|
converters: snapshot.context?.converters ?? [],
|
|
@@ -25,9 +25,6 @@ export function createTestSnapshot(snapshot: {
|
|
|
25
25
|
return {
|
|
26
26
|
blockIndexMap,
|
|
27
27
|
context,
|
|
28
|
-
|
|
29
|
-
activeAnnotations: snapshot.beta?.activeAnnotations ?? [],
|
|
30
|
-
activeDecorators: snapshot.beta?.activeDecorators ?? [],
|
|
31
|
-
},
|
|
28
|
+
decoratorState: snapshot?.decoratorState ?? {},
|
|
32
29
|
}
|
|
33
30
|
}
|
|
@@ -1,37 +1,67 @@
|
|
|
1
|
-
import
|
|
2
|
-
import type {
|
|
1
|
+
import type {Path} from 'slate'
|
|
2
|
+
import type {
|
|
3
|
+
EditorContext,
|
|
4
|
+
EditorSelectionPoint,
|
|
5
|
+
EditorSnapshot,
|
|
6
|
+
PortableTextBlock,
|
|
7
|
+
PortableTextObject,
|
|
8
|
+
PortableTextSpan,
|
|
9
|
+
} from '..'
|
|
3
10
|
import {
|
|
4
11
|
getBlockKeyFromSelectionPoint,
|
|
5
12
|
getChildKeyFromSelectionPoint,
|
|
6
13
|
} from '../selection/selection-point'
|
|
14
|
+
import {isSpan, isTextBlock} from './parse-blocks'
|
|
7
15
|
|
|
8
16
|
export function toSlatePath(
|
|
17
|
+
snapshot: {
|
|
18
|
+
context: Pick<EditorContext, 'schema' | 'value'>
|
|
19
|
+
} & Pick<EditorSnapshot, 'blockIndexMap'>,
|
|
9
20
|
path: EditorSelectionPoint['path'],
|
|
10
|
-
|
|
11
|
-
|
|
21
|
+
): {
|
|
22
|
+
block: PortableTextBlock | undefined
|
|
23
|
+
child: PortableTextSpan | PortableTextObject | undefined
|
|
24
|
+
path: Path
|
|
25
|
+
} {
|
|
12
26
|
const blockKey = getBlockKeyFromSelectionPoint({
|
|
13
27
|
path,
|
|
14
28
|
offset: 0,
|
|
15
29
|
})
|
|
16
30
|
|
|
17
31
|
if (!blockKey) {
|
|
18
|
-
return
|
|
32
|
+
return {
|
|
33
|
+
block: undefined,
|
|
34
|
+
child: undefined,
|
|
35
|
+
path: [],
|
|
36
|
+
}
|
|
19
37
|
}
|
|
20
38
|
|
|
21
|
-
const blockIndex =
|
|
39
|
+
const blockIndex = snapshot.blockIndexMap.get(blockKey)
|
|
22
40
|
|
|
23
41
|
if (blockIndex === undefined) {
|
|
24
|
-
return
|
|
42
|
+
return {
|
|
43
|
+
block: undefined,
|
|
44
|
+
child: undefined,
|
|
45
|
+
path: [],
|
|
46
|
+
}
|
|
25
47
|
}
|
|
26
48
|
|
|
27
|
-
const block =
|
|
49
|
+
const block = snapshot.context.value.at(blockIndex)
|
|
28
50
|
|
|
29
|
-
if (!block
|
|
30
|
-
return
|
|
51
|
+
if (!block) {
|
|
52
|
+
return {
|
|
53
|
+
block: undefined,
|
|
54
|
+
child: undefined,
|
|
55
|
+
path: [],
|
|
56
|
+
}
|
|
31
57
|
}
|
|
32
58
|
|
|
33
|
-
if (
|
|
34
|
-
return
|
|
59
|
+
if (!isTextBlock(snapshot.context, block)) {
|
|
60
|
+
return {
|
|
61
|
+
block,
|
|
62
|
+
child: undefined,
|
|
63
|
+
path: [blockIndex, 0],
|
|
64
|
+
}
|
|
35
65
|
}
|
|
36
66
|
|
|
37
67
|
const childKey = getChildKeyFromSelectionPoint({
|
|
@@ -40,23 +70,41 @@ export function toSlatePath(
|
|
|
40
70
|
})
|
|
41
71
|
|
|
42
72
|
if (!childKey) {
|
|
43
|
-
return
|
|
73
|
+
return {
|
|
74
|
+
block,
|
|
75
|
+
child: undefined,
|
|
76
|
+
path: [blockIndex, 0],
|
|
77
|
+
}
|
|
44
78
|
}
|
|
45
79
|
|
|
46
80
|
let childPath: Array<number> = []
|
|
47
81
|
let childIndex = -1
|
|
82
|
+
let pathChild: PortableTextSpan | PortableTextObject | undefined = undefined
|
|
48
83
|
|
|
49
84
|
for (const child of block.children) {
|
|
50
85
|
childIndex++
|
|
51
86
|
if (child._key === childKey) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
} else {
|
|
87
|
+
pathChild = child
|
|
88
|
+
if (isSpan(snapshot.context, child)) {
|
|
55
89
|
childPath = [childIndex]
|
|
90
|
+
} else {
|
|
91
|
+
childPath = [childIndex, 0]
|
|
56
92
|
}
|
|
57
93
|
break
|
|
58
94
|
}
|
|
59
95
|
}
|
|
60
96
|
|
|
61
|
-
|
|
97
|
+
if (childPath.length === 0) {
|
|
98
|
+
return {
|
|
99
|
+
block,
|
|
100
|
+
child: undefined,
|
|
101
|
+
path: [blockIndex, 0],
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return {
|
|
106
|
+
block,
|
|
107
|
+
child: pathChild,
|
|
108
|
+
path: [blockIndex].concat(childPath),
|
|
109
|
+
}
|
|
62
110
|
}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import {describe, expect, test} from 'vitest'
|
|
2
|
+
import {compileSchemaDefinition} from '../editor/editor-schema'
|
|
3
|
+
import {defineSchema} from '../editor/editor-schema-definition'
|
|
4
|
+
import {toSlateRange} from './ranges'
|
|
5
|
+
import {createTestKeyGenerator} from './test-key-generator'
|
|
6
|
+
|
|
7
|
+
describe(toSlateRange.name, () => {
|
|
8
|
+
const schema = compileSchemaDefinition(
|
|
9
|
+
defineSchema({
|
|
10
|
+
blockObjects: [{name: 'image'}],
|
|
11
|
+
inlineObjects: [
|
|
12
|
+
{name: 'stock-ticker', fields: [{name: 'symbol', type: 'string'}]},
|
|
13
|
+
],
|
|
14
|
+
}),
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
test("Scenario: Block object offset that doesn't exist", () => {
|
|
18
|
+
const keyGenerator = createTestKeyGenerator()
|
|
19
|
+
const blockObjectKey = keyGenerator()
|
|
20
|
+
|
|
21
|
+
const range = toSlateRange({
|
|
22
|
+
context: {
|
|
23
|
+
schema,
|
|
24
|
+
value: [
|
|
25
|
+
{
|
|
26
|
+
_key: blockObjectKey,
|
|
27
|
+
_type: 'image',
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
selection: {
|
|
31
|
+
anchor: {
|
|
32
|
+
path: [{_key: blockObjectKey}],
|
|
33
|
+
offset: 3,
|
|
34
|
+
},
|
|
35
|
+
focus: {
|
|
36
|
+
path: [{_key: blockObjectKey}],
|
|
37
|
+
offset: 3,
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
blockIndexMap: new Map([[blockObjectKey, 0]]),
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
expect(range).toEqual({
|
|
45
|
+
anchor: {path: [0, 0], offset: 0},
|
|
46
|
+
focus: {path: [0, 0], offset: 0},
|
|
47
|
+
})
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
test("Scenario: Child that doesn't exist", () => {
|
|
51
|
+
const keyGenerator = createTestKeyGenerator()
|
|
52
|
+
|
|
53
|
+
const blockKey = keyGenerator()
|
|
54
|
+
const removedChildKey = keyGenerator()
|
|
55
|
+
|
|
56
|
+
const range = toSlateRange({
|
|
57
|
+
context: {
|
|
58
|
+
schema,
|
|
59
|
+
value: [
|
|
60
|
+
{
|
|
61
|
+
_key: blockKey,
|
|
62
|
+
_type: 'block',
|
|
63
|
+
children: [
|
|
64
|
+
{
|
|
65
|
+
_key: keyGenerator(),
|
|
66
|
+
_type: 'span',
|
|
67
|
+
text: 'foobar',
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
selection: {
|
|
73
|
+
anchor: {
|
|
74
|
+
path: [{_key: blockKey}, 'children', {_key: removedChildKey}],
|
|
75
|
+
offset: 3,
|
|
76
|
+
},
|
|
77
|
+
focus: {
|
|
78
|
+
path: [{_key: blockKey}, 'children', {_key: removedChildKey}],
|
|
79
|
+
offset: 3,
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
blockIndexMap: new Map([[blockKey, 0]]),
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
expect(range).toEqual({
|
|
87
|
+
anchor: {path: [0, 0], offset: 0},
|
|
88
|
+
focus: {path: [0, 0], offset: 0},
|
|
89
|
+
})
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
test("Scenario: Span offset that doesn't exist", () => {
|
|
93
|
+
const keyGenerator = createTestKeyGenerator()
|
|
94
|
+
const blockKey = keyGenerator()
|
|
95
|
+
const spanKey = keyGenerator()
|
|
96
|
+
|
|
97
|
+
const range = toSlateRange({
|
|
98
|
+
context: {
|
|
99
|
+
schema,
|
|
100
|
+
value: [
|
|
101
|
+
{
|
|
102
|
+
_key: blockKey,
|
|
103
|
+
_type: 'block',
|
|
104
|
+
children: [
|
|
105
|
+
{
|
|
106
|
+
_key: spanKey,
|
|
107
|
+
_type: 'span',
|
|
108
|
+
text: 'foo',
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
selection: {
|
|
114
|
+
anchor: {
|
|
115
|
+
path: [{_key: blockKey}, 'children', {_key: spanKey}],
|
|
116
|
+
offset: 4,
|
|
117
|
+
},
|
|
118
|
+
focus: {
|
|
119
|
+
path: [{_key: blockKey}, 'children', {_key: spanKey}],
|
|
120
|
+
offset: 4,
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
blockIndexMap: new Map([[blockKey, 0]]),
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
expect(range).toEqual({
|
|
128
|
+
anchor: {path: [0, 0], offset: 3},
|
|
129
|
+
focus: {path: [0, 0], offset: 3},
|
|
130
|
+
})
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
test("Scenario: Inline object offset that doesn't exist", () => {
|
|
134
|
+
const keyGenerator = createTestKeyGenerator()
|
|
135
|
+
const blockKey = keyGenerator()
|
|
136
|
+
const inlineObjectKey = keyGenerator()
|
|
137
|
+
|
|
138
|
+
const range = toSlateRange({
|
|
139
|
+
context: {
|
|
140
|
+
schema,
|
|
141
|
+
value: [
|
|
142
|
+
{
|
|
143
|
+
_key: blockKey,
|
|
144
|
+
_type: 'block',
|
|
145
|
+
children: [
|
|
146
|
+
{_key: keyGenerator(), _type: 'span', text: 'foo'},
|
|
147
|
+
{
|
|
148
|
+
_key: inlineObjectKey,
|
|
149
|
+
_type: 'stock-ticker',
|
|
150
|
+
symbol: 'AAPL',
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
_key: keyGenerator(),
|
|
154
|
+
_type: 'span',
|
|
155
|
+
text: 'bar',
|
|
156
|
+
},
|
|
157
|
+
],
|
|
158
|
+
},
|
|
159
|
+
],
|
|
160
|
+
selection: {
|
|
161
|
+
anchor: {
|
|
162
|
+
path: [{_key: blockKey}, 'children', {_key: inlineObjectKey}],
|
|
163
|
+
offset: 3,
|
|
164
|
+
},
|
|
165
|
+
focus: {
|
|
166
|
+
path: [{_key: blockKey}, 'children', {_key: inlineObjectKey}],
|
|
167
|
+
offset: 3,
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
blockIndexMap: new Map([[blockKey, 0]]),
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
expect(range).toEqual({
|
|
175
|
+
anchor: {path: [0, 1, 0], offset: 0},
|
|
176
|
+
focus: {path: [0, 1, 0], offset: 0},
|
|
177
|
+
})
|
|
178
|
+
})
|
|
179
|
+
})
|
|
@@ -1,37 +1,54 @@
|
|
|
1
|
-
import {Point, type
|
|
2
|
-
import type {
|
|
1
|
+
import {Point, type Operation, type Range} from 'slate'
|
|
2
|
+
import type {EditorContext, EditorSnapshot} from '../editor/editor-snapshot'
|
|
3
|
+
import {isSpan} from './parse-blocks'
|
|
3
4
|
import {toSlatePath} from './paths'
|
|
4
5
|
|
|
5
|
-
export interface ObjectWithKeyAndType {
|
|
6
|
-
_key: string
|
|
7
|
-
_type: string
|
|
8
|
-
children?: ObjectWithKeyAndType[]
|
|
9
|
-
}
|
|
10
|
-
|
|
11
6
|
export function toSlateRange(
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
snapshot: {
|
|
8
|
+
context: Pick<EditorContext, 'schema' | 'value' | 'selection'>
|
|
9
|
+
} & Pick<EditorSnapshot, 'blockIndexMap'>,
|
|
14
10
|
): Range | null {
|
|
15
|
-
if (!selection
|
|
11
|
+
if (!snapshot.context.selection) {
|
|
16
12
|
return null
|
|
17
13
|
}
|
|
18
14
|
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
path: toSlatePath(selection.focus.path, editor),
|
|
25
|
-
offset: selection.focus.offset,
|
|
26
|
-
}
|
|
15
|
+
const anchorPath = toSlatePath(
|
|
16
|
+
snapshot,
|
|
17
|
+
snapshot.context.selection.anchor.path,
|
|
18
|
+
)
|
|
19
|
+
const focusPath = toSlatePath(snapshot, snapshot.context.selection.focus.path)
|
|
27
20
|
|
|
28
|
-
if (
|
|
21
|
+
if (anchorPath.path.length === 0 || focusPath.path.length === 0) {
|
|
29
22
|
return null
|
|
30
23
|
}
|
|
31
24
|
|
|
32
|
-
const
|
|
25
|
+
const anchorOffset = anchorPath.child
|
|
26
|
+
? isSpan(snapshot.context, anchorPath.child)
|
|
27
|
+
? Math.min(
|
|
28
|
+
anchorPath.child.text.length,
|
|
29
|
+
snapshot.context.selection.anchor.offset,
|
|
30
|
+
)
|
|
31
|
+
: 0
|
|
32
|
+
: 0
|
|
33
|
+
const focusOffset = focusPath.child
|
|
34
|
+
? isSpan(snapshot.context, focusPath.child)
|
|
35
|
+
? Math.min(
|
|
36
|
+
focusPath.child.text.length,
|
|
37
|
+
snapshot.context.selection.focus.offset,
|
|
38
|
+
)
|
|
39
|
+
: 0
|
|
40
|
+
: 0
|
|
33
41
|
|
|
34
|
-
return
|
|
42
|
+
return {
|
|
43
|
+
anchor: {
|
|
44
|
+
path: anchorPath.path,
|
|
45
|
+
offset: anchorOffset,
|
|
46
|
+
},
|
|
47
|
+
focus: {
|
|
48
|
+
path: focusPath.path,
|
|
49
|
+
offset: focusOffset,
|
|
50
|
+
},
|
|
51
|
+
}
|
|
35
52
|
}
|
|
36
53
|
|
|
37
54
|
export function moveRangeByOperation(
|
|
@@ -5,6 +5,7 @@ import {expect, vi} from 'vitest'
|
|
|
5
5
|
import {render} from 'vitest-browser-react'
|
|
6
6
|
import type {Editor} from '../editor'
|
|
7
7
|
import {PortableTextEditable} from '../editor/Editable'
|
|
8
|
+
import type {EditorActor} from '../editor/editor-machine'
|
|
8
9
|
import {EditorProvider} from '../editor/editor-provider'
|
|
9
10
|
import {
|
|
10
11
|
defineSchema,
|
|
@@ -13,6 +14,9 @@ import {
|
|
|
13
14
|
import type {EditorEmittedEvent} from '../editor/relay-machine'
|
|
14
15
|
import {EditorRefPlugin} from '../plugins/plugin.editor-ref'
|
|
15
16
|
import {EventListenerPlugin} from '../plugins/plugin.event-listener'
|
|
17
|
+
import {InternalEditorAfterRefPlugin} from '../plugins/plugin.internal.editor-actor-ref'
|
|
18
|
+
import {InternalSlateEditorRefPlugin} from '../plugins/plugin.internal.slate-editor-ref'
|
|
19
|
+
import type {PortableTextSlateEditor} from '../types/editor'
|
|
16
20
|
import {createTestKeyGenerator} from './test-key-generator'
|
|
17
21
|
|
|
18
22
|
export async function createTestEditor(
|
|
@@ -23,6 +27,8 @@ export async function createTestEditor(
|
|
|
23
27
|
} = {},
|
|
24
28
|
) {
|
|
25
29
|
const editorRef = React.createRef<Editor>()
|
|
30
|
+
const editorActorRef = React.createRef<EditorActor>()
|
|
31
|
+
const slateRef = React.createRef<PortableTextSlateEditor>()
|
|
26
32
|
const onEvent = vi.fn<() => EditorEmittedEvent>()
|
|
27
33
|
const keyGenerator = options.keyGenerator ?? createTestKeyGenerator()
|
|
28
34
|
|
|
@@ -35,6 +41,8 @@ export async function createTestEditor(
|
|
|
35
41
|
}}
|
|
36
42
|
>
|
|
37
43
|
<EditorRefPlugin ref={editorRef} />
|
|
44
|
+
<InternalEditorAfterRefPlugin ref={editorActorRef} />
|
|
45
|
+
<InternalSlateEditorRefPlugin ref={slateRef} />
|
|
38
46
|
<EventListenerPlugin on={onEvent} />
|
|
39
47
|
<PortableTextEditable />
|
|
40
48
|
</EditorProvider>,
|
|
@@ -44,5 +52,12 @@ export async function createTestEditor(
|
|
|
44
52
|
|
|
45
53
|
await vi.waitFor(() => expect.element(locator).toBeInTheDocument())
|
|
46
54
|
|
|
47
|
-
return {
|
|
55
|
+
return {
|
|
56
|
+
editorActorRef,
|
|
57
|
+
editorRef,
|
|
58
|
+
keyGenerator,
|
|
59
|
+
locator,
|
|
60
|
+
onEvent,
|
|
61
|
+
slateRef,
|
|
62
|
+
}
|
|
48
63
|
}
|
|
@@ -8,13 +8,17 @@ import type {BehaviorOperationImplementation} from './behavior.operations'
|
|
|
8
8
|
export const blockSetOperationImplementation: BehaviorOperationImplementation<
|
|
9
9
|
'block.set'
|
|
10
10
|
> = ({context, operation}) => {
|
|
11
|
-
const location = toSlateRange(
|
|
12
|
-
{
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
const location = toSlateRange({
|
|
12
|
+
context: {
|
|
13
|
+
schema: context.schema,
|
|
14
|
+
value: operation.editor.value,
|
|
15
|
+
selection: {
|
|
16
|
+
anchor: {path: operation.at, offset: 0},
|
|
17
|
+
focus: {path: operation.at, offset: 0},
|
|
18
|
+
},
|
|
15
19
|
},
|
|
16
|
-
operation.editor,
|
|
17
|
-
)
|
|
20
|
+
blockIndexMap: operation.editor.blockIndexMap,
|
|
21
|
+
})
|
|
18
22
|
|
|
19
23
|
if (!location) {
|
|
20
24
|
throw new Error(
|
|
@@ -9,13 +9,17 @@ import type {BehaviorOperationImplementation} from './behavior.operations'
|
|
|
9
9
|
export const blockUnsetOperationImplementation: BehaviorOperationImplementation<
|
|
10
10
|
'block.unset'
|
|
11
11
|
> = ({context, operation}) => {
|
|
12
|
-
const location = toSlateRange(
|
|
13
|
-
{
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
const location = toSlateRange({
|
|
13
|
+
context: {
|
|
14
|
+
schema: context.schema,
|
|
15
|
+
value: operation.editor.value,
|
|
16
|
+
selection: {
|
|
17
|
+
anchor: {path: operation.at, offset: 0},
|
|
18
|
+
focus: {path: operation.at, offset: 0},
|
|
19
|
+
},
|
|
16
20
|
},
|
|
17
|
-
operation.editor,
|
|
18
|
-
)
|
|
21
|
+
blockIndexMap: operation.editor.blockIndexMap,
|
|
22
|
+
})
|
|
19
23
|
|
|
20
24
|
if (!location) {
|
|
21
25
|
throw new Error(
|
|
@@ -5,13 +5,17 @@ import type {BehaviorOperationImplementation} from './behavior.operations'
|
|
|
5
5
|
export const childSetOperationImplementation: BehaviorOperationImplementation<
|
|
6
6
|
'child.set'
|
|
7
7
|
> = ({context, operation}) => {
|
|
8
|
-
const location = toSlateRange(
|
|
9
|
-
{
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
const location = toSlateRange({
|
|
9
|
+
context: {
|
|
10
|
+
schema: context.schema,
|
|
11
|
+
value: operation.editor.value,
|
|
12
|
+
selection: {
|
|
13
|
+
anchor: {path: operation.at, offset: 0},
|
|
14
|
+
focus: {path: operation.at, offset: 0},
|
|
15
|
+
},
|
|
12
16
|
},
|
|
13
|
-
operation.editor,
|
|
14
|
-
)
|
|
17
|
+
blockIndexMap: operation.editor.blockIndexMap,
|
|
18
|
+
})
|
|
15
19
|
|
|
16
20
|
if (!location) {
|
|
17
21
|
throw new Error(
|
|
@@ -6,13 +6,17 @@ import type {BehaviorOperationImplementation} from './behavior.operations'
|
|
|
6
6
|
export const childUnsetOperationImplementation: BehaviorOperationImplementation<
|
|
7
7
|
'child.unset'
|
|
8
8
|
> = ({context, operation}) => {
|
|
9
|
-
const location = toSlateRange(
|
|
10
|
-
{
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
const location = toSlateRange({
|
|
10
|
+
context: {
|
|
11
|
+
schema: context.schema,
|
|
12
|
+
value: operation.editor.value,
|
|
13
|
+
selection: {
|
|
14
|
+
anchor: {path: operation.at, offset: 0},
|
|
15
|
+
focus: {path: operation.at, offset: 0},
|
|
16
|
+
},
|
|
13
17
|
},
|
|
14
|
-
operation.editor,
|
|
15
|
-
)
|
|
18
|
+
blockIndexMap: operation.editor.blockIndexMap,
|
|
19
|
+
})
|
|
16
20
|
|
|
17
21
|
if (!location) {
|
|
18
22
|
throw new Error(
|
|
@@ -47,7 +47,14 @@ export const decoratorAddOperationImplementation: BehaviorOperationImplementatio
|
|
|
47
47
|
: undefined
|
|
48
48
|
|
|
49
49
|
const selection = manualSelection
|
|
50
|
-
? (toSlateRange(
|
|
50
|
+
? (toSlateRange({
|
|
51
|
+
context: {
|
|
52
|
+
schema: context.schema,
|
|
53
|
+
value: operation.editor.value,
|
|
54
|
+
selection: manualSelection,
|
|
55
|
+
},
|
|
56
|
+
blockIndexMap: operation.editor.blockIndexMap,
|
|
57
|
+
}) ?? editor.selection)
|
|
51
58
|
: editor.selection
|
|
52
59
|
|
|
53
60
|
if (!selection) {
|
|
@@ -109,10 +116,6 @@ export const decoratorAddOperationImplementation: BehaviorOperationImplementatio
|
|
|
109
116
|
|
|
110
117
|
const trimmedSelection = selectors.getTrimmedSelection({
|
|
111
118
|
blockIndexMap: editor.blockIndexMap,
|
|
112
|
-
beta: {
|
|
113
|
-
activeAnnotations: [],
|
|
114
|
-
activeDecorators: [],
|
|
115
|
-
},
|
|
116
119
|
context: {
|
|
117
120
|
converters: [],
|
|
118
121
|
keyGenerator: context.keyGenerator,
|
|
@@ -121,13 +124,21 @@ export const decoratorAddOperationImplementation: BehaviorOperationImplementatio
|
|
|
121
124
|
selection: newSelection,
|
|
122
125
|
value: newValue,
|
|
123
126
|
},
|
|
127
|
+
decoratorState: editor.decoratorState,
|
|
124
128
|
})
|
|
125
129
|
|
|
126
130
|
if (!trimmedSelection) {
|
|
127
131
|
throw new Error('Unable to find trimmed selection')
|
|
128
132
|
}
|
|
129
133
|
|
|
130
|
-
const newRange = toSlateRange(
|
|
134
|
+
const newRange = toSlateRange({
|
|
135
|
+
context: {
|
|
136
|
+
schema: context.schema,
|
|
137
|
+
value: operation.editor.value,
|
|
138
|
+
selection: trimmedSelection,
|
|
139
|
+
},
|
|
140
|
+
blockIndexMap: operation.editor.blockIndexMap,
|
|
141
|
+
})
|
|
131
142
|
|
|
132
143
|
if (!newRange) {
|
|
133
144
|
throw new Error('Unable to find new selection')
|
|
@@ -44,7 +44,14 @@ export const deleteOperationImplementation: BehaviorOperationImplementation<
|
|
|
44
44
|
return
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
const range = toSlateRange(
|
|
47
|
+
const range = toSlateRange({
|
|
48
|
+
context: {
|
|
49
|
+
schema: context.schema,
|
|
50
|
+
value: operation.editor.value,
|
|
51
|
+
selection: operation.at,
|
|
52
|
+
},
|
|
53
|
+
blockIndexMap: operation.editor.blockIndexMap,
|
|
54
|
+
})
|
|
48
55
|
|
|
49
56
|
if (!range) {
|
|
50
57
|
throw new Error(
|