@portabletext/editor 3.0.6 → 3.0.8
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-dts/index.d.ts +2 -2
- package/lib/_chunks-es/util.slice-blocks.js +1 -8
- package/lib/_chunks-es/util.slice-blocks.js.map +1 -1
- package/lib/index.js +112 -131
- package/lib/index.js.map +1 -1
- package/package.json +9 -9
- package/src/converters/converter.portable-text.deserialize.test.ts +0 -13
- package/src/editor/Editable.tsx +3 -11
- package/src/editor/create-editor.ts +1 -7
- package/src/editor/create-slate-editor.tsx +13 -13
- package/src/editor/plugins/createWithEditableAPI.ts +68 -75
- package/src/editor/plugins/createWithPatches.ts +20 -23
- package/src/editor/plugins/createWithPortableTextMarkModel.ts +19 -0
- package/src/editor/range-decorations-machine.ts +1 -1
- package/src/editor/weakMaps.ts +0 -2
- package/src/history/slate-plugin.history.ts +1 -5
- package/src/internal-utils/__tests__/values.test.ts +1 -121
- package/src/internal-utils/applyPatch.ts +1 -1
- package/src/internal-utils/operation-to-patches.test.ts +31 -6
- package/src/internal-utils/operation-to-patches.ts +10 -16
- package/src/internal-utils/values.test.ts +0 -7
- package/src/internal-utils/values.ts +70 -34
- package/src/operations/behavior.operation.block.unset.ts +12 -36
- package/src/operations/behavior.operation.child.unset.ts +33 -15
- package/src/utils/parse-blocks.test.ts +0 -16
- package/src/utils/parse-blocks.ts +6 -11
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {compileSchema, defineSchema} from '@portabletext/schema'
|
|
2
2
|
import {describe, expect, it} from 'vitest'
|
|
3
|
-
import {
|
|
3
|
+
import {toSlateBlock} from '../values'
|
|
4
4
|
|
|
5
5
|
const schemaTypes = compileSchema(defineSchema({}))
|
|
6
6
|
|
|
@@ -51,7 +51,6 @@ describe(toSlateBlock.name, () => {
|
|
|
51
51
|
text: '123',
|
|
52
52
|
},
|
|
53
53
|
],
|
|
54
|
-
style: 'normal',
|
|
55
54
|
})
|
|
56
55
|
})
|
|
57
56
|
|
|
@@ -106,125 +105,6 @@ describe(toSlateBlock.name, () => {
|
|
|
106
105
|
},
|
|
107
106
|
},
|
|
108
107
|
],
|
|
109
|
-
style: 'normal',
|
|
110
108
|
})
|
|
111
109
|
})
|
|
112
110
|
})
|
|
113
|
-
|
|
114
|
-
describe('fromSlateValue', () => {
|
|
115
|
-
it('runs given empty array', () => {
|
|
116
|
-
const result = fromSlateValue([], 'image')
|
|
117
|
-
expect(result).toHaveLength(0)
|
|
118
|
-
})
|
|
119
|
-
|
|
120
|
-
it('converts a slate value to portable text', () => {
|
|
121
|
-
const ptValue = fromSlateValue(
|
|
122
|
-
[
|
|
123
|
-
{
|
|
124
|
-
_type: 'block',
|
|
125
|
-
_key: 'dr239u3',
|
|
126
|
-
children: [
|
|
127
|
-
{
|
|
128
|
-
_type: 'span',
|
|
129
|
-
_key: '252f4swet',
|
|
130
|
-
marks: [],
|
|
131
|
-
text: 'Hey ',
|
|
132
|
-
},
|
|
133
|
-
{
|
|
134
|
-
_type: 'image',
|
|
135
|
-
_key: 'e324t4s',
|
|
136
|
-
__inline: true,
|
|
137
|
-
children: [{_key: '1', _type: 'span', text: '', marks: []}],
|
|
138
|
-
value: {
|
|
139
|
-
_type: 'image',
|
|
140
|
-
_key: 'e324t4s',
|
|
141
|
-
asset: {_ref: '32423r32rewr3rwerwer'},
|
|
142
|
-
},
|
|
143
|
-
},
|
|
144
|
-
],
|
|
145
|
-
markDefs: [],
|
|
146
|
-
style: 'normal',
|
|
147
|
-
},
|
|
148
|
-
{
|
|
149
|
-
_type: 'image',
|
|
150
|
-
_key: 'wer32434',
|
|
151
|
-
children: [{_key: '1', _type: 'span', text: '', marks: []}],
|
|
152
|
-
value: {
|
|
153
|
-
_type: 'image',
|
|
154
|
-
_key: 'wer32434',
|
|
155
|
-
asset: {_ref: 'werwer452423423'},
|
|
156
|
-
},
|
|
157
|
-
},
|
|
158
|
-
],
|
|
159
|
-
'block',
|
|
160
|
-
)
|
|
161
|
-
expect(ptValue).toEqual([
|
|
162
|
-
{
|
|
163
|
-
_type: 'block',
|
|
164
|
-
_key: 'dr239u3',
|
|
165
|
-
children: [
|
|
166
|
-
{
|
|
167
|
-
_type: 'span',
|
|
168
|
-
_key: '252f4swet',
|
|
169
|
-
marks: [],
|
|
170
|
-
text: 'Hey ',
|
|
171
|
-
},
|
|
172
|
-
{
|
|
173
|
-
_type: 'image',
|
|
174
|
-
_key: 'e324t4s',
|
|
175
|
-
asset: {_ref: '32423r32rewr3rwerwer'},
|
|
176
|
-
},
|
|
177
|
-
],
|
|
178
|
-
markDefs: [],
|
|
179
|
-
style: 'normal',
|
|
180
|
-
},
|
|
181
|
-
{
|
|
182
|
-
_type: 'image',
|
|
183
|
-
_key: 'wer32434',
|
|
184
|
-
asset: {_ref: 'werwer452423423'},
|
|
185
|
-
},
|
|
186
|
-
])
|
|
187
|
-
})
|
|
188
|
-
|
|
189
|
-
it('has equality', () => {
|
|
190
|
-
const keyMap = {}
|
|
191
|
-
const value = [
|
|
192
|
-
{
|
|
193
|
-
_type: 'image',
|
|
194
|
-
_key: 'wer32434',
|
|
195
|
-
asset: {_ref: 'werwer452423423'},
|
|
196
|
-
},
|
|
197
|
-
{
|
|
198
|
-
_type: 'block',
|
|
199
|
-
_key: 'dr239u3',
|
|
200
|
-
children: [
|
|
201
|
-
{
|
|
202
|
-
_type: 'span',
|
|
203
|
-
_key: '252f4swet',
|
|
204
|
-
marks: [],
|
|
205
|
-
text: 'Hey ',
|
|
206
|
-
},
|
|
207
|
-
{
|
|
208
|
-
_type: 'image',
|
|
209
|
-
_key: 'e324t4s',
|
|
210
|
-
asset: {_ref: '32423r32rewr3rwerwer'},
|
|
211
|
-
},
|
|
212
|
-
],
|
|
213
|
-
markDefs: [],
|
|
214
|
-
style: 'normal',
|
|
215
|
-
},
|
|
216
|
-
]
|
|
217
|
-
const toSlate1 = value.map((block) =>
|
|
218
|
-
toSlateBlock(block, {schemaTypes}, keyMap),
|
|
219
|
-
)
|
|
220
|
-
const toSlate2 = value.map((block) =>
|
|
221
|
-
toSlateBlock(block, {schemaTypes}, keyMap),
|
|
222
|
-
)
|
|
223
|
-
expect(toSlate1[0]).toBe(toSlate2[0])
|
|
224
|
-
expect(toSlate1[1]).toBe(toSlate2[1])
|
|
225
|
-
const fromSlate1 = fromSlateValue(toSlate1, 'block', keyMap)
|
|
226
|
-
const fromSlate2 = fromSlateValue(toSlate2, 'block', keyMap)
|
|
227
|
-
expect(fromSlate1[0]).toBe(fromSlate2[0])
|
|
228
|
-
expect(fromSlate1[1]).toBe(fromSlate2[1])
|
|
229
|
-
})
|
|
230
|
-
})
|
|
@@ -145,7 +145,7 @@ function insertPatch(
|
|
|
145
145
|
const normalizedIdx =
|
|
146
146
|
position === 'after' ? targetBlockIndex + 1 : targetBlockIndex
|
|
147
147
|
|
|
148
|
-
const editorWasEmptyBefore = isEqualToEmptyEditor(editor.
|
|
148
|
+
const editorWasEmptyBefore = isEqualToEmptyEditor(editor.value, schema)
|
|
149
149
|
|
|
150
150
|
Transforms.insertNodes(editor, blocksToInsert, {at: [normalizedIdx]})
|
|
151
151
|
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import {compileSchemaDefinitionToPortableTextMemberSchemaTypes} from '@portabletext/sanity-bridge'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
compileSchema,
|
|
4
|
+
defineSchema,
|
|
5
|
+
type PortableTextBlock,
|
|
6
|
+
} from '@portabletext/schema'
|
|
3
7
|
import type {PortableTextTextBlock} from '@sanity/types'
|
|
4
8
|
import {createEditor, type Descendant} from 'slate'
|
|
5
9
|
import {beforeEach, describe, expect, it, test} from 'vitest'
|
|
@@ -32,13 +36,15 @@ const editorActor = createActor(editorMachine, {
|
|
|
32
36
|
})
|
|
33
37
|
const relayActor = createActor(relayMachine)
|
|
34
38
|
|
|
35
|
-
const
|
|
39
|
+
const e = createEditor()
|
|
40
|
+
e.value = []
|
|
41
|
+
const editor = withPlugins(e, {
|
|
36
42
|
editorActor,
|
|
37
43
|
relayActor,
|
|
38
44
|
subscriptions: [],
|
|
39
45
|
})
|
|
40
46
|
|
|
41
|
-
const
|
|
47
|
+
const createDefaultChildren = () =>
|
|
42
48
|
[
|
|
43
49
|
{
|
|
44
50
|
_type: 'block',
|
|
@@ -57,7 +63,25 @@ const createDefaultValue = () =>
|
|
|
57
63
|
{_type: 'span', _key: 'fd9b4a4e6c0b', text: '', marks: []},
|
|
58
64
|
],
|
|
59
65
|
},
|
|
60
|
-
]
|
|
66
|
+
] satisfies Array<Descendant>
|
|
67
|
+
const createDefaultValue = () =>
|
|
68
|
+
[
|
|
69
|
+
{
|
|
70
|
+
_type: 'block',
|
|
71
|
+
_key: '1f2e64b47787',
|
|
72
|
+
style: 'normal',
|
|
73
|
+
markDefs: [],
|
|
74
|
+
children: [
|
|
75
|
+
{_type: 'span', _key: 'c130395c640c', text: '', marks: []},
|
|
76
|
+
{
|
|
77
|
+
_key: '773866318fa8',
|
|
78
|
+
_type: 'someObject',
|
|
79
|
+
value: {title: 'The Object'},
|
|
80
|
+
},
|
|
81
|
+
{_type: 'span', _key: 'fd9b4a4e6c0b', text: '', marks: []},
|
|
82
|
+
],
|
|
83
|
+
},
|
|
84
|
+
] as Array<PortableTextBlock>
|
|
61
85
|
|
|
62
86
|
describe(insertNodePatch.name, () => {
|
|
63
87
|
test('Scenario: Inserting block object on empty editor', () => {
|
|
@@ -121,7 +145,7 @@ describe(insertNodePatch.name, () => {
|
|
|
121
145
|
|
|
122
146
|
describe('operationToPatches', () => {
|
|
123
147
|
beforeEach(() => {
|
|
124
|
-
editor.children =
|
|
148
|
+
editor.children = createDefaultChildren()
|
|
125
149
|
editor.onChange()
|
|
126
150
|
})
|
|
127
151
|
|
|
@@ -418,12 +442,13 @@ describe('operationToPatches', () => {
|
|
|
418
442
|
})
|
|
419
443
|
|
|
420
444
|
it('produce correct remove block patch', () => {
|
|
445
|
+
const children = createDefaultChildren()
|
|
421
446
|
const val = createDefaultValue()
|
|
422
447
|
expect(
|
|
423
448
|
removeNodePatch(editorActor.getSnapshot().context.schema, val, {
|
|
424
449
|
type: 'remove_node',
|
|
425
450
|
path: [0],
|
|
426
|
-
node:
|
|
451
|
+
node: children[0],
|
|
427
452
|
}),
|
|
428
453
|
).toMatchInlineSnapshot(`
|
|
429
454
|
[
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
type InsertPosition,
|
|
8
8
|
type Patch,
|
|
9
9
|
} from '@portabletext/patches'
|
|
10
|
-
import {isSpan, isTextBlock} from '@portabletext/schema'
|
|
10
|
+
import {isSpan, isTextBlock, type PortableTextBlock} from '@portabletext/schema'
|
|
11
11
|
import type {Path, PortableTextSpan, PortableTextTextBlock} from '@sanity/types'
|
|
12
12
|
import {
|
|
13
13
|
Element,
|
|
@@ -29,7 +29,7 @@ export function insertTextPatch(
|
|
|
29
29
|
schema: EditorSchema,
|
|
30
30
|
children: Descendant[],
|
|
31
31
|
operation: InsertTextOperation,
|
|
32
|
-
beforeValue:
|
|
32
|
+
beforeValue: Array<PortableTextBlock>,
|
|
33
33
|
): Array<Patch> {
|
|
34
34
|
const block =
|
|
35
35
|
isTextBlock({schema}, children[operation.path[0]]) &&
|
|
@@ -62,7 +62,7 @@ export function removeTextPatch(
|
|
|
62
62
|
schema: EditorSchema,
|
|
63
63
|
children: Descendant[],
|
|
64
64
|
operation: RemoveTextOperation,
|
|
65
|
-
beforeValue:
|
|
65
|
+
beforeValue: Array<PortableTextBlock>,
|
|
66
66
|
): Array<Patch> {
|
|
67
67
|
const block = children[operation.path[0]]
|
|
68
68
|
if (!block) {
|
|
@@ -271,7 +271,7 @@ export function insertNodePatch(
|
|
|
271
271
|
schema: EditorSchema,
|
|
272
272
|
children: Descendant[],
|
|
273
273
|
operation: InsertNodeOperation,
|
|
274
|
-
beforeValue:
|
|
274
|
+
beforeValue: Array<PortableTextBlock>,
|
|
275
275
|
): Array<Patch> {
|
|
276
276
|
const block = beforeValue[operation.path[0]]
|
|
277
277
|
if (operation.path.length === 1) {
|
|
@@ -346,7 +346,7 @@ export function splitNodePatch(
|
|
|
346
346
|
schema: EditorSchema,
|
|
347
347
|
children: Descendant[],
|
|
348
348
|
operation: SplitNodeOperation,
|
|
349
|
-
beforeValue:
|
|
349
|
+
beforeValue: Array<PortableTextBlock>,
|
|
350
350
|
): Array<Patch> {
|
|
351
351
|
const patches: Patch[] = []
|
|
352
352
|
const splitBlock = children[operation.path[0]]
|
|
@@ -414,7 +414,7 @@ export function splitNodePatch(
|
|
|
414
414
|
|
|
415
415
|
export function removeNodePatch(
|
|
416
416
|
schema: EditorSchema,
|
|
417
|
-
beforeValue:
|
|
417
|
+
beforeValue: Array<PortableTextBlock>,
|
|
418
418
|
operation: RemoveNodeOperation,
|
|
419
419
|
): Array<Patch> {
|
|
420
420
|
const block = beforeValue[operation.path[0]]
|
|
@@ -454,7 +454,7 @@ export function mergeNodePatch(
|
|
|
454
454
|
schema: EditorSchema,
|
|
455
455
|
children: Descendant[],
|
|
456
456
|
operation: MergeNodeOperation,
|
|
457
|
-
beforeValue:
|
|
457
|
+
beforeValue: Array<PortableTextBlock>,
|
|
458
458
|
): Array<Patch> {
|
|
459
459
|
const patches: Patch[] = []
|
|
460
460
|
|
|
@@ -532,7 +532,7 @@ export function mergeNodePatch(
|
|
|
532
532
|
|
|
533
533
|
export function moveNodePatch(
|
|
534
534
|
schema: EditorSchema,
|
|
535
|
-
beforeValue:
|
|
535
|
+
beforeValue: Array<PortableTextBlock>,
|
|
536
536
|
operation: MoveNodeOperation,
|
|
537
537
|
): Array<Patch> {
|
|
538
538
|
const patches: Patch[] = []
|
|
@@ -547,11 +547,7 @@ export function moveNodePatch(
|
|
|
547
547
|
const position: InsertPosition =
|
|
548
548
|
operation.path[0] > operation.newPath[0] ? 'before' : 'after'
|
|
549
549
|
patches.push(unset([{_key: block._key}]))
|
|
550
|
-
patches.push(
|
|
551
|
-
insert([fromSlateBlock(block, schema.block.name)], position, [
|
|
552
|
-
{_key: targetBlock._key},
|
|
553
|
-
]),
|
|
554
|
-
)
|
|
550
|
+
patches.push(insert([block], position, [{_key: targetBlock._key}]))
|
|
555
551
|
} else if (
|
|
556
552
|
operation.path.length === 2 &&
|
|
557
553
|
isTextBlock({schema}, block) &&
|
|
@@ -561,9 +557,7 @@ export function moveNodePatch(
|
|
|
561
557
|
const targetChild = targetBlock.children[operation.newPath[1]]
|
|
562
558
|
const position =
|
|
563
559
|
operation.newPath[1] === targetBlock.children.length ? 'after' : 'before'
|
|
564
|
-
const childToInsert =
|
|
565
|
-
fromSlateBlock(block, schema.block.name) as PortableTextTextBlock
|
|
566
|
-
).children[operation.path[1]]
|
|
560
|
+
const childToInsert = block.children[operation.path[1]]
|
|
567
561
|
patches.push(unset([{_key: block._key}, 'children', {_key: child._key}]))
|
|
568
562
|
patches.push(
|
|
569
563
|
insert([childToInsert], position, [
|
|
@@ -32,7 +32,6 @@ describe(toSlateBlock.name, () => {
|
|
|
32
32
|
text: 'foo',
|
|
33
33
|
},
|
|
34
34
|
],
|
|
35
|
-
style: 'normal',
|
|
36
35
|
})
|
|
37
36
|
})
|
|
38
37
|
|
|
@@ -62,7 +61,6 @@ describe(toSlateBlock.name, () => {
|
|
|
62
61
|
text: 'foo',
|
|
63
62
|
},
|
|
64
63
|
],
|
|
65
|
-
style: 'normal',
|
|
66
64
|
})
|
|
67
65
|
})
|
|
68
66
|
|
|
@@ -101,7 +99,6 @@ describe(toSlateBlock.name, () => {
|
|
|
101
99
|
__inline: true,
|
|
102
100
|
},
|
|
103
101
|
],
|
|
104
|
-
style: 'normal',
|
|
105
102
|
})
|
|
106
103
|
})
|
|
107
104
|
})
|
|
@@ -148,7 +145,6 @@ describe(toSlateBlock.name, () => {
|
|
|
148
145
|
},
|
|
149
146
|
},
|
|
150
147
|
],
|
|
151
|
-
style: 'normal',
|
|
152
148
|
})
|
|
153
149
|
})
|
|
154
150
|
|
|
@@ -191,7 +187,6 @@ describe(toSlateBlock.name, () => {
|
|
|
191
187
|
},
|
|
192
188
|
},
|
|
193
189
|
],
|
|
194
|
-
style: 'normal',
|
|
195
190
|
})
|
|
196
191
|
})
|
|
197
192
|
})
|
|
@@ -238,7 +233,6 @@ describe(toSlateBlock.name, () => {
|
|
|
238
233
|
},
|
|
239
234
|
},
|
|
240
235
|
],
|
|
241
|
-
style: 'normal',
|
|
242
236
|
})
|
|
243
237
|
})
|
|
244
238
|
|
|
@@ -281,7 +275,6 @@ describe(toSlateBlock.name, () => {
|
|
|
281
275
|
},
|
|
282
276
|
},
|
|
283
277
|
],
|
|
284
|
-
style: 'normal',
|
|
285
278
|
})
|
|
286
279
|
})
|
|
287
280
|
})
|
|
@@ -35,7 +35,6 @@ export function toSlateBlock(
|
|
|
35
35
|
if (isPortableText) {
|
|
36
36
|
const textBlock = block as PortableTextTextBlock
|
|
37
37
|
let hasInlines = false
|
|
38
|
-
const hasMissingStyle = typeof textBlock.style === 'undefined'
|
|
39
38
|
const hasMissingMarkDefs = typeof textBlock.markDefs === 'undefined'
|
|
40
39
|
const hasMissingChildren = typeof textBlock.children === 'undefined'
|
|
41
40
|
|
|
@@ -86,7 +85,6 @@ export function toSlateBlock(
|
|
|
86
85
|
|
|
87
86
|
// Return original block
|
|
88
87
|
if (
|
|
89
|
-
!hasMissingStyle &&
|
|
90
88
|
!hasMissingMarkDefs &&
|
|
91
89
|
!hasMissingChildren &&
|
|
92
90
|
!hasInlines &&
|
|
@@ -96,11 +94,6 @@ export function toSlateBlock(
|
|
|
96
94
|
return block
|
|
97
95
|
}
|
|
98
96
|
|
|
99
|
-
// TODO: remove this when we have a better way to handle missing style
|
|
100
|
-
if (hasMissingStyle) {
|
|
101
|
-
rest.style = schemaTypes.styles[0].name
|
|
102
|
-
}
|
|
103
|
-
|
|
104
97
|
return keepObjectEquality(
|
|
105
98
|
{_type, _key, ...rest, children},
|
|
106
99
|
keyMap,
|
|
@@ -125,14 +118,6 @@ export function toSlateBlock(
|
|
|
125
118
|
) as Descendant
|
|
126
119
|
}
|
|
127
120
|
|
|
128
|
-
export function fromSlateValue(
|
|
129
|
-
value: Descendant[],
|
|
130
|
-
textBlockType: string,
|
|
131
|
-
keyMap: Record<string, PortableTextBlock | PortableTextChild> = {},
|
|
132
|
-
): PortableTextBlock[] {
|
|
133
|
-
return value.map((block) => fromSlateBlock(block, textBlockType, keyMap))
|
|
134
|
-
}
|
|
135
|
-
|
|
136
121
|
export function fromSlateBlock(
|
|
137
122
|
block: Descendant,
|
|
138
123
|
textBlockType: string,
|
|
@@ -184,25 +169,76 @@ export function fromSlateBlock(
|
|
|
184
169
|
}
|
|
185
170
|
|
|
186
171
|
export function isEqualToEmptyEditor(
|
|
187
|
-
|
|
172
|
+
blocks: Array<Descendant> | Array<PortableTextBlock>,
|
|
188
173
|
schemaTypes: EditorSchema,
|
|
189
174
|
): boolean {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
175
|
+
// Must have exactly one block
|
|
176
|
+
if (blocks.length !== 1) {
|
|
177
|
+
return false
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const firstBlock = blocks.at(0)
|
|
181
|
+
|
|
182
|
+
if (!firstBlock) {
|
|
183
|
+
return true
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (!Element.isElement(firstBlock)) {
|
|
187
|
+
return false
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Must be a text block
|
|
191
|
+
if (firstBlock._type !== schemaTypes.block.name) {
|
|
192
|
+
return false
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Must not be a list item
|
|
196
|
+
if ('listItem' in firstBlock) {
|
|
197
|
+
return false
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Style must exist and be the default style
|
|
201
|
+
if (
|
|
202
|
+
!('style' in firstBlock) ||
|
|
203
|
+
firstBlock.style !== schemaTypes.styles.at(0)?.name
|
|
204
|
+
) {
|
|
205
|
+
return false
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Must have children array
|
|
209
|
+
if (!Array.isArray(firstBlock.children)) {
|
|
210
|
+
return false
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Must have exactly one child
|
|
214
|
+
if (firstBlock.children.length !== 1) {
|
|
215
|
+
return false
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const firstChild = firstBlock.children.at(0)
|
|
219
|
+
|
|
220
|
+
if (!firstChild) {
|
|
221
|
+
return false
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (!Text.isText(firstChild)) {
|
|
225
|
+
return false
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Must be a span type
|
|
229
|
+
if (!('_type' in firstChild) || firstChild._type !== schemaTypes.span.name) {
|
|
230
|
+
return false
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Must have empty text
|
|
234
|
+
if (firstChild.text !== '') {
|
|
235
|
+
return false
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Must have no marks (marks can be undefined or empty array)
|
|
239
|
+
if (firstChild.marks?.join('')) {
|
|
240
|
+
return false
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return true
|
|
208
244
|
}
|
|
@@ -1,56 +1,32 @@
|
|
|
1
1
|
import {isTextBlock} from '@portabletext/schema'
|
|
2
2
|
import {omit} from 'lodash'
|
|
3
|
-
import {
|
|
4
|
-
import {KEY_TO_VALUE_ELEMENT} from '../editor/weakMaps'
|
|
5
|
-
import {toSlateRange} from '../internal-utils/to-slate-range'
|
|
6
|
-
import {fromSlateBlock} from '../internal-utils/values'
|
|
3
|
+
import {Transforms} from 'slate'
|
|
7
4
|
import {parseBlock} from '../utils/parse-blocks'
|
|
8
5
|
import type {BehaviorOperationImplementation} from './behavior.operations'
|
|
9
6
|
|
|
10
7
|
export const blockUnsetOperationImplementation: BehaviorOperationImplementation<
|
|
11
8
|
'block.unset'
|
|
12
9
|
> = ({context, operation}) => {
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
schema: context.schema,
|
|
16
|
-
value: operation.editor.value,
|
|
17
|
-
selection: {
|
|
18
|
-
anchor: {path: operation.at, offset: 0},
|
|
19
|
-
focus: {path: operation.at, offset: 0},
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
|
-
blockIndexMap: operation.editor.blockIndexMap,
|
|
23
|
-
})
|
|
10
|
+
const blockKey = operation.at[0]._key
|
|
11
|
+
const blockIndex = operation.editor.blockIndexMap.get(blockKey)
|
|
24
12
|
|
|
25
|
-
if (
|
|
26
|
-
throw new Error(
|
|
27
|
-
`Unable to convert ${JSON.stringify(operation.at)} into a Slate Range`,
|
|
28
|
-
)
|
|
13
|
+
if (blockIndex === undefined) {
|
|
14
|
+
throw new Error(`Unable to find block index for block key ${blockKey}`)
|
|
29
15
|
}
|
|
30
16
|
|
|
31
|
-
const
|
|
32
|
-
|
|
17
|
+
const block =
|
|
18
|
+
blockIndex !== undefined ? operation.editor.value.at(blockIndex) : undefined
|
|
33
19
|
|
|
34
20
|
if (!block) {
|
|
35
21
|
throw new Error(`Unable to find block at ${JSON.stringify(operation.at)}`)
|
|
36
22
|
}
|
|
37
23
|
|
|
38
|
-
|
|
39
|
-
block,
|
|
40
|
-
context.schema.block.name,
|
|
41
|
-
KEY_TO_VALUE_ELEMENT.get(operation.editor),
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
if (!parsedBlock) {
|
|
45
|
-
throw new Error(`Unable to parse block at ${JSON.stringify(operation.at)}`)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (isTextBlock(context, parsedBlock)) {
|
|
24
|
+
if (isTextBlock(context, block)) {
|
|
49
25
|
const propsToRemove = operation.props.filter((prop) => prop !== '_type')
|
|
50
26
|
|
|
51
27
|
const updatedTextBlock = parseBlock({
|
|
52
28
|
context,
|
|
53
|
-
block: omit(
|
|
29
|
+
block: omit(block, propsToRemove),
|
|
54
30
|
options: {
|
|
55
31
|
normalize: false,
|
|
56
32
|
removeUnusedMarkDefs: true,
|
|
@@ -74,7 +50,7 @@ export const blockUnsetOperationImplementation: BehaviorOperationImplementation<
|
|
|
74
50
|
}
|
|
75
51
|
}
|
|
76
52
|
|
|
77
|
-
Transforms.setNodes(operation.editor, propsToSet, {at:
|
|
53
|
+
Transforms.setNodes(operation.editor, propsToSet, {at: [blockIndex]})
|
|
78
54
|
|
|
79
55
|
return
|
|
80
56
|
}
|
|
@@ -82,7 +58,7 @@ export const blockUnsetOperationImplementation: BehaviorOperationImplementation<
|
|
|
82
58
|
const updatedBlockObject = parseBlock({
|
|
83
59
|
context,
|
|
84
60
|
block: omit(
|
|
85
|
-
|
|
61
|
+
block,
|
|
86
62
|
operation.props.filter((prop) => prop !== '_type'),
|
|
87
63
|
),
|
|
88
64
|
options: {
|
|
@@ -105,6 +81,6 @@ export const blockUnsetOperationImplementation: BehaviorOperationImplementation<
|
|
|
105
81
|
_key,
|
|
106
82
|
value: props,
|
|
107
83
|
},
|
|
108
|
-
{at:
|
|
84
|
+
{at: [blockIndex]},
|
|
109
85
|
)
|
|
110
86
|
}
|
|
@@ -1,30 +1,48 @@
|
|
|
1
1
|
import {applyAll} from '@portabletext/patches'
|
|
2
|
+
import {isTextBlock} from '@portabletext/schema'
|
|
2
3
|
import {Editor, Element, Transforms} from 'slate'
|
|
3
|
-
import {toSlateRange} from '../internal-utils/to-slate-range'
|
|
4
4
|
import type {BehaviorOperationImplementation} from './behavior.operations'
|
|
5
5
|
|
|
6
6
|
export const childUnsetOperationImplementation: BehaviorOperationImplementation<
|
|
7
7
|
'child.unset'
|
|
8
8
|
> = ({context, operation}) => {
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
9
|
+
const blockKey = operation.at[0]._key
|
|
10
|
+
const blockIndex = operation.editor.blockIndexMap.get(blockKey)
|
|
11
|
+
|
|
12
|
+
if (blockIndex === undefined) {
|
|
13
|
+
throw new Error(`Unable to find block index for block key ${blockKey}`)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const block =
|
|
17
|
+
blockIndex !== undefined ? operation.editor.value.at(blockIndex) : undefined
|
|
18
|
+
|
|
19
|
+
if (!block) {
|
|
20
|
+
throw new Error(`Unable to find block at ${JSON.stringify(operation.at)}`)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (!isTextBlock(context, block)) {
|
|
24
|
+
throw new Error(`Block ${JSON.stringify(blockKey)} is not a text block`)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const childKey = operation.at[2]._key
|
|
20
28
|
|
|
21
|
-
if (!
|
|
29
|
+
if (!childKey) {
|
|
22
30
|
throw new Error(
|
|
23
|
-
`Unable to
|
|
31
|
+
`Unable to find child key at ${JSON.stringify(operation.at)}`,
|
|
24
32
|
)
|
|
25
33
|
}
|
|
26
34
|
|
|
27
|
-
const
|
|
35
|
+
const childIndex = block.children.findIndex(
|
|
36
|
+
(child) => child._key === childKey,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
if (childIndex === -1) {
|
|
40
|
+
throw new Error(`Unable to find child at ${JSON.stringify(operation.at)}`)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const childEntry = Editor.node(operation.editor, [blockIndex, childIndex], {
|
|
44
|
+
depth: 2,
|
|
45
|
+
})
|
|
28
46
|
const child = childEntry?.[0]
|
|
29
47
|
const childPath = childEntry?.[1]
|
|
30
48
|
|