@portabletext/editor 1.50.2 → 1.50.4
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/behaviors/index.d.cts +1 -0
- package/lib/behaviors/index.d.ts +1 -0
- package/lib/index.cjs +577 -286
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +15 -2
- package/lib/index.d.ts +15 -2
- package/lib/index.js +584 -292
- package/lib/index.js.map +1 -1
- package/lib/plugins/index.d.cts +7 -0
- package/lib/plugins/index.d.ts +7 -0
- package/lib/selectors/index.d.cts +1 -0
- package/lib/selectors/index.d.ts +1 -0
- package/lib/utils/index.d.cts +1 -0
- package/lib/utils/index.d.ts +1 -0
- package/package.json +14 -13
- package/src/editor/PortableTextEditor.tsx +22 -22
- package/src/editor/create-slate-editor.tsx +9 -1
- package/src/editor/editor-selector.ts +1 -5
- package/src/editor/editor-snapshot.ts +1 -3
- package/src/editor/plugins/createWithPatches.ts +37 -75
- package/src/editor/plugins/slate-plugin.update-value.ts +30 -0
- package/src/editor/plugins/with-plugins.ts +8 -4
- package/src/editor/relay-machine.ts +9 -0
- package/src/internal-utils/apply-operation-to-portable-text.test.ts +175 -0
- package/src/internal-utils/apply-operation-to-portable-text.ts +435 -0
- package/src/internal-utils/create-placeholder-block.ts +20 -0
- package/src/internal-utils/{__tests__/operationToPatches.test.ts → operation-to-patches.test.ts} +44 -39
- package/src/internal-utils/operation-to-patches.ts +467 -0
- package/src/internal-utils/portable-text-node.ts +209 -0
- package/src/types/editor.ts +8 -2
- package/src/internal-utils/__tests__/patchToOperations.test.ts +0 -312
- package/src/internal-utils/operationToPatches.ts +0 -489
- package/src/internal-utils/slate-children-to-blocks.ts +0 -49
package/lib/index.js
CHANGED
|
@@ -7,9 +7,9 @@ import { useSelector, useActorRef } from "@xstate/react";
|
|
|
7
7
|
import noop from "lodash/noop.js";
|
|
8
8
|
import { Element as Element$1, Text, Range, Editor, Node, Point, Transforms, Path, Operation, deleteBackward, deleteForward, createEditor } from "slate";
|
|
9
9
|
import { useSlateStatic, useSelected, withReact, ReactEditor, Slate, useSlate, Editable } from "slate-react";
|
|
10
|
-
import debug$
|
|
10
|
+
import debug$i from "debug";
|
|
11
11
|
import { getBlockEndPoint, isEmptyTextBlock, isEqualSelectionPoints } from "./_chunks-es/util.is-equal-selection-points.js";
|
|
12
|
-
import { getBlockStartPoint, isKeyedSegment as isKeyedSegment$1, parseInlineObject, parseTextBlock, parseBlockObject, parseBlock, sliceBlocks, isTextBlock, parseAnnotation, blockOffsetToSpanSelectionPoint, isSpan$1 as isSpan, isListBlock, getTextBlockText, parseBlocks } from "./_chunks-es/util.slice-blocks.js";
|
|
12
|
+
import { getBlockStartPoint, isKeyedSegment as isKeyedSegment$1, parseInlineObject, parseTextBlock, parseBlockObject, parseBlock, sliceBlocks, isTextBlock, parseAnnotation, blockOffsetToSpanSelectionPoint, isSpan$1 as isSpan, isListBlock, isTypedObject, getTextBlockText, parseBlocks } from "./_chunks-es/util.slice-blocks.js";
|
|
13
13
|
import { isSelectionCollapsed, getFocusTextBlock, getFocusSpan, getSelectedBlocks, isSelectionExpanded, getSelectionStartBlock as getSelectionStartBlock$1, getSelectionEndBlock as getSelectionEndBlock$1, getFocusBlock as getFocusBlock$1, getFocusBlockObject, getPreviousBlock, getNextBlock, getFirstBlock as getFirstBlock$1, getLastBlock as getLastBlock$1, getFocusListBlock } from "./_chunks-es/selector.is-selection-expanded.js";
|
|
14
14
|
import { getFocusInlineObject, isOverlappingSelection, isSelectingEntireBlocks, getTrimmedSelection, getCaretWordSelection, isAtTheEndOfBlock, isAtTheStartOfBlock, isActiveAnnotation, isActiveDecorator, getSelectedTextBlocks, isActiveListItem, isActiveStyle, getActiveAnnotations } from "./_chunks-es/selector.is-selecting-entire-blocks.js";
|
|
15
15
|
import { DOMEditor, isDOMNode } from "slate-dom";
|
|
@@ -24,13 +24,14 @@ import { setup, assign, enqueueActions, emit, assertEvent, stateIn, fromCallback
|
|
|
24
24
|
import { htmlToBlocks } from "@portabletext/block-tools";
|
|
25
25
|
import { toHTML } from "@portabletext/to-html";
|
|
26
26
|
import { Schema } from "@sanity/schema";
|
|
27
|
-
import { insert, unset, set, diffMatchPatch as diffMatchPatch$1, setIfMissing, applyAll } from "@portabletext/patches";
|
|
28
|
-
import get from "lodash/get.js";
|
|
29
|
-
import isUndefined from "lodash/isUndefined.js";
|
|
30
|
-
import omitBy from "lodash/omitBy.js";
|
|
31
27
|
import flatten from "lodash/flatten.js";
|
|
32
28
|
import omit from "lodash/omit.js";
|
|
33
29
|
import { blockOffsetsToSelection } from "./_chunks-es/util.child-selection-point-to-block-offset.js";
|
|
30
|
+
import { applyAll, unset, insert, set, setIfMissing, diffMatchPatch as diffMatchPatch$1 } from "@portabletext/patches";
|
|
31
|
+
import get from "lodash/get.js";
|
|
32
|
+
import isUndefined from "lodash/isUndefined.js";
|
|
33
|
+
import omitBy from "lodash/omitBy.js";
|
|
34
|
+
import { createDraft, finishDraft } from "immer";
|
|
34
35
|
import startCase from "lodash.startcase";
|
|
35
36
|
import isPlainObject from "lodash/isPlainObject.js";
|
|
36
37
|
function EditorEventListener(props) {
|
|
@@ -59,10 +60,10 @@ function getCompoundClientRect(nodes) {
|
|
|
59
60
|
return new DOMRect(left, top, right - left, bottom - top);
|
|
60
61
|
}
|
|
61
62
|
const rootName = "sanity-pte:";
|
|
62
|
-
debug$
|
|
63
|
+
debug$i(rootName);
|
|
63
64
|
function debugWithName(name) {
|
|
64
65
|
const namespace = `${rootName}${name}`;
|
|
65
|
-
return debug$
|
|
66
|
+
return debug$i && debug$i.enabled(namespace) ? debug$i(namespace) : debug$i(rootName);
|
|
66
67
|
}
|
|
67
68
|
function getDragSelection({
|
|
68
69
|
eventSelection,
|
|
@@ -1376,226 +1377,18 @@ function compileType(rawType) {
|
|
|
1376
1377
|
types: [rawType]
|
|
1377
1378
|
}).get(rawType.name);
|
|
1378
1379
|
}
|
|
1379
|
-
|
|
1380
|
-
function createOperationToPatches(editorActor) {
|
|
1381
|
-
const textBlockName = editorActor.getSnapshot().context.schema.block.name;
|
|
1382
|
-
function insertTextPatch(editor, operation, beforeValue) {
|
|
1383
|
-
debug$i.enabled && debug$i("Operation", JSON.stringify(operation, null, 2));
|
|
1384
|
-
const block = editor.isTextBlock(editor.children[operation.path[0]]) && editor.children[operation.path[0]];
|
|
1385
|
-
if (!block)
|
|
1386
|
-
throw new Error("Could not find block");
|
|
1387
|
-
const textChild = editor.isTextBlock(block) && editor.isTextSpan(block.children[operation.path[1]]) && block.children[operation.path[1]];
|
|
1388
|
-
if (!textChild)
|
|
1389
|
-
throw new Error("Could not find child");
|
|
1390
|
-
const path = [{
|
|
1391
|
-
_key: block._key
|
|
1392
|
-
}, "children", {
|
|
1393
|
-
_key: textChild._key
|
|
1394
|
-
}, "text"], prevBlock = beforeValue[operation.path[0]], prevChild = editor.isTextBlock(prevBlock) && prevBlock.children[operation.path[1]], prevText = editor.isTextSpan(prevChild) ? prevChild.text : "", patch = diffMatchPatch$1(prevText, textChild.text, path);
|
|
1395
|
-
return patch.value.length ? [patch] : [];
|
|
1396
|
-
}
|
|
1397
|
-
function removeTextPatch(editor, operation, beforeValue) {
|
|
1398
|
-
const block = editor && editor.children[operation.path[0]];
|
|
1399
|
-
if (!block)
|
|
1400
|
-
throw new Error("Could not find block");
|
|
1401
|
-
const child = editor.isTextBlock(block) && block.children[operation.path[1]] || void 0, textChild = editor.isTextSpan(child) ? child : void 0;
|
|
1402
|
-
if (child && !textChild)
|
|
1403
|
-
throw new Error("Expected span");
|
|
1404
|
-
if (!textChild)
|
|
1405
|
-
throw new Error("Could not find child");
|
|
1406
|
-
const path = [{
|
|
1407
|
-
_key: block._key
|
|
1408
|
-
}, "children", {
|
|
1409
|
-
_key: textChild._key
|
|
1410
|
-
}, "text"], beforeBlock = beforeValue[operation.path[0]], prevTextChild = editor.isTextBlock(beforeBlock) && beforeBlock.children[operation.path[1]], prevText = editor.isTextSpan(prevTextChild) && prevTextChild.text, patch = diffMatchPatch$1(prevText || "", textChild.text, path);
|
|
1411
|
-
return patch.value ? [patch] : [];
|
|
1412
|
-
}
|
|
1413
|
-
function setNodePatch(editor, operation) {
|
|
1414
|
-
if (operation.path.length === 1) {
|
|
1415
|
-
const block = editor.children[operation.path[0]];
|
|
1416
|
-
if (typeof block._key != "string")
|
|
1417
|
-
throw new Error("Expected block to have a _key");
|
|
1418
|
-
const setNode = omitBy({
|
|
1419
|
-
...editor.children[operation.path[0]],
|
|
1420
|
-
...operation.newProperties
|
|
1421
|
-
}, isUndefined);
|
|
1422
|
-
return [set(fromSlateValue([setNode], textBlockName)[0], [{
|
|
1423
|
-
_key: block._key
|
|
1424
|
-
}])];
|
|
1425
|
-
} else if (operation.path.length === 2) {
|
|
1426
|
-
const block = editor.children[operation.path[0]];
|
|
1427
|
-
if (editor.isTextBlock(block)) {
|
|
1428
|
-
const child = block.children[operation.path[1]];
|
|
1429
|
-
if (child) {
|
|
1430
|
-
const blockKey = block._key, childKey = child._key, patches = [], keys = Object.keys(operation.newProperties);
|
|
1431
|
-
return keys.forEach((keyName) => {
|
|
1432
|
-
if (keys.length === 1 && keyName === "_key") {
|
|
1433
|
-
const val = get(operation.newProperties, keyName);
|
|
1434
|
-
patches.push(set(val, [{
|
|
1435
|
-
_key: blockKey
|
|
1436
|
-
}, "children", block.children.indexOf(child), keyName]));
|
|
1437
|
-
} else {
|
|
1438
|
-
const val = get(operation.newProperties, keyName);
|
|
1439
|
-
patches.push(set(val, [{
|
|
1440
|
-
_key: blockKey
|
|
1441
|
-
}, "children", {
|
|
1442
|
-
_key: childKey
|
|
1443
|
-
}, keyName]));
|
|
1444
|
-
}
|
|
1445
|
-
}), patches;
|
|
1446
|
-
}
|
|
1447
|
-
throw new Error("Could not find a valid child");
|
|
1448
|
-
}
|
|
1449
|
-
throw new Error("Could not find a valid block");
|
|
1450
|
-
} else
|
|
1451
|
-
throw new Error(`Unexpected path encountered: ${JSON.stringify(operation.path)}`);
|
|
1452
|
-
}
|
|
1453
|
-
function insertNodePatch(editor, operation, beforeValue) {
|
|
1454
|
-
const block = beforeValue[operation.path[0]], isTextBlock2 = editor.isTextBlock(block);
|
|
1455
|
-
if (operation.path.length === 1) {
|
|
1456
|
-
const position = operation.path[0] === 0 ? "before" : "after", beforeBlock = beforeValue[operation.path[0] - 1], targetKey = operation.path[0] === 0 ? block?._key : beforeBlock?._key;
|
|
1457
|
-
return targetKey ? [insert([fromSlateValue([operation.node], textBlockName)[0]], position, [{
|
|
1458
|
-
_key: targetKey
|
|
1459
|
-
}])] : [setIfMissing(beforeValue, []), insert([fromSlateValue([operation.node], textBlockName)[0]], "before", [operation.path[0]])];
|
|
1460
|
-
} else if (isTextBlock2 && operation.path.length === 2 && editor.children[operation.path[0]]) {
|
|
1461
|
-
const position = block.children.length === 0 || !block.children[operation.path[1] - 1] ? "before" : "after", node = {
|
|
1462
|
-
...operation.node
|
|
1463
|
-
};
|
|
1464
|
-
!node._type && Text.isText(node) && (node._type = "span", node.marks = []);
|
|
1465
|
-
const child = fromSlateValue([{
|
|
1466
|
-
_key: "bogus",
|
|
1467
|
-
_type: textBlockName,
|
|
1468
|
-
children: [node]
|
|
1469
|
-
}], textBlockName)[0].children[0];
|
|
1470
|
-
return [insert([child], position, [{
|
|
1471
|
-
_key: block._key
|
|
1472
|
-
}, "children", block.children.length <= 1 || !block.children[operation.path[1] - 1] ? 0 : {
|
|
1473
|
-
_key: block.children[operation.path[1] - 1]._key
|
|
1474
|
-
}])];
|
|
1475
|
-
}
|
|
1476
|
-
return debug$i("Something was inserted into a void block. Not producing editor patches."), [];
|
|
1477
|
-
}
|
|
1478
|
-
function splitNodePatch(editor, operation, beforeValue) {
|
|
1479
|
-
const patches = [], splitBlock = editor.children[operation.path[0]];
|
|
1480
|
-
if (!editor.isTextBlock(splitBlock))
|
|
1481
|
-
throw new Error(`Block with path ${JSON.stringify(operation.path[0])} is not a text block and can't be split`);
|
|
1482
|
-
if (operation.path.length === 1) {
|
|
1483
|
-
const oldBlock = beforeValue[operation.path[0]];
|
|
1484
|
-
if (editor.isTextBlock(oldBlock)) {
|
|
1485
|
-
const targetValue = fromSlateValue([editor.children[operation.path[0] + 1]], textBlockName)[0];
|
|
1486
|
-
targetValue && (patches.push(insert([targetValue], "after", [{
|
|
1487
|
-
_key: splitBlock._key
|
|
1488
|
-
}])), oldBlock.children.slice(operation.position).forEach((span) => {
|
|
1489
|
-
const path = [{
|
|
1490
|
-
_key: oldBlock._key
|
|
1491
|
-
}, "children", {
|
|
1492
|
-
_key: span._key
|
|
1493
|
-
}];
|
|
1494
|
-
patches.push(unset(path));
|
|
1495
|
-
}));
|
|
1496
|
-
}
|
|
1497
|
-
return patches;
|
|
1498
|
-
}
|
|
1499
|
-
if (operation.path.length === 2) {
|
|
1500
|
-
const splitSpan = splitBlock.children[operation.path[1]];
|
|
1501
|
-
if (editor.isTextSpan(splitSpan)) {
|
|
1502
|
-
const targetSpans = fromSlateValue([{
|
|
1503
|
-
...splitBlock,
|
|
1504
|
-
children: splitBlock.children.slice(operation.path[1] + 1, operation.path[1] + 2)
|
|
1505
|
-
}], textBlockName)[0].children;
|
|
1506
|
-
patches.push(insert(targetSpans, "after", [{
|
|
1507
|
-
_key: splitBlock._key
|
|
1508
|
-
}, "children", {
|
|
1509
|
-
_key: splitSpan._key
|
|
1510
|
-
}])), patches.push(set(splitSpan.text, [{
|
|
1511
|
-
_key: splitBlock._key
|
|
1512
|
-
}, "children", {
|
|
1513
|
-
_key: splitSpan._key
|
|
1514
|
-
}, "text"]));
|
|
1515
|
-
}
|
|
1516
|
-
return patches;
|
|
1517
|
-
}
|
|
1518
|
-
return patches;
|
|
1519
|
-
}
|
|
1520
|
-
function removeNodePatch(editor, operation, beforeValue) {
|
|
1521
|
-
const block = beforeValue[operation.path[0]];
|
|
1522
|
-
if (operation.path.length === 1) {
|
|
1523
|
-
if (block && block._key)
|
|
1524
|
-
return [unset([{
|
|
1525
|
-
_key: block._key
|
|
1526
|
-
}])];
|
|
1527
|
-
throw new Error("Block not found");
|
|
1528
|
-
} else if (editor.isTextBlock(block) && operation.path.length === 2) {
|
|
1529
|
-
const spanToRemove = block.children[operation.path[1]];
|
|
1530
|
-
return spanToRemove ? block.children.filter((span) => span._key === operation.node._key).length > 1 ? (console.warn(`Multiple spans have \`_key\` ${operation.node._key}. It's ambiguous which one to remove.`, JSON.stringify(block, null, 2)), []) : [unset([{
|
|
1531
|
-
_key: block._key
|
|
1532
|
-
}, "children", {
|
|
1533
|
-
_key: spanToRemove._key
|
|
1534
|
-
}])] : (debug$i("Span not found in editor trying to remove node"), []);
|
|
1535
|
-
} else
|
|
1536
|
-
return debug$i("Not creating patch inside object block"), [];
|
|
1537
|
-
}
|
|
1538
|
-
function mergeNodePatch(editor, operation, beforeValue) {
|
|
1539
|
-
const patches = [], block = beforeValue[operation.path[0]], updatedBlock = editor.children[operation.path[0]];
|
|
1540
|
-
if (operation.path.length === 1)
|
|
1541
|
-
if (block?._key) {
|
|
1542
|
-
const newBlock = fromSlateValue([editor.children[operation.path[0] - 1]], textBlockName)[0];
|
|
1543
|
-
patches.push(set(newBlock, [{
|
|
1544
|
-
_key: newBlock._key
|
|
1545
|
-
}])), patches.push(unset([{
|
|
1546
|
-
_key: block._key
|
|
1547
|
-
}]));
|
|
1548
|
-
} else
|
|
1549
|
-
throw new Error("Target key not found!");
|
|
1550
|
-
else if (editor.isTextBlock(block) && editor.isTextBlock(updatedBlock) && operation.path.length === 2) {
|
|
1551
|
-
const updatedSpan = updatedBlock.children[operation.path[1] - 1] && editor.isTextSpan(updatedBlock.children[operation.path[1] - 1]) ? updatedBlock.children[operation.path[1] - 1] : void 0, removedSpan = block.children[operation.path[1]] && editor.isTextSpan(block.children[operation.path[1]]) ? block.children[operation.path[1]] : void 0;
|
|
1552
|
-
updatedSpan && (block.children.filter((span) => span._key === updatedSpan._key).length === 1 ? patches.push(set(updatedSpan.text, [{
|
|
1553
|
-
_key: block._key
|
|
1554
|
-
}, "children", {
|
|
1555
|
-
_key: updatedSpan._key
|
|
1556
|
-
}, "text"])) : console.warn(`Multiple spans have \`_key\` ${updatedSpan._key}. It's ambiguous which one to update.`, JSON.stringify(block, null, 2))), removedSpan && (block.children.filter((span) => span._key === removedSpan._key).length === 1 ? patches.push(unset([{
|
|
1557
|
-
_key: block._key
|
|
1558
|
-
}, "children", {
|
|
1559
|
-
_key: removedSpan._key
|
|
1560
|
-
}])) : console.warn(`Multiple spans have \`_key\` ${removedSpan._key}. It's ambiguous which one to remove.`, JSON.stringify(block, null, 2)));
|
|
1561
|
-
} else
|
|
1562
|
-
debug$i("Void nodes can't be merged, not creating any patches");
|
|
1563
|
-
return patches;
|
|
1564
|
-
}
|
|
1565
|
-
function moveNodePatch(editor, operation, beforeValue) {
|
|
1566
|
-
const patches = [], block = beforeValue[operation.path[0]], targetBlock = beforeValue[operation.newPath[0]];
|
|
1567
|
-
if (!targetBlock)
|
|
1568
|
-
return patches;
|
|
1569
|
-
if (operation.path.length === 1) {
|
|
1570
|
-
const position = operation.path[0] > operation.newPath[0] ? "before" : "after";
|
|
1571
|
-
patches.push(unset([{
|
|
1572
|
-
_key: block._key
|
|
1573
|
-
}])), patches.push(insert([fromSlateValue([block], textBlockName)[0]], position, [{
|
|
1574
|
-
_key: targetBlock._key
|
|
1575
|
-
}]));
|
|
1576
|
-
} else if (operation.path.length === 2 && editor.isTextBlock(block) && editor.isTextBlock(targetBlock)) {
|
|
1577
|
-
const child = block.children[operation.path[1]], targetChild = targetBlock.children[operation.newPath[1]], position = operation.newPath[1] === targetBlock.children.length ? "after" : "before", childToInsert = fromSlateValue([block], textBlockName)[0].children[operation.path[1]];
|
|
1578
|
-
patches.push(unset([{
|
|
1579
|
-
_key: block._key
|
|
1580
|
-
}, "children", {
|
|
1581
|
-
_key: child._key
|
|
1582
|
-
}])), patches.push(insert([childToInsert], position, [{
|
|
1583
|
-
_key: targetBlock._key
|
|
1584
|
-
}, "children", {
|
|
1585
|
-
_key: targetChild._key
|
|
1586
|
-
}]));
|
|
1587
|
-
}
|
|
1588
|
-
return patches;
|
|
1589
|
-
}
|
|
1380
|
+
function createPlaceholderBlock(context) {
|
|
1590
1381
|
return {
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1382
|
+
_type: context.schema.block.name,
|
|
1383
|
+
_key: context.keyGenerator(),
|
|
1384
|
+
style: context.schema.styles[0].name ?? "normal",
|
|
1385
|
+
markDefs: [],
|
|
1386
|
+
children: [{
|
|
1387
|
+
_type: context.schema.span.name,
|
|
1388
|
+
_key: context.keyGenerator(),
|
|
1389
|
+
text: "",
|
|
1390
|
+
marks: []
|
|
1391
|
+
}]
|
|
1599
1392
|
};
|
|
1600
1393
|
}
|
|
1601
1394
|
const insertTextOperationImplementation = ({
|
|
@@ -4439,6 +4232,254 @@ function findBlockAndChildFromPath(editor, path) {
|
|
|
4439
4232
|
childPath: void 0
|
|
4440
4233
|
};
|
|
4441
4234
|
}
|
|
4235
|
+
function insertTextPatch(schema, children, operation, beforeValue) {
|
|
4236
|
+
const block = isTextBlock({
|
|
4237
|
+
schema
|
|
4238
|
+
}, children[operation.path[0]]) && children[operation.path[0]];
|
|
4239
|
+
if (!block)
|
|
4240
|
+
throw new Error("Could not find block");
|
|
4241
|
+
const textChild = isTextBlock({
|
|
4242
|
+
schema
|
|
4243
|
+
}, block) && isSpan({
|
|
4244
|
+
schema
|
|
4245
|
+
}, block.children[operation.path[1]]) && block.children[operation.path[1]];
|
|
4246
|
+
if (!textChild)
|
|
4247
|
+
throw new Error("Could not find child");
|
|
4248
|
+
const path = [{
|
|
4249
|
+
_key: block._key
|
|
4250
|
+
}, "children", {
|
|
4251
|
+
_key: textChild._key
|
|
4252
|
+
}, "text"], prevBlock = beforeValue[operation.path[0]], prevChild = isTextBlock({
|
|
4253
|
+
schema
|
|
4254
|
+
}, prevBlock) && prevBlock.children[operation.path[1]], prevText = isSpan({
|
|
4255
|
+
schema
|
|
4256
|
+
}, prevChild) ? prevChild.text : "", patch = diffMatchPatch$1(prevText, textChild.text, path);
|
|
4257
|
+
return patch.value.length ? [patch] : [];
|
|
4258
|
+
}
|
|
4259
|
+
function removeTextPatch(schema, children, operation, beforeValue) {
|
|
4260
|
+
const block = children[operation.path[0]];
|
|
4261
|
+
if (!block)
|
|
4262
|
+
throw new Error("Could not find block");
|
|
4263
|
+
const child = isTextBlock({
|
|
4264
|
+
schema
|
|
4265
|
+
}, block) && block.children[operation.path[1]] || void 0, textChild = isSpan({
|
|
4266
|
+
schema
|
|
4267
|
+
}, child) ? child : void 0;
|
|
4268
|
+
if (child && !textChild)
|
|
4269
|
+
throw new Error("Expected span");
|
|
4270
|
+
if (!textChild)
|
|
4271
|
+
throw new Error("Could not find child");
|
|
4272
|
+
const path = [{
|
|
4273
|
+
_key: block._key
|
|
4274
|
+
}, "children", {
|
|
4275
|
+
_key: textChild._key
|
|
4276
|
+
}, "text"], beforeBlock = beforeValue[operation.path[0]], prevTextChild = isTextBlock({
|
|
4277
|
+
schema
|
|
4278
|
+
}, beforeBlock) && beforeBlock.children[operation.path[1]], prevText = isSpan({
|
|
4279
|
+
schema
|
|
4280
|
+
}, prevTextChild) && prevTextChild.text, patch = diffMatchPatch$1(prevText || "", textChild.text, path);
|
|
4281
|
+
return patch.value ? [patch] : [];
|
|
4282
|
+
}
|
|
4283
|
+
function setNodePatch(schema, children, operation) {
|
|
4284
|
+
if (operation.path.length === 1) {
|
|
4285
|
+
const block = children[operation.path[0]];
|
|
4286
|
+
if (typeof block._key != "string")
|
|
4287
|
+
throw new Error("Expected block to have a _key");
|
|
4288
|
+
const setNode = omitBy({
|
|
4289
|
+
...children[operation.path[0]],
|
|
4290
|
+
...operation.newProperties
|
|
4291
|
+
}, isUndefined);
|
|
4292
|
+
return [set(fromSlateValue([setNode], schema.block.name)[0], [{
|
|
4293
|
+
_key: block._key
|
|
4294
|
+
}])];
|
|
4295
|
+
} else if (operation.path.length === 2) {
|
|
4296
|
+
const block = children[operation.path[0]];
|
|
4297
|
+
if (isTextBlock({
|
|
4298
|
+
schema
|
|
4299
|
+
}, block)) {
|
|
4300
|
+
const child = block.children[operation.path[1]];
|
|
4301
|
+
if (child) {
|
|
4302
|
+
const blockKey = block._key, childKey = child._key, patches = [], keys = Object.keys(operation.newProperties);
|
|
4303
|
+
return keys.forEach((keyName) => {
|
|
4304
|
+
if (keys.length === 1 && keyName === "_key") {
|
|
4305
|
+
const val = get(operation.newProperties, keyName);
|
|
4306
|
+
patches.push(set(val, [{
|
|
4307
|
+
_key: blockKey
|
|
4308
|
+
}, "children", block.children.indexOf(child), keyName]));
|
|
4309
|
+
} else {
|
|
4310
|
+
const val = get(operation.newProperties, keyName);
|
|
4311
|
+
patches.push(set(val, [{
|
|
4312
|
+
_key: blockKey
|
|
4313
|
+
}, "children", {
|
|
4314
|
+
_key: childKey
|
|
4315
|
+
}, keyName]));
|
|
4316
|
+
}
|
|
4317
|
+
}), patches;
|
|
4318
|
+
}
|
|
4319
|
+
throw new Error("Could not find a valid child");
|
|
4320
|
+
}
|
|
4321
|
+
throw new Error("Could not find a valid block");
|
|
4322
|
+
} else
|
|
4323
|
+
throw new Error(`Unexpected path encountered: ${JSON.stringify(operation.path)}`);
|
|
4324
|
+
}
|
|
4325
|
+
function insertNodePatch(schema, children, operation, beforeValue) {
|
|
4326
|
+
const block = beforeValue[operation.path[0]];
|
|
4327
|
+
if (operation.path.length === 1) {
|
|
4328
|
+
const position = operation.path[0] === 0 ? "before" : "after", beforeBlock = beforeValue[operation.path[0] - 1], targetKey = operation.path[0] === 0 ? block?._key : beforeBlock?._key;
|
|
4329
|
+
return targetKey ? [insert([fromSlateValue([operation.node], schema.block.name)[0]], position, [{
|
|
4330
|
+
_key: targetKey
|
|
4331
|
+
}])] : [setIfMissing(beforeValue, []), insert([fromSlateValue([operation.node], schema.block.name)[0]], "before", [operation.path[0]])];
|
|
4332
|
+
} else if (isTextBlock({
|
|
4333
|
+
schema
|
|
4334
|
+
}, block) && operation.path.length === 2 && children[operation.path[0]]) {
|
|
4335
|
+
const position = block.children.length === 0 || !block.children[operation.path[1] - 1] ? "before" : "after", node = {
|
|
4336
|
+
...operation.node
|
|
4337
|
+
};
|
|
4338
|
+
!node._type && Text.isText(node) && (node._type = "span", node.marks = []);
|
|
4339
|
+
const child = fromSlateValue([{
|
|
4340
|
+
_key: "bogus",
|
|
4341
|
+
_type: schema.block.name,
|
|
4342
|
+
children: [node]
|
|
4343
|
+
}], schema.block.name)[0].children[0];
|
|
4344
|
+
return [insert([child], position, [{
|
|
4345
|
+
_key: block._key
|
|
4346
|
+
}, "children", block.children.length <= 1 || !block.children[operation.path[1] - 1] ? 0 : {
|
|
4347
|
+
_key: block.children[operation.path[1] - 1]._key
|
|
4348
|
+
}])];
|
|
4349
|
+
}
|
|
4350
|
+
return [];
|
|
4351
|
+
}
|
|
4352
|
+
function splitNodePatch(schema, children, operation, beforeValue) {
|
|
4353
|
+
const patches = [], splitBlock = children[operation.path[0]];
|
|
4354
|
+
if (!isTextBlock({
|
|
4355
|
+
schema
|
|
4356
|
+
}, splitBlock))
|
|
4357
|
+
throw new Error(`Block with path ${JSON.stringify(operation.path[0])} is not a text block and can't be split`);
|
|
4358
|
+
if (operation.path.length === 1) {
|
|
4359
|
+
const oldBlock = beforeValue[operation.path[0]];
|
|
4360
|
+
if (isTextBlock({
|
|
4361
|
+
schema
|
|
4362
|
+
}, oldBlock)) {
|
|
4363
|
+
const targetValue = fromSlateValue([children[operation.path[0] + 1]], schema.block.name)[0];
|
|
4364
|
+
targetValue && (patches.push(insert([targetValue], "after", [{
|
|
4365
|
+
_key: splitBlock._key
|
|
4366
|
+
}])), oldBlock.children.slice(operation.position).forEach((span) => {
|
|
4367
|
+
const path = [{
|
|
4368
|
+
_key: oldBlock._key
|
|
4369
|
+
}, "children", {
|
|
4370
|
+
_key: span._key
|
|
4371
|
+
}];
|
|
4372
|
+
patches.push(unset(path));
|
|
4373
|
+
}));
|
|
4374
|
+
}
|
|
4375
|
+
return patches;
|
|
4376
|
+
}
|
|
4377
|
+
if (operation.path.length === 2) {
|
|
4378
|
+
const splitSpan = splitBlock.children[operation.path[1]];
|
|
4379
|
+
if (isSpan({
|
|
4380
|
+
schema
|
|
4381
|
+
}, splitSpan)) {
|
|
4382
|
+
const targetSpans = fromSlateValue([{
|
|
4383
|
+
...splitBlock,
|
|
4384
|
+
children: splitBlock.children.slice(operation.path[1] + 1, operation.path[1] + 2)
|
|
4385
|
+
}], schema.block.name)[0].children;
|
|
4386
|
+
patches.push(insert(targetSpans, "after", [{
|
|
4387
|
+
_key: splitBlock._key
|
|
4388
|
+
}, "children", {
|
|
4389
|
+
_key: splitSpan._key
|
|
4390
|
+
}])), patches.push(set(splitSpan.text, [{
|
|
4391
|
+
_key: splitBlock._key
|
|
4392
|
+
}, "children", {
|
|
4393
|
+
_key: splitSpan._key
|
|
4394
|
+
}, "text"]));
|
|
4395
|
+
}
|
|
4396
|
+
return patches;
|
|
4397
|
+
}
|
|
4398
|
+
return patches;
|
|
4399
|
+
}
|
|
4400
|
+
function removeNodePatch(schema, beforeValue, operation) {
|
|
4401
|
+
const block = beforeValue[operation.path[0]];
|
|
4402
|
+
if (operation.path.length === 1) {
|
|
4403
|
+
if (block && block._key)
|
|
4404
|
+
return [unset([{
|
|
4405
|
+
_key: block._key
|
|
4406
|
+
}])];
|
|
4407
|
+
throw new Error("Block not found");
|
|
4408
|
+
} else if (isTextBlock({
|
|
4409
|
+
schema
|
|
4410
|
+
}, block) && operation.path.length === 2) {
|
|
4411
|
+
const spanToRemove = block.children[operation.path[1]];
|
|
4412
|
+
return spanToRemove ? block.children.filter((span) => span._key === operation.node._key).length > 1 ? (console.warn(`Multiple spans have \`_key\` ${operation.node._key}. It's ambiguous which one to remove.`, JSON.stringify(block, null, 2)), []) : [unset([{
|
|
4413
|
+
_key: block._key
|
|
4414
|
+
}, "children", {
|
|
4415
|
+
_key: spanToRemove._key
|
|
4416
|
+
}])] : [];
|
|
4417
|
+
} else
|
|
4418
|
+
return [];
|
|
4419
|
+
}
|
|
4420
|
+
function mergeNodePatch(schema, children, operation, beforeValue) {
|
|
4421
|
+
const patches = [], block = beforeValue[operation.path[0]], updatedBlock = children[operation.path[0]];
|
|
4422
|
+
if (operation.path.length === 1)
|
|
4423
|
+
if (block?._key) {
|
|
4424
|
+
const newBlock = fromSlateValue([children[operation.path[0] - 1]], schema.block.name)[0];
|
|
4425
|
+
patches.push(set(newBlock, [{
|
|
4426
|
+
_key: newBlock._key
|
|
4427
|
+
}])), patches.push(unset([{
|
|
4428
|
+
_key: block._key
|
|
4429
|
+
}]));
|
|
4430
|
+
} else
|
|
4431
|
+
throw new Error("Target key not found!");
|
|
4432
|
+
else if (isTextBlock({
|
|
4433
|
+
schema
|
|
4434
|
+
}, block) && isTextBlock({
|
|
4435
|
+
schema
|
|
4436
|
+
}, updatedBlock) && operation.path.length === 2) {
|
|
4437
|
+
const updatedSpan = updatedBlock.children[operation.path[1] - 1] && isSpan({
|
|
4438
|
+
schema
|
|
4439
|
+
}, updatedBlock.children[operation.path[1] - 1]) ? updatedBlock.children[operation.path[1] - 1] : void 0, removedSpan = block.children[operation.path[1]] && isSpan({
|
|
4440
|
+
schema
|
|
4441
|
+
}, block.children[operation.path[1]]) ? block.children[operation.path[1]] : void 0;
|
|
4442
|
+
updatedSpan && (block.children.filter((span) => span._key === updatedSpan._key).length === 1 ? patches.push(set(updatedSpan.text, [{
|
|
4443
|
+
_key: block._key
|
|
4444
|
+
}, "children", {
|
|
4445
|
+
_key: updatedSpan._key
|
|
4446
|
+
}, "text"])) : console.warn(`Multiple spans have \`_key\` ${updatedSpan._key}. It's ambiguous which one to update.`, JSON.stringify(block, null, 2))), removedSpan && (block.children.filter((span) => span._key === removedSpan._key).length === 1 ? patches.push(unset([{
|
|
4447
|
+
_key: block._key
|
|
4448
|
+
}, "children", {
|
|
4449
|
+
_key: removedSpan._key
|
|
4450
|
+
}])) : console.warn(`Multiple spans have \`_key\` ${removedSpan._key}. It's ambiguous which one to remove.`, JSON.stringify(block, null, 2)));
|
|
4451
|
+
}
|
|
4452
|
+
return patches;
|
|
4453
|
+
}
|
|
4454
|
+
function moveNodePatch(schema, beforeValue, operation) {
|
|
4455
|
+
const patches = [], block = beforeValue[operation.path[0]], targetBlock = beforeValue[operation.newPath[0]];
|
|
4456
|
+
if (!targetBlock)
|
|
4457
|
+
return patches;
|
|
4458
|
+
if (operation.path.length === 1) {
|
|
4459
|
+
const position = operation.path[0] > operation.newPath[0] ? "before" : "after";
|
|
4460
|
+
patches.push(unset([{
|
|
4461
|
+
_key: block._key
|
|
4462
|
+
}])), patches.push(insert([fromSlateValue([block], schema.block.name)[0]], position, [{
|
|
4463
|
+
_key: targetBlock._key
|
|
4464
|
+
}]));
|
|
4465
|
+
} else if (operation.path.length === 2 && isTextBlock({
|
|
4466
|
+
schema
|
|
4467
|
+
}, block) && isTextBlock({
|
|
4468
|
+
schema
|
|
4469
|
+
}, targetBlock)) {
|
|
4470
|
+
const child = block.children[operation.path[1]], targetChild = targetBlock.children[operation.newPath[1]], position = operation.newPath[1] === targetBlock.children.length ? "after" : "before", childToInsert = fromSlateValue([block], schema.block.name)[0].children[operation.path[1]];
|
|
4471
|
+
patches.push(unset([{
|
|
4472
|
+
_key: block._key
|
|
4473
|
+
}, "children", {
|
|
4474
|
+
_key: child._key
|
|
4475
|
+
}])), patches.push(insert([childToInsert], position, [{
|
|
4476
|
+
_key: targetBlock._key
|
|
4477
|
+
}, "children", {
|
|
4478
|
+
_key: targetChild._key
|
|
4479
|
+
}]));
|
|
4480
|
+
}
|
|
4481
|
+
return patches;
|
|
4482
|
+
}
|
|
4442
4483
|
const PATCHING = /* @__PURE__ */ new WeakMap();
|
|
4443
4484
|
function withoutPatching(editor, fn) {
|
|
4444
4485
|
const prev = isPatching(editor);
|
|
@@ -4451,7 +4492,6 @@ const debug$e = debugWithName("plugin:withPatches");
|
|
|
4451
4492
|
function createWithPatches({
|
|
4452
4493
|
editorActor,
|
|
4453
4494
|
relayActor,
|
|
4454
|
-
patchFunctions,
|
|
4455
4495
|
subscriptions
|
|
4456
4496
|
}) {
|
|
4457
4497
|
let previousChildren;
|
|
@@ -4506,28 +4546,28 @@ function createWithPatches({
|
|
|
4506
4546
|
return editor;
|
|
4507
4547
|
switch (editorWasEmpty && !editorIsEmpty && operation.type !== "set_selection" && patches.push(insert(previousChildren, "before", [0])), operation.type) {
|
|
4508
4548
|
case "insert_text":
|
|
4509
|
-
patches = [...patches, ...
|
|
4549
|
+
patches = [...patches, ...insertTextPatch(editorActor.getSnapshot().context.schema, editor.children, operation, previousChildren)];
|
|
4510
4550
|
break;
|
|
4511
4551
|
case "remove_text":
|
|
4512
|
-
patches = [...patches, ...
|
|
4552
|
+
patches = [...patches, ...removeTextPatch(editorActor.getSnapshot().context.schema, editor.children, operation, previousChildren)];
|
|
4513
4553
|
break;
|
|
4514
4554
|
case "remove_node":
|
|
4515
|
-
patches = [...patches, ...
|
|
4555
|
+
patches = [...patches, ...removeNodePatch(editorActor.getSnapshot().context.schema, previousChildren, operation)];
|
|
4516
4556
|
break;
|
|
4517
4557
|
case "split_node":
|
|
4518
|
-
patches = [...patches, ...
|
|
4558
|
+
patches = [...patches, ...splitNodePatch(editorActor.getSnapshot().context.schema, editor.children, operation, previousChildren)];
|
|
4519
4559
|
break;
|
|
4520
4560
|
case "insert_node":
|
|
4521
|
-
patches = [...patches, ...
|
|
4561
|
+
patches = [...patches, ...insertNodePatch(editorActor.getSnapshot().context.schema, editor.children, operation, previousChildren)];
|
|
4522
4562
|
break;
|
|
4523
4563
|
case "set_node":
|
|
4524
|
-
patches = [...patches, ...
|
|
4564
|
+
patches = [...patches, ...setNodePatch(editorActor.getSnapshot().context.schema, editor.children, operation)];
|
|
4525
4565
|
break;
|
|
4526
4566
|
case "merge_node":
|
|
4527
|
-
patches = [...patches, ...
|
|
4567
|
+
patches = [...patches, ...mergeNodePatch(editorActor.getSnapshot().context.schema, editor.children, operation, previousChildren)];
|
|
4528
4568
|
break;
|
|
4529
4569
|
case "move_node":
|
|
4530
|
-
patches = [...patches, ...
|
|
4570
|
+
patches = [...patches, ...moveNodePatch(editorActor.getSnapshot().context.schema, previousChildren, operation)];
|
|
4531
4571
|
break;
|
|
4532
4572
|
}
|
|
4533
4573
|
if (!editorWasEmpty && editorIsEmpty && ["merge_node", "set_node", "remove_text", "remove_node"].includes(operation.type) && (patches = [...patches, unset([])], relayActor.send({
|
|
@@ -4719,16 +4759,298 @@ function createWithUtils({
|
|
|
4719
4759
|
})[0], editor;
|
|
4720
4760
|
};
|
|
4721
4761
|
}
|
|
4762
|
+
function isEditorNode(node) {
|
|
4763
|
+
return typeof node == "object" && node !== null ? !("_type" in node) && "children" in node && Array.isArray(node.children) : !1;
|
|
4764
|
+
}
|
|
4765
|
+
function isTextBlockNode(context, node) {
|
|
4766
|
+
return isTypedObject(node) && node._type === context.schema.block.name;
|
|
4767
|
+
}
|
|
4768
|
+
function isSpanNode(context, node) {
|
|
4769
|
+
return typeof node != "object" || node === null || "children" in node ? !1 : "_type" in node ? node._type === context.schema.span.name : "text" in node;
|
|
4770
|
+
}
|
|
4771
|
+
function isPartialSpanNode(node) {
|
|
4772
|
+
return typeof node == "object" && node !== null && "text" in node && typeof node.text == "string";
|
|
4773
|
+
}
|
|
4774
|
+
function isObjectNode(context, node) {
|
|
4775
|
+
return !isEditorNode(node) && !isTextBlockNode(context, node) && !isSpanNode(context, node) && !isPartialSpanNode(node);
|
|
4776
|
+
}
|
|
4777
|
+
function getBlock(root, path) {
|
|
4778
|
+
const index = path.at(0);
|
|
4779
|
+
if (!(index === void 0 || path.length !== 1))
|
|
4780
|
+
return root.children.at(index);
|
|
4781
|
+
}
|
|
4782
|
+
function getNode(context, root, path) {
|
|
4783
|
+
if (path.length === 0)
|
|
4784
|
+
return root;
|
|
4785
|
+
if (path.length === 1)
|
|
4786
|
+
return getBlock(root, path);
|
|
4787
|
+
if (path.length === 2) {
|
|
4788
|
+
const block = getBlock(root, path.slice(0, 1));
|
|
4789
|
+
return !block || !isTextBlockNode(context, block) ? void 0 : block.children.at(path[1]) || void 0;
|
|
4790
|
+
}
|
|
4791
|
+
}
|
|
4792
|
+
function getSpan(context, root, path) {
|
|
4793
|
+
const node = getNode(context, root, path);
|
|
4794
|
+
if (node && isSpanNode(context, node))
|
|
4795
|
+
return node;
|
|
4796
|
+
}
|
|
4797
|
+
function getParent(context, root, path) {
|
|
4798
|
+
if (path.length === 0)
|
|
4799
|
+
return;
|
|
4800
|
+
const parentPath = path.slice(0, -1);
|
|
4801
|
+
if (parentPath.length === 0)
|
|
4802
|
+
return root;
|
|
4803
|
+
const blockIndex = parentPath.at(0);
|
|
4804
|
+
if (blockIndex === void 0 || parentPath.length !== 1)
|
|
4805
|
+
return;
|
|
4806
|
+
const block = root.children.at(blockIndex);
|
|
4807
|
+
if (block && isTextBlockNode(context, block))
|
|
4808
|
+
return block;
|
|
4809
|
+
}
|
|
4810
|
+
function applyOperationToPortableText(context, value, operation) {
|
|
4811
|
+
const draft = createDraft({
|
|
4812
|
+
children: value
|
|
4813
|
+
});
|
|
4814
|
+
try {
|
|
4815
|
+
applyOperationToPortableTextDraft(context, draft, operation);
|
|
4816
|
+
} catch (e) {
|
|
4817
|
+
console.error(e);
|
|
4818
|
+
}
|
|
4819
|
+
return finishDraft(draft).children;
|
|
4820
|
+
}
|
|
4821
|
+
function applyOperationToPortableTextDraft(context, root, operation) {
|
|
4822
|
+
switch (operation.type) {
|
|
4823
|
+
case "insert_node": {
|
|
4824
|
+
const {
|
|
4825
|
+
path,
|
|
4826
|
+
node: insertedNode
|
|
4827
|
+
} = operation, parent = getParent(context, root, path), index = path[path.length - 1];
|
|
4828
|
+
if (!parent || index > parent.children.length)
|
|
4829
|
+
break;
|
|
4830
|
+
if (path.length === 1) {
|
|
4831
|
+
if (isTextBlockNode(context, insertedNode)) {
|
|
4832
|
+
parent.children.splice(index, 0, {
|
|
4833
|
+
...insertedNode,
|
|
4834
|
+
children: insertedNode.children.map((child) => "__inline" in child ? {
|
|
4835
|
+
_key: child._key,
|
|
4836
|
+
_type: child._type,
|
|
4837
|
+
..."value" in child && typeof child.value == "object" ? child.value : {}
|
|
4838
|
+
} : child)
|
|
4839
|
+
});
|
|
4840
|
+
break;
|
|
4841
|
+
}
|
|
4842
|
+
if (Element$1.isElement(insertedNode) && !("__inline" in insertedNode)) {
|
|
4843
|
+
parent.children.splice(index, 0, {
|
|
4844
|
+
_key: insertedNode._key,
|
|
4845
|
+
_type: insertedNode._type,
|
|
4846
|
+
..."value" in insertedNode && typeof insertedNode.value == "object" ? insertedNode.value : {}
|
|
4847
|
+
});
|
|
4848
|
+
break;
|
|
4849
|
+
}
|
|
4850
|
+
}
|
|
4851
|
+
if (path.length === 2) {
|
|
4852
|
+
if (!isTextBlockNode(context, parent))
|
|
4853
|
+
break;
|
|
4854
|
+
if (isPartialSpanNode(insertedNode)) {
|
|
4855
|
+
parent.children.splice(index, 0, insertedNode);
|
|
4856
|
+
break;
|
|
4857
|
+
}
|
|
4858
|
+
if ("__inline" in insertedNode) {
|
|
4859
|
+
parent.children.splice(index, 0, {
|
|
4860
|
+
_key: insertedNode._key,
|
|
4861
|
+
_type: insertedNode._type,
|
|
4862
|
+
..."value" in insertedNode && typeof insertedNode.value == "object" ? insertedNode.value : {}
|
|
4863
|
+
});
|
|
4864
|
+
break;
|
|
4865
|
+
}
|
|
4866
|
+
}
|
|
4867
|
+
break;
|
|
4868
|
+
}
|
|
4869
|
+
case "insert_text": {
|
|
4870
|
+
const {
|
|
4871
|
+
path,
|
|
4872
|
+
offset,
|
|
4873
|
+
text
|
|
4874
|
+
} = operation;
|
|
4875
|
+
if (text.length === 0) break;
|
|
4876
|
+
const span = getSpan(context, root, path);
|
|
4877
|
+
if (!span)
|
|
4878
|
+
break;
|
|
4879
|
+
const before = span.text.slice(0, offset), after = span.text.slice(offset);
|
|
4880
|
+
span.text = before + text + after;
|
|
4881
|
+
break;
|
|
4882
|
+
}
|
|
4883
|
+
case "merge_node": {
|
|
4884
|
+
const {
|
|
4885
|
+
path
|
|
4886
|
+
} = operation, node = getNode(context, root, path), prevPath = Path.previous(path), prev = getNode(context, root, prevPath), parent = getParent(context, root, path);
|
|
4887
|
+
if (!node || !prev || !parent)
|
|
4888
|
+
break;
|
|
4889
|
+
const index = path[path.length - 1];
|
|
4890
|
+
if (isPartialSpanNode(node) && isPartialSpanNode(prev))
|
|
4891
|
+
prev.text += node.text;
|
|
4892
|
+
else if (isTextBlockNode(context, node) && isTextBlockNode(context, prev))
|
|
4893
|
+
prev.children.push(...node.children);
|
|
4894
|
+
else
|
|
4895
|
+
break;
|
|
4896
|
+
parent.children.splice(index, 1);
|
|
4897
|
+
break;
|
|
4898
|
+
}
|
|
4899
|
+
case "move_node": {
|
|
4900
|
+
const {
|
|
4901
|
+
path,
|
|
4902
|
+
newPath
|
|
4903
|
+
} = operation;
|
|
4904
|
+
if (Path.isAncestor(path, newPath))
|
|
4905
|
+
break;
|
|
4906
|
+
const node = getNode(context, root, path), parent = getParent(context, root, path), index = path[path.length - 1];
|
|
4907
|
+
if (!node || !parent)
|
|
4908
|
+
break;
|
|
4909
|
+
parent.children.splice(index, 1);
|
|
4910
|
+
const truePath = Path.transform(path, operation), newParent = getNode(context, root, Path.parent(truePath)), newIndex = truePath[truePath.length - 1];
|
|
4911
|
+
if (!newParent || !("children" in newParent) || !Array.isArray(newParent.children))
|
|
4912
|
+
break;
|
|
4913
|
+
newParent.children.splice(newIndex, 0, node);
|
|
4914
|
+
break;
|
|
4915
|
+
}
|
|
4916
|
+
case "remove_node": {
|
|
4917
|
+
const {
|
|
4918
|
+
path
|
|
4919
|
+
} = operation, index = path[path.length - 1];
|
|
4920
|
+
getParent(context, root, path)?.children.splice(index, 1);
|
|
4921
|
+
break;
|
|
4922
|
+
}
|
|
4923
|
+
case "remove_text": {
|
|
4924
|
+
const {
|
|
4925
|
+
path,
|
|
4926
|
+
offset,
|
|
4927
|
+
text
|
|
4928
|
+
} = operation;
|
|
4929
|
+
if (text.length === 0)
|
|
4930
|
+
break;
|
|
4931
|
+
const span = getSpan(context, root, path);
|
|
4932
|
+
if (!span)
|
|
4933
|
+
break;
|
|
4934
|
+
const before = span.text.slice(0, offset), after = span.text.slice(offset + text.length);
|
|
4935
|
+
span.text = before + after;
|
|
4936
|
+
break;
|
|
4937
|
+
}
|
|
4938
|
+
case "set_node": {
|
|
4939
|
+
const {
|
|
4940
|
+
path,
|
|
4941
|
+
properties,
|
|
4942
|
+
newProperties
|
|
4943
|
+
} = operation, node = getNode(context, root, path);
|
|
4944
|
+
if (!node || isEditorNode(node))
|
|
4945
|
+
break;
|
|
4946
|
+
if (isObjectNode(context, node)) {
|
|
4947
|
+
const valueBefore = "value" in properties && typeof properties.value == "object" ? properties.value : {}, valueAfter = "value" in newProperties && typeof newProperties.value == "object" ? newProperties.value : {};
|
|
4948
|
+
for (const key in newProperties) {
|
|
4949
|
+
if (key === "value")
|
|
4950
|
+
continue;
|
|
4951
|
+
const value = newProperties[key];
|
|
4952
|
+
value == null ? delete node[key] : node[key] = value;
|
|
4953
|
+
}
|
|
4954
|
+
for (const key in properties)
|
|
4955
|
+
key !== "value" && (newProperties.hasOwnProperty(key) || delete node[key]);
|
|
4956
|
+
for (const key in valueAfter) {
|
|
4957
|
+
const value = valueAfter[key];
|
|
4958
|
+
value == null ? delete node[key] : node[key] = value;
|
|
4959
|
+
}
|
|
4960
|
+
for (const key in valueBefore)
|
|
4961
|
+
valueAfter.hasOwnProperty(key) || delete node[key];
|
|
4962
|
+
break;
|
|
4963
|
+
}
|
|
4964
|
+
if (isTextBlockNode(context, node)) {
|
|
4965
|
+
for (const key in newProperties) {
|
|
4966
|
+
if (key === "children" || key === "text")
|
|
4967
|
+
break;
|
|
4968
|
+
const value = newProperties[key];
|
|
4969
|
+
value == null ? delete node[key] : node[key] = value;
|
|
4970
|
+
}
|
|
4971
|
+
for (const key in properties)
|
|
4972
|
+
newProperties.hasOwnProperty(key) || delete node[key];
|
|
4973
|
+
break;
|
|
4974
|
+
}
|
|
4975
|
+
if (isPartialSpanNode(node)) {
|
|
4976
|
+
for (const key in newProperties) {
|
|
4977
|
+
if (key === "text")
|
|
4978
|
+
break;
|
|
4979
|
+
const value = newProperties[key];
|
|
4980
|
+
value == null ? delete node[key] : node[key] = value;
|
|
4981
|
+
}
|
|
4982
|
+
for (const key in properties)
|
|
4983
|
+
newProperties.hasOwnProperty(key) || delete node[key];
|
|
4984
|
+
break;
|
|
4985
|
+
}
|
|
4986
|
+
break;
|
|
4987
|
+
}
|
|
4988
|
+
case "split_node": {
|
|
4989
|
+
const {
|
|
4990
|
+
path,
|
|
4991
|
+
position,
|
|
4992
|
+
properties
|
|
4993
|
+
} = operation;
|
|
4994
|
+
if (path.length === 0)
|
|
4995
|
+
break;
|
|
4996
|
+
const parent = getParent(context, root, path), index = path[path.length - 1];
|
|
4997
|
+
if (!parent)
|
|
4998
|
+
break;
|
|
4999
|
+
if (isEditorNode(parent)) {
|
|
5000
|
+
const block = getBlock(root, path);
|
|
5001
|
+
if (!block || !isTextBlockNode(context, block))
|
|
5002
|
+
break;
|
|
5003
|
+
const before = block.children.slice(0, position), after = block.children.slice(position);
|
|
5004
|
+
block.children = before;
|
|
5005
|
+
const newTextBlockNode = {
|
|
5006
|
+
...properties,
|
|
5007
|
+
children: after,
|
|
5008
|
+
_type: context.schema.block.name
|
|
5009
|
+
};
|
|
5010
|
+
parent.children.splice(index + 1, 0, newTextBlockNode);
|
|
5011
|
+
break;
|
|
5012
|
+
}
|
|
5013
|
+
if (isTextBlockNode(context, parent)) {
|
|
5014
|
+
const node = getNode(context, root, path);
|
|
5015
|
+
if (!node || !isSpanNode(context, node))
|
|
5016
|
+
break;
|
|
5017
|
+
const before = node.text.slice(0, position), after = node.text.slice(position);
|
|
5018
|
+
node.text = before;
|
|
5019
|
+
const newSpanNode = {
|
|
5020
|
+
...properties,
|
|
5021
|
+
text: after
|
|
5022
|
+
};
|
|
5023
|
+
parent.children.splice(index + 1, 0, newSpanNode);
|
|
5024
|
+
}
|
|
5025
|
+
break;
|
|
5026
|
+
}
|
|
5027
|
+
}
|
|
5028
|
+
return root;
|
|
5029
|
+
}
|
|
5030
|
+
function pluginUpdateValue(context, editor) {
|
|
5031
|
+
const {
|
|
5032
|
+
apply: apply2
|
|
5033
|
+
} = editor;
|
|
5034
|
+
return editor.apply = (operation) => {
|
|
5035
|
+
if (operation.type === "set_selection") {
|
|
5036
|
+
apply2(operation);
|
|
5037
|
+
return;
|
|
5038
|
+
}
|
|
5039
|
+
editor.value = applyOperationToPortableText({
|
|
5040
|
+
keyGenerator: context.keyGenerator,
|
|
5041
|
+
schema: context.schema
|
|
5042
|
+
}, editor.value, operation), apply2(operation);
|
|
5043
|
+
}, editor;
|
|
5044
|
+
}
|
|
4722
5045
|
const withPlugins = (editor, options) => {
|
|
4723
5046
|
const e = editor, {
|
|
4724
5047
|
editorActor,
|
|
4725
5048
|
relayActor
|
|
4726
|
-
} = options,
|
|
5049
|
+
} = options, withObjectKeys = createWithObjectKeys(editorActor), withSchemaTypes = createWithSchemaTypes({
|
|
4727
5050
|
editorActor
|
|
4728
5051
|
}), withPatches = createWithPatches({
|
|
4729
5052
|
editorActor,
|
|
4730
5053
|
relayActor,
|
|
4731
|
-
patchFunctions: operationToPatches,
|
|
4732
5054
|
subscriptions: options.subscriptions
|
|
4733
5055
|
}), withMaxBlocks = createWithMaxBlocks(editorActor), withUndoRedo = createWithUndoRedo({
|
|
4734
5056
|
editorActor,
|
|
@@ -4736,7 +5058,7 @@ const withPlugins = (editor, options) => {
|
|
|
4736
5058
|
}), withPortableTextMarkModel = createWithPortableTextMarkModel(editorActor), withPortableTextBlockStyle = createWithPortableTextBlockStyle(editorActor), withPlaceholderBlock = createWithPlaceholderBlock(editorActor), withUtils = createWithUtils({
|
|
4737
5059
|
editorActor
|
|
4738
5060
|
}), withPortableTextSelections = createWithPortableTextSelections(editorActor);
|
|
4739
|
-
return createWithEventListeners(editorActor)(withSchemaTypes(withObjectKeys(withPortableTextMarkModel(withPortableTextBlockStyle(withPlaceholderBlock(withUtils(withMaxBlocks(withUndoRedo(withPatches(withPortableTextSelections(e)))))))))));
|
|
5061
|
+
return createWithEventListeners(editorActor)(withSchemaTypes(withObjectKeys(withPortableTextMarkModel(withPortableTextBlockStyle(withPlaceholderBlock(withUtils(withMaxBlocks(withUndoRedo(withPatches(withPortableTextSelections(pluginUpdateValue(editorActor.getSnapshot().context, e))))))))))));
|
|
4740
5062
|
}, debug$a = debugWithName("setup");
|
|
4741
5063
|
function createSlateEditor(config) {
|
|
4742
5064
|
debug$a("Creating new Slate editor instance");
|
|
@@ -4745,10 +5067,10 @@ function createSlateEditor(config) {
|
|
|
4745
5067
|
relayActor: config.relayActor,
|
|
4746
5068
|
subscriptions: config.subscriptions
|
|
4747
5069
|
});
|
|
4748
|
-
KEY_TO_VALUE_ELEMENT.set(instance, {}), KEY_TO_SLATE_ELEMENT.set(instance, {});
|
|
4749
|
-
const initialValue =
|
|
4750
|
-
|
|
4751
|
-
})
|
|
5070
|
+
KEY_TO_VALUE_ELEMENT.set(instance, {}), KEY_TO_SLATE_ELEMENT.set(instance, {}), instance.value = [createPlaceholderBlock(config.editorActor.getSnapshot().context)];
|
|
5071
|
+
const initialValue = toSlateValue(instance.value, {
|
|
5072
|
+
schemaTypes: config.editorActor.getSnapshot().context.schema
|
|
5073
|
+
});
|
|
4752
5074
|
return {
|
|
4753
5075
|
instance,
|
|
4754
5076
|
initialValue
|
|
@@ -6540,34 +6862,6 @@ function sortByPriority(items) {
|
|
|
6540
6862
|
result.includes(item) || result.push(item);
|
|
6541
6863
|
return [...result, ...itemsWithoutPriority];
|
|
6542
6864
|
}
|
|
6543
|
-
function slateChildrenToBlocks(schema, value) {
|
|
6544
|
-
const blocks = new Array(value.length);
|
|
6545
|
-
for (let blockIndex = 0; blockIndex < value.length; blockIndex++) {
|
|
6546
|
-
const descendant = value[blockIndex];
|
|
6547
|
-
if (descendant._type !== schema.block.name) {
|
|
6548
|
-
blocks[blockIndex] = {
|
|
6549
|
-
_key: descendant._key,
|
|
6550
|
-
_type: descendant._type,
|
|
6551
|
-
..."value" in descendant && typeof descendant.value == "object" ? descendant.value : {}
|
|
6552
|
-
};
|
|
6553
|
-
continue;
|
|
6554
|
-
}
|
|
6555
|
-
const children = "children" in descendant ? descendant.children : [], processedChildren = new Array(children.length);
|
|
6556
|
-
for (let childIndex = 0; childIndex < children.length; childIndex++) {
|
|
6557
|
-
const child = children[childIndex];
|
|
6558
|
-
processedChildren[childIndex] = child._type === schema.span.name ? child : {
|
|
6559
|
-
_key: child._key,
|
|
6560
|
-
_type: child._type,
|
|
6561
|
-
..."value" in child && typeof child.value == "object" ? child.value : {}
|
|
6562
|
-
};
|
|
6563
|
-
}
|
|
6564
|
-
blocks[blockIndex] = {
|
|
6565
|
-
...descendant,
|
|
6566
|
-
children: processedChildren
|
|
6567
|
-
};
|
|
6568
|
-
}
|
|
6569
|
-
return blocks;
|
|
6570
|
-
}
|
|
6571
6865
|
function getActiveDecorators({
|
|
6572
6866
|
schema,
|
|
6573
6867
|
slateEditorInstance
|
|
@@ -6586,7 +6880,7 @@ function createEditorSnapshot({
|
|
|
6586
6880
|
hasTag,
|
|
6587
6881
|
internalDrag
|
|
6588
6882
|
}) {
|
|
6589
|
-
const
|
|
6883
|
+
const selection = editor.selection ? slateRangeToSelection({
|
|
6590
6884
|
schema,
|
|
6591
6885
|
editor,
|
|
6592
6886
|
range: editor.selection
|
|
@@ -6602,7 +6896,7 @@ function createEditorSnapshot({
|
|
|
6602
6896
|
readOnly,
|
|
6603
6897
|
schema,
|
|
6604
6898
|
selection,
|
|
6605
|
-
value
|
|
6899
|
+
value: editor.value
|
|
6606
6900
|
},
|
|
6607
6901
|
beta: {
|
|
6608
6902
|
hasTag,
|
|
@@ -7318,7 +7612,7 @@ function getEditorSnapshot({
|
|
|
7318
7612
|
}),
|
|
7319
7613
|
schema: editorActorSnapshot.context.schema,
|
|
7320
7614
|
selection: editorActorSnapshot.context.selection,
|
|
7321
|
-
value:
|
|
7615
|
+
value: slateEditorInstance.value
|
|
7322
7616
|
},
|
|
7323
7617
|
beta: {
|
|
7324
7618
|
hasTag: (tag) => editorActorSnapshot.hasTag(tag),
|
|
@@ -7705,8 +7999,8 @@ function createEditableAPI(editor, editorActor) {
|
|
|
7705
7999
|
}]
|
|
7706
8000
|
}], {
|
|
7707
8001
|
schemaTypes: editorActor.getSnapshot().context.schema
|
|
7708
|
-
})[0].children[0], focusChildPath = editor.selection.focus.path.slice(0, 2),
|
|
7709
|
-
return
|
|
8002
|
+
})[0].children[0], focusChildPath = editor.selection.focus.path.slice(0, 2), isSpanNode2 = child._type === types.span.name, focusNode = Node.get(editor, focusChildPath);
|
|
8003
|
+
return isSpanNode2 && focusNode._type !== types.span.name && (debug$6("Inserting span child next to inline object child, moving selection + 1"), editor.move({
|
|
7710
8004
|
distance: 1,
|
|
7711
8005
|
unit: "character"
|
|
7712
8006
|
})), Transforms.insertNodes(editor, child, {
|
|
@@ -8746,8 +9040,8 @@ function _updateBlock(slateEditor, currentBlock, oldBlock, currentBlockIndex) {
|
|
|
8746
9040
|
debug$5("Updating changed child", currentBlockChild, oldBlockChild), Transforms.setNodes(slateEditor, currentBlockChild, {
|
|
8747
9041
|
at: path
|
|
8748
9042
|
});
|
|
8749
|
-
const
|
|
8750
|
-
|
|
9043
|
+
const isSpanNode2 = Text.isText(currentBlockChild) && currentBlockChild._type === "span" && Text.isText(oldBlockChild) && oldBlockChild._type === "span";
|
|
9044
|
+
isSpanNode2 && isTextChanged ? (oldBlockChild.text.length > 0 && Transforms.delete(slateEditor, {
|
|
8751
9045
|
at: {
|
|
8752
9046
|
focus: {
|
|
8753
9047
|
path,
|
|
@@ -8760,7 +9054,7 @@ function _updateBlock(slateEditor, currentBlock, oldBlock, currentBlockIndex) {
|
|
|
8760
9054
|
}
|
|
8761
9055
|
}), Transforms.insertText(slateEditor, currentBlockChild.text, {
|
|
8762
9056
|
at: path
|
|
8763
|
-
}), slateEditor.onChange()) :
|
|
9057
|
+
}), slateEditor.onChange()) : isSpanNode2 || (debug$5("Updating changed inline object child", currentBlockChild), Transforms.setNodes(slateEditor, {
|
|
8764
9058
|
_key: VOID_CHILD_KEY
|
|
8765
9059
|
}, {
|
|
8766
9060
|
at: [...path, 0],
|
|
@@ -9130,6 +9424,7 @@ class PortableTextEditor extends Component {
|
|
|
9130
9424
|
/*
|
|
9131
9425
|
* The editor API (currently implemented with Slate).
|
|
9132
9426
|
*/
|
|
9427
|
+
subscriptions = [];
|
|
9133
9428
|
unsubscribers = [];
|
|
9134
9429
|
constructor(props) {
|
|
9135
9430
|
if (super(props), props.editor)
|
|
@@ -9146,23 +9441,20 @@ class PortableTextEditor extends Component {
|
|
|
9146
9441
|
readOnly: props.readOnly,
|
|
9147
9442
|
schema: props.schemaType
|
|
9148
9443
|
});
|
|
9149
|
-
this.
|
|
9150
|
-
const subscription = actors.relayActor.on("*", (event) => {
|
|
9151
|
-
const change = eventToChange(event);
|
|
9152
|
-
change && (props.onChange(change), this.change$.next(change));
|
|
9153
|
-
});
|
|
9154
|
-
return () => {
|
|
9155
|
-
subscription.unsubscribe();
|
|
9156
|
-
};
|
|
9157
|
-
})());
|
|
9158
|
-
for (const subscription of subscriptions)
|
|
9159
|
-
this.unsubscribers.push(subscription());
|
|
9160
|
-
this.actors = actors, this.editor = editor, this.schemaTypes = actors.editorActor.getSnapshot().context.getLegacySchema();
|
|
9444
|
+
this.subscriptions = subscriptions, this.actors = actors, this.editor = editor, this.schemaTypes = actors.editorActor.getSnapshot().context.getLegacySchema();
|
|
9161
9445
|
}
|
|
9162
9446
|
this.editable = this.editor._internal.editable;
|
|
9163
9447
|
}
|
|
9164
9448
|
componentDidMount() {
|
|
9165
|
-
|
|
9449
|
+
if (!this.actors)
|
|
9450
|
+
return;
|
|
9451
|
+
for (const subscription of this.subscriptions)
|
|
9452
|
+
this.unsubscribers.push(subscription());
|
|
9453
|
+
const relayActorSubscription = this.actors.relayActor.on("*", (event) => {
|
|
9454
|
+
const change = eventToChange(event);
|
|
9455
|
+
change && (this.props.editor || this.props.onChange(change), this.change$.next(change));
|
|
9456
|
+
});
|
|
9457
|
+
this.unsubscribers.push(relayActorSubscription.unsubscribe), this.actors.editorActor.start(), this.actors.mutationActor.start(), this.actors.relayActor.start(), this.actors.syncActor.start();
|
|
9166
9458
|
}
|
|
9167
9459
|
componentDidUpdate(prevProps) {
|
|
9168
9460
|
!this.props.editor && !prevProps.editor && this.props.schemaType !== prevProps.schemaType && console.warn("Updating schema type is no longer supported"), !this.props.editor && !prevProps.editor && (this.props.readOnly !== prevProps.readOnly && this.editor._internal.editorActor.send({
|