@portabletext/editor 1.0.19 → 1.1.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/index.d.mts +140 -66
- package/lib/index.d.ts +140 -66
- package/lib/index.esm.js +1125 -362
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +1125 -362
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +1125 -362
- package/lib/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/editor/Editable.tsx +107 -36
- package/src/editor/PortableTextEditor.tsx +47 -12
- package/src/editor/__tests__/PortableTextEditor.test.tsx +42 -15
- package/src/editor/__tests__/PortableTextEditorTester.tsx +50 -38
- package/src/editor/__tests__/RangeDecorations.test.tsx +0 -1
- package/src/editor/__tests__/handleClick.test.tsx +28 -9
- package/src/editor/__tests__/insert-block.test.tsx +22 -6
- package/src/editor/__tests__/pteWarningsSelfSolving.test.tsx +30 -62
- package/src/editor/__tests__/utils.ts +10 -3
- package/src/editor/components/DraggableBlock.tsx +36 -13
- package/src/editor/components/Element.tsx +59 -17
- package/src/editor/components/Leaf.tsx +106 -68
- package/src/editor/components/SlateContainer.tsx +12 -5
- package/src/editor/components/Synchronizer.tsx +5 -2
- package/src/editor/hooks/usePortableTextEditor.ts +2 -2
- package/src/editor/hooks/usePortableTextEditorSelection.tsx +9 -3
- package/src/editor/hooks/useSyncValue.test.tsx +9 -4
- package/src/editor/hooks/useSyncValue.ts +199 -130
- package/src/editor/nodes/DefaultAnnotation.tsx +6 -3
- package/src/editor/plugins/__tests__/createWithInsertData.test.tsx +25 -7
- package/src/editor/plugins/__tests__/withEditableAPIDelete.test.tsx +26 -9
- package/src/editor/plugins/__tests__/withEditableAPIGetFragment.test.tsx +15 -5
- package/src/editor/plugins/__tests__/withEditableAPIInsert.test.tsx +60 -19
- package/src/editor/plugins/__tests__/withEditableAPISelectionsOverlapping.test.tsx +4 -2
- package/src/editor/plugins/__tests__/withPortableTextLists.test.tsx +4 -2
- package/src/editor/plugins/__tests__/withPortableTextMarkModel.test.tsx +61 -17
- package/src/editor/plugins/__tests__/withPortableTextSelections.test.tsx +6 -3
- package/src/editor/plugins/__tests__/withUndoRedo.test.tsx +30 -13
- package/src/editor/plugins/createWithEditableAPI.ts +354 -124
- package/src/editor/plugins/createWithHotKeys.ts +41 -121
- package/src/editor/plugins/createWithInsertBreak.ts +166 -27
- package/src/editor/plugins/createWithInsertData.ts +60 -23
- package/src/editor/plugins/createWithMaxBlocks.ts +5 -2
- package/src/editor/plugins/createWithObjectKeys.ts +7 -3
- package/src/editor/plugins/createWithPatches.ts +60 -16
- package/src/editor/plugins/createWithPlaceholderBlock.ts +7 -3
- package/src/editor/plugins/createWithPortableTextBlockStyle.ts +17 -7
- package/src/editor/plugins/createWithPortableTextLists.ts +21 -8
- package/src/editor/plugins/createWithPortableTextMarkModel.ts +213 -46
- package/src/editor/plugins/createWithPortableTextSelections.ts +4 -2
- package/src/editor/plugins/createWithSchemaTypes.ts +25 -9
- package/src/editor/plugins/createWithUndoRedo.ts +107 -24
- package/src/editor/plugins/createWithUtils.ts +32 -10
- package/src/editor/plugins/index.ts +31 -10
- package/src/types/editor.ts +44 -15
- package/src/types/options.ts +4 -2
- package/src/types/slate.ts +2 -2
- package/src/utils/__tests__/dmpToOperations.test.ts +38 -13
- package/src/utils/__tests__/operationToPatches.test.ts +3 -2
- package/src/utils/__tests__/patchToOperations.test.ts +15 -4
- package/src/utils/__tests__/ranges.test.ts +8 -3
- package/src/utils/__tests__/valueNormalization.test.tsx +12 -4
- package/src/utils/__tests__/values.test.ts +0 -1
- package/src/utils/applyPatch.ts +71 -20
- package/src/utils/getPortableTextMemberSchemaTypes.ts +30 -15
- package/src/utils/operationToPatches.ts +126 -43
- package/src/utils/paths.ts +24 -7
- package/src/utils/ranges.ts +12 -5
- package/src/utils/selection.ts +19 -7
- package/src/utils/validateValue.ts +118 -45
- package/src/utils/values.ts +31 -9
- package/src/utils/weakMaps.ts +18 -8
- package/src/utils/withChanges.ts +4 -2
|
@@ -7,10 +7,19 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import {isPortableTextBlock, isPortableTextSpan} from '@portabletext/toolkit'
|
|
10
|
+
import {type PortableTextObject} from '@sanity/types'
|
|
10
11
|
import {isEqual, uniq} from 'lodash'
|
|
11
12
|
import {type Subject} from 'rxjs'
|
|
12
|
-
import {
|
|
13
|
-
|
|
13
|
+
import {
|
|
14
|
+
Editor,
|
|
15
|
+
Element,
|
|
16
|
+
Node,
|
|
17
|
+
Path,
|
|
18
|
+
Range,
|
|
19
|
+
Text,
|
|
20
|
+
Transforms,
|
|
21
|
+
type Descendant,
|
|
22
|
+
} from 'slate'
|
|
14
23
|
import {
|
|
15
24
|
type EditorChange,
|
|
16
25
|
type PortableTextMemberSchemaTypes,
|
|
@@ -47,7 +56,11 @@ export function createWithPortableTextMarkModel(
|
|
|
47
56
|
Transforms.select(editor, {...editor.selection})
|
|
48
57
|
editor.selection = {...editor.selection} // Ensure new object
|
|
49
58
|
}
|
|
50
|
-
const ptRange = toPortableTextRange(
|
|
59
|
+
const ptRange = toPortableTextRange(
|
|
60
|
+
editor.children,
|
|
61
|
+
editor.selection,
|
|
62
|
+
types,
|
|
63
|
+
)
|
|
51
64
|
change$.next({type: 'selection', selection: ptRange})
|
|
52
65
|
}
|
|
53
66
|
|
|
@@ -71,12 +84,24 @@ export function createWithPortableTextMarkModel(
|
|
|
71
84
|
JSON.stringify(child, null, 2),
|
|
72
85
|
JSON.stringify(nextNode, null, 2),
|
|
73
86
|
)
|
|
74
|
-
Transforms.mergeNodes(editor, {
|
|
87
|
+
Transforms.mergeNodes(editor, {
|
|
88
|
+
at: [childPath[0], childPath[1] + 1],
|
|
89
|
+
voids: true,
|
|
90
|
+
})
|
|
75
91
|
return
|
|
76
92
|
}
|
|
77
93
|
}
|
|
78
94
|
}
|
|
79
95
|
|
|
96
|
+
/**
|
|
97
|
+
* Add missing .markDefs to block nodes
|
|
98
|
+
*/
|
|
99
|
+
if (editor.isTextBlock(node) && !Array.isArray(node.markDefs)) {
|
|
100
|
+
debug('Adding .markDefs to block node')
|
|
101
|
+
Transforms.setNodes(editor, {markDefs: []}, {at: path})
|
|
102
|
+
return
|
|
103
|
+
}
|
|
104
|
+
|
|
80
105
|
/**
|
|
81
106
|
* Add missing .marks to span nodes
|
|
82
107
|
*/
|
|
@@ -93,7 +118,9 @@ export function createWithPortableTextMarkModel(
|
|
|
93
118
|
const blockPath = Path.parent(path)
|
|
94
119
|
const [block] = Editor.node(editor, blockPath)
|
|
95
120
|
const decorators = types.decorators.map((decorator) => decorator.value)
|
|
96
|
-
const annotations = node.marks?.filter(
|
|
121
|
+
const annotations = node.marks?.filter(
|
|
122
|
+
(mark) => !decorators.includes(mark),
|
|
123
|
+
)
|
|
97
124
|
|
|
98
125
|
if (editor.isTextBlock(block)) {
|
|
99
126
|
if (node.text === '' && annotations && annotations.length > 0) {
|
|
@@ -118,14 +145,21 @@ export function createWithPortableTextMarkModel(
|
|
|
118
145
|
if (editor.isTextSpan(child)) {
|
|
119
146
|
const marks = child.marks ?? []
|
|
120
147
|
const orphanedAnnotations = marks.filter((mark) => {
|
|
121
|
-
return
|
|
148
|
+
return (
|
|
149
|
+
!decorators.includes(mark) &&
|
|
150
|
+
!node.markDefs?.find((def) => def._key === mark)
|
|
151
|
+
)
|
|
122
152
|
})
|
|
123
153
|
|
|
124
154
|
if (orphanedAnnotations.length > 0) {
|
|
125
155
|
debug('Removing orphaned annotations from span node')
|
|
126
156
|
Transforms.setNodes(
|
|
127
157
|
editor,
|
|
128
|
-
{
|
|
158
|
+
{
|
|
159
|
+
marks: marks.filter(
|
|
160
|
+
(mark) => !orphanedAnnotations.includes(mark),
|
|
161
|
+
),
|
|
162
|
+
},
|
|
129
163
|
{at: childPath},
|
|
130
164
|
)
|
|
131
165
|
return
|
|
@@ -142,17 +176,26 @@ export function createWithPortableTextMarkModel(
|
|
|
142
176
|
const [block] = Editor.node(editor, blockPath)
|
|
143
177
|
|
|
144
178
|
if (editor.isTextBlock(block)) {
|
|
145
|
-
const decorators = types.decorators.map(
|
|
179
|
+
const decorators = types.decorators.map(
|
|
180
|
+
(decorator) => decorator.value,
|
|
181
|
+
)
|
|
146
182
|
const marks = node.marks ?? []
|
|
147
183
|
const orphanedAnnotations = marks.filter((mark) => {
|
|
148
|
-
return
|
|
184
|
+
return (
|
|
185
|
+
!decorators.includes(mark) &&
|
|
186
|
+
!block.markDefs?.find((def) => def._key === mark)
|
|
187
|
+
)
|
|
149
188
|
})
|
|
150
189
|
|
|
151
190
|
if (orphanedAnnotations.length > 0) {
|
|
152
191
|
debug('Removing orphaned annotations from span node')
|
|
153
192
|
Transforms.setNodes(
|
|
154
193
|
editor,
|
|
155
|
-
{
|
|
194
|
+
{
|
|
195
|
+
marks: marks.filter(
|
|
196
|
+
(mark) => !orphanedAnnotations.includes(mark),
|
|
197
|
+
),
|
|
198
|
+
},
|
|
156
199
|
{at: path},
|
|
157
200
|
)
|
|
158
201
|
return
|
|
@@ -160,17 +203,41 @@ export function createWithPortableTextMarkModel(
|
|
|
160
203
|
}
|
|
161
204
|
}
|
|
162
205
|
|
|
206
|
+
// Remove duplicate markDefs
|
|
207
|
+
if (editor.isTextBlock(node)) {
|
|
208
|
+
const markDefs = node.markDefs ?? []
|
|
209
|
+
const markDefKeys = new Set<string>()
|
|
210
|
+
const newMarkDefs: Array<PortableTextObject> = []
|
|
211
|
+
|
|
212
|
+
for (const markDef of markDefs) {
|
|
213
|
+
if (!markDefKeys.has(markDef._key)) {
|
|
214
|
+
markDefKeys.add(markDef._key)
|
|
215
|
+
newMarkDefs.push(markDef)
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (markDefs.length !== newMarkDefs.length) {
|
|
220
|
+
debug('Removing duplicate markDefs')
|
|
221
|
+
Transforms.setNodes(editor, {markDefs: newMarkDefs}, {at: path})
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
163
225
|
// Check consistency of markDefs (unless we are merging two nodes)
|
|
164
226
|
if (
|
|
165
227
|
editor.isTextBlock(node) &&
|
|
166
228
|
!editor.operations.some(
|
|
167
|
-
(op) =>
|
|
229
|
+
(op) =>
|
|
230
|
+
op.type === 'merge_node' &&
|
|
231
|
+
'markDefs' in op.properties &&
|
|
232
|
+
op.path.length === 1,
|
|
168
233
|
)
|
|
169
234
|
) {
|
|
170
235
|
const newMarkDefs = (node.markDefs || []).filter((def) => {
|
|
171
236
|
return node.children.find((child) => {
|
|
172
237
|
return (
|
|
173
|
-
Text.isText(child) &&
|
|
238
|
+
Text.isText(child) &&
|
|
239
|
+
Array.isArray(child.marks) &&
|
|
240
|
+
child.marks.includes(def._key)
|
|
174
241
|
)
|
|
175
242
|
})
|
|
176
243
|
})
|
|
@@ -215,13 +282,16 @@ export function createWithPortableTextMarkModel(
|
|
|
215
282
|
if (
|
|
216
283
|
selection &&
|
|
217
284
|
Range.isCollapsed(selection) &&
|
|
218
|
-
Editor.marks(editor)?.marks?.some(
|
|
285
|
+
Editor.marks(editor)?.marks?.some(
|
|
286
|
+
(mark) => !decorators.includes(mark),
|
|
287
|
+
)
|
|
219
288
|
) {
|
|
220
289
|
const [node] = Array.from(
|
|
221
290
|
Editor.nodes(editor, {
|
|
222
291
|
mode: 'lowest',
|
|
223
292
|
at: selection.focus,
|
|
224
|
-
match: (n) =>
|
|
293
|
+
match: (n) =>
|
|
294
|
+
(n as unknown as Descendant)._type === types.span.name,
|
|
225
295
|
voids: false,
|
|
226
296
|
}),
|
|
227
297
|
)[0] || [undefined]
|
|
@@ -261,15 +331,25 @@ export function createWithPortableTextMarkModel(
|
|
|
261
331
|
const blockEntry = Editor.node(editor, Path.parent(op.path))
|
|
262
332
|
const block = blockEntry[0]
|
|
263
333
|
|
|
264
|
-
if (
|
|
334
|
+
if (
|
|
335
|
+
node &&
|
|
336
|
+
isPortableTextSpan(node) &&
|
|
337
|
+
block &&
|
|
338
|
+
isPortableTextBlock(block)
|
|
339
|
+
) {
|
|
265
340
|
const markDefs = block.markDefs ?? []
|
|
266
341
|
const nodeHasAnnotations = (node.marks ?? []).some((mark) =>
|
|
267
342
|
markDefs.find((markDef) => markDef._key === mark),
|
|
268
343
|
)
|
|
269
344
|
const deletingPartOfTheNode = op.offset !== 0
|
|
270
|
-
const deletingFromTheEnd =
|
|
345
|
+
const deletingFromTheEnd =
|
|
346
|
+
op.offset + op.text.length === node.text.length
|
|
271
347
|
|
|
272
|
-
if (
|
|
348
|
+
if (
|
|
349
|
+
nodeHasAnnotations &&
|
|
350
|
+
deletingPartOfTheNode &&
|
|
351
|
+
deletingFromTheEnd
|
|
352
|
+
) {
|
|
273
353
|
Editor.withoutNormalizing(editor, () => {
|
|
274
354
|
Transforms.splitNodes(editor, {
|
|
275
355
|
match: Text.isText,
|
|
@@ -293,7 +373,11 @@ export function createWithPortableTextMarkModel(
|
|
|
293
373
|
|
|
294
374
|
Editor.withoutNormalizing(editor, () => {
|
|
295
375
|
apply(op)
|
|
296
|
-
Transforms.setNodes(
|
|
376
|
+
Transforms.setNodes(
|
|
377
|
+
editor,
|
|
378
|
+
{marks: marksWithoutAnnotationMarks},
|
|
379
|
+
{at: op.path},
|
|
380
|
+
)
|
|
297
381
|
})
|
|
298
382
|
|
|
299
383
|
editor.onChange()
|
|
@@ -329,11 +413,16 @@ export function createWithPortableTextMarkModel(
|
|
|
329
413
|
const [targetBlock, targetPath] = Editor.node(editor, [op.path[0] - 1])
|
|
330
414
|
|
|
331
415
|
if (editor.isTextBlock(targetBlock)) {
|
|
332
|
-
const oldDefs =
|
|
416
|
+
const oldDefs =
|
|
417
|
+
(Array.isArray(targetBlock.markDefs) && targetBlock.markDefs) || []
|
|
333
418
|
const newMarkDefs = uniq([...oldDefs, ...op.properties.markDefs])
|
|
334
419
|
|
|
335
420
|
debug(`Copying markDefs over to merged block`, op)
|
|
336
|
-
Transforms.setNodes(
|
|
421
|
+
Transforms.setNodes(
|
|
422
|
+
editor,
|
|
423
|
+
{markDefs: newMarkDefs},
|
|
424
|
+
{at: targetPath, voids: false},
|
|
425
|
+
)
|
|
337
426
|
apply(op)
|
|
338
427
|
return
|
|
339
428
|
}
|
|
@@ -348,10 +437,19 @@ export function createWithPortableTextMarkModel(
|
|
|
348
437
|
if (Range.isExpanded(editor.selection)) {
|
|
349
438
|
Editor.withoutNormalizing(editor, () => {
|
|
350
439
|
// Split if needed
|
|
351
|
-
Transforms.setNodes(
|
|
440
|
+
Transforms.setNodes(
|
|
441
|
+
editor,
|
|
442
|
+
{},
|
|
443
|
+
{match: Text.isText, split: true, hanging: true},
|
|
444
|
+
)
|
|
352
445
|
// Use new selection
|
|
353
446
|
const splitTextNodes = Range.isRange(editor.selection)
|
|
354
|
-
? [
|
|
447
|
+
? [
|
|
448
|
+
...Editor.nodes(editor, {
|
|
449
|
+
at: editor.selection,
|
|
450
|
+
match: Text.isText,
|
|
451
|
+
}),
|
|
452
|
+
]
|
|
355
453
|
: []
|
|
356
454
|
const shouldRemoveMark =
|
|
357
455
|
splitTextNodes.length > 1 &&
|
|
@@ -376,17 +474,49 @@ export function createWithPortableTextMarkModel(
|
|
|
376
474
|
}
|
|
377
475
|
})
|
|
378
476
|
} else {
|
|
379
|
-
const
|
|
380
|
-
|
|
477
|
+
const [block, blockPath] = Editor.node(editor, editor.selection, {
|
|
478
|
+
depth: 1,
|
|
479
|
+
})
|
|
480
|
+
const lonelyEmptySpan =
|
|
481
|
+
editor.isTextBlock(block) &&
|
|
482
|
+
block.children.length === 1 &&
|
|
483
|
+
editor.isTextSpan(block.children[0]) &&
|
|
484
|
+
block.children[0].text === ''
|
|
485
|
+
? block.children[0]
|
|
486
|
+
: undefined
|
|
487
|
+
|
|
488
|
+
if (lonelyEmptySpan) {
|
|
489
|
+
const existingMarks = lonelyEmptySpan.marks ?? []
|
|
490
|
+
const existingMarksWithoutDecorator = existingMarks.filter(
|
|
491
|
+
(existingMark) => existingMark !== mark,
|
|
492
|
+
)
|
|
493
|
+
|
|
494
|
+
Transforms.setNodes(
|
|
495
|
+
editor,
|
|
496
|
+
{
|
|
497
|
+
marks:
|
|
498
|
+
existingMarks.length === existingMarksWithoutDecorator.length
|
|
499
|
+
? [...existingMarks, mark]
|
|
500
|
+
: existingMarksWithoutDecorator,
|
|
501
|
+
},
|
|
502
|
+
{
|
|
503
|
+
at: blockPath,
|
|
504
|
+
match: (node) => editor.isTextSpan(node),
|
|
505
|
+
},
|
|
506
|
+
)
|
|
507
|
+
} else {
|
|
508
|
+
const existingMarks: string[] =
|
|
509
|
+
{
|
|
510
|
+
...(Editor.marks(editor) || {}),
|
|
511
|
+
}.marks || []
|
|
512
|
+
const marks = {
|
|
381
513
|
...(Editor.marks(editor) || {}),
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
514
|
+
marks: [...existingMarks, mark],
|
|
515
|
+
}
|
|
516
|
+
editor.marks = marks as Text
|
|
517
|
+
forceNewSelection()
|
|
518
|
+
return editor
|
|
386
519
|
}
|
|
387
|
-
editor.marks = marks as Text
|
|
388
|
-
forceNewSelection()
|
|
389
|
-
return editor
|
|
390
520
|
}
|
|
391
521
|
editor.onChange()
|
|
392
522
|
forceNewSelection()
|
|
@@ -401,10 +531,17 @@ export function createWithPortableTextMarkModel(
|
|
|
401
531
|
if (Range.isExpanded(selection)) {
|
|
402
532
|
Editor.withoutNormalizing(editor, () => {
|
|
403
533
|
// Split if needed
|
|
404
|
-
Transforms.setNodes(
|
|
534
|
+
Transforms.setNodes(
|
|
535
|
+
editor,
|
|
536
|
+
{},
|
|
537
|
+
{match: Text.isText, split: true, hanging: true},
|
|
538
|
+
)
|
|
405
539
|
if (editor.selection) {
|
|
406
540
|
const splitTextNodes = [
|
|
407
|
-
...Editor.nodes(editor, {
|
|
541
|
+
...Editor.nodes(editor, {
|
|
542
|
+
at: editor.selection,
|
|
543
|
+
match: Text.isText,
|
|
544
|
+
}),
|
|
408
545
|
]
|
|
409
546
|
splitTextNodes.forEach(([node, path]) => {
|
|
410
547
|
const block = editor.children[path[0]]
|
|
@@ -412,9 +549,10 @@ export function createWithPortableTextMarkModel(
|
|
|
412
549
|
Transforms.setNodes(
|
|
413
550
|
editor,
|
|
414
551
|
{
|
|
415
|
-
marks: (Array.isArray(node.marks)
|
|
416
|
-
|
|
417
|
-
|
|
552
|
+
marks: (Array.isArray(node.marks)
|
|
553
|
+
? node.marks
|
|
554
|
+
: []
|
|
555
|
+
).filter((eMark: string) => eMark !== mark),
|
|
418
556
|
_type: 'span',
|
|
419
557
|
},
|
|
420
558
|
{at: path},
|
|
@@ -425,17 +563,46 @@ export function createWithPortableTextMarkModel(
|
|
|
425
563
|
})
|
|
426
564
|
Editor.normalize(editor)
|
|
427
565
|
} else {
|
|
428
|
-
const
|
|
429
|
-
|
|
566
|
+
const [block, blockPath] = Editor.node(editor, selection, {
|
|
567
|
+
depth: 1,
|
|
568
|
+
})
|
|
569
|
+
const lonelyEmptySpan =
|
|
570
|
+
editor.isTextBlock(block) &&
|
|
571
|
+
block.children.length === 1 &&
|
|
572
|
+
editor.isTextSpan(block.children[0]) &&
|
|
573
|
+
block.children[0].text === ''
|
|
574
|
+
? block.children[0]
|
|
575
|
+
: undefined
|
|
576
|
+
|
|
577
|
+
if (lonelyEmptySpan) {
|
|
578
|
+
const existingMarks = lonelyEmptySpan.marks ?? []
|
|
579
|
+
const existingMarksWithoutDecorator = existingMarks.filter(
|
|
580
|
+
(existingMark) => existingMark !== mark,
|
|
581
|
+
)
|
|
582
|
+
|
|
583
|
+
Transforms.setNodes(
|
|
584
|
+
editor,
|
|
585
|
+
{
|
|
586
|
+
marks: existingMarksWithoutDecorator,
|
|
587
|
+
},
|
|
588
|
+
{
|
|
589
|
+
at: blockPath,
|
|
590
|
+
match: (node) => editor.isTextSpan(node),
|
|
591
|
+
},
|
|
592
|
+
)
|
|
593
|
+
} else {
|
|
594
|
+
const existingMarks: string[] =
|
|
595
|
+
{
|
|
596
|
+
...(Editor.marks(editor) || {}),
|
|
597
|
+
}.marks || []
|
|
598
|
+
const marks = {
|
|
430
599
|
...(Editor.marks(editor) || {}),
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
forceNewSelection()
|
|
438
|
-
return editor
|
|
600
|
+
marks: existingMarks.filter((eMark) => eMark !== mark),
|
|
601
|
+
} as Text
|
|
602
|
+
editor.marks = {marks: marks.marks, _type: 'span'} as Text
|
|
603
|
+
forceNewSelection()
|
|
604
|
+
return editor
|
|
605
|
+
}
|
|
439
606
|
}
|
|
440
607
|
editor.onChange()
|
|
441
608
|
forceNewSelection()
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {type Subject} from 'rxjs'
|
|
2
2
|
import {type BaseRange} from 'slate'
|
|
3
|
-
|
|
4
3
|
import {
|
|
5
4
|
type EditorChange,
|
|
6
5
|
type EditorSelection,
|
|
@@ -8,7 +7,10 @@ import {
|
|
|
8
7
|
type PortableTextSlateEditor,
|
|
9
8
|
} from '../../types/editor'
|
|
10
9
|
import {debugWithName} from '../../utils/debug'
|
|
11
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
toPortableTextRange,
|
|
12
|
+
type ObjectWithKeyAndType,
|
|
13
|
+
} from '../../utils/ranges'
|
|
12
14
|
import {SLATE_TO_PORTABLE_TEXT_RANGE} from '../../utils/weakMaps'
|
|
13
15
|
|
|
14
16
|
const debug = debugWithName('plugin:withPortableTextSelections')
|
|
@@ -6,9 +6,11 @@ import {
|
|
|
6
6
|
type PortableTextSpan,
|
|
7
7
|
type PortableTextTextBlock,
|
|
8
8
|
} from '@sanity/types'
|
|
9
|
-
import {type Element
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
import {Transforms, type Element} from 'slate'
|
|
10
|
+
import {
|
|
11
|
+
type PortableTextMemberSchemaTypes,
|
|
12
|
+
type PortableTextSlateEditor,
|
|
13
|
+
} from '../../types/editor'
|
|
12
14
|
import {debugWithName} from '../../utils/debug'
|
|
13
15
|
|
|
14
16
|
const debug = debugWithName('plugin:withSchemaTypes')
|
|
@@ -23,21 +25,31 @@ export function createWithSchemaTypes({
|
|
|
23
25
|
schemaTypes: PortableTextMemberSchemaTypes
|
|
24
26
|
keyGenerator: () => string
|
|
25
27
|
}) {
|
|
26
|
-
return function withSchemaTypes(
|
|
28
|
+
return function withSchemaTypes(
|
|
29
|
+
editor: PortableTextSlateEditor,
|
|
30
|
+
): PortableTextSlateEditor {
|
|
27
31
|
editor.isTextBlock = (value: unknown): value is PortableTextTextBlock => {
|
|
28
|
-
return
|
|
32
|
+
return (
|
|
33
|
+
isPortableTextTextBlock(value) && value._type === schemaTypes.block.name
|
|
34
|
+
)
|
|
29
35
|
}
|
|
30
36
|
editor.isTextSpan = (value: unknown): value is PortableTextSpan => {
|
|
31
37
|
return isPortableTextSpan(value) && value._type == schemaTypes.span.name
|
|
32
38
|
}
|
|
33
39
|
editor.isListBlock = (value: unknown): value is PortableTextListBlock => {
|
|
34
|
-
return
|
|
40
|
+
return (
|
|
41
|
+
isPortableTextListBlock(value) && value._type === schemaTypes.block.name
|
|
42
|
+
)
|
|
35
43
|
}
|
|
36
44
|
editor.isVoid = (element: Element): boolean => {
|
|
37
45
|
return (
|
|
38
46
|
schemaTypes.block.name !== element._type &&
|
|
39
|
-
(schemaTypes.blockObjects
|
|
40
|
-
|
|
47
|
+
(schemaTypes.blockObjects
|
|
48
|
+
.map((obj) => obj.name)
|
|
49
|
+
.includes(element._type) ||
|
|
50
|
+
schemaTypes.inlineObjects
|
|
51
|
+
.map((obj) => obj.name)
|
|
52
|
+
.includes(element._type))
|
|
41
53
|
)
|
|
42
54
|
}
|
|
43
55
|
editor.isInline = (element: Element): boolean => {
|
|
@@ -59,7 +71,11 @@ export function createWithSchemaTypes({
|
|
|
59
71
|
debug('Setting span type on text node without a type')
|
|
60
72
|
const span = node as PortableTextSpan
|
|
61
73
|
const key = span._key || keyGenerator()
|
|
62
|
-
Transforms.setNodes(
|
|
74
|
+
Transforms.setNodes(
|
|
75
|
+
editor,
|
|
76
|
+
{...span, _type: schemaTypes.span.name, _key: key},
|
|
77
|
+
{at: path},
|
|
78
|
+
)
|
|
63
79
|
}
|
|
64
80
|
|
|
65
81
|
// catches cases when the children are missing keys but excludes it when the normalize is running the node as the editor object
|