@portabletext/editor 1.1.0 → 1.1.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 +3 -0
- package/lib/index.d.mts +1680 -12
- package/lib/index.d.ts +1680 -12
- package/lib/index.esm.js +310 -162
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +310 -163
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +310 -162
- package/lib/index.mjs.map +1 -1
- package/package.json +25 -38
- package/src/editor/Editable.tsx +51 -50
- package/src/editor/PortableTextEditor.tsx +42 -26
- package/src/editor/__tests__/PortableTextEditor.test.tsx +11 -12
- package/src/editor/__tests__/PortableTextEditorTester.tsx +2 -5
- package/src/editor/__tests__/RangeDecorations.test.tsx +6 -7
- package/src/editor/__tests__/handleClick.test.tsx +27 -7
- package/src/editor/__tests__/insert-block.test.tsx +6 -6
- package/src/editor/__tests__/pteWarningsSelfSolving.test.tsx +8 -8
- package/src/editor/__tests__/self-solving.test.tsx +176 -0
- package/src/editor/components/Element.tsx +15 -17
- package/src/editor/components/Leaf.tsx +40 -35
- package/src/editor/components/SlateContainer.tsx +2 -2
- package/src/editor/components/Synchronizer.tsx +62 -34
- package/src/editor/editor-machine.ts +195 -0
- package/src/editor/hooks/usePortableTextEditor.ts +1 -1
- package/src/editor/hooks/usePortableTextEditorSelection.tsx +12 -14
- package/src/editor/hooks/useSyncValue.test.tsx +9 -9
- package/src/editor/hooks/useSyncValue.ts +16 -19
- package/src/editor/nodes/DefaultAnnotation.tsx +1 -2
- package/src/editor/nodes/DefaultObject.tsx +1 -1
- package/src/editor/plugins/__tests__/createWithInsertData.test.tsx +2 -5
- package/src/editor/plugins/__tests__/withEditableAPIDelete.test.tsx +28 -28
- package/src/editor/plugins/__tests__/withEditableAPIGetFragment.test.tsx +17 -17
- package/src/editor/plugins/__tests__/withEditableAPIInsert.test.tsx +8 -8
- package/src/editor/plugins/__tests__/withEditableAPISelectionsOverlapping.test.tsx +6 -6
- package/src/editor/plugins/__tests__/withPortableTextLists.test.tsx +2 -2
- package/src/editor/plugins/__tests__/withPortableTextMarkModel.test.tsx +47 -49
- package/src/editor/plugins/__tests__/withPortableTextSelections.test.tsx +22 -11
- package/src/editor/plugins/__tests__/withUndoRedo.test.tsx +9 -9
- package/src/editor/plugins/createWithEditableAPI.ts +8 -8
- package/src/editor/plugins/createWithHotKeys.ts +8 -12
- package/src/editor/plugins/createWithInsertBreak.ts +4 -4
- package/src/editor/plugins/createWithInsertData.ts +11 -16
- package/src/editor/plugins/createWithMaxBlocks.ts +1 -1
- package/src/editor/plugins/createWithObjectKeys.ts +10 -3
- package/src/editor/plugins/createWithPatches.ts +9 -12
- package/src/editor/plugins/createWithPlaceholderBlock.ts +2 -2
- package/src/editor/plugins/createWithPortableTextBlockStyle.ts +13 -5
- package/src/editor/plugins/createWithPortableTextLists.ts +3 -4
- package/src/editor/plugins/createWithPortableTextMarkModel.ts +24 -10
- package/src/editor/plugins/createWithPortableTextSelections.ts +9 -10
- package/src/editor/plugins/createWithSchemaTypes.ts +13 -4
- package/src/editor/plugins/createWithUndoRedo.ts +3 -7
- package/src/editor/plugins/createWithUtils.ts +6 -6
- package/src/editor/plugins/index.ts +21 -11
- package/src/index.ts +9 -3
- package/src/types/editor.ts +33 -33
- package/src/types/options.ts +3 -3
- package/src/types/slate.ts +4 -4
- package/src/utils/__tests__/dmpToOperations.test.ts +4 -4
- package/src/utils/__tests__/operationToPatches.test.ts +62 -62
- package/src/utils/__tests__/patchToOperations.test.ts +40 -40
- package/src/utils/__tests__/ranges.test.ts +2 -2
- package/src/utils/__tests__/valueNormalization.test.tsx +14 -2
- package/src/utils/__tests__/values.test.ts +17 -17
- package/src/utils/applyPatch.ts +10 -12
- package/src/utils/getPortableTextMemberSchemaTypes.ts +8 -8
- package/src/utils/operationToPatches.ts +5 -9
- package/src/utils/paths.ts +5 -5
- package/src/utils/ranges.ts +4 -5
- package/src/utils/selection.ts +2 -2
- package/src/utils/ucs2Indices.ts +2 -2
- package/src/utils/validateValue.ts +3 -25
- package/src/utils/values.ts +7 -8
- package/src/utils/weakMaps.ts +2 -2
- package/src/utils/withChanges.ts +1 -1
- package/src/utils/withUndoRedo.ts +1 -1
- package/src/utils/withoutPatching.ts +1 -1
- package/src/editor/__tests__/utils.ts +0 -45
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {isEqual} from 'lodash'
|
|
2
2
|
import {Editor, Node, Path, Range, Transforms} from 'slate'
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
import type {
|
|
4
|
+
PortableTextMemberSchemaTypes,
|
|
5
|
+
PortableTextSlateEditor,
|
|
6
6
|
} from '../../types/editor'
|
|
7
|
-
import
|
|
7
|
+
import type {SlateTextBlock, VoidElement} from '../../types/slate'
|
|
8
8
|
|
|
9
9
|
export function createWithInsertBreak(
|
|
10
10
|
types: PortableTextMemberSchemaTypes,
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {htmlToBlocks, normalizeBlock} from '@sanity/block-tools'
|
|
2
|
-
import
|
|
2
|
+
import type {PortableTextBlock, PortableTextChild} from '@sanity/types'
|
|
3
3
|
import {isEqual, uniq} from 'lodash'
|
|
4
4
|
import {Editor, Range, Transforms, type Descendant, type Node} from 'slate'
|
|
5
5
|
import {ReactEditor} from 'slate-react'
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
import type {
|
|
7
|
+
EditorChanges,
|
|
8
|
+
PortableTextMemberSchemaTypes,
|
|
9
|
+
PortableTextSlateEditor,
|
|
10
10
|
} from '../../types/editor'
|
|
11
11
|
import {debugWithName} from '../../utils/debug'
|
|
12
12
|
import {validateValue} from '../../utils/validateValue'
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
isEqualToEmptyEditor,
|
|
16
16
|
toSlateValue,
|
|
17
17
|
} from '../../utils/values'
|
|
18
|
+
import type {EditorActor} from '../editor-machine'
|
|
18
19
|
|
|
19
20
|
const debug = debugWithName('plugin:withInsertData')
|
|
20
21
|
|
|
@@ -23,7 +24,7 @@ const debug = debugWithName('plugin:withInsertData')
|
|
|
23
24
|
*
|
|
24
25
|
*/
|
|
25
26
|
export function createWithInsertData(
|
|
26
|
-
|
|
27
|
+
editorActor: EditorActor,
|
|
27
28
|
schemaTypes: PortableTextMemberSchemaTypes,
|
|
28
29
|
keyGenerator: () => string,
|
|
29
30
|
) {
|
|
@@ -158,9 +159,8 @@ export function createWithInsertData(
|
|
|
158
159
|
// Bail out if it's not valid
|
|
159
160
|
if (!validation.valid && !validation.resolution?.autoResolve) {
|
|
160
161
|
const errorDescription = `${validation.resolution?.description}`
|
|
161
|
-
|
|
162
|
+
editorActor.send({
|
|
162
163
|
type: 'error',
|
|
163
|
-
level: 'warning',
|
|
164
164
|
name: 'pasteError',
|
|
165
165
|
description: errorDescription,
|
|
166
166
|
data: validation,
|
|
@@ -180,7 +180,6 @@ export function createWithInsertData(
|
|
|
180
180
|
debug('No selection, not inserting')
|
|
181
181
|
return false
|
|
182
182
|
}
|
|
183
|
-
change$.next({type: 'loading', isLoading: true}) // This could potentially take some time
|
|
184
183
|
const html = data.getData('text/html')
|
|
185
184
|
const text = data.getData('text/plain')
|
|
186
185
|
|
|
@@ -188,7 +187,7 @@ export function createWithInsertData(
|
|
|
188
187
|
debug('Inserting data', data)
|
|
189
188
|
let portableText: PortableTextBlock[]
|
|
190
189
|
let fragment: Node[]
|
|
191
|
-
let insertedType
|
|
190
|
+
let insertedType: string | undefined
|
|
192
191
|
|
|
193
192
|
if (html) {
|
|
194
193
|
portableText = htmlToBlocks(html, schemaTypes.portableText, {
|
|
@@ -232,9 +231,8 @@ export function createWithInsertData(
|
|
|
232
231
|
// Bail out if it's not valid
|
|
233
232
|
if (!validation.valid) {
|
|
234
233
|
const errorDescription = `Could not validate the resulting portable text to insert.\n${validation.resolution?.description}\nTry to insert as plain text (shift-paste) instead.`
|
|
235
|
-
|
|
234
|
+
editorActor.send({
|
|
236
235
|
type: 'error',
|
|
237
|
-
level: 'warning',
|
|
238
236
|
name: 'pasteError',
|
|
239
237
|
description: errorDescription,
|
|
240
238
|
data: validation,
|
|
@@ -246,10 +244,8 @@ export function createWithInsertData(
|
|
|
246
244
|
`Inserting ${insertedType} fragment at ${JSON.stringify(editor.selection)}`,
|
|
247
245
|
)
|
|
248
246
|
_insertFragment(editor, fragment, schemaTypes)
|
|
249
|
-
change$.next({type: 'loading', isLoading: false})
|
|
250
247
|
return true
|
|
251
248
|
}
|
|
252
|
-
change$.next({type: 'loading', isLoading: false})
|
|
253
249
|
return false
|
|
254
250
|
}
|
|
255
251
|
|
|
@@ -335,8 +331,7 @@ function _regenerateKeys(
|
|
|
335
331
|
...child,
|
|
336
332
|
marks:
|
|
337
333
|
child.marks && child.marks.includes(oldKey)
|
|
338
|
-
?
|
|
339
|
-
[...child.marks]
|
|
334
|
+
? [...child.marks]
|
|
340
335
|
.filter((mark) => mark !== oldKey)
|
|
341
336
|
.concat(newKey)
|
|
342
337
|
: child.marks,
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import {Editor, Element, Node, Transforms} from 'slate'
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import type {
|
|
3
|
+
PortableTextMemberSchemaTypes,
|
|
4
|
+
PortableTextSlateEditor,
|
|
5
5
|
} from '../../types/editor'
|
|
6
6
|
import {isChangingRemotely} from '../../utils/withChanges'
|
|
7
7
|
import {isRedoing, isUndoing} from '../../utils/withUndoRedo'
|
|
8
|
+
import type {EditorActor} from '../editor-machine'
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* This plugin makes sure that every new node in the editor get a new _key prop when created
|
|
11
12
|
*
|
|
12
13
|
*/
|
|
13
14
|
export function createWithObjectKeys(
|
|
15
|
+
editorActor: EditorActor,
|
|
14
16
|
schemaTypes: PortableTextMemberSchemaTypes,
|
|
15
17
|
keyGenerator: () => string,
|
|
16
18
|
) {
|
|
@@ -75,12 +77,17 @@ export function createWithObjectKeys(
|
|
|
75
77
|
if (Element.isElement(node) && node._type === schemaTypes.block.name) {
|
|
76
78
|
// Set key on block itself
|
|
77
79
|
if (!node._key) {
|
|
80
|
+
editorActor.send({type: 'normalizing'})
|
|
78
81
|
Transforms.setNodes(editor, {_key: keyGenerator()}, {at: path})
|
|
82
|
+
editorActor.send({type: 'done normalizing'})
|
|
83
|
+
return
|
|
79
84
|
}
|
|
80
85
|
// Set keys on it's children
|
|
81
86
|
for (const [child, childPath] of Node.children(editor, path)) {
|
|
82
87
|
if (!child._key) {
|
|
88
|
+
editorActor.send({type: 'normalizing'})
|
|
83
89
|
Transforms.setNodes(editor, {_key: keyGenerator()}, {at: childPath})
|
|
90
|
+
editorActor.send({type: 'done normalizing'})
|
|
84
91
|
return
|
|
85
92
|
}
|
|
86
93
|
}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
/* eslint-disable max-nested-callbacks */
|
|
2
1
|
import {insert, setIfMissing, unset, type Patch} from '@portabletext/patches'
|
|
3
|
-
import {type Subject} from 'rxjs'
|
|
4
2
|
import {
|
|
5
3
|
Editor,
|
|
6
4
|
type Descendant,
|
|
@@ -14,11 +12,10 @@ import {
|
|
|
14
12
|
type SetNodeOperation,
|
|
15
13
|
type SplitNodeOperation,
|
|
16
14
|
} from 'slate'
|
|
17
|
-
import {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
type PortableTextSlateEditor,
|
|
15
|
+
import type {
|
|
16
|
+
PatchObservable,
|
|
17
|
+
PortableTextMemberSchemaTypes,
|
|
18
|
+
PortableTextSlateEditor,
|
|
22
19
|
} from '../../types/editor'
|
|
23
20
|
import {createApplyPatch} from '../../utils/applyPatch'
|
|
24
21
|
import {debugWithName} from '../../utils/debug'
|
|
@@ -33,6 +30,7 @@ import {
|
|
|
33
30
|
PATCHING,
|
|
34
31
|
withoutPatching,
|
|
35
32
|
} from '../../utils/withoutPatching'
|
|
33
|
+
import type {EditorActor} from '../editor-machine'
|
|
36
34
|
import {withoutSaving} from './createWithUndoRedo'
|
|
37
35
|
|
|
38
36
|
const debug = debugWithName('plugin:withPatches')
|
|
@@ -82,7 +80,7 @@ export interface PatchFunctions {
|
|
|
82
80
|
}
|
|
83
81
|
|
|
84
82
|
interface Options {
|
|
85
|
-
|
|
83
|
+
editorActor: EditorActor
|
|
86
84
|
keyGenerator: () => string
|
|
87
85
|
patches$?: PatchObservable
|
|
88
86
|
patchFunctions: PatchFunctions
|
|
@@ -91,7 +89,7 @@ interface Options {
|
|
|
91
89
|
}
|
|
92
90
|
|
|
93
91
|
export function createWithPatches({
|
|
94
|
-
|
|
92
|
+
editorActor,
|
|
95
93
|
patches$,
|
|
96
94
|
patchFunctions,
|
|
97
95
|
readOnly,
|
|
@@ -269,7 +267,6 @@ export function createWithPatches({
|
|
|
269
267
|
),
|
|
270
268
|
]
|
|
271
269
|
break
|
|
272
|
-
case 'set_selection':
|
|
273
270
|
default:
|
|
274
271
|
// Do nothing
|
|
275
272
|
}
|
|
@@ -283,7 +280,7 @@ export function createWithPatches({
|
|
|
283
280
|
)
|
|
284
281
|
) {
|
|
285
282
|
patches = [...patches, unset([])]
|
|
286
|
-
|
|
283
|
+
editorActor.send({
|
|
287
284
|
type: 'unset',
|
|
288
285
|
previousValue: fromSlateValue(
|
|
289
286
|
previousChildren,
|
|
@@ -301,7 +298,7 @@ export function createWithPatches({
|
|
|
301
298
|
// Emit all patches
|
|
302
299
|
if (patches.length > 0) {
|
|
303
300
|
patches.forEach((patch) => {
|
|
304
|
-
|
|
301
|
+
editorActor.send({
|
|
305
302
|
type: 'patch',
|
|
306
303
|
patch: {...patch, origin: 'local'},
|
|
307
304
|
})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {Editor, Path} from 'slate'
|
|
2
|
-
import
|
|
3
|
-
import
|
|
2
|
+
import type {PortableTextSlateEditor} from '../../types/editor'
|
|
3
|
+
import type {SlateTextBlock, VoidElement} from '../../types/slate'
|
|
4
4
|
import {debugWithName} from '../../utils/debug'
|
|
5
5
|
import {isChangingRemotely} from '../../utils/withChanges'
|
|
6
6
|
import {isRedoing, isUndoing} from '../../utils/withUndoRedo'
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import {Editor, Path, Text as SlateText, Transforms, type Node} from 'slate'
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import type {
|
|
3
|
+
PortableTextMemberSchemaTypes,
|
|
4
|
+
PortableTextSlateEditor,
|
|
5
5
|
} from '../../types/editor'
|
|
6
6
|
import {debugWithName} from '../../utils/debug'
|
|
7
|
+
import type {EditorActor} from '../editor-machine'
|
|
7
8
|
|
|
8
9
|
const debug = debugWithName('plugin:withPortableTextBlockStyle')
|
|
9
10
|
|
|
10
11
|
export function createWithPortableTextBlockStyle(
|
|
12
|
+
editorActor: EditorActor,
|
|
11
13
|
types: PortableTextMemberSchemaTypes,
|
|
12
14
|
): (editor: PortableTextSlateEditor) => PortableTextSlateEditor {
|
|
13
15
|
const defaultStyle = types.styles[0].value
|
|
@@ -17,9 +19,10 @@ export function createWithPortableTextBlockStyle(
|
|
|
17
19
|
// Extend Slate's default normalization to reset split node to normal style
|
|
18
20
|
// if there is no text at the right end of the split.
|
|
19
21
|
const {normalizeNode} = editor
|
|
22
|
+
|
|
20
23
|
editor.normalizeNode = (nodeEntry) => {
|
|
21
|
-
normalizeNode(nodeEntry)
|
|
22
24
|
const [, path] = nodeEntry
|
|
25
|
+
|
|
23
26
|
for (const op of editor.operations) {
|
|
24
27
|
if (
|
|
25
28
|
op.type === 'split_node' &&
|
|
@@ -32,16 +35,21 @@ export function createWithPortableTextBlockStyle(
|
|
|
32
35
|
const [child] = Editor.node(editor, [op.path[0] + 1, 0])
|
|
33
36
|
if (SlateText.isText(child) && child.text === '') {
|
|
34
37
|
debug(`Normalizing split node to ${defaultStyle} style`, op)
|
|
38
|
+
editorActor.send({type: 'normalizing'})
|
|
35
39
|
Transforms.setNodes(
|
|
36
40
|
editor,
|
|
37
41
|
{style: defaultStyle},
|
|
38
42
|
{at: [op.path[0] + 1], voids: false},
|
|
39
43
|
)
|
|
40
|
-
|
|
44
|
+
editorActor.send({type: 'done normalizing'})
|
|
45
|
+
return
|
|
41
46
|
}
|
|
42
47
|
}
|
|
43
48
|
}
|
|
49
|
+
|
|
50
|
+
normalizeNode(nodeEntry)
|
|
44
51
|
}
|
|
52
|
+
|
|
45
53
|
editor.pteHasBlockStyle = (style: string): boolean => {
|
|
46
54
|
if (!editor.selection) {
|
|
47
55
|
return false
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {Editor, Element, Text, Transforms, type Node} from 'slate'
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import type {
|
|
3
|
+
PortableTextMemberSchemaTypes,
|
|
4
|
+
PortableTextSlateEditor,
|
|
5
5
|
} from '../../types/editor'
|
|
6
6
|
import {debugWithName} from '../../utils/debug'
|
|
7
7
|
|
|
@@ -38,7 +38,6 @@ export function createWithPortableTextLists(
|
|
|
38
38
|
]
|
|
39
39
|
selectedBlocks.forEach(([node, path]) => {
|
|
40
40
|
if (editor.isListBlock(node)) {
|
|
41
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
42
41
|
const {listItem, level, ...rest} = node
|
|
43
42
|
const newNode = {
|
|
44
43
|
...rest,
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
/* eslint-disable max-statements */
|
|
2
|
-
/* eslint-disable complexity */
|
|
3
1
|
/**
|
|
4
2
|
*
|
|
5
3
|
* This plugin will change Slate's default marks model (every prop is a mark) with the Portable Text model (marks is an array of strings on prop .marks).
|
|
@@ -7,9 +5,8 @@
|
|
|
7
5
|
*/
|
|
8
6
|
|
|
9
7
|
import {isPortableTextBlock, isPortableTextSpan} from '@portabletext/toolkit'
|
|
10
|
-
import
|
|
8
|
+
import type {PortableTextObject} from '@sanity/types'
|
|
11
9
|
import {isEqual, uniq} from 'lodash'
|
|
12
|
-
import {type Subject} from 'rxjs'
|
|
13
10
|
import {
|
|
14
11
|
Editor,
|
|
15
12
|
Element,
|
|
@@ -20,21 +17,21 @@ import {
|
|
|
20
17
|
Transforms,
|
|
21
18
|
type Descendant,
|
|
22
19
|
} from 'slate'
|
|
23
|
-
import {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
type PortableTextSlateEditor,
|
|
20
|
+
import type {
|
|
21
|
+
PortableTextMemberSchemaTypes,
|
|
22
|
+
PortableTextSlateEditor,
|
|
27
23
|
} from '../../types/editor'
|
|
28
24
|
import {debugWithName} from '../../utils/debug'
|
|
29
25
|
import {toPortableTextRange} from '../../utils/ranges'
|
|
30
26
|
import {isChangingRemotely} from '../../utils/withChanges'
|
|
31
27
|
import {isRedoing, isUndoing} from '../../utils/withUndoRedo'
|
|
28
|
+
import type {EditorActor} from '../editor-machine'
|
|
32
29
|
|
|
33
30
|
const debug = debugWithName('plugin:withPortableTextMarkModel')
|
|
34
31
|
|
|
35
32
|
export function createWithPortableTextMarkModel(
|
|
33
|
+
editorActor: EditorActor,
|
|
36
34
|
types: PortableTextMemberSchemaTypes,
|
|
37
|
-
change$: Subject<EditorChange>,
|
|
38
35
|
keyGenerator: () => string,
|
|
39
36
|
): (editor: PortableTextSlateEditor) => PortableTextSlateEditor {
|
|
40
37
|
return function withPortableTextMarkModel(editor: PortableTextSlateEditor) {
|
|
@@ -61,7 +58,7 @@ export function createWithPortableTextMarkModel(
|
|
|
61
58
|
editor.selection,
|
|
62
59
|
types,
|
|
63
60
|
)
|
|
64
|
-
|
|
61
|
+
editorActor.send({type: 'selection', selection: ptRange})
|
|
65
62
|
}
|
|
66
63
|
|
|
67
64
|
// Extend Slate's default normalization. Merge spans with same set of .marks when doing merge_node operations, and clean up markDefs / marks
|
|
@@ -84,10 +81,12 @@ export function createWithPortableTextMarkModel(
|
|
|
84
81
|
JSON.stringify(child, null, 2),
|
|
85
82
|
JSON.stringify(nextNode, null, 2),
|
|
86
83
|
)
|
|
84
|
+
editorActor.send({type: 'normalizing'})
|
|
87
85
|
Transforms.mergeNodes(editor, {
|
|
88
86
|
at: [childPath[0], childPath[1] + 1],
|
|
89
87
|
voids: true,
|
|
90
88
|
})
|
|
89
|
+
editorActor.send({type: 'done normalizing'})
|
|
91
90
|
return
|
|
92
91
|
}
|
|
93
92
|
}
|
|
@@ -98,7 +97,9 @@ export function createWithPortableTextMarkModel(
|
|
|
98
97
|
*/
|
|
99
98
|
if (editor.isTextBlock(node) && !Array.isArray(node.markDefs)) {
|
|
100
99
|
debug('Adding .markDefs to block node')
|
|
100
|
+
editorActor.send({type: 'normalizing'})
|
|
101
101
|
Transforms.setNodes(editor, {markDefs: []}, {at: path})
|
|
102
|
+
editorActor.send({type: 'done normalizing'})
|
|
102
103
|
return
|
|
103
104
|
}
|
|
104
105
|
|
|
@@ -107,7 +108,9 @@ export function createWithPortableTextMarkModel(
|
|
|
107
108
|
*/
|
|
108
109
|
if (editor.isTextSpan(node) && !Array.isArray(node.marks)) {
|
|
109
110
|
debug('Adding .marks to span node')
|
|
111
|
+
editorActor.send({type: 'normalizing'})
|
|
110
112
|
Transforms.setNodes(editor, {marks: []}, {at: path})
|
|
113
|
+
editorActor.send({type: 'done normalizing'})
|
|
111
114
|
return
|
|
112
115
|
}
|
|
113
116
|
|
|
@@ -125,11 +128,13 @@ export function createWithPortableTextMarkModel(
|
|
|
125
128
|
if (editor.isTextBlock(block)) {
|
|
126
129
|
if (node.text === '' && annotations && annotations.length > 0) {
|
|
127
130
|
debug('Removing annotations from empty span node')
|
|
131
|
+
editorActor.send({type: 'normalizing'})
|
|
128
132
|
Transforms.setNodes(
|
|
129
133
|
editor,
|
|
130
134
|
{marks: node.marks?.filter((mark) => decorators.includes(mark))},
|
|
131
135
|
{at: path},
|
|
132
136
|
)
|
|
137
|
+
editorActor.send({type: 'done normalizing'})
|
|
133
138
|
return
|
|
134
139
|
}
|
|
135
140
|
}
|
|
@@ -153,6 +158,7 @@ export function createWithPortableTextMarkModel(
|
|
|
153
158
|
|
|
154
159
|
if (orphanedAnnotations.length > 0) {
|
|
155
160
|
debug('Removing orphaned annotations from span node')
|
|
161
|
+
editorActor.send({type: 'normalizing'})
|
|
156
162
|
Transforms.setNodes(
|
|
157
163
|
editor,
|
|
158
164
|
{
|
|
@@ -162,6 +168,7 @@ export function createWithPortableTextMarkModel(
|
|
|
162
168
|
},
|
|
163
169
|
{at: childPath},
|
|
164
170
|
)
|
|
171
|
+
editorActor.send({type: 'done normalizing'})
|
|
165
172
|
return
|
|
166
173
|
}
|
|
167
174
|
}
|
|
@@ -189,6 +196,7 @@ export function createWithPortableTextMarkModel(
|
|
|
189
196
|
|
|
190
197
|
if (orphanedAnnotations.length > 0) {
|
|
191
198
|
debug('Removing orphaned annotations from span node')
|
|
199
|
+
editorActor.send({type: 'normalizing'})
|
|
192
200
|
Transforms.setNodes(
|
|
193
201
|
editor,
|
|
194
202
|
{
|
|
@@ -198,6 +206,7 @@ export function createWithPortableTextMarkModel(
|
|
|
198
206
|
},
|
|
199
207
|
{at: path},
|
|
200
208
|
)
|
|
209
|
+
editorActor.send({type: 'done normalizing'})
|
|
201
210
|
return
|
|
202
211
|
}
|
|
203
212
|
}
|
|
@@ -218,7 +227,10 @@ export function createWithPortableTextMarkModel(
|
|
|
218
227
|
|
|
219
228
|
if (markDefs.length !== newMarkDefs.length) {
|
|
220
229
|
debug('Removing duplicate markDefs')
|
|
230
|
+
editorActor.send({type: 'normalizing'})
|
|
221
231
|
Transforms.setNodes(editor, {markDefs: newMarkDefs}, {at: path})
|
|
232
|
+
editorActor.send({type: 'done normalizing'})
|
|
233
|
+
return
|
|
222
234
|
}
|
|
223
235
|
}
|
|
224
236
|
|
|
@@ -243,6 +255,7 @@ export function createWithPortableTextMarkModel(
|
|
|
243
255
|
})
|
|
244
256
|
if (node.markDefs && !isEqual(newMarkDefs, node.markDefs)) {
|
|
245
257
|
debug('Removing markDef not in use')
|
|
258
|
+
editorActor.send({type: 'normalizing'})
|
|
246
259
|
Transforms.setNodes(
|
|
247
260
|
editor,
|
|
248
261
|
{
|
|
@@ -250,6 +263,7 @@ export function createWithPortableTextMarkModel(
|
|
|
250
263
|
},
|
|
251
264
|
{at: path},
|
|
252
265
|
)
|
|
266
|
+
editorActor.send({type: 'done normalizing'})
|
|
253
267
|
return
|
|
254
268
|
}
|
|
255
269
|
}
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
type PortableTextMemberSchemaTypes,
|
|
7
|
-
type PortableTextSlateEditor,
|
|
1
|
+
import type {BaseRange} from 'slate'
|
|
2
|
+
import type {
|
|
3
|
+
EditorSelection,
|
|
4
|
+
PortableTextMemberSchemaTypes,
|
|
5
|
+
PortableTextSlateEditor,
|
|
8
6
|
} from '../../types/editor'
|
|
9
7
|
import {debugWithName} from '../../utils/debug'
|
|
10
8
|
import {
|
|
@@ -12,13 +10,14 @@ import {
|
|
|
12
10
|
type ObjectWithKeyAndType,
|
|
13
11
|
} from '../../utils/ranges'
|
|
14
12
|
import {SLATE_TO_PORTABLE_TEXT_RANGE} from '../../utils/weakMaps'
|
|
13
|
+
import type {EditorActor} from '../editor-machine'
|
|
15
14
|
|
|
16
15
|
const debug = debugWithName('plugin:withPortableTextSelections')
|
|
17
16
|
const debugVerbose = debug.enabled && false
|
|
18
17
|
|
|
19
18
|
// This plugin will make sure that we emit a PT selection whenever the editor has changed.
|
|
20
19
|
export function createWithPortableTextSelections(
|
|
21
|
-
|
|
20
|
+
editorActor: EditorActor,
|
|
22
21
|
types: PortableTextMemberSchemaTypes,
|
|
23
22
|
): (editor: PortableTextSlateEditor) => PortableTextSlateEditor {
|
|
24
23
|
let prevSelection: BaseRange | null = null
|
|
@@ -46,9 +45,9 @@ export function createWithPortableTextSelections(
|
|
|
46
45
|
)
|
|
47
46
|
}
|
|
48
47
|
if (ptRange) {
|
|
49
|
-
|
|
48
|
+
editorActor.send({type: 'selection', selection: ptRange})
|
|
50
49
|
} else {
|
|
51
|
-
|
|
50
|
+
editorActor.send({type: 'selection', selection: null})
|
|
52
51
|
}
|
|
53
52
|
}
|
|
54
53
|
prevSelection = editor.selection
|
|
@@ -7,11 +7,12 @@ import {
|
|
|
7
7
|
type PortableTextTextBlock,
|
|
8
8
|
} from '@sanity/types'
|
|
9
9
|
import {Transforms, type Element} from 'slate'
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
import type {
|
|
11
|
+
PortableTextMemberSchemaTypes,
|
|
12
|
+
PortableTextSlateEditor,
|
|
13
13
|
} from '../../types/editor'
|
|
14
14
|
import {debugWithName} from '../../utils/debug'
|
|
15
|
+
import type {EditorActor} from '../editor-machine'
|
|
15
16
|
|
|
16
17
|
const debug = debugWithName('plugin:withSchemaTypes')
|
|
17
18
|
/**
|
|
@@ -19,9 +20,11 @@ const debug = debugWithName('plugin:withSchemaTypes')
|
|
|
19
20
|
*
|
|
20
21
|
*/
|
|
21
22
|
export function createWithSchemaTypes({
|
|
23
|
+
editorActor,
|
|
22
24
|
schemaTypes,
|
|
23
25
|
keyGenerator,
|
|
24
26
|
}: {
|
|
27
|
+
editorActor: EditorActor
|
|
25
28
|
schemaTypes: PortableTextMemberSchemaTypes
|
|
26
29
|
keyGenerator: () => string
|
|
27
30
|
}) {
|
|
@@ -34,7 +37,7 @@ export function createWithSchemaTypes({
|
|
|
34
37
|
)
|
|
35
38
|
}
|
|
36
39
|
editor.isTextSpan = (value: unknown): value is PortableTextSpan => {
|
|
37
|
-
return isPortableTextSpan(value) && value._type
|
|
40
|
+
return isPortableTextSpan(value) && value._type === schemaTypes.span.name
|
|
38
41
|
}
|
|
39
42
|
editor.isListBlock = (value: unknown): value is PortableTextListBlock => {
|
|
40
43
|
return (
|
|
@@ -71,18 +74,24 @@ export function createWithSchemaTypes({
|
|
|
71
74
|
debug('Setting span type on text node without a type')
|
|
72
75
|
const span = node as PortableTextSpan
|
|
73
76
|
const key = span._key || keyGenerator()
|
|
77
|
+
editorActor.send({type: 'normalizing'})
|
|
74
78
|
Transforms.setNodes(
|
|
75
79
|
editor,
|
|
76
80
|
{...span, _type: schemaTypes.span.name, _key: key},
|
|
77
81
|
{at: path},
|
|
78
82
|
)
|
|
83
|
+
editorActor.send({type: 'done normalizing'})
|
|
84
|
+
return
|
|
79
85
|
}
|
|
80
86
|
|
|
81
87
|
// catches cases when the children are missing keys but excludes it when the normalize is running the node as the editor object
|
|
82
88
|
if (node._key === undefined && (path.length === 1 || path.length === 2)) {
|
|
83
89
|
debug('Setting missing key on child node without a key')
|
|
84
90
|
const key = keyGenerator()
|
|
91
|
+
editorActor.send({type: 'normalizing'})
|
|
85
92
|
Transforms.setNodes(editor, {_key: key}, {at: path})
|
|
93
|
+
editorActor.send({type: 'done normalizing'})
|
|
94
|
+
return
|
|
86
95
|
}
|
|
87
96
|
|
|
88
97
|
normalizeNode(entry)
|
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
* The undo/redo steps are rebased against incoming patches since the step occurred.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import
|
|
6
|
+
import type {Patch} from '@portabletext/patches'
|
|
7
7
|
import {
|
|
8
8
|
DIFF_DELETE,
|
|
9
9
|
DIFF_EQUAL,
|
|
10
10
|
DIFF_INSERT,
|
|
11
11
|
parsePatch,
|
|
12
12
|
} from '@sanity/diff-match-patch'
|
|
13
|
-
import
|
|
13
|
+
import type {ObjectSchemaType, PortableTextBlock} from '@sanity/types'
|
|
14
14
|
import {flatten, isEqual} from 'lodash'
|
|
15
15
|
import {
|
|
16
16
|
Editor,
|
|
@@ -20,10 +20,7 @@ import {
|
|
|
20
20
|
type Descendant,
|
|
21
21
|
type SelectionOperation,
|
|
22
22
|
} from 'slate'
|
|
23
|
-
import {
|
|
24
|
-
type PatchObservable,
|
|
25
|
-
type PortableTextSlateEditor,
|
|
26
|
-
} from '../../types/editor'
|
|
23
|
+
import type {PatchObservable, PortableTextSlateEditor} from '../../types/editor'
|
|
27
24
|
import {debugWithName} from '../../utils/debug'
|
|
28
25
|
import {fromSlateValue} from '../../utils/values'
|
|
29
26
|
import {
|
|
@@ -248,7 +245,6 @@ export function createWithUndoRedo(
|
|
|
248
245
|
Editor.withoutNormalizing(editor, () => {
|
|
249
246
|
withRedoing(editor, () => {
|
|
250
247
|
withoutSaving(editor, () => {
|
|
251
|
-
// eslint-disable-next-line max-nested-callbacks
|
|
252
248
|
transformedOperations.forEach((op) => {
|
|
253
249
|
editor.apply(op)
|
|
254
250
|
})
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {Editor, Range, Text, Transforms} from 'slate'
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import type {
|
|
3
|
+
PortableTextMemberSchemaTypes,
|
|
4
|
+
PortableTextSlateEditor,
|
|
5
5
|
} from '../../types/editor'
|
|
6
6
|
import {debugWithName} from '../../utils/debug'
|
|
7
7
|
import {toSlateValue} from '../../utils/values'
|
|
8
|
-
import
|
|
8
|
+
import type {PortableTextEditor} from '../PortableTextEditor'
|
|
9
9
|
|
|
10
10
|
const debug = debugWithName('plugin:withUtils')
|
|
11
11
|
|
|
@@ -59,8 +59,8 @@ export function createWithUtils({
|
|
|
59
59
|
if (
|
|
60
60
|
!(
|
|
61
61
|
newStartOffset === newEndOffset ||
|
|
62
|
-
isNaN(newStartOffset) ||
|
|
63
|
-
isNaN(newEndOffset)
|
|
62
|
+
Number.isNaN(newStartOffset) ||
|
|
63
|
+
Number.isNaN(newEndOffset)
|
|
64
64
|
)
|
|
65
65
|
) {
|
|
66
66
|
debug('pteExpandToWord: Expanding to focused word')
|