@portabletext/editor 2.14.0 → 2.14.2
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/README.md +44 -0
- package/lib/_chunks-dts/behavior.types.action.d.cts +113 -128
- package/lib/_chunks-dts/behavior.types.action.d.ts +113 -128
- package/lib/index.cjs +145 -138
- package/lib/index.cjs.map +1 -1
- package/lib/index.js +145 -138
- package/lib/index.js.map +1 -1
- package/package.json +8 -8
- package/src/behaviors/behavior.abstract.insert.ts +19 -0
- package/src/editor/editor-machine.ts +37 -44
- package/src/editor/editor-provider.tsx +4 -0
- package/src/editor/plugins/createWithObjectKeys.ts +19 -15
- package/src/editor/plugins/createWithPortableTextMarkModel.ts +60 -53
- package/src/editor/plugins/createWithSchemaTypes.ts +18 -15
- package/src/editor/plugins/createWithUndoRedo.ts +3 -1
- package/src/editor/with-normalizing-node.ts +14 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@portabletext/editor",
|
|
3
|
-
"version": "2.14.
|
|
3
|
+
"version": "2.14.2",
|
|
4
4
|
"description": "Portable Text Editor made in React",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sanity",
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
"slate-dom": "^0.118.1",
|
|
86
86
|
"slate-react": "0.117.4",
|
|
87
87
|
"xstate": "^5.23.0",
|
|
88
|
-
"@portabletext/block-tools": "^3.5.
|
|
88
|
+
"@portabletext/block-tools": "^3.5.11",
|
|
89
89
|
"@portabletext/keyboard-shortcuts": "^1.1.1",
|
|
90
90
|
"@portabletext/patches": "^1.1.8",
|
|
91
91
|
"@portabletext/schema": "^1.2.0"
|
|
@@ -93,8 +93,8 @@
|
|
|
93
93
|
"devDependencies": {
|
|
94
94
|
"@sanity/diff-match-patch": "^3.2.0",
|
|
95
95
|
"@sanity/pkg-utils": "^8.1.14",
|
|
96
|
-
"@sanity/schema": "^4.10.
|
|
97
|
-
"@sanity/types": "^4.10.
|
|
96
|
+
"@sanity/schema": "^4.10.3",
|
|
97
|
+
"@sanity/types": "^4.10.3",
|
|
98
98
|
"@types/debug": "^4.1.12",
|
|
99
99
|
"@types/lodash": "^4.17.20",
|
|
100
100
|
"@types/lodash.startcase": "^4.4.9",
|
|
@@ -117,14 +117,14 @@
|
|
|
117
117
|
"vite": "^7.1.7",
|
|
118
118
|
"vitest": "^3.2.4",
|
|
119
119
|
"vitest-browser-react": "^1.0.1",
|
|
120
|
-
"@portabletext/sanity-bridge": "1.1.
|
|
120
|
+
"@portabletext/sanity-bridge": "1.1.14",
|
|
121
121
|
"@portabletext/test": "^0.0.0",
|
|
122
122
|
"racejar": "1.3.1"
|
|
123
123
|
},
|
|
124
124
|
"peerDependencies": {
|
|
125
|
-
"@portabletext/sanity-bridge": "^1.1.
|
|
126
|
-
"@sanity/schema": "^4.10.
|
|
127
|
-
"@sanity/types": "^4.10.
|
|
125
|
+
"@portabletext/sanity-bridge": "^1.1.14",
|
|
126
|
+
"@sanity/schema": "^4.10.3",
|
|
127
|
+
"@sanity/types": "^4.10.3",
|
|
128
128
|
"react": "^18.3 || ^19",
|
|
129
129
|
"rxjs": "^7.8.2"
|
|
130
130
|
},
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {getFocusTextBlock} from '../selectors/selector.get-focus-text-block'
|
|
2
2
|
import {getLastBlock} from '../selectors/selector.get-last-block'
|
|
3
|
+
import {isSelectionCollapsed} from '../utils'
|
|
3
4
|
import {getBlockEndPoint} from '../utils/util.get-block-end-point'
|
|
4
5
|
import {getBlockStartPoint} from '../utils/util.get-block-start-point'
|
|
5
6
|
import {isEmptyTextBlock} from '../utils/util.is-empty-text-block'
|
|
@@ -472,4 +473,22 @@ export const abstractInsertBehaviors = [
|
|
|
472
473
|
],
|
|
473
474
|
],
|
|
474
475
|
}),
|
|
476
|
+
defineBehavior({
|
|
477
|
+
on: 'insert.text',
|
|
478
|
+
guard: ({snapshot}) => {
|
|
479
|
+
const selection = snapshot.context.selection
|
|
480
|
+
|
|
481
|
+
if (!selection || isSelectionCollapsed(selection)) {
|
|
482
|
+
return false
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
return {selection}
|
|
486
|
+
},
|
|
487
|
+
actions: [
|
|
488
|
+
({event}, {selection}) => [
|
|
489
|
+
raise({type: 'delete', at: selection}),
|
|
490
|
+
raise(event),
|
|
491
|
+
],
|
|
492
|
+
],
|
|
493
|
+
}),
|
|
475
494
|
]
|
|
@@ -34,6 +34,7 @@ import type {
|
|
|
34
34
|
MutationEvent,
|
|
35
35
|
PatchEvent,
|
|
36
36
|
} from './relay-machine'
|
|
37
|
+
import {isNormalizingNode} from './with-normalizing-node'
|
|
37
38
|
|
|
38
39
|
export * from 'xstate/guards'
|
|
39
40
|
|
|
@@ -93,16 +94,10 @@ export type InternalEditorEvent =
|
|
|
93
94
|
type: 'focus'
|
|
94
95
|
editor: PortableTextSlateEditor
|
|
95
96
|
}
|
|
96
|
-
| {
|
|
97
|
-
type: 'normalizing'
|
|
98
|
-
}
|
|
99
97
|
| {
|
|
100
98
|
type: 'update selection'
|
|
101
99
|
selection: EditorSelection
|
|
102
100
|
}
|
|
103
|
-
| {
|
|
104
|
-
type: 'done normalizing'
|
|
105
|
-
}
|
|
106
101
|
| {
|
|
107
102
|
type: 'done syncing value'
|
|
108
103
|
}
|
|
@@ -128,6 +123,7 @@ export type InternalEditorEvent =
|
|
|
128
123
|
}
|
|
129
124
|
| {type: 'dragend'}
|
|
130
125
|
| {type: 'drop'}
|
|
126
|
+
| {type: 'add slate editor'; editor: PortableTextSlateEditor}
|
|
131
127
|
|
|
132
128
|
/**
|
|
133
129
|
* @internal
|
|
@@ -235,6 +231,13 @@ export const editorMachine = setup({
|
|
|
235
231
|
return new Set([...context.behaviors])
|
|
236
232
|
},
|
|
237
233
|
}),
|
|
234
|
+
'add slate editor to context': assign({
|
|
235
|
+
slateEditor: ({context, event}) => {
|
|
236
|
+
return event.type === 'add slate editor'
|
|
237
|
+
? event.editor
|
|
238
|
+
: context.slateEditor
|
|
239
|
+
},
|
|
240
|
+
}),
|
|
238
241
|
'emit patch event': emit(({event}) => {
|
|
239
242
|
assertEvent(event, 'internal.patch')
|
|
240
243
|
return event
|
|
@@ -363,6 +366,13 @@ export const editorMachine = setup({
|
|
|
363
366
|
|
|
364
367
|
return context.slateEditor.operations.length > 0
|
|
365
368
|
},
|
|
369
|
+
'slate is normalizing node': ({context}) => {
|
|
370
|
+
if (!context.slateEditor) {
|
|
371
|
+
return false
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
return isNormalizingNode(context.slateEditor)
|
|
375
|
+
},
|
|
366
376
|
},
|
|
367
377
|
}).createMachine({
|
|
368
378
|
id: 'editor',
|
|
@@ -386,6 +396,7 @@ export const editorMachine = setup({
|
|
|
386
396
|
'update maxBlocks': {
|
|
387
397
|
actions: assign({maxBlocks: ({event}) => event.maxBlocks}),
|
|
388
398
|
},
|
|
399
|
+
'add slate editor': {actions: 'add slate editor to context'},
|
|
389
400
|
'update selection': {
|
|
390
401
|
actions: [
|
|
391
402
|
assign({selection: ({event}) => event.selection}),
|
|
@@ -694,44 +705,26 @@ export const editorMachine = setup({
|
|
|
694
705
|
},
|
|
695
706
|
],
|
|
696
707
|
on: {
|
|
697
|
-
'
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
],
|
|
718
|
-
exit: [
|
|
719
|
-
() => {
|
|
720
|
-
debug(
|
|
721
|
-
'exit: setup->set up->writing->pristine->normalizing',
|
|
722
|
-
)
|
|
723
|
-
},
|
|
724
|
-
],
|
|
725
|
-
on: {
|
|
726
|
-
'done normalizing': {
|
|
727
|
-
target: 'idle',
|
|
728
|
-
},
|
|
729
|
-
'internal.patch': {
|
|
730
|
-
actions: 'defer event',
|
|
731
|
-
},
|
|
732
|
-
'mutation': {
|
|
733
|
-
actions: 'defer event',
|
|
734
|
-
},
|
|
708
|
+
'internal.patch': [
|
|
709
|
+
{
|
|
710
|
+
guard: 'slate is normalizing node',
|
|
711
|
+
actions: 'defer event',
|
|
712
|
+
},
|
|
713
|
+
{
|
|
714
|
+
actions: 'defer event',
|
|
715
|
+
target: '#editor.setup.set up.writing.dirty',
|
|
716
|
+
},
|
|
717
|
+
],
|
|
718
|
+
'mutation': [
|
|
719
|
+
{
|
|
720
|
+
guard: 'slate is normalizing node',
|
|
721
|
+
actions: 'defer event',
|
|
722
|
+
},
|
|
723
|
+
{
|
|
724
|
+
actions: 'defer event',
|
|
725
|
+
target: '#editor.setup.set up.writing.dirty',
|
|
726
|
+
},
|
|
727
|
+
],
|
|
735
728
|
},
|
|
736
729
|
},
|
|
737
730
|
},
|
|
@@ -70,6 +70,10 @@ export function EditorProvider(props: EditorProviderProps) {
|
|
|
70
70
|
unsubscribers.push(relayActorSubscription.unsubscribe)
|
|
71
71
|
|
|
72
72
|
internalEditor.actors.editorActor.start()
|
|
73
|
+
internalEditor.actors.editorActor.send({
|
|
74
|
+
type: 'add slate editor',
|
|
75
|
+
editor: internalEditor.editor._internal.slateEditor.instance,
|
|
76
|
+
})
|
|
73
77
|
internalEditor.actors.mutationActor.start()
|
|
74
78
|
internalEditor.actors.relayActor.start()
|
|
75
79
|
internalEditor.actors.syncActor.start()
|
|
@@ -3,6 +3,7 @@ import {isEqual} from 'lodash'
|
|
|
3
3
|
import {Editor, Element, Node, Path, Transforms} from 'slate'
|
|
4
4
|
import type {PortableTextSlateEditor} from '../../types/editor'
|
|
5
5
|
import type {EditorActor} from '../editor-machine'
|
|
6
|
+
import {withNormalizeNode} from '../with-normalizing-node'
|
|
6
7
|
import {isChangingRemotely} from '../withChanges'
|
|
7
8
|
import {isRedoing, isUndoing} from '../withUndoRedo'
|
|
8
9
|
|
|
@@ -198,30 +199,33 @@ export function createWithObjectKeys(editorActor: EditorActor) {
|
|
|
198
199
|
) {
|
|
199
200
|
// Set key on block itself
|
|
200
201
|
if (!node._key) {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
202
|
+
withNormalizeNode(editor, () => {
|
|
203
|
+
Transforms.setNodes(
|
|
204
|
+
editor,
|
|
205
|
+
{_key: editorActor.getSnapshot().context.keyGenerator()},
|
|
206
|
+
{at: path},
|
|
207
|
+
)
|
|
208
|
+
})
|
|
208
209
|
return
|
|
209
210
|
}
|
|
210
211
|
// Set keys on it's children
|
|
211
212
|
for (const [child, childPath] of Node.children(editor, path)) {
|
|
212
213
|
if (!child._key) {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
214
|
+
withNormalizeNode(editor, () => {
|
|
215
|
+
Transforms.setNodes(
|
|
216
|
+
editor,
|
|
217
|
+
{_key: editorActor.getSnapshot().context.keyGenerator()},
|
|
218
|
+
{at: childPath},
|
|
219
|
+
)
|
|
220
|
+
})
|
|
220
221
|
return
|
|
221
222
|
}
|
|
222
223
|
}
|
|
223
224
|
}
|
|
224
|
-
|
|
225
|
+
|
|
226
|
+
withNormalizeNode(editor, () => {
|
|
227
|
+
normalizeNode(entry)
|
|
228
|
+
})
|
|
225
229
|
}
|
|
226
230
|
|
|
227
231
|
return editor
|
|
@@ -15,6 +15,7 @@ import {getActiveDecorators} from '../../selectors/selector.get-active-decorator
|
|
|
15
15
|
import type {PortableTextSlateEditor} from '../../types/editor'
|
|
16
16
|
import type {EditorActor} from '../editor-machine'
|
|
17
17
|
import {getEditorSnapshot} from '../editor-selector'
|
|
18
|
+
import {withNormalizeNode} from '../with-normalizing-node'
|
|
18
19
|
import {isChangingRemotely} from '../withChanges'
|
|
19
20
|
import {isRedoing, isUndoing} from '../withUndoRedo'
|
|
20
21
|
|
|
@@ -50,12 +51,12 @@ export function createWithPortableTextMarkModel(
|
|
|
50
51
|
JSON.stringify(child, null, 2),
|
|
51
52
|
JSON.stringify(nextNode, null, 2),
|
|
52
53
|
)
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
withNormalizeNode(editor, () => {
|
|
55
|
+
Transforms.mergeNodes(editor, {
|
|
56
|
+
at: [childPath[0], childPath[1] + 1],
|
|
57
|
+
voids: true,
|
|
58
|
+
})
|
|
57
59
|
})
|
|
58
|
-
editorActor.send({type: 'done normalizing'})
|
|
59
60
|
return
|
|
60
61
|
}
|
|
61
62
|
}
|
|
@@ -66,9 +67,9 @@ export function createWithPortableTextMarkModel(
|
|
|
66
67
|
*/
|
|
67
68
|
if (editor.isTextBlock(node) && !Array.isArray(node.markDefs)) {
|
|
68
69
|
debug('Adding .markDefs to block node')
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
withNormalizeNode(editor, () => {
|
|
71
|
+
Transforms.setNodes(editor, {markDefs: []}, {at: path})
|
|
72
|
+
})
|
|
72
73
|
return
|
|
73
74
|
}
|
|
74
75
|
|
|
@@ -77,9 +78,9 @@ export function createWithPortableTextMarkModel(
|
|
|
77
78
|
*/
|
|
78
79
|
if (editor.isTextSpan(node) && !Array.isArray(node.marks)) {
|
|
79
80
|
debug('Adding .marks to span node')
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
withNormalizeNode(editor, () => {
|
|
82
|
+
Transforms.setNodes(editor, {marks: []}, {at: path})
|
|
83
|
+
})
|
|
83
84
|
return
|
|
84
85
|
}
|
|
85
86
|
|
|
@@ -99,13 +100,17 @@ export function createWithPortableTextMarkModel(
|
|
|
99
100
|
if (editor.isTextBlock(block)) {
|
|
100
101
|
if (node.text === '' && annotations && annotations.length > 0) {
|
|
101
102
|
debug('Removing annotations from empty span node')
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
103
|
+
withNormalizeNode(editor, () => {
|
|
104
|
+
Transforms.setNodes(
|
|
105
|
+
editor,
|
|
106
|
+
{
|
|
107
|
+
marks: node.marks?.filter((mark) =>
|
|
108
|
+
decorators.includes(mark),
|
|
109
|
+
),
|
|
110
|
+
},
|
|
111
|
+
{at: path},
|
|
112
|
+
)
|
|
113
|
+
})
|
|
109
114
|
return
|
|
110
115
|
}
|
|
111
116
|
}
|
|
@@ -131,17 +136,17 @@ export function createWithPortableTextMarkModel(
|
|
|
131
136
|
|
|
132
137
|
if (orphanedAnnotations.length > 0) {
|
|
133
138
|
debug('Removing orphaned annotations from span node')
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
139
|
+
withNormalizeNode(editor, () => {
|
|
140
|
+
Transforms.setNodes(
|
|
141
|
+
editor,
|
|
142
|
+
{
|
|
143
|
+
marks: marks.filter(
|
|
144
|
+
(mark) => !orphanedAnnotations.includes(mark),
|
|
145
|
+
),
|
|
146
|
+
},
|
|
147
|
+
{at: childPath},
|
|
148
|
+
)
|
|
149
|
+
})
|
|
145
150
|
return
|
|
146
151
|
}
|
|
147
152
|
}
|
|
@@ -169,17 +174,17 @@ export function createWithPortableTextMarkModel(
|
|
|
169
174
|
|
|
170
175
|
if (orphanedAnnotations.length > 0) {
|
|
171
176
|
debug('Removing orphaned annotations from span node')
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
177
|
+
withNormalizeNode(editor, () => {
|
|
178
|
+
Transforms.setNodes(
|
|
179
|
+
editor,
|
|
180
|
+
{
|
|
181
|
+
marks: marks.filter(
|
|
182
|
+
(mark) => !orphanedAnnotations.includes(mark),
|
|
183
|
+
),
|
|
184
|
+
},
|
|
185
|
+
{at: path},
|
|
186
|
+
)
|
|
187
|
+
})
|
|
183
188
|
return
|
|
184
189
|
}
|
|
185
190
|
}
|
|
@@ -200,9 +205,9 @@ export function createWithPortableTextMarkModel(
|
|
|
200
205
|
|
|
201
206
|
if (markDefs.length !== newMarkDefs.length) {
|
|
202
207
|
debug('Removing duplicate markDefs')
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
208
|
+
withNormalizeNode(editor, () => {
|
|
209
|
+
Transforms.setNodes(editor, {markDefs: newMarkDefs}, {at: path})
|
|
210
|
+
})
|
|
206
211
|
return
|
|
207
212
|
}
|
|
208
213
|
}
|
|
@@ -228,20 +233,22 @@ export function createWithPortableTextMarkModel(
|
|
|
228
233
|
})
|
|
229
234
|
if (node.markDefs && !isEqual(newMarkDefs, node.markDefs)) {
|
|
230
235
|
debug('Removing markDef not in use')
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
236
|
+
withNormalizeNode(editor, () => {
|
|
237
|
+
Transforms.setNodes(
|
|
238
|
+
editor,
|
|
239
|
+
{
|
|
240
|
+
markDefs: newMarkDefs,
|
|
241
|
+
},
|
|
242
|
+
{at: path},
|
|
243
|
+
)
|
|
244
|
+
})
|
|
240
245
|
return
|
|
241
246
|
}
|
|
242
247
|
}
|
|
243
248
|
|
|
244
|
-
|
|
249
|
+
withNormalizeNode(editor, () => {
|
|
250
|
+
normalizeNode(nodeEntry)
|
|
251
|
+
})
|
|
245
252
|
}
|
|
246
253
|
|
|
247
254
|
editor.apply = (op) => {
|
|
@@ -9,6 +9,7 @@ import {debugWithName} from '../../internal-utils/debug'
|
|
|
9
9
|
import type {PortableTextSlateEditor} from '../../types/editor'
|
|
10
10
|
import {isListBlock} from '../../utils/parse-blocks'
|
|
11
11
|
import type {EditorActor} from '../editor-machine'
|
|
12
|
+
import {withNormalizeNode} from '../with-normalizing-node'
|
|
12
13
|
|
|
13
14
|
const debug = debugWithName('plugin:withSchemaTypes')
|
|
14
15
|
/**
|
|
@@ -87,17 +88,17 @@ export function createWithSchemaTypes({
|
|
|
87
88
|
const span = node as PortableTextSpan
|
|
88
89
|
const key =
|
|
89
90
|
span._key || editorActor.getSnapshot().context.keyGenerator()
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
91
|
+
withNormalizeNode(editor, () => {
|
|
92
|
+
Transforms.setNodes(
|
|
93
|
+
editor,
|
|
94
|
+
{
|
|
95
|
+
...span,
|
|
96
|
+
_type: editorActor.getSnapshot().context.schema.span.name,
|
|
97
|
+
_key: key,
|
|
98
|
+
},
|
|
99
|
+
{at: path},
|
|
100
|
+
)
|
|
101
|
+
})
|
|
101
102
|
return
|
|
102
103
|
}
|
|
103
104
|
|
|
@@ -105,13 +106,15 @@ export function createWithSchemaTypes({
|
|
|
105
106
|
if (node._key === undefined && (path.length === 1 || path.length === 2)) {
|
|
106
107
|
debug('Setting missing key on child node without a key')
|
|
107
108
|
const key = editorActor.getSnapshot().context.keyGenerator()
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
109
|
+
withNormalizeNode(editor, () => {
|
|
110
|
+
Transforms.setNodes(editor, {_key: key}, {at: path})
|
|
111
|
+
})
|
|
111
112
|
return
|
|
112
113
|
}
|
|
113
114
|
|
|
114
|
-
|
|
115
|
+
withNormalizeNode(editor, () => {
|
|
116
|
+
normalizeNode(entry)
|
|
117
|
+
})
|
|
115
118
|
}
|
|
116
119
|
return editor
|
|
117
120
|
}
|
|
@@ -25,6 +25,7 @@ import {fromSlateValue} from '../../internal-utils/values'
|
|
|
25
25
|
import type {BehaviorOperationImplementation} from '../../operations/behavior.operations'
|
|
26
26
|
import type {PortableTextSlateEditor} from '../../types/editor'
|
|
27
27
|
import type {EditorActor} from '../editor-machine'
|
|
28
|
+
import {isNormalizingNode} from '../with-normalizing-node'
|
|
28
29
|
import {getCurrentUndoStepId} from '../with-undo-step'
|
|
29
30
|
import {isChangingRemotely} from '../withChanges'
|
|
30
31
|
import {
|
|
@@ -151,7 +152,8 @@ export function createWithUndoRedo(
|
|
|
151
152
|
|
|
152
153
|
const currentUndoStepId = getCurrentUndoStepId(editor)
|
|
153
154
|
|
|
154
|
-
let merge =
|
|
155
|
+
let merge =
|
|
156
|
+
currentUndoStepId === previousUndoStepId || isNormalizingNode(editor)
|
|
155
157
|
|
|
156
158
|
if (save) {
|
|
157
159
|
if (!step) {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type {Editor} from 'slate'
|
|
2
|
+
|
|
3
|
+
const IS_NORMALIZING_NODE: WeakMap<Editor, boolean | undefined> = new WeakMap()
|
|
4
|
+
|
|
5
|
+
export function withNormalizeNode(editor: Editor, fn: () => void) {
|
|
6
|
+
const prev = IS_NORMALIZING_NODE.get(editor)
|
|
7
|
+
IS_NORMALIZING_NODE.set(editor, true)
|
|
8
|
+
fn()
|
|
9
|
+
IS_NORMALIZING_NODE.set(editor, prev)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function isNormalizingNode(editor: Editor) {
|
|
13
|
+
return IS_NORMALIZING_NODE.get(editor) ?? false
|
|
14
|
+
}
|