@portabletext/editor 1.11.3 → 1.12.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/README.md +11 -0
- package/lib/index.d.mts +26 -7
- package/lib/index.d.ts +26 -7
- package/lib/index.esm.js +427 -152
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +426 -151
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +427 -152
- package/lib/index.mjs.map +1 -1
- package/package.json +12 -12
- package/src/editor/behavior/behavior.action-utils.insert-block.ts +63 -0
- package/src/editor/behavior/behavior.action.insert-block-object.ts +25 -0
- package/src/editor/behavior/behavior.actions.ts +88 -32
- package/src/editor/behavior/behavior.core.block-objects.ts +5 -11
- package/src/editor/behavior/behavior.markdown.ts +162 -69
- package/src/editor/behavior/behavior.types.ts +22 -6
- package/src/editor/behavior/behavior.utils.block-offset.test.ts +143 -0
- package/src/editor/behavior/behavior.utils.block-offset.ts +101 -0
- package/src/editor/behavior/behavior.utils.get-selection-text.ts +92 -0
- package/src/editor/behavior/behavior.utils.get-start-point.ts +26 -0
- package/src/editor/behavior/behavior.utils.is-keyed-segment.ts +5 -0
- package/src/editor/behavior/behavior.utils.reverse-selection.ts +21 -0
- package/src/editor/behavior/behavior.utils.ts +13 -2
- package/src/editor/behavior/behavior.utilts.get-text-before.ts +31 -0
- package/src/editor/plugins/createWithEditableAPI.ts +22 -87
- package/src/index.ts +1 -0
package/lib/index.js
CHANGED
|
@@ -117,7 +117,13 @@ function getNextBlock(context) {
|
|
|
117
117
|
return nextBlock;
|
|
118
118
|
}
|
|
119
119
|
function isEmptyTextBlock(block) {
|
|
120
|
-
|
|
120
|
+
if (!types.isPortableTextTextBlock(block))
|
|
121
|
+
return !1;
|
|
122
|
+
const onlyText = block.children.every(types.isPortableTextSpan), blockText = getTextBlockText(block);
|
|
123
|
+
return onlyText && blockText === "";
|
|
124
|
+
}
|
|
125
|
+
function getTextBlockText(block) {
|
|
126
|
+
return block.children.map((child) => child.text ?? "").join("");
|
|
121
127
|
}
|
|
122
128
|
const breakingBlockObject = {
|
|
123
129
|
on: "insert break",
|
|
@@ -126,7 +132,7 @@ const breakingBlockObject = {
|
|
|
126
132
|
}) => !!getFocusBlockObject(context),
|
|
127
133
|
actions: [() => [{
|
|
128
134
|
type: "insert text block",
|
|
129
|
-
|
|
135
|
+
placement: "after"
|
|
130
136
|
}]]
|
|
131
137
|
}, deletingEmptyTextBlockAfterBlockObject = {
|
|
132
138
|
on: "delete backward",
|
|
@@ -143,17 +149,8 @@ const breakingBlockObject = {
|
|
|
143
149
|
focusTextBlock,
|
|
144
150
|
previousBlock
|
|
145
151
|
}) => [{
|
|
146
|
-
type: "delete",
|
|
147
|
-
|
|
148
|
-
anchor: {
|
|
149
|
-
path: focusTextBlock.path,
|
|
150
|
-
offset: 0
|
|
151
|
-
},
|
|
152
|
-
focus: {
|
|
153
|
-
path: focusTextBlock.path,
|
|
154
|
-
offset: 0
|
|
155
|
-
}
|
|
156
|
-
}
|
|
152
|
+
type: "delete block",
|
|
153
|
+
blockPath: focusTextBlock.path
|
|
157
154
|
}, {
|
|
158
155
|
type: "select",
|
|
159
156
|
selection: {
|
|
@@ -182,17 +179,8 @@ const breakingBlockObject = {
|
|
|
182
179
|
focusTextBlock,
|
|
183
180
|
nextBlock
|
|
184
181
|
}) => [{
|
|
185
|
-
type: "delete",
|
|
186
|
-
|
|
187
|
-
anchor: {
|
|
188
|
-
path: focusTextBlock.path,
|
|
189
|
-
offset: 0
|
|
190
|
-
},
|
|
191
|
-
focus: {
|
|
192
|
-
path: focusTextBlock.path,
|
|
193
|
-
offset: 0
|
|
194
|
-
}
|
|
195
|
-
}
|
|
182
|
+
type: "delete block",
|
|
183
|
+
blockPath: focusTextBlock.path
|
|
196
184
|
}, {
|
|
197
185
|
type: "select",
|
|
198
186
|
selection: {
|
|
@@ -355,20 +343,138 @@ function looksLikeUrl(text) {
|
|
|
355
343
|
}
|
|
356
344
|
return looksLikeUrl2;
|
|
357
345
|
}
|
|
358
|
-
function
|
|
359
|
-
|
|
346
|
+
function blockOffsetToSpanSelectionPoint({
|
|
347
|
+
value,
|
|
348
|
+
blockOffset
|
|
349
|
+
}) {
|
|
350
|
+
let offsetLeft = blockOffset.offset, selectionPoint;
|
|
351
|
+
for (const block of value)
|
|
352
|
+
if (block._key === blockOffset.path[0]._key && types.isPortableTextTextBlock(block)) {
|
|
353
|
+
for (const child of block.children)
|
|
354
|
+
if (types.isPortableTextSpan(child)) {
|
|
355
|
+
if (offsetLeft === 0) {
|
|
356
|
+
selectionPoint = {
|
|
357
|
+
path: [...blockOffset.path, "children", {
|
|
358
|
+
_key: child._key
|
|
359
|
+
}],
|
|
360
|
+
offset: 0
|
|
361
|
+
};
|
|
362
|
+
break;
|
|
363
|
+
}
|
|
364
|
+
if (offsetLeft <= child.text.length) {
|
|
365
|
+
selectionPoint = {
|
|
366
|
+
path: [...blockOffset.path, "children", {
|
|
367
|
+
_key: child._key
|
|
368
|
+
}],
|
|
369
|
+
offset: offsetLeft
|
|
370
|
+
};
|
|
371
|
+
break;
|
|
372
|
+
}
|
|
373
|
+
offsetLeft -= child.text.length;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
return selectionPoint;
|
|
360
377
|
}
|
|
361
|
-
function
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
(
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
378
|
+
function spanSelectionPointToBlockOffset({
|
|
379
|
+
value,
|
|
380
|
+
selectionPoint
|
|
381
|
+
}) {
|
|
382
|
+
let offset = 0;
|
|
383
|
+
for (const block of value)
|
|
384
|
+
if (block._key === selectionPoint.path[0]._key && types.isPortableTextTextBlock(block)) {
|
|
385
|
+
for (const child of block.children)
|
|
386
|
+
if (types.isPortableTextSpan(child)) {
|
|
387
|
+
if (child._key === selectionPoint.path[2]._key)
|
|
388
|
+
return {
|
|
389
|
+
path: [{
|
|
390
|
+
_key: block._key
|
|
391
|
+
}],
|
|
392
|
+
offset: offset + selectionPoint.offset
|
|
393
|
+
};
|
|
394
|
+
offset += child.text.length;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
function isKeyedSegment$1(segment) {
|
|
399
|
+
return typeof segment == "object" && segment !== null && "_key" in segment;
|
|
400
|
+
}
|
|
401
|
+
function reverseSelection(selection) {
|
|
402
|
+
return selection && (selection.backward ? {
|
|
403
|
+
anchor: selection.focus,
|
|
404
|
+
focus: selection.anchor,
|
|
405
|
+
backward: !1
|
|
406
|
+
} : {
|
|
407
|
+
anchor: selection.focus,
|
|
408
|
+
focus: selection.anchor,
|
|
409
|
+
backward: !0
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
function getSelectionText({
|
|
413
|
+
value,
|
|
414
|
+
selection
|
|
415
|
+
}) {
|
|
416
|
+
let text = "";
|
|
417
|
+
if (!value || !selection)
|
|
418
|
+
return text;
|
|
419
|
+
const forwardSelection = selection.backward ? reverseSelection(selection) : selection;
|
|
420
|
+
if (!forwardSelection)
|
|
421
|
+
return text;
|
|
422
|
+
for (const block of value)
|
|
423
|
+
if (!(isKeyedSegment$1(forwardSelection.anchor.path[0]) && block._key !== forwardSelection.anchor.path[0]._key) && types.isPortableTextTextBlock(block)) {
|
|
424
|
+
for (const child of block.children)
|
|
425
|
+
if (types.isPortableTextSpan(child)) {
|
|
426
|
+
if (isKeyedSegment$1(forwardSelection.anchor.path[2]) && child._key === forwardSelection.anchor.path[2]._key && isKeyedSegment$1(forwardSelection.focus.path[2]) && child._key === forwardSelection.focus.path[2]._key) {
|
|
427
|
+
text = text + child.text.slice(forwardSelection.anchor.offset, forwardSelection.focus.offset);
|
|
428
|
+
break;
|
|
429
|
+
}
|
|
430
|
+
if (isKeyedSegment$1(forwardSelection.anchor.path[2]) && child._key === forwardSelection.anchor.path[2]._key) {
|
|
431
|
+
text = text + child.text.slice(forwardSelection.anchor.offset);
|
|
432
|
+
continue;
|
|
433
|
+
}
|
|
434
|
+
if (isKeyedSegment$1(forwardSelection.focus.path[2]) && child._key === forwardSelection.focus.path[2]._key) {
|
|
435
|
+
text = text + child.text.slice(0, forwardSelection.focus.offset);
|
|
436
|
+
break;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
if (isKeyedSegment$1(forwardSelection.focus.path[0]) && block._key === forwardSelection.focus.path[0]._key)
|
|
440
|
+
break;
|
|
441
|
+
}
|
|
442
|
+
return text;
|
|
443
|
+
}
|
|
444
|
+
function getStartPoint({
|
|
445
|
+
node,
|
|
446
|
+
path
|
|
447
|
+
}) {
|
|
448
|
+
return types.isPortableTextTextBlock(node) ? {
|
|
449
|
+
path: [...path, "children", {
|
|
450
|
+
_key: node.children[0]._key
|
|
451
|
+
}],
|
|
452
|
+
offset: 0
|
|
453
|
+
} : {
|
|
454
|
+
path,
|
|
455
|
+
offset: 0
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
function getBlockTextBefore({
|
|
459
|
+
value,
|
|
460
|
+
point
|
|
461
|
+
}) {
|
|
462
|
+
const key = isKeyedSegment$1(point.path[0]) ? point.path[0]._key : void 0, block = key ? value.find((block2) => block2._key === key) : void 0;
|
|
463
|
+
if (!block)
|
|
464
|
+
return "";
|
|
465
|
+
const startPoint = getStartPoint({
|
|
466
|
+
node: block,
|
|
467
|
+
path: [{
|
|
468
|
+
_key: block._key
|
|
469
|
+
}]
|
|
470
|
+
});
|
|
471
|
+
return getSelectionText({
|
|
472
|
+
value,
|
|
473
|
+
selection: {
|
|
474
|
+
anchor: startPoint,
|
|
475
|
+
focus: point
|
|
476
|
+
}
|
|
477
|
+
});
|
|
372
478
|
}
|
|
373
479
|
function createMarkdownBehaviors(config) {
|
|
374
480
|
const automaticBlockquoteOnSpace = {
|
|
@@ -382,12 +488,24 @@ function createMarkdownBehaviors(config) {
|
|
|
382
488
|
const selectionCollapsed = selectionIsCollapsed(context), focusTextBlock = getFocusTextBlock(context), focusSpan = getFocusSpan(context);
|
|
383
489
|
if (!selectionCollapsed || !focusTextBlock || !focusSpan)
|
|
384
490
|
return !1;
|
|
385
|
-
const
|
|
491
|
+
const blockOffset = spanSelectionPointToBlockOffset({
|
|
492
|
+
value: context.value,
|
|
493
|
+
selectionPoint: {
|
|
494
|
+
path: [{
|
|
495
|
+
_key: focusTextBlock.node._key
|
|
496
|
+
}, "children", {
|
|
497
|
+
_key: focusSpan.node._key
|
|
498
|
+
}],
|
|
499
|
+
offset: context.selection.focus.offset
|
|
500
|
+
}
|
|
501
|
+
});
|
|
502
|
+
if (!blockOffset)
|
|
503
|
+
return !1;
|
|
504
|
+
const blockText = getTextBlockText(focusTextBlock.node), caretAtTheEndOfQuote = blockOffset.offset === 1, looksLikeMarkdownQuote = /^>/.test(blockText), blockquoteStyle = config.blockquoteStyle?.({
|
|
386
505
|
schema: context.schema
|
|
387
506
|
});
|
|
388
507
|
return caretAtTheEndOfQuote && looksLikeMarkdownQuote && blockquoteStyle !== void 0 ? {
|
|
389
508
|
focusTextBlock,
|
|
390
|
-
focusSpan,
|
|
391
509
|
style: blockquoteStyle
|
|
392
510
|
} : !1;
|
|
393
511
|
},
|
|
@@ -396,7 +514,6 @@ function createMarkdownBehaviors(config) {
|
|
|
396
514
|
text: " "
|
|
397
515
|
}], (_, {
|
|
398
516
|
focusTextBlock,
|
|
399
|
-
focusSpan,
|
|
400
517
|
style
|
|
401
518
|
}) => [{
|
|
402
519
|
type: "unset block",
|
|
@@ -407,19 +524,17 @@ function createMarkdownBehaviors(config) {
|
|
|
407
524
|
style,
|
|
408
525
|
paths: [focusTextBlock.path]
|
|
409
526
|
}, {
|
|
410
|
-
type: "delete",
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
offset: 2
|
|
419
|
-
}
|
|
527
|
+
type: "delete text",
|
|
528
|
+
anchor: {
|
|
529
|
+
path: focusTextBlock.path,
|
|
530
|
+
offset: 0
|
|
531
|
+
},
|
|
532
|
+
focus: {
|
|
533
|
+
path: focusTextBlock.path,
|
|
534
|
+
offset: 2
|
|
420
535
|
}
|
|
421
536
|
}]]
|
|
422
|
-
},
|
|
537
|
+
}, automaticHr = {
|
|
423
538
|
on: "insert text",
|
|
424
539
|
guard: ({
|
|
425
540
|
context,
|
|
@@ -428,16 +543,29 @@ function createMarkdownBehaviors(config) {
|
|
|
428
543
|
const hrCharacter = event.text === "-" ? "-" : event.text === "*" ? "*" : event.text === "_" ? "_" : void 0;
|
|
429
544
|
if (hrCharacter === void 0)
|
|
430
545
|
return !1;
|
|
431
|
-
const
|
|
546
|
+
const hrObject = config.horizontalRuleObject?.({
|
|
432
547
|
schema: context.schema
|
|
433
548
|
}), focusBlock = getFocusTextBlock(context), selectionCollapsed = selectionIsCollapsed(context);
|
|
434
|
-
if (!
|
|
549
|
+
if (!hrObject || !focusBlock || !selectionCollapsed)
|
|
435
550
|
return !1;
|
|
436
|
-
const
|
|
437
|
-
|
|
438
|
-
|
|
551
|
+
const textBefore = getBlockTextBefore({
|
|
552
|
+
value: context.value,
|
|
553
|
+
point: context.selection.focus
|
|
554
|
+
}), hrBlockOffsets = {
|
|
555
|
+
anchor: {
|
|
556
|
+
path: focusBlock.path,
|
|
557
|
+
offset: 0
|
|
558
|
+
},
|
|
559
|
+
focus: {
|
|
560
|
+
path: focusBlock.path,
|
|
561
|
+
offset: 3
|
|
562
|
+
}
|
|
563
|
+
};
|
|
564
|
+
return textBefore === `${hrCharacter}${hrCharacter}` ? {
|
|
565
|
+
hrObject,
|
|
439
566
|
focusBlock,
|
|
440
|
-
hrCharacter
|
|
567
|
+
hrCharacter,
|
|
568
|
+
hrBlockOffsets
|
|
441
569
|
} : !1;
|
|
442
570
|
},
|
|
443
571
|
actions: [(_, {
|
|
@@ -446,26 +574,56 @@ function createMarkdownBehaviors(config) {
|
|
|
446
574
|
type: "insert text",
|
|
447
575
|
text: hrCharacter
|
|
448
576
|
}], (_, {
|
|
449
|
-
|
|
450
|
-
|
|
577
|
+
hrObject,
|
|
578
|
+
hrBlockOffsets
|
|
451
579
|
}) => [{
|
|
452
580
|
type: "insert block object",
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
type: "delete",
|
|
456
|
-
selection: {
|
|
457
|
-
anchor: {
|
|
458
|
-
path: focusBlock.path,
|
|
459
|
-
offset: 0
|
|
460
|
-
},
|
|
461
|
-
focus: {
|
|
462
|
-
path: focusBlock.path,
|
|
463
|
-
offset: 0
|
|
464
|
-
}
|
|
465
|
-
}
|
|
581
|
+
placement: "before",
|
|
582
|
+
blockObject: hrObject
|
|
466
583
|
}, {
|
|
584
|
+
type: "delete text",
|
|
585
|
+
...hrBlockOffsets
|
|
586
|
+
}]]
|
|
587
|
+
}, automaticHrOnPaste = {
|
|
588
|
+
on: "paste",
|
|
589
|
+
guard: ({
|
|
590
|
+
context,
|
|
591
|
+
event
|
|
592
|
+
}) => {
|
|
593
|
+
const text = event.clipboardData.getData("text/plain"), hrRegExp = /^(---)$|(___)$|(\*\*\*)$/gm, hrCharacters = text.match(hrRegExp)?.[0], hrObject = config.horizontalRuleObject?.({
|
|
594
|
+
schema: context.schema
|
|
595
|
+
}), focusBlock = getFocusBlock(context);
|
|
596
|
+
return !hrCharacters || !hrObject || !focusBlock ? !1 : {
|
|
597
|
+
hrCharacters,
|
|
598
|
+
hrObject,
|
|
599
|
+
focusBlock
|
|
600
|
+
};
|
|
601
|
+
},
|
|
602
|
+
actions: [(_, {
|
|
603
|
+
hrCharacters
|
|
604
|
+
}) => [{
|
|
605
|
+
type: "insert text",
|
|
606
|
+
text: hrCharacters
|
|
607
|
+
}], (_, {
|
|
608
|
+
hrObject,
|
|
609
|
+
focusBlock
|
|
610
|
+
}) => types.isPortableTextTextBlock(focusBlock.node) ? [{
|
|
467
611
|
type: "insert text block",
|
|
468
|
-
|
|
612
|
+
textBlock: {
|
|
613
|
+
children: focusBlock.node.children
|
|
614
|
+
},
|
|
615
|
+
placement: "after"
|
|
616
|
+
}, {
|
|
617
|
+
type: "insert block object",
|
|
618
|
+
blockObject: hrObject,
|
|
619
|
+
placement: "after"
|
|
620
|
+
}, {
|
|
621
|
+
type: "delete block",
|
|
622
|
+
blockPath: focusBlock.path
|
|
623
|
+
}] : [{
|
|
624
|
+
type: "insert block object",
|
|
625
|
+
blockObject: hrObject,
|
|
626
|
+
placement: "after"
|
|
469
627
|
}]]
|
|
470
628
|
}, automaticHeadingOnSpace = {
|
|
471
629
|
on: "insert text",
|
|
@@ -478,8 +636,21 @@ function createMarkdownBehaviors(config) {
|
|
|
478
636
|
const selectionCollapsed = selectionIsCollapsed(context), focusTextBlock = getFocusTextBlock(context), focusSpan = getFocusSpan(context);
|
|
479
637
|
if (!selectionCollapsed || !focusTextBlock || !focusSpan)
|
|
480
638
|
return !1;
|
|
481
|
-
const
|
|
482
|
-
|
|
639
|
+
const blockOffset = spanSelectionPointToBlockOffset({
|
|
640
|
+
value: context.value,
|
|
641
|
+
selectionPoint: {
|
|
642
|
+
path: [{
|
|
643
|
+
_key: focusTextBlock.node._key
|
|
644
|
+
}, "children", {
|
|
645
|
+
_key: focusSpan.node._key
|
|
646
|
+
}],
|
|
647
|
+
offset: context.selection.focus.offset
|
|
648
|
+
}
|
|
649
|
+
});
|
|
650
|
+
if (!blockOffset)
|
|
651
|
+
return !1;
|
|
652
|
+
const blockText = getTextBlockText(focusTextBlock.node), markdownHeadingSearch = /^#+/.exec(blockText), level = markdownHeadingSearch ? markdownHeadingSearch[0].length : void 0;
|
|
653
|
+
if (blockOffset.offset !== level)
|
|
483
654
|
return !1;
|
|
484
655
|
const style = level !== void 0 ? config.headingStyle?.({
|
|
485
656
|
schema: context.schema,
|
|
@@ -487,7 +658,6 @@ function createMarkdownBehaviors(config) {
|
|
|
487
658
|
}) : void 0;
|
|
488
659
|
return level !== void 0 && style !== void 0 ? {
|
|
489
660
|
focusTextBlock,
|
|
490
|
-
focusSpan,
|
|
491
661
|
style,
|
|
492
662
|
level
|
|
493
663
|
} : !1;
|
|
@@ -497,7 +667,6 @@ function createMarkdownBehaviors(config) {
|
|
|
497
667
|
text: " "
|
|
498
668
|
}], (_, {
|
|
499
669
|
focusTextBlock,
|
|
500
|
-
focusSpan,
|
|
501
670
|
style,
|
|
502
671
|
level
|
|
503
672
|
}) => [{
|
|
@@ -509,16 +678,14 @@ function createMarkdownBehaviors(config) {
|
|
|
509
678
|
style,
|
|
510
679
|
paths: [focusTextBlock.path]
|
|
511
680
|
}, {
|
|
512
|
-
type: "delete",
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
offset: level + 1
|
|
521
|
-
}
|
|
681
|
+
type: "delete text",
|
|
682
|
+
anchor: {
|
|
683
|
+
path: focusTextBlock.path,
|
|
684
|
+
offset: 0
|
|
685
|
+
},
|
|
686
|
+
focus: {
|
|
687
|
+
path: focusTextBlock.path,
|
|
688
|
+
offset: level + 1
|
|
522
689
|
}
|
|
523
690
|
}]]
|
|
524
691
|
}, clearStyleOnBackspace = {
|
|
@@ -556,15 +723,27 @@ function createMarkdownBehaviors(config) {
|
|
|
556
723
|
const selectionCollapsed = selectionIsCollapsed(context), focusTextBlock = getFocusTextBlock(context), focusSpan = getFocusSpan(context);
|
|
557
724
|
if (!selectionCollapsed || !focusTextBlock || !focusSpan)
|
|
558
725
|
return !1;
|
|
559
|
-
const
|
|
726
|
+
const blockOffset = spanSelectionPointToBlockOffset({
|
|
727
|
+
value: context.value,
|
|
728
|
+
selectionPoint: {
|
|
729
|
+
path: [{
|
|
730
|
+
_key: focusTextBlock.node._key
|
|
731
|
+
}, "children", {
|
|
732
|
+
_key: focusSpan.node._key
|
|
733
|
+
}],
|
|
734
|
+
offset: context.selection.focus.offset
|
|
735
|
+
}
|
|
736
|
+
});
|
|
737
|
+
if (!blockOffset)
|
|
738
|
+
return !1;
|
|
739
|
+
const blockText = getTextBlockText(focusTextBlock.node), defaultStyle = config.defaultStyle?.({
|
|
560
740
|
schema: context.schema
|
|
561
|
-
}), looksLikeUnorderedList = /^(-|\*)/.test(
|
|
741
|
+
}), looksLikeUnorderedList = /^(-|\*)/.test(blockText), unorderedListStyle = config.unorderedListStyle?.({
|
|
562
742
|
schema: context.schema
|
|
563
|
-
}), caretAtTheEndOfUnorderedList =
|
|
743
|
+
}), caretAtTheEndOfUnorderedList = blockOffset.offset === 1;
|
|
564
744
|
if (defaultStyle && caretAtTheEndOfUnorderedList && looksLikeUnorderedList && unorderedListStyle !== void 0)
|
|
565
745
|
return {
|
|
566
746
|
focusTextBlock,
|
|
567
|
-
focusSpan,
|
|
568
747
|
listItem: unorderedListStyle,
|
|
569
748
|
listItemLength: 1,
|
|
570
749
|
style: defaultStyle
|
|
@@ -574,7 +753,6 @@ function createMarkdownBehaviors(config) {
|
|
|
574
753
|
}), caretAtTheEndOfOrderedList = context.selection.focus.offset === 2;
|
|
575
754
|
return defaultStyle && caretAtTheEndOfOrderedList && looksLikeOrderedList && orderedListStyle !== void 0 ? {
|
|
576
755
|
focusTextBlock,
|
|
577
|
-
focusSpan,
|
|
578
756
|
listItem: orderedListStyle,
|
|
579
757
|
listItemLength: 2,
|
|
580
758
|
style: defaultStyle
|
|
@@ -585,7 +763,6 @@ function createMarkdownBehaviors(config) {
|
|
|
585
763
|
text: " "
|
|
586
764
|
}], (_, {
|
|
587
765
|
focusTextBlock,
|
|
588
|
-
focusSpan,
|
|
589
766
|
style,
|
|
590
767
|
listItem,
|
|
591
768
|
listItemLength
|
|
@@ -596,20 +773,18 @@ function createMarkdownBehaviors(config) {
|
|
|
596
773
|
style,
|
|
597
774
|
paths: [focusTextBlock.path]
|
|
598
775
|
}, {
|
|
599
|
-
type: "delete",
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
offset: listItemLength + 1
|
|
608
|
-
}
|
|
776
|
+
type: "delete text",
|
|
777
|
+
anchor: {
|
|
778
|
+
path: focusTextBlock.path,
|
|
779
|
+
offset: 0
|
|
780
|
+
},
|
|
781
|
+
focus: {
|
|
782
|
+
path: focusTextBlock.path,
|
|
783
|
+
offset: listItemLength + 1
|
|
609
784
|
}
|
|
610
785
|
}]]
|
|
611
786
|
};
|
|
612
|
-
return [automaticBlockquoteOnSpace,
|
|
787
|
+
return [automaticBlockquoteOnSpace, automaticHeadingOnSpace, automaticHr, automaticHrOnPaste, clearStyleOnBackspace, automaticListOnSpace];
|
|
613
788
|
}
|
|
614
789
|
function getPortableTextMemberSchemaTypes(portableTextType) {
|
|
615
790
|
if (!portableTextType)
|
|
@@ -4007,6 +4182,21 @@ function createWithPortableTextLists(types2) {
|
|
|
4007
4182
|
}, editor;
|
|
4008
4183
|
};
|
|
4009
4184
|
}
|
|
4185
|
+
function isPortableTextSpan(node) {
|
|
4186
|
+
return node._type === "span" && "text" in node && typeof node.text == "string" && (typeof node.marks > "u" || Array.isArray(node.marks) && node.marks.every((mark) => typeof mark == "string"));
|
|
4187
|
+
}
|
|
4188
|
+
function isPortableTextBlock(node) {
|
|
4189
|
+
return (
|
|
4190
|
+
// A block doesn't _have_ to be named 'block' - to differentiate between
|
|
4191
|
+
// allowed child types and marks, one might name them differently
|
|
4192
|
+
typeof node._type == "string" && // Toolkit-types like nested spans are @-prefixed
|
|
4193
|
+
node._type[0] !== "@" && // `markDefs` isn't _required_ per say, but if it's there, it needs to be an array
|
|
4194
|
+
(!("markDefs" in node) || !node.markDefs || Array.isArray(node.markDefs) && // Every mark definition needs to have an `_key` to be mappable in child spans
|
|
4195
|
+
node.markDefs.every((def) => typeof def._key == "string")) && // `children` is required and needs to be an array
|
|
4196
|
+
"children" in node && Array.isArray(node.children) && // All children are objects with `_type` (usually spans, but can contain other stuff)
|
|
4197
|
+
node.children.every((child) => typeof child == "object" && "_type" in child)
|
|
4198
|
+
);
|
|
4199
|
+
}
|
|
4010
4200
|
function getPreviousSpan({
|
|
4011
4201
|
editor,
|
|
4012
4202
|
blockPath,
|
|
@@ -4707,7 +4897,66 @@ function createSlateEditor(config) {
|
|
|
4707
4897
|
};
|
|
4708
4898
|
return slateEditors.set(config.editorActor, slateEditor), slateEditor;
|
|
4709
4899
|
}
|
|
4710
|
-
|
|
4900
|
+
function insertBlock({
|
|
4901
|
+
block,
|
|
4902
|
+
placement,
|
|
4903
|
+
editor,
|
|
4904
|
+
schema: schema2
|
|
4905
|
+
}) {
|
|
4906
|
+
if (editor.selection) {
|
|
4907
|
+
const [focusBlock, focusBlockPath] = Array.from(slate.Editor.nodes(editor, {
|
|
4908
|
+
at: editor.selection.focus.path.slice(0, 1),
|
|
4909
|
+
match: (n) => !slate.Editor.isEditor(n)
|
|
4910
|
+
}))[0] ?? [void 0, void 0];
|
|
4911
|
+
if (placement === "after") {
|
|
4912
|
+
const nextPath = [focusBlockPath[0] + 1];
|
|
4913
|
+
slate.Transforms.insertNodes(editor, block, {
|
|
4914
|
+
at: nextPath
|
|
4915
|
+
}), slate.Transforms.select(editor, {
|
|
4916
|
+
anchor: {
|
|
4917
|
+
path: [nextPath[0], 0],
|
|
4918
|
+
offset: 0
|
|
4919
|
+
},
|
|
4920
|
+
focus: {
|
|
4921
|
+
path: [nextPath[0], 0],
|
|
4922
|
+
offset: 0
|
|
4923
|
+
}
|
|
4924
|
+
});
|
|
4925
|
+
} else placement === "before" ? slate.Transforms.insertNodes(editor, block, {
|
|
4926
|
+
at: focusBlockPath
|
|
4927
|
+
}) : slate.Editor.insertNode(editor, block);
|
|
4928
|
+
focusBlock && isEqualToEmptyEditor([focusBlock], schema2) && slate.Transforms.removeNodes(editor, {
|
|
4929
|
+
at: focusBlockPath
|
|
4930
|
+
});
|
|
4931
|
+
} else {
|
|
4932
|
+
const lastBlock = Array.from(slate.Editor.nodes(editor, {
|
|
4933
|
+
match: (n) => !slate.Editor.isEditor(n),
|
|
4934
|
+
at: [],
|
|
4935
|
+
reverse: !0
|
|
4936
|
+
}))[0];
|
|
4937
|
+
slate.Editor.insertNode(editor, block), lastBlock && isEqualToEmptyEditor([lastBlock[0]], schema2) && slate.Transforms.removeNodes(editor, {
|
|
4938
|
+
at: lastBlock[1]
|
|
4939
|
+
});
|
|
4940
|
+
}
|
|
4941
|
+
}
|
|
4942
|
+
const insertBlockObjectActionImplementation = ({
|
|
4943
|
+
context,
|
|
4944
|
+
action
|
|
4945
|
+
}) => {
|
|
4946
|
+
const block = toSlateValue([{
|
|
4947
|
+
_key: context.keyGenerator(),
|
|
4948
|
+
_type: action.blockObject.name,
|
|
4949
|
+
...action.blockObject.value ? action.blockObject.value : {}
|
|
4950
|
+
}], {
|
|
4951
|
+
schemaTypes: context.schema
|
|
4952
|
+
})[0];
|
|
4953
|
+
insertBlock({
|
|
4954
|
+
block,
|
|
4955
|
+
placement: action.placement,
|
|
4956
|
+
editor: action.editor,
|
|
4957
|
+
schema: context.schema
|
|
4958
|
+
});
|
|
4959
|
+
}, debug$5 = debugWithName("API:editable");
|
|
4711
4960
|
function createEditableAPI(editor, editorActor) {
|
|
4712
4961
|
const types2 = editorActor.getSnapshot().context.schema;
|
|
4713
4962
|
return {
|
|
@@ -4796,18 +5045,21 @@ function createEditableAPI(editor, editorActor) {
|
|
|
4796
5045
|
at: editor.selection
|
|
4797
5046
|
}), editor.onChange(), toPortableTextRange(fromSlateValue(editor.children, types2.block.name, KEY_TO_VALUE_ELEMENT.get(editor)), editor.selection, types2)?.focus.path || [];
|
|
4798
5047
|
},
|
|
4799
|
-
insertBlock: (type, value) => insertBlockObjectActionImplementation({
|
|
5048
|
+
insertBlock: (type, value) => (insertBlockObjectActionImplementation({
|
|
4800
5049
|
context: {
|
|
4801
5050
|
keyGenerator: editorActor.getSnapshot().context.keyGenerator,
|
|
4802
5051
|
schema: types2
|
|
4803
5052
|
},
|
|
4804
5053
|
action: {
|
|
4805
5054
|
type: "insert block object",
|
|
4806
|
-
|
|
4807
|
-
|
|
5055
|
+
blockObject: {
|
|
5056
|
+
name: type.name,
|
|
5057
|
+
value
|
|
5058
|
+
},
|
|
5059
|
+
placement: "auto",
|
|
4808
5060
|
editor
|
|
4809
5061
|
}
|
|
4810
|
-
}),
|
|
5062
|
+
}), editor.onChange(), toPortableTextRange(fromSlateValue(editor.children, types2.block.name, KEY_TO_VALUE_ELEMENT.get(editor)), editor.selection, types2)?.focus.path ?? []),
|
|
4811
5063
|
hasBlockStyle: (style) => {
|
|
4812
5064
|
try {
|
|
4813
5065
|
return editor.pteHasBlockStyle(style);
|
|
@@ -4977,35 +5229,6 @@ function createEditableAPI(editor, editorActor) {
|
|
|
4977
5229
|
}
|
|
4978
5230
|
};
|
|
4979
5231
|
}
|
|
4980
|
-
const insertBlockObjectActionImplementation = ({
|
|
4981
|
-
context,
|
|
4982
|
-
action
|
|
4983
|
-
}) => {
|
|
4984
|
-
const editor = action.editor, types2 = context.schema, block = toSlateValue([{
|
|
4985
|
-
_key: context.keyGenerator(),
|
|
4986
|
-
_type: action.name,
|
|
4987
|
-
...action.value ? action.value : {}
|
|
4988
|
-
}], {
|
|
4989
|
-
schemaTypes: context.schema
|
|
4990
|
-
})[0];
|
|
4991
|
-
if (!editor.selection) {
|
|
4992
|
-
const lastBlock = Array.from(slate.Editor.nodes(editor, {
|
|
4993
|
-
match: (n) => !slate.Editor.isEditor(n),
|
|
4994
|
-
at: [],
|
|
4995
|
-
reverse: !0
|
|
4996
|
-
}))[0];
|
|
4997
|
-
return slate.Editor.insertNode(editor, block), lastBlock && isEqualToEmptyEditor([lastBlock[0]], types2) && slate.Transforms.removeNodes(editor, {
|
|
4998
|
-
at: lastBlock[1]
|
|
4999
|
-
}), editor.onChange(), toPortableTextRange(fromSlateValue(editor.children, types2.block.name, KEY_TO_VALUE_ELEMENT.get(editor)), editor.selection, types2)?.focus.path ?? [];
|
|
5000
|
-
}
|
|
5001
|
-
const focusBlock = Array.from(slate.Editor.nodes(editor, {
|
|
5002
|
-
at: editor.selection.focus.path.slice(0, 1),
|
|
5003
|
-
match: (n) => n._type === types2.block.name
|
|
5004
|
-
}))[0];
|
|
5005
|
-
return slate.Editor.insertNode(editor, block), focusBlock && isEqualToEmptyEditor([focusBlock[0]], types2) && slate.Transforms.removeNodes(editor, {
|
|
5006
|
-
at: focusBlock[1]
|
|
5007
|
-
}), editor.onChange(), toPortableTextRange(fromSlateValue(editor.children, types2.block.name, KEY_TO_VALUE_ELEMENT.get(editor)), editor.selection, types2)?.focus.path || [];
|
|
5008
|
-
};
|
|
5009
5232
|
function isAnnotationActive({
|
|
5010
5233
|
editor,
|
|
5011
5234
|
annotation
|
|
@@ -5401,18 +5624,52 @@ const addAnnotationActionImplementation = ({
|
|
|
5401
5624
|
}) => {
|
|
5402
5625
|
slate.deleteForward(action.editor, action.unit);
|
|
5403
5626
|
},
|
|
5404
|
-
delete: ({
|
|
5627
|
+
"delete block": ({
|
|
5628
|
+
action
|
|
5629
|
+
}) => {
|
|
5630
|
+
const range = toSlateRange({
|
|
5631
|
+
anchor: {
|
|
5632
|
+
path: action.blockPath,
|
|
5633
|
+
offset: 0
|
|
5634
|
+
},
|
|
5635
|
+
focus: {
|
|
5636
|
+
path: action.blockPath,
|
|
5637
|
+
offset: 0
|
|
5638
|
+
}
|
|
5639
|
+
}, action.editor);
|
|
5640
|
+
if (!range) {
|
|
5641
|
+
console.error("Unable to find Slate range from selection points");
|
|
5642
|
+
return;
|
|
5643
|
+
}
|
|
5644
|
+
slate.Transforms.removeNodes(action.editor, {
|
|
5645
|
+
at: range
|
|
5646
|
+
});
|
|
5647
|
+
},
|
|
5648
|
+
"delete text": ({
|
|
5649
|
+
context,
|
|
5405
5650
|
action
|
|
5406
5651
|
}) => {
|
|
5407
|
-
const
|
|
5408
|
-
|
|
5409
|
-
|
|
5652
|
+
const value = fromSlateValue(action.editor.children, context.schema.block.name, KEY_TO_VALUE_ELEMENT.get(action.editor)), anchor = blockOffsetToSpanSelectionPoint({
|
|
5653
|
+
value,
|
|
5654
|
+
blockOffset: action.anchor
|
|
5655
|
+
}), focus = blockOffsetToSpanSelectionPoint({
|
|
5656
|
+
value,
|
|
5657
|
+
blockOffset: action.focus
|
|
5658
|
+
});
|
|
5659
|
+
if (!anchor || !focus) {
|
|
5660
|
+
console.error("Unable to find anchor or focus selection point");
|
|
5410
5661
|
return;
|
|
5411
5662
|
}
|
|
5412
|
-
|
|
5413
|
-
|
|
5414
|
-
|
|
5415
|
-
|
|
5663
|
+
const range = toSlateRange({
|
|
5664
|
+
anchor,
|
|
5665
|
+
focus
|
|
5666
|
+
}, action.editor);
|
|
5667
|
+
if (!range) {
|
|
5668
|
+
console.error("Unable to find Slate range from selection points");
|
|
5669
|
+
return;
|
|
5670
|
+
}
|
|
5671
|
+
slate.Transforms.delete(action.editor, {
|
|
5672
|
+
at: range
|
|
5416
5673
|
});
|
|
5417
5674
|
},
|
|
5418
5675
|
"insert block object": insertBlockObjectActionImplementation,
|
|
@@ -5428,16 +5685,27 @@ const addAnnotationActionImplementation = ({
|
|
|
5428
5685
|
context,
|
|
5429
5686
|
action
|
|
5430
5687
|
}) => {
|
|
5431
|
-
|
|
5688
|
+
const block = toSlateValue([{
|
|
5432
5689
|
_key: context.keyGenerator(),
|
|
5433
5690
|
_type: context.schema.block.name,
|
|
5434
5691
|
style: context.schema.styles[0].value ?? "normal",
|
|
5435
5692
|
markDefs: [],
|
|
5436
|
-
children:
|
|
5693
|
+
children: action.textBlock?.children?.map((child) => ({
|
|
5694
|
+
...child,
|
|
5695
|
+
_key: context.keyGenerator()
|
|
5696
|
+
})) ?? [{
|
|
5697
|
+
_type: context.schema.span.name,
|
|
5437
5698
|
_key: context.keyGenerator(),
|
|
5438
|
-
_type: "span",
|
|
5439
5699
|
text: ""
|
|
5440
5700
|
}]
|
|
5701
|
+
}], {
|
|
5702
|
+
schemaTypes: context.schema
|
|
5703
|
+
})[0];
|
|
5704
|
+
insertBlock({
|
|
5705
|
+
block,
|
|
5706
|
+
editor: action.editor,
|
|
5707
|
+
schema: context.schema,
|
|
5708
|
+
placement: action.placement
|
|
5441
5709
|
});
|
|
5442
5710
|
},
|
|
5443
5711
|
effect: ({
|
|
@@ -5472,8 +5740,15 @@ function performAction({
|
|
|
5472
5740
|
action
|
|
5473
5741
|
}) {
|
|
5474
5742
|
switch (action.type) {
|
|
5475
|
-
case "delete": {
|
|
5476
|
-
behaviorActionImplementations
|
|
5743
|
+
case "delete block": {
|
|
5744
|
+
behaviorActionImplementations["delete block"]({
|
|
5745
|
+
context,
|
|
5746
|
+
action
|
|
5747
|
+
});
|
|
5748
|
+
break;
|
|
5749
|
+
}
|
|
5750
|
+
case "delete text": {
|
|
5751
|
+
behaviorActionImplementations["delete text"]({
|
|
5477
5752
|
context,
|
|
5478
5753
|
action
|
|
5479
5754
|
});
|