@portabletext/editor 1.23.0 → 1.25.0
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/behavior.core.cjs +249 -62
- package/lib/_chunks-cjs/behavior.core.cjs.map +1 -1
- package/lib/_chunks-cjs/{selector.is-selection-collapsed.cjs → selector.is-active-style.cjs} +158 -3
- package/lib/_chunks-cjs/selector.is-active-style.cjs.map +1 -0
- package/lib/_chunks-cjs/util.slice-blocks.cjs +23 -9
- package/lib/_chunks-cjs/util.slice-blocks.cjs.map +1 -1
- package/lib/_chunks-es/behavior.core.js +225 -38
- package/lib/_chunks-es/behavior.core.js.map +1 -1
- package/lib/_chunks-es/{selector.is-selection-collapsed.js → selector.is-active-style.js} +159 -4
- package/lib/_chunks-es/selector.is-active-style.js.map +1 -0
- package/lib/_chunks-es/util.slice-blocks.js +23 -9
- package/lib/_chunks-es/util.slice-blocks.js.map +1 -1
- package/lib/behaviors/index.cjs +27 -27
- package/lib/behaviors/index.cjs.map +1 -1
- package/lib/behaviors/index.d.cts +2830 -139
- package/lib/behaviors/index.d.ts +2830 -139
- package/lib/behaviors/index.js +1 -1
- package/lib/index.cjs +695 -526
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +8950 -246
- package/lib/index.d.ts +8950 -246
- package/lib/index.js +696 -525
- package/lib/index.js.map +1 -1
- package/lib/selectors/index.cjs +24 -171
- package/lib/selectors/index.cjs.map +1 -1
- package/lib/selectors/index.d.cts +73 -0
- package/lib/selectors/index.d.ts +73 -0
- package/lib/selectors/index.js +3 -151
- package/lib/selectors/index.js.map +1 -1
- package/package.json +11 -10
- package/src/behavior-actions/behavior.action.data-transfer-set.ts +7 -0
- package/src/behavior-actions/behavior.action.insert-blocks.ts +61 -0
- package/src/behavior-actions/behavior.actions.ts +159 -83
- package/src/behaviors/behavior.core.annotations.ts +29 -0
- package/src/behaviors/behavior.core.block-objects.ts +13 -13
- package/src/behaviors/behavior.core.decorators.ts +19 -0
- package/src/behaviors/behavior.core.deserialize.ts +46 -0
- package/src/behaviors/behavior.core.lists.ts +57 -23
- package/src/behaviors/behavior.core.serialize.ts +44 -0
- package/src/behaviors/behavior.core.style.ts +19 -0
- package/src/behaviors/behavior.core.ts +19 -0
- package/src/behaviors/behavior.types.ts +126 -89
- package/src/converters/converter.json.ts +53 -0
- package/src/converters/converter.portable-text.deserialize.test.ts +686 -0
- package/src/converters/converter.portable-text.ts +59 -0
- package/src/converters/converter.text-html.deserialize.test.ts +349 -0
- package/src/converters/converter.text-html.serialize.test.ts +233 -0
- package/src/converters/converter.text-html.ts +61 -0
- package/src/converters/converter.text-plain.test.ts +241 -0
- package/src/converters/converter.text-plain.ts +91 -0
- package/src/converters/converter.ts +65 -0
- package/src/converters/converters.ts +11 -0
- package/src/editor/Editable.tsx +3 -13
- package/src/editor/create-editor.ts +48 -6
- package/src/editor/editor-machine.ts +56 -2
- package/src/editor/editor-selector.ts +1 -0
- package/src/editor/editor-snapshot.ts +5 -0
- package/src/editor/plugins/create-with-event-listeners.ts +82 -106
- package/src/internal-utils/asserters.ts +9 -0
- package/src/internal-utils/mime-type.ts +1 -0
- package/src/internal-utils/parse-blocks.ts +136 -0
- package/src/internal-utils/test-key-generator.ts +9 -0
- package/src/selectors/selector.get-selected-spans.test.ts +1 -0
- package/src/selectors/selector.get-selection-text.test.ts +1 -0
- package/src/selectors/selector.is-active-decorator.test.ts +1 -0
- package/src/utils/util.slice-blocks.test.ts +87 -0
- package/src/utils/util.slice-blocks.ts +27 -10
- package/lib/_chunks-cjs/selector.is-selection-collapsed.cjs.map +0 -1
- package/lib/_chunks-es/selector.is-selection-collapsed.js.map +0 -1
- package/src/editor/plugins/__tests__/createWithInsertData.test.tsx +0 -181
- package/src/editor/plugins/createWithInsertData.ts +0 -425
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type {PortableTextBlock} from '@sanity/types'
|
|
2
|
+
import type {Converter} from '../converters/converter'
|
|
2
3
|
import {toPortableTextRange} from '../internal-utils/ranges'
|
|
3
4
|
import {fromSlateValue} from '../internal-utils/values'
|
|
4
5
|
import {KEY_TO_VALUE_ELEMENT} from '../internal-utils/weakMaps'
|
|
@@ -11,6 +12,7 @@ import {getActiveDecorators} from './get-active-decorators'
|
|
|
11
12
|
*/
|
|
12
13
|
export type EditorContext = {
|
|
13
14
|
activeDecorators: Array<string>
|
|
15
|
+
converters: Array<Converter>
|
|
14
16
|
keyGenerator: () => string
|
|
15
17
|
schema: EditorSchema
|
|
16
18
|
selection: EditorSelection
|
|
@@ -25,10 +27,12 @@ export type EditorSnapshot = {
|
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
export function createEditorSnapshot({
|
|
30
|
+
converters,
|
|
28
31
|
editor,
|
|
29
32
|
keyGenerator,
|
|
30
33
|
schema,
|
|
31
34
|
}: {
|
|
35
|
+
converters: Array<Converter>
|
|
32
36
|
editor: PortableTextSlateEditor
|
|
33
37
|
keyGenerator: () => string
|
|
34
38
|
schema: EditorSchema
|
|
@@ -45,6 +49,7 @@ export function createEditorSnapshot({
|
|
|
45
49
|
schema,
|
|
46
50
|
slateEditorInstance: editor,
|
|
47
51
|
}),
|
|
52
|
+
converters,
|
|
48
53
|
keyGenerator,
|
|
49
54
|
schema,
|
|
50
55
|
selection,
|
|
@@ -17,123 +17,55 @@ export function createWithEventListeners(
|
|
|
17
17
|
subscriptions.push(() => {
|
|
18
18
|
const subscription = editorActor.on('*', (event) => {
|
|
19
19
|
switch (event.type) {
|
|
20
|
-
case '
|
|
21
|
-
editorActor.send({
|
|
22
|
-
type: 'behavior event',
|
|
23
|
-
behaviorEvent: {
|
|
24
|
-
type: 'annotation.add',
|
|
25
|
-
annotation: event.annotation,
|
|
26
|
-
},
|
|
27
|
-
editor,
|
|
28
|
-
})
|
|
29
|
-
break
|
|
30
|
-
}
|
|
31
|
-
case 'annotation.remove': {
|
|
32
|
-
editorActor.send({
|
|
33
|
-
type: 'behavior event',
|
|
34
|
-
behaviorEvent: {
|
|
35
|
-
type: 'annotation.remove',
|
|
36
|
-
annotation: event.annotation,
|
|
37
|
-
},
|
|
38
|
-
editor,
|
|
39
|
-
})
|
|
40
|
-
break
|
|
41
|
-
}
|
|
42
|
-
case 'blur': {
|
|
43
|
-
editorActor.send({
|
|
44
|
-
type: 'behavior event',
|
|
45
|
-
behaviorEvent: {
|
|
46
|
-
type: 'blur',
|
|
47
|
-
},
|
|
48
|
-
editor,
|
|
49
|
-
})
|
|
50
|
-
break
|
|
51
|
-
}
|
|
52
|
-
case 'custom.*': {
|
|
20
|
+
case 'custom.*':
|
|
53
21
|
editorActor.send({
|
|
54
22
|
type: 'custom behavior event',
|
|
55
23
|
behaviorEvent: event.event,
|
|
56
24
|
editor,
|
|
57
25
|
})
|
|
58
26
|
break
|
|
59
|
-
|
|
60
|
-
case '
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
case '
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
case '
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
case '
|
|
94
|
-
|
|
95
|
-
type: 'behavior event',
|
|
96
|
-
behaviorEvent: {
|
|
97
|
-
type: 'insert.inline object',
|
|
98
|
-
inlineObject: event.inlineObject,
|
|
99
|
-
},
|
|
100
|
-
editor,
|
|
101
|
-
})
|
|
102
|
-
break
|
|
103
|
-
}
|
|
104
|
-
case 'list item.toggle': {
|
|
105
|
-
editorActor.send({
|
|
106
|
-
type: 'behavior event',
|
|
107
|
-
behaviorEvent: {
|
|
108
|
-
type: 'list item.toggle',
|
|
109
|
-
listItem: event.listItem,
|
|
110
|
-
},
|
|
111
|
-
editor,
|
|
112
|
-
})
|
|
113
|
-
break
|
|
114
|
-
}
|
|
115
|
-
case 'select': {
|
|
116
|
-
editorActor.send({
|
|
117
|
-
type: 'behavior event',
|
|
118
|
-
behaviorEvent: {
|
|
119
|
-
type: 'select',
|
|
120
|
-
selection: event.selection,
|
|
121
|
-
},
|
|
122
|
-
editor,
|
|
123
|
-
})
|
|
124
|
-
break
|
|
125
|
-
}
|
|
126
|
-
case 'style.toggle': {
|
|
27
|
+
|
|
28
|
+
case 'annotation.add':
|
|
29
|
+
case 'annotation.remove':
|
|
30
|
+
case 'annotation.toggle':
|
|
31
|
+
case 'blur':
|
|
32
|
+
case 'data transfer.set':
|
|
33
|
+
case 'decorator.add':
|
|
34
|
+
case 'decorator.remove':
|
|
35
|
+
case 'decorator.toggle':
|
|
36
|
+
case 'delete.backward':
|
|
37
|
+
case 'delete.block':
|
|
38
|
+
case 'delete.forward':
|
|
39
|
+
case 'delete.text':
|
|
40
|
+
case 'deserialization.failure':
|
|
41
|
+
case 'deserialization.success':
|
|
42
|
+
case 'focus':
|
|
43
|
+
case 'insert.block object':
|
|
44
|
+
case 'insert.inline object':
|
|
45
|
+
case 'insert.span':
|
|
46
|
+
case 'insert.text block':
|
|
47
|
+
case 'list item.add':
|
|
48
|
+
case 'list item.remove':
|
|
49
|
+
case 'list item.toggle':
|
|
50
|
+
case 'move.block':
|
|
51
|
+
case 'move.block down':
|
|
52
|
+
case 'move.block up':
|
|
53
|
+
case 'select':
|
|
54
|
+
case 'select.next block':
|
|
55
|
+
case 'select.previous block':
|
|
56
|
+
case 'serialization.failure':
|
|
57
|
+
case 'serialization.success':
|
|
58
|
+
case 'style.add':
|
|
59
|
+
case 'style.remove':
|
|
60
|
+
case 'style.toggle':
|
|
61
|
+
case 'text block.set':
|
|
62
|
+
case 'text block.unset':
|
|
127
63
|
editorActor.send({
|
|
128
64
|
type: 'behavior event',
|
|
129
|
-
behaviorEvent:
|
|
130
|
-
type: 'style.toggle',
|
|
131
|
-
style: event.style,
|
|
132
|
-
},
|
|
65
|
+
behaviorEvent: event,
|
|
133
66
|
editor,
|
|
134
67
|
})
|
|
135
68
|
break
|
|
136
|
-
}
|
|
137
69
|
}
|
|
138
70
|
})
|
|
139
71
|
|
|
@@ -146,9 +78,11 @@ export function createWithEventListeners(
|
|
|
146
78
|
deleteBackward,
|
|
147
79
|
deleteForward,
|
|
148
80
|
insertBreak,
|
|
81
|
+
insertData,
|
|
149
82
|
insertSoftBreak,
|
|
150
83
|
insertText,
|
|
151
84
|
select,
|
|
85
|
+
setFragmentData,
|
|
152
86
|
} = editor
|
|
153
87
|
|
|
154
88
|
editor.deleteBackward = (unit) => {
|
|
@@ -201,6 +135,23 @@ export function createWithEventListeners(
|
|
|
201
135
|
return
|
|
202
136
|
}
|
|
203
137
|
|
|
138
|
+
editor.insertData = (dataTransfer) => {
|
|
139
|
+
if (isApplyingBehaviorActions(editor)) {
|
|
140
|
+
insertData(dataTransfer)
|
|
141
|
+
return
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
editorActor.send({
|
|
145
|
+
type: 'behavior event',
|
|
146
|
+
behaviorEvent: {
|
|
147
|
+
type: 'deserialize',
|
|
148
|
+
dataTransfer,
|
|
149
|
+
},
|
|
150
|
+
editor,
|
|
151
|
+
})
|
|
152
|
+
return
|
|
153
|
+
}
|
|
154
|
+
|
|
204
155
|
editor.insertSoftBreak = () => {
|
|
205
156
|
if (isApplyingBehaviorActions(editor)) {
|
|
206
157
|
insertSoftBreak()
|
|
@@ -268,6 +219,31 @@ export function createWithEventListeners(
|
|
|
268
219
|
return
|
|
269
220
|
}
|
|
270
221
|
|
|
222
|
+
editor.setFragmentData = (dataTransfer, originEvent) => {
|
|
223
|
+
if (originEvent === 'drag') {
|
|
224
|
+
setFragmentData(dataTransfer)
|
|
225
|
+
return
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (isApplyingBehaviorActions(editor)) {
|
|
229
|
+
setFragmentData(dataTransfer)
|
|
230
|
+
return
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
dataTransfer.clearData()
|
|
234
|
+
|
|
235
|
+
editorActor.send({
|
|
236
|
+
type: 'behavior event',
|
|
237
|
+
behaviorEvent: {
|
|
238
|
+
type: 'serialize',
|
|
239
|
+
dataTransfer,
|
|
240
|
+
originEvent: originEvent ?? 'unknown',
|
|
241
|
+
},
|
|
242
|
+
editor,
|
|
243
|
+
})
|
|
244
|
+
return
|
|
245
|
+
}
|
|
246
|
+
|
|
271
247
|
return editor
|
|
272
248
|
}
|
|
273
249
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type {TypedObject} from '@sanity/types'
|
|
2
|
+
|
|
3
|
+
export function isTypedObject(object: unknown): object is TypedObject {
|
|
4
|
+
return isRecord(object) && typeof object._type === 'string'
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
8
|
+
return !!value && (typeof value === 'object' || typeof value === 'function')
|
|
9
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type MIMEType = `${string}/${string}`
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isPortableTextSpan,
|
|
3
|
+
isPortableTextTextBlock,
|
|
4
|
+
type PortableTextBlock,
|
|
5
|
+
} from '@sanity/types'
|
|
6
|
+
import type {EditorContext} from '../editor/editor-snapshot'
|
|
7
|
+
import {isTypedObject} from './asserters'
|
|
8
|
+
|
|
9
|
+
export function parseBlock({
|
|
10
|
+
context,
|
|
11
|
+
block,
|
|
12
|
+
}: {
|
|
13
|
+
context: Pick<EditorContext, 'keyGenerator' | 'schema'>
|
|
14
|
+
block: unknown
|
|
15
|
+
}): PortableTextBlock | undefined {
|
|
16
|
+
if (!isTypedObject(block)) {
|
|
17
|
+
return undefined
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (
|
|
21
|
+
block._type !== context.schema.block.name &&
|
|
22
|
+
!context.schema.blockObjects.some(
|
|
23
|
+
(blockObject) => blockObject.name === block._type,
|
|
24
|
+
)
|
|
25
|
+
) {
|
|
26
|
+
return undefined
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (!isPortableTextTextBlock(block)) {
|
|
30
|
+
return {
|
|
31
|
+
...block,
|
|
32
|
+
_key: context.keyGenerator(),
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const markDefKeyMap = new Map<string, string>()
|
|
37
|
+
const markDefs = (block.markDefs ?? []).flatMap((markDef) => {
|
|
38
|
+
if (
|
|
39
|
+
context.schema.annotations.some(
|
|
40
|
+
(annotation) => annotation.name === markDef._type,
|
|
41
|
+
)
|
|
42
|
+
) {
|
|
43
|
+
const _key = context.keyGenerator()
|
|
44
|
+
markDefKeyMap.set(markDef._key, _key)
|
|
45
|
+
|
|
46
|
+
return [
|
|
47
|
+
{
|
|
48
|
+
...markDef,
|
|
49
|
+
_key,
|
|
50
|
+
},
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return []
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
const children = block.children.flatMap((child) => {
|
|
58
|
+
if (!isTypedObject(child)) {
|
|
59
|
+
return []
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (
|
|
63
|
+
child._type !== context.schema.span.name &&
|
|
64
|
+
!context.schema.inlineObjects.some(
|
|
65
|
+
(inlineObject) => inlineObject.name === child._type,
|
|
66
|
+
)
|
|
67
|
+
) {
|
|
68
|
+
return []
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (!isPortableTextSpan(child)) {
|
|
72
|
+
return [
|
|
73
|
+
{
|
|
74
|
+
...child,
|
|
75
|
+
_key: context.keyGenerator(),
|
|
76
|
+
},
|
|
77
|
+
]
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const marks = (child.marks ?? []).flatMap((mark) => {
|
|
81
|
+
if (markDefKeyMap.has(mark)) {
|
|
82
|
+
return [markDefKeyMap.get(mark)]
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (
|
|
86
|
+
context.schema.decorators.some((decorator) => decorator.value === mark)
|
|
87
|
+
) {
|
|
88
|
+
return [mark]
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return []
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
return [
|
|
95
|
+
{
|
|
96
|
+
...child,
|
|
97
|
+
_key: context.keyGenerator(),
|
|
98
|
+
marks,
|
|
99
|
+
},
|
|
100
|
+
]
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
const parsedBlock = {
|
|
104
|
+
...block,
|
|
105
|
+
_key: context.keyGenerator(),
|
|
106
|
+
children:
|
|
107
|
+
children.length > 0
|
|
108
|
+
? children
|
|
109
|
+
: [
|
|
110
|
+
{
|
|
111
|
+
_key: context.keyGenerator(),
|
|
112
|
+
_type: context.schema.span.name,
|
|
113
|
+
text: '',
|
|
114
|
+
marks: [],
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
markDefs,
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (!context.schema.styles.find((style) => style.value === block.style)) {
|
|
121
|
+
const defaultStyle = context.schema.styles[0].value
|
|
122
|
+
|
|
123
|
+
if (defaultStyle !== undefined) {
|
|
124
|
+
parsedBlock.style = defaultStyle
|
|
125
|
+
} else {
|
|
126
|
+
delete parsedBlock.style
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (!context.schema.lists.find((list) => list.value === block.listItem)) {
|
|
131
|
+
delete parsedBlock.listItem
|
|
132
|
+
delete parsedBlock.level
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return parsedBlock
|
|
136
|
+
}
|
|
@@ -134,6 +134,24 @@ describe(sliceBlocks.name, () => {
|
|
|
134
134
|
).toEqual([b2])
|
|
135
135
|
})
|
|
136
136
|
|
|
137
|
+
test('starting selection on a block object', () => {
|
|
138
|
+
expect(
|
|
139
|
+
sliceBlocks({
|
|
140
|
+
blocks,
|
|
141
|
+
selection: {
|
|
142
|
+
anchor: {
|
|
143
|
+
path: [{_key: b2._key}],
|
|
144
|
+
offset: 0,
|
|
145
|
+
},
|
|
146
|
+
focus: {
|
|
147
|
+
path: [{_key: b3._key}, 'children', {_key: b3.children[0]._key}],
|
|
148
|
+
offset: 3,
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
}),
|
|
152
|
+
).toEqual([b2, b3])
|
|
153
|
+
})
|
|
154
|
+
|
|
137
155
|
test('ending selection on a block object', () => {
|
|
138
156
|
expect(
|
|
139
157
|
sliceBlocks({
|
|
@@ -254,4 +272,73 @@ describe(sliceBlocks.name, () => {
|
|
|
254
272
|
},
|
|
255
273
|
])
|
|
256
274
|
})
|
|
275
|
+
|
|
276
|
+
test('starting on inline object', () => {
|
|
277
|
+
expect(
|
|
278
|
+
sliceBlocks({
|
|
279
|
+
blocks,
|
|
280
|
+
selection: {
|
|
281
|
+
anchor: {
|
|
282
|
+
path: [{_key: b4._key}, 'children', {_key: b4.children[1]._key}],
|
|
283
|
+
offset: 0,
|
|
284
|
+
},
|
|
285
|
+
focus: {
|
|
286
|
+
path: [{_key: b4._key}, 'children', {_key: b4.children[2]._key}],
|
|
287
|
+
offset: 4,
|
|
288
|
+
},
|
|
289
|
+
},
|
|
290
|
+
}),
|
|
291
|
+
).toEqual([
|
|
292
|
+
{
|
|
293
|
+
...b4,
|
|
294
|
+
children: [b4.children[1], b4.children[2]],
|
|
295
|
+
},
|
|
296
|
+
])
|
|
297
|
+
})
|
|
298
|
+
|
|
299
|
+
test('ending on inline object', () => {
|
|
300
|
+
expect(
|
|
301
|
+
sliceBlocks({
|
|
302
|
+
blocks,
|
|
303
|
+
selection: {
|
|
304
|
+
anchor: {
|
|
305
|
+
path: [{_key: b4._key}, 'children', {_key: b4.children[0]._key}],
|
|
306
|
+
offset: 0,
|
|
307
|
+
},
|
|
308
|
+
focus: {
|
|
309
|
+
path: [{_key: b4._key}, 'children', {_key: b4.children[1]._key}],
|
|
310
|
+
offset: 0,
|
|
311
|
+
},
|
|
312
|
+
},
|
|
313
|
+
}),
|
|
314
|
+
).toEqual([
|
|
315
|
+
{
|
|
316
|
+
...b4,
|
|
317
|
+
children: [b4.children[0], b4.children[1]],
|
|
318
|
+
},
|
|
319
|
+
])
|
|
320
|
+
})
|
|
321
|
+
|
|
322
|
+
test('starting and ending on inline object', () => {
|
|
323
|
+
expect(
|
|
324
|
+
sliceBlocks({
|
|
325
|
+
blocks,
|
|
326
|
+
selection: {
|
|
327
|
+
anchor: {
|
|
328
|
+
path: [{_key: b4._key}, 'children', {_key: b4.children[1]._key}],
|
|
329
|
+
offset: 0,
|
|
330
|
+
},
|
|
331
|
+
focus: {
|
|
332
|
+
path: [{_key: b4._key}, 'children', {_key: b4.children[1]._key}],
|
|
333
|
+
offset: 0,
|
|
334
|
+
},
|
|
335
|
+
},
|
|
336
|
+
}),
|
|
337
|
+
).toEqual([
|
|
338
|
+
{
|
|
339
|
+
...b4,
|
|
340
|
+
children: [b4.children[1]],
|
|
341
|
+
},
|
|
342
|
+
])
|
|
343
|
+
})
|
|
257
344
|
})
|
|
@@ -47,8 +47,20 @@ export function sliceBlocks({
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
for (const block of blocks) {
|
|
50
|
+
if (!isPortableTextTextBlock(block)) {
|
|
51
|
+
if (block._key === startBlockKey && block._key === endBlockKey) {
|
|
52
|
+
startBlock = block
|
|
53
|
+
break
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
50
57
|
if (block._key === startBlockKey) {
|
|
51
|
-
if (isPortableTextTextBlock(block)
|
|
58
|
+
if (!isPortableTextTextBlock(block)) {
|
|
59
|
+
startBlock = block
|
|
60
|
+
continue
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (startChildKey) {
|
|
52
64
|
for (const child of block.children) {
|
|
53
65
|
if (child._key === startChildKey) {
|
|
54
66
|
if (isPortableTextSpan(child)) {
|
|
@@ -66,17 +78,17 @@ export function sliceBlocks({
|
|
|
66
78
|
},
|
|
67
79
|
],
|
|
68
80
|
}
|
|
69
|
-
|
|
81
|
+
} else {
|
|
82
|
+
startBlock = {
|
|
83
|
+
...block,
|
|
84
|
+
children: [child],
|
|
85
|
+
}
|
|
70
86
|
}
|
|
71
87
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
children: [child],
|
|
88
|
+
if (startChildKey === endChildKey) {
|
|
89
|
+
break
|
|
75
90
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
if (startChildKey === endChildKey) {
|
|
79
|
-
break
|
|
91
|
+
continue
|
|
80
92
|
}
|
|
81
93
|
|
|
82
94
|
if (startBlock && isPortableTextTextBlock(startBlock)) {
|
|
@@ -107,7 +119,12 @@ export function sliceBlocks({
|
|
|
107
119
|
}
|
|
108
120
|
|
|
109
121
|
if (block._key === endBlockKey) {
|
|
110
|
-
if (isPortableTextTextBlock(block)
|
|
122
|
+
if (!isPortableTextTextBlock(block)) {
|
|
123
|
+
endBlock = block
|
|
124
|
+
break
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (endChildKey) {
|
|
111
128
|
endBlock = {
|
|
112
129
|
...block,
|
|
113
130
|
children: [],
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"selector.is-selection-collapsed.cjs","sources":["../../src/behavior-actions/behavior.guards.ts","../../src/selectors/selectors.ts","../../src/selectors/selector.is-selection-collapsed.ts"],"sourcesContent":["import {\n isPortableTextListBlock,\n isPortableTextTextBlock,\n type PortableTextListBlock,\n type PortableTextTextBlock,\n} from '@sanity/types'\nimport type {EditorSchema} from '../editor/define-schema'\n\n/**\n * @alpha\n */\nexport type BehaviorGuards = ReturnType<typeof createGuards>\n\nexport function createGuards({schema}: {schema: EditorSchema}) {\n function isListBlock(block: unknown): block is PortableTextListBlock {\n return isPortableTextListBlock(block) && block._type === schema.block.name\n }\n\n function isTextBlock(block: unknown): block is PortableTextTextBlock {\n return isPortableTextTextBlock(block) && block._type === schema.block.name\n }\n\n return {isListBlock, isTextBlock}\n}\n","import {\n isKeySegment,\n isPortableTextSpan,\n isPortableTextTextBlock,\n type KeyedSegment,\n type PortableTextBlock,\n type PortableTextListBlock,\n type PortableTextObject,\n type PortableTextSpan,\n type PortableTextTextBlock,\n} from '@sanity/types'\nimport {createGuards} from '../behavior-actions/behavior.guards'\nimport type {EditorSelector} from '../editor/editor-selector'\n\n/**\n * @public\n */\nexport const getFocusBlock: EditorSelector<\n {node: PortableTextBlock; path: [KeyedSegment]} | undefined\n> = ({context}) => {\n const key = context.selection\n ? isKeySegment(context.selection.focus.path[0])\n ? context.selection.focus.path[0]._key\n : undefined\n : undefined\n\n const node = key\n ? context.value.find((block) => block._key === key)\n : undefined\n\n return node && key ? {node, path: [{_key: key}]} : undefined\n}\n\n/**\n * @public\n */\nexport const getFocusListBlock: EditorSelector<\n {node: PortableTextListBlock; path: [KeyedSegment]} | undefined\n> = ({context}) => {\n const guards = createGuards(context)\n const focusBlock = getFocusBlock({context})\n\n return focusBlock && guards.isListBlock(focusBlock.node)\n ? {node: focusBlock.node, path: focusBlock.path}\n : undefined\n}\n\n/**\n * @public\n */\nexport const getFocusTextBlock: EditorSelector<\n {node: PortableTextTextBlock; path: [KeyedSegment]} | undefined\n> = ({context}) => {\n const focusBlock = getFocusBlock({context})\n\n return focusBlock && isPortableTextTextBlock(focusBlock.node)\n ? {node: focusBlock.node, path: focusBlock.path}\n : undefined\n}\n\n/**\n * @public\n */\nexport const getFocusBlockObject: EditorSelector<\n {node: PortableTextObject; path: [KeyedSegment]} | undefined\n> = ({context}) => {\n const focusBlock = getFocusBlock({context})\n\n return focusBlock && !isPortableTextTextBlock(focusBlock.node)\n ? {node: focusBlock.node, path: focusBlock.path}\n : undefined\n}\n\n/**\n * @public\n */\nexport const getFocusChild: EditorSelector<\n | {\n node: PortableTextObject | PortableTextSpan\n path: [KeyedSegment, 'children', KeyedSegment]\n }\n | undefined\n> = ({context}) => {\n const focusBlock = getFocusTextBlock({context})\n\n if (!focusBlock) {\n return undefined\n }\n\n const key = context.selection\n ? isKeySegment(context.selection.focus.path[2])\n ? context.selection.focus.path[2]._key\n : undefined\n : undefined\n\n const node = key\n ? focusBlock.node.children.find((span) => span._key === key)\n : undefined\n\n return node && key\n ? {node, path: [...focusBlock.path, 'children', {_key: key}]}\n : undefined\n}\n\n/**\n * @public\n */\nexport const getFocusSpan: EditorSelector<\n | {node: PortableTextSpan; path: [KeyedSegment, 'children', KeyedSegment]}\n | undefined\n> = ({context}) => {\n const focusChild = getFocusChild({context})\n\n return focusChild && isPortableTextSpan(focusChild.node)\n ? {node: focusChild.node, path: focusChild.path}\n : undefined\n}\n\n/**\n * @public\n */\nexport const getFirstBlock: EditorSelector<\n {node: PortableTextBlock; path: [KeyedSegment]} | undefined\n> = ({context}) => {\n const node = context.value[0]\n\n return node ? {node, path: [{_key: node._key}]} : undefined\n}\n\n/**\n * @public\n */\nexport const getLastBlock: EditorSelector<\n {node: PortableTextBlock; path: [KeyedSegment]} | undefined\n> = ({context}) => {\n const node = context.value[context.value.length - 1]\n ? context.value[context.value.length - 1]\n : undefined\n\n return node ? {node, path: [{_key: node._key}]} : undefined\n}\n\n/**\n * @public\n */\nexport const getSelectedBlocks: EditorSelector<\n Array<{node: PortableTextBlock; path: [KeyedSegment]}>\n> = ({context}) => {\n if (!context.selection) {\n return []\n }\n\n const selectedBlocks: Array<{node: PortableTextBlock; path: [KeyedSegment]}> =\n []\n const startKey = context.selection.backward\n ? isKeySegment(context.selection.focus.path[0])\n ? context.selection.focus.path[0]._key\n : undefined\n : isKeySegment(context.selection.anchor.path[0])\n ? context.selection.anchor.path[0]._key\n : undefined\n const endKey = context.selection.backward\n ? isKeySegment(context.selection.anchor.path[0])\n ? context.selection.anchor.path[0]._key\n : undefined\n : isKeySegment(context.selection.focus.path[0])\n ? context.selection.focus.path[0]._key\n : undefined\n\n if (!startKey || !endKey) {\n return selectedBlocks\n }\n\n for (const block of context.value) {\n if (block._key === startKey) {\n selectedBlocks.push({node: block, path: [{_key: block._key}]})\n\n if (startKey === endKey) {\n break\n }\n continue\n }\n\n if (block._key === endKey) {\n selectedBlocks.push({node: block, path: [{_key: block._key}]})\n break\n }\n\n if (selectedBlocks.length > 0) {\n selectedBlocks.push({node: block, path: [{_key: block._key}]})\n }\n }\n\n return selectedBlocks\n}\n\n/**\n * @public\n */\nexport const getSelectionStartBlock: EditorSelector<\n | {\n node: PortableTextBlock\n path: [KeyedSegment]\n }\n | undefined\n> = ({context}) => {\n if (!context.selection) {\n return undefined\n }\n\n const key = context.selection.backward\n ? isKeySegment(context.selection.focus.path[0])\n ? context.selection.focus.path[0]._key\n : undefined\n : isKeySegment(context.selection.anchor.path[0])\n ? context.selection.anchor.path[0]._key\n : undefined\n\n const node = key\n ? context.value.find((block) => block._key === key)\n : undefined\n\n return node && key ? {node, path: [{_key: key}]} : undefined\n}\n\n/**\n * @public\n */\nexport const getSelectionEndBlock: EditorSelector<\n | {\n node: PortableTextBlock\n path: [KeyedSegment]\n }\n | undefined\n> = ({context}) => {\n if (!context.selection) {\n return undefined\n }\n\n const key = context.selection.backward\n ? isKeySegment(context.selection.anchor.path[0])\n ? context.selection.anchor.path[0]._key\n : undefined\n : isKeySegment(context.selection.focus.path[0])\n ? context.selection.focus.path[0]._key\n : undefined\n\n const node = key\n ? context.value.find((block) => block._key === key)\n : undefined\n\n return node && key ? {node, path: [{_key: key}]} : undefined\n}\n\n/**\n * @public\n */\nexport const getPreviousBlock: EditorSelector<\n {node: PortableTextBlock; path: [KeyedSegment]} | undefined\n> = ({context}) => {\n let previousBlock: {node: PortableTextBlock; path: [KeyedSegment]} | undefined\n const selectionStartBlock = getSelectionStartBlock({context})\n\n if (!selectionStartBlock) {\n return undefined\n }\n\n let foundSelectionStartBlock = false\n\n for (const block of context.value) {\n if (block._key === selectionStartBlock.node._key) {\n foundSelectionStartBlock = true\n break\n }\n\n previousBlock = {node: block, path: [{_key: block._key}]}\n }\n\n if (foundSelectionStartBlock && previousBlock) {\n return previousBlock\n }\n\n return undefined\n}\n\n/**\n * @public\n */\nexport const getNextBlock: EditorSelector<\n {node: PortableTextBlock; path: [KeyedSegment]} | undefined\n> = ({context}) => {\n let nextBlock: {node: PortableTextBlock; path: [KeyedSegment]} | undefined\n const selectionEndBlock = getSelectionEndBlock({context})\n\n if (!selectionEndBlock) {\n return undefined\n }\n\n let foundSelectionEndBlock = false\n\n for (const block of context.value) {\n if (block._key === selectionEndBlock.node._key) {\n foundSelectionEndBlock = true\n continue\n }\n\n if (foundSelectionEndBlock) {\n nextBlock = {node: block, path: [{_key: block._key}]}\n break\n }\n }\n\n if (foundSelectionEndBlock && nextBlock) {\n return nextBlock\n }\n\n return undefined\n}\n","import type {EditorSelector} from '../editor/editor-selector'\n\n/**\n * @public\n */\nexport const isSelectionCollapsed: EditorSelector<boolean> = ({context}) => {\n return (\n JSON.stringify(context.selection?.anchor.path) ===\n JSON.stringify(context.selection?.focus.path) &&\n context.selection?.anchor.offset === context.selection?.focus.offset\n )\n}\n"],"names":["createGuards","schema","isListBlock","block","isPortableTextListBlock","_type","name","isTextBlock","isPortableTextTextBlock","getFocusBlock","context","key","selection","isKeySegment","focus","path","_key","undefined","node","value","find","getFocusListBlock","guards","focusBlock","getFocusTextBlock","getFocusBlockObject","getFocusChild","children","span","getFocusSpan","focusChild","isPortableTextSpan","getFirstBlock","getLastBlock","length","getSelectedBlocks","selectedBlocks","startKey","backward","anchor","endKey","push","getSelectionStartBlock","getSelectionEndBlock","getPreviousBlock","previousBlock","selectionStartBlock","foundSelectionStartBlock","getNextBlock","nextBlock","selectionEndBlock","foundSelectionEndBlock","isSelectionCollapsed","JSON","stringify","offset"],"mappings":"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"}
|