@portabletext/editor 3.0.7 → 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-es/util.slice-blocks.js +1 -8
- package/lib/_chunks-es/util.slice-blocks.js.map +1 -1
- package/lib/index.js +24 -6
- package/lib/index.js.map +1 -1
- package/package.json +8 -8
- package/src/converters/converter.portable-text.deserialize.test.ts +0 -13
- package/src/editor/plugins/createWithPortableTextMarkModel.ts +19 -0
- package/src/internal-utils/__tests__/values.test.ts +0 -2
- package/src/internal-utils/values.test.ts +0 -7
- package/src/internal-utils/values.ts +70 -26
- package/src/utils/parse-blocks.test.ts +0 -16
- package/src/utils/parse-blocks.ts +6 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@portabletext/editor",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.8",
|
|
4
4
|
"description": "Portable Text Editor made in React",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sanity",
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
"slate-dom": "^0.119.0",
|
|
74
74
|
"slate-react": "0.119.0",
|
|
75
75
|
"xstate": "^5.24.0",
|
|
76
|
-
"@portabletext/block-tools": "^4.1.
|
|
76
|
+
"@portabletext/block-tools": "^4.1.3",
|
|
77
77
|
"@portabletext/keyboard-shortcuts": "^2.1.0",
|
|
78
78
|
"@portabletext/patches": "^2.0.0",
|
|
79
79
|
"@portabletext/schema": "^2.0.0"
|
|
@@ -81,8 +81,8 @@
|
|
|
81
81
|
"devDependencies": {
|
|
82
82
|
"@sanity/diff-match-patch": "^3.2.0",
|
|
83
83
|
"@sanity/pkg-utils": "^9.0.3",
|
|
84
|
-
"@sanity/schema": "^4.
|
|
85
|
-
"@sanity/types": "^4.
|
|
84
|
+
"@sanity/schema": "^4.19.0",
|
|
85
|
+
"@sanity/types": "^4.19.0",
|
|
86
86
|
"@types/debug": "^4.1.12",
|
|
87
87
|
"@types/lodash": "^4.17.20",
|
|
88
88
|
"@types/lodash.startcase": "^4.4.9",
|
|
@@ -106,14 +106,14 @@
|
|
|
106
106
|
"vite": "^7.1.12",
|
|
107
107
|
"vitest": "^4.0.9",
|
|
108
108
|
"vitest-browser-react": "^2.0.2",
|
|
109
|
-
"@portabletext/sanity-bridge": "1.2.
|
|
109
|
+
"@portabletext/sanity-bridge": "1.2.6",
|
|
110
110
|
"@portabletext/test": "^1.0.0",
|
|
111
111
|
"racejar": "2.0.0"
|
|
112
112
|
},
|
|
113
113
|
"peerDependencies": {
|
|
114
|
-
"@portabletext/sanity-bridge": "^1.2.
|
|
115
|
-
"@sanity/schema": "^4.
|
|
116
|
-
"@sanity/types": "^4.
|
|
114
|
+
"@portabletext/sanity-bridge": "^1.2.6",
|
|
115
|
+
"@sanity/schema": "^4.19.0",
|
|
116
|
+
"@sanity/types": "^4.19.0",
|
|
117
117
|
"react": "^18.3 || ^19",
|
|
118
118
|
"rxjs": "^7.8.2"
|
|
119
119
|
},
|
|
@@ -81,7 +81,6 @@ describe(converterPortableText.deserialize, () => {
|
|
|
81
81
|
marks: [],
|
|
82
82
|
},
|
|
83
83
|
],
|
|
84
|
-
markDefs: [],
|
|
85
84
|
},
|
|
86
85
|
],
|
|
87
86
|
})
|
|
@@ -117,7 +116,6 @@ describe(converterPortableText.deserialize, () => {
|
|
|
117
116
|
marks: [],
|
|
118
117
|
},
|
|
119
118
|
],
|
|
120
|
-
markDefs: [],
|
|
121
119
|
},
|
|
122
120
|
],
|
|
123
121
|
})
|
|
@@ -263,8 +261,6 @@ describe(converterPortableText.deserialize, () => {
|
|
|
263
261
|
marks: [],
|
|
264
262
|
},
|
|
265
263
|
],
|
|
266
|
-
markDefs: [],
|
|
267
|
-
style: 'normal',
|
|
268
264
|
},
|
|
269
265
|
])
|
|
270
266
|
})
|
|
@@ -299,8 +295,6 @@ describe(converterPortableText.deserialize, () => {
|
|
|
299
295
|
marks: [],
|
|
300
296
|
},
|
|
301
297
|
],
|
|
302
|
-
markDefs: [],
|
|
303
|
-
style: 'normal',
|
|
304
298
|
},
|
|
305
299
|
])
|
|
306
300
|
})
|
|
@@ -336,8 +330,6 @@ describe(converterPortableText.deserialize, () => {
|
|
|
336
330
|
marks: [],
|
|
337
331
|
},
|
|
338
332
|
],
|
|
339
|
-
markDefs: [],
|
|
340
|
-
style: 'normal',
|
|
341
333
|
},
|
|
342
334
|
])
|
|
343
335
|
})
|
|
@@ -377,7 +369,6 @@ describe(converterPortableText.deserialize, () => {
|
|
|
377
369
|
marks: [],
|
|
378
370
|
},
|
|
379
371
|
],
|
|
380
|
-
markDefs: [],
|
|
381
372
|
style: 'h1',
|
|
382
373
|
},
|
|
383
374
|
])
|
|
@@ -415,9 +406,7 @@ describe(converterPortableText.deserialize, () => {
|
|
|
415
406
|
marks: [],
|
|
416
407
|
},
|
|
417
408
|
],
|
|
418
|
-
markDefs: [],
|
|
419
409
|
level: 1,
|
|
420
|
-
style: 'normal',
|
|
421
410
|
},
|
|
422
411
|
])
|
|
423
412
|
})
|
|
@@ -458,10 +447,8 @@ describe(converterPortableText.deserialize, () => {
|
|
|
458
447
|
marks: [],
|
|
459
448
|
},
|
|
460
449
|
],
|
|
461
|
-
markDefs: [],
|
|
462
450
|
listItem: 'bullet',
|
|
463
451
|
level: 1,
|
|
464
|
-
style: 'normal',
|
|
465
452
|
},
|
|
466
453
|
])
|
|
467
454
|
})
|
|
@@ -30,6 +30,9 @@ export function createWithPortableTextMarkModel(
|
|
|
30
30
|
const decorators = editorActor
|
|
31
31
|
.getSnapshot()
|
|
32
32
|
.context.schema.decorators.map((t) => t.name)
|
|
33
|
+
const defaultStyle = editorActor
|
|
34
|
+
.getSnapshot()
|
|
35
|
+
.context.schema.styles.at(0)?.name
|
|
33
36
|
|
|
34
37
|
// Extend Slate's default normalization. Merge spans with same set of .marks when doing merge_node operations, and clean up markDefs / marks
|
|
35
38
|
editor.normalizeNode = (nodeEntry) => {
|
|
@@ -74,6 +77,22 @@ export function createWithPortableTextMarkModel(
|
|
|
74
77
|
return
|
|
75
78
|
}
|
|
76
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Add missing .style to block nodes
|
|
82
|
+
*/
|
|
83
|
+
if (
|
|
84
|
+
defaultStyle &&
|
|
85
|
+
editor.isTextBlock(node) &&
|
|
86
|
+
typeof node.style === 'undefined'
|
|
87
|
+
) {
|
|
88
|
+
debug('Adding .style to block node')
|
|
89
|
+
|
|
90
|
+
withNormalizeNode(editor, () => {
|
|
91
|
+
Transforms.setNodes(editor, {style: defaultStyle}, {at: path})
|
|
92
|
+
})
|
|
93
|
+
return
|
|
94
|
+
}
|
|
95
|
+
|
|
77
96
|
/**
|
|
78
97
|
* Add missing .marks to span nodes
|
|
79
98
|
*/
|
|
@@ -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,
|
|
@@ -176,25 +169,76 @@ export function fromSlateBlock(
|
|
|
176
169
|
}
|
|
177
170
|
|
|
178
171
|
export function isEqualToEmptyEditor(
|
|
179
|
-
|
|
172
|
+
blocks: Array<Descendant> | Array<PortableTextBlock>,
|
|
180
173
|
schemaTypes: EditorSchema,
|
|
181
174
|
): boolean {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
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
|
|
200
244
|
}
|
|
@@ -129,8 +129,6 @@ describe(parseBlock.name, () => {
|
|
|
129
129
|
marks: [],
|
|
130
130
|
},
|
|
131
131
|
],
|
|
132
|
-
markDefs: [],
|
|
133
|
-
style: 'normal',
|
|
134
132
|
})
|
|
135
133
|
})
|
|
136
134
|
|
|
@@ -160,8 +158,6 @@ describe(parseBlock.name, () => {
|
|
|
160
158
|
marks: [],
|
|
161
159
|
},
|
|
162
160
|
],
|
|
163
|
-
markDefs: [],
|
|
164
|
-
style: 'normal',
|
|
165
161
|
})
|
|
166
162
|
})
|
|
167
163
|
|
|
@@ -271,8 +267,6 @@ describe(parseBlock.name, () => {
|
|
|
271
267
|
marks: ['em'],
|
|
272
268
|
},
|
|
273
269
|
],
|
|
274
|
-
markDefs: [],
|
|
275
|
-
style: 'normal',
|
|
276
270
|
})
|
|
277
271
|
})
|
|
278
272
|
|
|
@@ -301,9 +295,7 @@ describe(parseBlock.name, () => {
|
|
|
301
295
|
marks: [],
|
|
302
296
|
},
|
|
303
297
|
],
|
|
304
|
-
markDefs: [],
|
|
305
298
|
listItem: 'bullet',
|
|
306
|
-
style: 'normal',
|
|
307
299
|
})
|
|
308
300
|
})
|
|
309
301
|
|
|
@@ -332,8 +324,6 @@ describe(parseBlock.name, () => {
|
|
|
332
324
|
marks: [],
|
|
333
325
|
},
|
|
334
326
|
],
|
|
335
|
-
markDefs: [],
|
|
336
|
-
style: 'normal',
|
|
337
327
|
})
|
|
338
328
|
})
|
|
339
329
|
|
|
@@ -363,8 +353,6 @@ describe(parseBlock.name, () => {
|
|
|
363
353
|
marks: [],
|
|
364
354
|
},
|
|
365
355
|
],
|
|
366
|
-
markDefs: [],
|
|
367
|
-
style: 'normal',
|
|
368
356
|
})
|
|
369
357
|
})
|
|
370
358
|
|
|
@@ -398,8 +386,6 @@ describe(parseBlock.name, () => {
|
|
|
398
386
|
marks: [],
|
|
399
387
|
},
|
|
400
388
|
],
|
|
401
|
-
markDefs: [],
|
|
402
|
-
style: 'normal',
|
|
403
389
|
})
|
|
404
390
|
})
|
|
405
391
|
|
|
@@ -432,8 +418,6 @@ describe(parseBlock.name, () => {
|
|
|
432
418
|
marks: [],
|
|
433
419
|
},
|
|
434
420
|
],
|
|
435
|
-
markDefs: [],
|
|
436
|
-
style: 'normal',
|
|
437
421
|
})
|
|
438
422
|
})
|
|
439
423
|
})
|
|
@@ -249,25 +249,20 @@ export function parseTextBlock({
|
|
|
249
249
|
_type: context.schema.block.name,
|
|
250
250
|
_key,
|
|
251
251
|
children: normalizedChildren,
|
|
252
|
-
markDefs: options.removeUnusedMarkDefs
|
|
253
|
-
? markDefs.filter((markDef) => marks.includes(markDef._key))
|
|
254
|
-
: markDefs,
|
|
255
252
|
...customFields,
|
|
256
253
|
}
|
|
257
254
|
|
|
255
|
+
if (typeof block.markDefs === 'object' && block.markDefs !== null) {
|
|
256
|
+
parsedBlock.markDefs = options.removeUnusedMarkDefs
|
|
257
|
+
? markDefs.filter((markDef) => marks.includes(markDef._key))
|
|
258
|
+
: markDefs
|
|
259
|
+
}
|
|
260
|
+
|
|
258
261
|
if (
|
|
259
262
|
typeof block.style === 'string' &&
|
|
260
263
|
context.schema.styles.find((style) => style.name === block.style)
|
|
261
264
|
) {
|
|
262
265
|
parsedBlock.style = block.style
|
|
263
|
-
} else {
|
|
264
|
-
const defaultStyle = context.schema.styles.at(0)?.name
|
|
265
|
-
|
|
266
|
-
if (defaultStyle !== undefined) {
|
|
267
|
-
parsedBlock.style = defaultStyle
|
|
268
|
-
} else {
|
|
269
|
-
console.error('Expected default style')
|
|
270
|
-
}
|
|
271
266
|
}
|
|
272
267
|
|
|
273
268
|
if (
|