@portabletext/editor 8.1.1 → 8.1.2
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 +3 -3
- package/lib/index.js +197 -184
- package/lib/index.js.map +1 -1
- package/lib/selector.is-selecting-entire-blocks-BFhnnkHf.js.map +1 -1
- package/package.json +2 -3
package/README.md
CHANGED
|
@@ -13,14 +13,14 @@
|
|
|
13
13
|
|
|
14
14
|
This library provides you with the building blocks to create a completely custom editor experience built on top of Portable Text. We recommend [checking out the official documentation](https://www.portabletext.org/). The following guide includes the basics to get your started.
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
To set up an editor you need to:
|
|
17
17
|
|
|
18
18
|
- Create a schema that defines the rich text and block content elements.
|
|
19
19
|
- Create a toolbar to toggle and insert these elements.
|
|
20
20
|
- Set up rendering for each element type in the editor, including text blocks and inline formatting.
|
|
21
21
|
- Render the editor.
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
The [Portable Text Playground](../../apps/playground/) is a complete editor built with this library. Use it as a reference.
|
|
24
24
|
|
|
25
25
|
### Add the library to your project
|
|
26
26
|
|
|
@@ -361,7 +361,7 @@ Extend the editor with [official plugins](../../#editor-plugins).
|
|
|
361
361
|
|
|
362
362
|
## End-user experience
|
|
363
363
|
|
|
364
|
-
|
|
364
|
+
A large E2E test suite, generated from a [human-readable Gherkin spec](./gherkin-spec/), guards the end-user experience: how selection, editing, and formatting behave under real keyboard and pointer input.
|
|
365
365
|
|
|
366
366
|
## Development
|
|
367
367
|
|
package/lib/index.js
CHANGED
|
@@ -465,17 +465,19 @@ const IS_IOS = typeof navigator < "u" && typeof window < "u" && /iPad|iPhone|iPo
|
|
|
465
465
|
},
|
|
466
466
|
toEditorSelection: (editor, domRange, options) => {
|
|
467
467
|
let { exactMatch, suppressThrow } = options, el = isDOMSelection(domRange) ? domRange.anchorNode : domRange.startContainer, anchorNode = null, anchorOffset = 0, focusNode = null, focusOffset = 0, isCollapsed = !1;
|
|
468
|
-
if (el)
|
|
469
|
-
if (
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
468
|
+
if (el) {
|
|
469
|
+
if (isDOMSelection(domRange)) {
|
|
470
|
+
if (IS_FIREFOX && domRange.rangeCount > 1) {
|
|
471
|
+
focusNode = domRange.focusNode;
|
|
472
|
+
let firstRange = domRange.getRangeAt(0), lastRange = domRange.getRangeAt(domRange.rangeCount - 1);
|
|
473
|
+
if (focusNode instanceof HTMLTableRowElement && firstRange.startContainer instanceof HTMLTableRowElement && lastRange.startContainer instanceof HTMLTableRowElement) {
|
|
474
|
+
let getLastChildren = (element) => element.childElementCount > 0 ? getLastChildren(element.children[0]) : element, firstNodeRow = firstRange.startContainer, lastNodeRow = lastRange.startContainer, firstNode = getLastChildren(firstNodeRow.children[firstRange.startOffset]), lastNode = getLastChildren(lastNodeRow.children[lastRange.startOffset]);
|
|
475
|
+
focusOffset = 0, anchorNode = lastNode.childNodes.length > 0 ? lastNode.childNodes[0] ?? null : lastNode, focusNode = firstNode.childNodes.length > 0 ? firstNode.childNodes[0] ?? null : firstNode, anchorOffset = lastNode instanceof HTMLElement ? lastNode.innerHTML.length : 0;
|
|
476
|
+
} else firstRange.startContainer === focusNode ? (anchorNode = lastRange.endContainer, anchorOffset = lastRange.endOffset, focusOffset = firstRange.startOffset) : (anchorNode = firstRange.startContainer, anchorOffset = firstRange.endOffset, focusOffset = lastRange.startOffset);
|
|
477
|
+
} else anchorNode = domRange.anchorNode, anchorOffset = domRange.anchorOffset, focusNode = domRange.focusNode, focusOffset = domRange.focusOffset;
|
|
478
|
+
isCollapsed = IS_CHROME && hasShadowRoot(anchorNode) || IS_FIREFOX ? domRange.anchorNode === domRange.focusNode && domRange.anchorOffset === domRange.focusOffset : domRange.isCollapsed;
|
|
479
|
+
} else anchorNode = domRange.startContainer, anchorOffset = domRange.startOffset, focusNode = domRange.endContainer, focusOffset = domRange.endOffset, isCollapsed = domRange.collapsed;
|
|
480
|
+
}
|
|
479
481
|
if (anchorNode == null || focusNode == null || anchorOffset == null || focusOffset == null) {
|
|
480
482
|
if (suppressThrow) return null;
|
|
481
483
|
throw Error(`Cannot map DOM range to an editor selection: ${domRange}`);
|
|
@@ -2863,12 +2865,14 @@ const RestoreDOM = IS_ANDROID ? RestoreDOMComponent : ({ children }) => /* @__PU
|
|
|
2863
2865
|
exactMatch: !1,
|
|
2864
2866
|
suppressThrow: !0
|
|
2865
2867
|
});
|
|
2866
|
-
if (range)
|
|
2867
|
-
if (editor.
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2868
|
+
if (range) {
|
|
2869
|
+
if (!editor.composing && !androidInputManager?.hasPendingChanges() && !androidInputManager?.isFlushing()) {
|
|
2870
|
+
if (editor.select(range), domSelection.isCollapsed && anchorNode && anchorNode.nodeType === Node.ELEMENT_NODE) try {
|
|
2871
|
+
let canonicalRange = DOMEditor.toDOMRange(editor, range);
|
|
2872
|
+
domSelection.setBaseAndExtent(canonicalRange.startContainer, canonicalRange.startOffset, canonicalRange.startContainer, canonicalRange.startOffset);
|
|
2873
|
+
} catch {}
|
|
2874
|
+
} else androidInputManager?.handleUserSelect(range);
|
|
2875
|
+
}
|
|
2872
2876
|
}
|
|
2873
2877
|
readOnly && (!anchorNodeSelectable || !focusNodeInEditor) && deselect(editor);
|
|
2874
2878
|
}
|
|
@@ -5644,11 +5648,7 @@ const PortableTextEditable = forwardRef(function PortableTextEditable(props, for
|
|
|
5644
5648
|
}, $[105] = editorActor, $[106] = editorEngine, $[107] = onDragStart, $[108] = readOnly, $[109] = t28) : t28 = $[109];
|
|
5645
5649
|
let handleDragStart = t28, t29;
|
|
5646
5650
|
$[110] !== editorActor || $[111] !== editorEngine || $[112] !== onDrag ? (t29 = (event_9) => {
|
|
5647
|
-
if (onDrag?.(event_9), !(event_9.isDefaultPrevented() || event_9.isPropagationStopped()) &&
|
|
5648
|
-
editorActor,
|
|
5649
|
-
editorEngine,
|
|
5650
|
-
event: event_9.nativeEvent
|
|
5651
|
-
})) return editorActor.send({
|
|
5651
|
+
if (onDrag?.(event_9), !(event_9.isDefaultPrevented() || event_9.isPropagationStopped()) && !(editorActor.getSnapshot().matches({ setup: "setting up" }) || !DOMEditor.hasTarget(editorEngine, event_9.target))) return editorActor.send({
|
|
5652
5652
|
type: "behavior event",
|
|
5653
5653
|
behaviorEvent: {
|
|
5654
5654
|
type: "drag.drag",
|
|
@@ -5671,17 +5671,17 @@ const PortableTextEditable = forwardRef(function PortableTextEditable(props, for
|
|
|
5671
5671
|
let handleDragEnd = t30, t31;
|
|
5672
5672
|
$[118] !== editorActor || $[119] !== editorEngine || $[120] !== onDragEnter ? (t31 = (event_11) => {
|
|
5673
5673
|
if (onDragEnter?.(event_11), event_11.isDefaultPrevented() || event_11.isPropagationStopped()) return;
|
|
5674
|
-
let
|
|
5674
|
+
let position_5 = getEventPosition({
|
|
5675
5675
|
editorActor,
|
|
5676
5676
|
editorEngine,
|
|
5677
5677
|
event: event_11.nativeEvent
|
|
5678
5678
|
});
|
|
5679
|
-
if (
|
|
5679
|
+
if (position_5) return editorActor.send({
|
|
5680
5680
|
type: "behavior event",
|
|
5681
5681
|
behaviorEvent: {
|
|
5682
5682
|
type: "drag.dragenter",
|
|
5683
5683
|
originEvent: { dataTransfer: event_11.dataTransfer },
|
|
5684
|
-
position:
|
|
5684
|
+
position: position_5
|
|
5685
5685
|
},
|
|
5686
5686
|
editor: editorEngine
|
|
5687
5687
|
}), !0;
|
|
@@ -5689,18 +5689,18 @@ const PortableTextEditable = forwardRef(function PortableTextEditable(props, for
|
|
|
5689
5689
|
let handleDragEnter = t31, t32;
|
|
5690
5690
|
$[122] !== editorActor || $[123] !== editorEngine || $[124] !== onDragOver ? (t32 = (event_12) => {
|
|
5691
5691
|
if (onDragOver?.(event_12), event_12.isDefaultPrevented() || event_12.isPropagationStopped()) return;
|
|
5692
|
-
let
|
|
5692
|
+
let position_6 = getEventPosition({
|
|
5693
5693
|
editorActor,
|
|
5694
5694
|
editorEngine,
|
|
5695
5695
|
event: event_12.nativeEvent
|
|
5696
5696
|
});
|
|
5697
|
-
if (
|
|
5697
|
+
if (position_6) return editorActor.send({
|
|
5698
5698
|
type: "behavior event",
|
|
5699
5699
|
behaviorEvent: {
|
|
5700
5700
|
type: "drag.dragover",
|
|
5701
5701
|
originEvent: { dataTransfer: event_12.dataTransfer },
|
|
5702
5702
|
dragOrigin: editorActor.getSnapshot().context.internalDrag?.origin,
|
|
5703
|
-
position:
|
|
5703
|
+
position: position_6
|
|
5704
5704
|
},
|
|
5705
5705
|
editor: editorEngine,
|
|
5706
5706
|
nativeEvent: event_12
|
|
@@ -5709,12 +5709,12 @@ const PortableTextEditable = forwardRef(function PortableTextEditable(props, for
|
|
|
5709
5709
|
let handleDragOver = t32, t33;
|
|
5710
5710
|
$[126] !== editorActor || $[127] !== editorEngine || $[128] !== onDrop ? (t33 = (event_13) => {
|
|
5711
5711
|
if (onDrop?.(event_13), event_13.isDefaultPrevented() || event_13.isPropagationStopped()) return;
|
|
5712
|
-
let
|
|
5712
|
+
let position_7 = getEventPosition({
|
|
5713
5713
|
editorActor,
|
|
5714
5714
|
editorEngine,
|
|
5715
5715
|
event: event_13.nativeEvent
|
|
5716
5716
|
});
|
|
5717
|
-
if (!
|
|
5717
|
+
if (!position_7) {
|
|
5718
5718
|
console.warn("Could not find position for drop event");
|
|
5719
5719
|
return;
|
|
5720
5720
|
}
|
|
@@ -5724,7 +5724,7 @@ const PortableTextEditable = forwardRef(function PortableTextEditable(props, for
|
|
|
5724
5724
|
type: "drag.drop",
|
|
5725
5725
|
originEvent: { dataTransfer: event_13.dataTransfer },
|
|
5726
5726
|
dragOrigin: editorActor.getSnapshot().context.internalDrag?.origin,
|
|
5727
|
-
position:
|
|
5727
|
+
position: position_7
|
|
5728
5728
|
},
|
|
5729
5729
|
editor: editorEngine,
|
|
5730
5730
|
nativeEvent: event_13
|
|
@@ -5732,11 +5732,7 @@ const PortableTextEditable = forwardRef(function PortableTextEditable(props, for
|
|
|
5732
5732
|
}, $[126] = editorActor, $[127] = editorEngine, $[128] = onDrop, $[129] = t33) : t33 = $[129];
|
|
5733
5733
|
let handleDrop = t33, t34;
|
|
5734
5734
|
$[130] !== editorActor || $[131] !== editorEngine || $[132] !== onDragLeave ? (t34 = (event_14) => {
|
|
5735
|
-
if (onDragLeave?.(event_14), !(event_14.isDefaultPrevented() || event_14.isPropagationStopped()) &&
|
|
5736
|
-
editorActor,
|
|
5737
|
-
editorEngine,
|
|
5738
|
-
event: event_14.nativeEvent
|
|
5739
|
-
})) return editorActor.send({
|
|
5735
|
+
if (onDragLeave?.(event_14), !(event_14.isDefaultPrevented() || event_14.isPropagationStopped()) && !(editorActor.getSnapshot().matches({ setup: "setting up" }) || !DOMEditor.hasTarget(editorEngine, event_14.target))) return editorActor.send({
|
|
5740
5736
|
type: "behavior event",
|
|
5741
5737
|
behaviorEvent: {
|
|
5742
5738
|
type: "drag.dragleave",
|
|
@@ -6945,14 +6941,15 @@ function applyOperation(editor, op) {
|
|
|
6945
6941
|
typeof value == "object" && value && !Array.isArray(value) && modifyDescendant(editor, setNodePath, () => value), transformSelection = !0;
|
|
6946
6942
|
break;
|
|
6947
6943
|
}
|
|
6948
|
-
if (getNode(editor.snapshot, setNodePath))
|
|
6949
|
-
|
|
6950
|
-
|
|
6951
|
-
|
|
6952
|
-
|
|
6953
|
-
|
|
6954
|
-
|
|
6955
|
-
|
|
6944
|
+
if (getNode(editor.snapshot, setNodePath)) {
|
|
6945
|
+
if (setPropertyPath.length === 1) {
|
|
6946
|
+
let propertyName = setPropertyPath[0];
|
|
6947
|
+
modifyDescendant(editor, setNodePath, (node) => ({
|
|
6948
|
+
...node,
|
|
6949
|
+
[propertyName]: value
|
|
6950
|
+
}));
|
|
6951
|
+
} else modifyDescendant(editor, setNodePath, (node) => deepSet(node, setPropertyPath, value));
|
|
6952
|
+
} else {
|
|
6956
6953
|
let blockSegment = findBlockSegment(path);
|
|
6957
6954
|
if (!blockSegment) break;
|
|
6958
6955
|
let blockIndex = resolveBlockIndex(editor, blockSegment);
|
|
@@ -7042,14 +7039,15 @@ function applyOperation(editor, op) {
|
|
|
7042
7039
|
value: previousValue
|
|
7043
7040
|
};
|
|
7044
7041
|
}
|
|
7045
|
-
if (getNode(editor.snapshot, unsetNodePath))
|
|
7046
|
-
|
|
7047
|
-
|
|
7048
|
-
|
|
7049
|
-
|
|
7050
|
-
|
|
7051
|
-
|
|
7052
|
-
|
|
7042
|
+
if (getNode(editor.snapshot, unsetNodePath)) {
|
|
7043
|
+
if (unsetPropertyPath.length === 1) {
|
|
7044
|
+
let propertyName = unsetPropertyPath[0];
|
|
7045
|
+
modifyDescendant(editor, unsetNodePath, (node) => {
|
|
7046
|
+
let newNode = { ...node };
|
|
7047
|
+
return delete newNode[propertyName], newNode;
|
|
7048
|
+
});
|
|
7049
|
+
} else modifyDescendant(editor, unsetNodePath, (node) => deepUnset(node, unsetPropertyPath));
|
|
7050
|
+
} else {
|
|
7053
7051
|
let blockSegment = findBlockSegment(path);
|
|
7054
7052
|
if (!blockSegment) break;
|
|
7055
7053
|
let blockIndex = resolveBlockIndex(editor, blockSegment);
|
|
@@ -7253,23 +7251,25 @@ const apply$1 = (editor, op) => {
|
|
|
7253
7251
|
for (let ref of editor.pathRefs) PathRef.transform(ref, op);
|
|
7254
7252
|
for (let ref of editor.pointRefs) PointRef.transform(ref, op);
|
|
7255
7253
|
for (let ref of editor.rangeRefs) transformRangeRef(ref, op, editor.snapshot.context);
|
|
7256
|
-
if (applyOperation(editor, op), updateDirtyPaths(editor, getDirtyPaths(editor.snapshot.context, op)), editor.operations.push(op), normalize(editor, { operation: op }), op.type === "set.selection")
|
|
7257
|
-
|
|
7258
|
-
|
|
7259
|
-
|
|
7260
|
-
|
|
7261
|
-
|
|
7262
|
-
|
|
7263
|
-
|
|
7264
|
-
|
|
7265
|
-
|
|
7266
|
-
|
|
7267
|
-
|
|
7268
|
-
|
|
7254
|
+
if (applyOperation(editor, op), updateDirtyPaths(editor, getDirtyPaths(editor.snapshot.context, op)), editor.operations.push(op), normalize(editor, { operation: op }), op.type === "set.selection") {
|
|
7255
|
+
if (op.properties && op.newProperties && op.properties.anchor && op.properties.focus && op.newProperties.anchor && op.newProperties.focus) {
|
|
7256
|
+
let previousSelectionIsCollapsed = isCollapsedRange({
|
|
7257
|
+
anchor: op.properties.anchor,
|
|
7258
|
+
focus: op.properties.focus
|
|
7259
|
+
}), newSelectionIsCollapsed = isCollapsedRange({
|
|
7260
|
+
anchor: op.newProperties.anchor,
|
|
7261
|
+
focus: op.newProperties.focus
|
|
7262
|
+
});
|
|
7263
|
+
if (previousSelectionIsCollapsed && newSelectionIsCollapsed) {
|
|
7264
|
+
let focusSpan = getSpan(editor.snapshot, op.properties.focus.path)?.node, newFocusSpan = getSpan(editor.snapshot, op.newProperties.focus.path)?.node, sameParent = pathEquals(parentPath(op.properties.focus.path), parentPath(op.newProperties.focus.path)), movedToNextSpan = !1, movedToPreviousSpan = !1;
|
|
7265
|
+
if (sameParent && focusSpan && newFocusSpan) {
|
|
7266
|
+
let nextSibling = getSibling(editor.snapshot, op.properties.focus.path, { direction: "next" }), previousSibling = getSibling(editor.snapshot, op.properties.focus.path, { direction: "previous" });
|
|
7267
|
+
movedToNextSpan = nextSibling !== void 0 && pathEquals(nextSibling.path, op.newProperties.focus.path) && focusSpan.text.length === op.properties.focus.offset && op.newProperties.focus.offset === 0, movedToPreviousSpan = previousSibling !== void 0 && pathEquals(previousSibling.path, op.newProperties.focus.path) && op.properties.focus.offset === 0 && newFocusSpan.text.length === op.newProperties.focus.offset;
|
|
7268
|
+
}
|
|
7269
|
+
!movedToNextSpan && !movedToPreviousSpan && (editor.snapshot.decoratorState = {});
|
|
7269
7270
|
}
|
|
7270
|
-
|
|
7271
|
-
|
|
7272
|
-
} else editor.snapshot.decoratorState = {};
|
|
7271
|
+
} else editor.snapshot.decoratorState = {};
|
|
7272
|
+
}
|
|
7273
7273
|
editor.flushing || (editor.flushing = !0, Promise.resolve().then(() => {
|
|
7274
7274
|
editor.flushing = !1, editor.onChange({ operation: op }), editor.operations = [];
|
|
7275
7275
|
})), operationEvent && emitOperationEvent(editor.operationListeners.after, operationEvent);
|
|
@@ -7677,30 +7677,32 @@ function applyNodeProperties(editor, props, path) {
|
|
|
7677
7677
|
let nodeRecord = result.entry.node, propsRecord = props, keys = Object.keys(propsRecord), keyIndex = keys.indexOf("_key");
|
|
7678
7678
|
keyIndex !== -1 && (keys.splice(keyIndex, 1), keys.unshift("_key"));
|
|
7679
7679
|
let currentPath = path;
|
|
7680
|
-
for (let key of keys) if (propsRecord[key] !== nodeRecord[key])
|
|
7681
|
-
|
|
7682
|
-
|
|
7683
|
-
|
|
7680
|
+
for (let key of keys) if (propsRecord[key] !== nodeRecord[key]) {
|
|
7681
|
+
if (propsRecord[key] != null) {
|
|
7682
|
+
let hadProperty = nodeRecord.hasOwnProperty(key), lastSegment = currentPath[currentPath.length - 1], renamedPath = key === "_key" && typeof propsRecord[key] == "string" && isKeyedSegment(lastSegment) ? [...currentPath.slice(0, -1), { _key: propsRecord[key] }] : void 0, inversePath = renamedPath ? [...renamedPath, key] : [...currentPath, key];
|
|
7683
|
+
editor.apply({
|
|
7684
|
+
type: "set",
|
|
7685
|
+
path: [...currentPath, key],
|
|
7686
|
+
value: propsRecord[key],
|
|
7687
|
+
inverse: hadProperty ? {
|
|
7688
|
+
type: "set",
|
|
7689
|
+
path: inversePath,
|
|
7690
|
+
value: nodeRecord[key]
|
|
7691
|
+
} : {
|
|
7692
|
+
type: "unset",
|
|
7693
|
+
path: inversePath
|
|
7694
|
+
}
|
|
7695
|
+
}), renamedPath && (currentPath = renamedPath);
|
|
7696
|
+
} else nodeRecord.hasOwnProperty(key) && editor.apply({
|
|
7697
|
+
type: "unset",
|
|
7684
7698
|
path: [...currentPath, key],
|
|
7685
|
-
|
|
7686
|
-
inverse: hadProperty ? {
|
|
7699
|
+
inverse: {
|
|
7687
7700
|
type: "set",
|
|
7688
|
-
path:
|
|
7701
|
+
path: [...currentPath, key],
|
|
7689
7702
|
value: nodeRecord[key]
|
|
7690
|
-
} : {
|
|
7691
|
-
type: "unset",
|
|
7692
|
-
path: inversePath
|
|
7693
7703
|
}
|
|
7694
|
-
})
|
|
7695
|
-
}
|
|
7696
|
-
type: "unset",
|
|
7697
|
-
path: [...currentPath, key],
|
|
7698
|
-
inverse: {
|
|
7699
|
-
type: "set",
|
|
7700
|
-
path: [...currentPath, key],
|
|
7701
|
-
value: nodeRecord[key]
|
|
7702
|
-
}
|
|
7703
|
-
});
|
|
7704
|
+
});
|
|
7705
|
+
}
|
|
7704
7706
|
}
|
|
7705
7707
|
/**
|
|
7706
7708
|
* Create a placeholder text block -- the empty initial block used when the
|
|
@@ -7819,7 +7821,7 @@ function richDescentToParent(input, path) {
|
|
|
7819
7821
|
* 3. **Global fallback with position-validity.** Falls back to the
|
|
7820
7822
|
* top-level rich `containers` map keyed by `_type`. Activates only
|
|
7821
7823
|
* when schema-at-position permits the registered `arrayField`
|
|
7822
|
-
* (for containers) or
|
|
7824
|
+
* (for containers) or declares `_type` (for leaves).
|
|
7823
7825
|
* Registration is type-keyed; activation is position-gated.
|
|
7824
7826
|
*/
|
|
7825
7827
|
function resolveContainerByPath(input, path, node) {
|
|
@@ -8759,8 +8761,10 @@ function bitap(text, pattern, loc, opts = {}) {
|
|
|
8759
8761
|
let charMatch = s[text.charAt(j - 1)];
|
|
8760
8762
|
if (d === 0 ? rd[j] = (rd[j + 1] << 1 | 1) & charMatch : rd[j] = (rd[j + 1] << 1 | 1) & charMatch | (lastRd[j + 1] | lastRd[j]) << 1 | 1 | lastRd[j + 1], rd[j] & matchmask) {
|
|
8761
8763
|
let score = getBitapScore(d, j - 1);
|
|
8762
|
-
if (score <= scoreThreshold)
|
|
8763
|
-
|
|
8764
|
+
if (score <= scoreThreshold) {
|
|
8765
|
+
if (scoreThreshold = score, bestLoc = j - 1, bestLoc > loc) start = Math.max(1, 2 * loc - bestLoc);
|
|
8766
|
+
else break;
|
|
8767
|
+
}
|
|
8764
8768
|
}
|
|
8765
8769
|
}
|
|
8766
8770
|
if (getBitapScore(d + 1, loc) > scoreThreshold) break;
|
|
@@ -10387,9 +10391,9 @@ function isBlockLike(value) {
|
|
|
10387
10391
|
* drag origin in a way that would make the drop a no-op.
|
|
10388
10392
|
*
|
|
10389
10393
|
* Two expanded selections that only touch at a single endpoint are not treated
|
|
10390
|
-
* as a self-drop
|
|
10394
|
+
* as a self-drop: the drop position covers an adjacent block (typical when
|
|
10391
10395
|
* dragging a block-object onto the next block via the expanded fallback in
|
|
10392
|
-
* `getEventPosition`),
|
|
10396
|
+
* `getEventPosition`), so the drop should go through.
|
|
10393
10397
|
*
|
|
10394
10398
|
* Chrome drags emit a collapsed selection pointing AT the dragged container.
|
|
10395
10399
|
* A drop position whose path descends into that container is dropping the
|
|
@@ -11222,59 +11226,65 @@ function isBeforePath(path, another, root) {
|
|
|
11222
11226
|
}
|
|
11223
11227
|
const removeAnnotationOperationImplementation = ({ snapshot, operation }) => {
|
|
11224
11228
|
let editor = operation.editor, at = operation.at ? resolveSelection(operation.editor, operation.at) : null, effectiveSelection = at ?? editor.snapshot.context.selection;
|
|
11225
|
-
if (effectiveSelection)
|
|
11226
|
-
|
|
11227
|
-
|
|
11228
|
-
|
|
11229
|
-
|
|
11230
|
-
|
|
11231
|
-
|
|
11232
|
-
|
|
11233
|
-
|
|
11234
|
-
|
|
11235
|
-
|
|
11236
|
-
let
|
|
11237
|
-
|
|
11238
|
-
|
|
11239
|
-
|
|
11240
|
-
|
|
11241
|
-
|
|
11242
|
-
|
|
11243
|
-
for (let { node: child, path: childPath } of getChildren(editor.snapshot, blockPath)) if (isSpan({ schema: editor.snapshot.context.schema }, child) && isAfterPath(childPath, selectedChildPath, editor.snapshot.context)) if (child.marks?.includes(annotationToRemove)) nextSpansWithSameAnnotation.push([child, childPath]);
|
|
11244
|
-
else break;
|
|
11245
|
-
for (let [child, childPath] of [
|
|
11246
|
-
...previousSpansWithSameAnnotation,
|
|
11247
|
-
[selectedChild, selectedChildPath],
|
|
11248
|
-
...nextSpansWithSameAnnotation
|
|
11249
|
-
]) applyNodeProperties(editor, { marks: child.marks?.filter((mark) => mark !== annotationToRemove) }, childPath);
|
|
11250
|
-
} else {
|
|
11251
|
-
let ref = at ? rangeRef(editor, at, { affinity: "inward" }) : null;
|
|
11252
|
-
withoutNormalizing(editor, () => {
|
|
11253
|
-
let splitRange = at ?? editor.snapshot.context.selection;
|
|
11254
|
-
if (splitRange && isRange(splitRange)) {
|
|
11255
|
-
let splitLeaf = getNode(editor.snapshot, splitRange.anchor.path)?.node;
|
|
11256
|
-
if (!(splitLeaf && isCollapsedRange(splitRange) && isSpan({ schema: editor.snapshot.context.schema }, splitLeaf) && splitLeaf.text.length > 0)) {
|
|
11257
|
-
let splitRangeRef = rangeRef(editor, splitRange, { affinity: "inward" }), [splitStart, splitEnd] = rangeEdges(splitRange, editor.snapshot.context);
|
|
11258
|
-
(!isEnd(editor, splitEnd, splitEnd.path) || !isEdge(editor, splitEnd, splitEnd.path)) && applySplitNode(editor, splitEnd.path, splitEnd.offset), (!isStart(editor, splitStart, splitStart.path) || !isEdge(editor, splitStart, splitStart.path)) && applySplitNode(editor, splitStart.path, splitStart.offset);
|
|
11259
|
-
let updatedSplitRange = splitRangeRef.unref();
|
|
11260
|
-
!at && updatedSplitRange && applySelect(editor, updatedSplitRange);
|
|
11229
|
+
if (effectiveSelection) {
|
|
11230
|
+
if (isCollapsedRange(effectiveSelection)) {
|
|
11231
|
+
let blockEntry = getParent(snapshot, effectiveSelection.focus.path, { match: (node) => isTextBlock({ schema: editor.snapshot.context.schema }, node) });
|
|
11232
|
+
if (!blockEntry) return;
|
|
11233
|
+
let { node: block, path: blockPath } = blockEntry, potentialAnnotations = (block.markDefs ?? []).filter((markDef) => markDef._type === operation.annotation.name), selectedChildEntry = getNode(editor.snapshot, effectiveSelection.focus.path);
|
|
11234
|
+
if (!selectedChildEntry) return;
|
|
11235
|
+
let { node: selectedChild, path: selectedChildPath } = selectedChildEntry;
|
|
11236
|
+
if (!isSpan({ schema: editor.snapshot.context.schema }, selectedChild)) return;
|
|
11237
|
+
let annotationToRemove = selectedChild.marks?.find((mark) => potentialAnnotations.some((markDef) => markDef._key === mark));
|
|
11238
|
+
if (!annotationToRemove) return;
|
|
11239
|
+
let previousSpansWithSameAnnotation = [], reversedChildren = getChildren(editor.snapshot, blockPath);
|
|
11240
|
+
for (let index = reversedChildren.length - 1; index >= 0; index--) {
|
|
11241
|
+
let entry = reversedChildren[index];
|
|
11242
|
+
if (!entry) continue;
|
|
11243
|
+
let { node: child, path: childPath } = entry;
|
|
11244
|
+
if (isSpan({ schema: editor.snapshot.context.schema }, child) && isBeforePath(childPath, selectedChildPath, editor.snapshot.context)) {
|
|
11245
|
+
if (child.marks?.includes(annotationToRemove)) previousSpansWithSameAnnotation.push([child, childPath]);
|
|
11246
|
+
else break;
|
|
11261
11247
|
}
|
|
11262
11248
|
}
|
|
11263
|
-
let
|
|
11264
|
-
|
|
11265
|
-
|
|
11266
|
-
|
|
11267
|
-
})), selectionRange = ref?.current ?? editor.snapshot.context.selection;
|
|
11268
|
-
for (let { node: block, path: blockPath } of blocks) {
|
|
11269
|
-
if (!isTextBlock({ schema: editor.snapshot.context.schema }, block)) continue;
|
|
11270
|
-
let children = getChildren(editor.snapshot, blockPath);
|
|
11271
|
-
for (let { node: child, path: childPath } of children) {
|
|
11272
|
-
if (!isSpan({ schema: editor.snapshot.context.schema }, child) || !selectionRange || !rangeIntersects(editor.snapshot, selectionRange, childPath)) continue;
|
|
11273
|
-
let markDefs = block.markDefs ?? [], marks = child.marks ?? [], marksWithoutAnnotation = marks.filter((mark) => markDefs.find((markDef) => markDef._key === mark)?._type !== operation.annotation.name);
|
|
11274
|
-
marksWithoutAnnotation.length !== marks.length && applyNodeProperties(editor, { marks: marksWithoutAnnotation }, childPath);
|
|
11275
|
-
}
|
|
11249
|
+
let nextSpansWithSameAnnotation = [];
|
|
11250
|
+
for (let { node: child, path: childPath } of getChildren(editor.snapshot, blockPath)) if (isSpan({ schema: editor.snapshot.context.schema }, child) && isAfterPath(childPath, selectedChildPath, editor.snapshot.context)) {
|
|
11251
|
+
if (child.marks?.includes(annotationToRemove)) nextSpansWithSameAnnotation.push([child, childPath]);
|
|
11252
|
+
else break;
|
|
11276
11253
|
}
|
|
11277
|
-
|
|
11254
|
+
for (let [child, childPath] of [
|
|
11255
|
+
...previousSpansWithSameAnnotation,
|
|
11256
|
+
[selectedChild, selectedChildPath],
|
|
11257
|
+
...nextSpansWithSameAnnotation
|
|
11258
|
+
]) applyNodeProperties(editor, { marks: child.marks?.filter((mark) => mark !== annotationToRemove) }, childPath);
|
|
11259
|
+
} else {
|
|
11260
|
+
let ref = at ? rangeRef(editor, at, { affinity: "inward" }) : null;
|
|
11261
|
+
withoutNormalizing(editor, () => {
|
|
11262
|
+
let splitRange = at ?? editor.snapshot.context.selection;
|
|
11263
|
+
if (splitRange && isRange(splitRange)) {
|
|
11264
|
+
let splitLeaf = getNode(editor.snapshot, splitRange.anchor.path)?.node;
|
|
11265
|
+
if (!(splitLeaf && isCollapsedRange(splitRange) && isSpan({ schema: editor.snapshot.context.schema }, splitLeaf) && splitLeaf.text.length > 0)) {
|
|
11266
|
+
let splitRangeRef = rangeRef(editor, splitRange, { affinity: "inward" }), [splitStart, splitEnd] = rangeEdges(splitRange, editor.snapshot.context);
|
|
11267
|
+
(!isEnd(editor, splitEnd, splitEnd.path) || !isEdge(editor, splitEnd, splitEnd.path)) && applySplitNode(editor, splitEnd.path, splitEnd.offset), (!isStart(editor, splitStart, splitStart.path) || !isEdge(editor, splitStart, splitStart.path)) && applySplitNode(editor, splitStart.path, splitStart.offset);
|
|
11268
|
+
let updatedSplitRange = splitRangeRef.unref();
|
|
11269
|
+
!at && updatedSplitRange && applySelect(editor, updatedSplitRange);
|
|
11270
|
+
}
|
|
11271
|
+
}
|
|
11272
|
+
let blocks = Array.from(getNodes(editor.snapshot, {
|
|
11273
|
+
from: rangeStart(effectiveSelection, editor.snapshot.context).path,
|
|
11274
|
+
to: rangeEnd(effectiveSelection, editor.snapshot.context).path,
|
|
11275
|
+
match: (node) => isTextBlock({ schema: editor.snapshot.context.schema }, node)
|
|
11276
|
+
})), selectionRange = ref?.current ?? editor.snapshot.context.selection;
|
|
11277
|
+
for (let { node: block, path: blockPath } of blocks) {
|
|
11278
|
+
if (!isTextBlock({ schema: editor.snapshot.context.schema }, block)) continue;
|
|
11279
|
+
let children = getChildren(editor.snapshot, blockPath);
|
|
11280
|
+
for (let { node: child, path: childPath } of children) {
|
|
11281
|
+
if (!isSpan({ schema: editor.snapshot.context.schema }, child) || !selectionRange || !rangeIntersects(editor.snapshot, selectionRange, childPath)) continue;
|
|
11282
|
+
let markDefs = block.markDefs ?? [], marks = child.marks ?? [], marksWithoutAnnotation = marks.filter((mark) => markDefs.find((markDef) => markDef._key === mark)?._type !== operation.annotation.name);
|
|
11283
|
+
marksWithoutAnnotation.length !== marks.length && applyNodeProperties(editor, { marks: marksWithoutAnnotation }, childPath);
|
|
11284
|
+
}
|
|
11285
|
+
}
|
|
11286
|
+
}), ref?.unref();
|
|
11287
|
+
}
|
|
11278
11288
|
}
|
|
11279
11289
|
};
|
|
11280
11290
|
/**
|
|
@@ -13014,12 +13024,13 @@ const insertChildOperationImplementation = ({ snapshot, operation }) => {
|
|
|
13014
13024
|
let node = nodeEntry.node;
|
|
13015
13025
|
if (isLeafObject(editor.snapshot, node, nodeEntry.path)) {
|
|
13016
13026
|
let nextSibling = getSibling(editor.snapshot, nodeEntry.path, { direction: "next" });
|
|
13017
|
-
if (nextSibling)
|
|
13018
|
-
path,
|
|
13019
|
-
|
|
13020
|
-
|
|
13021
|
-
|
|
13022
|
-
|
|
13027
|
+
if (nextSibling) {
|
|
13028
|
+
if (getSpan(editor.snapshot, nextSibling.path)) path = nextSibling.path, offset = 0, applySelect(editor, {
|
|
13029
|
+
path,
|
|
13030
|
+
offset
|
|
13031
|
+
});
|
|
13032
|
+
else return;
|
|
13033
|
+
} else return;
|
|
13023
13034
|
}
|
|
13024
13035
|
operation.text.length > 0 && editor.apply({
|
|
13025
13036
|
type: "insert.text",
|
|
@@ -16142,49 +16153,51 @@ async function updateValue({ context, sendBack, editorEngine, streamBlocks, valu
|
|
|
16142
16153
|
if ((!value || value.length === 0) && (clearEditor({
|
|
16143
16154
|
editorEngine,
|
|
16144
16155
|
doneSyncing
|
|
16145
|
-
}), isChanged = !0), value && value.length > 0)
|
|
16146
|
-
if (
|
|
16147
|
-
|
|
16148
|
-
|
|
16149
|
-
|
|
16150
|
-
|
|
16151
|
-
|
|
16152
|
-
|
|
16156
|
+
}), isChanged = !0), value && value.length > 0) {
|
|
16157
|
+
if (streamBlocks) await new Promise((resolve) => {
|
|
16158
|
+
if (doneSyncing) {
|
|
16159
|
+
resolve();
|
|
16160
|
+
return;
|
|
16161
|
+
}
|
|
16162
|
+
isChanged = removeExtraBlocks({
|
|
16163
|
+
editorEngine,
|
|
16164
|
+
value
|
|
16165
|
+
});
|
|
16166
|
+
let processBlocks = async () => {
|
|
16167
|
+
for await (let [currentBlock, currentBlockIndex] of getStreamedBlocks({ value })) {
|
|
16168
|
+
let { blockChanged, blockValid } = syncBlock({
|
|
16169
|
+
context,
|
|
16170
|
+
sendBack,
|
|
16171
|
+
block: currentBlock,
|
|
16172
|
+
index: currentBlockIndex,
|
|
16173
|
+
editorEngine,
|
|
16174
|
+
value
|
|
16175
|
+
});
|
|
16176
|
+
if (isChanged = blockChanged || isChanged, isValid &&= blockValid, !isValid) break;
|
|
16177
|
+
}
|
|
16178
|
+
resolve();
|
|
16179
|
+
};
|
|
16180
|
+
processBlocks();
|
|
16153
16181
|
});
|
|
16154
|
-
|
|
16155
|
-
|
|
16182
|
+
else {
|
|
16183
|
+
if (doneSyncing) return;
|
|
16184
|
+
isChanged = removeExtraBlocks({
|
|
16185
|
+
editorEngine,
|
|
16186
|
+
value
|
|
16187
|
+
});
|
|
16188
|
+
let index = 0;
|
|
16189
|
+
for (let block of value) {
|
|
16156
16190
|
let { blockChanged, blockValid } = syncBlock({
|
|
16157
16191
|
context,
|
|
16158
16192
|
sendBack,
|
|
16159
|
-
block
|
|
16160
|
-
index
|
|
16193
|
+
block,
|
|
16194
|
+
index,
|
|
16161
16195
|
editorEngine,
|
|
16162
16196
|
value
|
|
16163
16197
|
});
|
|
16164
|
-
if (isChanged = blockChanged || isChanged, isValid &&= blockValid, !
|
|
16198
|
+
if (isChanged = blockChanged || isChanged, isValid &&= blockValid, !blockValid) break;
|
|
16199
|
+
index++;
|
|
16165
16200
|
}
|
|
16166
|
-
resolve();
|
|
16167
|
-
};
|
|
16168
|
-
processBlocks();
|
|
16169
|
-
});
|
|
16170
|
-
else {
|
|
16171
|
-
if (doneSyncing) return;
|
|
16172
|
-
isChanged = removeExtraBlocks({
|
|
16173
|
-
editorEngine,
|
|
16174
|
-
value
|
|
16175
|
-
});
|
|
16176
|
-
let index = 0;
|
|
16177
|
-
for (let block of value) {
|
|
16178
|
-
let { blockChanged, blockValid } = syncBlock({
|
|
16179
|
-
context,
|
|
16180
|
-
sendBack,
|
|
16181
|
-
block,
|
|
16182
|
-
index,
|
|
16183
|
-
editorEngine,
|
|
16184
|
-
value
|
|
16185
|
-
});
|
|
16186
|
-
if (isChanged = blockChanged || isChanged, isValid &&= blockValid, !blockValid) break;
|
|
16187
|
-
index++;
|
|
16188
16201
|
}
|
|
16189
16202
|
}
|
|
16190
16203
|
if (!isValid) {
|