@portabletext/editor 1.31.2 → 1.33.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 +4 -4
- package/lib/_chunks-cjs/behavior.core.cjs.map +1 -1
- package/lib/_chunks-cjs/behavior.markdown.cjs +19 -11
- package/lib/_chunks-cjs/behavior.markdown.cjs.map +1 -1
- package/lib/_chunks-cjs/plugin.event-listener.cjs +1839 -1724
- package/lib/_chunks-cjs/plugin.event-listener.cjs.map +1 -1
- package/lib/_chunks-cjs/selector.get-trimmed-selection.cjs +97 -0
- package/lib/_chunks-cjs/selector.get-trimmed-selection.cjs.map +1 -0
- package/lib/_chunks-cjs/{parse-blocks.cjs → util.block-offsets-to-selection.cjs} +21 -2
- package/lib/_chunks-cjs/util.block-offsets-to-selection.cjs.map +1 -0
- package/lib/_chunks-cjs/util.reverse-selection.cjs +11 -0
- package/lib/_chunks-cjs/util.reverse-selection.cjs.map +1 -1
- package/lib/_chunks-es/behavior.core.js +1 -1
- package/lib/_chunks-es/behavior.core.js.map +1 -1
- package/lib/_chunks-es/behavior.markdown.js +18 -11
- package/lib/_chunks-es/behavior.markdown.js.map +1 -1
- package/lib/_chunks-es/plugin.event-listener.js +1842 -1726
- package/lib/_chunks-es/plugin.event-listener.js.map +1 -1
- package/lib/_chunks-es/selector.get-trimmed-selection.js +100 -0
- package/lib/_chunks-es/selector.get-trimmed-selection.js.map +1 -0
- package/lib/_chunks-es/{parse-blocks.js → util.block-offsets-to-selection.js} +21 -1
- package/lib/_chunks-es/util.block-offsets-to-selection.js.map +1 -0
- package/lib/_chunks-es/util.reverse-selection.js +11 -0
- package/lib/_chunks-es/util.reverse-selection.js.map +1 -1
- package/lib/behaviors/index.d.cts +27 -0
- package/lib/behaviors/index.d.ts +27 -0
- package/lib/index.d.cts +1128 -66
- package/lib/index.d.ts +1128 -66
- package/lib/plugins/index.cjs +295 -3
- package/lib/plugins/index.cjs.map +1 -1
- package/lib/plugins/index.d.cts +1142 -67
- package/lib/plugins/index.d.ts +1142 -67
- package/lib/plugins/index.js +300 -4
- package/lib/plugins/index.js.map +1 -1
- package/lib/selectors/index.cjs +51 -1
- package/lib/selectors/index.cjs.map +1 -1
- package/lib/selectors/index.d.cts +67 -0
- package/lib/selectors/index.d.ts +67 -0
- package/lib/selectors/index.js +53 -2
- package/lib/selectors/index.js.map +1 -1
- package/lib/utils/index.cjs +5 -4
- package/lib/utils/index.cjs.map +1 -1
- package/lib/utils/index.d.cts +16 -0
- package/lib/utils/index.d.ts +16 -0
- package/lib/utils/index.js +4 -3
- package/package.json +2 -2
- package/src/behavior-actions/behavior.action.decorator.add.ts +161 -0
- package/src/behavior-actions/behavior.action.delete.text.ts +54 -0
- package/src/behavior-actions/behavior.actions.ts +25 -43
- package/src/behaviors/behavior.markdown-emphasis.ts +395 -0
- package/src/behaviors/behavior.markdown.ts +11 -4
- package/src/behaviors/behavior.types.ts +7 -0
- package/src/editor/editor-machine.ts +80 -85
- package/src/editor/plugins/create-with-event-listeners.ts +51 -0
- package/src/editor/plugins/createWithEditableAPI.ts +18 -2
- package/src/editor/plugins/createWithPortableTextMarkModel.ts +2 -97
- package/src/editor/plugins/createWithUndoRedo.ts +132 -107
- package/src/editor/with-applying-behavior-actions.ts +27 -3
- package/src/plugins/plugin.markdown.tsx +11 -1
- package/src/selectors/index.ts +5 -0
- package/src/selectors/selector.get-anchor-block.ts +22 -0
- package/src/selectors/selector.get-anchor-child.ts +36 -0
- package/src/selectors/selector.get-anchor-span.ts +18 -0
- package/src/selectors/selector.get-anchor-text-block.ts +20 -0
- package/src/selectors/selector.get-trimmed-selection.test.ts +658 -0
- package/src/selectors/selector.get-trimmed-selection.ts +175 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/util.block-offsets-to-selection.ts +36 -0
- package/lib/_chunks-cjs/parse-blocks.cjs.map +0 -1
- package/lib/_chunks-cjs/util.is-empty-text-block.cjs +0 -14
- package/lib/_chunks-cjs/util.is-empty-text-block.cjs.map +0 -1
- package/lib/_chunks-es/parse-blocks.js.map +0 -1
- package/lib/_chunks-es/util.is-empty-text-block.js +0 -15
- package/lib/_chunks-es/util.is-empty-text-block.js.map +0 -1
|
@@ -1,7 +1,6 @@
|
|
|
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'
|
|
5
4
|
import {
|
|
6
5
|
assertEvent,
|
|
7
6
|
assign,
|
|
@@ -30,7 +29,10 @@ import type {
|
|
|
30
29
|
} from '../types/editor'
|
|
31
30
|
import type {EditorSchema} from './define-schema'
|
|
32
31
|
import {createEditorSnapshot} from './editor-snapshot'
|
|
33
|
-
import {
|
|
32
|
+
import {
|
|
33
|
+
withApplyingBehaviorActionIntendSet,
|
|
34
|
+
withApplyingBehaviorActions,
|
|
35
|
+
} from './with-applying-behavior-actions'
|
|
34
36
|
|
|
35
37
|
export * from 'xstate/guards'
|
|
36
38
|
|
|
@@ -315,17 +317,15 @@ export const editorMachine = setup({
|
|
|
315
317
|
if (eventBehaviors.length === 0) {
|
|
316
318
|
if (defaultActionCallback) {
|
|
317
319
|
withApplyingBehaviorActions(event.editor, () => {
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
}
|
|
328
|
-
})
|
|
320
|
+
try {
|
|
321
|
+
defaultActionCallback()
|
|
322
|
+
} catch (error) {
|
|
323
|
+
console.error(
|
|
324
|
+
new Error(
|
|
325
|
+
`Performing action "${event.behaviorEvent.type}" failed due to: ${error.message}`,
|
|
326
|
+
),
|
|
327
|
+
)
|
|
328
|
+
}
|
|
329
329
|
})
|
|
330
330
|
return
|
|
331
331
|
}
|
|
@@ -335,20 +335,18 @@ export const editorMachine = setup({
|
|
|
335
335
|
}
|
|
336
336
|
|
|
337
337
|
withApplyingBehaviorActions(event.editor, () => {
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
}
|
|
351
|
-
})
|
|
338
|
+
try {
|
|
339
|
+
performAction({
|
|
340
|
+
context,
|
|
341
|
+
action: defaultAction,
|
|
342
|
+
})
|
|
343
|
+
} catch (error) {
|
|
344
|
+
console.error(
|
|
345
|
+
new Error(
|
|
346
|
+
`Performing action "${defaultAction.type}" as a result of "${event.behaviorEvent.type}" failed due to: ${error.message}`,
|
|
347
|
+
),
|
|
348
|
+
)
|
|
349
|
+
}
|
|
352
350
|
})
|
|
353
351
|
event.editor.onChange()
|
|
354
352
|
return
|
|
@@ -390,43 +388,41 @@ export const editorMachine = setup({
|
|
|
390
388
|
(actionIntend) => actionIntend.type !== 'effect',
|
|
391
389
|
))
|
|
392
390
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
if (actionIntend.
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
})
|
|
409
|
-
}
|
|
410
|
-
continue
|
|
391
|
+
withApplyingBehaviorActionIntendSet(event.editor, () => {
|
|
392
|
+
for (const actionIntend of actionIntends) {
|
|
393
|
+
if (actionIntend.type === 'raise') {
|
|
394
|
+
if (isCustomBehaviorEvent(actionIntend.event)) {
|
|
395
|
+
enqueue.raise({
|
|
396
|
+
type: 'custom behavior event',
|
|
397
|
+
behaviorEvent: actionIntend.event as CustomBehaviorEvent,
|
|
398
|
+
editor: event.editor,
|
|
399
|
+
})
|
|
400
|
+
} else {
|
|
401
|
+
enqueue.raise({
|
|
402
|
+
type: 'behavior event',
|
|
403
|
+
behaviorEvent: actionIntend.event,
|
|
404
|
+
editor: event.editor,
|
|
405
|
+
})
|
|
411
406
|
}
|
|
407
|
+
continue
|
|
408
|
+
}
|
|
412
409
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
410
|
+
const action = {
|
|
411
|
+
...actionIntend,
|
|
412
|
+
editor: event.editor,
|
|
413
|
+
}
|
|
417
414
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
}
|
|
415
|
+
try {
|
|
416
|
+
performAction({context, action})
|
|
417
|
+
} catch (error) {
|
|
418
|
+
console.error(
|
|
419
|
+
new Error(
|
|
420
|
+
`Performing action "${action.type}" as a result of "${event.behaviorEvent.type}" failed due to: ${error.message}`,
|
|
421
|
+
),
|
|
422
|
+
)
|
|
423
|
+
break
|
|
428
424
|
}
|
|
429
|
-
}
|
|
425
|
+
}
|
|
430
426
|
})
|
|
431
427
|
event.editor.onChange()
|
|
432
428
|
}
|
|
@@ -440,17 +436,15 @@ export const editorMachine = setup({
|
|
|
440
436
|
if (!behaviorOverwritten) {
|
|
441
437
|
if (defaultActionCallback) {
|
|
442
438
|
withApplyingBehaviorActions(event.editor, () => {
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
}
|
|
453
|
-
})
|
|
439
|
+
try {
|
|
440
|
+
defaultActionCallback()
|
|
441
|
+
} catch (error) {
|
|
442
|
+
console.error(
|
|
443
|
+
new Error(
|
|
444
|
+
`Performing "${event.behaviorEvent.type}" failed due to: ${error.message}`,
|
|
445
|
+
),
|
|
446
|
+
)
|
|
447
|
+
}
|
|
454
448
|
})
|
|
455
449
|
return
|
|
456
450
|
}
|
|
@@ -460,20 +454,18 @@ export const editorMachine = setup({
|
|
|
460
454
|
}
|
|
461
455
|
|
|
462
456
|
withApplyingBehaviorActions(event.editor, () => {
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
}
|
|
476
|
-
})
|
|
457
|
+
try {
|
|
458
|
+
performAction({
|
|
459
|
+
context,
|
|
460
|
+
action: defaultAction,
|
|
461
|
+
})
|
|
462
|
+
} catch (error) {
|
|
463
|
+
console.error(
|
|
464
|
+
new Error(
|
|
465
|
+
`Performing action "${defaultAction.type}" as a result of "${event.behaviorEvent.type}" failed due to: ${error.message}`,
|
|
466
|
+
),
|
|
467
|
+
)
|
|
468
|
+
}
|
|
477
469
|
})
|
|
478
470
|
event.editor.onChange()
|
|
479
471
|
}
|
|
@@ -610,6 +602,9 @@ export const editorMachine = setup({
|
|
|
610
602
|
'focus': {
|
|
611
603
|
actions: emit(({event}) => event),
|
|
612
604
|
},
|
|
605
|
+
'history.*': {
|
|
606
|
+
actions: emit(({event}) => event),
|
|
607
|
+
},
|
|
613
608
|
'insert.*': {
|
|
614
609
|
actions: emit(({event}) => event),
|
|
615
610
|
},
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {Editor} from 'slate'
|
|
2
2
|
import {insertSoftBreakActionImplementation} from '../../behavior-actions/behavior.action.insert-break'
|
|
3
|
+
import {performAction} from '../../behavior-actions/behavior.actions'
|
|
3
4
|
import {toPortableTextRange} from '../../internal-utils/ranges'
|
|
4
5
|
import {fromSlateValue} from '../../internal-utils/values'
|
|
5
6
|
import {KEY_TO_VALUE_ELEMENT} from '../../internal-utils/weakMaps'
|
|
@@ -179,6 +180,31 @@ export function createWithEventListeners(
|
|
|
179
180
|
return
|
|
180
181
|
}
|
|
181
182
|
|
|
183
|
+
editor.redo = () => {
|
|
184
|
+
if (isApplyingBehaviorActions(editor)) {
|
|
185
|
+
performAction({
|
|
186
|
+
context: {
|
|
187
|
+
keyGenerator: editorActor.getSnapshot().context.keyGenerator,
|
|
188
|
+
schema: editorActor.getSnapshot().context.schema,
|
|
189
|
+
},
|
|
190
|
+
action: {
|
|
191
|
+
type: 'history.redo',
|
|
192
|
+
editor,
|
|
193
|
+
},
|
|
194
|
+
})
|
|
195
|
+
return
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
editorActor.send({
|
|
199
|
+
type: 'behavior event',
|
|
200
|
+
behaviorEvent: {
|
|
201
|
+
type: 'history.redo',
|
|
202
|
+
},
|
|
203
|
+
editor,
|
|
204
|
+
})
|
|
205
|
+
return
|
|
206
|
+
}
|
|
207
|
+
|
|
182
208
|
editor.select = (location) => {
|
|
183
209
|
if (isApplyingBehaviorActions(editor)) {
|
|
184
210
|
select(location)
|
|
@@ -234,6 +260,31 @@ export function createWithEventListeners(
|
|
|
234
260
|
return
|
|
235
261
|
}
|
|
236
262
|
|
|
263
|
+
editor.undo = () => {
|
|
264
|
+
if (isApplyingBehaviorActions(editor)) {
|
|
265
|
+
performAction({
|
|
266
|
+
context: {
|
|
267
|
+
keyGenerator: editorActor.getSnapshot().context.keyGenerator,
|
|
268
|
+
schema: editorActor.getSnapshot().context.schema,
|
|
269
|
+
},
|
|
270
|
+
action: {
|
|
271
|
+
type: 'history.undo',
|
|
272
|
+
editor,
|
|
273
|
+
},
|
|
274
|
+
})
|
|
275
|
+
return
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
editorActor.send({
|
|
279
|
+
type: 'behavior event',
|
|
280
|
+
behaviorEvent: {
|
|
281
|
+
type: 'history.undo',
|
|
282
|
+
},
|
|
283
|
+
editor,
|
|
284
|
+
})
|
|
285
|
+
return
|
|
286
|
+
}
|
|
287
|
+
|
|
237
288
|
return editor
|
|
238
289
|
}
|
|
239
290
|
}
|
|
@@ -111,8 +111,24 @@ export function createEditableAPI(
|
|
|
111
111
|
}.marks || []
|
|
112
112
|
)
|
|
113
113
|
},
|
|
114
|
-
undo: (): void =>
|
|
115
|
-
|
|
114
|
+
undo: (): void => {
|
|
115
|
+
editorActor.send({
|
|
116
|
+
type: 'behavior event',
|
|
117
|
+
behaviorEvent: {
|
|
118
|
+
type: 'history.undo',
|
|
119
|
+
},
|
|
120
|
+
editor,
|
|
121
|
+
})
|
|
122
|
+
},
|
|
123
|
+
redo: (): void => {
|
|
124
|
+
editorActor.send({
|
|
125
|
+
type: 'behavior event',
|
|
126
|
+
behaviorEvent: {
|
|
127
|
+
type: 'history.redo',
|
|
128
|
+
},
|
|
129
|
+
editor,
|
|
130
|
+
})
|
|
131
|
+
},
|
|
116
132
|
select: (selection: EditorSelection): void => {
|
|
117
133
|
const slateSelection = toSlateRange(selection, editor)
|
|
118
134
|
if (slateSelection) {
|
|
@@ -8,6 +8,7 @@ import {isPortableTextBlock, isPortableTextSpan} from '@portabletext/toolkit'
|
|
|
8
8
|
import type {PortableTextObject, PortableTextSpan} from '@sanity/types'
|
|
9
9
|
import {isEqual, uniq} from 'lodash'
|
|
10
10
|
import {Editor, Element, Node, Path, Range, Text, Transforms} from 'slate'
|
|
11
|
+
import {decoratorAddActionImplementation} from '../../behavior-actions/behavior.action.decorator.add'
|
|
11
12
|
import type {BehaviorActionImplementation} from '../../behavior-actions/behavior.actions'
|
|
12
13
|
import {debugWithName} from '../../internal-utils/debug'
|
|
13
14
|
import {getNextSpan, getPreviousSpan} from '../../internal-utils/sibling-utils'
|
|
@@ -657,102 +658,6 @@ export function createWithPortableTextMarkModel(
|
|
|
657
658
|
}
|
|
658
659
|
}
|
|
659
660
|
|
|
660
|
-
export const addDecoratorActionImplementation: BehaviorActionImplementation<
|
|
661
|
-
'decorator.add'
|
|
662
|
-
> = ({action}) => {
|
|
663
|
-
const editor = action.editor
|
|
664
|
-
const mark = action.decorator
|
|
665
|
-
|
|
666
|
-
if (editor.selection) {
|
|
667
|
-
if (Range.isExpanded(editor.selection)) {
|
|
668
|
-
// Split if needed
|
|
669
|
-
Transforms.setNodes(
|
|
670
|
-
editor,
|
|
671
|
-
{},
|
|
672
|
-
{match: Text.isText, split: true, hanging: true},
|
|
673
|
-
)
|
|
674
|
-
// Use new selection
|
|
675
|
-
const splitTextNodes = Range.isRange(editor.selection)
|
|
676
|
-
? [
|
|
677
|
-
...Editor.nodes(editor, {
|
|
678
|
-
at: editor.selection,
|
|
679
|
-
match: Text.isText,
|
|
680
|
-
}),
|
|
681
|
-
]
|
|
682
|
-
: []
|
|
683
|
-
const shouldRemoveMark =
|
|
684
|
-
splitTextNodes.length > 1 &&
|
|
685
|
-
splitTextNodes.every((node) => node[0].marks?.includes(mark))
|
|
686
|
-
|
|
687
|
-
if (shouldRemoveMark) {
|
|
688
|
-
editor.removeMark(mark)
|
|
689
|
-
} else {
|
|
690
|
-
splitTextNodes.forEach(([node, path]) => {
|
|
691
|
-
const marks = [
|
|
692
|
-
...(Array.isArray(node.marks) ? node.marks : []).filter(
|
|
693
|
-
(eMark: string) => eMark !== mark,
|
|
694
|
-
),
|
|
695
|
-
mark,
|
|
696
|
-
]
|
|
697
|
-
Transforms.setNodes(
|
|
698
|
-
editor,
|
|
699
|
-
{marks},
|
|
700
|
-
{at: path, match: Text.isText, split: true, hanging: true},
|
|
701
|
-
)
|
|
702
|
-
})
|
|
703
|
-
}
|
|
704
|
-
} else {
|
|
705
|
-
const [block, blockPath] = Editor.node(editor, editor.selection, {
|
|
706
|
-
depth: 1,
|
|
707
|
-
})
|
|
708
|
-
const lonelyEmptySpan =
|
|
709
|
-
editor.isTextBlock(block) &&
|
|
710
|
-
block.children.length === 1 &&
|
|
711
|
-
editor.isTextSpan(block.children[0]) &&
|
|
712
|
-
block.children[0].text === ''
|
|
713
|
-
? block.children[0]
|
|
714
|
-
: undefined
|
|
715
|
-
|
|
716
|
-
if (lonelyEmptySpan) {
|
|
717
|
-
const existingMarks = lonelyEmptySpan.marks ?? []
|
|
718
|
-
const existingMarksWithoutDecorator = existingMarks.filter(
|
|
719
|
-
(existingMark) => existingMark !== mark,
|
|
720
|
-
)
|
|
721
|
-
|
|
722
|
-
Transforms.setNodes(
|
|
723
|
-
editor,
|
|
724
|
-
{
|
|
725
|
-
marks:
|
|
726
|
-
existingMarks.length === existingMarksWithoutDecorator.length
|
|
727
|
-
? [...existingMarks, mark]
|
|
728
|
-
: existingMarksWithoutDecorator,
|
|
729
|
-
},
|
|
730
|
-
{
|
|
731
|
-
at: blockPath,
|
|
732
|
-
match: (node) => editor.isTextSpan(node),
|
|
733
|
-
},
|
|
734
|
-
)
|
|
735
|
-
} else {
|
|
736
|
-
const existingMarks: string[] =
|
|
737
|
-
{
|
|
738
|
-
...(Editor.marks(editor) || {}),
|
|
739
|
-
}.marks || []
|
|
740
|
-
const marks = {
|
|
741
|
-
...(Editor.marks(editor) || {}),
|
|
742
|
-
marks: [...existingMarks, mark],
|
|
743
|
-
}
|
|
744
|
-
editor.marks = marks as Text
|
|
745
|
-
}
|
|
746
|
-
}
|
|
747
|
-
|
|
748
|
-
if (editor.selection) {
|
|
749
|
-
// Reselect
|
|
750
|
-
const selection = editor.selection
|
|
751
|
-
editor.selection = {...selection}
|
|
752
|
-
}
|
|
753
|
-
}
|
|
754
|
-
}
|
|
755
|
-
|
|
756
661
|
export const removeDecoratorActionImplementation: BehaviorActionImplementation<
|
|
757
662
|
'decorator.remove'
|
|
758
663
|
> = ({action}) => {
|
|
@@ -892,7 +797,7 @@ export const toggleDecoratorActionImplementation: BehaviorActionImplementation<
|
|
|
892
797
|
},
|
|
893
798
|
})
|
|
894
799
|
} else {
|
|
895
|
-
|
|
800
|
+
decoratorAddActionImplementation({
|
|
896
801
|
context,
|
|
897
802
|
action: {
|
|
898
803
|
type: 'decorator.add',
|