@portabletext/editor 3.0.0 → 3.0.1
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-es/util.slice-blocks.js +44 -19
- package/lib/_chunks-es/util.slice-blocks.js.map +1 -1
- package/lib/index.js +42 -21
- package/lib/index.js.map +1 -1
- package/lib/utils/index.d.ts +3 -1
- package/lib/utils/index.js +1 -0
- package/lib/utils/index.js.map +1 -1
- package/package.json +3 -3
- package/src/behaviors/behavior.abstract.split.ts +1 -0
- package/src/converters/converter.portable-text.ts +1 -0
- package/src/converters/converter.text-html.ts +1 -0
- package/src/converters/converter.text-plain.ts +1 -0
- package/src/editor/Editable.tsx +1 -0
- package/src/editor/plugins/create-with-event-listeners.ts +30 -2
- package/src/internal-utils/operation-to-patches.test.ts +23 -25
- package/src/internal-utils/operation-to-patches.ts +31 -22
- package/src/internal-utils/selection-text.test.ts +3 -0
- package/src/internal-utils/selection-text.ts +5 -2
- package/src/internal-utils/values.ts +23 -11
- package/src/operations/behavior.operation.block.set.ts +1 -0
- package/src/operations/behavior.operation.block.unset.ts +2 -0
- package/src/operations/behavior.operation.insert.block.ts +1 -0
- package/src/test/vitest/step-definitions.tsx +2 -0
- package/src/utils/parse-blocks.test.ts +296 -16
- package/src/utils/parse-blocks.ts +81 -22
- package/src/utils/util.merge-text-blocks.ts +5 -1
- package/src/utils/util.slice-blocks.ts +24 -10
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {compileSchema, defineSchema} from '@portabletext/schema'
|
|
2
2
|
import {createTestKeyGenerator} from '@portabletext/test'
|
|
3
3
|
import {describe, expect, test} from 'vitest'
|
|
4
|
-
import {parseBlock, parseSpan} from './parse-blocks'
|
|
4
|
+
import {parseBlock, parseInlineObject, parseSpan} from './parse-blocks'
|
|
5
5
|
|
|
6
6
|
describe(parseBlock.name, () => {
|
|
7
7
|
test('null', () => {
|
|
@@ -12,7 +12,11 @@ describe(parseBlock.name, () => {
|
|
|
12
12
|
keyGenerator: createTestKeyGenerator(),
|
|
13
13
|
schema: compileSchema(defineSchema({})),
|
|
14
14
|
},
|
|
15
|
-
options: {
|
|
15
|
+
options: {
|
|
16
|
+
normalize: false,
|
|
17
|
+
removeUnusedMarkDefs: true,
|
|
18
|
+
validateFields: true,
|
|
19
|
+
},
|
|
16
20
|
}),
|
|
17
21
|
).toBe(undefined)
|
|
18
22
|
})
|
|
@@ -25,7 +29,11 @@ describe(parseBlock.name, () => {
|
|
|
25
29
|
keyGenerator: createTestKeyGenerator(),
|
|
26
30
|
schema: compileSchema(defineSchema({})),
|
|
27
31
|
},
|
|
28
|
-
options: {
|
|
32
|
+
options: {
|
|
33
|
+
normalize: false,
|
|
34
|
+
removeUnusedMarkDefs: true,
|
|
35
|
+
validateFields: true,
|
|
36
|
+
},
|
|
29
37
|
}),
|
|
30
38
|
).toBe(undefined)
|
|
31
39
|
})
|
|
@@ -39,7 +47,11 @@ describe(parseBlock.name, () => {
|
|
|
39
47
|
keyGenerator: createTestKeyGenerator(),
|
|
40
48
|
schema: compileSchema(defineSchema({})),
|
|
41
49
|
},
|
|
42
|
-
options: {
|
|
50
|
+
options: {
|
|
51
|
+
normalize: false,
|
|
52
|
+
removeUnusedMarkDefs: true,
|
|
53
|
+
validateFields: true,
|
|
54
|
+
},
|
|
43
55
|
}),
|
|
44
56
|
).toBe(undefined)
|
|
45
57
|
})
|
|
@@ -54,7 +66,11 @@ describe(parseBlock.name, () => {
|
|
|
54
66
|
defineSchema({blockObjects: [{name: 'image'}]}),
|
|
55
67
|
),
|
|
56
68
|
},
|
|
57
|
-
options: {
|
|
69
|
+
options: {
|
|
70
|
+
normalize: false,
|
|
71
|
+
removeUnusedMarkDefs: true,
|
|
72
|
+
validateFields: true,
|
|
73
|
+
},
|
|
58
74
|
}),
|
|
59
75
|
).toBe(undefined)
|
|
60
76
|
})
|
|
@@ -69,7 +85,11 @@ describe(parseBlock.name, () => {
|
|
|
69
85
|
defineSchema({blockObjects: [{name: 'image'}]}),
|
|
70
86
|
),
|
|
71
87
|
},
|
|
72
|
-
options: {
|
|
88
|
+
options: {
|
|
89
|
+
normalize: false,
|
|
90
|
+
removeUnusedMarkDefs: true,
|
|
91
|
+
validateFields: true,
|
|
92
|
+
},
|
|
73
93
|
}),
|
|
74
94
|
).toEqual({
|
|
75
95
|
_key: 'k0',
|
|
@@ -87,7 +107,11 @@ describe(parseBlock.name, () => {
|
|
|
87
107
|
keyGenerator: createTestKeyGenerator(),
|
|
88
108
|
schema: compileSchema(defineSchema({})),
|
|
89
109
|
},
|
|
90
|
-
options: {
|
|
110
|
+
options: {
|
|
111
|
+
normalize: false,
|
|
112
|
+
removeUnusedMarkDefs: true,
|
|
113
|
+
validateFields: true,
|
|
114
|
+
},
|
|
91
115
|
}),
|
|
92
116
|
).toEqual({
|
|
93
117
|
_key: 'k0',
|
|
@@ -114,7 +138,11 @@ describe(parseBlock.name, () => {
|
|
|
114
138
|
keyGenerator: createTestKeyGenerator(),
|
|
115
139
|
schema: {...schema, block: {...schema.block, name: 'text'}},
|
|
116
140
|
},
|
|
117
|
-
options: {
|
|
141
|
+
options: {
|
|
142
|
+
normalize: false,
|
|
143
|
+
removeUnusedMarkDefs: true,
|
|
144
|
+
validateFields: true,
|
|
145
|
+
},
|
|
118
146
|
}),
|
|
119
147
|
).toEqual({
|
|
120
148
|
_key: 'k0',
|
|
@@ -149,7 +177,11 @@ describe(parseBlock.name, () => {
|
|
|
149
177
|
keyGenerator: createTestKeyGenerator(),
|
|
150
178
|
schema: compileSchema(defineSchema({})),
|
|
151
179
|
},
|
|
152
|
-
options: {
|
|
180
|
+
options: {
|
|
181
|
+
normalize: false,
|
|
182
|
+
removeUnusedMarkDefs: true,
|
|
183
|
+
validateFields: true,
|
|
184
|
+
},
|
|
153
185
|
}),
|
|
154
186
|
).toBe(undefined)
|
|
155
187
|
})
|
|
@@ -166,7 +198,7 @@ describe(parseBlock.name, () => {
|
|
|
166
198
|
42,
|
|
167
199
|
{foo: 'bar'},
|
|
168
200
|
{
|
|
169
|
-
_key: '
|
|
201
|
+
_key: 'some key',
|
|
170
202
|
text: 'foo',
|
|
171
203
|
marks: [],
|
|
172
204
|
},
|
|
@@ -177,6 +209,7 @@ describe(parseBlock.name, () => {
|
|
|
177
209
|
{_type: 'span', text: 'foo'},
|
|
178
210
|
{_type: 'span', marks: ['strong']},
|
|
179
211
|
{_type: 'span', marks: ['em']},
|
|
212
|
+
{_type: 'image', text: 'inline object or span?'},
|
|
180
213
|
],
|
|
181
214
|
},
|
|
182
215
|
context: {
|
|
@@ -188,12 +221,22 @@ describe(parseBlock.name, () => {
|
|
|
188
221
|
}),
|
|
189
222
|
),
|
|
190
223
|
},
|
|
191
|
-
options: {
|
|
224
|
+
options: {
|
|
225
|
+
normalize: false,
|
|
226
|
+
removeUnusedMarkDefs: true,
|
|
227
|
+
validateFields: true,
|
|
228
|
+
},
|
|
192
229
|
}),
|
|
193
230
|
).toEqual({
|
|
194
231
|
_key: 'k0',
|
|
195
232
|
_type: 'block',
|
|
196
233
|
children: [
|
|
234
|
+
{
|
|
235
|
+
_key: 'some key',
|
|
236
|
+
_type: 'span',
|
|
237
|
+
text: 'foo',
|
|
238
|
+
marks: [],
|
|
239
|
+
},
|
|
197
240
|
{
|
|
198
241
|
_key: 'k1',
|
|
199
242
|
_type: 'stock-ticker',
|
|
@@ -222,6 +265,12 @@ describe(parseBlock.name, () => {
|
|
|
222
265
|
text: '',
|
|
223
266
|
marks: ['em'],
|
|
224
267
|
},
|
|
268
|
+
{
|
|
269
|
+
_key: 'k6',
|
|
270
|
+
_type: 'span',
|
|
271
|
+
text: 'inline object or span?',
|
|
272
|
+
marks: [],
|
|
273
|
+
},
|
|
225
274
|
],
|
|
226
275
|
markDefs: [],
|
|
227
276
|
style: 'normal',
|
|
@@ -236,7 +285,11 @@ describe(parseBlock.name, () => {
|
|
|
236
285
|
keyGenerator: createTestKeyGenerator(),
|
|
237
286
|
schema: compileSchema(defineSchema({lists: [{name: 'bullet'}]})),
|
|
238
287
|
},
|
|
239
|
-
options: {
|
|
288
|
+
options: {
|
|
289
|
+
normalize: false,
|
|
290
|
+
removeUnusedMarkDefs: true,
|
|
291
|
+
validateFields: true,
|
|
292
|
+
},
|
|
240
293
|
}),
|
|
241
294
|
).toEqual({
|
|
242
295
|
_key: 'k0',
|
|
@@ -263,7 +316,11 @@ describe(parseBlock.name, () => {
|
|
|
263
316
|
keyGenerator: createTestKeyGenerator(),
|
|
264
317
|
schema: compileSchema(defineSchema({lists: [{name: 'bullet'}]})),
|
|
265
318
|
},
|
|
266
|
-
options: {
|
|
319
|
+
options: {
|
|
320
|
+
normalize: false,
|
|
321
|
+
removeUnusedMarkDefs: true,
|
|
322
|
+
validateFields: true,
|
|
323
|
+
},
|
|
267
324
|
}),
|
|
268
325
|
).toEqual({
|
|
269
326
|
_key: 'k0',
|
|
@@ -290,7 +347,11 @@ describe(parseBlock.name, () => {
|
|
|
290
347
|
keyGenerator: createTestKeyGenerator(),
|
|
291
348
|
schema: compileSchema(defineSchema({})),
|
|
292
349
|
},
|
|
293
|
-
options: {
|
|
350
|
+
options: {
|
|
351
|
+
normalize: false,
|
|
352
|
+
removeUnusedMarkDefs: true,
|
|
353
|
+
validateFields: true,
|
|
354
|
+
},
|
|
294
355
|
}),
|
|
295
356
|
).toEqual({
|
|
296
357
|
_type: 'block',
|
|
@@ -320,7 +381,11 @@ describe(parseBlock.name, () => {
|
|
|
320
381
|
}),
|
|
321
382
|
),
|
|
322
383
|
},
|
|
323
|
-
options: {
|
|
384
|
+
options: {
|
|
385
|
+
normalize: false,
|
|
386
|
+
removeUnusedMarkDefs: true,
|
|
387
|
+
validateFields: true,
|
|
388
|
+
},
|
|
324
389
|
}),
|
|
325
390
|
).toEqual({
|
|
326
391
|
_type: 'block',
|
|
@@ -351,7 +416,11 @@ describe(parseBlock.name, () => {
|
|
|
351
416
|
}),
|
|
352
417
|
),
|
|
353
418
|
},
|
|
354
|
-
options: {
|
|
419
|
+
options: {
|
|
420
|
+
normalize: false,
|
|
421
|
+
removeUnusedMarkDefs: true,
|
|
422
|
+
validateFields: true,
|
|
423
|
+
},
|
|
355
424
|
}),
|
|
356
425
|
).toEqual({
|
|
357
426
|
_type: 'block',
|
|
@@ -533,3 +602,214 @@ describe(parseSpan.name, () => {
|
|
|
533
602
|
})
|
|
534
603
|
})
|
|
535
604
|
})
|
|
605
|
+
|
|
606
|
+
describe(parseInlineObject.name, () => {
|
|
607
|
+
test('undefined', () => {
|
|
608
|
+
expect(
|
|
609
|
+
parseInlineObject({
|
|
610
|
+
inlineObject: undefined,
|
|
611
|
+
context: {
|
|
612
|
+
keyGenerator: createTestKeyGenerator(),
|
|
613
|
+
schema: compileSchema(
|
|
614
|
+
defineSchema({inlineObjects: [{name: 'stock-ticker'}]}),
|
|
615
|
+
),
|
|
616
|
+
},
|
|
617
|
+
options: {validateFields: true},
|
|
618
|
+
}),
|
|
619
|
+
).toBe(undefined)
|
|
620
|
+
})
|
|
621
|
+
|
|
622
|
+
test('null', () => {
|
|
623
|
+
expect(
|
|
624
|
+
parseInlineObject({
|
|
625
|
+
inlineObject: null,
|
|
626
|
+
context: {
|
|
627
|
+
keyGenerator: createTestKeyGenerator(),
|
|
628
|
+
schema: compileSchema(
|
|
629
|
+
defineSchema({inlineObjects: [{name: 'stock-ticker'}]}),
|
|
630
|
+
),
|
|
631
|
+
},
|
|
632
|
+
options: {validateFields: true},
|
|
633
|
+
}),
|
|
634
|
+
).toBe(undefined)
|
|
635
|
+
})
|
|
636
|
+
|
|
637
|
+
test('empty object', () => {
|
|
638
|
+
expect(
|
|
639
|
+
parseInlineObject({
|
|
640
|
+
inlineObject: {},
|
|
641
|
+
context: {
|
|
642
|
+
keyGenerator: createTestKeyGenerator(),
|
|
643
|
+
schema: compileSchema(
|
|
644
|
+
defineSchema({inlineObjects: [{name: 'stock-ticker'}]}),
|
|
645
|
+
),
|
|
646
|
+
},
|
|
647
|
+
options: {validateFields: true},
|
|
648
|
+
}),
|
|
649
|
+
).toBe(undefined)
|
|
650
|
+
})
|
|
651
|
+
|
|
652
|
+
test('invalid _type', () => {
|
|
653
|
+
expect(
|
|
654
|
+
parseInlineObject({
|
|
655
|
+
inlineObject: {_type: 'image'},
|
|
656
|
+
context: {
|
|
657
|
+
keyGenerator: createTestKeyGenerator(),
|
|
658
|
+
schema: compileSchema(
|
|
659
|
+
defineSchema({inlineObjects: [{name: 'stock-ticker'}]}),
|
|
660
|
+
),
|
|
661
|
+
},
|
|
662
|
+
options: {validateFields: true},
|
|
663
|
+
}),
|
|
664
|
+
).toBe(undefined)
|
|
665
|
+
})
|
|
666
|
+
|
|
667
|
+
test('only _type', () => {
|
|
668
|
+
expect(
|
|
669
|
+
parseInlineObject({
|
|
670
|
+
inlineObject: {_type: 'stock-ticker'},
|
|
671
|
+
context: {
|
|
672
|
+
keyGenerator: createTestKeyGenerator(),
|
|
673
|
+
schema: compileSchema(
|
|
674
|
+
defineSchema({inlineObjects: [{name: 'stock-ticker'}]}),
|
|
675
|
+
),
|
|
676
|
+
},
|
|
677
|
+
options: {validateFields: true},
|
|
678
|
+
}),
|
|
679
|
+
).toEqual({
|
|
680
|
+
_key: 'k0',
|
|
681
|
+
_type: 'stock-ticker',
|
|
682
|
+
})
|
|
683
|
+
})
|
|
684
|
+
|
|
685
|
+
describe('looks like text node', () => {
|
|
686
|
+
test('known inline object _type', () => {
|
|
687
|
+
expect(
|
|
688
|
+
parseInlineObject({
|
|
689
|
+
inlineObject: {_type: 'stock-ticker', text: 'foo'},
|
|
690
|
+
context: {
|
|
691
|
+
keyGenerator: createTestKeyGenerator(),
|
|
692
|
+
schema: compileSchema(
|
|
693
|
+
defineSchema({inlineObjects: [{name: 'stock-ticker'}]}),
|
|
694
|
+
),
|
|
695
|
+
},
|
|
696
|
+
options: {validateFields: true},
|
|
697
|
+
}),
|
|
698
|
+
).toEqual({_key: 'k0', _type: 'stock-ticker'})
|
|
699
|
+
})
|
|
700
|
+
|
|
701
|
+
test('unknown inline object _type', () => {
|
|
702
|
+
expect(
|
|
703
|
+
parseInlineObject({
|
|
704
|
+
inlineObject: {_type: 'image', text: 'foo'},
|
|
705
|
+
context: {
|
|
706
|
+
keyGenerator: createTestKeyGenerator(),
|
|
707
|
+
schema: compileSchema(
|
|
708
|
+
defineSchema({inlineObjects: [{name: 'stock-ticker'}]}),
|
|
709
|
+
),
|
|
710
|
+
},
|
|
711
|
+
options: {validateFields: true},
|
|
712
|
+
}),
|
|
713
|
+
).toBe(undefined)
|
|
714
|
+
})
|
|
715
|
+
})
|
|
716
|
+
|
|
717
|
+
describe('custom props', () => {
|
|
718
|
+
describe('unknown prop', () => {
|
|
719
|
+
test('validateFields: true', () => {
|
|
720
|
+
expect(
|
|
721
|
+
parseInlineObject({
|
|
722
|
+
inlineObject: {_type: 'stock-ticker', foo: 'bar'},
|
|
723
|
+
context: {
|
|
724
|
+
keyGenerator: createTestKeyGenerator(),
|
|
725
|
+
schema: compileSchema(
|
|
726
|
+
defineSchema({
|
|
727
|
+
inlineObjects: [{name: 'stock-ticker'}],
|
|
728
|
+
}),
|
|
729
|
+
),
|
|
730
|
+
},
|
|
731
|
+
options: {validateFields: true},
|
|
732
|
+
}),
|
|
733
|
+
).toEqual({
|
|
734
|
+
_key: 'k0',
|
|
735
|
+
_type: 'stock-ticker',
|
|
736
|
+
})
|
|
737
|
+
})
|
|
738
|
+
|
|
739
|
+
test('validateFields: false', () => {
|
|
740
|
+
expect(
|
|
741
|
+
parseInlineObject({
|
|
742
|
+
inlineObject: {_type: 'stock-ticker', foo: 'bar'},
|
|
743
|
+
context: {
|
|
744
|
+
keyGenerator: createTestKeyGenerator(),
|
|
745
|
+
schema: compileSchema(
|
|
746
|
+
defineSchema({
|
|
747
|
+
inlineObjects: [{name: 'stock-ticker'}],
|
|
748
|
+
}),
|
|
749
|
+
),
|
|
750
|
+
},
|
|
751
|
+
options: {validateFields: false},
|
|
752
|
+
}),
|
|
753
|
+
).toEqual({
|
|
754
|
+
_key: 'k0',
|
|
755
|
+
_type: 'stock-ticker',
|
|
756
|
+
foo: 'bar',
|
|
757
|
+
})
|
|
758
|
+
})
|
|
759
|
+
})
|
|
760
|
+
|
|
761
|
+
describe('known prop', () => {
|
|
762
|
+
test('validateFields: true', () => {
|
|
763
|
+
expect(
|
|
764
|
+
parseInlineObject({
|
|
765
|
+
inlineObject: {_type: 'stock-ticker', foo: 'bar'},
|
|
766
|
+
context: {
|
|
767
|
+
keyGenerator: createTestKeyGenerator(),
|
|
768
|
+
schema: compileSchema(
|
|
769
|
+
defineSchema({
|
|
770
|
+
inlineObjects: [
|
|
771
|
+
{
|
|
772
|
+
name: 'stock-ticker',
|
|
773
|
+
fields: [{name: 'foo', type: 'string'}],
|
|
774
|
+
},
|
|
775
|
+
],
|
|
776
|
+
}),
|
|
777
|
+
),
|
|
778
|
+
},
|
|
779
|
+
options: {validateFields: true},
|
|
780
|
+
}),
|
|
781
|
+
).toEqual({
|
|
782
|
+
_key: 'k0',
|
|
783
|
+
_type: 'stock-ticker',
|
|
784
|
+
foo: 'bar',
|
|
785
|
+
})
|
|
786
|
+
})
|
|
787
|
+
})
|
|
788
|
+
|
|
789
|
+
test('validateFields: false', () => {
|
|
790
|
+
expect(
|
|
791
|
+
parseInlineObject({
|
|
792
|
+
inlineObject: {_type: 'stock-ticker', foo: 'bar'},
|
|
793
|
+
context: {
|
|
794
|
+
keyGenerator: createTestKeyGenerator(),
|
|
795
|
+
schema: compileSchema(
|
|
796
|
+
defineSchema({
|
|
797
|
+
inlineObjects: [
|
|
798
|
+
{
|
|
799
|
+
name: 'stock-ticker',
|
|
800
|
+
fields: [{name: 'foo', type: 'string'}],
|
|
801
|
+
},
|
|
802
|
+
],
|
|
803
|
+
}),
|
|
804
|
+
),
|
|
805
|
+
},
|
|
806
|
+
options: {validateFields: false},
|
|
807
|
+
}),
|
|
808
|
+
).toEqual({
|
|
809
|
+
_key: 'k0',
|
|
810
|
+
_type: 'stock-ticker',
|
|
811
|
+
foo: 'bar',
|
|
812
|
+
})
|
|
813
|
+
})
|
|
814
|
+
})
|
|
815
|
+
})
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {isTextBlock} from '@portabletext/schema'
|
|
1
|
+
import {isSpan, isTextBlock} from '@portabletext/schema'
|
|
2
2
|
import type {
|
|
3
3
|
PortableTextBlock,
|
|
4
4
|
PortableTextListBlock,
|
|
@@ -9,7 +9,7 @@ import type {
|
|
|
9
9
|
} from '@sanity/types'
|
|
10
10
|
import type {EditorSchema} from '../editor/editor-schema'
|
|
11
11
|
import type {EditorContext} from '../editor/editor-snapshot'
|
|
12
|
-
import {isTypedObject} from './asserters'
|
|
12
|
+
import {isRecord, isTypedObject} from './asserters'
|
|
13
13
|
|
|
14
14
|
export function parseBlocks({
|
|
15
15
|
context,
|
|
@@ -19,6 +19,7 @@ export function parseBlocks({
|
|
|
19
19
|
context: Pick<EditorContext, 'keyGenerator' | 'schema'>
|
|
20
20
|
blocks: unknown
|
|
21
21
|
options: {
|
|
22
|
+
normalize: boolean
|
|
22
23
|
removeUnusedMarkDefs: boolean
|
|
23
24
|
validateFields: boolean
|
|
24
25
|
}
|
|
@@ -42,6 +43,7 @@ export function parseBlock({
|
|
|
42
43
|
context: Pick<EditorContext, 'keyGenerator' | 'schema'>
|
|
43
44
|
block: unknown
|
|
44
45
|
options: {
|
|
46
|
+
normalize: boolean
|
|
45
47
|
removeUnusedMarkDefs: boolean
|
|
46
48
|
validateFields: boolean
|
|
47
49
|
}
|
|
@@ -102,6 +104,7 @@ export function parseTextBlock({
|
|
|
102
104
|
block: unknown
|
|
103
105
|
context: Pick<EditorContext, 'keyGenerator' | 'schema'>
|
|
104
106
|
options: {
|
|
107
|
+
normalize: boolean
|
|
105
108
|
removeUnusedMarkDefs: boolean
|
|
106
109
|
validateFields: boolean
|
|
107
110
|
}
|
|
@@ -186,29 +189,70 @@ export function parseTextBlock({
|
|
|
186
189
|
? block.children
|
|
187
190
|
: []
|
|
188
191
|
|
|
189
|
-
const
|
|
192
|
+
const parsedChildren = unparsedChildren
|
|
190
193
|
.map(
|
|
191
194
|
(child) =>
|
|
192
195
|
parseSpan({span: child, context, markDefKeyMap, options}) ??
|
|
193
196
|
parseInlineObject({inlineObject: child, context, options}),
|
|
194
197
|
)
|
|
195
198
|
.filter((child) => child !== undefined)
|
|
196
|
-
const marks =
|
|
199
|
+
const marks = parsedChildren.flatMap((child) => child.marks ?? [])
|
|
200
|
+
|
|
201
|
+
const children =
|
|
202
|
+
parsedChildren.length > 0
|
|
203
|
+
? parsedChildren
|
|
204
|
+
: [
|
|
205
|
+
{
|
|
206
|
+
_key: context.keyGenerator(),
|
|
207
|
+
_type: context.schema.span.name,
|
|
208
|
+
text: '',
|
|
209
|
+
marks: [],
|
|
210
|
+
},
|
|
211
|
+
]
|
|
212
|
+
|
|
213
|
+
const normalizedChildren = options.normalize
|
|
214
|
+
? // Ensure that inline objects re surrounded by spans
|
|
215
|
+
children.reduce<Array<PortableTextObject | PortableTextSpan>>(
|
|
216
|
+
(normalizedChildren, child, index) => {
|
|
217
|
+
if (isSpan(context, child)) {
|
|
218
|
+
return [...normalizedChildren, child]
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const previousChild = normalizedChildren.at(-1)
|
|
222
|
+
|
|
223
|
+
if (!previousChild || !isSpan(context, previousChild)) {
|
|
224
|
+
return [
|
|
225
|
+
...normalizedChildren,
|
|
226
|
+
{
|
|
227
|
+
_key: context.keyGenerator(),
|
|
228
|
+
_type: context.schema.span.name,
|
|
229
|
+
text: '',
|
|
230
|
+
marks: [],
|
|
231
|
+
},
|
|
232
|
+
child,
|
|
233
|
+
...(index === children.length - 1
|
|
234
|
+
? [
|
|
235
|
+
{
|
|
236
|
+
_key: context.keyGenerator(),
|
|
237
|
+
_type: context.schema.span.name,
|
|
238
|
+
text: '',
|
|
239
|
+
marks: [],
|
|
240
|
+
},
|
|
241
|
+
]
|
|
242
|
+
: []),
|
|
243
|
+
]
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return [...normalizedChildren, child]
|
|
247
|
+
},
|
|
248
|
+
[],
|
|
249
|
+
)
|
|
250
|
+
: children
|
|
197
251
|
|
|
198
252
|
const parsedBlock: PortableTextTextBlock = {
|
|
199
253
|
_type: context.schema.block.name,
|
|
200
254
|
_key,
|
|
201
|
-
children:
|
|
202
|
-
children.length > 0
|
|
203
|
-
? children
|
|
204
|
-
: [
|
|
205
|
-
{
|
|
206
|
-
_key: context.keyGenerator(),
|
|
207
|
-
_type: context.schema.span.name,
|
|
208
|
-
text: '',
|
|
209
|
-
marks: [],
|
|
210
|
-
},
|
|
211
|
-
],
|
|
255
|
+
children: normalizedChildren,
|
|
212
256
|
markDefs: options.removeUnusedMarkDefs
|
|
213
257
|
? markDefs.filter((markDef) => marks.includes(markDef._key))
|
|
214
258
|
: markDefs,
|
|
@@ -255,7 +299,7 @@ export function parseSpan({
|
|
|
255
299
|
markDefKeyMap: Map<string, string>
|
|
256
300
|
options: {validateFields: boolean}
|
|
257
301
|
}): PortableTextSpan | undefined {
|
|
258
|
-
if (!
|
|
302
|
+
if (!isRecord(span)) {
|
|
259
303
|
return undefined
|
|
260
304
|
}
|
|
261
305
|
|
|
@@ -272,11 +316,6 @@ export function parseSpan({
|
|
|
272
316
|
}
|
|
273
317
|
}
|
|
274
318
|
|
|
275
|
-
// In reality, the span schema name is always 'span', but we only the check here anyway
|
|
276
|
-
if (span._type !== context.schema.span.name || span._type !== 'span') {
|
|
277
|
-
return undefined
|
|
278
|
-
}
|
|
279
|
-
|
|
280
319
|
const unparsedMarks: Array<unknown> = Array.isArray(span.marks)
|
|
281
320
|
? span.marks
|
|
282
321
|
: []
|
|
@@ -300,8 +339,28 @@ export function parseSpan({
|
|
|
300
339
|
return []
|
|
301
340
|
})
|
|
302
341
|
|
|
342
|
+
if (span._type !== context.schema.span.name) {
|
|
343
|
+
if (
|
|
344
|
+
!context.schema.inlineObjects.some(
|
|
345
|
+
(inlineObject) => inlineObject.name === span._type,
|
|
346
|
+
) &&
|
|
347
|
+
typeof span.text === 'string'
|
|
348
|
+
) {
|
|
349
|
+
return {
|
|
350
|
+
_type: context.schema.span.name as 'span',
|
|
351
|
+
_key:
|
|
352
|
+
typeof span._key === 'string' ? span._key : context.keyGenerator(),
|
|
353
|
+
text: span.text,
|
|
354
|
+
marks,
|
|
355
|
+
...(options.validateFields ? {} : customFields),
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
return undefined
|
|
360
|
+
}
|
|
361
|
+
|
|
303
362
|
return {
|
|
304
|
-
_type: 'span',
|
|
363
|
+
_type: context.schema.span.name as 'span',
|
|
305
364
|
_key: typeof span._key === 'string' ? span._key : context.keyGenerator(),
|
|
306
365
|
text: typeof span.text === 'string' ? span.text : '',
|
|
307
366
|
marks,
|
|
@@ -18,7 +18,11 @@ export function mergeTextBlocks({
|
|
|
18
18
|
const parsedIncomingBlock = parseBlock({
|
|
19
19
|
context,
|
|
20
20
|
block: incomingBlock,
|
|
21
|
-
options: {
|
|
21
|
+
options: {
|
|
22
|
+
normalize: false,
|
|
23
|
+
removeUnusedMarkDefs: true,
|
|
24
|
+
validateFields: false,
|
|
25
|
+
},
|
|
22
26
|
})
|
|
23
27
|
|
|
24
28
|
if (!parsedIncomingBlock || !isTextBlock(context, parsedIncomingBlock)) {
|
|
@@ -17,7 +17,9 @@ export function sliceBlocks({
|
|
|
17
17
|
context,
|
|
18
18
|
blocks,
|
|
19
19
|
}: {
|
|
20
|
-
context: Pick<EditorContext, 'schema' | 'selection'>
|
|
20
|
+
context: Pick<EditorContext, 'schema' | 'selection'> & {
|
|
21
|
+
keyGenerator?: () => string
|
|
22
|
+
}
|
|
21
23
|
blocks: Array<PortableTextBlock>
|
|
22
24
|
}): Array<PortableTextBlock> {
|
|
23
25
|
const slice: Array<PortableTextBlock> = []
|
|
@@ -167,11 +169,15 @@ export function sliceBlocks({
|
|
|
167
169
|
middleBlocks.push(
|
|
168
170
|
parseBlock({
|
|
169
171
|
context: {
|
|
170
|
-
|
|
171
|
-
keyGenerator: defaultKeyGenerator,
|
|
172
|
+
schema: context.schema,
|
|
173
|
+
keyGenerator: context.keyGenerator ?? defaultKeyGenerator,
|
|
172
174
|
},
|
|
173
175
|
block,
|
|
174
|
-
options: {
|
|
176
|
+
options: {
|
|
177
|
+
normalize: false,
|
|
178
|
+
removeUnusedMarkDefs: true,
|
|
179
|
+
validateFields: false,
|
|
180
|
+
},
|
|
175
181
|
}) ?? block,
|
|
176
182
|
)
|
|
177
183
|
}
|
|
@@ -180,22 +186,30 @@ export function sliceBlocks({
|
|
|
180
186
|
const parsedStartBlock = startBlock
|
|
181
187
|
? parseBlock({
|
|
182
188
|
context: {
|
|
183
|
-
|
|
184
|
-
keyGenerator: defaultKeyGenerator,
|
|
189
|
+
schema: context.schema,
|
|
190
|
+
keyGenerator: context.keyGenerator ?? defaultKeyGenerator,
|
|
185
191
|
},
|
|
186
192
|
block: startBlock,
|
|
187
|
-
options: {
|
|
193
|
+
options: {
|
|
194
|
+
normalize: false,
|
|
195
|
+
removeUnusedMarkDefs: true,
|
|
196
|
+
validateFields: false,
|
|
197
|
+
},
|
|
188
198
|
})
|
|
189
199
|
: undefined
|
|
190
200
|
|
|
191
201
|
const parsedEndBlock = endBlock
|
|
192
202
|
? parseBlock({
|
|
193
203
|
context: {
|
|
194
|
-
|
|
195
|
-
keyGenerator: defaultKeyGenerator,
|
|
204
|
+
schema: context.schema,
|
|
205
|
+
keyGenerator: context.keyGenerator ?? defaultKeyGenerator,
|
|
196
206
|
},
|
|
197
207
|
block: endBlock,
|
|
198
|
-
options: {
|
|
208
|
+
options: {
|
|
209
|
+
normalize: false,
|
|
210
|
+
removeUnusedMarkDefs: true,
|
|
211
|
+
validateFields: false,
|
|
212
|
+
},
|
|
199
213
|
})
|
|
200
214
|
: undefined
|
|
201
215
|
|