@portabletext/editor 1.5.1 → 1.5.3
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 +1 -1
- package/lib/index.d.mts +74 -18
- package/lib/index.d.ts +74 -18
- package/lib/index.esm.js +178 -140
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +178 -140
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +178 -140
- package/lib/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/editor/behavior/behavior.core.block-objects.ts +4 -4
- package/src/editor/behavior/behavior.core.lists.ts +1 -1
- package/src/editor/behavior/behavior.core.ts +17 -2
- package/src/editor/behavior/behavior.markdown.ts +5 -0
- package/src/editor/define-schema.ts +22 -2
- package/src/editor/editor-machine.ts +2 -4
- package/src/editor/plugins/createWithPortableTextMarkModel.ts +18 -0
- package/src/index.ts +2 -1
package/lib/index.mjs
CHANGED
|
@@ -140,6 +140,148 @@ function getNextBlock(context) {
|
|
|
140
140
|
function isEmptyTextBlock(block) {
|
|
141
141
|
return block.children.length === 1 && block.children[0].text === "";
|
|
142
142
|
}
|
|
143
|
+
const breakingBlockObject = {
|
|
144
|
+
on: "insert break",
|
|
145
|
+
guard: ({
|
|
146
|
+
context
|
|
147
|
+
}) => !!getFocusBlockObject(context),
|
|
148
|
+
actions: [() => [{
|
|
149
|
+
type: "insert text block",
|
|
150
|
+
decorators: []
|
|
151
|
+
}]]
|
|
152
|
+
}, deletingEmptyTextBlockAfterBlockObject = {
|
|
153
|
+
on: "delete backward",
|
|
154
|
+
guard: ({
|
|
155
|
+
context
|
|
156
|
+
}) => {
|
|
157
|
+
const focusTextBlock = getFocusTextBlock(context), selectionCollapsed = selectionIsCollapsed(context), previousBlock = getPreviousBlock(context);
|
|
158
|
+
return !focusTextBlock || !selectionCollapsed || !previousBlock ? !1 : isEmptyTextBlock(focusTextBlock.node) && !isPortableTextTextBlock(previousBlock.node) ? {
|
|
159
|
+
focusTextBlock,
|
|
160
|
+
previousBlock
|
|
161
|
+
} : !1;
|
|
162
|
+
},
|
|
163
|
+
actions: [(_, {
|
|
164
|
+
focusTextBlock,
|
|
165
|
+
previousBlock
|
|
166
|
+
}) => [{
|
|
167
|
+
type: "delete",
|
|
168
|
+
selection: {
|
|
169
|
+
anchor: {
|
|
170
|
+
path: focusTextBlock.path,
|
|
171
|
+
offset: 0
|
|
172
|
+
},
|
|
173
|
+
focus: {
|
|
174
|
+
path: focusTextBlock.path,
|
|
175
|
+
offset: 0
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}, {
|
|
179
|
+
type: "select",
|
|
180
|
+
selection: {
|
|
181
|
+
anchor: {
|
|
182
|
+
path: previousBlock.path,
|
|
183
|
+
offset: 0
|
|
184
|
+
},
|
|
185
|
+
focus: {
|
|
186
|
+
path: previousBlock.path,
|
|
187
|
+
offset: 0
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}]]
|
|
191
|
+
}, deletingEmptyTextBlockBeforeBlockObject = {
|
|
192
|
+
on: "delete forward",
|
|
193
|
+
guard: ({
|
|
194
|
+
context
|
|
195
|
+
}) => {
|
|
196
|
+
const focusTextBlock = getFocusTextBlock(context), selectionCollapsed = selectionIsCollapsed(context), nextBlock = getNextBlock(context);
|
|
197
|
+
return !focusTextBlock || !selectionCollapsed || !nextBlock ? !1 : isEmptyTextBlock(focusTextBlock.node) && !isPortableTextTextBlock(nextBlock.node) ? {
|
|
198
|
+
focusTextBlock,
|
|
199
|
+
nextBlock
|
|
200
|
+
} : !1;
|
|
201
|
+
},
|
|
202
|
+
actions: [(_, {
|
|
203
|
+
focusTextBlock,
|
|
204
|
+
nextBlock
|
|
205
|
+
}) => [{
|
|
206
|
+
type: "delete",
|
|
207
|
+
selection: {
|
|
208
|
+
anchor: {
|
|
209
|
+
path: focusTextBlock.path,
|
|
210
|
+
offset: 0
|
|
211
|
+
},
|
|
212
|
+
focus: {
|
|
213
|
+
path: focusTextBlock.path,
|
|
214
|
+
offset: 0
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}, {
|
|
218
|
+
type: "select",
|
|
219
|
+
selection: {
|
|
220
|
+
anchor: {
|
|
221
|
+
path: nextBlock.path,
|
|
222
|
+
offset: 0
|
|
223
|
+
},
|
|
224
|
+
focus: {
|
|
225
|
+
path: nextBlock.path,
|
|
226
|
+
offset: 0
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}]]
|
|
230
|
+
}, coreBlockObjectBehaviors = {
|
|
231
|
+
breakingBlockObject,
|
|
232
|
+
deletingEmptyTextBlockAfterBlockObject,
|
|
233
|
+
deletingEmptyTextBlockBeforeBlockObject
|
|
234
|
+
}, clearListOnBackspace = {
|
|
235
|
+
on: "delete backward",
|
|
236
|
+
guard: ({
|
|
237
|
+
context
|
|
238
|
+
}) => {
|
|
239
|
+
const selectionCollapsed = selectionIsCollapsed(context), focusTextBlock = getFocusTextBlock(context), focusSpan = getFocusSpan(context);
|
|
240
|
+
return !selectionCollapsed || !focusTextBlock || !focusSpan ? !1 : focusTextBlock.node.children[0]._key === focusSpan.node._key && context.selection.focus.offset === 0 && focusTextBlock.node.level === 1 ? {
|
|
241
|
+
focusTextBlock
|
|
242
|
+
} : !1;
|
|
243
|
+
},
|
|
244
|
+
actions: [(_, {
|
|
245
|
+
focusTextBlock
|
|
246
|
+
}) => [{
|
|
247
|
+
type: "unset block",
|
|
248
|
+
props: ["listItem", "level"],
|
|
249
|
+
paths: [focusTextBlock.path]
|
|
250
|
+
}]]
|
|
251
|
+
}, unindentListOnBackspace = {
|
|
252
|
+
on: "delete backward",
|
|
253
|
+
guard: ({
|
|
254
|
+
context
|
|
255
|
+
}) => {
|
|
256
|
+
const selectionCollapsed = selectionIsCollapsed(context), focusTextBlock = getFocusTextBlock(context), focusSpan = getFocusSpan(context);
|
|
257
|
+
return !selectionCollapsed || !focusTextBlock || !focusSpan ? !1 : focusTextBlock.node.children[0]._key === focusSpan.node._key && context.selection.focus.offset === 0 && focusTextBlock.node.level !== void 0 && focusTextBlock.node.level > 1 ? {
|
|
258
|
+
focusTextBlock,
|
|
259
|
+
level: focusTextBlock.node.level - 1
|
|
260
|
+
} : !1;
|
|
261
|
+
},
|
|
262
|
+
actions: [(_, {
|
|
263
|
+
focusTextBlock,
|
|
264
|
+
level
|
|
265
|
+
}) => [{
|
|
266
|
+
type: "set block",
|
|
267
|
+
level,
|
|
268
|
+
paths: [focusTextBlock.path]
|
|
269
|
+
}]]
|
|
270
|
+
}, coreListBehaviors = {
|
|
271
|
+
clearListOnBackspace,
|
|
272
|
+
unindentListOnBackspace
|
|
273
|
+
}, softReturn = {
|
|
274
|
+
on: "insert soft break",
|
|
275
|
+
actions: [() => [{
|
|
276
|
+
type: "insert text",
|
|
277
|
+
text: `
|
|
278
|
+
`
|
|
279
|
+
}]]
|
|
280
|
+
}, coreBehaviors = [softReturn, coreBlockObjectBehaviors.breakingBlockObject, coreBlockObjectBehaviors.deletingEmptyTextBlockAfterBlockObject, coreBlockObjectBehaviors.deletingEmptyTextBlockBeforeBlockObject, coreListBehaviors.clearListOnBackspace, coreListBehaviors.unindentListOnBackspace], coreBehavior = {
|
|
281
|
+
softReturn,
|
|
282
|
+
blockObjects: coreBlockObjectBehaviors,
|
|
283
|
+
lists: coreListBehaviors
|
|
284
|
+
};
|
|
143
285
|
function createMarkdownBehaviors(config) {
|
|
144
286
|
const automaticStyleOnSpace = {
|
|
145
287
|
on: "insert text",
|
|
@@ -171,6 +313,10 @@ function createMarkdownBehaviors(config) {
|
|
|
171
313
|
focusSpan,
|
|
172
314
|
style
|
|
173
315
|
}) => [{
|
|
316
|
+
type: "unset block",
|
|
317
|
+
props: ["listItem", "level"],
|
|
318
|
+
paths: [focusTextBlock.path]
|
|
319
|
+
}, {
|
|
174
320
|
type: "set block",
|
|
175
321
|
style,
|
|
176
322
|
paths: [focusTextBlock.path]
|
|
@@ -324,7 +470,9 @@ function defineSchema(definition) {
|
|
|
324
470
|
function compileSchemaDefinition(definition) {
|
|
325
471
|
const blockObjects = definition?.blockObjects?.map((blockObject) => defineType({
|
|
326
472
|
type: "object",
|
|
327
|
-
|
|
473
|
+
// Very naive way to work around `SanitySchema.compile` adding default
|
|
474
|
+
// fields to objects with the name `image`
|
|
475
|
+
name: blockObject.name === "image" ? "tmp-image" : blockObject.name,
|
|
328
476
|
title: blockObject.title,
|
|
329
477
|
icon: blockObject.icon,
|
|
330
478
|
fields: []
|
|
@@ -371,8 +519,18 @@ function compileSchemaDefinition(definition) {
|
|
|
371
519
|
}]
|
|
372
520
|
}), schema = Schema.compile({
|
|
373
521
|
types: [portableTextSchema, ...blockObjects, ...inlineObjects]
|
|
374
|
-
}).get("portable-text");
|
|
375
|
-
return
|
|
522
|
+
}).get("portable-text"), pteSchema = getPortableTextMemberSchemaTypes(schema);
|
|
523
|
+
return {
|
|
524
|
+
...pteSchema,
|
|
525
|
+
blockObjects: pteSchema.blockObjects.map((blockObject) => blockObject.name === "tmp-image" ? {
|
|
526
|
+
...blockObject,
|
|
527
|
+
name: "image",
|
|
528
|
+
type: {
|
|
529
|
+
...blockObject.type,
|
|
530
|
+
name: "image"
|
|
531
|
+
}
|
|
532
|
+
} : blockObject)
|
|
533
|
+
};
|
|
376
534
|
}
|
|
377
535
|
const rootName = "sanity-pte:";
|
|
378
536
|
debug$m(rootName);
|
|
@@ -3547,22 +3705,30 @@ function createWithPortableTextMarkModel(editorActor, types) {
|
|
|
3547
3705
|
editor,
|
|
3548
3706
|
blockPath,
|
|
3549
3707
|
spanPath: [op.path[0], op.path[1] - 1]
|
|
3550
|
-
}), nextSpanAnnotations = nextSpan ? nextSpan.marks?.filter((mark) => !decorators.includes(mark)) : [], annotationsEnding = previousSpanAnnotations?.filter((annotation) => !nextSpanAnnotations?.includes(annotation)) ?? [];
|
|
3551
|
-
if (
|
|
3708
|
+
}), nextSpanAnnotations = nextSpan ? nextSpan.marks?.filter((mark) => !decorators.includes(mark)) : [], annotationsEnding = previousSpanAnnotations?.filter((annotation) => !nextSpanAnnotations?.includes(annotation)) ?? [], atTheEndOfAnnotation = annotationsEnding.length > 0;
|
|
3709
|
+
if (atTheEndOfAnnotation && isPortableTextSpan(op.node) && op.node.marks?.some((mark) => annotationsEnding.includes(mark))) {
|
|
3552
3710
|
Transforms.insertNodes(editor, {
|
|
3553
3711
|
...op.node,
|
|
3554
3712
|
marks: op.node.marks?.filter((mark) => !annotationsEnding.includes(mark)) ?? []
|
|
3555
3713
|
});
|
|
3556
3714
|
return;
|
|
3557
3715
|
}
|
|
3558
|
-
const annotationsStarting = nextSpanAnnotations?.filter((annotation) => !previousSpanAnnotations?.includes(annotation)) ?? [];
|
|
3559
|
-
if (
|
|
3716
|
+
const annotationsStarting = nextSpanAnnotations?.filter((annotation) => !previousSpanAnnotations?.includes(annotation)) ?? [], atTheStartOfAnnotation = annotationsStarting.length > 0;
|
|
3717
|
+
if (atTheStartOfAnnotation && isPortableTextSpan(op.node) && op.node.marks?.some((mark) => annotationsStarting.includes(mark))) {
|
|
3560
3718
|
Transforms.insertNodes(editor, {
|
|
3561
3719
|
...op.node,
|
|
3562
3720
|
marks: op.node.marks?.filter((mark) => !annotationsStarting.includes(mark)) ?? []
|
|
3563
3721
|
});
|
|
3564
3722
|
return;
|
|
3565
3723
|
}
|
|
3724
|
+
const nextSpanDecorators = nextSpan?.marks?.filter((mark) => decorators.includes(mark)) ?? [];
|
|
3725
|
+
if (nextSpanDecorators.length > 0 && atTheEndOfAnnotation && !atTheStartOfAnnotation && isPortableTextSpan(op.node) && op.node.marks?.length === 0) {
|
|
3726
|
+
Transforms.insertNodes(editor, {
|
|
3727
|
+
...op.node,
|
|
3728
|
+
marks: nextSpanDecorators
|
|
3729
|
+
});
|
|
3730
|
+
return;
|
|
3731
|
+
}
|
|
3566
3732
|
}
|
|
3567
3733
|
}
|
|
3568
3734
|
if (op.type === "insert_text") {
|
|
@@ -5339,137 +5505,7 @@ function performDefaultAction({
|
|
|
5339
5505
|
});
|
|
5340
5506
|
}
|
|
5341
5507
|
}
|
|
5342
|
-
const
|
|
5343
|
-
on: "insert break",
|
|
5344
|
-
guard: ({
|
|
5345
|
-
context
|
|
5346
|
-
}) => !!getFocusBlockObject(context),
|
|
5347
|
-
actions: [() => [{
|
|
5348
|
-
type: "insert text block",
|
|
5349
|
-
decorators: []
|
|
5350
|
-
}]]
|
|
5351
|
-
}, deletingEmptyTextBlockAfterBlockObject = {
|
|
5352
|
-
on: "delete backward",
|
|
5353
|
-
guard: ({
|
|
5354
|
-
context
|
|
5355
|
-
}) => {
|
|
5356
|
-
const focusTextBlock = getFocusTextBlock(context), selectionCollapsed = selectionIsCollapsed(context), previousBlock = getPreviousBlock(context);
|
|
5357
|
-
return !focusTextBlock || !selectionCollapsed || !previousBlock ? !1 : isEmptyTextBlock(focusTextBlock.node) && !isPortableTextTextBlock(previousBlock.node) ? {
|
|
5358
|
-
focusTextBlock,
|
|
5359
|
-
previousBlock
|
|
5360
|
-
} : !1;
|
|
5361
|
-
},
|
|
5362
|
-
actions: [(_, {
|
|
5363
|
-
focusTextBlock,
|
|
5364
|
-
previousBlock
|
|
5365
|
-
}) => [{
|
|
5366
|
-
type: "delete",
|
|
5367
|
-
selection: {
|
|
5368
|
-
anchor: {
|
|
5369
|
-
path: focusTextBlock.path,
|
|
5370
|
-
offset: 0
|
|
5371
|
-
},
|
|
5372
|
-
focus: {
|
|
5373
|
-
path: focusTextBlock.path,
|
|
5374
|
-
offset: 0
|
|
5375
|
-
}
|
|
5376
|
-
}
|
|
5377
|
-
}, {
|
|
5378
|
-
type: "select",
|
|
5379
|
-
selection: {
|
|
5380
|
-
anchor: {
|
|
5381
|
-
path: previousBlock.path,
|
|
5382
|
-
offset: 0
|
|
5383
|
-
},
|
|
5384
|
-
focus: {
|
|
5385
|
-
path: previousBlock.path,
|
|
5386
|
-
offset: 0
|
|
5387
|
-
}
|
|
5388
|
-
}
|
|
5389
|
-
}]]
|
|
5390
|
-
}, deletingEmptyTextBlockBeforeBlockObject = {
|
|
5391
|
-
on: "delete forward",
|
|
5392
|
-
guard: ({
|
|
5393
|
-
context
|
|
5394
|
-
}) => {
|
|
5395
|
-
const focusTextBlock = getFocusTextBlock(context), selectionCollapsed = selectionIsCollapsed(context), nextBlock = getNextBlock(context);
|
|
5396
|
-
return !focusTextBlock || !selectionCollapsed || !nextBlock ? !1 : isEmptyTextBlock(focusTextBlock.node) && !isPortableTextTextBlock(nextBlock.node) ? {
|
|
5397
|
-
focusTextBlock,
|
|
5398
|
-
nextBlock
|
|
5399
|
-
} : !1;
|
|
5400
|
-
},
|
|
5401
|
-
actions: [(_, {
|
|
5402
|
-
focusTextBlock,
|
|
5403
|
-
nextBlock
|
|
5404
|
-
}) => [{
|
|
5405
|
-
type: "delete",
|
|
5406
|
-
selection: {
|
|
5407
|
-
anchor: {
|
|
5408
|
-
path: focusTextBlock.path,
|
|
5409
|
-
offset: 0
|
|
5410
|
-
},
|
|
5411
|
-
focus: {
|
|
5412
|
-
path: focusTextBlock.path,
|
|
5413
|
-
offset: 0
|
|
5414
|
-
}
|
|
5415
|
-
}
|
|
5416
|
-
}, {
|
|
5417
|
-
type: "select",
|
|
5418
|
-
selection: {
|
|
5419
|
-
anchor: {
|
|
5420
|
-
path: nextBlock.path,
|
|
5421
|
-
offset: 0
|
|
5422
|
-
},
|
|
5423
|
-
focus: {
|
|
5424
|
-
path: nextBlock.path,
|
|
5425
|
-
offset: 0
|
|
5426
|
-
}
|
|
5427
|
-
}
|
|
5428
|
-
}]]
|
|
5429
|
-
}, coreBlockObjectBehaviors = [breakingVoidBlock, deletingEmptyTextBlockAfterBlockObject, deletingEmptyTextBlockBeforeBlockObject], clearListOnBackspace = {
|
|
5430
|
-
on: "delete backward",
|
|
5431
|
-
guard: ({
|
|
5432
|
-
context
|
|
5433
|
-
}) => {
|
|
5434
|
-
const selectionCollapsed = selectionIsCollapsed(context), focusTextBlock = getFocusTextBlock(context), focusSpan = getFocusSpan(context);
|
|
5435
|
-
return !selectionCollapsed || !focusTextBlock || !focusSpan ? !1 : focusTextBlock.node.children[0]._key === focusSpan.node._key && context.selection.focus.offset === 0 && focusTextBlock.node.level === 1 ? {
|
|
5436
|
-
focusTextBlock
|
|
5437
|
-
} : !1;
|
|
5438
|
-
},
|
|
5439
|
-
actions: [(_, {
|
|
5440
|
-
focusTextBlock
|
|
5441
|
-
}) => [{
|
|
5442
|
-
type: "unset block",
|
|
5443
|
-
props: ["listItem", "level"],
|
|
5444
|
-
paths: [focusTextBlock.path]
|
|
5445
|
-
}]]
|
|
5446
|
-
}, unindentListOnBackspace = {
|
|
5447
|
-
on: "delete backward",
|
|
5448
|
-
guard: ({
|
|
5449
|
-
context
|
|
5450
|
-
}) => {
|
|
5451
|
-
const selectionCollapsed = selectionIsCollapsed(context), focusTextBlock = getFocusTextBlock(context), focusSpan = getFocusSpan(context);
|
|
5452
|
-
return !selectionCollapsed || !focusTextBlock || !focusSpan ? !1 : focusTextBlock.node.children[0]._key === focusSpan.node._key && context.selection.focus.offset === 0 && focusTextBlock.node.level !== void 0 && focusTextBlock.node.level > 1 ? {
|
|
5453
|
-
focusTextBlock,
|
|
5454
|
-
level: focusTextBlock.node.level - 1
|
|
5455
|
-
} : !1;
|
|
5456
|
-
},
|
|
5457
|
-
actions: [(_, {
|
|
5458
|
-
focusTextBlock,
|
|
5459
|
-
level
|
|
5460
|
-
}) => [{
|
|
5461
|
-
type: "set block",
|
|
5462
|
-
level,
|
|
5463
|
-
paths: [focusTextBlock.path]
|
|
5464
|
-
}]]
|
|
5465
|
-
}, coreListBehaviors = [clearListOnBackspace, unindentListOnBackspace], softReturn = {
|
|
5466
|
-
on: "insert soft break",
|
|
5467
|
-
actions: [() => [{
|
|
5468
|
-
type: "insert text",
|
|
5469
|
-
text: `
|
|
5470
|
-
`
|
|
5471
|
-
}]]
|
|
5472
|
-
}, coreBehaviors = [softReturn, ...coreBlockObjectBehaviors, ...coreListBehaviors], networkLogic = fromCallback(({
|
|
5508
|
+
const networkLogic = fromCallback(({
|
|
5473
5509
|
sendBack
|
|
5474
5510
|
}) => {
|
|
5475
5511
|
const onlineHandler = () => {
|
|
@@ -5495,7 +5531,7 @@ const breakingVoidBlock = {
|
|
|
5495
5531
|
"assign behaviors": assign({
|
|
5496
5532
|
behaviors: ({
|
|
5497
5533
|
event
|
|
5498
|
-
}) => (assertEvent(event, "update behaviors"),
|
|
5534
|
+
}) => (assertEvent(event, "update behaviors"), event.behaviors)
|
|
5499
5535
|
}),
|
|
5500
5536
|
"assign schema": assign({
|
|
5501
5537
|
schema: ({
|
|
@@ -5589,7 +5625,7 @@ const breakingVoidBlock = {
|
|
|
5589
5625
|
context: ({
|
|
5590
5626
|
input
|
|
5591
5627
|
}) => ({
|
|
5592
|
-
behaviors: input.behaviors
|
|
5628
|
+
behaviors: input.behaviors ?? coreBehaviors,
|
|
5593
5629
|
keyGenerator: input.keyGenerator,
|
|
5594
5630
|
pendingEvents: [],
|
|
5595
5631
|
schema: input.schema
|
|
@@ -6289,6 +6325,8 @@ function useEditor(config) {
|
|
|
6289
6325
|
export {
|
|
6290
6326
|
PortableTextEditable,
|
|
6291
6327
|
PortableTextEditor,
|
|
6328
|
+
coreBehavior,
|
|
6329
|
+
coreBehaviors,
|
|
6292
6330
|
createMarkdownBehaviors,
|
|
6293
6331
|
defineBehavior,
|
|
6294
6332
|
defineSchema,
|