@portabletext/editor 1.1.9 → 1.1.11
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/index.d.mts +295 -635
- package/lib/index.d.ts +295 -635
- package/lib/index.esm.js +360 -208
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +357 -205
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +360 -208
- package/lib/index.mjs.map +1 -1
- package/package.json +13 -13
- package/src/editor/Editable.tsx +0 -13
- package/src/editor/behavior/behavior.action.insert-break.ts +206 -0
- package/src/editor/behavior/behavior.actions.ts +91 -17
- package/src/editor/behavior/behavior.core.ts +8 -26
- package/src/editor/behavior/behavior.types.ts +41 -15
- package/src/editor/editor-machine.ts +124 -30
- package/src/editor/plugins/create-with-event-listeners.ts +55 -0
- package/src/editor/plugins/createWithUtils.ts +7 -1
- package/src/editor/plugins/index.ts +15 -18
- package/src/index.ts +1 -1
- package/src/types/editor.ts +5 -1
- package/src/editor/plugins/createWithInsertBreak.ts +0 -220
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type {Patch} from '@portabletext/patches'
|
|
2
2
|
import type {PortableTextBlock} from '@sanity/types'
|
|
3
3
|
import type {FocusEvent} from 'react'
|
|
4
|
+
import {Editor} from 'slate'
|
|
4
5
|
import {
|
|
5
6
|
assertEvent,
|
|
6
7
|
assign,
|
|
@@ -14,14 +15,19 @@ import type {
|
|
|
14
15
|
EditorSelection,
|
|
15
16
|
InvalidValueResolution,
|
|
16
17
|
PortableTextMemberSchemaTypes,
|
|
18
|
+
PortableTextSlateEditor,
|
|
17
19
|
} from '../types/editor'
|
|
18
20
|
import {toPortableTextRange} from '../utils/ranges'
|
|
19
21
|
import {fromSlateValue} from '../utils/values'
|
|
20
22
|
import {KEY_TO_VALUE_ELEMENT} from '../utils/weakMaps'
|
|
21
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
behaviorActionImplementations,
|
|
25
|
+
performDefaultAction,
|
|
26
|
+
} from './behavior/behavior.actions'
|
|
22
27
|
import type {
|
|
23
28
|
Behavior,
|
|
24
29
|
BehaviorAction,
|
|
30
|
+
BehaviorActionIntend,
|
|
25
31
|
BehaviorContext,
|
|
26
32
|
BehaviorEvent,
|
|
27
33
|
} from './behavior/behavior.types'
|
|
@@ -65,8 +71,16 @@ export type MutationEvent = {
|
|
|
65
71
|
type EditorEvent =
|
|
66
72
|
| {type: 'normalizing'}
|
|
67
73
|
| {type: 'done normalizing'}
|
|
68
|
-
|
|
|
69
|
-
|
|
74
|
+
| {
|
|
75
|
+
type: 'behavior event'
|
|
76
|
+
behaviorEvent: BehaviorEvent
|
|
77
|
+
editor: PortableTextSlateEditor
|
|
78
|
+
}
|
|
79
|
+
| {
|
|
80
|
+
type: 'behavior action intends'
|
|
81
|
+
editor: PortableTextSlateEditor
|
|
82
|
+
actionIntends: Array<BehaviorActionIntend>
|
|
83
|
+
}
|
|
70
84
|
| {
|
|
71
85
|
type: 'update schema'
|
|
72
86
|
schema: PortableTextMemberSchemaTypes
|
|
@@ -153,13 +167,19 @@ export const editorMachine = setup({
|
|
|
153
167
|
pendingEvents: [],
|
|
154
168
|
}),
|
|
155
169
|
'handle behavior event': enqueueActions(({context, event, enqueue}) => {
|
|
156
|
-
assertEvent(event, ['
|
|
170
|
+
assertEvent(event, ['behavior event'])
|
|
171
|
+
|
|
172
|
+
const defaultAction = {
|
|
173
|
+
...event.behaviorEvent,
|
|
174
|
+
editor: event.editor,
|
|
175
|
+
} satisfies BehaviorAction
|
|
157
176
|
|
|
158
177
|
const eventBehaviors = context.behaviors.filter(
|
|
159
|
-
(behavior) => behavior.on === event.type,
|
|
178
|
+
(behavior) => behavior.on === event.behaviorEvent.type,
|
|
160
179
|
)
|
|
161
180
|
|
|
162
181
|
if (eventBehaviors.length === 0) {
|
|
182
|
+
performDefaultAction({context, action: defaultAction})
|
|
163
183
|
return
|
|
164
184
|
}
|
|
165
185
|
|
|
@@ -178,6 +198,7 @@ export const editorMachine = setup({
|
|
|
178
198
|
console.warn(
|
|
179
199
|
`Unable to handle event ${event.type} due to missing selection`,
|
|
180
200
|
)
|
|
201
|
+
performDefaultAction({context, action: defaultAction})
|
|
181
202
|
return
|
|
182
203
|
}
|
|
183
204
|
|
|
@@ -187,32 +208,42 @@ export const editorMachine = setup({
|
|
|
187
208
|
selection,
|
|
188
209
|
} satisfies BehaviorContext
|
|
189
210
|
|
|
211
|
+
let behaviorOverwritten = false
|
|
212
|
+
|
|
190
213
|
for (const eventBehavior of eventBehaviors) {
|
|
191
214
|
const shouldRun =
|
|
192
215
|
eventBehavior.guard?.({
|
|
193
216
|
context: behaviorContext,
|
|
194
|
-
event,
|
|
217
|
+
event: event.behaviorEvent,
|
|
195
218
|
}) ?? true
|
|
196
219
|
|
|
197
220
|
if (!shouldRun) {
|
|
198
221
|
continue
|
|
199
222
|
}
|
|
200
223
|
|
|
201
|
-
const
|
|
202
|
-
|
|
224
|
+
const actionIntendSets = eventBehavior.actions.map((actionSet) =>
|
|
225
|
+
actionSet(
|
|
226
|
+
{context: behaviorContext, event: event.behaviorEvent},
|
|
227
|
+
shouldRun,
|
|
228
|
+
),
|
|
203
229
|
)
|
|
204
230
|
|
|
205
|
-
for (const
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
231
|
+
for (const actionIntends of actionIntendSets) {
|
|
232
|
+
behaviorOverwritten =
|
|
233
|
+
actionIntends.length > 0 &&
|
|
234
|
+
actionIntends.some((actionIntend) => actionIntend.type !== 'effect')
|
|
209
235
|
|
|
210
236
|
enqueue.raise({
|
|
211
|
-
|
|
237
|
+
type: 'behavior action intends',
|
|
212
238
|
editor: event.editor,
|
|
239
|
+
actionIntends,
|
|
213
240
|
})
|
|
214
241
|
}
|
|
215
242
|
}
|
|
243
|
+
|
|
244
|
+
if (!behaviorOverwritten) {
|
|
245
|
+
performDefaultAction({context, action: defaultAction})
|
|
246
|
+
}
|
|
216
247
|
}),
|
|
217
248
|
},
|
|
218
249
|
actors: {
|
|
@@ -244,23 +275,86 @@ export const editorMachine = setup({
|
|
|
244
275
|
'loading': {actions: emit({type: 'loading'})},
|
|
245
276
|
'done loading': {actions: emit({type: 'done loading'})},
|
|
246
277
|
'update schema': {actions: 'assign schema'},
|
|
247
|
-
'
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
278
|
+
'behavior event': {actions: 'handle behavior event'},
|
|
279
|
+
'behavior action intends': {
|
|
280
|
+
actions: [
|
|
281
|
+
({context, event}) => {
|
|
282
|
+
Editor.withoutNormalizing(event.editor, () => {
|
|
283
|
+
for (const actionIntend of event.actionIntends) {
|
|
284
|
+
const action = {
|
|
285
|
+
...actionIntend,
|
|
286
|
+
editor: event.editor,
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
switch (action.type) {
|
|
290
|
+
case 'delete backward': {
|
|
291
|
+
behaviorActionImplementations['delete backward']({
|
|
292
|
+
context,
|
|
293
|
+
action,
|
|
294
|
+
})
|
|
295
|
+
break
|
|
296
|
+
}
|
|
297
|
+
case 'delete text': {
|
|
298
|
+
behaviorActionImplementations['delete text']({
|
|
299
|
+
context,
|
|
300
|
+
action,
|
|
301
|
+
})
|
|
302
|
+
break
|
|
303
|
+
}
|
|
304
|
+
case 'insert break': {
|
|
305
|
+
behaviorActionImplementations['insert break']({
|
|
306
|
+
context,
|
|
307
|
+
action,
|
|
308
|
+
})
|
|
309
|
+
break
|
|
310
|
+
}
|
|
311
|
+
case 'insert soft break': {
|
|
312
|
+
behaviorActionImplementations['insert soft break']({
|
|
313
|
+
context,
|
|
314
|
+
action,
|
|
315
|
+
})
|
|
316
|
+
break
|
|
317
|
+
}
|
|
318
|
+
case 'insert text': {
|
|
319
|
+
behaviorActionImplementations['insert text']({
|
|
320
|
+
context,
|
|
321
|
+
action,
|
|
322
|
+
})
|
|
323
|
+
break
|
|
324
|
+
}
|
|
325
|
+
case 'insert text block': {
|
|
326
|
+
behaviorActionImplementations['insert text block']({
|
|
327
|
+
context,
|
|
328
|
+
action,
|
|
329
|
+
})
|
|
330
|
+
break
|
|
331
|
+
}
|
|
332
|
+
case 'set block': {
|
|
333
|
+
behaviorActionImplementations['set block']({
|
|
334
|
+
context,
|
|
335
|
+
action,
|
|
336
|
+
})
|
|
337
|
+
break
|
|
338
|
+
}
|
|
339
|
+
case 'unset block': {
|
|
340
|
+
behaviorActionImplementations['unset block']({
|
|
341
|
+
context,
|
|
342
|
+
action,
|
|
343
|
+
})
|
|
344
|
+
break
|
|
345
|
+
}
|
|
346
|
+
default: {
|
|
347
|
+
behaviorActionImplementations.effect({
|
|
348
|
+
context,
|
|
349
|
+
action,
|
|
350
|
+
})
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
})
|
|
355
|
+
event.editor.onChange()
|
|
356
|
+
},
|
|
357
|
+
],
|
|
264
358
|
},
|
|
265
359
|
},
|
|
266
360
|
initial: 'pristine',
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type {Editor} from 'slate'
|
|
2
|
+
import type {EditorActor} from '../editor-machine'
|
|
3
|
+
|
|
4
|
+
export function createWithEventListeners(editorActor: EditorActor) {
|
|
5
|
+
return function withEventListeners(editor: Editor) {
|
|
6
|
+
editor.deleteBackward = (unit) => {
|
|
7
|
+
editorActor.send({
|
|
8
|
+
type: 'behavior event',
|
|
9
|
+
behaviorEvent: {
|
|
10
|
+
type: 'delete backward',
|
|
11
|
+
unit,
|
|
12
|
+
},
|
|
13
|
+
editor,
|
|
14
|
+
})
|
|
15
|
+
return
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
editor.insertBreak = () => {
|
|
19
|
+
editorActor.send({
|
|
20
|
+
type: 'behavior event',
|
|
21
|
+
behaviorEvent: {
|
|
22
|
+
type: 'insert break',
|
|
23
|
+
},
|
|
24
|
+
editor,
|
|
25
|
+
})
|
|
26
|
+
return
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
editor.insertSoftBreak = () => {
|
|
30
|
+
editorActor.send({
|
|
31
|
+
type: 'behavior event',
|
|
32
|
+
behaviorEvent: {
|
|
33
|
+
type: 'insert soft break',
|
|
34
|
+
},
|
|
35
|
+
editor,
|
|
36
|
+
})
|
|
37
|
+
return
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
editor.insertText = (text, options) => {
|
|
41
|
+
editorActor.send({
|
|
42
|
+
type: 'behavior event',
|
|
43
|
+
behaviorEvent: {
|
|
44
|
+
type: 'insert text',
|
|
45
|
+
text,
|
|
46
|
+
options,
|
|
47
|
+
},
|
|
48
|
+
editor,
|
|
49
|
+
})
|
|
50
|
+
return
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return editor
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -75,13 +75,19 @@ export function createWithUtils({
|
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
editor.pteCreateTextBlock = (options: {
|
|
78
|
+
editor.pteCreateTextBlock = (options: {
|
|
79
|
+
decorators: Array<string>
|
|
80
|
+
listItem?: string
|
|
81
|
+
level?: number
|
|
82
|
+
}) => {
|
|
79
83
|
const block = toSlateValue(
|
|
80
84
|
[
|
|
81
85
|
{
|
|
82
86
|
_type: schemaTypes.block.name,
|
|
83
87
|
_key: editorActor.getSnapshot().context.keyGenerator(),
|
|
84
88
|
style: schemaTypes.styles[0].value || 'normal',
|
|
89
|
+
...(options.listItem ? {listItem: options.listItem} : {}),
|
|
90
|
+
...(options.level ? {level: options.level} : {}),
|
|
85
91
|
markDefs: [],
|
|
86
92
|
children: [
|
|
87
93
|
{
|
|
@@ -3,8 +3,8 @@ import type {BaseOperation, Editor, Node, NodeEntry} from 'slate'
|
|
|
3
3
|
import type {PortableTextSlateEditor} from '../../types/editor'
|
|
4
4
|
import type {createEditorOptions} from '../../types/options'
|
|
5
5
|
import {createOperationToPatches} from '../../utils/operationToPatches'
|
|
6
|
+
import {createWithEventListeners} from './create-with-event-listeners'
|
|
6
7
|
import {createWithEditableAPI} from './createWithEditableAPI'
|
|
7
|
-
import {createWithInsertBreak} from './createWithInsertBreak'
|
|
8
8
|
import {createWithMaxBlocks} from './createWithMaxBlocks'
|
|
9
9
|
import {createWithObjectKeys} from './createWithObjectKeys'
|
|
10
10
|
import {createWithPatches} from './createWithPatches'
|
|
@@ -98,8 +98,6 @@ export const withPlugins = <T extends Editor>(
|
|
|
98
98
|
|
|
99
99
|
const withPlaceholderBlock = createWithPlaceholderBlock()
|
|
100
100
|
|
|
101
|
-
const withInsertBreak = createWithInsertBreak(editorActor, schemaTypes)
|
|
102
|
-
|
|
103
101
|
const withUtils = createWithUtils({
|
|
104
102
|
editorActor,
|
|
105
103
|
schemaTypes,
|
|
@@ -109,6 +107,7 @@ export const withPlugins = <T extends Editor>(
|
|
|
109
107
|
editorActor,
|
|
110
108
|
schemaTypes,
|
|
111
109
|
)
|
|
110
|
+
const withEventListeners = createWithEventListeners(editorActor)
|
|
112
111
|
|
|
113
112
|
e.destroy = () => {
|
|
114
113
|
const originalFunctions = originalFnMap.get(e)
|
|
@@ -129,9 +128,7 @@ export const withPlugins = <T extends Editor>(
|
|
|
129
128
|
withUtils(
|
|
130
129
|
withPlaceholderBlock(
|
|
131
130
|
withPortableTextLists(
|
|
132
|
-
withPortableTextSelections(
|
|
133
|
-
withEditableAPI(withInsertBreak(e)),
|
|
134
|
-
),
|
|
131
|
+
withPortableTextSelections(withEditableAPI(e)),
|
|
135
132
|
),
|
|
136
133
|
),
|
|
137
134
|
),
|
|
@@ -145,18 +142,18 @@ export const withPlugins = <T extends Editor>(
|
|
|
145
142
|
|
|
146
143
|
// Ordering is important here, selection dealing last, data manipulation in the middle and core model stuff first.
|
|
147
144
|
return {
|
|
148
|
-
editor:
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
withEditableAPI(
|
|
145
|
+
editor: withEventListeners(
|
|
146
|
+
withSchemaTypes(
|
|
147
|
+
withObjectKeys(
|
|
148
|
+
withPortableTextMarkModel(
|
|
149
|
+
withPortableTextBlockStyle(
|
|
150
|
+
withPortableTextLists(
|
|
151
|
+
withPlaceholderBlock(
|
|
152
|
+
withUtils(
|
|
153
|
+
withMaxBlocks(
|
|
154
|
+
withUndoRedo(
|
|
155
|
+
withPatches(
|
|
156
|
+
withPortableTextSelections(withEditableAPI(e)),
|
|
160
157
|
),
|
|
161
158
|
),
|
|
162
159
|
),
|
package/src/index.ts
CHANGED
|
@@ -5,8 +5,8 @@ export type {
|
|
|
5
5
|
BehaviorContext,
|
|
6
6
|
BehaviorEvent,
|
|
7
7
|
BehaviorGuard,
|
|
8
|
-
RaiseBehaviorActionIntend,
|
|
9
8
|
PickFromUnion,
|
|
9
|
+
BehaviorActionIntendSet,
|
|
10
10
|
} from './editor/behavior/behavior.types'
|
|
11
11
|
export {PortableTextEditable} from './editor/Editable'
|
|
12
12
|
export type {PortableTextEditableProps} from './editor/Editable'
|
package/src/types/editor.ts
CHANGED
|
@@ -222,7 +222,11 @@ export interface PortableTextSlateEditor extends ReactEditor {
|
|
|
222
222
|
/**
|
|
223
223
|
* Helper function that creates a text block
|
|
224
224
|
*/
|
|
225
|
-
pteCreateTextBlock: (options: {
|
|
225
|
+
pteCreateTextBlock: (options: {
|
|
226
|
+
decorators: Array<string>
|
|
227
|
+
listItem?: string
|
|
228
|
+
level?: number
|
|
229
|
+
}) => Descendant
|
|
226
230
|
|
|
227
231
|
/**
|
|
228
232
|
* Undo
|
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
import {isEqual} from 'lodash'
|
|
2
|
-
import {Editor, Node, Path, Range, Transforms} from 'slate'
|
|
3
|
-
import type {
|
|
4
|
-
PortableTextMemberSchemaTypes,
|
|
5
|
-
PortableTextSlateEditor,
|
|
6
|
-
} from '../../types/editor'
|
|
7
|
-
import type {SlateTextBlock, VoidElement} from '../../types/slate'
|
|
8
|
-
import type {EditorActor} from '../editor-machine'
|
|
9
|
-
|
|
10
|
-
export function createWithInsertBreak(
|
|
11
|
-
editorActor: EditorActor,
|
|
12
|
-
types: PortableTextMemberSchemaTypes,
|
|
13
|
-
): (editor: PortableTextSlateEditor) => PortableTextSlateEditor {
|
|
14
|
-
return function withInsertBreak(
|
|
15
|
-
editor: PortableTextSlateEditor,
|
|
16
|
-
): PortableTextSlateEditor {
|
|
17
|
-
const {insertBreak} = editor
|
|
18
|
-
|
|
19
|
-
editor.insertBreak = () => {
|
|
20
|
-
if (!editor.selection) {
|
|
21
|
-
insertBreak()
|
|
22
|
-
return
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const [focusSpan] = Array.from(
|
|
26
|
-
Editor.nodes(editor, {
|
|
27
|
-
mode: 'lowest',
|
|
28
|
-
at: editor.selection.focus,
|
|
29
|
-
match: (n) => editor.isTextSpan(n),
|
|
30
|
-
voids: false,
|
|
31
|
-
}),
|
|
32
|
-
)[0] ?? [undefined]
|
|
33
|
-
const focusDecorators =
|
|
34
|
-
focusSpan.marks?.filter((mark) =>
|
|
35
|
-
types.decorators.some((decorator) => decorator.value === mark),
|
|
36
|
-
) ?? []
|
|
37
|
-
const focusAnnotations =
|
|
38
|
-
focusSpan.marks?.filter(
|
|
39
|
-
(mark) =>
|
|
40
|
-
!types.decorators.some((decorator) => decorator.value === mark),
|
|
41
|
-
) ?? []
|
|
42
|
-
|
|
43
|
-
const focusBlockPath = editor.selection.focus.path.slice(0, 1)
|
|
44
|
-
const focusBlock = Node.descendant(editor, focusBlockPath) as
|
|
45
|
-
| SlateTextBlock
|
|
46
|
-
| VoidElement
|
|
47
|
-
|
|
48
|
-
if (editor.isTextBlock(focusBlock)) {
|
|
49
|
-
const [start, end] = Range.edges(editor.selection)
|
|
50
|
-
const atTheStartOfBlock = isEqual(end, {
|
|
51
|
-
path: [...focusBlockPath, 0],
|
|
52
|
-
offset: 0,
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
if (atTheStartOfBlock && Range.isCollapsed(editor.selection)) {
|
|
56
|
-
Editor.insertNode(
|
|
57
|
-
editor,
|
|
58
|
-
editor.pteCreateTextBlock({
|
|
59
|
-
decorators: focusAnnotations.length === 0 ? focusDecorators : [],
|
|
60
|
-
}),
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
const [nextBlockPath] = Path.next(focusBlockPath)
|
|
64
|
-
|
|
65
|
-
Transforms.select(editor, {
|
|
66
|
-
anchor: {path: [nextBlockPath, 0], offset: 0},
|
|
67
|
-
focus: {path: [nextBlockPath, 0], offset: 0},
|
|
68
|
-
})
|
|
69
|
-
|
|
70
|
-
return
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const lastFocusBlockChild =
|
|
74
|
-
focusBlock.children[focusBlock.children.length - 1]
|
|
75
|
-
const atTheEndOfBlock = isEqual(start, {
|
|
76
|
-
path: [...focusBlockPath, focusBlock.children.length - 1],
|
|
77
|
-
offset: editor.isTextSpan(lastFocusBlockChild)
|
|
78
|
-
? lastFocusBlockChild.text.length
|
|
79
|
-
: 0,
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
if (atTheEndOfBlock && Range.isCollapsed(editor.selection)) {
|
|
83
|
-
Editor.insertNode(
|
|
84
|
-
editor,
|
|
85
|
-
editor.pteCreateTextBlock({
|
|
86
|
-
decorators: [],
|
|
87
|
-
}),
|
|
88
|
-
)
|
|
89
|
-
|
|
90
|
-
const [nextBlockPath] = Path.next(focusBlockPath)
|
|
91
|
-
|
|
92
|
-
Transforms.setSelection(editor, {
|
|
93
|
-
anchor: {path: [nextBlockPath, 0], offset: 0},
|
|
94
|
-
focus: {path: [nextBlockPath, 0], offset: 0},
|
|
95
|
-
})
|
|
96
|
-
|
|
97
|
-
return
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const isInTheMiddleOfNode = !atTheStartOfBlock && !atTheEndOfBlock
|
|
101
|
-
|
|
102
|
-
if (isInTheMiddleOfNode) {
|
|
103
|
-
Editor.withoutNormalizing(editor, () => {
|
|
104
|
-
if (!editor.selection) {
|
|
105
|
-
return
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
Transforms.splitNodes(editor, {
|
|
109
|
-
at: editor.selection,
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
const [nextNode, nextNodePath] = Editor.node(
|
|
113
|
-
editor,
|
|
114
|
-
Path.next(focusBlockPath),
|
|
115
|
-
{depth: 1},
|
|
116
|
-
)
|
|
117
|
-
|
|
118
|
-
Transforms.setSelection(editor, {
|
|
119
|
-
anchor: {path: [...nextNodePath, 0], offset: 0},
|
|
120
|
-
focus: {path: [...nextNodePath, 0], offset: 0},
|
|
121
|
-
})
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Assign new keys to markDefs that are now split across two blocks
|
|
125
|
-
*/
|
|
126
|
-
if (
|
|
127
|
-
editor.isTextBlock(nextNode) &&
|
|
128
|
-
nextNode.markDefs &&
|
|
129
|
-
nextNode.markDefs.length > 0
|
|
130
|
-
) {
|
|
131
|
-
const newMarkDefKeys = new Map<string, string>()
|
|
132
|
-
|
|
133
|
-
const prevNodeSpans = Array.from(
|
|
134
|
-
Node.children(editor, focusBlockPath),
|
|
135
|
-
)
|
|
136
|
-
.map((entry) => entry[0])
|
|
137
|
-
.filter((node) => editor.isTextSpan(node))
|
|
138
|
-
const children = Node.children(editor, nextNodePath)
|
|
139
|
-
|
|
140
|
-
for (const [child, childPath] of children) {
|
|
141
|
-
if (!editor.isTextSpan(child)) {
|
|
142
|
-
continue
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
const marks = child.marks ?? []
|
|
146
|
-
|
|
147
|
-
// Go through the marks of the span and figure out if any of
|
|
148
|
-
// them refer to annotations that are also present in the
|
|
149
|
-
// previous block
|
|
150
|
-
for (const mark of marks) {
|
|
151
|
-
if (
|
|
152
|
-
types.decorators.some(
|
|
153
|
-
(decorator) => decorator.value === mark,
|
|
154
|
-
)
|
|
155
|
-
) {
|
|
156
|
-
continue
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
if (
|
|
160
|
-
prevNodeSpans.some((prevNodeSpan) =>
|
|
161
|
-
prevNodeSpan.marks?.includes(mark),
|
|
162
|
-
) &&
|
|
163
|
-
!newMarkDefKeys.has(mark)
|
|
164
|
-
) {
|
|
165
|
-
// This annotation is both present in the previous block
|
|
166
|
-
// and this block, so let's assign a new key to it
|
|
167
|
-
newMarkDefKeys.set(
|
|
168
|
-
mark,
|
|
169
|
-
editorActor.getSnapshot().context.keyGenerator(),
|
|
170
|
-
)
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
const newMarks = marks.map(
|
|
175
|
-
(mark) => newMarkDefKeys.get(mark) ?? mark,
|
|
176
|
-
)
|
|
177
|
-
|
|
178
|
-
// No need to update the marks if they are the same
|
|
179
|
-
if (!isEqual(marks, newMarks)) {
|
|
180
|
-
Transforms.setNodes(
|
|
181
|
-
editor,
|
|
182
|
-
{marks: newMarks},
|
|
183
|
-
{
|
|
184
|
-
at: childPath,
|
|
185
|
-
},
|
|
186
|
-
)
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
// Time to update all the markDefs that need a new key because
|
|
191
|
-
// they've been split across blocks
|
|
192
|
-
const newMarkDefs = nextNode.markDefs.map((markDef) => ({
|
|
193
|
-
...markDef,
|
|
194
|
-
_key: newMarkDefKeys.get(markDef._key) ?? markDef._key,
|
|
195
|
-
}))
|
|
196
|
-
|
|
197
|
-
// No need to update the markDefs if they are the same
|
|
198
|
-
if (!isEqual(nextNode.markDefs, newMarkDefs)) {
|
|
199
|
-
Transforms.setNodes(
|
|
200
|
-
editor,
|
|
201
|
-
{markDefs: newMarkDefs},
|
|
202
|
-
{
|
|
203
|
-
at: nextNodePath,
|
|
204
|
-
match: (node) => editor.isTextBlock(node),
|
|
205
|
-
},
|
|
206
|
-
)
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
})
|
|
210
|
-
editor.onChange()
|
|
211
|
-
return
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
insertBreak()
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
return editor
|
|
219
|
-
}
|
|
220
|
-
}
|