@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.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isPortableTextTextBlock, isPortableTextSpan as isPortableTextSpan$1,
|
|
1
|
+
import { isKeySegment, isPortableTextTextBlock, isPortableTextSpan as isPortableTextSpan$1, defineType, defineField, isPortableTextListBlock } from "@sanity/types";
|
|
2
2
|
import { Schema } from "@sanity/schema";
|
|
3
3
|
import startCase from "lodash.startcase";
|
|
4
4
|
import { jsx, Fragment, jsxs } from "react/jsx-runtime";
|
|
@@ -138,7 +138,13 @@ function getNextBlock(context) {
|
|
|
138
138
|
return nextBlock;
|
|
139
139
|
}
|
|
140
140
|
function isEmptyTextBlock(block) {
|
|
141
|
-
|
|
141
|
+
if (!isPortableTextTextBlock(block))
|
|
142
|
+
return !1;
|
|
143
|
+
const onlyText = block.children.every(isPortableTextSpan$1), blockText = getTextBlockText(block);
|
|
144
|
+
return onlyText && blockText === "";
|
|
145
|
+
}
|
|
146
|
+
function getTextBlockText(block) {
|
|
147
|
+
return block.children.map((child) => child.text ?? "").join("");
|
|
142
148
|
}
|
|
143
149
|
const breakingBlockObject = {
|
|
144
150
|
on: "insert break",
|
|
@@ -147,7 +153,7 @@ const breakingBlockObject = {
|
|
|
147
153
|
}) => !!getFocusBlockObject(context),
|
|
148
154
|
actions: [() => [{
|
|
149
155
|
type: "insert text block",
|
|
150
|
-
|
|
156
|
+
placement: "after"
|
|
151
157
|
}]]
|
|
152
158
|
}, deletingEmptyTextBlockAfterBlockObject = {
|
|
153
159
|
on: "delete backward",
|
|
@@ -164,17 +170,8 @@ const breakingBlockObject = {
|
|
|
164
170
|
focusTextBlock,
|
|
165
171
|
previousBlock
|
|
166
172
|
}) => [{
|
|
167
|
-
type: "delete",
|
|
168
|
-
|
|
169
|
-
anchor: {
|
|
170
|
-
path: focusTextBlock.path,
|
|
171
|
-
offset: 0
|
|
172
|
-
},
|
|
173
|
-
focus: {
|
|
174
|
-
path: focusTextBlock.path,
|
|
175
|
-
offset: 0
|
|
176
|
-
}
|
|
177
|
-
}
|
|
173
|
+
type: "delete block",
|
|
174
|
+
blockPath: focusTextBlock.path
|
|
178
175
|
}, {
|
|
179
176
|
type: "select",
|
|
180
177
|
selection: {
|
|
@@ -203,17 +200,8 @@ const breakingBlockObject = {
|
|
|
203
200
|
focusTextBlock,
|
|
204
201
|
nextBlock
|
|
205
202
|
}) => [{
|
|
206
|
-
type: "delete",
|
|
207
|
-
|
|
208
|
-
anchor: {
|
|
209
|
-
path: focusTextBlock.path,
|
|
210
|
-
offset: 0
|
|
211
|
-
},
|
|
212
|
-
focus: {
|
|
213
|
-
path: focusTextBlock.path,
|
|
214
|
-
offset: 0
|
|
215
|
-
}
|
|
216
|
-
}
|
|
203
|
+
type: "delete block",
|
|
204
|
+
blockPath: focusTextBlock.path
|
|
217
205
|
}, {
|
|
218
206
|
type: "select",
|
|
219
207
|
selection: {
|
|
@@ -376,20 +364,138 @@ function looksLikeUrl(text) {
|
|
|
376
364
|
}
|
|
377
365
|
return looksLikeUrl2;
|
|
378
366
|
}
|
|
379
|
-
function
|
|
380
|
-
|
|
367
|
+
function blockOffsetToSpanSelectionPoint({
|
|
368
|
+
value,
|
|
369
|
+
blockOffset
|
|
370
|
+
}) {
|
|
371
|
+
let offsetLeft = blockOffset.offset, selectionPoint;
|
|
372
|
+
for (const block of value)
|
|
373
|
+
if (block._key === blockOffset.path[0]._key && isPortableTextTextBlock(block)) {
|
|
374
|
+
for (const child of block.children)
|
|
375
|
+
if (isPortableTextSpan$1(child)) {
|
|
376
|
+
if (offsetLeft === 0) {
|
|
377
|
+
selectionPoint = {
|
|
378
|
+
path: [...blockOffset.path, "children", {
|
|
379
|
+
_key: child._key
|
|
380
|
+
}],
|
|
381
|
+
offset: 0
|
|
382
|
+
};
|
|
383
|
+
break;
|
|
384
|
+
}
|
|
385
|
+
if (offsetLeft <= child.text.length) {
|
|
386
|
+
selectionPoint = {
|
|
387
|
+
path: [...blockOffset.path, "children", {
|
|
388
|
+
_key: child._key
|
|
389
|
+
}],
|
|
390
|
+
offset: offsetLeft
|
|
391
|
+
};
|
|
392
|
+
break;
|
|
393
|
+
}
|
|
394
|
+
offsetLeft -= child.text.length;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
return selectionPoint;
|
|
381
398
|
}
|
|
382
|
-
function
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
(
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
399
|
+
function spanSelectionPointToBlockOffset({
|
|
400
|
+
value,
|
|
401
|
+
selectionPoint
|
|
402
|
+
}) {
|
|
403
|
+
let offset = 0;
|
|
404
|
+
for (const block of value)
|
|
405
|
+
if (block._key === selectionPoint.path[0]._key && isPortableTextTextBlock(block)) {
|
|
406
|
+
for (const child of block.children)
|
|
407
|
+
if (isPortableTextSpan$1(child)) {
|
|
408
|
+
if (child._key === selectionPoint.path[2]._key)
|
|
409
|
+
return {
|
|
410
|
+
path: [{
|
|
411
|
+
_key: block._key
|
|
412
|
+
}],
|
|
413
|
+
offset: offset + selectionPoint.offset
|
|
414
|
+
};
|
|
415
|
+
offset += child.text.length;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
function isKeyedSegment$1(segment) {
|
|
420
|
+
return typeof segment == "object" && segment !== null && "_key" in segment;
|
|
421
|
+
}
|
|
422
|
+
function reverseSelection(selection) {
|
|
423
|
+
return selection && (selection.backward ? {
|
|
424
|
+
anchor: selection.focus,
|
|
425
|
+
focus: selection.anchor,
|
|
426
|
+
backward: !1
|
|
427
|
+
} : {
|
|
428
|
+
anchor: selection.focus,
|
|
429
|
+
focus: selection.anchor,
|
|
430
|
+
backward: !0
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
function getSelectionText({
|
|
434
|
+
value,
|
|
435
|
+
selection
|
|
436
|
+
}) {
|
|
437
|
+
let text = "";
|
|
438
|
+
if (!value || !selection)
|
|
439
|
+
return text;
|
|
440
|
+
const forwardSelection = selection.backward ? reverseSelection(selection) : selection;
|
|
441
|
+
if (!forwardSelection)
|
|
442
|
+
return text;
|
|
443
|
+
for (const block of value)
|
|
444
|
+
if (!(isKeyedSegment$1(forwardSelection.anchor.path[0]) && block._key !== forwardSelection.anchor.path[0]._key) && isPortableTextTextBlock(block)) {
|
|
445
|
+
for (const child of block.children)
|
|
446
|
+
if (isPortableTextSpan$1(child)) {
|
|
447
|
+
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) {
|
|
448
|
+
text = text + child.text.slice(forwardSelection.anchor.offset, forwardSelection.focus.offset);
|
|
449
|
+
break;
|
|
450
|
+
}
|
|
451
|
+
if (isKeyedSegment$1(forwardSelection.anchor.path[2]) && child._key === forwardSelection.anchor.path[2]._key) {
|
|
452
|
+
text = text + child.text.slice(forwardSelection.anchor.offset);
|
|
453
|
+
continue;
|
|
454
|
+
}
|
|
455
|
+
if (isKeyedSegment$1(forwardSelection.focus.path[2]) && child._key === forwardSelection.focus.path[2]._key) {
|
|
456
|
+
text = text + child.text.slice(0, forwardSelection.focus.offset);
|
|
457
|
+
break;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
if (isKeyedSegment$1(forwardSelection.focus.path[0]) && block._key === forwardSelection.focus.path[0]._key)
|
|
461
|
+
break;
|
|
462
|
+
}
|
|
463
|
+
return text;
|
|
464
|
+
}
|
|
465
|
+
function getStartPoint({
|
|
466
|
+
node,
|
|
467
|
+
path
|
|
468
|
+
}) {
|
|
469
|
+
return isPortableTextTextBlock(node) ? {
|
|
470
|
+
path: [...path, "children", {
|
|
471
|
+
_key: node.children[0]._key
|
|
472
|
+
}],
|
|
473
|
+
offset: 0
|
|
474
|
+
} : {
|
|
475
|
+
path,
|
|
476
|
+
offset: 0
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
function getBlockTextBefore({
|
|
480
|
+
value,
|
|
481
|
+
point
|
|
482
|
+
}) {
|
|
483
|
+
const key = isKeyedSegment$1(point.path[0]) ? point.path[0]._key : void 0, block = key ? value.find((block2) => block2._key === key) : void 0;
|
|
484
|
+
if (!block)
|
|
485
|
+
return "";
|
|
486
|
+
const startPoint = getStartPoint({
|
|
487
|
+
node: block,
|
|
488
|
+
path: [{
|
|
489
|
+
_key: block._key
|
|
490
|
+
}]
|
|
491
|
+
});
|
|
492
|
+
return getSelectionText({
|
|
493
|
+
value,
|
|
494
|
+
selection: {
|
|
495
|
+
anchor: startPoint,
|
|
496
|
+
focus: point
|
|
497
|
+
}
|
|
498
|
+
});
|
|
393
499
|
}
|
|
394
500
|
function createMarkdownBehaviors(config) {
|
|
395
501
|
const automaticBlockquoteOnSpace = {
|
|
@@ -403,12 +509,24 @@ function createMarkdownBehaviors(config) {
|
|
|
403
509
|
const selectionCollapsed = selectionIsCollapsed(context), focusTextBlock = getFocusTextBlock(context), focusSpan = getFocusSpan(context);
|
|
404
510
|
if (!selectionCollapsed || !focusTextBlock || !focusSpan)
|
|
405
511
|
return !1;
|
|
406
|
-
const
|
|
512
|
+
const blockOffset = spanSelectionPointToBlockOffset({
|
|
513
|
+
value: context.value,
|
|
514
|
+
selectionPoint: {
|
|
515
|
+
path: [{
|
|
516
|
+
_key: focusTextBlock.node._key
|
|
517
|
+
}, "children", {
|
|
518
|
+
_key: focusSpan.node._key
|
|
519
|
+
}],
|
|
520
|
+
offset: context.selection.focus.offset
|
|
521
|
+
}
|
|
522
|
+
});
|
|
523
|
+
if (!blockOffset)
|
|
524
|
+
return !1;
|
|
525
|
+
const blockText = getTextBlockText(focusTextBlock.node), caretAtTheEndOfQuote = blockOffset.offset === 1, looksLikeMarkdownQuote = /^>/.test(blockText), blockquoteStyle = config.blockquoteStyle?.({
|
|
407
526
|
schema: context.schema
|
|
408
527
|
});
|
|
409
528
|
return caretAtTheEndOfQuote && looksLikeMarkdownQuote && blockquoteStyle !== void 0 ? {
|
|
410
529
|
focusTextBlock,
|
|
411
|
-
focusSpan,
|
|
412
530
|
style: blockquoteStyle
|
|
413
531
|
} : !1;
|
|
414
532
|
},
|
|
@@ -417,7 +535,6 @@ function createMarkdownBehaviors(config) {
|
|
|
417
535
|
text: " "
|
|
418
536
|
}], (_, {
|
|
419
537
|
focusTextBlock,
|
|
420
|
-
focusSpan,
|
|
421
538
|
style
|
|
422
539
|
}) => [{
|
|
423
540
|
type: "unset block",
|
|
@@ -428,19 +545,17 @@ function createMarkdownBehaviors(config) {
|
|
|
428
545
|
style,
|
|
429
546
|
paths: [focusTextBlock.path]
|
|
430
547
|
}, {
|
|
431
|
-
type: "delete",
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
offset: 2
|
|
440
|
-
}
|
|
548
|
+
type: "delete text",
|
|
549
|
+
anchor: {
|
|
550
|
+
path: focusTextBlock.path,
|
|
551
|
+
offset: 0
|
|
552
|
+
},
|
|
553
|
+
focus: {
|
|
554
|
+
path: focusTextBlock.path,
|
|
555
|
+
offset: 2
|
|
441
556
|
}
|
|
442
557
|
}]]
|
|
443
|
-
},
|
|
558
|
+
}, automaticHr = {
|
|
444
559
|
on: "insert text",
|
|
445
560
|
guard: ({
|
|
446
561
|
context,
|
|
@@ -449,16 +564,29 @@ function createMarkdownBehaviors(config) {
|
|
|
449
564
|
const hrCharacter = event.text === "-" ? "-" : event.text === "*" ? "*" : event.text === "_" ? "_" : void 0;
|
|
450
565
|
if (hrCharacter === void 0)
|
|
451
566
|
return !1;
|
|
452
|
-
const
|
|
567
|
+
const hrObject = config.horizontalRuleObject?.({
|
|
453
568
|
schema: context.schema
|
|
454
569
|
}), focusBlock = getFocusTextBlock(context), selectionCollapsed = selectionIsCollapsed(context);
|
|
455
|
-
if (!
|
|
570
|
+
if (!hrObject || !focusBlock || !selectionCollapsed)
|
|
456
571
|
return !1;
|
|
457
|
-
const
|
|
458
|
-
|
|
459
|
-
|
|
572
|
+
const textBefore = getBlockTextBefore({
|
|
573
|
+
value: context.value,
|
|
574
|
+
point: context.selection.focus
|
|
575
|
+
}), hrBlockOffsets = {
|
|
576
|
+
anchor: {
|
|
577
|
+
path: focusBlock.path,
|
|
578
|
+
offset: 0
|
|
579
|
+
},
|
|
580
|
+
focus: {
|
|
581
|
+
path: focusBlock.path,
|
|
582
|
+
offset: 3
|
|
583
|
+
}
|
|
584
|
+
};
|
|
585
|
+
return textBefore === `${hrCharacter}${hrCharacter}` ? {
|
|
586
|
+
hrObject,
|
|
460
587
|
focusBlock,
|
|
461
|
-
hrCharacter
|
|
588
|
+
hrCharacter,
|
|
589
|
+
hrBlockOffsets
|
|
462
590
|
} : !1;
|
|
463
591
|
},
|
|
464
592
|
actions: [(_, {
|
|
@@ -467,26 +595,56 @@ function createMarkdownBehaviors(config) {
|
|
|
467
595
|
type: "insert text",
|
|
468
596
|
text: hrCharacter
|
|
469
597
|
}], (_, {
|
|
470
|
-
|
|
471
|
-
|
|
598
|
+
hrObject,
|
|
599
|
+
hrBlockOffsets
|
|
472
600
|
}) => [{
|
|
473
601
|
type: "insert block object",
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
type: "delete",
|
|
477
|
-
selection: {
|
|
478
|
-
anchor: {
|
|
479
|
-
path: focusBlock.path,
|
|
480
|
-
offset: 0
|
|
481
|
-
},
|
|
482
|
-
focus: {
|
|
483
|
-
path: focusBlock.path,
|
|
484
|
-
offset: 0
|
|
485
|
-
}
|
|
486
|
-
}
|
|
602
|
+
placement: "before",
|
|
603
|
+
blockObject: hrObject
|
|
487
604
|
}, {
|
|
605
|
+
type: "delete text",
|
|
606
|
+
...hrBlockOffsets
|
|
607
|
+
}]]
|
|
608
|
+
}, automaticHrOnPaste = {
|
|
609
|
+
on: "paste",
|
|
610
|
+
guard: ({
|
|
611
|
+
context,
|
|
612
|
+
event
|
|
613
|
+
}) => {
|
|
614
|
+
const text = event.clipboardData.getData("text/plain"), hrRegExp = /^(---)$|(___)$|(\*\*\*)$/gm, hrCharacters = text.match(hrRegExp)?.[0], hrObject = config.horizontalRuleObject?.({
|
|
615
|
+
schema: context.schema
|
|
616
|
+
}), focusBlock = getFocusBlock(context);
|
|
617
|
+
return !hrCharacters || !hrObject || !focusBlock ? !1 : {
|
|
618
|
+
hrCharacters,
|
|
619
|
+
hrObject,
|
|
620
|
+
focusBlock
|
|
621
|
+
};
|
|
622
|
+
},
|
|
623
|
+
actions: [(_, {
|
|
624
|
+
hrCharacters
|
|
625
|
+
}) => [{
|
|
626
|
+
type: "insert text",
|
|
627
|
+
text: hrCharacters
|
|
628
|
+
}], (_, {
|
|
629
|
+
hrObject,
|
|
630
|
+
focusBlock
|
|
631
|
+
}) => isPortableTextTextBlock(focusBlock.node) ? [{
|
|
488
632
|
type: "insert text block",
|
|
489
|
-
|
|
633
|
+
textBlock: {
|
|
634
|
+
children: focusBlock.node.children
|
|
635
|
+
},
|
|
636
|
+
placement: "after"
|
|
637
|
+
}, {
|
|
638
|
+
type: "insert block object",
|
|
639
|
+
blockObject: hrObject,
|
|
640
|
+
placement: "after"
|
|
641
|
+
}, {
|
|
642
|
+
type: "delete block",
|
|
643
|
+
blockPath: focusBlock.path
|
|
644
|
+
}] : [{
|
|
645
|
+
type: "insert block object",
|
|
646
|
+
blockObject: hrObject,
|
|
647
|
+
placement: "after"
|
|
490
648
|
}]]
|
|
491
649
|
}, automaticHeadingOnSpace = {
|
|
492
650
|
on: "insert text",
|
|
@@ -499,8 +657,21 @@ function createMarkdownBehaviors(config) {
|
|
|
499
657
|
const selectionCollapsed = selectionIsCollapsed(context), focusTextBlock = getFocusTextBlock(context), focusSpan = getFocusSpan(context);
|
|
500
658
|
if (!selectionCollapsed || !focusTextBlock || !focusSpan)
|
|
501
659
|
return !1;
|
|
502
|
-
const
|
|
503
|
-
|
|
660
|
+
const blockOffset = spanSelectionPointToBlockOffset({
|
|
661
|
+
value: context.value,
|
|
662
|
+
selectionPoint: {
|
|
663
|
+
path: [{
|
|
664
|
+
_key: focusTextBlock.node._key
|
|
665
|
+
}, "children", {
|
|
666
|
+
_key: focusSpan.node._key
|
|
667
|
+
}],
|
|
668
|
+
offset: context.selection.focus.offset
|
|
669
|
+
}
|
|
670
|
+
});
|
|
671
|
+
if (!blockOffset)
|
|
672
|
+
return !1;
|
|
673
|
+
const blockText = getTextBlockText(focusTextBlock.node), markdownHeadingSearch = /^#+/.exec(blockText), level = markdownHeadingSearch ? markdownHeadingSearch[0].length : void 0;
|
|
674
|
+
if (blockOffset.offset !== level)
|
|
504
675
|
return !1;
|
|
505
676
|
const style = level !== void 0 ? config.headingStyle?.({
|
|
506
677
|
schema: context.schema,
|
|
@@ -508,7 +679,6 @@ function createMarkdownBehaviors(config) {
|
|
|
508
679
|
}) : void 0;
|
|
509
680
|
return level !== void 0 && style !== void 0 ? {
|
|
510
681
|
focusTextBlock,
|
|
511
|
-
focusSpan,
|
|
512
682
|
style,
|
|
513
683
|
level
|
|
514
684
|
} : !1;
|
|
@@ -518,7 +688,6 @@ function createMarkdownBehaviors(config) {
|
|
|
518
688
|
text: " "
|
|
519
689
|
}], (_, {
|
|
520
690
|
focusTextBlock,
|
|
521
|
-
focusSpan,
|
|
522
691
|
style,
|
|
523
692
|
level
|
|
524
693
|
}) => [{
|
|
@@ -530,16 +699,14 @@ function createMarkdownBehaviors(config) {
|
|
|
530
699
|
style,
|
|
531
700
|
paths: [focusTextBlock.path]
|
|
532
701
|
}, {
|
|
533
|
-
type: "delete",
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
offset: level + 1
|
|
542
|
-
}
|
|
702
|
+
type: "delete text",
|
|
703
|
+
anchor: {
|
|
704
|
+
path: focusTextBlock.path,
|
|
705
|
+
offset: 0
|
|
706
|
+
},
|
|
707
|
+
focus: {
|
|
708
|
+
path: focusTextBlock.path,
|
|
709
|
+
offset: level + 1
|
|
543
710
|
}
|
|
544
711
|
}]]
|
|
545
712
|
}, clearStyleOnBackspace = {
|
|
@@ -577,15 +744,27 @@ function createMarkdownBehaviors(config) {
|
|
|
577
744
|
const selectionCollapsed = selectionIsCollapsed(context), focusTextBlock = getFocusTextBlock(context), focusSpan = getFocusSpan(context);
|
|
578
745
|
if (!selectionCollapsed || !focusTextBlock || !focusSpan)
|
|
579
746
|
return !1;
|
|
580
|
-
const
|
|
747
|
+
const blockOffset = spanSelectionPointToBlockOffset({
|
|
748
|
+
value: context.value,
|
|
749
|
+
selectionPoint: {
|
|
750
|
+
path: [{
|
|
751
|
+
_key: focusTextBlock.node._key
|
|
752
|
+
}, "children", {
|
|
753
|
+
_key: focusSpan.node._key
|
|
754
|
+
}],
|
|
755
|
+
offset: context.selection.focus.offset
|
|
756
|
+
}
|
|
757
|
+
});
|
|
758
|
+
if (!blockOffset)
|
|
759
|
+
return !1;
|
|
760
|
+
const blockText = getTextBlockText(focusTextBlock.node), defaultStyle = config.defaultStyle?.({
|
|
581
761
|
schema: context.schema
|
|
582
|
-
}), looksLikeUnorderedList = /^(-|\*)/.test(
|
|
762
|
+
}), looksLikeUnorderedList = /^(-|\*)/.test(blockText), unorderedListStyle = config.unorderedListStyle?.({
|
|
583
763
|
schema: context.schema
|
|
584
|
-
}), caretAtTheEndOfUnorderedList =
|
|
764
|
+
}), caretAtTheEndOfUnorderedList = blockOffset.offset === 1;
|
|
585
765
|
if (defaultStyle && caretAtTheEndOfUnorderedList && looksLikeUnorderedList && unorderedListStyle !== void 0)
|
|
586
766
|
return {
|
|
587
767
|
focusTextBlock,
|
|
588
|
-
focusSpan,
|
|
589
768
|
listItem: unorderedListStyle,
|
|
590
769
|
listItemLength: 1,
|
|
591
770
|
style: defaultStyle
|
|
@@ -595,7 +774,6 @@ function createMarkdownBehaviors(config) {
|
|
|
595
774
|
}), caretAtTheEndOfOrderedList = context.selection.focus.offset === 2;
|
|
596
775
|
return defaultStyle && caretAtTheEndOfOrderedList && looksLikeOrderedList && orderedListStyle !== void 0 ? {
|
|
597
776
|
focusTextBlock,
|
|
598
|
-
focusSpan,
|
|
599
777
|
listItem: orderedListStyle,
|
|
600
778
|
listItemLength: 2,
|
|
601
779
|
style: defaultStyle
|
|
@@ -606,7 +784,6 @@ function createMarkdownBehaviors(config) {
|
|
|
606
784
|
text: " "
|
|
607
785
|
}], (_, {
|
|
608
786
|
focusTextBlock,
|
|
609
|
-
focusSpan,
|
|
610
787
|
style,
|
|
611
788
|
listItem,
|
|
612
789
|
listItemLength
|
|
@@ -617,20 +794,18 @@ function createMarkdownBehaviors(config) {
|
|
|
617
794
|
style,
|
|
618
795
|
paths: [focusTextBlock.path]
|
|
619
796
|
}, {
|
|
620
|
-
type: "delete",
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
offset: listItemLength + 1
|
|
629
|
-
}
|
|
797
|
+
type: "delete text",
|
|
798
|
+
anchor: {
|
|
799
|
+
path: focusTextBlock.path,
|
|
800
|
+
offset: 0
|
|
801
|
+
},
|
|
802
|
+
focus: {
|
|
803
|
+
path: focusTextBlock.path,
|
|
804
|
+
offset: listItemLength + 1
|
|
630
805
|
}
|
|
631
806
|
}]]
|
|
632
807
|
};
|
|
633
|
-
return [automaticBlockquoteOnSpace,
|
|
808
|
+
return [automaticBlockquoteOnSpace, automaticHeadingOnSpace, automaticHr, automaticHrOnPaste, clearStyleOnBackspace, automaticListOnSpace];
|
|
634
809
|
}
|
|
635
810
|
function getPortableTextMemberSchemaTypes(portableTextType) {
|
|
636
811
|
if (!portableTextType)
|
|
@@ -4028,6 +4203,21 @@ function createWithPortableTextLists(types) {
|
|
|
4028
4203
|
}, editor;
|
|
4029
4204
|
};
|
|
4030
4205
|
}
|
|
4206
|
+
function isPortableTextSpan(node) {
|
|
4207
|
+
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"));
|
|
4208
|
+
}
|
|
4209
|
+
function isPortableTextBlock(node) {
|
|
4210
|
+
return (
|
|
4211
|
+
// A block doesn't _have_ to be named 'block' - to differentiate between
|
|
4212
|
+
// allowed child types and marks, one might name them differently
|
|
4213
|
+
typeof node._type == "string" && // Toolkit-types like nested spans are @-prefixed
|
|
4214
|
+
node._type[0] !== "@" && // `markDefs` isn't _required_ per say, but if it's there, it needs to be an array
|
|
4215
|
+
(!("markDefs" in node) || !node.markDefs || Array.isArray(node.markDefs) && // Every mark definition needs to have an `_key` to be mappable in child spans
|
|
4216
|
+
node.markDefs.every((def) => typeof def._key == "string")) && // `children` is required and needs to be an array
|
|
4217
|
+
"children" in node && Array.isArray(node.children) && // All children are objects with `_type` (usually spans, but can contain other stuff)
|
|
4218
|
+
node.children.every((child) => typeof child == "object" && "_type" in child)
|
|
4219
|
+
);
|
|
4220
|
+
}
|
|
4031
4221
|
function getPreviousSpan({
|
|
4032
4222
|
editor,
|
|
4033
4223
|
blockPath,
|
|
@@ -4728,7 +4918,66 @@ function createSlateEditor(config) {
|
|
|
4728
4918
|
};
|
|
4729
4919
|
return slateEditors.set(config.editorActor, slateEditor), slateEditor;
|
|
4730
4920
|
}
|
|
4731
|
-
|
|
4921
|
+
function insertBlock({
|
|
4922
|
+
block,
|
|
4923
|
+
placement,
|
|
4924
|
+
editor,
|
|
4925
|
+
schema
|
|
4926
|
+
}) {
|
|
4927
|
+
if (editor.selection) {
|
|
4928
|
+
const [focusBlock, focusBlockPath] = Array.from(Editor.nodes(editor, {
|
|
4929
|
+
at: editor.selection.focus.path.slice(0, 1),
|
|
4930
|
+
match: (n) => !Editor.isEditor(n)
|
|
4931
|
+
}))[0] ?? [void 0, void 0];
|
|
4932
|
+
if (placement === "after") {
|
|
4933
|
+
const nextPath = [focusBlockPath[0] + 1];
|
|
4934
|
+
Transforms.insertNodes(editor, block, {
|
|
4935
|
+
at: nextPath
|
|
4936
|
+
}), Transforms.select(editor, {
|
|
4937
|
+
anchor: {
|
|
4938
|
+
path: [nextPath[0], 0],
|
|
4939
|
+
offset: 0
|
|
4940
|
+
},
|
|
4941
|
+
focus: {
|
|
4942
|
+
path: [nextPath[0], 0],
|
|
4943
|
+
offset: 0
|
|
4944
|
+
}
|
|
4945
|
+
});
|
|
4946
|
+
} else placement === "before" ? Transforms.insertNodes(editor, block, {
|
|
4947
|
+
at: focusBlockPath
|
|
4948
|
+
}) : Editor.insertNode(editor, block);
|
|
4949
|
+
focusBlock && isEqualToEmptyEditor([focusBlock], schema) && Transforms.removeNodes(editor, {
|
|
4950
|
+
at: focusBlockPath
|
|
4951
|
+
});
|
|
4952
|
+
} else {
|
|
4953
|
+
const lastBlock = Array.from(Editor.nodes(editor, {
|
|
4954
|
+
match: (n) => !Editor.isEditor(n),
|
|
4955
|
+
at: [],
|
|
4956
|
+
reverse: !0
|
|
4957
|
+
}))[0];
|
|
4958
|
+
Editor.insertNode(editor, block), lastBlock && isEqualToEmptyEditor([lastBlock[0]], schema) && Transforms.removeNodes(editor, {
|
|
4959
|
+
at: lastBlock[1]
|
|
4960
|
+
});
|
|
4961
|
+
}
|
|
4962
|
+
}
|
|
4963
|
+
const insertBlockObjectActionImplementation = ({
|
|
4964
|
+
context,
|
|
4965
|
+
action
|
|
4966
|
+
}) => {
|
|
4967
|
+
const block = toSlateValue([{
|
|
4968
|
+
_key: context.keyGenerator(),
|
|
4969
|
+
_type: action.blockObject.name,
|
|
4970
|
+
...action.blockObject.value ? action.blockObject.value : {}
|
|
4971
|
+
}], {
|
|
4972
|
+
schemaTypes: context.schema
|
|
4973
|
+
})[0];
|
|
4974
|
+
insertBlock({
|
|
4975
|
+
block,
|
|
4976
|
+
placement: action.placement,
|
|
4977
|
+
editor: action.editor,
|
|
4978
|
+
schema: context.schema
|
|
4979
|
+
});
|
|
4980
|
+
}, debug$5 = debugWithName("API:editable");
|
|
4732
4981
|
function createEditableAPI(editor, editorActor) {
|
|
4733
4982
|
const types = editorActor.getSnapshot().context.schema;
|
|
4734
4983
|
return {
|
|
@@ -4817,18 +5066,21 @@ function createEditableAPI(editor, editorActor) {
|
|
|
4817
5066
|
at: editor.selection
|
|
4818
5067
|
}), editor.onChange(), toPortableTextRange(fromSlateValue(editor.children, types.block.name, KEY_TO_VALUE_ELEMENT.get(editor)), editor.selection, types)?.focus.path || [];
|
|
4819
5068
|
},
|
|
4820
|
-
insertBlock: (type, value) => insertBlockObjectActionImplementation({
|
|
5069
|
+
insertBlock: (type, value) => (insertBlockObjectActionImplementation({
|
|
4821
5070
|
context: {
|
|
4822
5071
|
keyGenerator: editorActor.getSnapshot().context.keyGenerator,
|
|
4823
5072
|
schema: types
|
|
4824
5073
|
},
|
|
4825
5074
|
action: {
|
|
4826
5075
|
type: "insert block object",
|
|
4827
|
-
|
|
4828
|
-
|
|
5076
|
+
blockObject: {
|
|
5077
|
+
name: type.name,
|
|
5078
|
+
value
|
|
5079
|
+
},
|
|
5080
|
+
placement: "auto",
|
|
4829
5081
|
editor
|
|
4830
5082
|
}
|
|
4831
|
-
}),
|
|
5083
|
+
}), editor.onChange(), toPortableTextRange(fromSlateValue(editor.children, types.block.name, KEY_TO_VALUE_ELEMENT.get(editor)), editor.selection, types)?.focus.path ?? []),
|
|
4832
5084
|
hasBlockStyle: (style) => {
|
|
4833
5085
|
try {
|
|
4834
5086
|
return editor.pteHasBlockStyle(style);
|
|
@@ -4998,35 +5250,6 @@ function createEditableAPI(editor, editorActor) {
|
|
|
4998
5250
|
}
|
|
4999
5251
|
};
|
|
5000
5252
|
}
|
|
5001
|
-
const insertBlockObjectActionImplementation = ({
|
|
5002
|
-
context,
|
|
5003
|
-
action
|
|
5004
|
-
}) => {
|
|
5005
|
-
const editor = action.editor, types = context.schema, block = toSlateValue([{
|
|
5006
|
-
_key: context.keyGenerator(),
|
|
5007
|
-
_type: action.name,
|
|
5008
|
-
...action.value ? action.value : {}
|
|
5009
|
-
}], {
|
|
5010
|
-
schemaTypes: context.schema
|
|
5011
|
-
})[0];
|
|
5012
|
-
if (!editor.selection) {
|
|
5013
|
-
const lastBlock = Array.from(Editor.nodes(editor, {
|
|
5014
|
-
match: (n) => !Editor.isEditor(n),
|
|
5015
|
-
at: [],
|
|
5016
|
-
reverse: !0
|
|
5017
|
-
}))[0];
|
|
5018
|
-
return Editor.insertNode(editor, block), lastBlock && isEqualToEmptyEditor([lastBlock[0]], types) && Transforms.removeNodes(editor, {
|
|
5019
|
-
at: lastBlock[1]
|
|
5020
|
-
}), editor.onChange(), toPortableTextRange(fromSlateValue(editor.children, types.block.name, KEY_TO_VALUE_ELEMENT.get(editor)), editor.selection, types)?.focus.path ?? [];
|
|
5021
|
-
}
|
|
5022
|
-
const focusBlock = Array.from(Editor.nodes(editor, {
|
|
5023
|
-
at: editor.selection.focus.path.slice(0, 1),
|
|
5024
|
-
match: (n) => n._type === types.block.name
|
|
5025
|
-
}))[0];
|
|
5026
|
-
return Editor.insertNode(editor, block), focusBlock && isEqualToEmptyEditor([focusBlock[0]], types) && Transforms.removeNodes(editor, {
|
|
5027
|
-
at: focusBlock[1]
|
|
5028
|
-
}), editor.onChange(), toPortableTextRange(fromSlateValue(editor.children, types.block.name, KEY_TO_VALUE_ELEMENT.get(editor)), editor.selection, types)?.focus.path || [];
|
|
5029
|
-
};
|
|
5030
5253
|
function isAnnotationActive({
|
|
5031
5254
|
editor,
|
|
5032
5255
|
annotation
|
|
@@ -5422,18 +5645,52 @@ const addAnnotationActionImplementation = ({
|
|
|
5422
5645
|
}) => {
|
|
5423
5646
|
deleteForward(action.editor, action.unit);
|
|
5424
5647
|
},
|
|
5425
|
-
delete: ({
|
|
5648
|
+
"delete block": ({
|
|
5649
|
+
action
|
|
5650
|
+
}) => {
|
|
5651
|
+
const range = toSlateRange({
|
|
5652
|
+
anchor: {
|
|
5653
|
+
path: action.blockPath,
|
|
5654
|
+
offset: 0
|
|
5655
|
+
},
|
|
5656
|
+
focus: {
|
|
5657
|
+
path: action.blockPath,
|
|
5658
|
+
offset: 0
|
|
5659
|
+
}
|
|
5660
|
+
}, action.editor);
|
|
5661
|
+
if (!range) {
|
|
5662
|
+
console.error("Unable to find Slate range from selection points");
|
|
5663
|
+
return;
|
|
5664
|
+
}
|
|
5665
|
+
Transforms.removeNodes(action.editor, {
|
|
5666
|
+
at: range
|
|
5667
|
+
});
|
|
5668
|
+
},
|
|
5669
|
+
"delete text": ({
|
|
5670
|
+
context,
|
|
5426
5671
|
action
|
|
5427
5672
|
}) => {
|
|
5428
|
-
const
|
|
5429
|
-
|
|
5430
|
-
|
|
5673
|
+
const value = fromSlateValue(action.editor.children, context.schema.block.name, KEY_TO_VALUE_ELEMENT.get(action.editor)), anchor = blockOffsetToSpanSelectionPoint({
|
|
5674
|
+
value,
|
|
5675
|
+
blockOffset: action.anchor
|
|
5676
|
+
}), focus = blockOffsetToSpanSelectionPoint({
|
|
5677
|
+
value,
|
|
5678
|
+
blockOffset: action.focus
|
|
5679
|
+
});
|
|
5680
|
+
if (!anchor || !focus) {
|
|
5681
|
+
console.error("Unable to find anchor or focus selection point");
|
|
5431
5682
|
return;
|
|
5432
5683
|
}
|
|
5433
|
-
|
|
5434
|
-
|
|
5435
|
-
|
|
5436
|
-
|
|
5684
|
+
const range = toSlateRange({
|
|
5685
|
+
anchor,
|
|
5686
|
+
focus
|
|
5687
|
+
}, action.editor);
|
|
5688
|
+
if (!range) {
|
|
5689
|
+
console.error("Unable to find Slate range from selection points");
|
|
5690
|
+
return;
|
|
5691
|
+
}
|
|
5692
|
+
Transforms.delete(action.editor, {
|
|
5693
|
+
at: range
|
|
5437
5694
|
});
|
|
5438
5695
|
},
|
|
5439
5696
|
"insert block object": insertBlockObjectActionImplementation,
|
|
@@ -5449,16 +5706,27 @@ const addAnnotationActionImplementation = ({
|
|
|
5449
5706
|
context,
|
|
5450
5707
|
action
|
|
5451
5708
|
}) => {
|
|
5452
|
-
|
|
5709
|
+
const block = toSlateValue([{
|
|
5453
5710
|
_key: context.keyGenerator(),
|
|
5454
5711
|
_type: context.schema.block.name,
|
|
5455
5712
|
style: context.schema.styles[0].value ?? "normal",
|
|
5456
5713
|
markDefs: [],
|
|
5457
|
-
children:
|
|
5714
|
+
children: action.textBlock?.children?.map((child) => ({
|
|
5715
|
+
...child,
|
|
5716
|
+
_key: context.keyGenerator()
|
|
5717
|
+
})) ?? [{
|
|
5718
|
+
_type: context.schema.span.name,
|
|
5458
5719
|
_key: context.keyGenerator(),
|
|
5459
|
-
_type: "span",
|
|
5460
5720
|
text: ""
|
|
5461
5721
|
}]
|
|
5722
|
+
}], {
|
|
5723
|
+
schemaTypes: context.schema
|
|
5724
|
+
})[0];
|
|
5725
|
+
insertBlock({
|
|
5726
|
+
block,
|
|
5727
|
+
editor: action.editor,
|
|
5728
|
+
schema: context.schema,
|
|
5729
|
+
placement: action.placement
|
|
5462
5730
|
});
|
|
5463
5731
|
},
|
|
5464
5732
|
effect: ({
|
|
@@ -5493,8 +5761,15 @@ function performAction({
|
|
|
5493
5761
|
action
|
|
5494
5762
|
}) {
|
|
5495
5763
|
switch (action.type) {
|
|
5496
|
-
case "delete": {
|
|
5497
|
-
behaviorActionImplementations
|
|
5764
|
+
case "delete block": {
|
|
5765
|
+
behaviorActionImplementations["delete block"]({
|
|
5766
|
+
context,
|
|
5767
|
+
action
|
|
5768
|
+
});
|
|
5769
|
+
break;
|
|
5770
|
+
}
|
|
5771
|
+
case "delete text": {
|
|
5772
|
+
behaviorActionImplementations["delete text"]({
|
|
5498
5773
|
context,
|
|
5499
5774
|
action
|
|
5500
5775
|
});
|