@portabletext/editor 8.0.3 → 8.1.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/lib/{behavior.types.action-C6D8CCF9.d.ts → behavior.types.action-C0XDEQnB.d.ts} +18 -1
- package/lib/behavior.types.action-C0XDEQnB.d.ts.map +1 -0
- package/lib/behaviors/index.d.ts +1 -1
- package/lib/{get-container-D1nM_ww9.js → get-container-D2pN5Npr.js} +3 -3
- package/lib/{get-container-D1nM_ww9.js.map → get-container-D2pN5Npr.js.map} +1 -1
- package/lib/{get-parent-Ci5241qs.js → get-parent-DgaKcy8-.js} +18 -12
- package/lib/get-parent-DgaKcy8-.js.map +1 -0
- package/lib/{get-path-sub-schema-CZd9VcVM.js → get-path-sub-schema-Dd0QYZ0m.js} +2 -2
- package/lib/{get-path-sub-schema-CZd9VcVM.js.map → get-path-sub-schema-Dd0QYZ0m.js.map} +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.js +290 -205
- package/lib/index.js.map +1 -1
- package/lib/plugins/index.d.ts +1 -1
- package/lib/{selector.is-selecting-entire-blocks-DPnzucrd.js → selector.is-selecting-entire-blocks-BFhnnkHf.js} +4 -4
- package/lib/{selector.is-selecting-entire-blocks-DPnzucrd.js.map → selector.is-selecting-entire-blocks-BFhnnkHf.js.map} +1 -1
- package/lib/selectors/index.d.ts +1 -1
- package/lib/selectors/index.js +4 -4
- package/lib/traversal/index.d.ts +1 -1
- package/lib/traversal/index.js +3 -3
- package/lib/{util.is-equal-selections-N1hxVUbE.js → util.is-equal-selections-BdK98okY.js} +2 -2
- package/lib/{util.is-equal-selections-N1hxVUbE.js.map → util.is-equal-selections-BdK98okY.js.map} +1 -1
- package/lib/{util.slice-blocks-B2fZcNok.js → util.slice-blocks-_ElaB53f.js} +2 -2
- package/lib/{util.slice-blocks-B2fZcNok.js.map → util.slice-blocks-_ElaB53f.js.map} +1 -1
- package/lib/utils/index.d.ts +1 -1
- package/lib/utils/index.js +3 -3
- package/package.json +1 -1
- package/lib/behavior.types.action-C6D8CCF9.d.ts.map +0 -1
- package/lib/get-parent-Ci5241qs.js.map +0 -1
package/lib/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
import { C as getAncestors, S as hasNode, _ as comparePoints, a as isInline, b as isEditableContainer, c as isSpanNode, d as resolveChildEntryIndex, f as isAncestorPath, g as isAfterPoint, h as isBackwardRange, i as getEnclosingBlock, l as getSibling, m as rangeEdges, n as getEnclosingContainer, o as getBlock, p as isTextBlockNode, s as isBlock, t as getPathSubSchema, u as getNodes, v as comparePaths, x as resolveContainerAt, y as isObject } from "./get-path-sub-schema-
|
|
3
|
-
import { _ as getAncestor, a as getTextBlock, c as pathContains, d as isRange, f as isPoint, g as isLeafObject, h as getLeaf, i as getFirstChild, l as getSpan, m as isPath, n as getUnionSchema, o as rangeIntersects, p as isObject$1, r as getLastChild, s as isBeforePoint, t as getContainer, u as getText } from "./get-container-
|
|
4
|
-
import { a as parseBlocks, b as childAtTextOffset, c as parseSpan, d as getSelectionEndPoint, f as isSelectionCollapsed, g as isEqualSelectionPoints, h as getBlockKeyFromSelectionPoint, i as parseBlock, l as defaultKeyGenerator, m as getBlockEndPoint, n as isListBlock, o as parseInlineObject, p as getBlockStartPoint, r as parseAnnotation, s as parseMarkDefs, u as getSelectionStartPoint, v as blockOffsetToSpanSelectionPoint, x as textOffsetOfChild } from "./util.slice-blocks-
|
|
5
|
-
import { A as getSelectionEndPoint$1, B as getFocusBlock, C as getSelectedTextBlocks, D as getPreviousSpan, F as getSelectionEndBlock, G as rangesOverlap, H as getFocusInlineObject, I as getFragment, L as getSelectedValue, M as isSelectionCollapsed$1, N as isOverlappingSelection, O as getSelectionStartPoint$1, P as getSelectionStartBlock, R as getRootAcceptedTypes, S as getActiveDecorators, T as getMarkState, U as getFocusChild, V as getFocusSpan, a as isActiveListItem, b as getActiveAnnotations, c as getSelectionEndChild, d as getLastBlock, f as getFocusListBlock, i as isActiveStyle, j as isSelectionExpanded, k as getNextSpan, l as getPreviousBlock, m as getCaretWordSelection, n as isAtTheStartOfBlock, o as isActiveDecorator, p as getFocusBlockObject, r as isAtTheEndOfBlock, s as getSelectionStartChild, t as isSelectingEntireBlocks, u as getNextBlock, w as getActiveAnnotationsMarks, x as isActiveAnnotation, z as getFocusTextBlock } from "./selector.is-selecting-entire-blocks-
|
|
6
|
-
import { n as isEmptyTextBlock, r as getTextBlockText, t as isEqualSelections } from "./util.is-equal-selections-
|
|
1
|
+
import { a as getChildren, d as isKeyedSegment, i as resolveNode, n as parentPath, o as getNodeChildren, r as getNode, t as getParent, u as serializePath } from "./get-parent-DgaKcy8-.js";
|
|
2
|
+
import { C as getAncestors, S as hasNode, _ as comparePoints, a as isInline, b as isEditableContainer, c as isSpanNode, d as resolveChildEntryIndex, f as isAncestorPath, g as isAfterPoint, h as isBackwardRange, i as getEnclosingBlock, l as getSibling, m as rangeEdges, n as getEnclosingContainer, o as getBlock, p as isTextBlockNode, s as isBlock, t as getPathSubSchema, u as getNodes, v as comparePaths, x as resolveContainerAt, y as isObject } from "./get-path-sub-schema-Dd0QYZ0m.js";
|
|
3
|
+
import { _ as getAncestor, a as getTextBlock, c as pathContains, d as isRange, f as isPoint, g as isLeafObject, h as getLeaf, i as getFirstChild, l as getSpan, m as isPath, n as getUnionSchema, o as rangeIntersects, p as isObject$1, r as getLastChild, s as isBeforePoint, t as getContainer, u as getText } from "./get-container-D2pN5Npr.js";
|
|
4
|
+
import { a as parseBlocks, b as childAtTextOffset, c as parseSpan, d as getSelectionEndPoint, f as isSelectionCollapsed, g as isEqualSelectionPoints, h as getBlockKeyFromSelectionPoint, i as parseBlock, l as defaultKeyGenerator, m as getBlockEndPoint, n as isListBlock, o as parseInlineObject, p as getBlockStartPoint, r as parseAnnotation, s as parseMarkDefs, u as getSelectionStartPoint, v as blockOffsetToSpanSelectionPoint, x as textOffsetOfChild } from "./util.slice-blocks-_ElaB53f.js";
|
|
5
|
+
import { A as getSelectionEndPoint$1, B as getFocusBlock, C as getSelectedTextBlocks, D as getPreviousSpan, F as getSelectionEndBlock, G as rangesOverlap, H as getFocusInlineObject, I as getFragment, L as getSelectedValue, M as isSelectionCollapsed$1, N as isOverlappingSelection, O as getSelectionStartPoint$1, P as getSelectionStartBlock, R as getRootAcceptedTypes, S as getActiveDecorators, T as getMarkState, U as getFocusChild, V as getFocusSpan, a as isActiveListItem, b as getActiveAnnotations, c as getSelectionEndChild, d as getLastBlock, f as getFocusListBlock, i as isActiveStyle, j as isSelectionExpanded, k as getNextSpan, l as getPreviousBlock, m as getCaretWordSelection, n as isAtTheStartOfBlock, o as isActiveDecorator, p as getFocusBlockObject, r as isAtTheEndOfBlock, s as getSelectionStartChild, t as isSelectingEntireBlocks, u as getNextBlock, w as getActiveAnnotationsMarks, x as isActiveAnnotation, z as getFocusTextBlock } from "./selector.is-selecting-entire-blocks-BFhnnkHf.js";
|
|
6
|
+
import { n as isEmptyTextBlock, r as getTextBlockText, t as isEqualSelections } from "./util.is-equal-selections-BdK98okY.js";
|
|
7
7
|
import { a as raise$1, i as forward, n as effect, t as defineBehavior } from "./behavior.types.behavior-BxSLb73I.js";
|
|
8
8
|
import { n as EditorContext$1, t as useEditor } from "./use-editor-CwNeVwVC.js";
|
|
9
9
|
import { c } from "react/compiler-runtime";
|
|
@@ -746,6 +746,40 @@ function move(editor, options = {}) {
|
|
|
746
746
|
}
|
|
747
747
|
editor.setSelection(props);
|
|
748
748
|
}
|
|
749
|
+
function subscribeToOperations(editor, listener, options) {
|
|
750
|
+
let phase = options?.phase ?? "after";
|
|
751
|
+
return editor.operationListeners[phase] = [...editor.operationListeners[phase], listener], () => {
|
|
752
|
+
let listeners = editor.operationListeners[phase], index = listeners.indexOf(listener);
|
|
753
|
+
index !== -1 && (editor.operationListeners[phase] = [...listeners.slice(0, index), ...listeners.slice(index + 1)]);
|
|
754
|
+
};
|
|
755
|
+
}
|
|
756
|
+
/**
|
|
757
|
+
* Captures the operation together with the engine state that `after`
|
|
758
|
+
* listeners can no longer read once the operation has been applied. All
|
|
759
|
+
* engine flags are stable for the duration of a single apply call, so
|
|
760
|
+
* capturing them at entry is equivalent to reading them at any point during
|
|
761
|
+
* the apply.
|
|
762
|
+
*/
|
|
763
|
+
function createOperationEvent(editor, operation) {
|
|
764
|
+
let isNormalizingNode = !!editor.isNormalizingNode, isProcessingRemoteChanges = !!editor.isProcessingRemoteChanges, isUndoing = !!editor.isUndoing, isRedoing = !!editor.isRedoing;
|
|
765
|
+
return {
|
|
766
|
+
operation,
|
|
767
|
+
beforeValue: editor.snapshot.context.value,
|
|
768
|
+
beforeSelection: editor.snapshot.context.selection,
|
|
769
|
+
operationsInProgress: editor.operations.length > 0,
|
|
770
|
+
isNormalizingNode,
|
|
771
|
+
isPatching: !!editor.isPatching,
|
|
772
|
+
isProcessingRemoteChanges,
|
|
773
|
+
isUndoing,
|
|
774
|
+
isRedoing,
|
|
775
|
+
withHistory: !!editor.withHistory,
|
|
776
|
+
undoStepId: editor.undoStepId,
|
|
777
|
+
origin: isProcessingRemoteChanges ? "remote" : isUndoing ? "undo" : isRedoing ? "redo" : isNormalizingNode ? "normalization" : "local"
|
|
778
|
+
};
|
|
779
|
+
}
|
|
780
|
+
function emitOperationEvent(listeners, event) {
|
|
781
|
+
for (let index = 0; index < listeners.length; index++) listeners[index]?.(event);
|
|
782
|
+
}
|
|
749
783
|
const bold$1 = createKeyboardShortcut({
|
|
750
784
|
default: [{
|
|
751
785
|
key: "B",
|
|
@@ -2789,9 +2823,12 @@ const RestoreDOM = IS_ANDROID ? RestoreDOMComponent : ({ children }) => /* @__PU
|
|
|
2789
2823
|
editor.forceRender = forceRender, editor.readOnly = readOnly;
|
|
2790
2824
|
let state = useMemo(() => ({
|
|
2791
2825
|
isUpdatingSelection: !1,
|
|
2792
|
-
latestElement: null
|
|
2826
|
+
latestElement: null,
|
|
2827
|
+
localContentChangePending: !1
|
|
2793
2828
|
}), []);
|
|
2794
|
-
useEffect(() => {
|
|
2829
|
+
useEffect(() => subscribeToOperations(editor, (event) => {
|
|
2830
|
+
event.operation.type !== "set.selection" && (event.origin === "local" || event.origin === "undo" || event.origin === "redo") && (state.localContentChangePending = !0);
|
|
2831
|
+
}), [editor, state]), useEffect(() => {
|
|
2795
2832
|
ref.current && autoFocus && ref.current.focus();
|
|
2796
2833
|
}, [autoFocus]);
|
|
2797
2834
|
/**
|
|
@@ -2846,6 +2883,8 @@ const RestoreDOM = IS_ANDROID ? RestoreDOMComponent : ({ children }) => /* @__PU
|
|
|
2846
2883
|
onDOMSelectionChange,
|
|
2847
2884
|
scheduleOnDOMSelectionChange
|
|
2848
2885
|
}), useIsomorphicLayoutEffect(() => {
|
|
2886
|
+
let hadPendingLocalContentChange = state.localContentChangePending;
|
|
2887
|
+
state.localContentChangePending = !1;
|
|
2849
2888
|
let window = null;
|
|
2850
2889
|
ref.current && (window = getDefaultView(ref.current)) && (editor.domWindow = window, editor.domElement = ref.current);
|
|
2851
2890
|
let { selection } = editor.snapshot.context, root = DOMEditor.findDocumentOrShadowRoot(editor), domSelection = getSelection(root);
|
|
@@ -2864,7 +2903,13 @@ const RestoreDOM = IS_ANDROID ? RestoreDOMComponent : ({ children }) => /* @__PU
|
|
|
2864
2903
|
exactMatch: !0,
|
|
2865
2904
|
suppressThrow: !0
|
|
2866
2905
|
});
|
|
2867
|
-
if (editorSelection && rangeEquals(editorSelection, selection))
|
|
2906
|
+
if (editorSelection && rangeEquals(editorSelection, selection)) {
|
|
2907
|
+
if (hadPendingLocalContentChange) try {
|
|
2908
|
+
let domRange = DOMEditor.toDOMRange(editor, selection);
|
|
2909
|
+
scrollSelectionIntoView(editor, domRange);
|
|
2910
|
+
} catch {}
|
|
2911
|
+
return;
|
|
2912
|
+
}
|
|
2868
2913
|
}
|
|
2869
2914
|
if (selection && !DOMEditor.hasRange(editor, selection)) {
|
|
2870
2915
|
let fallbackRange = DOMEditor.toEditorSelection(editor, domSelection, {
|
|
@@ -4116,40 +4161,6 @@ function performHotkey({ editorActor, editor, portableTextEditor, hotkeys, event
|
|
|
4116
4161
|
}
|
|
4117
4162
|
});
|
|
4118
4163
|
}
|
|
4119
|
-
function subscribeToOperations(editor, listener, options) {
|
|
4120
|
-
let phase = options?.phase ?? "after";
|
|
4121
|
-
return editor.operationListeners[phase] = [...editor.operationListeners[phase], listener], () => {
|
|
4122
|
-
let listeners = editor.operationListeners[phase], index = listeners.indexOf(listener);
|
|
4123
|
-
index !== -1 && (editor.operationListeners[phase] = [...listeners.slice(0, index), ...listeners.slice(index + 1)]);
|
|
4124
|
-
};
|
|
4125
|
-
}
|
|
4126
|
-
/**
|
|
4127
|
-
* Captures the operation together with the engine state that `after`
|
|
4128
|
-
* listeners can no longer read once the operation has been applied. All
|
|
4129
|
-
* engine flags are stable for the duration of a single apply call, so
|
|
4130
|
-
* capturing them at entry is equivalent to reading them at any point during
|
|
4131
|
-
* the apply.
|
|
4132
|
-
*/
|
|
4133
|
-
function createOperationEvent(editor, operation) {
|
|
4134
|
-
let isNormalizingNode = !!editor.isNormalizingNode, isProcessingRemoteChanges = !!editor.isProcessingRemoteChanges, isUndoing = !!editor.isUndoing, isRedoing = !!editor.isRedoing;
|
|
4135
|
-
return {
|
|
4136
|
-
operation,
|
|
4137
|
-
beforeValue: editor.snapshot.context.value,
|
|
4138
|
-
beforeSelection: editor.snapshot.context.selection,
|
|
4139
|
-
operationsInProgress: editor.operations.length > 0,
|
|
4140
|
-
isNormalizingNode,
|
|
4141
|
-
isPatching: !!editor.isPatching,
|
|
4142
|
-
isProcessingRemoteChanges,
|
|
4143
|
-
isUndoing,
|
|
4144
|
-
isRedoing,
|
|
4145
|
-
withHistory: !!editor.withHistory,
|
|
4146
|
-
undoStepId: editor.undoStepId,
|
|
4147
|
-
origin: isProcessingRemoteChanges ? "remote" : isUndoing ? "undo" : isRedoing ? "redo" : isNormalizingNode ? "normalization" : "local"
|
|
4148
|
-
};
|
|
4149
|
-
}
|
|
4150
|
-
function emitOperationEvent(listeners, event) {
|
|
4151
|
-
for (let index = 0; index < listeners.length; index++) listeners[index]?.(event);
|
|
4152
|
-
}
|
|
4153
4164
|
function isForwardRange(range, root) {
|
|
4154
4165
|
return !isBackwardRange(range, root);
|
|
4155
4166
|
}
|
|
@@ -4192,7 +4203,12 @@ const engineOperationCallback = ({ input, sendBack }) => subscribeToOperations(i
|
|
|
4192
4203
|
operation: event.operation,
|
|
4193
4204
|
origin: event.origin
|
|
4194
4205
|
});
|
|
4195
|
-
}, { phase: "before" })
|
|
4206
|
+
}, { phase: "before" });
|
|
4207
|
+
function mergeRangeDecoration(leaf, decoration) {
|
|
4208
|
+
let { rangeDecoration } = decoration;
|
|
4209
|
+
leaf.rangeDecorations = [...leaf.rangeDecorations ?? [], rangeDecoration];
|
|
4210
|
+
}
|
|
4211
|
+
const rangeDecorationsMachine = setup({
|
|
4196
4212
|
types: {
|
|
4197
4213
|
context: {},
|
|
4198
4214
|
input: {},
|
|
@@ -4213,6 +4229,7 @@ const engineOperationCallback = ({ input, sendBack }) => subscribeToOperations(i
|
|
|
4213
4229
|
}
|
|
4214
4230
|
rangeDecorationState.push({
|
|
4215
4231
|
rangeDecoration,
|
|
4232
|
+
merge: mergeRangeDecoration,
|
|
4216
4233
|
...rangeDecoration.selection
|
|
4217
4234
|
});
|
|
4218
4235
|
}
|
|
@@ -4232,6 +4249,7 @@ const engineOperationCallback = ({ input, sendBack }) => subscribeToOperations(i
|
|
|
4232
4249
|
}
|
|
4233
4250
|
rangeDecorationState.push({
|
|
4234
4251
|
rangeDecoration,
|
|
4252
|
+
merge: mergeRangeDecoration,
|
|
4235
4253
|
...rangeDecoration.selection
|
|
4236
4254
|
});
|
|
4237
4255
|
}
|
|
@@ -4260,7 +4278,8 @@ const engineOperationCallback = ({ input, sendBack }) => subscribeToOperations(i
|
|
|
4260
4278
|
rangeDecoration: {
|
|
4261
4279
|
...decoratedRange.rangeDecoration,
|
|
4262
4280
|
selection: newRange || currentSelection
|
|
4263
|
-
}
|
|
4281
|
+
},
|
|
4282
|
+
merge: mergeRangeDecoration
|
|
4264
4283
|
});
|
|
4265
4284
|
}
|
|
4266
4285
|
context.editorEngine.decoratedRanges = rangeDecorationState;
|
|
@@ -5168,29 +5187,33 @@ const PLACEHOLDER_STYLE = {
|
|
|
5168
5187
|
right: 0
|
|
5169
5188
|
};
|
|
5170
5189
|
function RenderLeaf(props) {
|
|
5171
|
-
let $ = c(
|
|
5190
|
+
let $ = c(16), schema = props.schema;
|
|
5172
5191
|
if (props.leaf._type !== schema.span.name) return props.children;
|
|
5173
5192
|
let t0;
|
|
5174
5193
|
$[0] === props ? t0 = $[1] : (t0 = /* @__PURE__ */ jsx(RenderSpan, { ...props }), $[0] = props, $[1] = t0);
|
|
5175
|
-
let renderedSpan
|
|
5176
|
-
if (props.
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
|
|
5184
|
-
|
|
5185
|
-
|
|
5186
|
-
|
|
5187
|
-
|
|
5188
|
-
|
|
5189
|
-
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
|
|
5193
|
-
|
|
5194
|
+
let renderedSpan, t1;
|
|
5195
|
+
if ($[2] !== props.leaf.placeholder || $[3] !== props.leaf.rangeDecorations || $[4] !== props.renderPlaceholder || $[5] !== props.text || $[6] !== t0) {
|
|
5196
|
+
t1 = Symbol.for("react.early_return_sentinel");
|
|
5197
|
+
bb0: {
|
|
5198
|
+
if (renderedSpan = t0, props.renderPlaceholder && props.leaf.placeholder && props.text.text === "") {
|
|
5199
|
+
let t2;
|
|
5200
|
+
$[9] === props.renderPlaceholder ? t2 = $[10] : (t2 = props.renderPlaceholder(), $[9] = props.renderPlaceholder, $[10] = t2);
|
|
5201
|
+
let t3;
|
|
5202
|
+
$[11] === t2 ? t3 = $[12] : (t3 = /* @__PURE__ */ jsx("span", {
|
|
5203
|
+
style: PLACEHOLDER_STYLE,
|
|
5204
|
+
contentEditable: !1,
|
|
5205
|
+
children: t2
|
|
5206
|
+
}), $[11] = t2, $[12] = t3);
|
|
5207
|
+
let t4;
|
|
5208
|
+
$[13] !== renderedSpan || $[14] !== t3 ? (t4 = /* @__PURE__ */ jsxs(Fragment, { children: [t3, renderedSpan] }), $[13] = renderedSpan, $[14] = t3, $[15] = t4) : t4 = $[15], t1 = t4;
|
|
5209
|
+
break bb0;
|
|
5210
|
+
}
|
|
5211
|
+
let rangeDecorations = props.leaf.rangeDecorations;
|
|
5212
|
+
if (rangeDecorations) for (let rangeDecoration of [...rangeDecorations].reverse()) renderedSpan = rangeDecoration.component({ children: renderedSpan });
|
|
5213
|
+
}
|
|
5214
|
+
$[2] = props.leaf.placeholder, $[3] = props.leaf.rangeDecorations, $[4] = props.renderPlaceholder, $[5] = props.text, $[6] = t0, $[7] = renderedSpan, $[8] = t1;
|
|
5215
|
+
} else renderedSpan = $[7], t1 = $[8];
|
|
5216
|
+
return t1 === Symbol.for("react.early_return_sentinel") ? renderedSpan : t1;
|
|
5194
5217
|
}
|
|
5195
5218
|
function RenderText(props) {
|
|
5196
5219
|
let $ = c(3), t0;
|
|
@@ -7543,8 +7566,7 @@ function applyMergeNode(editor, path, position) {
|
|
|
7543
7566
|
if (!prevEntry || !isTextBlock({ schema: editor.snapshot.context.schema }, prevEntry.node)) return;
|
|
7544
7567
|
let prevChildren = prevEntry.node.children, lastInsertedKey = prevChildren.length > 0 ? prevChildren[prevChildren.length - 1]._key : void 0;
|
|
7545
7568
|
for (let i = 0; i < node.children.length; i++) {
|
|
7546
|
-
let child = node.children[i]
|
|
7547
|
-
lastInsertedKey === void 0 ? editor.apply({
|
|
7569
|
+
let child = node.children[i], operation = lastInsertedKey === void 0 ? {
|
|
7548
7570
|
type: "insert",
|
|
7549
7571
|
path: [
|
|
7550
7572
|
...prevPath,
|
|
@@ -7553,7 +7575,7 @@ function applyMergeNode(editor, path, position) {
|
|
|
7553
7575
|
],
|
|
7554
7576
|
node: child,
|
|
7555
7577
|
position: "before"
|
|
7556
|
-
}
|
|
7578
|
+
} : {
|
|
7557
7579
|
type: "insert",
|
|
7558
7580
|
path: [
|
|
7559
7581
|
...prevPath,
|
|
@@ -7562,7 +7584,8 @@ function applyMergeNode(editor, path, position) {
|
|
|
7562
7584
|
],
|
|
7563
7585
|
node: child,
|
|
7564
7586
|
position: "after"
|
|
7565
|
-
}
|
|
7587
|
+
};
|
|
7588
|
+
editor.apply(operation), lastInsertedKey = operation.node._key;
|
|
7566
7589
|
}
|
|
7567
7590
|
editor.apply({
|
|
7568
7591
|
type: "unset",
|
|
@@ -7639,33 +7662,6 @@ function transformPointForMerge(point, mergePath, prevKey, position) {
|
|
|
7639
7662
|
};
|
|
7640
7663
|
}
|
|
7641
7664
|
/**
|
|
7642
|
-
* Create a placeholder text block -- the empty initial block used when the
|
|
7643
|
-
* editor value is empty or when a container needs a default child.
|
|
7644
|
-
*
|
|
7645
|
-
* When `path` is provided and points into a container, the placeholder
|
|
7646
|
-
* uses the container's default style. Without `path`, or at root depth,
|
|
7647
|
-
* falls back to the root schema's first style.
|
|
7648
|
-
*/
|
|
7649
|
-
function createPlaceholderBlock(snapshot, path) {
|
|
7650
|
-
let style = resolveDefaultStyle(snapshot, path);
|
|
7651
|
-
return {
|
|
7652
|
-
_type: snapshot.context.schema.block.name,
|
|
7653
|
-
_key: snapshot.context.keyGenerator(),
|
|
7654
|
-
style,
|
|
7655
|
-
markDefs: [],
|
|
7656
|
-
children: [{
|
|
7657
|
-
_type: snapshot.context.schema.span.name,
|
|
7658
|
-
_key: snapshot.context.keyGenerator(),
|
|
7659
|
-
text: "",
|
|
7660
|
-
marks: []
|
|
7661
|
-
}]
|
|
7662
|
-
};
|
|
7663
|
-
}
|
|
7664
|
-
function resolveDefaultStyle(snapshot, path) {
|
|
7665
|
-
let rootFallback = snapshot.context.schema.styles[0]?.name ?? "normal";
|
|
7666
|
-
return path ? getPathSubSchema(snapshot, path).styles[0]?.name ?? rootFallback : rootFallback;
|
|
7667
|
-
}
|
|
7668
|
-
/**
|
|
7669
7665
|
* Apply property changes at a known path using primitive `set` and `unset`
|
|
7670
7666
|
* operations.
|
|
7671
7667
|
*
|
|
@@ -7674,10 +7670,11 @@ function resolveDefaultStyle(snapshot, path) {
|
|
|
7674
7670
|
* downstream patch consumers see the key change before any property
|
|
7675
7671
|
* mutations that reference the new key.
|
|
7676
7672
|
*/
|
|
7677
|
-
function
|
|
7678
|
-
let
|
|
7679
|
-
if (
|
|
7680
|
-
|
|
7673
|
+
function applyNodeProperties(editor, props, path) {
|
|
7674
|
+
let result = resolveNode(editor.snapshot, path);
|
|
7675
|
+
if (result.status === "unreachable") throw Error(`Unable to apply properties at structurally unreachable path ${safeStringify(path)}`);
|
|
7676
|
+
if (result.status === "missing") return;
|
|
7677
|
+
let nodeRecord = result.entry.node, propsRecord = props, keys = Object.keys(propsRecord), keyIndex = keys.indexOf("_key");
|
|
7681
7678
|
keyIndex !== -1 && (keys.splice(keyIndex, 1), keys.unshift("_key"));
|
|
7682
7679
|
let currentPath = path;
|
|
7683
7680
|
for (let key of keys) if (propsRecord[key] !== nodeRecord[key]) if (propsRecord[key] != null) {
|
|
@@ -7706,6 +7703,33 @@ function setNodeProperties(editor, props, path) {
|
|
|
7706
7703
|
});
|
|
7707
7704
|
}
|
|
7708
7705
|
/**
|
|
7706
|
+
* Create a placeholder text block -- the empty initial block used when the
|
|
7707
|
+
* editor value is empty or when a container needs a default child.
|
|
7708
|
+
*
|
|
7709
|
+
* When `path` is provided and points into a container, the placeholder
|
|
7710
|
+
* uses the container's default style. Without `path`, or at root depth,
|
|
7711
|
+
* falls back to the root schema's first style.
|
|
7712
|
+
*/
|
|
7713
|
+
function createPlaceholderBlock(snapshot, path) {
|
|
7714
|
+
let style = resolveDefaultStyle(snapshot, path);
|
|
7715
|
+
return {
|
|
7716
|
+
_type: snapshot.context.schema.block.name,
|
|
7717
|
+
_key: snapshot.context.keyGenerator(),
|
|
7718
|
+
style,
|
|
7719
|
+
markDefs: [],
|
|
7720
|
+
children: [{
|
|
7721
|
+
_type: snapshot.context.schema.span.name,
|
|
7722
|
+
_key: snapshot.context.keyGenerator(),
|
|
7723
|
+
text: "",
|
|
7724
|
+
marks: []
|
|
7725
|
+
}]
|
|
7726
|
+
};
|
|
7727
|
+
}
|
|
7728
|
+
function resolveDefaultStyle(snapshot, path) {
|
|
7729
|
+
let rootFallback = snapshot.context.schema.styles[0]?.name ?? "normal";
|
|
7730
|
+
return path ? getPathSubSchema(snapshot, path).styles[0]?.name ?? rootFallback : rootFallback;
|
|
7731
|
+
}
|
|
7732
|
+
/**
|
|
7709
7733
|
* Read the `_type` from a pre-resolved `of` entry.
|
|
7710
7734
|
*/
|
|
7711
7735
|
function entryType(entry) {
|
|
@@ -7936,7 +7960,7 @@ const normalizeNode = (editor, entry) => {
|
|
|
7936
7960
|
* Add missing .markDefs to text block nodes
|
|
7937
7961
|
*/
|
|
7938
7962
|
if (!editor.isProcessingRemoteChanges && isTextBlockNode({ schema: editor.snapshot.context.schema }, node) && !Array.isArray(node.markDefs)) {
|
|
7939
|
-
debug.normalization("adding .markDefs to block node"),
|
|
7963
|
+
debug.normalization("adding .markDefs to block node"), applyNodeProperties(editor, { markDefs: [] }, path);
|
|
7940
7964
|
return;
|
|
7941
7965
|
}
|
|
7942
7966
|
/**
|
|
@@ -7945,7 +7969,7 @@ const normalizeNode = (editor, entry) => {
|
|
|
7945
7969
|
if (!editor.isProcessingRemoteChanges && isTextBlockNode({ schema: editor.snapshot.context.schema }, node) && node.style === void 0) {
|
|
7946
7970
|
let defaultStyle = getPathSubSchema(editor.snapshot, path).styles.at(0)?.name;
|
|
7947
7971
|
if (defaultStyle) {
|
|
7948
|
-
debug.normalization("adding .style to block node"),
|
|
7972
|
+
debug.normalization("adding .style to block node"), applyNodeProperties(editor, { style: defaultStyle }, path);
|
|
7949
7973
|
return;
|
|
7950
7974
|
}
|
|
7951
7975
|
}
|
|
@@ -7968,7 +7992,7 @@ const normalizeNode = (editor, entry) => {
|
|
|
7968
7992
|
* Add missing .marks to span nodes
|
|
7969
7993
|
*/
|
|
7970
7994
|
if (!editor.isProcessingRemoteChanges && isSpan({ schema: editor.snapshot.context.schema }, node) && !Array.isArray(node.marks)) {
|
|
7971
|
-
debug.normalization("Adding .marks to span node"),
|
|
7995
|
+
debug.normalization("Adding .marks to span node"), applyNodeProperties(editor, { marks: [] }, path);
|
|
7972
7996
|
return;
|
|
7973
7997
|
}
|
|
7974
7998
|
/**
|
|
@@ -7979,7 +8003,7 @@ const normalizeNode = (editor, entry) => {
|
|
|
7979
8003
|
if (!blockEntry) return;
|
|
7980
8004
|
let annotations = node.marks?.filter((mark) => blockEntry.node.markDefs?.some((markDef) => markDef._key === mark));
|
|
7981
8005
|
if (node.text === "" && annotations && annotations.length > 0) {
|
|
7982
|
-
debug.normalization("removing annotations from empty span node"),
|
|
8006
|
+
debug.normalization("removing annotations from empty span node"), applyNodeProperties(editor, { marks: node.marks?.filter((mark) => !annotations.includes(mark)) }, path);
|
|
7983
8007
|
return;
|
|
7984
8008
|
}
|
|
7985
8009
|
}
|
|
@@ -7990,7 +8014,7 @@ const normalizeNode = (editor, entry) => {
|
|
|
7990
8014
|
let markDefs = node.markDefs ?? [], markDefKeys = /* @__PURE__ */ new Set(), newMarkDefs = [];
|
|
7991
8015
|
for (let markDef of markDefs) markDefKeys.has(markDef._key) || (markDefKeys.add(markDef._key), newMarkDefs.push(markDef));
|
|
7992
8016
|
if (markDefs.length !== newMarkDefs.length) {
|
|
7993
|
-
debug.normalization("removing duplicate markDefs"),
|
|
8017
|
+
debug.normalization("removing duplicate markDefs"), applyNodeProperties(editor, { markDefs: newMarkDefs }, path);
|
|
7994
8018
|
return;
|
|
7995
8019
|
}
|
|
7996
8020
|
}
|
|
@@ -8000,7 +8024,7 @@ const normalizeNode = (editor, entry) => {
|
|
|
8000
8024
|
if (!editor.isProcessingRemoteChanges && isTextBlock({ schema: editor.snapshot.context.schema }, node)) {
|
|
8001
8025
|
let newMarkDefs = (node.markDefs || []).filter((def) => node.children.find((child) => isSpan({ schema: editor.snapshot.context.schema }, child) && Array.isArray(child.marks) && child.marks.includes(def._key)));
|
|
8002
8026
|
if (node.markDefs && !isEqualMarkDefs(newMarkDefs, node.markDefs)) {
|
|
8003
|
-
debug.normalization("removing markDef not in use"),
|
|
8027
|
+
debug.normalization("removing markDef not in use"), applyNodeProperties(editor, { markDefs: newMarkDefs }, path);
|
|
8004
8028
|
return;
|
|
8005
8029
|
}
|
|
8006
8030
|
}
|
|
@@ -8040,11 +8064,11 @@ const normalizeNode = (editor, entry) => {
|
|
|
8040
8064
|
_type: firstChildType.type === "object" && "name" in firstChildType ? firstChildType.name : firstChildType.type,
|
|
8041
8065
|
_key: editor.snapshot.context.keyGenerator()
|
|
8042
8066
|
}), needsField && childNode) {
|
|
8043
|
-
|
|
8067
|
+
applyNodeProperties(editor, { [arrayField.name]: [childNode] }, path);
|
|
8044
8068
|
return;
|
|
8045
8069
|
}
|
|
8046
8070
|
if (needsField) {
|
|
8047
|
-
|
|
8071
|
+
applyNodeProperties(editor, { [arrayField.name]: [] }, path);
|
|
8048
8072
|
return;
|
|
8049
8073
|
}
|
|
8050
8074
|
if (childNode) {
|
|
@@ -11166,7 +11190,7 @@ const addAnnotationOperationImplementation = ({ snapshot, operation }) => {
|
|
|
11166
11190
|
for (let { node: block, path: blockPath } of selectedBlocks) {
|
|
11167
11191
|
if (!isTextBlock({ schema: editor.snapshot.context.schema }, block) || block.children.length === 0 || block.children.length === 1 && block.children[0]?.text === "" || !getPathSubSchema(snapshot, blockPath).annotations.some((annotation) => annotation.name === parsedAnnotation._type)) continue;
|
|
11168
11192
|
let annotationKey = blockIndex === 0 ? parsedAnnotation._key : context.keyGenerator(), markDefs = block.markDefs ?? [];
|
|
11169
|
-
markDefs.find((markDef) => markDef._type === parsedAnnotation._type && markDef._key === annotationKey) === void 0 &&
|
|
11193
|
+
markDefs.find((markDef) => markDef._type === parsedAnnotation._type && markDef._key === annotationKey) === void 0 && applyNodeProperties(editor, { markDefs: [...markDefs, {
|
|
11170
11194
|
...parsedAnnotation,
|
|
11171
11195
|
_key: annotationKey
|
|
11172
11196
|
}] }, blockPath);
|
|
@@ -11184,7 +11208,7 @@ const addAnnotationOperationImplementation = ({ snapshot, operation }) => {
|
|
|
11184
11208
|
for (let { node: span, path: spanPath } of children) {
|
|
11185
11209
|
if (!isSpan({ schema: editor.snapshot.context.schema }, span) || !selectionRange || !rangeIntersects(editor.snapshot, selectionRange, spanPath)) continue;
|
|
11186
11210
|
let marks = span.marks ?? [];
|
|
11187
|
-
|
|
11211
|
+
applyNodeProperties(editor, { marks: [...marks, annotationKey] }, spanPath);
|
|
11188
11212
|
}
|
|
11189
11213
|
blockIndex++;
|
|
11190
11214
|
}
|
|
@@ -11222,7 +11246,7 @@ const removeAnnotationOperationImplementation = ({ snapshot, operation }) => {
|
|
|
11222
11246
|
...previousSpansWithSameAnnotation,
|
|
11223
11247
|
[selectedChild, selectedChildPath],
|
|
11224
11248
|
...nextSpansWithSameAnnotation
|
|
11225
|
-
])
|
|
11249
|
+
]) applyNodeProperties(editor, { marks: child.marks?.filter((mark) => mark !== annotationToRemove) }, childPath);
|
|
11226
11250
|
} else {
|
|
11227
11251
|
let ref = at ? rangeRef(editor, at, { affinity: "inward" }) : null;
|
|
11228
11252
|
withoutNormalizing(editor, () => {
|
|
@@ -11247,7 +11271,7 @@ const removeAnnotationOperationImplementation = ({ snapshot, operation }) => {
|
|
|
11247
11271
|
for (let { node: child, path: childPath } of children) {
|
|
11248
11272
|
if (!isSpan({ schema: editor.snapshot.context.schema }, child) || !selectionRange || !rangeIntersects(editor.snapshot, selectionRange, childPath)) continue;
|
|
11249
11273
|
let markDefs = block.markDefs ?? [], marks = child.marks ?? [], marksWithoutAnnotation = marks.filter((mark) => markDefs.find((markDef) => markDef._key === mark)?._type !== operation.annotation.name);
|
|
11250
|
-
marksWithoutAnnotation.length !== marks.length &&
|
|
11274
|
+
marksWithoutAnnotation.length !== marks.length && applyNodeProperties(editor, { marks: marksWithoutAnnotation }, childPath);
|
|
11251
11275
|
}
|
|
11252
11276
|
}
|
|
11253
11277
|
}), ref?.unref();
|
|
@@ -11310,7 +11334,7 @@ const blockSetOperationImplementation = ({ snapshot, operation }) => {
|
|
|
11310
11334
|
}
|
|
11311
11335
|
context.schema.block.fields?.some((field) => field.name === key) && (filteredProps[key] = operation.props[key]);
|
|
11312
11336
|
}
|
|
11313
|
-
|
|
11337
|
+
applyNodeProperties(operation.editor, filteredProps, blockEntry.path);
|
|
11314
11338
|
} else {
|
|
11315
11339
|
let schemaDefinition = getBlockObjectSchema(snapshot, engineBlock, blockEntry.path), filteredProps = {};
|
|
11316
11340
|
for (let key of Object.keys(operation.props)) if (key !== "_type") {
|
|
@@ -11321,7 +11345,7 @@ const blockSetOperationImplementation = ({ snapshot, operation }) => {
|
|
|
11321
11345
|
schemaDefinition?.fields?.some((field) => field.name === key) && (filteredProps[key] = operation.props[key]);
|
|
11322
11346
|
}
|
|
11323
11347
|
let patches = Object.entries(filteredProps).map(([key, value]) => set(value, [key])), updatedEngineBlock = applyAll(engineBlock, patches);
|
|
11324
|
-
|
|
11348
|
+
applyNodeProperties(operation.editor, updatedEngineBlock, blockEntry.path);
|
|
11325
11349
|
}
|
|
11326
11350
|
}, blockUnsetOperationImplementation = ({ snapshot, operation }) => {
|
|
11327
11351
|
let { context } = snapshot, blockEntry = getNode(operation.editor.snapshot, operation.at);
|
|
@@ -11330,12 +11354,12 @@ const blockSetOperationImplementation = ({ snapshot, operation }) => {
|
|
|
11330
11354
|
if (isTextBlockNode(context, engineBlock)) {
|
|
11331
11355
|
let propsToRemove = operation.props.filter((prop) => prop !== "_type" && prop !== "_key"), unsetProps = {};
|
|
11332
11356
|
for (let prop of propsToRemove) unsetProps[prop] = null;
|
|
11333
|
-
|
|
11357
|
+
applyNodeProperties(operation.editor, unsetProps, blockEntry.path), operation.props.includes("_key") && applyNodeProperties(operation.editor, { _key: context.keyGenerator() }, blockEntry.path);
|
|
11334
11358
|
return;
|
|
11335
11359
|
}
|
|
11336
11360
|
let unsetProps = {};
|
|
11337
11361
|
for (let key of operation.props) key !== "_type" && (key === "_key" ? unsetProps._key = context.keyGenerator() : unsetProps[key] = null);
|
|
11338
|
-
|
|
11362
|
+
applyNodeProperties(operation.editor, unsetProps, blockEntry.path);
|
|
11339
11363
|
};
|
|
11340
11364
|
/**
|
|
11341
11365
|
* Compute the canonical path that a new node will have when inserted as a
|
|
@@ -11362,7 +11386,7 @@ const childSetOperationImplementation = ({ snapshot, operation }) => {
|
|
|
11362
11386
|
let { node: child, path: childPath } = childEntry;
|
|
11363
11387
|
if (isSpan({ schema: operation.editor.snapshot.context.schema }, child)) {
|
|
11364
11388
|
let { _type, text, ...rest } = operation.props;
|
|
11365
|
-
|
|
11389
|
+
applyNodeProperties(operation.editor, {
|
|
11366
11390
|
...child,
|
|
11367
11391
|
...rest
|
|
11368
11392
|
}, childPath);
|
|
@@ -11385,7 +11409,7 @@ const childSetOperationImplementation = ({ snapshot, operation }) => {
|
|
|
11385
11409
|
if (!definition) return;
|
|
11386
11410
|
let { _type, _key, ...rest } = operation.props;
|
|
11387
11411
|
for (let prop in rest) definition.fields.some((field) => field.name === prop) || delete rest[prop];
|
|
11388
|
-
|
|
11412
|
+
applyNodeProperties(operation.editor, {
|
|
11389
11413
|
...child,
|
|
11390
11414
|
_key: typeof _key == "string" ? _key : child._key,
|
|
11391
11415
|
...rest
|
|
@@ -11406,13 +11430,13 @@ const childSetOperationImplementation = ({ snapshot, operation }) => {
|
|
|
11406
11430
|
}
|
|
11407
11431
|
newNode[prop] = null;
|
|
11408
11432
|
}
|
|
11409
|
-
|
|
11433
|
+
applyNodeProperties(operation.editor, newNode, childPath);
|
|
11410
11434
|
return;
|
|
11411
11435
|
}
|
|
11412
11436
|
if (isObject(operation.editor.snapshot, child)) {
|
|
11413
11437
|
let unsetProps = {};
|
|
11414
11438
|
for (let prop of operation.props) prop !== "_type" && (prop === "_key" ? unsetProps._key = context.keyGenerator() : unsetProps[prop] = null);
|
|
11415
|
-
|
|
11439
|
+
applyNodeProperties(operation.editor, unsetProps, childPath);
|
|
11416
11440
|
return;
|
|
11417
11441
|
}
|
|
11418
11442
|
throw Error(`Unable to determine the type of child at ${safeStringify(operation.at)}`);
|
|
@@ -11435,7 +11459,7 @@ const childSetOperationImplementation = ({ snapshot, operation }) => {
|
|
|
11435
11459
|
let blockPath = parentPath(spanPath);
|
|
11436
11460
|
if (!getPathSubSchema(snapshot, blockPath).decorators.some((decorator) => decorator.name === mark)) continue;
|
|
11437
11461
|
let marks = [...(Array.isArray(node.marks) ? node.marks : []).filter((eMark) => eMark !== mark), mark];
|
|
11438
|
-
|
|
11462
|
+
applyNodeProperties(editor, { marks }, spanPath);
|
|
11439
11463
|
}
|
|
11440
11464
|
});
|
|
11441
11465
|
} else {
|
|
@@ -11454,7 +11478,7 @@ const childSetOperationImplementation = ({ snapshot, operation }) => {
|
|
|
11454
11478
|
for (let { path: spanPath } of Array.from(getNodes(editor.snapshot, {
|
|
11455
11479
|
at: blockPath,
|
|
11456
11480
|
match: (node) => isSpan({ schema: editor.snapshot.context.schema }, node)
|
|
11457
|
-
})))
|
|
11481
|
+
}))) applyNodeProperties(editor, { marks: newMarks }, spanPath);
|
|
11458
11482
|
} else editor.snapshot.decoratorState[mark] = !0;
|
|
11459
11483
|
}
|
|
11460
11484
|
if (editor.snapshot.context.selection) {
|
|
@@ -11483,7 +11507,7 @@ const childSetOperationImplementation = ({ snapshot, operation }) => {
|
|
|
11483
11507
|
for (let { node, path: nodePath } of splitTextNodes) {
|
|
11484
11508
|
if (!isSpan({ schema: editor.snapshot.context.schema }, node)) continue;
|
|
11485
11509
|
let blockPath = parentPath(nodePath), block = getNode(editor.snapshot, blockPath)?.node;
|
|
11486
|
-
isTextBlock({ schema: editor.snapshot.context.schema }, block) && block.children.includes(node) &&
|
|
11510
|
+
isTextBlock({ schema: editor.snapshot.context.schema }, block) && block.children.includes(node) && applyNodeProperties(editor, {
|
|
11487
11511
|
marks: (Array.isArray(node.marks) ? node.marks : []).filter((eMark) => eMark !== mark),
|
|
11488
11512
|
_type: context.schema.span.name
|
|
11489
11513
|
}, nodePath);
|
|
@@ -11499,7 +11523,7 @@ const childSetOperationImplementation = ({ snapshot, operation }) => {
|
|
|
11499
11523
|
for (let { path: spanPath } of Array.from(getNodes(editor.snapshot, {
|
|
11500
11524
|
at: blockPath,
|
|
11501
11525
|
match: (node) => isSpan({ schema: editor.snapshot.context.schema }, node)
|
|
11502
|
-
})))
|
|
11526
|
+
}))) applyNodeProperties(editor, { marks: existingMarksWithoutDecorator }, spanPath);
|
|
11503
11527
|
} else editor.snapshot.decoratorState[mark] = !1;
|
|
11504
11528
|
}
|
|
11505
11529
|
if (editor.snapshot.context.selection) {
|
|
@@ -11610,6 +11634,74 @@ function fieldAcceptsTextBlock(editor, node, _path) {
|
|
|
11610
11634
|
return container ? container.field.of.some((member) => member.type === editor.snapshot.context.schema.block.name) : !1;
|
|
11611
11635
|
}
|
|
11612
11636
|
/**
|
|
11637
|
+
* A block merge folds `mergingBlock`'s children (and markDefs) into
|
|
11638
|
+
* `destinationBlock` by key. Any child key the merging block shares with
|
|
11639
|
+
* the destination has to be renamed before the merge, or the engine's own
|
|
11640
|
+
* collision handling mints a fresh key for it, which reads on the wire as
|
|
11641
|
+
* that node being destroyed and a new one created instead of moved.
|
|
11642
|
+
*
|
|
11643
|
+
* A colliding markDef that is deeply equal to the destination's is left
|
|
11644
|
+
* unrenamed and reported in `dedupedMarkDefKeys` instead: the merge keeps
|
|
11645
|
+
* a single copy under the original `_key` rather than duplicating
|
|
11646
|
+
* identical content under two keys. A colliding markDef that differs gets
|
|
11647
|
+
* renamed like a child would.
|
|
11648
|
+
*
|
|
11649
|
+
* `renamedBlock` keeps every deduped def in its own `markDefs`, even
|
|
11650
|
+
* though the destination already carries it: `renamedBlock` feeds
|
|
11651
|
+
* `insert.block` on some callers' paths, and that path parses the block
|
|
11652
|
+
* standalone, stripping any mark that doesn't resolve in the block's own
|
|
11653
|
+
* `markDefs`. A caller that appends `renamedBlock.markDefs` onto the
|
|
11654
|
+
* destination's must skip the keys listed in `dedupedMarkDefKeys`, or the
|
|
11655
|
+
* def duplicates.
|
|
11656
|
+
*
|
|
11657
|
+
* Pure: computes the renames and the block they produce without touching
|
|
11658
|
+
* an editor. Callers raise or apply the renames themselves, ahead of the
|
|
11659
|
+
* merge, against the still-living `mergingBlock`.
|
|
11660
|
+
*/
|
|
11661
|
+
function planMergeKeyRenames(args) {
|
|
11662
|
+
let { context, mergingBlock, destinationBlock } = args, destinationChildKeys = new Set(destinationBlock.children.map((child) => child._key)), destinationMarkDefsByKey = new Map((destinationBlock.markDefs ?? []).map((markDef) => [markDef._key, markDef])), markDefKeyMap = /* @__PURE__ */ new Map(), dedupedMarkDefKeys = [], renamedMarkDefs = mergingBlock.markDefs?.flatMap((markDef) => {
|
|
11663
|
+
let destinationMarkDef = destinationMarkDefsByKey.get(markDef._key);
|
|
11664
|
+
if (!destinationMarkDef) return [markDef];
|
|
11665
|
+
if (isDeepEqual(markDef, destinationMarkDef)) return dedupedMarkDefKeys.push(markDef._key), [markDef];
|
|
11666
|
+
let newKey = context.keyGenerator();
|
|
11667
|
+
return markDefKeyMap.set(markDef._key, newKey), [{
|
|
11668
|
+
...markDef,
|
|
11669
|
+
_key: newKey
|
|
11670
|
+
}];
|
|
11671
|
+
}), markDefRenames = [];
|
|
11672
|
+
for (let markDef of mergingBlock.markDefs ?? []) {
|
|
11673
|
+
let newKey = markDefKeyMap.get(markDef._key);
|
|
11674
|
+
newKey && markDefRenames.push({
|
|
11675
|
+
markDefKey: markDef._key,
|
|
11676
|
+
newKey
|
|
11677
|
+
});
|
|
11678
|
+
}
|
|
11679
|
+
let childRenames = [], renamedChildren = mergingBlock.children.map((child) => {
|
|
11680
|
+
let currentMarks = isSpan(context, child) ? child.marks : void 0, remappedMarks = currentMarks?.map((mark) => markDefKeyMap.get(mark) ?? mark), marksChanged = !!(remappedMarks && !isEqualMarks(remappedMarks, currentMarks)), newKey = destinationChildKeys.has(child._key) ? context.keyGenerator() : child._key, props = {};
|
|
11681
|
+
return newKey !== child._key && (props._key = newKey), marksChanged && (props.marks = remappedMarks), Object.keys(props).length > 0 && childRenames.push({
|
|
11682
|
+
childKey: child._key,
|
|
11683
|
+
props
|
|
11684
|
+
}), marksChanged ? {
|
|
11685
|
+
...child,
|
|
11686
|
+
_key: newKey,
|
|
11687
|
+
marks: remappedMarks
|
|
11688
|
+
} : {
|
|
11689
|
+
...child,
|
|
11690
|
+
_key: newKey
|
|
11691
|
+
};
|
|
11692
|
+
});
|
|
11693
|
+
return {
|
|
11694
|
+
renamedBlock: {
|
|
11695
|
+
...mergingBlock,
|
|
11696
|
+
children: renamedChildren,
|
|
11697
|
+
...mergingBlock.markDefs ? { markDefs: renamedMarkDefs } : {}
|
|
11698
|
+
},
|
|
11699
|
+
childRenames,
|
|
11700
|
+
markDefRenames,
|
|
11701
|
+
dedupedMarkDefKeys
|
|
11702
|
+
};
|
|
11703
|
+
}
|
|
11704
|
+
/**
|
|
11613
11705
|
* Indic scripts whose grapheme clusters span multiple code points. Backward
|
|
11614
11706
|
* character delete on these scripts removes one code point at a time instead
|
|
11615
11707
|
* of the entire cluster. Besides the script ranges, the class lists the BMP
|
|
@@ -11942,12 +12034,28 @@ function mergeBlock(editor, startBlockPath, endBlockPath, removeEmptyStartBlock)
|
|
|
11942
12034
|
removeNodeAt(editor, startBlockPath);
|
|
11943
12035
|
return;
|
|
11944
12036
|
}
|
|
11945
|
-
let
|
|
11946
|
-
|
|
11947
|
-
|
|
11948
|
-
|
|
11949
|
-
}
|
|
11950
|
-
|
|
12037
|
+
let { renamedBlock, childRenames, markDefRenames, dedupedMarkDefKeys } = planMergeKeyRenames({
|
|
12038
|
+
context: editor.snapshot.context,
|
|
12039
|
+
mergingBlock: endBlock.node,
|
|
12040
|
+
destinationBlock: startBlock.node
|
|
12041
|
+
});
|
|
12042
|
+
for (let { markDefKey, newKey } of markDefRenames) editor.apply({
|
|
12043
|
+
type: "set",
|
|
12044
|
+
path: [
|
|
12045
|
+
...endBlockPath,
|
|
12046
|
+
"markDefs",
|
|
12047
|
+
{ _key: markDefKey },
|
|
12048
|
+
"_key"
|
|
12049
|
+
],
|
|
12050
|
+
value: newKey
|
|
12051
|
+
});
|
|
12052
|
+
for (let { childKey, props } of childRenames) applyNodeProperties(editor, props, [
|
|
12053
|
+
...endBlockPath,
|
|
12054
|
+
"children",
|
|
12055
|
+
{ _key: childKey }
|
|
12056
|
+
]);
|
|
12057
|
+
let endMarkDefs = renamedBlock.markDefs?.filter((markDef) => !dedupedMarkDefKeys.includes(markDef._key));
|
|
12058
|
+
Array.isArray(endMarkDefs) && endMarkDefs.length > 0 && applyNodeProperties(editor, { markDefs: [...startBlock.node.markDefs ?? [], ...endMarkDefs] }, startBlockPath), applyMergeNode(editor, endBlockPath, startBlock.node.children.length);
|
|
11951
12059
|
}
|
|
11952
12060
|
function removeNodeAt(editor, path) {
|
|
11953
12061
|
getNode(editor.snapshot, path) && editor.apply({
|
|
@@ -12636,7 +12744,7 @@ function mergeTextBlockFragment(args) {
|
|
|
12636
12744
|
block,
|
|
12637
12745
|
endBlock
|
|
12638
12746
|
});
|
|
12639
|
-
|
|
12747
|
+
applyNodeProperties(editor, { markDefs: [...endBlock.markDefs ?? [], ...adjustedMarkDefs ?? []] }, endBlockPath);
|
|
12640
12748
|
let atPathRef = pathRef(editor, at.path), atBlockStart = pointEquals(at, start(editor, endBlockPath)), firstInsertedKey = insertFragmentChildren(editor, adjustedBlock, at), resolvedAtPath = atPathRef.unref();
|
|
12641
12749
|
if (select === "none") {
|
|
12642
12750
|
(wasCrossBlock || !atBlockStart) && applySelect(editor, at);
|
|
@@ -12744,8 +12852,12 @@ function resolveChildIndex(children, segment) {
|
|
|
12744
12852
|
}
|
|
12745
12853
|
/**
|
|
12746
12854
|
* Reassign keys on spans, inline objects and markDefs that collide with the
|
|
12747
|
-
* end block's existing keys.
|
|
12748
|
-
*
|
|
12855
|
+
* end block's existing keys. A colliding markDef that is deeply equal to
|
|
12856
|
+
* the end block's is left out of the returned `adjustedMarkDefs` instead
|
|
12857
|
+
* of renamed, since the end block already carries it; its key isn't
|
|
12858
|
+
* remapped, so the fragment's marks keep pointing at it unchanged. The
|
|
12859
|
+
* caller must merge the returned `adjustedMarkDefs` into the end block's
|
|
12860
|
+
* own `markDefs`, or the deduped defs are lost.
|
|
12749
12861
|
*/
|
|
12750
12862
|
function adjustFragmentKeys(args) {
|
|
12751
12863
|
let { context, block, endBlock } = args;
|
|
@@ -12757,15 +12869,15 @@ function adjustFragmentKeys(args) {
|
|
|
12757
12869
|
adjustedBlock: block,
|
|
12758
12870
|
adjustedMarkDefs: block.markDefs
|
|
12759
12871
|
};
|
|
12760
|
-
let endBlockChildKeys = endBlock.children.map((child) => child._key),
|
|
12761
|
-
|
|
12762
|
-
|
|
12763
|
-
|
|
12764
|
-
|
|
12765
|
-
|
|
12766
|
-
|
|
12767
|
-
|
|
12768
|
-
|
|
12872
|
+
let endBlockChildKeys = endBlock.children.map((child) => child._key), endBlockMarkDefsByKey = new Map((endBlock.markDefs ?? []).map((markDef) => [markDef._key, markDef])), markDefKeyMap = /* @__PURE__ */ new Map(), adjustedMarkDefs = block.markDefs?.flatMap((markDef) => {
|
|
12873
|
+
let endBlockMarkDef = endBlockMarkDefsByKey.get(markDef._key);
|
|
12874
|
+
if (!endBlockMarkDef) return [markDef];
|
|
12875
|
+
if (isDeepEqual(markDef, endBlockMarkDef)) return [];
|
|
12876
|
+
let newKey = context.keyGenerator();
|
|
12877
|
+
return markDefKeyMap.set(markDef._key, newKey), [{
|
|
12878
|
+
...markDef,
|
|
12879
|
+
_key: newKey
|
|
12880
|
+
}];
|
|
12769
12881
|
}), adjustedChildren = block.children.map((child) => {
|
|
12770
12882
|
if (isSpan(context, child)) {
|
|
12771
12883
|
let marks = child.marks?.map((mark) => markDefKeyMap.get(mark) ?? mark) ?? [];
|
|
@@ -13138,7 +13250,7 @@ const abstractAnnotationBehaviors = [
|
|
|
13138
13250
|
}, previousBlockEndPoint = getBlockEndPoint({
|
|
13139
13251
|
context: snapshot.context,
|
|
13140
13252
|
block: previousBlock
|
|
13141
|
-
}), { renamedBlock, renameActions } =
|
|
13253
|
+
}), { renamedBlock, renameActions } = planMergeKeyRenameActions({
|
|
13142
13254
|
context: snapshot.context,
|
|
13143
13255
|
mergingBlockPath: focusTextBlock.path,
|
|
13144
13256
|
mergingBlock: focusTextBlock.node,
|
|
@@ -13236,7 +13348,7 @@ const abstractAnnotationBehaviors = [
|
|
|
13236
13348
|
if (!focusTextBlock) return !1;
|
|
13237
13349
|
let nextSibling = getSibling(adjustedSnapshot, focusTextBlock.path, { direction: "next" });
|
|
13238
13350
|
if (!nextSibling || !isAtTheEndOfBlock(focusTextBlock)(adjustedSnapshot) || !isTextBlock(snapshot.context, nextSibling.node)) return !1;
|
|
13239
|
-
let { renamedBlock, renameActions } =
|
|
13351
|
+
let { renamedBlock, renameActions } = planMergeKeyRenameActions({
|
|
13240
13352
|
context: snapshot.context,
|
|
13241
13353
|
mergingBlockPath: nextSibling.path,
|
|
13242
13354
|
mergingBlock: nextSibling.node,
|
|
@@ -13332,65 +13444,37 @@ const abstractAnnotationBehaviors = [
|
|
|
13332
13444
|
})
|
|
13333
13445
|
];
|
|
13334
13446
|
/**
|
|
13335
|
-
*
|
|
13336
|
-
* `
|
|
13337
|
-
*
|
|
13338
|
-
* collision handling mints a fresh key for it, which reads on the wire as
|
|
13339
|
-
* that node being destroyed and a new one created instead of moved.
|
|
13340
|
-
*
|
|
13341
|
-
* Renames are raised as `set`/`child.set` events against the still-living
|
|
13342
|
-
* `mergingBlock`, so they land on the wire before the merge's `unset`.
|
|
13343
|
-
* `renamedBlock` mirrors the same renames applied to the value the caller
|
|
13344
|
-
* already captured, since raising the rename events now doesn't change
|
|
13345
|
-
* that captured value.
|
|
13447
|
+
* Raise the child/markDef renames `planMergeKeyRenames` computed as
|
|
13448
|
+
* `set`/`child.set` events against the still-living `mergingBlock`, so
|
|
13449
|
+
* they land on the wire before the merge's `unset`.
|
|
13346
13450
|
*/
|
|
13347
|
-
function
|
|
13348
|
-
let { context, mergingBlockPath, mergingBlock, destinationBlock } = args,
|
|
13349
|
-
|
|
13350
|
-
|
|
13351
|
-
|
|
13352
|
-
...markDef,
|
|
13353
|
-
_key: newKey
|
|
13354
|
-
};
|
|
13451
|
+
function planMergeKeyRenameActions(args) {
|
|
13452
|
+
let { context, mergingBlockPath, mergingBlock, destinationBlock } = args, { renamedBlock, childRenames, markDefRenames } = planMergeKeyRenames({
|
|
13453
|
+
context,
|
|
13454
|
+
mergingBlock,
|
|
13455
|
+
destinationBlock
|
|
13355
13456
|
}), renameActions = [];
|
|
13356
|
-
for (let
|
|
13357
|
-
|
|
13358
|
-
|
|
13359
|
-
|
|
13360
|
-
|
|
13361
|
-
|
|
13362
|
-
|
|
13363
|
-
|
|
13364
|
-
|
|
13365
|
-
|
|
13366
|
-
|
|
13367
|
-
|
|
13368
|
-
|
|
13369
|
-
|
|
13370
|
-
|
|
13371
|
-
|
|
13372
|
-
|
|
13373
|
-
|
|
13374
|
-
|
|
13375
|
-
"children",
|
|
13376
|
-
{ _key: child._key }
|
|
13377
|
-
],
|
|
13378
|
-
props
|
|
13379
|
-
})), marksChanged ? {
|
|
13380
|
-
...child,
|
|
13381
|
-
_key: newKey,
|
|
13382
|
-
marks: remappedMarks
|
|
13383
|
-
} : {
|
|
13384
|
-
...child,
|
|
13385
|
-
_key: newKey
|
|
13386
|
-
};
|
|
13387
|
-
});
|
|
13457
|
+
for (let { markDefKey, newKey } of markDefRenames) renameActions.push(raise$1({
|
|
13458
|
+
type: "set",
|
|
13459
|
+
at: [
|
|
13460
|
+
...mergingBlockPath,
|
|
13461
|
+
"markDefs",
|
|
13462
|
+
{ _key: markDefKey },
|
|
13463
|
+
"_key"
|
|
13464
|
+
],
|
|
13465
|
+
value: newKey
|
|
13466
|
+
}));
|
|
13467
|
+
for (let { childKey, props } of childRenames) renameActions.push(raise$1({
|
|
13468
|
+
type: "child.set",
|
|
13469
|
+
at: [
|
|
13470
|
+
...mergingBlockPath,
|
|
13471
|
+
"children",
|
|
13472
|
+
{ _key: childKey }
|
|
13473
|
+
],
|
|
13474
|
+
props
|
|
13475
|
+
}));
|
|
13388
13476
|
return {
|
|
13389
|
-
renamedBlock
|
|
13390
|
-
...mergingBlock,
|
|
13391
|
-
children: renamedChildren,
|
|
13392
|
-
...mergingBlock.markDefs ? { markDefs: renamedMarkDefs } : {}
|
|
13393
|
-
},
|
|
13477
|
+
renamedBlock,
|
|
13394
13478
|
renameActions
|
|
13395
13479
|
};
|
|
13396
13480
|
}
|
|
@@ -16299,13 +16383,13 @@ function replaceBlock({ context, editorEngine, block, index }) {
|
|
|
16299
16383
|
}
|
|
16300
16384
|
function updateBlock({ context, editorEngine, oldEngineBlock, block, index: _index }) {
|
|
16301
16385
|
let engineBlock = toEngineBlock(block, { schemaTypes: context.schema }), { children: _children, ...blockProps } = engineBlock;
|
|
16302
|
-
|
|
16386
|
+
applyNodeProperties(editorEngine, blockProps, [{ _key: oldEngineBlock._key }]);
|
|
16303
16387
|
let oldRecord = oldEngineBlock, newRecord = engineBlock, removedProperties = {};
|
|
16304
16388
|
for (let key of Object.keys(oldRecord)) key !== "children" && key !== "text" && (newRecord.hasOwnProperty(key) || (removedProperties[key] = null));
|
|
16305
|
-
if (Object.keys(removedProperties).length > 0 &&
|
|
16389
|
+
if (Object.keys(removedProperties).length > 0 && applyNodeProperties(editorEngine, removedProperties, [{ _key: oldEngineBlock._key }]), isTextBlock({ schema: editorEngine.snapshot.context.schema }, engineBlock) && isTextBlock({ schema: editorEngine.snapshot.context.schema }, oldEngineBlock)) {
|
|
16306
16390
|
let oldKeys = oldEngineBlock.children.map((c) => c._key), newKeys = engineBlock.children.map((c) => c._key), oldKeySet = new Set(oldKeys), hasSharedKeys = newKeys.some((key) => oldKeySet.has(key));
|
|
16307
16391
|
if (oldKeys.length === newKeys.length && oldKeys.length > 0 && oldKeySet.size === oldKeys.length && oldKeys.some((key, i) => key !== newKeys[i]) && newKeys.every((key) => oldKeySet.has(key)) || newKeys.length > 0 && !hasSharedKeys) {
|
|
16308
|
-
debug.syncValue("Replacing children via set"),
|
|
16392
|
+
debug.syncValue("Replacing children via set"), applyNodeProperties(editorEngine, { children: engineBlock.children }, [{ _key: oldEngineBlock._key }]), editorEngine.onChange();
|
|
16309
16393
|
return;
|
|
16310
16394
|
}
|
|
16311
16395
|
let oldBlockChildrenLength = oldEngineBlock.children.length;
|
|
@@ -16334,7 +16418,7 @@ function updateBlock({ context, editorEngine, oldEngineBlock, block, index: _ind
|
|
|
16334
16418
|
if (currentBlockChild._key === oldBlockChild?._key && currentBlockChild._type === oldBlockChild?._type) {
|
|
16335
16419
|
debug.syncValue("Updating changed child", currentBlockChild, oldBlockChild);
|
|
16336
16420
|
let isSpanNode = isSpan({ schema: context.schema }, currentBlockChild) && isSpan({ schema: context.schema }, oldBlockChild), childProps = { ...currentBlockChild };
|
|
16337
|
-
isSpanNode && delete childProps.text,
|
|
16421
|
+
isSpanNode && delete childProps.text, applyNodeProperties(editorEngine, childProps, path), isSpanNode && isTextChanged ? (oldBlockChild.text.length > 0 && deleteRange(editorEngine, {
|
|
16338
16422
|
focus: {
|
|
16339
16423
|
path,
|
|
16340
16424
|
offset: 0
|
|
@@ -16542,7 +16626,8 @@ function createActors(config) {
|
|
|
16542
16626
|
return config.subscriptions.push(mutationBatcher.subscribe), config.subscriptions.push(() => subscribeToOperations(config.editorEngine, (event) => {
|
|
16543
16627
|
isPublicOperation(event.operation) && config.relay.send({
|
|
16544
16628
|
type: "operation",
|
|
16545
|
-
operation: event.operation
|
|
16629
|
+
operation: event.operation,
|
|
16630
|
+
origin: event.origin === "remote" ? "remote" : "local"
|
|
16546
16631
|
});
|
|
16547
16632
|
})), config.subscriptions.push(() => {
|
|
16548
16633
|
let subscription = syncActor.on("*", (event) => {
|