@portabletext/editor 6.6.0 → 6.6.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/lib/index.js CHANGED
@@ -9,7 +9,6 @@ import { isTypedObject, isKeyedSegment, isListBlock, getBlockEndPoint, getBlockS
9
9
  import { isTextBlockNode, isSpanNode, isSelectionCollapsed as isSelectionCollapsed$1, getFocusChild, getSelectedChildren, getSelectionStartPoint, getSelectionEndPoint, getFocusInlineObject, getFocusTextBlock, getFocusSpan, getSelectedBlocks, isSelectionExpanded, getSelectionStartBlock, getSelectionEndBlock, isOverlappingSelection, getFocusBlock, isSelectingEntireBlocks, getSelectedValue, isActiveAnnotation, getActiveAnnotationsMarks, getActiveDecorators, getSelectionStartChild, getSelectionEndChild, getPreviousSpan, getNextSpan, getCaretWordSelection, getFocusBlockObject, getPreviousBlock, getNextBlock, getMarkState, isAtTheEndOfBlock, isAtTheStartOfBlock, getFocusListBlock, isActiveDecorator, getActiveAnnotations, getLastBlock, getSelectedTextBlocks, isActiveListItem, isActiveStyle } from "./_chunks-es/selector.is-selecting-entire-blocks.js";
10
10
  import scrollIntoView from "scroll-into-view-if-needed";
11
11
  import { createKeyboardShortcut, code, underline, italic as italic$1, bold as bold$1, undo as undo$1, redo as redo$1 } from "@portabletext/keyboard-shortcuts";
12
- import { ResizeObserver } from "@juggle/resize-observer";
13
12
  import { isEmptyTextBlock, sliceTextBlock, getTextBlockText } from "./_chunks-es/util.slice-text-block.js";
14
13
  import { setup, fromCallback, assign, and, enqueueActions, emit, assertEvent, raise as raise$1, not, createActor } from "xstate";
15
14
  import { defineBehavior, forward, raise, effect } from "./behaviors/index.js";
@@ -47,36 +46,96 @@ function isChildArrayField(field) {
47
46
  function isObjectNode(context, node) {
48
47
  return isTypedObject(node) && node._type !== context.schema.block.name && node._type !== context.schema.span.name;
49
48
  }
50
- function indexedPathToKeyedPath(root, path2, schema) {
49
+ function getChildren(context, path2) {
50
+ const traversalContext = {
51
+ schema: context.schema,
52
+ editableTypes: context.editableTypes
53
+ };
54
+ return getChildrenInternal(traversalContext, {
55
+ value: context.value
56
+ }, path2);
57
+ }
58
+ function getChildrenInternal(context, root, path2) {
59
+ const rootChildren = getNodeChildren(context, root, void 0, "");
60
+ if (!rootChildren)
61
+ return [];
62
+ let currentChildren = rootChildren.children, currentScope = rootChildren.scope, scopePath = rootChildren.scopePath, currentPath = [];
63
+ for (const index of path2) {
64
+ const node = currentChildren[index];
65
+ if (!node)
66
+ return [];
67
+ currentPath = [...currentPath, index];
68
+ const next = getNodeChildren(context, node, currentScope, scopePath);
69
+ if (!next)
70
+ return [];
71
+ currentChildren = next.children, currentScope = next.scope, scopePath = next.scopePath;
72
+ }
73
+ return currentChildren.map((child, index) => ({
74
+ node: child,
75
+ path: [...currentPath, index]
76
+ }));
77
+ }
78
+ const _textBlockResult = {
79
+ children: [],
80
+ scope: void 0,
81
+ scopePath: "",
82
+ fieldName: "children"
83
+ }, _rootResult = {
84
+ children: [],
85
+ scope: void 0,
86
+ scopePath: "",
87
+ fieldName: "value"
88
+ };
89
+ function getNodeChildren(context, node, scope, scopePath) {
90
+ if (isTextBlock(context, node))
91
+ return _textBlockResult.children = node.children, _textBlockResult;
92
+ if (isObjectNode(context, node)) {
93
+ const scopedKey = scopePath ? `${scopePath}.${node._type}` : node._type;
94
+ if (!context.editableTypes.has(scopedKey))
95
+ return;
96
+ const arrayField = resolveChildArrayField({
97
+ schema: context.schema,
98
+ scope
99
+ }, node);
100
+ return arrayField ? {
101
+ children: node[arrayField.name],
102
+ scope: arrayField.of,
103
+ scopePath: scopedKey,
104
+ fieldName: arrayField.name
105
+ } : void 0;
106
+ }
107
+ if ("value" in node && Array.isArray(node.value) && !("_key" in node) && !("_type" in node))
108
+ return _rootResult.children = node.value, _rootResult;
109
+ }
110
+ function indexedPathToKeyedPath(context, path2) {
51
111
  if (path2.length === 0)
52
112
  return [];
53
113
  const keyedPath = [];
54
- let currentChildren = root.children, currentScope;
114
+ let nodeChildren = getNodeChildren({
115
+ schema: context.schema,
116
+ editableTypes: context.editableTypes
117
+ }, {
118
+ value: context.value
119
+ }, void 0, "");
55
120
  for (let i = 0; i < path2.length; i++) {
56
- const index = path2[i];
121
+ if (!nodeChildren)
122
+ return;
123
+ const index = path2.at(i);
57
124
  if (index === void 0)
58
125
  return;
59
- const node = currentChildren[index];
126
+ const node = nodeChildren.children.at(index);
60
127
  if (!node || !node._key)
61
128
  return;
62
129
  if (keyedPath.push({
63
130
  _key: node._key
64
131
  }), i < path2.length - 1) {
65
- if (isTextBlock({
66
- schema
67
- }, node))
68
- keyedPath.push("children"), currentChildren = node.children, currentScope = void 0;
69
- else if (isObjectNode({
70
- schema
71
- }, node)) {
72
- const arrayField = resolveChildArrayField({
73
- schema,
74
- scope: currentScope
75
- }, node);
76
- if (!arrayField)
77
- return;
78
- keyedPath.push(arrayField.name), currentChildren = node[arrayField.name], currentScope = arrayField.of;
79
- }
132
+ const childInfo = getNodeChildren({
133
+ schema: context.schema,
134
+ editableTypes: context.editableTypes
135
+ }, node, nodeChildren.scope, nodeChildren.scopePath);
136
+ if (!childInfo)
137
+ return;
138
+ keyedPath.push(childInfo.fieldName), nodeChildren = childInfo;
80
139
  }
81
140
  }
82
141
  return keyedPath;
@@ -90,7 +149,11 @@ function getDomNode(editor, path2) {
90
149
  return;
91
150
  if (path2.length === 0)
92
151
  return editorElement;
93
- const keyedPath = indexedPathToKeyedPath(editor, path2, editor.schema);
152
+ const keyedPath = indexedPathToKeyedPath({
153
+ schema: editor.schema,
154
+ editableTypes: editor.editableTypes,
155
+ value: editor.children
156
+ }, path2);
94
157
  if (!keyedPath)
95
158
  return;
96
159
  const serializedPath = serializePath(keyedPath), blockIndex = path2.at(0);
@@ -140,64 +203,6 @@ function safeParse(text) {
140
203
  return console.error(error), "JSON.parse failed";
141
204
  }
142
205
  }
143
- function getChildren(context, path2) {
144
- const traversalContext = {
145
- schema: context.schema,
146
- editableTypes: context.editableTypes
147
- };
148
- return getChildrenInternal(traversalContext, {
149
- value: context.value
150
- }, path2);
151
- }
152
- function getChildrenInternal(context, root, path2) {
153
- const rootChildren = getNodeChildren(context, root, void 0, "");
154
- if (!rootChildren)
155
- return [];
156
- let currentChildren = rootChildren.children, currentScope = rootChildren.scope, scopePath = rootChildren.scopePath, currentPath = [];
157
- for (const index of path2) {
158
- const node = currentChildren[index];
159
- if (!node)
160
- return [];
161
- currentPath = [...currentPath, index];
162
- const next = getNodeChildren(context, node, currentScope, scopePath);
163
- if (!next)
164
- return [];
165
- currentChildren = next.children, currentScope = next.scope, scopePath = next.scopePath;
166
- }
167
- return currentChildren.map((child, index) => ({
168
- node: child,
169
- path: [...currentPath, index]
170
- }));
171
- }
172
- const _textBlockResult = {
173
- children: [],
174
- scope: void 0,
175
- scopePath: ""
176
- }, _rootResult = {
177
- children: [],
178
- scope: void 0,
179
- scopePath: ""
180
- };
181
- function getNodeChildren(context, node, scope, scopePath) {
182
- if (isTextBlock(context, node))
183
- return _textBlockResult.children = node.children, _textBlockResult;
184
- if (isObjectNode(context, node)) {
185
- const scopedKey = scopePath ? `${scopePath}.${node._type}` : node._type;
186
- if (!context.editableTypes.has(scopedKey))
187
- return;
188
- const arrayField = resolveChildArrayField({
189
- schema: context.schema,
190
- scope
191
- }, node);
192
- return arrayField ? {
193
- children: node[arrayField.name],
194
- scope: arrayField.of,
195
- scopePath: scopedKey
196
- } : void 0;
197
- }
198
- if ("value" in node && Array.isArray(node.value) && !("_key" in node) && !("_type" in node))
199
- return _rootResult.children = node.value, _rootResult;
200
- }
201
206
  function getNode(context, path2) {
202
207
  if (path2.length === 0)
203
208
  return;
@@ -654,9 +659,12 @@ typeof globalThis < "u" && globalThis.InputEvent && typeof globalThis.InputEvent
654
659
  const domSelection = getSelection(root), domRange = DOMEditor.toDOMRange(editor, editor.selection);
655
660
  domSelection?.removeAllRanges(), domSelection?.addRange(domRange);
656
661
  }
657
- editor.selection || editor.select(start(editor, [])), editor.focused = !0, el.focus({
662
+ if (editor.selection || editor.select(start(editor, [])), editor.focused = !0, el.focus({
658
663
  preventScroll: !0
659
- });
664
+ }), editor.selection && root instanceof Document) {
665
+ const domSelection = getSelection(root), domRange = DOMEditor.toDOMRange(editor, editor.selection);
666
+ domSelection?.removeAllRanges(), domSelection?.addRange(domRange);
667
+ }
660
668
  }
661
669
  },
662
670
  getWindow: (editor) => {
@@ -1669,30 +1677,26 @@ function* positions(editor, options = {}) {
1669
1677
  if (isTextBlockNode({
1670
1678
  schema: editor.schema
1671
1679
  }, node)) {
1672
- if (editor.isInline(node))
1673
- continue;
1674
- {
1675
- const e = isAncestorPath(nodePath, end$1.path) ? end$1 : end(editor, nodePath), s = isAncestorPath(nodePath, start$1.path) ? start$1 : start(editor, nodePath);
1676
- blockText = "";
1677
- for (const {
1678
- node: spanNode,
1679
- path: spanPath
1680
- } of getNodes(editor, {
1681
- from: s.path,
1682
- to: e.path,
1683
- match: (n) => isSpan({
1684
- schema: editor.schema
1685
- }, n)
1686
- })) {
1687
- if (!isSpan({
1688
- schema: editor.schema
1689
- }, spanNode))
1690
- continue;
1691
- let spanText = spanNode.text;
1692
- pathEquals(spanPath, e.path) && (spanText = spanText.slice(0, e.offset)), pathEquals(spanPath, s.path) && (spanText = spanText.slice(s.offset)), blockText += spanText;
1693
- }
1694
- isNewBlock = !0;
1680
+ const e = isAncestorPath(nodePath, end$1.path) ? end$1 : end(editor, nodePath), s = isAncestorPath(nodePath, start$1.path) ? start$1 : start(editor, nodePath);
1681
+ blockText = "";
1682
+ for (const {
1683
+ node: spanNode,
1684
+ path: spanPath
1685
+ } of getNodes(editor, {
1686
+ from: s.path,
1687
+ to: e.path,
1688
+ match: (n) => isSpan({
1689
+ schema: editor.schema
1690
+ }, n)
1691
+ })) {
1692
+ if (!isSpan({
1693
+ schema: editor.schema
1694
+ }, spanNode))
1695
+ continue;
1696
+ let spanText = spanNode.text;
1697
+ pathEquals(spanPath, e.path) && (spanText = spanText.slice(0, e.offset)), pathEquals(spanPath, s.path) && (spanText = spanText.slice(s.offset)), blockText += spanText;
1695
1698
  }
1699
+ isNewBlock = !0;
1696
1700
  }
1697
1701
  if (isObjectNode({
1698
1702
  schema: editor.schema
@@ -2342,6 +2346,11 @@ function transformPoint(point2, op, options = {}) {
2342
2346
  path2 = transformPath(path2, op);
2343
2347
  break;
2344
2348
  }
2349
+ case "set_node": {
2350
+ const newProperties = op.newProperties;
2351
+ pathEquals(op.path, path2) && "text" in op.properties && (!("text" in newProperties) || newProperties.text == null) && (offset = 0);
2352
+ break;
2353
+ }
2345
2354
  default:
2346
2355
  return point2;
2347
2356
  }
@@ -3172,6 +3181,9 @@ const shallowCompare = (obj1, obj2) => Object.keys(obj1).length === Object.keys(
3172
3181
  }
3173
3182
  return decorationsByChild;
3174
3183
  };
3184
+ function isInline(context, path2) {
3185
+ return !isBlock(context, path2);
3186
+ }
3175
3187
  function useGenericSelector(selector, equalityFn) {
3176
3188
  const [, forceRender] = useReducer((s) => s + 1, 0), latestSubscriptionCallbackError = useRef(void 0), latestSelector = useRef(() => null), latestSelectedState = useRef(null);
3177
3189
  let selectedState;
@@ -3244,7 +3256,7 @@ const defaultRenderElement$1 = (props) => /* @__PURE__ */ jsx(DefaultElement, {
3244
3256
  renderPlaceholder,
3245
3257
  renderLeaf,
3246
3258
  renderText
3247
- } = props, editor = useSlateStatic(), isInline2 = editor.isInline(element), decorations = useDecorations(element, props.indexedPath, parentDecorations), children = useChildren({
3259
+ } = props, editor = useSlateStatic(), isInline$1 = isInline(editor, props.indexedPath), decorations = useDecorations(element, props.indexedPath, parentDecorations), children = useChildren({
3248
3260
  parentDataPath: dataPath,
3249
3261
  decorations,
3250
3262
  node: element,
@@ -3257,7 +3269,7 @@ const defaultRenderElement$1 = (props) => /* @__PURE__ */ jsx(DefaultElement, {
3257
3269
  "data-slate-node": "element",
3258
3270
  "data-pt-path": dataPath
3259
3271
  };
3260
- if (isInline2 && (attributes["data-slate-inline"] = !0), !isInline2 && isTextBlockNode({
3272
+ if (isInline$1 && (attributes["data-slate-inline"] = !0), !isInline$1 && isTextBlockNode({
3261
3273
  schema: editor.schema
3262
3274
  }, element)) {
3263
3275
  const text = getText(editor, props.indexedPath), dir = text !== void 0 ? getDirection(text) : void 0;
@@ -3272,9 +3284,8 @@ const defaultRenderElement$1 = (props) => /* @__PURE__ */ jsx(DefaultElement, {
3272
3284
  }, MemoizedElement = React.memo(Element$1, (prev, next) => prev.dataPath === next.dataPath && prev.element === next.element && pathEquals(prev.indexedPath, next.indexedPath) && prev.renderElement === next.renderElement && prev.renderText === next.renderText && prev.renderLeaf === next.renderLeaf && prev.renderPlaceholder === next.renderPlaceholder && isElementDecorationsEqual(prev.decorations, next.decorations)), DefaultElement = (props) => {
3273
3285
  const {
3274
3286
  attributes,
3275
- children,
3276
- element
3277
- } = props, Tag = useSlateStatic().isInline(element) ? "span" : "div";
3287
+ children
3288
+ } = props, editor = useSlateStatic(), Tag = isInline(editor, props.indexedPath) ? "span" : "div";
3278
3289
  return /* @__PURE__ */ jsx(Tag, { ...attributes, style: {
3279
3290
  position: "relative"
3280
3291
  }, children });
@@ -3420,11 +3431,11 @@ const SlateString = (props) => {
3420
3431
  parent,
3421
3432
  indexedPath,
3422
3433
  text
3423
- } = props, editor = useSlateStatic(), parentIndexedPath = parentPath(indexedPath), isMarkPlaceholder = !!leaf[MARK_PLACEHOLDER_SYMBOL];
3424
- return leaf.text === "" && isTextBlock({
3434
+ } = props, editor = useSlateStatic(), parentIndexedPath = parentPath(indexedPath), isMarkPlaceholder = !!leaf[MARK_PLACEHOLDER_SYMBOL], leafText = leaf.text ?? "";
3435
+ return leafText === "" && isTextBlock({
3425
3436
  schema: editor.schema
3426
- }, parent) && parent.children[parent.children.length - 1] === text && !editor.isInline(parent) && getTextContent(editor, parentIndexedPath) === "" ? /* @__PURE__ */ jsx(ZeroWidthString, { isLineBreak: !0, isMarkPlaceholder }) : leaf.text === "" ? /* @__PURE__ */ jsx(ZeroWidthString, { isMarkPlaceholder }) : isLast && leaf.text.slice(-1) === `
3427
- ` ? /* @__PURE__ */ jsx(TextString, { isTrailing: !0, text: leaf.text }) : /* @__PURE__ */ jsx(TextString, { text: leaf.text });
3437
+ }, parent) && parent.children[parent.children.length - 1] === text && getTextContent(editor, parentIndexedPath) === "" ? /* @__PURE__ */ jsx(ZeroWidthString, { isLineBreak: !0, isMarkPlaceholder }) : leafText === "" ? /* @__PURE__ */ jsx(ZeroWidthString, { isMarkPlaceholder }) : isLast && leafText.slice(-1) === `
3438
+ ` ? /* @__PURE__ */ jsx(TextString, { isTrailing: !0, text: leafText }) : /* @__PURE__ */ jsx(TextString, { text: leafText });
3428
3439
  }, TextString = (props) => {
3429
3440
  const {
3430
3441
  text,
@@ -3466,17 +3477,9 @@ const defaultRenderLeaf = (props) => /* @__PURE__ */ jsx(DefaultLeaf, { ...props
3466
3477
  renderLeaf = defaultRenderLeaf,
3467
3478
  leafPosition
3468
3479
  } = props, editor = useSlateStatic(), placeholderResizeObserver = useRef(null), placeholderRef = useRef(null), [showPlaceholder, setShowPlaceholder] = useState(!1), showPlaceholderTimeoutRef = useRef(null), callbackPlaceholderRef = useCallback((placeholderEl) => {
3469
- if (disconnectPlaceholderResizeObserver(placeholderResizeObserver, placeholderEl == null), placeholderEl == null)
3470
- editor.domPlaceholderElement = null, leaf.onPlaceholderResize?.(null);
3471
- else {
3472
- if (editor.domPlaceholderElement = placeholderEl, !placeholderResizeObserver.current) {
3473
- const ResizeObserver$1 = window.ResizeObserver || ResizeObserver;
3474
- placeholderResizeObserver.current = new ResizeObserver$1(() => {
3475
- leaf.onPlaceholderResize?.(placeholderEl);
3476
- });
3477
- }
3478
- placeholderResizeObserver.current.observe(placeholderEl), placeholderRef.current = placeholderEl;
3479
- }
3480
+ disconnectPlaceholderResizeObserver(placeholderResizeObserver, placeholderEl == null), placeholderEl == null ? (editor.domPlaceholderElement = null, leaf.onPlaceholderResize?.(null)) : (editor.domPlaceholderElement = placeholderEl, placeholderResizeObserver.current || (placeholderResizeObserver.current = new ResizeObserver(() => {
3481
+ leaf.onPlaceholderResize?.(placeholderEl);
3482
+ })), placeholderResizeObserver.current.observe(placeholderEl), placeholderRef.current = placeholderEl);
3480
3483
  }, [placeholderRef, leaf, editor]);
3481
3484
  let children = /* @__PURE__ */ jsx(SlateString, { isLast, leaf, parent, indexedPath, text });
3482
3485
  const leafIsPlaceholder = !!leaf[PLACEHOLDER_SYMBOL];
@@ -3837,7 +3840,13 @@ const RestoreDOM = IS_ANDROID ? RestoreDOMComponent : ({
3837
3840
  if (!el2)
3838
3841
  return;
3839
3842
  const domSelection = getSelection(root2);
3840
- if (activeElement === el2 ? (state.latestElement = activeElement, editor.focused = !0) : editor.focused = !1, !domSelection)
3843
+ if (activeElement === el2)
3844
+ state.latestElement = activeElement, editor.focused = !0;
3845
+ else {
3846
+ editor.focused = !1;
3847
+ return;
3848
+ }
3849
+ if (!domSelection)
3841
3850
  return deselect(editor);
3842
3851
  const {
3843
3852
  anchorNode,
@@ -4366,7 +4375,7 @@ const RestoreDOM = IS_ANDROID ? RestoreDOMComponent : ({
4366
4375
  let blockPath = indexedPath;
4367
4376
  isTextBlockNode({
4368
4377
  schema: editor.schema
4369
- }, node) && !editor.isInline(node) || (blockPath = getAncestorTextBlock(editor, indexedPath)?.path ?? indexedPath.slice(0, 1));
4378
+ }, node) || (blockPath = getAncestorTextBlock(editor, indexedPath)?.path ?? indexedPath.slice(0, 1));
4370
4379
  const range$1 = range(editor, blockPath);
4371
4380
  editor.select(range$1);
4372
4381
  return;
@@ -5786,7 +5795,7 @@ function RenderElement(props) {
5786
5795
  let t12;
5787
5796
  return $[0] !== props.attributes || $[1] !== props.children || $[2] !== props.element || $[3] !== props.readOnly || $[4] !== props.renderBlock || $[5] !== props.renderListItem || $[6] !== props.renderStyle || $[7] !== props.spellCheck || $[8] !== schema || $[9] !== t02 ? (t12 = /* @__PURE__ */ jsx(RenderTextBlock, { attributes: props.attributes, dropPosition: t02, element: props.element, readOnly: props.readOnly, renderBlock: props.renderBlock, renderListItem: props.renderListItem, renderStyle: props.renderStyle, schema, spellCheck: props.spellCheck, textBlock: props.element, children: props.children }), $[0] = props.attributes, $[1] = props.children, $[2] = props.element, $[3] = props.readOnly, $[4] = props.renderBlock, $[5] = props.renderListItem, $[6] = props.renderStyle, $[7] = props.spellCheck, $[8] = schema, $[9] = t02, $[10] = t12) : t12 = $[10], t12;
5788
5797
  }
5789
- if (slateStatic.isInline(props.element)) {
5798
+ if (isInline(slateStatic, props.indexedPath)) {
5790
5799
  let t02;
5791
5800
  return $[11] !== props.attributes || $[12] !== props.children || $[13] !== props.element || $[14] !== props.indexedPath || $[15] !== props.readOnly || $[16] !== props.renderChild || $[17] !== schema ? (t02 = /* @__PURE__ */ jsx(RenderInlineObject, { attributes: props.attributes, element: props.element, indexedPath: props.indexedPath, readOnly: props.readOnly, renderChild: props.renderChild, schema, children: props.children }), $[11] = props.attributes, $[12] = props.children, $[13] = props.element, $[14] = props.indexedPath, $[15] = props.readOnly, $[16] = props.renderChild, $[17] = schema, $[18] = t02) : t02 = $[18], t02;
5792
5801
  }
@@ -7348,34 +7357,15 @@ function createEditableAPI(editor, editorActor) {
7348
7357
  return ![schema.block.name, schema.span.name].includes(element._type);
7349
7358
  },
7350
7359
  findByPath: (path2) => {
7351
- const blockKey = getBlockKeyFromSelectionPoint({
7352
- path: path2
7353
- });
7354
- if (!blockKey)
7355
- return [void 0, void 0];
7356
- const blockIndex = editor.blockIndexMap.get(blockKey);
7357
- if (blockIndex === void 0)
7360
+ const indexedPath = keyedPathToIndexedPath(editor, path2, editor.blockIndexMap);
7361
+ if (!indexedPath)
7358
7362
  return [void 0, void 0];
7359
- const block = editor.children.at(blockIndex);
7360
- if (!block)
7361
- return [void 0, void 0];
7362
- const childKey = getChildKeyFromSelectionPoint({
7363
- path: path2
7364
- });
7365
- if (path2.length === 1 && !childKey)
7366
- return [block, [{
7367
- _key: block._key
7368
- }]];
7369
- if (isTextBlock(editorActor.getSnapshot().context, block) && childKey) {
7370
- const child = block.children.find((child2) => child2._key === childKey);
7371
- if (child)
7372
- return [child, [{
7373
- _key: block._key
7374
- }, "children", {
7375
- _key: child._key
7376
- }]];
7377
- }
7378
- return [void 0, void 0];
7363
+ const result = getNode({
7364
+ schema: editor.schema,
7365
+ editableTypes: editor.editableTypes,
7366
+ value: editor.children
7367
+ }, indexedPath);
7368
+ return result ? [result.node, path2] : [void 0, void 0];
7379
7369
  },
7380
7370
  findDOMNode: (element) => {
7381
7371
  let node;
@@ -7790,915 +7780,303 @@ function createHistoryPlugin({
7790
7780
  }, editor;
7791
7781
  };
7792
7782
  }
7793
- function isEnd(editor, point2, at) {
7794
- const editorEnd = end(editor, at);
7795
- return pointEquals(point2, editorEnd);
7783
+ function cloneDiff(diff2) {
7784
+ const [type, patch] = diff2;
7785
+ return [type, patch];
7796
7786
  }
7797
- function isStart(editor, point2, at) {
7798
- if (point2.offset !== 0)
7799
- return !1;
7800
- const editorStart = start(editor, at);
7801
- return pointEquals(point2, editorStart);
7787
+ function getCommonOverlap(textA, textB) {
7788
+ let text1 = textA, text2 = textB;
7789
+ const text1Length = text1.length, text2Length = text2.length;
7790
+ if (text1Length === 0 || text2Length === 0) return 0;
7791
+ text1Length > text2Length ? text1 = text1.substring(text1Length - text2Length) : text1Length < text2Length && (text2 = text2.substring(0, text1Length));
7792
+ const textLength = Math.min(text1Length, text2Length);
7793
+ if (text1 === text2) return textLength;
7794
+ let best = 0, length = 1;
7795
+ for (let found = 0; found !== -1; ) {
7796
+ const pattern = text1.substring(textLength - length);
7797
+ if (found = text2.indexOf(pattern), found === -1) return best;
7798
+ length += found, (found === 0 || text1.substring(textLength - length) === text2.substring(0, length)) && (best = length, length++);
7799
+ }
7800
+ return best;
7802
7801
  }
7803
- function isEdge(editor, point2, at) {
7804
- return isStart(editor, point2, at) || isEnd(editor, point2, at);
7802
+ function getCommonPrefix(text1, text2) {
7803
+ if (!text1 || !text2 || text1[0] !== text2[0]) return 0;
7804
+ let pointerMin = 0, pointerMax = Math.min(text1.length, text2.length), pointerMid = pointerMax, pointerStart = 0;
7805
+ for (; pointerMin < pointerMid; ) text1.substring(pointerStart, pointerMid) === text2.substring(pointerStart, pointerMid) ? (pointerMin = pointerMid, pointerStart = pointerMin) : pointerMax = pointerMid, pointerMid = Math.floor((pointerMax - pointerMin) / 2 + pointerMin);
7806
+ return pointerMid;
7805
7807
  }
7806
- function pathRef(editor, path2, options = {}) {
7807
- const {
7808
- affinity = "forward"
7809
- } = options, ref = {
7810
- current: path2,
7811
- affinity,
7812
- unref() {
7813
- const {
7814
- current
7815
- } = ref;
7816
- return editor.pathRefs.delete(ref), ref.current = null, current;
7817
- }
7818
- };
7819
- return editor.pathRefs.add(ref), ref;
7808
+ function getCommonSuffix(text1, text2) {
7809
+ if (!text1 || !text2 || text1[text1.length - 1] !== text2[text2.length - 1]) return 0;
7810
+ let pointerMin = 0, pointerMax = Math.min(text1.length, text2.length), pointerMid = pointerMax, pointerEnd = 0;
7811
+ for (; pointerMin < pointerMid; ) text1.substring(text1.length - pointerMid, text1.length - pointerEnd) === text2.substring(text2.length - pointerMid, text2.length - pointerEnd) ? (pointerMin = pointerMid, pointerEnd = pointerMin) : pointerMax = pointerMid, pointerMid = Math.floor((pointerMax - pointerMin) / 2 + pointerMin);
7812
+ return pointerMid;
7820
7813
  }
7821
- function isNormalizing(editor) {
7822
- return editor.normalizing;
7814
+ function isHighSurrogate(char) {
7815
+ const charCode = char.charCodeAt(0);
7816
+ return charCode >= 55296 && charCode <= 56319;
7823
7817
  }
7824
- function normalize(editor, options = {}) {
7825
- const {
7826
- force = !1,
7827
- operation
7828
- } = options, getDirtyPaths2 = (editor2) => editor2.dirtyPaths, getDirtyPathKeys = (editor2) => editor2.dirtyPathKeys, popDirtyPath = (editor2) => {
7829
- const path2 = getDirtyPaths2(editor2).pop(), key = path2.length === 1 ? String(path2[0]) : path2.length === 2 ? `${path2[0]},${path2[1]}` : path2.join(",");
7830
- return getDirtyPathKeys(editor2).delete(key), path2;
7831
- };
7832
- if (isNormalizing(editor)) {
7833
- if (force) {
7834
- const allPaths = Array.from(getNodes(editor), (entry) => entry.path), allPathKeys = new Set(allPaths.map((p) => p.join(",")));
7835
- editor.dirtyPaths = allPaths, editor.dirtyPathKeys = allPathKeys;
7836
- }
7837
- getDirtyPaths2(editor).length !== 0 && withoutNormalizing(editor, () => {
7838
- for (const dirtyPath of getDirtyPaths2(editor))
7839
- if (dirtyPath.length !== 0 && hasNode(editor, dirtyPath)) {
7840
- const entry = getNode(editor, dirtyPath);
7841
- if (!entry)
7842
- continue;
7843
- const entryNode = entry.node;
7844
- isTextBlock({
7845
- schema: editor.schema
7846
- }, entryNode) && entryNode.children.length === 0 && editor.normalizeNode([entry.node, entry.path], {
7847
- operation
7848
- });
7849
- }
7850
- let dirtyPaths = getDirtyPaths2(editor);
7851
- const initialDirtyPathsLength = dirtyPaths.length;
7852
- let iteration = 0;
7853
- for (; dirtyPaths.length !== 0; ) {
7854
- if (!editor.shouldNormalize({
7855
- dirtyPaths,
7856
- iteration,
7857
- initialDirtyPathsLength,
7858
- operation
7859
- }))
7860
- return;
7861
- const dirtyPath = popDirtyPath(editor);
7862
- if (dirtyPath.length === 0)
7863
- editor.normalizeNode([editor, dirtyPath], {
7864
- operation
7865
- });
7866
- else if (hasNode(editor, dirtyPath)) {
7867
- const entry = getNode(editor, dirtyPath);
7868
- entry && editor.normalizeNode([entry.node, entry.path], {
7869
- operation
7870
- });
7818
+ function isLowSurrogate(char) {
7819
+ const charCode = char.charCodeAt(0);
7820
+ return charCode >= 56320 && charCode <= 57343;
7821
+ }
7822
+ function bisect(text1, text2, deadline) {
7823
+ const text1Length = text1.length, text2Length = text2.length, maxD = Math.ceil((text1Length + text2Length) / 2), vOffset = maxD, vLength = 2 * maxD, v1 = new Array(vLength), v2 = new Array(vLength);
7824
+ for (let x = 0; x < vLength; x++) v1[x] = -1, v2[x] = -1;
7825
+ v1[vOffset + 1] = 0, v2[vOffset + 1] = 0;
7826
+ const delta = text1Length - text2Length, front = delta % 2 !== 0;
7827
+ let k1start = 0, k1end = 0, k2start = 0, k2end = 0;
7828
+ for (let d = 0; d < maxD && !(Date.now() > deadline); d++) {
7829
+ for (let k1 = -d + k1start; k1 <= d - k1end; k1 += 2) {
7830
+ const k1Offset = vOffset + k1;
7831
+ let x1;
7832
+ k1 === -d || k1 !== d && v1[k1Offset - 1] < v1[k1Offset + 1] ? x1 = v1[k1Offset + 1] : x1 = v1[k1Offset - 1] + 1;
7833
+ let y1 = x1 - k1;
7834
+ for (; x1 < text1Length && y1 < text2Length && text1.charAt(x1) === text2.charAt(y1); ) x1++, y1++;
7835
+ if (v1[k1Offset] = x1, x1 > text1Length) k1end += 2;
7836
+ else if (y1 > text2Length) k1start += 2;
7837
+ else if (front) {
7838
+ const k2Offset = vOffset + delta - k1;
7839
+ if (k2Offset >= 0 && k2Offset < vLength && v2[k2Offset] !== -1) {
7840
+ const x2 = text1Length - v2[k2Offset];
7841
+ if (x1 >= x2) return bisectSplit(text1, text2, x1, y1, deadline);
7871
7842
  }
7872
- iteration++, dirtyPaths = getDirtyPaths2(editor);
7873
7843
  }
7874
- });
7844
+ }
7845
+ for (let k2 = -d + k2start; k2 <= d - k2end; k2 += 2) {
7846
+ const k2Offset = vOffset + k2;
7847
+ let x2;
7848
+ k2 === -d || k2 !== d && v2[k2Offset - 1] < v2[k2Offset + 1] ? x2 = v2[k2Offset + 1] : x2 = v2[k2Offset - 1] + 1;
7849
+ let y2 = x2 - k2;
7850
+ for (; x2 < text1Length && y2 < text2Length && text1.charAt(text1Length - x2 - 1) === text2.charAt(text2Length - y2 - 1); ) x2++, y2++;
7851
+ if (v2[k2Offset] = x2, x2 > text1Length) k2end += 2;
7852
+ else if (y2 > text2Length) k2start += 2;
7853
+ else if (!front) {
7854
+ const k1Offset = vOffset + delta - k2;
7855
+ if (k1Offset >= 0 && k1Offset < vLength && v1[k1Offset] !== -1) {
7856
+ const x1 = v1[k1Offset], y1 = vOffset + x1 - k1Offset;
7857
+ if (x2 = text1Length - x2, x1 >= x2) return bisectSplit(text1, text2, x1, y1, deadline);
7858
+ }
7859
+ }
7860
+ }
7875
7861
  }
7862
+ return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]];
7876
7863
  }
7877
- function setNormalizing(editor, isNormalizing2) {
7878
- editor.normalizing = isNormalizing2;
7864
+ function bisectSplit(text1, text2, x, y, deadline) {
7865
+ const text1a = text1.substring(0, x), text2a = text2.substring(0, y), text1b = text1.substring(x), text2b = text2.substring(y), diffs = doDiff(text1a, text2a, {
7866
+ checkLines: !1,
7867
+ deadline
7868
+ }), diffsb = doDiff(text1b, text2b, {
7869
+ checkLines: !1,
7870
+ deadline
7871
+ });
7872
+ return diffs.concat(diffsb);
7879
7873
  }
7880
- function withoutNormalizing(editor, fn) {
7881
- const value = isNormalizing(editor);
7882
- setNormalizing(editor, !1);
7883
- try {
7884
- fn();
7885
- } finally {
7886
- setNormalizing(editor, value);
7874
+ function findHalfMatch(text1, text2, timeout = 1) {
7875
+ if (timeout <= 0) return null;
7876
+ const longText = text1.length > text2.length ? text1 : text2, shortText = text1.length > text2.length ? text2 : text1;
7877
+ if (longText.length < 4 || shortText.length * 2 < longText.length) return null;
7878
+ const halfMatch1 = halfMatchI(longText, shortText, Math.ceil(longText.length / 4)), halfMatch2 = halfMatchI(longText, shortText, Math.ceil(longText.length / 2));
7879
+ let halfMatch;
7880
+ if (halfMatch1 && halfMatch2) halfMatch = halfMatch1[4].length > halfMatch2[4].length ? halfMatch1 : halfMatch2;
7881
+ else {
7882
+ if (!halfMatch1 && !halfMatch2) return null;
7883
+ halfMatch2 ? halfMatch1 || (halfMatch = halfMatch2) : halfMatch = halfMatch1;
7887
7884
  }
7888
- normalize(editor);
7889
- }
7890
- function rangeRefAffinities(range2, affinity) {
7891
- if (affinity === "inward") {
7892
- const isCollapsed = isCollapsedRange(range2);
7893
- if (isForwardRange(range2)) {
7894
- const anchorAffinity = "forward";
7895
- return [anchorAffinity, isCollapsed ? anchorAffinity : "backward"];
7896
- } else {
7897
- const anchorAffinity = "backward";
7898
- return [anchorAffinity, isCollapsed ? anchorAffinity : "forward"];
7899
- }
7900
- } else return affinity === "outward" ? isForwardRange(range2) ? ["backward", "forward"] : ["forward", "backward"] : [affinity, affinity];
7885
+ if (!halfMatch) throw new Error("Unable to find a half match.");
7886
+ let text1A, text1B, text2A, text2B;
7887
+ text1.length > text2.length ? (text1A = halfMatch[0], text1B = halfMatch[1], text2A = halfMatch[2], text2B = halfMatch[3]) : (text2A = halfMatch[0], text2B = halfMatch[1], text1A = halfMatch[2], text1B = halfMatch[3]);
7888
+ const midCommon = halfMatch[4];
7889
+ return [text1A, text1B, text2A, text2B, midCommon];
7901
7890
  }
7902
- function applySplitNode(editor, path2, position) {
7903
- const nodeEntry = getNode(editor, path2);
7904
- if (!nodeEntry)
7905
- return;
7906
- const node = nodeEntry.node;
7907
- for (const ref of editor.pathRefs) {
7908
- const current = ref.current;
7909
- current && (ref.current = transformPathForSplit(current, path2, position, ref.affinity ?? "forward"));
7891
+ function halfMatchI(longText, shortText, i) {
7892
+ const seed = longText.slice(i, i + Math.floor(longText.length / 4));
7893
+ let j = -1, bestCommon = "", bestLongTextA, bestLongTextB, bestShortTextA, bestShortTextB;
7894
+ for (; (j = shortText.indexOf(seed, j + 1)) !== -1; ) {
7895
+ const prefixLength = getCommonPrefix(longText.slice(i), shortText.slice(j)), suffixLength = getCommonSuffix(longText.slice(0, i), shortText.slice(0, j));
7896
+ bestCommon.length < suffixLength + prefixLength && (bestCommon = shortText.slice(j - suffixLength, j) + shortText.slice(j, j + prefixLength), bestLongTextA = longText.slice(0, i - suffixLength), bestLongTextB = longText.slice(i + prefixLength), bestShortTextA = shortText.slice(0, j - suffixLength), bestShortTextB = shortText.slice(j + prefixLength));
7910
7897
  }
7911
- for (const ref of editor.pointRefs) {
7912
- const current = ref.current;
7913
- current && (ref.current = transformPointForSplit(current, path2, position, ref.affinity ?? "forward"));
7898
+ return bestCommon.length * 2 >= longText.length ? [bestLongTextA || "", bestLongTextB || "", bestShortTextA || "", bestShortTextB || "", bestCommon || ""] : null;
7899
+ }
7900
+ function charsToLines(diffs, lineArray) {
7901
+ for (let x = 0; x < diffs.length; x++) {
7902
+ const chars = diffs[x][1], text = [];
7903
+ for (let y = 0; y < chars.length; y++) text[y] = lineArray[chars.charCodeAt(y)];
7904
+ diffs[x][1] = text.join("");
7914
7905
  }
7915
- for (const ref of editor.rangeRefs) {
7916
- const current = ref.current;
7917
- if (current) {
7918
- const [anchorAffinity, focusAffinity] = rangeRefAffinities(current, ref.affinity), anchor = transformPointForSplit(current.anchor, path2, position, anchorAffinity ?? "forward"), focus = transformPointForSplit(current.focus, path2, position, focusAffinity ?? "forward");
7919
- anchor && focus ? ref.current = {
7920
- anchor,
7921
- focus
7922
- } : (ref.current = null, ref.unref());
7906
+ }
7907
+ function linesToChars(textA, textB) {
7908
+ const lineArray = [], lineHash = {};
7909
+ lineArray[0] = "";
7910
+ function diffLinesToMunge(text) {
7911
+ let chars = "", lineStart = 0, lineEnd = -1, lineArrayLength = lineArray.length;
7912
+ for (; lineEnd < text.length - 1; ) {
7913
+ lineEnd = text.indexOf(`
7914
+ `, lineStart), lineEnd === -1 && (lineEnd = text.length - 1);
7915
+ let line = text.slice(lineStart, lineEnd + 1);
7916
+ (lineHash.hasOwnProperty ? lineHash.hasOwnProperty(line) : lineHash[line] !== void 0) ? chars += String.fromCharCode(lineHash[line]) : (lineArrayLength === maxLines && (line = text.slice(lineStart), lineEnd = text.length), chars += String.fromCharCode(lineArrayLength), lineHash[line] = lineArrayLength, lineArray[lineArrayLength++] = line), lineStart = lineEnd + 1;
7923
7917
  }
7918
+ return chars;
7924
7919
  }
7925
- if (editor.selection) {
7926
- const anchor = transformPointForSplit(editor.selection.anchor, path2, position, "forward"), focus = transformPointForSplit(editor.selection.focus, path2, position, "forward");
7927
- anchor && focus && (editor.selection = {
7928
- anchor,
7929
- focus
7930
- });
7931
- }
7932
- const pathRefs = new Set(editor.pathRefs), pointRefs = new Set(editor.pointRefs), rangeRefs = new Set(editor.rangeRefs);
7933
- editor.pathRefs.clear(), editor.pointRefs.clear(), editor.rangeRefs.clear();
7934
- const savedSelection = editor.selection;
7935
- try {
7936
- withoutNormalizing(editor, () => {
7937
- if (isSpan({
7938
- schema: editor.schema
7939
- }, node)) {
7940
- const {
7941
- text: _text,
7942
- ...properties
7943
- } = node, afterText = node.text.slice(position), newNode = {
7944
- ...properties,
7945
- text: afterText
7946
- };
7947
- editor.apply({
7948
- type: "remove_text",
7949
- path: path2,
7950
- offset: position,
7951
- text: afterText
7952
- }), editor.apply({
7953
- type: "insert_node",
7954
- path: nextPath(path2),
7955
- node: newNode
7956
- });
7957
- } else if (isTextBlock({
7958
- schema: editor.schema
7959
- }, node)) {
7960
- const {
7961
- children: _children,
7962
- ...properties
7963
- } = node, children = node.children, afterChildren = children.slice(position), newNode = {
7964
- ...properties,
7965
- children: afterChildren
7966
- };
7967
- for (let i = children.length - 1; i >= position; i--)
7968
- editor.apply({
7969
- type: "remove_node",
7970
- path: [...path2, i],
7971
- node: children[i]
7972
- });
7973
- editor.apply({
7974
- type: "insert_node",
7975
- path: nextPath(path2),
7976
- node: newNode
7977
- });
7978
- }
7979
- });
7980
- } finally {
7981
- editor.selection = savedSelection;
7982
- for (const ref of pathRefs)
7983
- editor.pathRefs.add(ref);
7984
- for (const ref of pointRefs)
7985
- editor.pointRefs.add(ref);
7986
- for (const ref of rangeRefs)
7987
- editor.rangeRefs.add(ref);
7988
- }
7989
- }
7990
- function transformPathForSplit(path2, splitPath, position, affinity = "forward") {
7991
- const p = [...path2];
7992
- return pathEquals(splitPath, p) ? affinity === "forward" && (p[p.length - 1] = p[p.length - 1] + 1) : pathEndsBefore(splitPath, p) ? p[splitPath.length - 1] = p[splitPath.length - 1] + 1 : isAncestorPath(splitPath, p) && path2[splitPath.length] >= position && (p[splitPath.length - 1] = p[splitPath.length - 1] + 1, p[splitPath.length] = p[splitPath.length] - position), p;
7993
- }
7994
- function transformPointForSplit(point2, splitPath, position, affinity = "forward") {
7995
- let {
7996
- path: path2,
7997
- offset
7998
- } = point2;
7999
- return pathEquals(splitPath, path2) ? (position < offset || position === offset && affinity === "forward") && (offset -= position, path2 = transformPathForSplit(path2, splitPath, position, "forward")) : path2 = transformPathForSplit(path2, splitPath, position, affinity), {
8000
- path: path2,
8001
- offset
7920
+ let maxLines = 4e4;
7921
+ const chars1 = diffLinesToMunge(textA);
7922
+ maxLines = 65535;
7923
+ const chars2 = diffLinesToMunge(textB);
7924
+ return {
7925
+ chars1,
7926
+ chars2,
7927
+ lineArray
8002
7928
  };
8003
7929
  }
8004
- function applyInsertNodeAtPath(editor, node, path2) {
8005
- editor.apply({
8006
- type: "insert_node",
8007
- path: path2,
8008
- node
7930
+ function doLineModeDiff(textA, textB, opts) {
7931
+ let text1 = textA, text2 = textB;
7932
+ const a = linesToChars(text1, text2);
7933
+ text1 = a.chars1, text2 = a.chars2;
7934
+ const linearray = a.lineArray;
7935
+ let diffs = doDiff(text1, text2, {
7936
+ checkLines: !1,
7937
+ deadline: opts.deadline
8009
7938
  });
8010
- const point2 = end(editor, path2);
8011
- point2 && applySelect(editor, point2);
8012
- }
8013
- function applyInsertNodeAtPoint(editor, node, at) {
8014
- withoutNormalizing(editor, () => {
8015
- const match2 = isSpan({
8016
- schema: editor.schema
8017
- }, node) ? (n) => isSpan({
8018
- schema: editor.schema
8019
- }, n) : (n) => isSpan({
8020
- schema: editor.schema
8021
- }, n) || isObjectNode({
8022
- schema: editor.schema
8023
- }, n), nodeEntry = getNode(editor, at.path), entry = nodeEntry && match2(nodeEntry.node) ? nodeEntry : void 0;
8024
- if (!entry)
8025
- return;
8026
- const matchPath2 = entry.path, ref = pathRef(editor, matchPath2), isAtEnd = isEnd(editor, at, matchPath2);
8027
- isEdge(editor, at, matchPath2) || applySplitNode(editor, at.path, at.offset);
8028
- const path2 = ref.unref(), insertPath = isAtEnd ? nextPath(path2) : path2;
8029
- editor.apply({
8030
- type: "insert_node",
8031
- path: insertPath,
8032
- node
8033
- });
8034
- const point2 = end(editor, insertPath);
8035
- point2 && applySelect(editor, point2);
8036
- });
8037
- }
8038
- function previousPath(path2) {
8039
- if (path2.length === 0)
8040
- throw new Error(`Cannot get the previous path of a root path [${path2}], because it has no previous index.`);
8041
- const last = path2[path2.length - 1];
8042
- if (last <= 0)
8043
- throw new Error(`Cannot get the previous path of a first child path [${path2}] because it would result in a negative index.`);
8044
- return path2.slice(0, -1).concat(last - 1);
8045
- }
8046
- function applyMergeNode(editor, path2, position) {
8047
- const nodeEntry = getNode(editor, path2);
8048
- if (!nodeEntry)
8049
- return;
8050
- const node = nodeEntry.node, prevPath = previousPath(path2);
8051
- for (const ref of editor.pathRefs) {
8052
- const current = ref.current;
8053
- current && (ref.current = transformPathForMerge(current, path2, position));
8054
- }
8055
- for (const ref of editor.pointRefs) {
8056
- const current = ref.current;
8057
- current && (ref.current = transformPointForMerge(current, path2, position));
8058
- }
8059
- for (const ref of editor.rangeRefs) {
8060
- const current = ref.current;
8061
- if (current) {
8062
- const anchor = transformPointForMerge(current.anchor, path2, position), focus = transformPointForMerge(current.focus, path2, position);
8063
- anchor && focus ? ref.current = {
8064
- anchor,
8065
- focus
8066
- } : (ref.current = null, ref.unref());
8067
- }
8068
- }
8069
- if (editor.selection) {
8070
- const anchor = transformPointForMerge(editor.selection.anchor, path2, position), focus = transformPointForMerge(editor.selection.focus, path2, position);
8071
- anchor && focus && (editor.selection = {
8072
- anchor,
8073
- focus
8074
- });
8075
- }
8076
- const pathRefs = new Set(editor.pathRefs), pointRefs = new Set(editor.pointRefs), rangeRefs = new Set(editor.rangeRefs);
8077
- editor.pathRefs.clear(), editor.pointRefs.clear(), editor.rangeRefs.clear();
8078
- const savedSelection = editor.selection, editorAny = editor, savedPendingDiffs = editorAny.pendingDiffs, savedPendingSelection = editorAny.pendingSelection, savedPendingAction = editorAny.pendingAction;
8079
- if (Array.isArray(savedPendingDiffs) && savedPendingDiffs.length > 0 && (editorAny.pendingDiffs = savedPendingDiffs.map((textDiff) => transformTextDiffForMerge(textDiff, path2, position)).filter(Boolean)), savedPendingSelection && typeof savedPendingSelection == "object" && "anchor" in savedPendingSelection && "focus" in savedPendingSelection) {
8080
- const sel = savedPendingSelection, anchor = transformPointForMerge(sel.anchor, path2, position), focus = transformPointForMerge(sel.focus, path2, position);
8081
- editorAny.pendingSelection = anchor && focus ? {
8082
- anchor,
8083
- focus
8084
- } : null;
8085
- }
8086
- if (savedPendingAction && typeof savedPendingAction == "object" && "at" in savedPendingAction) {
8087
- const action = savedPendingAction;
8088
- if ("offset" in action.at && typeof action.at.offset == "number") {
8089
- const at = transformPointForMerge(action.at, path2, position);
8090
- editorAny.pendingAction = at ? {
8091
- ...action,
8092
- at
8093
- } : null;
8094
- } else if (isRange(action.at)) {
8095
- const anchor = transformPointForMerge(action.at.anchor, path2, position), focus = transformPointForMerge(action.at.focus, path2, position);
8096
- editorAny.pendingAction = anchor && focus ? {
8097
- ...action,
8098
- at: {
8099
- anchor,
8100
- focus
7939
+ charsToLines(diffs, linearray), diffs = cleanupSemantic(diffs), diffs.push([DIFF_EQUAL, ""]);
7940
+ let pointer = 0, countDelete = 0, countInsert = 0, textDelete = "", textInsert = "";
7941
+ for (; pointer < diffs.length; ) {
7942
+ switch (diffs[pointer][0]) {
7943
+ case DIFF_INSERT:
7944
+ countInsert++, textInsert += diffs[pointer][1];
7945
+ break;
7946
+ case DIFF_DELETE:
7947
+ countDelete++, textDelete += diffs[pointer][1];
7948
+ break;
7949
+ case DIFF_EQUAL:
7950
+ if (countDelete >= 1 && countInsert >= 1) {
7951
+ diffs.splice(pointer - countDelete - countInsert, countDelete + countInsert), pointer = pointer - countDelete - countInsert;
7952
+ const aa = doDiff(textDelete, textInsert, {
7953
+ checkLines: !1,
7954
+ deadline: opts.deadline
7955
+ });
7956
+ for (let j = aa.length - 1; j >= 0; j--) diffs.splice(pointer, 0, aa[j]);
7957
+ pointer += aa.length;
8101
7958
  }
8102
- } : null;
7959
+ countInsert = 0, countDelete = 0, textDelete = "", textInsert = "";
7960
+ break;
7961
+ default:
7962
+ throw new Error("Unknown diff operation.");
8103
7963
  }
7964
+ pointer++;
8104
7965
  }
8105
- const preTransformedPendingDiffs = editorAny.pendingDiffs, preTransformedPendingSelection = editorAny.pendingSelection, preTransformedPendingAction = editorAny.pendingAction;
8106
- editorAny.pendingDiffs = [], editorAny.pendingSelection = null, editorAny.pendingAction = null;
8107
- try {
8108
- withoutNormalizing(editor, () => {
8109
- if (isSpan({
8110
- schema: editor.schema
8111
- }, node))
8112
- node.text.length > 0 && editor.apply({
8113
- type: "insert_text",
8114
- path: prevPath,
8115
- offset: position,
8116
- text: node.text
8117
- }), editor.apply({
8118
- type: "remove_node",
8119
- path: path2,
8120
- node
8121
- });
8122
- else if (isTextBlock({
8123
- schema: editor.schema
8124
- }, node)) {
8125
- for (let i = 0; i < node.children.length; i++)
8126
- editor.apply({
8127
- type: "insert_node",
8128
- path: [...prevPath, position + i],
8129
- node: node.children[i]
8130
- });
8131
- editor.apply({
8132
- type: "remove_node",
8133
- path: path2,
8134
- node
8135
- });
8136
- }
8137
- });
8138
- } finally {
8139
- editor.selection = savedSelection;
8140
- for (const ref of pathRefs)
8141
- editor.pathRefs.add(ref);
8142
- for (const ref of pointRefs)
8143
- editor.pointRefs.add(ref);
8144
- for (const ref of rangeRefs)
8145
- editor.rangeRefs.add(ref);
8146
- editorAny.pendingDiffs = preTransformedPendingDiffs, editorAny.pendingSelection = preTransformedPendingSelection, editorAny.pendingAction = preTransformedPendingAction;
8147
- }
7966
+ return diffs.pop(), diffs;
8148
7967
  }
8149
- function transformTextDiffForMerge(textDiff, mergePath, position) {
8150
- const {
8151
- path: path2,
8152
- diff: diff2,
8153
- id
8154
- } = textDiff;
8155
- if (!pathEquals(mergePath, path2)) {
8156
- const newPath = transformPathForMerge(path2, mergePath, position);
8157
- return newPath ? {
8158
- diff: diff2,
8159
- id,
8160
- path: newPath
8161
- } : null;
7968
+ function computeDiff(text1, text2, opts) {
7969
+ let diffs;
7970
+ if (!text1) return [[DIFF_INSERT, text2]];
7971
+ if (!text2) return [[DIFF_DELETE, text1]];
7972
+ const longtext = text1.length > text2.length ? text1 : text2, shorttext = text1.length > text2.length ? text2 : text1, i = longtext.indexOf(shorttext);
7973
+ if (i !== -1) return diffs = [[DIFF_INSERT, longtext.substring(0, i)], [DIFF_EQUAL, shorttext], [DIFF_INSERT, longtext.substring(i + shorttext.length)]], text1.length > text2.length && (diffs[0][0] = DIFF_DELETE, diffs[2][0] = DIFF_DELETE), diffs;
7974
+ if (shorttext.length === 1) return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]];
7975
+ const halfMatch = findHalfMatch(text1, text2);
7976
+ if (halfMatch) {
7977
+ const text1A = halfMatch[0], text1B = halfMatch[1], text2A = halfMatch[2], text2B = halfMatch[3], midCommon = halfMatch[4], diffsA = doDiff(text1A, text2A, opts), diffsB = doDiff(text1B, text2B, opts);
7978
+ return diffsA.concat([[DIFF_EQUAL, midCommon]], diffsB);
8162
7979
  }
8163
- return {
8164
- diff: {
8165
- start: diff2.start + position,
8166
- end: diff2.end + position,
8167
- text: diff2.text
8168
- },
8169
- id,
8170
- path: transformPathForMerge(path2, mergePath, position)
8171
- };
7980
+ return opts.checkLines && text1.length > 100 && text2.length > 100 ? doLineModeDiff(text1, text2, opts) : bisect(text1, text2, opts.deadline);
8172
7981
  }
8173
- function transformPathForMerge(path2, mergePath, position) {
8174
- const p = [...path2];
8175
- return pathEquals(mergePath, p) || pathEndsBefore(mergePath, p) ? p[mergePath.length - 1] = p[mergePath.length - 1] - 1 : isAncestorPath(mergePath, p) && (p[mergePath.length - 1] = p[mergePath.length - 1] - 1, p[mergePath.length] = p[mergePath.length] + position), p;
7982
+ var __defProp$2 = Object.defineProperty, __getOwnPropSymbols$2 = Object.getOwnPropertySymbols, __hasOwnProp$2 = Object.prototype.hasOwnProperty, __propIsEnum$2 = Object.prototype.propertyIsEnumerable, __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, {
7983
+ enumerable: !0,
7984
+ configurable: !0,
7985
+ writable: !0,
7986
+ value
7987
+ }) : obj[key] = value, __spreadValues$2 = (a, b) => {
7988
+ for (var prop in b || (b = {})) __hasOwnProp$2.call(b, prop) && __defNormalProp$2(a, prop, b[prop]);
7989
+ if (__getOwnPropSymbols$2) for (var prop of __getOwnPropSymbols$2(b)) __propIsEnum$2.call(b, prop) && __defNormalProp$2(a, prop, b[prop]);
7990
+ return a;
7991
+ };
7992
+ const DIFF_DELETE = -1, DIFF_INSERT = 1, DIFF_EQUAL = 0;
7993
+ function diff(textA, textB, opts) {
7994
+ if (textA === null || textB === null) throw new Error("Null input. (diff)");
7995
+ const diffs = doDiff(textA, textB, createInternalOpts(opts || {}));
7996
+ return adjustDiffForSurrogatePairs(diffs), diffs;
8176
7997
  }
8177
- function transformPointForMerge(point2, mergePath, position) {
8178
- let {
8179
- path: path2,
8180
- offset
8181
- } = point2;
8182
- return pathEquals(mergePath, path2) && (offset += position), path2 = transformPathForMerge(path2, mergePath, position), {
8183
- path: path2,
8184
- offset
8185
- };
7998
+ function doDiff(textA, textB, options) {
7999
+ let text1 = textA, text2 = textB;
8000
+ if (text1 === text2) return text1 ? [[DIFF_EQUAL, text1]] : [];
8001
+ let commonlength = getCommonPrefix(text1, text2);
8002
+ const commonprefix = text1.substring(0, commonlength);
8003
+ text1 = text1.substring(commonlength), text2 = text2.substring(commonlength), commonlength = getCommonSuffix(text1, text2);
8004
+ const commonsuffix = text1.substring(text1.length - commonlength);
8005
+ text1 = text1.substring(0, text1.length - commonlength), text2 = text2.substring(0, text2.length - commonlength);
8006
+ let diffs = computeDiff(text1, text2, options);
8007
+ return commonprefix && diffs.unshift([DIFF_EQUAL, commonprefix]), commonsuffix && diffs.push([DIFF_EQUAL, commonsuffix]), diffs = cleanupMerge(diffs), diffs;
8186
8008
  }
8187
- function applySetNode(editor, props, path2) {
8188
- const nodeEntry = getNode(editor, path2);
8189
- if (!nodeEntry)
8190
- return;
8191
- const node = nodeEntry.node, nodeRecord = node, propsRecord = props, properties = {}, newProperties = {};
8192
- for (const key of Object.keys(propsRecord))
8193
- key !== "children" && (key === "text" && isSpanNode({
8194
- schema: editor.schema
8195
- }, node) || propsRecord[key] !== nodeRecord[key] && (nodeRecord.hasOwnProperty(key) && (properties[key] = nodeRecord[key]), propsRecord[key] != null && (newProperties[key] = propsRecord[key])));
8196
- (Object.keys(newProperties).length > 0 || Object.keys(properties).length > 0) && editor.apply({
8197
- type: "set_node",
8198
- path: path2,
8199
- properties,
8200
- newProperties
8201
- });
8009
+ function createDeadLine(timeout) {
8010
+ let t = 1;
8011
+ return typeof timeout < "u" && (t = timeout <= 0 ? Number.MAX_VALUE : timeout), Date.now() + t * 1e3;
8202
8012
  }
8203
- function withNormalizeNode(editor, fn) {
8204
- const prev = editor.isNormalizingNode;
8205
- editor.isNormalizingNode = !0, fn(), editor.isNormalizingNode = prev;
8013
+ function createInternalOpts(opts) {
8014
+ return __spreadValues$2({
8015
+ checkLines: !0,
8016
+ deadline: createDeadLine(opts.timeout || 1)
8017
+ }, opts);
8206
8018
  }
8207
- function withoutPatching(editor, fn) {
8208
- const prev = editor.isPatching;
8209
- editor.isPatching = !1, fn(), editor.isPatching = prev;
8019
+ function combineChar(data, char, dir) {
8020
+ return dir === 1 ? data + char : char + data;
8210
8021
  }
8211
- function createNormalizationPlugin(editorActor) {
8212
- return function(editor) {
8213
- const {
8214
- apply: apply2,
8215
- normalizeNode: normalizeNode2
8216
- } = editor, defaultStyle = editorActor.getSnapshot().context.schema.styles.at(0)?.name;
8217
- return editor.normalizeNode = (nodeEntry) => {
8218
- const [node, path2] = nodeEntry;
8219
- if (isEditor(node) && node.children.length === 0 && withoutPatching(editor, () => {
8220
- withNormalizeNode(editor, () => {
8221
- applyInsertNodeAtPath(editor, createPlaceholderBlock(editorActor.getSnapshot().context), [0]);
8222
- });
8223
- }), isTextBlock({
8224
- schema: editor.schema
8225
- }, node)) {
8226
- const children = getChildren(editor, path2);
8227
- for (const {
8228
- node: child,
8229
- path: childPath
8230
- } of children) {
8231
- const childIndex = childPath[childPath.length - 1], nextNode = node.children[childIndex + 1];
8232
- if (isSpan({
8233
- schema: editor.schema
8234
- }, child) && isSpan({
8235
- schema: editor.schema
8236
- }, nextNode) && child.marks?.every((mark) => nextNode.marks?.includes(mark)) && nextNode.marks?.every((mark) => child.marks?.includes(mark))) {
8237
- debug$1.normalization("merging spans with same marks"), withNormalizeNode(editor, () => {
8238
- const mergePath = [childPath[0], childPath[1] + 1];
8239
- applyMergeNode(editor, mergePath, child.text.length);
8240
- });
8241
- return;
8242
- }
8243
- }
8244
- }
8245
- if (isTextBlockNode({
8246
- schema: editor.schema
8247
- }, node) && !Array.isArray(node.markDefs)) {
8248
- debug$1.normalization("adding .markDefs to block node"), withNormalizeNode(editor, () => {
8249
- applySetNode(editor, {
8250
- markDefs: []
8251
- }, path2);
8252
- });
8253
- return;
8254
- }
8255
- if (defaultStyle && isTextBlockNode({
8256
- schema: editor.schema
8257
- }, node) && typeof node.style > "u") {
8258
- debug$1.normalization("adding .style to block node"), withNormalizeNode(editor, () => {
8259
- applySetNode(editor, {
8260
- style: defaultStyle
8261
- }, path2);
8262
- });
8263
- return;
8264
- }
8265
- if (isSpanNode({
8266
- schema: editor.schema
8267
- }, node) && typeof node.text != "string") {
8268
- debug$1.normalization("Adding .text to span node"), withNormalizeNode(editor, () => {
8269
- editor.apply({
8270
- type: "set_node",
8271
- path: path2,
8272
- properties: {},
8273
- newProperties: {
8274
- text: ""
8275
- }
8276
- });
8277
- });
8278
- return;
8279
- }
8280
- if (isSpan({
8281
- schema: editor.schema
8282
- }, node) && !Array.isArray(node.marks)) {
8283
- debug$1.normalization("Adding .marks to span node"), withNormalizeNode(editor, () => {
8284
- applySetNode(editor, {
8285
- marks: []
8286
- }, path2);
8287
- });
8288
- return;
8289
- }
8290
- if (isSpan({
8291
- schema: editor.schema
8292
- }, node)) {
8293
- const blockPath = parentPath(path2);
8294
- if (!getTextBlockNode(editor, blockPath))
8295
- return;
8296
- const decorators = editorActor.getSnapshot().context.schema.decorators.map((decorator) => decorator.name), annotations = node.marks?.filter((mark) => !decorators.includes(mark));
8297
- if (node.text === "" && annotations && annotations.length > 0) {
8298
- debug$1.normalization("removing annotations from empty span node"), withNormalizeNode(editor, () => {
8299
- applySetNode(editor, {
8300
- marks: node.marks?.filter((mark) => decorators.includes(mark))
8301
- }, path2);
8302
- });
8303
- return;
8304
- }
8305
- }
8306
- if (isTextBlock({
8307
- schema: editor.schema
8308
- }, node)) {
8309
- const decorators = editorActor.getSnapshot().context.schema.decorators.map((decorator) => decorator.name);
8310
- for (const {
8311
- node: child,
8312
- path: childPath
8313
- } of getChildren(editor, path2))
8314
- if (isSpan({
8315
- schema: editor.schema
8316
- }, child)) {
8317
- const marks = child.marks ?? [], orphanedAnnotations = marks.filter((mark) => !decorators.includes(mark) && !node.markDefs?.find((def) => def._key === mark));
8318
- if (orphanedAnnotations.length > 0) {
8319
- debug$1.normalization("removing orphaned annotations from span node"), withNormalizeNode(editor, () => {
8320
- applySetNode(editor, {
8321
- marks: marks.filter((mark) => !orphanedAnnotations.includes(mark))
8322
- }, childPath);
8323
- });
8324
- return;
8325
- }
8326
- }
8327
- }
8328
- if (isSpan({
8329
- schema: editor.schema
8330
- }, node)) {
8331
- const blockPath = parentPath(path2), blockEntry2 = getTextBlockNode(editor, blockPath);
8332
- if (blockEntry2) {
8333
- const block = blockEntry2.node, decorators = editorActor.getSnapshot().context.schema.decorators.map((decorator) => decorator.name), marks = node.marks ?? [], orphanedAnnotations = marks.filter((mark) => !decorators.includes(mark) && !block.markDefs?.find((def) => def._key === mark));
8334
- if (orphanedAnnotations.length > 0) {
8335
- debug$1.normalization("removing orphaned annotations from span node"), withNormalizeNode(editor, () => {
8336
- applySetNode(editor, {
8337
- marks: marks.filter((mark) => !orphanedAnnotations.includes(mark))
8338
- }, path2);
8339
- });
8340
- return;
8341
- }
8342
- }
8343
- }
8344
- if (isTextBlock({
8345
- schema: editor.schema
8346
- }, node)) {
8347
- const markDefs = node.markDefs ?? [], markDefKeys = /* @__PURE__ */ new Set(), newMarkDefs = [];
8348
- for (const markDef of markDefs)
8349
- markDefKeys.has(markDef._key) || (markDefKeys.add(markDef._key), newMarkDefs.push(markDef));
8350
- if (markDefs.length !== newMarkDefs.length) {
8351
- debug$1.normalization("removing duplicate markDefs"), withNormalizeNode(editor, () => {
8352
- applySetNode(editor, {
8353
- markDefs: newMarkDefs
8354
- }, path2);
8355
- });
8356
- return;
8357
- }
8358
- }
8359
- if (isTextBlock({
8360
- schema: editor.schema
8361
- }, node)) {
8362
- const newMarkDefs = (node.markDefs || []).filter((def) => node.children.find((child) => isSpan({
8363
- schema: editor.schema
8364
- }, child) && Array.isArray(child.marks) && child.marks.includes(def._key)));
8365
- if (node.markDefs && !isEqualMarkDefs(newMarkDefs, node.markDefs)) {
8366
- debug$1.normalization("removing markDef not in use"), withNormalizeNode(editor, () => {
8367
- applySetNode(editor, {
8368
- markDefs: newMarkDefs
8369
- }, path2);
8370
- });
8371
- return;
8372
- }
8373
- }
8374
- withNormalizeNode(editor, () => {
8375
- normalizeNode2(nodeEntry);
8376
- });
8377
- }, editor.apply = (op) => {
8378
- if (editor.isProcessingRemoteChanges) {
8379
- apply2(op);
8380
- return;
8381
- }
8382
- if (editor.isUndoing || editor.isRedoing) {
8383
- apply2(op);
8384
- return;
8385
- }
8386
- if (op.type === "set_selection")
8387
- if (op.properties && op.newProperties && op.properties.anchor && op.properties.focus && op.newProperties.anchor && op.newProperties.focus) {
8388
- const previousSelectionIsCollapsed = isCollapsedRange({
8389
- anchor: op.properties.anchor,
8390
- focus: op.properties.focus
8391
- }), newSelectionIsCollapsed = isCollapsedRange({
8392
- anchor: op.newProperties.anchor,
8393
- focus: op.newProperties.focus
8394
- });
8395
- if (previousSelectionIsCollapsed && newSelectionIsCollapsed) {
8396
- const focusSpan = getSpanNode(editor, op.properties.focus.path)?.node, newFocusSpan = getSpanNode(editor, op.newProperties.focus.path)?.node, movedToNextSpan = focusSpan && newFocusSpan && op.newProperties.focus.path[0] === op.properties.focus.path[0] && op.newProperties.focus.path[1] === op.properties.focus.path[1] + 1 && focusSpan.text.length === op.properties.focus.offset && op.newProperties.focus.offset === 0, movedToPreviousSpan = focusSpan && newFocusSpan && op.newProperties.focus.path[0] === op.properties.focus.path[0] && op.newProperties.focus.path[1] === op.properties.focus.path[1] - 1 && op.properties.focus.offset === 0 && newFocusSpan.text.length === op.newProperties.focus.offset;
8397
- !movedToNextSpan && !movedToPreviousSpan && (editor.decoratorState = {});
8398
- }
8399
- } else
8400
- editor.decoratorState = {};
8401
- apply2(op);
8402
- }, editor;
8403
- };
8404
- }
8405
- function cloneDiff(diff2) {
8406
- const [type, patch] = diff2;
8407
- return [type, patch];
8408
- }
8409
- function getCommonOverlap(textA, textB) {
8410
- let text1 = textA, text2 = textB;
8411
- const text1Length = text1.length, text2Length = text2.length;
8412
- if (text1Length === 0 || text2Length === 0) return 0;
8413
- text1Length > text2Length ? text1 = text1.substring(text1Length - text2Length) : text1Length < text2Length && (text2 = text2.substring(0, text1Length));
8414
- const textLength = Math.min(text1Length, text2Length);
8415
- if (text1 === text2) return textLength;
8416
- let best = 0, length = 1;
8417
- for (let found = 0; found !== -1; ) {
8418
- const pattern = text1.substring(textLength - length);
8419
- if (found = text2.indexOf(pattern), found === -1) return best;
8420
- length += found, (found === 0 || text1.substring(textLength - length) === text2.substring(0, length)) && (best = length, length++);
8421
- }
8422
- return best;
8423
- }
8424
- function getCommonPrefix(text1, text2) {
8425
- if (!text1 || !text2 || text1[0] !== text2[0]) return 0;
8426
- let pointerMin = 0, pointerMax = Math.min(text1.length, text2.length), pointerMid = pointerMax, pointerStart = 0;
8427
- for (; pointerMin < pointerMid; ) text1.substring(pointerStart, pointerMid) === text2.substring(pointerStart, pointerMid) ? (pointerMin = pointerMid, pointerStart = pointerMin) : pointerMax = pointerMid, pointerMid = Math.floor((pointerMax - pointerMin) / 2 + pointerMin);
8428
- return pointerMid;
8429
- }
8430
- function getCommonSuffix(text1, text2) {
8431
- if (!text1 || !text2 || text1[text1.length - 1] !== text2[text2.length - 1]) return 0;
8432
- let pointerMin = 0, pointerMax = Math.min(text1.length, text2.length), pointerMid = pointerMax, pointerEnd = 0;
8433
- for (; pointerMin < pointerMid; ) text1.substring(text1.length - pointerMid, text1.length - pointerEnd) === text2.substring(text2.length - pointerMid, text2.length - pointerEnd) ? (pointerMin = pointerMid, pointerEnd = pointerMin) : pointerMax = pointerMid, pointerMid = Math.floor((pointerMax - pointerMin) / 2 + pointerMin);
8434
- return pointerMid;
8435
- }
8436
- function isHighSurrogate(char) {
8437
- const charCode = char.charCodeAt(0);
8438
- return charCode >= 55296 && charCode <= 56319;
8022
+ function splitChar(data, dir) {
8023
+ return dir === 1 ? [data.substring(0, data.length - 1), data[data.length - 1]] : [data.substring(1), data[0]];
8439
8024
  }
8440
- function isLowSurrogate(char) {
8441
- const charCode = char.charCodeAt(0);
8442
- return charCode >= 56320 && charCode <= 57343;
8025
+ function hasSharedChar(diffs, i, j, dir) {
8026
+ return dir === 1 ? diffs[i][1][diffs[i][1].length - 1] === diffs[j][1][diffs[j][1].length - 1] : diffs[i][1][0] === diffs[j][1][0];
8443
8027
  }
8444
- function bisect(text1, text2, deadline) {
8445
- const text1Length = text1.length, text2Length = text2.length, maxD = Math.ceil((text1Length + text2Length) / 2), vOffset = maxD, vLength = 2 * maxD, v1 = new Array(vLength), v2 = new Array(vLength);
8446
- for (let x = 0; x < vLength; x++) v1[x] = -1, v2[x] = -1;
8447
- v1[vOffset + 1] = 0, v2[vOffset + 1] = 0;
8448
- const delta = text1Length - text2Length, front = delta % 2 !== 0;
8449
- let k1start = 0, k1end = 0, k2start = 0, k2end = 0;
8450
- for (let d = 0; d < maxD && !(Date.now() > deadline); d++) {
8451
- for (let k1 = -d + k1start; k1 <= d - k1end; k1 += 2) {
8452
- const k1Offset = vOffset + k1;
8453
- let x1;
8454
- k1 === -d || k1 !== d && v1[k1Offset - 1] < v1[k1Offset + 1] ? x1 = v1[k1Offset + 1] : x1 = v1[k1Offset - 1] + 1;
8455
- let y1 = x1 - k1;
8456
- for (; x1 < text1Length && y1 < text2Length && text1.charAt(x1) === text2.charAt(y1); ) x1++, y1++;
8457
- if (v1[k1Offset] = x1, x1 > text1Length) k1end += 2;
8458
- else if (y1 > text2Length) k1start += 2;
8459
- else if (front) {
8460
- const k2Offset = vOffset + delta - k1;
8461
- if (k2Offset >= 0 && k2Offset < vLength && v2[k2Offset] !== -1) {
8462
- const x2 = text1Length - v2[k2Offset];
8463
- if (x1 >= x2) return bisectSplit(text1, text2, x1, y1, deadline);
8464
- }
8465
- }
8466
- }
8467
- for (let k2 = -d + k2start; k2 <= d - k2end; k2 += 2) {
8468
- const k2Offset = vOffset + k2;
8469
- let x2;
8470
- k2 === -d || k2 !== d && v2[k2Offset - 1] < v2[k2Offset + 1] ? x2 = v2[k2Offset + 1] : x2 = v2[k2Offset - 1] + 1;
8471
- let y2 = x2 - k2;
8472
- for (; x2 < text1Length && y2 < text2Length && text1.charAt(text1Length - x2 - 1) === text2.charAt(text2Length - y2 - 1); ) x2++, y2++;
8473
- if (v2[k2Offset] = x2, x2 > text1Length) k2end += 2;
8474
- else if (y2 > text2Length) k2start += 2;
8475
- else if (!front) {
8476
- const k1Offset = vOffset + delta - k2;
8477
- if (k1Offset >= 0 && k1Offset < vLength && v1[k1Offset] !== -1) {
8478
- const x1 = v1[k1Offset], y1 = vOffset + x1 - k1Offset;
8479
- if (x2 = text1Length - x2, x1 >= x2) return bisectSplit(text1, text2, x1, y1, deadline);
8028
+ function deisolateChar(diffs, i, dir) {
8029
+ const inv = dir === 1 ? -1 : 1;
8030
+ let insertIdx = null, deleteIdx = null, j = i + dir;
8031
+ for (; j >= 0 && j < diffs.length && (insertIdx === null || deleteIdx === null); j += dir) {
8032
+ const [op, text2] = diffs[j];
8033
+ if (text2.length !== 0) {
8034
+ if (op === DIFF_INSERT) {
8035
+ insertIdx === null && (insertIdx = j);
8036
+ continue;
8037
+ } else if (op === DIFF_DELETE) {
8038
+ deleteIdx === null && (deleteIdx = j);
8039
+ continue;
8040
+ } else if (op === DIFF_EQUAL) {
8041
+ if (insertIdx === null && deleteIdx === null) {
8042
+ const [rest, char2] = splitChar(diffs[i][1], dir);
8043
+ diffs[i][1] = rest, diffs[j][1] = combineChar(diffs[j][1], char2, inv);
8044
+ return;
8480
8045
  }
8046
+ break;
8481
8047
  }
8482
8048
  }
8483
8049
  }
8484
- return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]];
8485
- }
8486
- function bisectSplit(text1, text2, x, y, deadline) {
8487
- const text1a = text1.substring(0, x), text2a = text2.substring(0, y), text1b = text1.substring(x), text2b = text2.substring(y), diffs = doDiff(text1a, text2a, {
8488
- checkLines: !1,
8489
- deadline
8490
- }), diffsb = doDiff(text1b, text2b, {
8491
- checkLines: !1,
8492
- deadline
8493
- });
8494
- return diffs.concat(diffsb);
8495
- }
8496
- function findHalfMatch(text1, text2, timeout = 1) {
8497
- if (timeout <= 0) return null;
8498
- const longText = text1.length > text2.length ? text1 : text2, shortText = text1.length > text2.length ? text2 : text1;
8499
- if (longText.length < 4 || shortText.length * 2 < longText.length) return null;
8500
- const halfMatch1 = halfMatchI(longText, shortText, Math.ceil(longText.length / 4)), halfMatch2 = halfMatchI(longText, shortText, Math.ceil(longText.length / 2));
8501
- let halfMatch;
8502
- if (halfMatch1 && halfMatch2) halfMatch = halfMatch1[4].length > halfMatch2[4].length ? halfMatch1 : halfMatch2;
8503
- else {
8504
- if (!halfMatch1 && !halfMatch2) return null;
8505
- halfMatch2 ? halfMatch1 || (halfMatch = halfMatch2) : halfMatch = halfMatch1;
8050
+ if (insertIdx !== null && deleteIdx !== null && hasSharedChar(diffs, insertIdx, deleteIdx, dir)) {
8051
+ const [insertText2, insertChar] = splitChar(diffs[insertIdx][1], inv), [deleteText2] = splitChar(diffs[deleteIdx][1], inv);
8052
+ diffs[insertIdx][1] = insertText2, diffs[deleteIdx][1] = deleteText2, diffs[i][1] = combineChar(diffs[i][1], insertChar, dir);
8053
+ return;
8506
8054
  }
8507
- if (!halfMatch) throw new Error("Unable to find a half match.");
8508
- let text1A, text1B, text2A, text2B;
8509
- text1.length > text2.length ? (text1A = halfMatch[0], text1B = halfMatch[1], text2A = halfMatch[2], text2B = halfMatch[3]) : (text2A = halfMatch[0], text2B = halfMatch[1], text1A = halfMatch[2], text1B = halfMatch[3]);
8510
- const midCommon = halfMatch[4];
8511
- return [text1A, text1B, text2A, text2B, midCommon];
8055
+ const [text, char] = splitChar(diffs[i][1], dir);
8056
+ diffs[i][1] = text, insertIdx === null ? (diffs.splice(j, 0, [DIFF_INSERT, char]), deleteIdx !== null && deleteIdx >= j && deleteIdx++) : diffs[insertIdx][1] = combineChar(diffs[insertIdx][1], char, inv), deleteIdx === null ? diffs.splice(j, 0, [DIFF_DELETE, char]) : diffs[deleteIdx][1] = combineChar(diffs[deleteIdx][1], char, inv);
8512
8057
  }
8513
- function halfMatchI(longText, shortText, i) {
8514
- const seed = longText.slice(i, i + Math.floor(longText.length / 4));
8515
- let j = -1, bestCommon = "", bestLongTextA, bestLongTextB, bestShortTextA, bestShortTextB;
8516
- for (; (j = shortText.indexOf(seed, j + 1)) !== -1; ) {
8517
- const prefixLength = getCommonPrefix(longText.slice(i), shortText.slice(j)), suffixLength = getCommonSuffix(longText.slice(0, i), shortText.slice(0, j));
8518
- bestCommon.length < suffixLength + prefixLength && (bestCommon = shortText.slice(j - suffixLength, j) + shortText.slice(j, j + prefixLength), bestLongTextA = longText.slice(0, i - suffixLength), bestLongTextB = longText.slice(i + prefixLength), bestShortTextA = shortText.slice(0, j - suffixLength), bestShortTextB = shortText.slice(j + prefixLength));
8058
+ function adjustDiffForSurrogatePairs(diffs) {
8059
+ for (let i = 0; i < diffs.length; i++) {
8060
+ const [diffType, diffText] = diffs[i];
8061
+ if (diffText.length === 0) continue;
8062
+ const firstChar = diffText[0], lastChar = diffText[diffText.length - 1];
8063
+ isHighSurrogate(lastChar) && diffType === DIFF_EQUAL && deisolateChar(diffs, i, 1), isLowSurrogate(firstChar) && diffType === DIFF_EQUAL && deisolateChar(diffs, i, -1);
8519
8064
  }
8520
- return bestCommon.length * 2 >= longText.length ? [bestLongTextA || "", bestLongTextB || "", bestShortTextA || "", bestShortTextB || "", bestCommon || ""] : null;
8065
+ for (let i = 0; i < diffs.length; i++) diffs[i][1].length === 0 && diffs.splice(i, 1);
8521
8066
  }
8522
- function charsToLines(diffs, lineArray) {
8523
- for (let x = 0; x < diffs.length; x++) {
8524
- const chars = diffs[x][1], text = [];
8525
- for (let y = 0; y < chars.length; y++) text[y] = lineArray[chars.charCodeAt(y)];
8526
- diffs[x][1] = text.join("");
8067
+ function cleanupSemantic(rawDiffs) {
8068
+ let diffs = rawDiffs.map((diff2) => cloneDiff(diff2)), hasChanges = !1;
8069
+ const equalities = [];
8070
+ let equalitiesLength = 0, lastEquality = null, pointer = 0, lengthInsertions1 = 0, lengthDeletions1 = 0, lengthInsertions2 = 0, lengthDeletions2 = 0;
8071
+ for (; pointer < diffs.length; ) diffs[pointer][0] === DIFF_EQUAL ? (equalities[equalitiesLength++] = pointer, lengthInsertions1 = lengthInsertions2, lengthDeletions1 = lengthDeletions2, lengthInsertions2 = 0, lengthDeletions2 = 0, lastEquality = diffs[pointer][1]) : (diffs[pointer][0] === DIFF_INSERT ? lengthInsertions2 += diffs[pointer][1].length : lengthDeletions2 += diffs[pointer][1].length, lastEquality && lastEquality.length <= Math.max(lengthInsertions1, lengthDeletions1) && lastEquality.length <= Math.max(lengthInsertions2, lengthDeletions2) && (diffs.splice(equalities[equalitiesLength - 1], 0, [DIFF_DELETE, lastEquality]), diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT, equalitiesLength--, equalitiesLength--, pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1, lengthInsertions1 = 0, lengthDeletions1 = 0, lengthInsertions2 = 0, lengthDeletions2 = 0, lastEquality = null, hasChanges = !0)), pointer++;
8072
+ for (hasChanges && (diffs = cleanupMerge(diffs)), diffs = cleanupSemanticLossless(diffs), pointer = 1; pointer < diffs.length; ) {
8073
+ if (diffs[pointer - 1][0] === DIFF_DELETE && diffs[pointer][0] === DIFF_INSERT) {
8074
+ const deletion = diffs[pointer - 1][1], insertion = diffs[pointer][1], overlapLength1 = getCommonOverlap(deletion, insertion), overlapLength2 = getCommonOverlap(insertion, deletion);
8075
+ overlapLength1 >= overlapLength2 ? (overlapLength1 >= deletion.length / 2 || overlapLength1 >= insertion.length / 2) && (diffs.splice(pointer, 0, [DIFF_EQUAL, insertion.substring(0, overlapLength1)]), diffs[pointer - 1][1] = deletion.substring(0, deletion.length - overlapLength1), diffs[pointer + 1][1] = insertion.substring(overlapLength1), pointer++) : (overlapLength2 >= deletion.length / 2 || overlapLength2 >= insertion.length / 2) && (diffs.splice(pointer, 0, [DIFF_EQUAL, deletion.substring(0, overlapLength2)]), diffs[pointer - 1][0] = DIFF_INSERT, diffs[pointer - 1][1] = insertion.substring(0, insertion.length - overlapLength2), diffs[pointer + 1][0] = DIFF_DELETE, diffs[pointer + 1][1] = deletion.substring(overlapLength2), pointer++), pointer++;
8076
+ }
8077
+ pointer++;
8527
8078
  }
8528
- }
8529
- function linesToChars(textA, textB) {
8530
- const lineArray = [], lineHash = {};
8531
- lineArray[0] = "";
8532
- function diffLinesToMunge(text) {
8533
- let chars = "", lineStart = 0, lineEnd = -1, lineArrayLength = lineArray.length;
8534
- for (; lineEnd < text.length - 1; ) {
8535
- lineEnd = text.indexOf(`
8536
- `, lineStart), lineEnd === -1 && (lineEnd = text.length - 1);
8537
- let line = text.slice(lineStart, lineEnd + 1);
8538
- (lineHash.hasOwnProperty ? lineHash.hasOwnProperty(line) : lineHash[line] !== void 0) ? chars += String.fromCharCode(lineHash[line]) : (lineArrayLength === maxLines && (line = text.slice(lineStart), lineEnd = text.length), chars += String.fromCharCode(lineArrayLength), lineHash[line] = lineArrayLength, lineArray[lineArrayLength++] = line), lineStart = lineEnd + 1;
8539
- }
8540
- return chars;
8541
- }
8542
- let maxLines = 4e4;
8543
- const chars1 = diffLinesToMunge(textA);
8544
- maxLines = 65535;
8545
- const chars2 = diffLinesToMunge(textB);
8546
- return {
8547
- chars1,
8548
- chars2,
8549
- lineArray
8550
- };
8551
- }
8552
- function doLineModeDiff(textA, textB, opts) {
8553
- let text1 = textA, text2 = textB;
8554
- const a = linesToChars(text1, text2);
8555
- text1 = a.chars1, text2 = a.chars2;
8556
- const linearray = a.lineArray;
8557
- let diffs = doDiff(text1, text2, {
8558
- checkLines: !1,
8559
- deadline: opts.deadline
8560
- });
8561
- charsToLines(diffs, linearray), diffs = cleanupSemantic(diffs), diffs.push([DIFF_EQUAL, ""]);
8562
- let pointer = 0, countDelete = 0, countInsert = 0, textDelete = "", textInsert = "";
8563
- for (; pointer < diffs.length; ) {
8564
- switch (diffs[pointer][0]) {
8565
- case DIFF_INSERT:
8566
- countInsert++, textInsert += diffs[pointer][1];
8567
- break;
8568
- case DIFF_DELETE:
8569
- countDelete++, textDelete += diffs[pointer][1];
8570
- break;
8571
- case DIFF_EQUAL:
8572
- if (countDelete >= 1 && countInsert >= 1) {
8573
- diffs.splice(pointer - countDelete - countInsert, countDelete + countInsert), pointer = pointer - countDelete - countInsert;
8574
- const aa = doDiff(textDelete, textInsert, {
8575
- checkLines: !1,
8576
- deadline: opts.deadline
8577
- });
8578
- for (let j = aa.length - 1; j >= 0; j--) diffs.splice(pointer, 0, aa[j]);
8579
- pointer += aa.length;
8580
- }
8581
- countInsert = 0, countDelete = 0, textDelete = "", textInsert = "";
8582
- break;
8583
- default:
8584
- throw new Error("Unknown diff operation.");
8585
- }
8586
- pointer++;
8587
- }
8588
- return diffs.pop(), diffs;
8589
- }
8590
- function computeDiff(text1, text2, opts) {
8591
- let diffs;
8592
- if (!text1) return [[DIFF_INSERT, text2]];
8593
- if (!text2) return [[DIFF_DELETE, text1]];
8594
- const longtext = text1.length > text2.length ? text1 : text2, shorttext = text1.length > text2.length ? text2 : text1, i = longtext.indexOf(shorttext);
8595
- if (i !== -1) return diffs = [[DIFF_INSERT, longtext.substring(0, i)], [DIFF_EQUAL, shorttext], [DIFF_INSERT, longtext.substring(i + shorttext.length)]], text1.length > text2.length && (diffs[0][0] = DIFF_DELETE, diffs[2][0] = DIFF_DELETE), diffs;
8596
- if (shorttext.length === 1) return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]];
8597
- const halfMatch = findHalfMatch(text1, text2);
8598
- if (halfMatch) {
8599
- const text1A = halfMatch[0], text1B = halfMatch[1], text2A = halfMatch[2], text2B = halfMatch[3], midCommon = halfMatch[4], diffsA = doDiff(text1A, text2A, opts), diffsB = doDiff(text1B, text2B, opts);
8600
- return diffsA.concat([[DIFF_EQUAL, midCommon]], diffsB);
8601
- }
8602
- return opts.checkLines && text1.length > 100 && text2.length > 100 ? doLineModeDiff(text1, text2, opts) : bisect(text1, text2, opts.deadline);
8603
- }
8604
- var __defProp$2 = Object.defineProperty, __getOwnPropSymbols$2 = Object.getOwnPropertySymbols, __hasOwnProp$2 = Object.prototype.hasOwnProperty, __propIsEnum$2 = Object.prototype.propertyIsEnumerable, __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, {
8605
- enumerable: !0,
8606
- configurable: !0,
8607
- writable: !0,
8608
- value
8609
- }) : obj[key] = value, __spreadValues$2 = (a, b) => {
8610
- for (var prop in b || (b = {})) __hasOwnProp$2.call(b, prop) && __defNormalProp$2(a, prop, b[prop]);
8611
- if (__getOwnPropSymbols$2) for (var prop of __getOwnPropSymbols$2(b)) __propIsEnum$2.call(b, prop) && __defNormalProp$2(a, prop, b[prop]);
8612
- return a;
8613
- };
8614
- const DIFF_DELETE = -1, DIFF_INSERT = 1, DIFF_EQUAL = 0;
8615
- function diff(textA, textB, opts) {
8616
- if (textA === null || textB === null) throw new Error("Null input. (diff)");
8617
- const diffs = doDiff(textA, textB, createInternalOpts(opts || {}));
8618
- return adjustDiffForSurrogatePairs(diffs), diffs;
8619
- }
8620
- function doDiff(textA, textB, options) {
8621
- let text1 = textA, text2 = textB;
8622
- if (text1 === text2) return text1 ? [[DIFF_EQUAL, text1]] : [];
8623
- let commonlength = getCommonPrefix(text1, text2);
8624
- const commonprefix = text1.substring(0, commonlength);
8625
- text1 = text1.substring(commonlength), text2 = text2.substring(commonlength), commonlength = getCommonSuffix(text1, text2);
8626
- const commonsuffix = text1.substring(text1.length - commonlength);
8627
- text1 = text1.substring(0, text1.length - commonlength), text2 = text2.substring(0, text2.length - commonlength);
8628
- let diffs = computeDiff(text1, text2, options);
8629
- return commonprefix && diffs.unshift([DIFF_EQUAL, commonprefix]), commonsuffix && diffs.push([DIFF_EQUAL, commonsuffix]), diffs = cleanupMerge(diffs), diffs;
8630
- }
8631
- function createDeadLine(timeout) {
8632
- let t = 1;
8633
- return typeof timeout < "u" && (t = timeout <= 0 ? Number.MAX_VALUE : timeout), Date.now() + t * 1e3;
8634
- }
8635
- function createInternalOpts(opts) {
8636
- return __spreadValues$2({
8637
- checkLines: !0,
8638
- deadline: createDeadLine(opts.timeout || 1)
8639
- }, opts);
8640
- }
8641
- function combineChar(data, char, dir) {
8642
- return dir === 1 ? data + char : char + data;
8643
- }
8644
- function splitChar(data, dir) {
8645
- return dir === 1 ? [data.substring(0, data.length - 1), data[data.length - 1]] : [data.substring(1), data[0]];
8646
- }
8647
- function hasSharedChar(diffs, i, j, dir) {
8648
- return dir === 1 ? diffs[i][1][diffs[i][1].length - 1] === diffs[j][1][diffs[j][1].length - 1] : diffs[i][1][0] === diffs[j][1][0];
8649
- }
8650
- function deisolateChar(diffs, i, dir) {
8651
- const inv = dir === 1 ? -1 : 1;
8652
- let insertIdx = null, deleteIdx = null, j = i + dir;
8653
- for (; j >= 0 && j < diffs.length && (insertIdx === null || deleteIdx === null); j += dir) {
8654
- const [op, text2] = diffs[j];
8655
- if (text2.length !== 0) {
8656
- if (op === DIFF_INSERT) {
8657
- insertIdx === null && (insertIdx = j);
8658
- continue;
8659
- } else if (op === DIFF_DELETE) {
8660
- deleteIdx === null && (deleteIdx = j);
8661
- continue;
8662
- } else if (op === DIFF_EQUAL) {
8663
- if (insertIdx === null && deleteIdx === null) {
8664
- const [rest, char2] = splitChar(diffs[i][1], dir);
8665
- diffs[i][1] = rest, diffs[j][1] = combineChar(diffs[j][1], char2, inv);
8666
- return;
8667
- }
8668
- break;
8669
- }
8670
- }
8671
- }
8672
- if (insertIdx !== null && deleteIdx !== null && hasSharedChar(diffs, insertIdx, deleteIdx, dir)) {
8673
- const [insertText2, insertChar] = splitChar(diffs[insertIdx][1], inv), [deleteText2] = splitChar(diffs[deleteIdx][1], inv);
8674
- diffs[insertIdx][1] = insertText2, diffs[deleteIdx][1] = deleteText2, diffs[i][1] = combineChar(diffs[i][1], insertChar, dir);
8675
- return;
8676
- }
8677
- const [text, char] = splitChar(diffs[i][1], dir);
8678
- diffs[i][1] = text, insertIdx === null ? (diffs.splice(j, 0, [DIFF_INSERT, char]), deleteIdx !== null && deleteIdx >= j && deleteIdx++) : diffs[insertIdx][1] = combineChar(diffs[insertIdx][1], char, inv), deleteIdx === null ? diffs.splice(j, 0, [DIFF_DELETE, char]) : diffs[deleteIdx][1] = combineChar(diffs[deleteIdx][1], char, inv);
8679
- }
8680
- function adjustDiffForSurrogatePairs(diffs) {
8681
- for (let i = 0; i < diffs.length; i++) {
8682
- const [diffType, diffText] = diffs[i];
8683
- if (diffText.length === 0) continue;
8684
- const firstChar = diffText[0], lastChar = diffText[diffText.length - 1];
8685
- isHighSurrogate(lastChar) && diffType === DIFF_EQUAL && deisolateChar(diffs, i, 1), isLowSurrogate(firstChar) && diffType === DIFF_EQUAL && deisolateChar(diffs, i, -1);
8686
- }
8687
- for (let i = 0; i < diffs.length; i++) diffs[i][1].length === 0 && diffs.splice(i, 1);
8688
- }
8689
- function cleanupSemantic(rawDiffs) {
8690
- let diffs = rawDiffs.map((diff2) => cloneDiff(diff2)), hasChanges = !1;
8691
- const equalities = [];
8692
- let equalitiesLength = 0, lastEquality = null, pointer = 0, lengthInsertions1 = 0, lengthDeletions1 = 0, lengthInsertions2 = 0, lengthDeletions2 = 0;
8693
- for (; pointer < diffs.length; ) diffs[pointer][0] === DIFF_EQUAL ? (equalities[equalitiesLength++] = pointer, lengthInsertions1 = lengthInsertions2, lengthDeletions1 = lengthDeletions2, lengthInsertions2 = 0, lengthDeletions2 = 0, lastEquality = diffs[pointer][1]) : (diffs[pointer][0] === DIFF_INSERT ? lengthInsertions2 += diffs[pointer][1].length : lengthDeletions2 += diffs[pointer][1].length, lastEquality && lastEquality.length <= Math.max(lengthInsertions1, lengthDeletions1) && lastEquality.length <= Math.max(lengthInsertions2, lengthDeletions2) && (diffs.splice(equalities[equalitiesLength - 1], 0, [DIFF_DELETE, lastEquality]), diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT, equalitiesLength--, equalitiesLength--, pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1, lengthInsertions1 = 0, lengthDeletions1 = 0, lengthInsertions2 = 0, lengthDeletions2 = 0, lastEquality = null, hasChanges = !0)), pointer++;
8694
- for (hasChanges && (diffs = cleanupMerge(diffs)), diffs = cleanupSemanticLossless(diffs), pointer = 1; pointer < diffs.length; ) {
8695
- if (diffs[pointer - 1][0] === DIFF_DELETE && diffs[pointer][0] === DIFF_INSERT) {
8696
- const deletion = diffs[pointer - 1][1], insertion = diffs[pointer][1], overlapLength1 = getCommonOverlap(deletion, insertion), overlapLength2 = getCommonOverlap(insertion, deletion);
8697
- overlapLength1 >= overlapLength2 ? (overlapLength1 >= deletion.length / 2 || overlapLength1 >= insertion.length / 2) && (diffs.splice(pointer, 0, [DIFF_EQUAL, insertion.substring(0, overlapLength1)]), diffs[pointer - 1][1] = deletion.substring(0, deletion.length - overlapLength1), diffs[pointer + 1][1] = insertion.substring(overlapLength1), pointer++) : (overlapLength2 >= deletion.length / 2 || overlapLength2 >= insertion.length / 2) && (diffs.splice(pointer, 0, [DIFF_EQUAL, deletion.substring(0, overlapLength2)]), diffs[pointer - 1][0] = DIFF_INSERT, diffs[pointer - 1][1] = insertion.substring(0, insertion.length - overlapLength2), diffs[pointer + 1][0] = DIFF_DELETE, diffs[pointer + 1][1] = deletion.substring(overlapLength2), pointer++), pointer++;
8698
- }
8699
- pointer++;
8700
- }
8701
- return diffs;
8079
+ return diffs;
8702
8080
  }
8703
8081
  const nonAlphaNumericRegex = /[^a-zA-Z0-9]/, whitespaceRegex = /\s/, linebreakRegex = /[\r\n]/, blanklineEndRegex = /\n\r?\n$/, blanklineStartRegex = /^\r?\n\r?\n/;
8704
8082
  function cleanupSemanticLossless(rawDiffs) {
@@ -9038,6 +8416,35 @@ function parse(textline) {
9038
8416
  function toInt(num) {
9039
8417
  return parseInt(num, 10);
9040
8418
  }
8419
+ function pathRef(editor, path2, options = {}) {
8420
+ const {
8421
+ affinity = "forward"
8422
+ } = options, ref = {
8423
+ current: path2,
8424
+ affinity,
8425
+ unref() {
8426
+ const {
8427
+ current
8428
+ } = ref;
8429
+ return editor.pathRefs.delete(ref), ref.current = null, current;
8430
+ }
8431
+ };
8432
+ return editor.pathRefs.add(ref), ref;
8433
+ }
8434
+ function applySetNode(editor, props, path2) {
8435
+ const nodeEntry = getNode(editor, path2);
8436
+ if (!nodeEntry)
8437
+ return;
8438
+ const nodeRecord = nodeEntry.node, propsRecord = props, properties = {}, newProperties = {};
8439
+ for (const key of Object.keys(propsRecord))
8440
+ propsRecord[key] !== nodeRecord[key] && (nodeRecord.hasOwnProperty(key) && (properties[key] = nodeRecord[key]), propsRecord[key] != null && (newProperties[key] = propsRecord[key]));
8441
+ (Object.keys(newProperties).length > 0 || Object.keys(properties).length > 0) && editor.apply({
8442
+ type: "set_node",
8443
+ path: path2,
8444
+ properties,
8445
+ newProperties
8446
+ });
8447
+ }
9041
8448
  function toSlateBlock(block, {
9042
8449
  schemaTypes
9043
8450
  }) {
@@ -9283,7 +8690,7 @@ function setPatch(editor, patch) {
9283
8690
  } else
9284
8691
  return applySetNode(editor, updatedBlock, [block.index]), !0;
9285
8692
  }
9286
- if (blockIsTextBlock && patch.path[1] !== "children") {
8693
+ if (blockIsTextBlock && (patch.path.length === 2 || patch.path[1] !== "children")) {
9287
8694
  const updatedBlock = applyAll(block.node, [{
9288
8695
  ...patch,
9289
8696
  path: patch.path.slice(1)
@@ -9568,13 +8975,13 @@ function setNodePatch(schema, children, operation) {
9568
8975
  const patches = [], _key = operation.newProperties._key;
9569
8976
  _key !== void 0 && patches.push(set(_key, [blockIndex, "_key"]));
9570
8977
  for (const [key, propertyValue] of Object.entries(operation.newProperties))
9571
- key === "_key" || key === "children" || patches.push(set(propertyValue, [{
8978
+ key !== "_key" && patches.push(set(propertyValue, [{
9572
8979
  _key: block._key
9573
8980
  }, key]));
9574
8981
  for (const key of Object.keys(operation.properties))
9575
- key === "_key" || key === "children" || key in operation.newProperties || patches.push(unset([{
8982
+ key !== "_key" && (key in operation.newProperties || patches.push(unset([{
9576
8983
  _key: block._key
9577
- }, key]));
8984
+ }, key])));
9578
8985
  return patches;
9579
8986
  }
9580
8987
  } else if (operation.path.length === 2) {
@@ -9593,7 +9000,7 @@ function setNodePatch(schema, children, operation) {
9593
9000
  _key: blockKey
9594
9001
  }, "children", block.children.indexOf(child), "_key"]));
9595
9002
  for (const [key, propertyValue] of Object.entries(operation.newProperties))
9596
- key === "_key" || key === "children" || patches.push(set(propertyValue, [{
9003
+ key !== "_key" && patches.push(set(propertyValue, [{
9597
9004
  _key: blockKey
9598
9005
  }, "children", {
9599
9006
  _key: childKey
@@ -9673,6 +9080,75 @@ function removeNodePatch(schema, beforeValue, operation) {
9673
9080
  } else
9674
9081
  return [];
9675
9082
  }
9083
+ function isNormalizing(editor) {
9084
+ return editor.normalizing;
9085
+ }
9086
+ function setNormalizing(editor, isNormalizing2) {
9087
+ editor.normalizing = isNormalizing2;
9088
+ }
9089
+ function withoutNormalizing(editor, fn) {
9090
+ const value = isNormalizing(editor);
9091
+ setNormalizing(editor, !1);
9092
+ try {
9093
+ fn();
9094
+ } finally {
9095
+ setNormalizing(editor, value);
9096
+ }
9097
+ normalize(editor);
9098
+ }
9099
+ function normalize(editor, options = {}) {
9100
+ const {
9101
+ force = !1,
9102
+ operation
9103
+ } = options, getDirtyPaths = (editor2) => editor2.dirtyPaths, getDirtyPathKeys = (editor2) => editor2.dirtyPathKeys, popDirtyPath = (editor2) => {
9104
+ const path2 = getDirtyPaths(editor2).pop(), key = path2.length === 1 ? String(path2[0]) : path2.length === 2 ? `${path2[0]},${path2[1]}` : path2.join(",");
9105
+ return getDirtyPathKeys(editor2).delete(key), path2;
9106
+ };
9107
+ if (isNormalizing(editor)) {
9108
+ if (force) {
9109
+ const allPaths = Array.from(getNodes(editor), (entry) => entry.path), allPathKeys = new Set(allPaths.map((p) => p.join(",")));
9110
+ editor.dirtyPaths = allPaths, editor.dirtyPathKeys = allPathKeys;
9111
+ }
9112
+ getDirtyPaths(editor).length !== 0 && withoutNormalizing(editor, () => {
9113
+ for (const dirtyPath of getDirtyPaths(editor))
9114
+ if (dirtyPath.length !== 0 && hasNode(editor, dirtyPath)) {
9115
+ const entry = getNode(editor, dirtyPath);
9116
+ if (!entry)
9117
+ continue;
9118
+ const entryNode = entry.node;
9119
+ isTextBlock({
9120
+ schema: editor.schema
9121
+ }, entryNode) && entryNode.children.length === 0 && (editor.isNormalizingNode = !0, editor.normalizeNode([entry.node, entry.path], {
9122
+ operation
9123
+ }), editor.isNormalizingNode = !1);
9124
+ }
9125
+ let dirtyPaths = getDirtyPaths(editor);
9126
+ const initialDirtyPathsLength = dirtyPaths.length;
9127
+ let iteration = 0;
9128
+ for (; dirtyPaths.length !== 0; ) {
9129
+ if (!editor.shouldNormalize({
9130
+ dirtyPaths,
9131
+ iteration,
9132
+ initialDirtyPathsLength,
9133
+ operation
9134
+ }))
9135
+ return;
9136
+ const dirtyPath = popDirtyPath(editor);
9137
+ if (dirtyPath.length === 0)
9138
+ editor.isNormalizingNode = !0, editor.normalizeNode([editor, dirtyPath], {
9139
+ operation
9140
+ }), editor.isNormalizingNode = !1;
9141
+ else if (hasNode(editor, dirtyPath)) {
9142
+ const entry = getNode(editor, dirtyPath);
9143
+ entry && (editor.isNormalizingNode = !0, editor.normalizeNode([entry.node, entry.path], {
9144
+ operation
9145
+ }), editor.isNormalizingNode = !1);
9146
+ }
9147
+ iteration++, dirtyPaths = getDirtyPaths(editor);
9148
+ }
9149
+ });
9150
+ }
9151
+ }
9676
9152
  function withRemoteChanges(editor, fn) {
9677
9153
  const prev = editor.isProcessingRemoteChanges;
9678
9154
  editor.isProcessingRemoteChanges = !0, fn(), editor.isProcessingRemoteChanges = prev;
@@ -9681,6 +9157,10 @@ function pluginWithoutHistory(editor, fn) {
9681
9157
  const prev = editor.withHistory;
9682
9158
  editor.withHistory = !1, fn(), editor.withHistory = prev;
9683
9159
  }
9160
+ function withoutPatching(editor, fn) {
9161
+ const prev = editor.isPatching;
9162
+ editor.isPatching = !1, fn(), editor.isPatching = prev;
9163
+ }
9684
9164
  function createPatchesPlugin({
9685
9165
  editorActor,
9686
9166
  relayActor,
@@ -9772,134 +9252,6 @@ function createPatchesPlugin({
9772
9252
  }, editor;
9773
9253
  };
9774
9254
  }
9775
- function createSchemaPlugin({
9776
- editorActor
9777
- }) {
9778
- return function(editor) {
9779
- editor.schema = editorActor.getSnapshot().context.schema, editor.isInline = (element) => {
9780
- if (isEditor(element))
9781
- return !1;
9782
- const snapshot = editorActor.getSnapshot();
9783
- if (!snapshot.context.schema.inlineObjects.map((obj) => obj.name).includes(element._type))
9784
- return !1;
9785
- if (snapshot.context.schema.blockObjects.map((obj) => obj.name).includes(element._type)) {
9786
- for (const child of editor.children)
9787
- if (child === element)
9788
- return !1;
9789
- }
9790
- return !0;
9791
- };
9792
- const {
9793
- normalizeNode: normalizeNode2
9794
- } = editor;
9795
- return editor.normalizeNode = (entry) => {
9796
- const [node, path2] = entry;
9797
- if (isEditor(node)) {
9798
- normalizeNode2(entry);
9799
- return;
9800
- }
9801
- if (node._type === void 0 && path2.length === 2) {
9802
- debug$1.normalization("Setting span type on text node without a type");
9803
- const span = node, key = span._key || editorActor.getSnapshot().context.keyGenerator();
9804
- withNormalizeNode(editor, () => {
9805
- applySetNode(editor, {
9806
- ...span,
9807
- _type: editorActor.getSnapshot().context.schema.span.name,
9808
- _key: key
9809
- }, path2);
9810
- });
9811
- return;
9812
- }
9813
- if (node._key === void 0 && (path2.length === 1 || path2.length === 2)) {
9814
- debug$1.normalization("Setting missing key on child node without a key");
9815
- const key = editorActor.getSnapshot().context.keyGenerator();
9816
- withNormalizeNode(editor, () => {
9817
- applySetNode(editor, {
9818
- _key: key
9819
- }, path2);
9820
- });
9821
- return;
9822
- }
9823
- withNormalizeNode(editor, () => {
9824
- normalizeNode2(entry);
9825
- });
9826
- }, editor;
9827
- };
9828
- }
9829
- function createUniqueKeysPlugin(editorActor) {
9830
- const context = editorActor.getSnapshot().context;
9831
- return function(editor) {
9832
- const {
9833
- apply: apply2,
9834
- normalizeNode: normalizeNode2
9835
- } = editor;
9836
- return editor.apply = (operation) => {
9837
- if (editor.isProcessingRemoteChanges) {
9838
- apply2(operation);
9839
- return;
9840
- }
9841
- if (editor.isUndoing || editor.isRedoing) {
9842
- apply2(operation);
9843
- return;
9844
- }
9845
- if (operation.type === "insert_node" && !isEditor(operation.node)) {
9846
- const _key = operation.node._key && keyExistsAtPath({
9847
- blockIndexMap: editor.blockIndexMap,
9848
- context: {
9849
- schema: context.schema,
9850
- value: editor.children
9851
- }
9852
- }, operation.path, operation.node._key) ? void 0 : operation.node._key;
9853
- apply2({
9854
- ...operation,
9855
- node: {
9856
- ...operation.node,
9857
- _key: _key === void 0 ? editorActor.getSnapshot().context.keyGenerator() : _key
9858
- }
9859
- });
9860
- return;
9861
- }
9862
- apply2(operation);
9863
- }, editor.normalizeNode = (entry) => {
9864
- const [_node, path2] = entry, parent = getParent(editor, path2), siblings = parent ? getChildren(editor, parent.path) : editor.children.map((child, index) => ({
9865
- node: child,
9866
- path: [index]
9867
- })), siblingKeys = /* @__PURE__ */ new Set();
9868
- for (const sibling of siblings) {
9869
- if (sibling.node._key && siblingKeys.has(sibling.node._key)) {
9870
- const _key = editorActor.getSnapshot().context.keyGenerator();
9871
- siblingKeys.add(_key), withNormalizeNode(editor, () => {
9872
- applySetNode(editor, {
9873
- _key
9874
- }, path2);
9875
- });
9876
- return;
9877
- }
9878
- if (!sibling.node._key) {
9879
- const _key = editorActor.getSnapshot().context.keyGenerator();
9880
- siblingKeys.add(_key), withNormalizeNode(editor, () => {
9881
- applySetNode(editor, {
9882
- _key
9883
- }, path2);
9884
- });
9885
- return;
9886
- }
9887
- siblingKeys.add(sibling.node._key);
9888
- }
9889
- withNormalizeNode(editor, () => {
9890
- normalizeNode2(entry);
9891
- });
9892
- }, editor;
9893
- };
9894
- }
9895
- function keyExistsAtPath(snapshot, path2, key) {
9896
- if (path2.length === 1)
9897
- return snapshot.blockIndexMap.has(key);
9898
- if (path2.length > 2)
9899
- return !1;
9900
- const parentBlockIndex = path2.at(0), parentBlock = parentBlockIndex !== void 0 ? snapshot.context.value.at(parentBlockIndex) : void 0;
9901
- return !parentBlock || !isTextBlock(snapshot.context, parentBlock) ? !1 : parentBlock.children.some((child) => child._key === key);
9902
- }
9903
9255
  function updateSelectionPlugin({
9904
9256
  editor,
9905
9257
  editorActor
@@ -9963,21 +9315,100 @@ const plugins = (editor, options) => {
9963
9315
  const e = editor, {
9964
9316
  editorActor,
9965
9317
  relayActor
9966
- } = options, uniqueKeysPlugin = createUniqueKeysPlugin(editorActor), schemaPlugin = createSchemaPlugin({
9967
- editorActor
9968
- }), patchesPlugin = createPatchesPlugin({
9318
+ } = options, patchesPlugin = createPatchesPlugin({
9969
9319
  editorActor,
9970
9320
  relayActor,
9971
9321
  subscriptions: options.subscriptions
9972
9322
  }), historyPlugin = createHistoryPlugin({
9973
9323
  editorActor,
9974
9324
  subscriptions: options.subscriptions
9975
- }), normalizationPlugin = createNormalizationPlugin(editorActor);
9976
- return createBehaviorApiPlugin(editorActor)(schemaPlugin(uniqueKeysPlugin(normalizationPlugin(historyPlugin(patchesPlugin(updateValuePlugin(editorActor.getSnapshot().context, updateSelectionPlugin({
9325
+ });
9326
+ return createBehaviorApiPlugin(editorActor)(historyPlugin(patchesPlugin(updateValuePlugin(editorActor.getSnapshot().context, updateSelectionPlugin({
9977
9327
  editorActor,
9978
9328
  editor: e
9979
- }))))))));
9980
- }, PathRef = {
9329
+ })))));
9330
+ };
9331
+ function pathLevels(path2) {
9332
+ const list = [];
9333
+ for (let i = 0; i <= path2.length; i++)
9334
+ list.push(path2.slice(0, i));
9335
+ return list;
9336
+ }
9337
+ function getChildFieldName(context, path2) {
9338
+ let nodeChildren = getNodeChildren({
9339
+ schema: context.schema,
9340
+ editableTypes: context.editableTypes
9341
+ }, {
9342
+ value: context.value
9343
+ }, void 0, "");
9344
+ for (let i = 0; i < path2.length; i++) {
9345
+ if (!nodeChildren)
9346
+ return;
9347
+ const index = path2.at(i);
9348
+ if (index === void 0)
9349
+ return;
9350
+ const node = nodeChildren.children.at(index);
9351
+ if (!node)
9352
+ return;
9353
+ if (i === path2.length - 1)
9354
+ return getNodeChildren({
9355
+ schema: context.schema,
9356
+ editableTypes: context.editableTypes
9357
+ }, node, nodeChildren.scope, nodeChildren.scopePath)?.fieldName;
9358
+ nodeChildren = getNodeChildren({
9359
+ schema: context.schema,
9360
+ editableTypes: context.editableTypes
9361
+ }, node, nodeChildren.scope, nodeChildren.scopePath);
9362
+ }
9363
+ }
9364
+ function getDirtyIndexedPaths(context, op) {
9365
+ switch (op.type) {
9366
+ case "insert_text":
9367
+ case "remove_text":
9368
+ case "set_node": {
9369
+ const {
9370
+ path: path2
9371
+ } = op, levels = pathLevels(path2);
9372
+ if (op.type === "set_node") {
9373
+ const childFieldName = getChildFieldName(context, path2);
9374
+ if (childFieldName) {
9375
+ const newChildren = op.newProperties[childFieldName];
9376
+ if (Array.isArray(newChildren))
9377
+ for (let i = 0; i < newChildren.length; i++) {
9378
+ const child = newChildren[i];
9379
+ if (typeof child != "object" || child === null)
9380
+ continue;
9381
+ const childPath = [...path2, i];
9382
+ levels.push(childPath);
9383
+ for (const entry of getNodeDescendants(context, child))
9384
+ levels.push(childPath.concat(entry.path));
9385
+ }
9386
+ }
9387
+ }
9388
+ return levels;
9389
+ }
9390
+ case "insert_node": {
9391
+ const {
9392
+ node,
9393
+ path: path2
9394
+ } = op, levels = pathLevels(path2);
9395
+ if (isSpan(context, node))
9396
+ return levels;
9397
+ for (const entry of getNodeDescendants(context, node))
9398
+ levels.push(path2.concat(entry.path));
9399
+ return levels;
9400
+ }
9401
+ case "remove_node": {
9402
+ const {
9403
+ path: path2
9404
+ } = op;
9405
+ return [...pathLevels(path2).slice(0, -1)];
9406
+ }
9407
+ default:
9408
+ return [];
9409
+ }
9410
+ }
9411
+ const PathRef = {
9981
9412
  transform(ref, op) {
9982
9413
  const {
9983
9414
  current
@@ -10062,7 +9493,7 @@ function replaceChildren(xs, index, removeCount, ...newValues) {
10062
9493
  }
10063
9494
  const removeChildren = replaceChildren, modifyDescendant = (root, path2, schema, f) => {
10064
9495
  if (path2.length === 0)
10065
- throw new Error("Cannot modify the editor");
9496
+ return;
10066
9497
  const editableTypes = isEditor(root) ? root.editableTypes : /* @__PURE__ */ new Set(), context = {
10067
9498
  schema,
10068
9499
  editableTypes
@@ -10070,28 +9501,42 @@ const removeChildren = replaceChildren, modifyDescendant = (root, path2, schema,
10070
9501
  schema
10071
9502
  }, root) ? root : void 0;
10072
9503
  if (!typedRoot)
10073
- throw new Error("Cannot modify descendant: root has no children");
9504
+ return;
10074
9505
  const nodeEntry = getNode({
10075
9506
  ...context,
10076
9507
  value: typedRoot.children
10077
9508
  }, path2);
10078
9509
  if (!nodeEntry)
10079
- throw new Error(`Cannot find a descendant at path [${path2}]`);
9510
+ return;
10080
9511
  const node = nodeEntry.node, slicedPath = path2.slice();
10081
9512
  let modifiedNode = f(node);
9513
+ const fieldNames = [];
9514
+ {
9515
+ let currentNode = {
9516
+ value: typedRoot.children
9517
+ }, scope, scopePath = "";
9518
+ for (let i = 0; i < path2.length; i++) {
9519
+ const result = getNodeChildren(context, currentNode, scope, scopePath);
9520
+ if (!result)
9521
+ return;
9522
+ fieldNames.push(result.fieldName);
9523
+ const child = result.children.at(path2.at(i));
9524
+ if (!child)
9525
+ return;
9526
+ currentNode = child, scope = result.scope, scopePath = result.scopePath;
9527
+ }
9528
+ }
10082
9529
  for (; slicedPath.length > 1; ) {
10083
- const index2 = slicedPath.pop(), ancestorEntry = getNode({
9530
+ const index2 = slicedPath.pop(), level = slicedPath.length, fieldName = fieldNames.at(level), ancestorEntry = getNode({
10084
9531
  ...context,
10085
9532
  value: typedRoot.children
10086
9533
  }, slicedPath);
10087
9534
  if (!ancestorEntry)
10088
- throw new Error(`Cannot find ancestor at path [${slicedPath}]`);
10089
- const ancestorNode = ancestorEntry.node;
9535
+ return;
9536
+ const ancestorNode = ancestorEntry.node, ancestorRecord = ancestorNode, currentChildren = Array.isArray(ancestorRecord[fieldName]) ? ancestorRecord[fieldName] : [];
10090
9537
  modifiedNode = {
10091
9538
  ...ancestorNode,
10092
- children: replaceChildren(isTextBlock({
10093
- schema
10094
- }, ancestorNode) ? ancestorNode.children : [], index2, 1, modifiedNode)
9539
+ [fieldName]: replaceChildren(currentChildren, index2, 1, modifiedNode)
10095
9540
  };
10096
9541
  }
10097
9542
  const index = slicedPath.pop(), newRootChildren = replaceChildren(isEditor(root) || isTextBlock({
@@ -10101,35 +9546,32 @@ const removeChildren = replaceChildren, modifyDescendant = (root, path2, schema,
10101
9546
  }, modifyChildren = (root, path2, schema, f) => {
10102
9547
  path2.length === 0 ? root.children = f(isEditor(root) || isTextBlock({
10103
9548
  schema
10104
- }, root) ? root.children : []) : modifyDescendant(root, path2, schema, (node) => {
10105
- if (isSpan({
9549
+ }, root) ? root.children : []) : modifyDescendant(root, path2, schema, (node) => ({
9550
+ ...node,
9551
+ children: f(isTextBlock({
10106
9552
  schema
10107
- }, node) || isObjectNode({
10108
- schema
10109
- }, node))
10110
- throw new Error(`Cannot get the element at path [${path2}] because it refers to a leaf node: ${safeStringify(node)}`);
10111
- return {
10112
- ...node,
10113
- children: f(isTextBlock({
10114
- schema
10115
- }, node) ? node.children : [])
10116
- };
10117
- });
10118
- }, modifyLeaf = (root, path2, schema, f) => modifyDescendant(root, path2, schema, (node) => {
10119
- if (!isSpan({
10120
- schema
10121
- }, node))
10122
- throw new Error(`Cannot get the leaf node at path [${path2}] because it refers to a non-leaf node: ${safeStringify(node)}`);
10123
- return f(node);
10124
- });
9553
+ }, node) ? node.children : [])
9554
+ }));
9555
+ }, modifyLeaf = (root, path2, schema, f) => modifyDescendant(root, path2, schema, (node) => isSpan({
9556
+ schema
9557
+ }, node) ? f(node) : node);
10125
9558
  function applyOperation(editor, op) {
10126
9559
  let transformSelection = !1;
10127
9560
  switch (op.type) {
10128
9561
  case "insert_node": {
10129
9562
  const {
10130
- path: path2,
9563
+ path: path2
9564
+ } = op;
9565
+ let {
10131
9566
  node
10132
9567
  } = op;
9568
+ if (!editor.isProcessingRemoteChanges && !editor.isUndoing && !editor.isRedoing && node._key !== void 0) {
9569
+ const insertParentPath = parentPath(path2);
9570
+ (insertParentPath.length === 0 ? editor.children : getChildren(editor, insertParentPath).map((entry) => entry.node)).some((sibling) => sibling._key === node._key) && (node = {
9571
+ ...node,
9572
+ _key: editor.keyGenerator()
9573
+ }, op.node = node);
9574
+ }
10133
9575
  modifyChildren(editor, parentPath(path2), editor.schema, (children) => {
10134
9576
  const index = path2[path2.length - 1];
10135
9577
  if (index > children.length)
@@ -10226,15 +9668,13 @@ function applyOperation(editor, op) {
10226
9668
  ...node
10227
9669
  };
10228
9670
  for (const key in newProperties) {
10229
- if (key === "children")
10230
- throw new Error(`Cannot set the "${key}" property of nodes!`);
10231
9671
  const value = newProperties[key];
10232
9672
  value == null ? delete newNode[key] : newNode[key] = value;
10233
9673
  }
10234
9674
  for (const key in properties)
10235
9675
  newProperties.hasOwnProperty(key) || delete newNode[key];
10236
9676
  return newNode;
10237
- });
9677
+ }), transformSelection = !0;
10238
9678
  break;
10239
9679
  }
10240
9680
  case "set_selection": {
@@ -10278,15 +9718,6 @@ function applyOperation(editor, op) {
10278
9718
  rangeEquals(selection, editor.selection) || (editor.selection = selection);
10279
9719
  }
10280
9720
  }
10281
- const isBatchingDirtyPaths = (editor) => editor.batchingDirtyPaths, batchDirtyPaths = (editor, fn, update) => {
10282
- const value = editor.batchingDirtyPaths;
10283
- editor.batchingDirtyPaths = !0;
10284
- try {
10285
- fn(), update();
10286
- } finally {
10287
- editor.batchingDirtyPaths = value;
10288
- }
10289
- };
10290
9721
  function updateDirtyPaths(editor, newDirtyPaths, transform) {
10291
9722
  const oldDirtyPaths = editor.dirtyPaths, oldDirtyPathKeys = editor.dirtyPathKeys;
10292
9723
  let dirtyPaths, dirtyPathKeys;
@@ -10315,607 +9746,640 @@ const apply = (editor, op) => {
10315
9746
  PointRef.transform(ref, op);
10316
9747
  for (const ref of editor.rangeRefs)
10317
9748
  transformRangeRef(ref, op);
10318
- if (!isBatchingDirtyPaths(editor)) {
10319
- const transform = operationCanTransformPath(op) ? (p) => transformPath(p, op) : void 0;
10320
- updateDirtyPaths(editor, editor.getDirtyPaths(op), transform);
10321
- }
10322
- applyOperation(editor, op), editor.operations.push(op), normalize(editor, {
9749
+ const needsTransform = operationCanTransformPath(op), isAppendAtEnd = needsTransform && op.type === "insert_node" && op.path.length === 1 && op.path[0] >= editor.children.length, transform = needsTransform && !isAppendAtEnd ? (p) => transformPath(p, op) : void 0;
9750
+ if (updateDirtyPaths(editor, getDirtyIndexedPaths(editor, op), transform), applyOperation(editor, op), editor.operations.push(op), normalize(editor, {
10323
9751
  operation: op
10324
- }), op.type === "set_selection" && (editor.marks = null), editor.flushing || (editor.flushing = !0, Promise.resolve().then(() => {
9752
+ }), op.type === "set_selection")
9753
+ if (editor.marks = null, op.properties && op.newProperties && op.properties.anchor && op.properties.focus && op.newProperties.anchor && op.newProperties.focus) {
9754
+ const previousSelectionIsCollapsed = isCollapsedRange({
9755
+ anchor: op.properties.anchor,
9756
+ focus: op.properties.focus
9757
+ }), newSelectionIsCollapsed = isCollapsedRange({
9758
+ anchor: op.newProperties.anchor,
9759
+ focus: op.newProperties.focus
9760
+ });
9761
+ if (previousSelectionIsCollapsed && newSelectionIsCollapsed) {
9762
+ const focusSpan = getSpanNode(editor, op.properties.focus.path)?.node, newFocusSpan = getSpanNode(editor, op.newProperties.focus.path)?.node, movedToNextSpan = focusSpan && newFocusSpan && op.newProperties.focus.path[0] === op.properties.focus.path[0] && op.newProperties.focus.path[1] === op.properties.focus.path[1] + 1 && focusSpan.text.length === op.properties.focus.offset && op.newProperties.focus.offset === 0, movedToPreviousSpan = focusSpan && newFocusSpan && op.newProperties.focus.path[0] === op.properties.focus.path[0] && op.newProperties.focus.path[1] === op.properties.focus.path[1] - 1 && op.properties.focus.offset === 0 && newFocusSpan.text.length === op.newProperties.focus.offset;
9763
+ !movedToNextSpan && !movedToPreviousSpan && (editor.decoratorState = {});
9764
+ }
9765
+ } else
9766
+ editor.decoratorState = {};
9767
+ editor.flushing || (editor.flushing = !0, Promise.resolve().then(() => {
10325
9768
  editor.flushing = !1, editor.onChange({
10326
9769
  operation: op
10327
9770
  }), editor.operations = [];
10328
9771
  }));
10329
9772
  };
10330
- function pathLevels(path2, options = {}) {
10331
- const {
10332
- reverse = !1
10333
- } = options, list = [];
10334
- for (let i = 0; i <= path2.length; i++)
10335
- list.push(path2.slice(0, i));
10336
- return reverse && list.reverse(), list;
9773
+ function isEnd(editor, point2, at) {
9774
+ const editorEnd = end(editor, at);
9775
+ return pointEquals(point2, editorEnd);
10337
9776
  }
10338
- function pathAncestors(path2, options = {}) {
10339
- const {
10340
- reverse = !1
10341
- } = options;
10342
- let paths = pathLevels(path2, options);
10343
- return reverse ? paths = paths.slice(1) : paths = paths.slice(0, -1), paths;
9777
+ function isStart(editor, point2, at) {
9778
+ if (point2.offset !== 0)
9779
+ return !1;
9780
+ const editorStart = start(editor, at);
9781
+ return pointEquals(point2, editorStart);
10344
9782
  }
10345
- const getDirtyPaths = (editor, op) => {
10346
- switch (op.type) {
10347
- case "insert_text":
10348
- case "remove_text":
10349
- case "set_node": {
10350
- const {
10351
- path: path2
10352
- } = op;
10353
- return pathLevels(path2);
10354
- }
10355
- case "insert_node": {
10356
- const {
10357
- node,
10358
- path: path2
10359
- } = op, levels = pathLevels(path2);
10360
- if (isSpan(editor, node))
10361
- return levels;
10362
- for (const entry of getNodeDescendants(editor, node))
10363
- levels.push(path2.concat(entry.path));
10364
- return levels;
10365
- }
10366
- case "remove_node": {
10367
- const {
10368
- path: path2
10369
- } = op;
10370
- return [...pathAncestors(path2)];
9783
+ function isEdge(editor, point2, at) {
9784
+ return isStart(editor, point2, at) || isEnd(editor, point2, at);
9785
+ }
9786
+ function rangeRefAffinities(range2, affinity) {
9787
+ if (affinity === "inward") {
9788
+ const isCollapsed = isCollapsedRange(range2);
9789
+ if (isForwardRange(range2)) {
9790
+ const anchorAffinity = "forward";
9791
+ return [anchorAffinity, isCollapsed ? anchorAffinity : "backward"];
9792
+ } else {
9793
+ const anchorAffinity = "backward";
9794
+ return [anchorAffinity, isCollapsed ? anchorAffinity : "forward"];
10371
9795
  }
10372
- default:
10373
- return [];
9796
+ } else return affinity === "outward" ? isForwardRange(range2) ? ["backward", "forward"] : ["forward", "backward"] : [affinity, affinity];
9797
+ }
9798
+ function applySplitNode(editor, path2, position) {
9799
+ const nodeEntry = getNode(editor, path2);
9800
+ if (!nodeEntry)
9801
+ return;
9802
+ const node = nodeEntry.node;
9803
+ for (const ref of editor.pathRefs) {
9804
+ const current = ref.current;
9805
+ current && (ref.current = transformPathForSplit(current, path2, position, ref.affinity ?? "forward"));
10374
9806
  }
10375
- };
10376
- function pointRef(editor, point2, options = {}) {
10377
- const {
10378
- affinity = "forward"
10379
- } = options, ref = {
10380
- current: point2,
10381
- affinity,
10382
- unref() {
10383
- const {
10384
- current
10385
- } = ref;
10386
- return editor.pointRefs.delete(ref), ref.current = null, current;
9807
+ for (const ref of editor.pointRefs) {
9808
+ const current = ref.current;
9809
+ current && (ref.current = transformPointForSplit(current, path2, position, ref.affinity ?? "forward"));
9810
+ }
9811
+ for (const ref of editor.rangeRefs) {
9812
+ const current = ref.current;
9813
+ if (current) {
9814
+ const [anchorAffinity, focusAffinity] = rangeRefAffinities(current, ref.affinity), anchor = transformPointForSplit(current.anchor, path2, position, anchorAffinity ?? "forward"), focus = transformPointForSplit(current.focus, path2, position, focusAffinity ?? "forward");
9815
+ anchor && focus ? ref.current = {
9816
+ anchor,
9817
+ focus
9818
+ } : (ref.current = null, ref.unref());
10387
9819
  }
10388
- };
10389
- return editor.pointRefs.add(ref), ref;
10390
- }
10391
- const getDefaultInsertLocation = (editor) => editor.selection ? editor.selection : editor.children.length > 0 ? end(editor, []) : [0];
10392
- function shouldMergeNodesRemovePrevNode(editor, prev, _current) {
10393
- let isEmptyElement = !1;
10394
- if (isTextBlock({
10395
- schema: editor.schema
10396
- }, prev.node)) {
10397
- const prevChildren = prev.node.children;
10398
- isEmptyElement = prevChildren.length === 0 || prevChildren.length === 1 && isSpan({
10399
- schema: editor.schema
10400
- }, prevChildren[0]) && prevChildren[0].text === "";
10401
9820
  }
10402
- return isEmptyElement || isSpan({
10403
- schema: editor.schema
10404
- }, prev.node) && prev.node.text === "" && prev.path[prev.path.length - 1] !== 0;
10405
- }
10406
- function isCommonPath(path2, another) {
10407
- return path2.length <= another.length && comparePaths(path2, another) === 0;
10408
- }
10409
- function insertText(editor, text, options = {}) {
10410
- withoutNormalizing(editor, () => {
10411
- const {
10412
- includeObjectNodes = !1
10413
- } = options;
10414
- let {
10415
- at = getDefaultInsertLocation(editor)
10416
- } = options;
10417
- if (isPath(at) && (at = range(editor, at)), isRange(at))
10418
- if (isCollapsedRange(at))
10419
- at = at.anchor;
10420
- else {
10421
- const end2 = rangeEnd(at);
10422
- if (!includeObjectNodes) {
10423
- const endPath = path(editor, end2), endEntry = getNode(editor, endPath);
10424
- if (endEntry && isObjectNode({
10425
- schema: editor.schema
10426
- }, endEntry.node) ? endEntry : getAncestorObjectNode(editor, end2.path))
10427
- return;
10428
- }
10429
- const start2 = rangeStart(at), startRef = pointRef(editor, start2), endRef = pointRef(editor, end2);
10430
- deleteText(editor, {
10431
- at,
10432
- includeObjectNodes
10433
- });
10434
- const startPoint = startRef.unref(), endPoint = endRef.unref();
10435
- at = startPoint || endPoint, editor.setSelection({
10436
- anchor: at,
10437
- focus: at
9821
+ if (editor.selection) {
9822
+ const anchor = transformPointForSplit(editor.selection.anchor, path2, position, "forward"), focus = transformPointForSplit(editor.selection.focus, path2, position, "forward");
9823
+ anchor && focus && (editor.selection = {
9824
+ anchor,
9825
+ focus
9826
+ });
9827
+ }
9828
+ const pathRefs = new Set(editor.pathRefs), pointRefs = new Set(editor.pointRefs), rangeRefs = new Set(editor.rangeRefs);
9829
+ editor.pathRefs.clear(), editor.pointRefs.clear(), editor.rangeRefs.clear();
9830
+ const savedSelection = editor.selection;
9831
+ try {
9832
+ withoutNormalizing(editor, () => {
9833
+ if (isSpan({
9834
+ schema: editor.schema
9835
+ }, node)) {
9836
+ const {
9837
+ text: _text,
9838
+ ...properties
9839
+ } = node, afterText = node.text.slice(position), newNode = {
9840
+ ...properties,
9841
+ text: afterText
9842
+ };
9843
+ editor.apply({
9844
+ type: "remove_text",
9845
+ path: path2,
9846
+ offset: position,
9847
+ text: afterText
9848
+ }), editor.apply({
9849
+ type: "insert_node",
9850
+ path: nextPath(path2),
9851
+ node: newNode
10438
9852
  });
10439
- }
10440
- if (!includeObjectNodes) {
10441
- const atPath = path(editor, at), atEntry = getNode(editor, atPath);
10442
- if (atEntry && isObjectNode({
9853
+ } else if (isTextBlock({
10443
9854
  schema: editor.schema
10444
- }, atEntry.node) ? atEntry : getAncestorObjectNode(editor, at.path))
10445
- return;
10446
- }
10447
- const {
10448
- path: path$1,
10449
- offset
10450
- } = at;
10451
- text.length > 0 && editor.apply({
10452
- type: "insert_text",
10453
- path: path$1,
10454
- offset,
10455
- text
10456
- });
10457
- });
10458
- }
10459
- const matchPath = (editor, path2) => {
10460
- const matchedEntry = getNode(editor, path2);
10461
- if (!matchedEntry)
10462
- return () => !1;
10463
- const matchedNode = matchedEntry.node;
10464
- return (n) => n === matchedNode;
10465
- };
10466
- function removeNodes(editor, options = {}) {
10467
- withoutNormalizing(editor, () => {
10468
- const {
10469
- hanging = !1,
10470
- mode = "lowest"
10471
- } = options;
10472
- let {
10473
- at = editor.selection,
10474
- match: match2
10475
- } = options;
10476
- if (!at)
10477
- return;
10478
- match2 == null && (match2 = isPath(at) ? matchPath(editor, at) : (n) => isTextBlockNode({
10479
- schema: editor.schema
10480
- }, n)), !hanging && isRange(at) && (at = unhangRange(editor, at));
10481
- let from, to;
10482
- if (isRange(at)) {
10483
- const [start2, end2] = rangeEdges(at);
10484
- from = start2.path, to = end2.path;
10485
- } else isPath(at) ? (from = path(editor, at, {
10486
- edge: "start"
10487
- }), to = path(editor, at, {
10488
- edge: "end"
10489
- })) : (from = at.path, to = at.path);
10490
- const depths = [];
10491
- let hit;
10492
- for (const {
10493
- node,
10494
- path: nodePath
10495
- } of getNodes(editor, {
10496
- from,
10497
- to,
10498
- match: (n, p) => match2(n, p)
10499
- })) {
10500
- const isLower = hit && comparePaths(nodePath, hit[1]) === 0;
10501
- if (mode === "highest" && isLower)
10502
- continue;
10503
- if (mode === "lowest" && isLower) {
10504
- hit = [node, nodePath];
10505
- continue;
10506
- }
10507
- const emit2 = mode === "lowest" ? hit : [node, nodePath];
10508
- emit2 && depths.push(emit2), hit = [node, nodePath];
10509
- }
10510
- mode === "lowest" && hit && depths.push(hit);
10511
- const pathRefs = Array.from(depths, ([, p]) => pathRef(editor, p));
10512
- for (const ref of pathRefs) {
10513
- const path2 = ref.unref();
10514
- if (path2) {
10515
- const removedEntry = getNode(editor, path2);
10516
- if (removedEntry) {
10517
- const removedNode = removedEntry.node;
9855
+ }, node)) {
9856
+ const {
9857
+ children: _children,
9858
+ ...properties
9859
+ } = node, children = node.children, afterChildren = children.slice(position), newNode = {
9860
+ ...properties,
9861
+ children: afterChildren
9862
+ };
9863
+ for (let i = children.length - 1; i >= position; i--)
10518
9864
  editor.apply({
10519
9865
  type: "remove_node",
10520
- path: path2,
10521
- node: removedNode
9866
+ path: [...path2, i],
9867
+ node: children[i]
10522
9868
  });
10523
- }
9869
+ editor.apply({
9870
+ type: "insert_node",
9871
+ path: nextPath(path2),
9872
+ node: newNode
9873
+ });
10524
9874
  }
10525
- }
9875
+ });
9876
+ } finally {
9877
+ editor.selection = savedSelection;
9878
+ for (const ref of pathRefs)
9879
+ editor.pathRefs.add(ref);
9880
+ for (const ref of pointRefs)
9881
+ editor.pointRefs.add(ref);
9882
+ for (const ref of rangeRefs)
9883
+ editor.rangeRefs.add(ref);
9884
+ }
9885
+ }
9886
+ function transformPathForSplit(path2, splitPath, position, affinity = "forward") {
9887
+ const p = [...path2];
9888
+ return pathEquals(splitPath, p) ? affinity === "forward" && (p[p.length - 1] = p[p.length - 1] + 1) : pathEndsBefore(splitPath, p) ? p[splitPath.length - 1] = p[splitPath.length - 1] + 1 : isAncestorPath(splitPath, p) && path2[splitPath.length] >= position && (p[splitPath.length - 1] = p[splitPath.length - 1] + 1, p[splitPath.length] = p[splitPath.length] - position), p;
9889
+ }
9890
+ function transformPointForSplit(point2, splitPath, position, affinity = "forward") {
9891
+ let {
9892
+ path: path2,
9893
+ offset
9894
+ } = point2;
9895
+ return pathEquals(splitPath, path2) ? (position < offset || position === offset && affinity === "forward") && (offset -= position, path2 = transformPathForSplit(path2, splitPath, position, "forward")) : path2 = transformPathForSplit(path2, splitPath, position, affinity), {
9896
+ path: path2,
9897
+ offset
9898
+ };
9899
+ }
9900
+ function applyInsertNodeAtPath(editor, node, path2) {
9901
+ editor.apply({
9902
+ type: "insert_node",
9903
+ path: path2,
9904
+ node
10526
9905
  });
9906
+ const point2 = end(editor, path2);
9907
+ point2 && applySelect(editor, point2);
10527
9908
  }
10528
- function deleteText(editor, options = {}) {
9909
+ function applyInsertNodeAtPoint(editor, node, at) {
10529
9910
  withoutNormalizing(editor, () => {
10530
- const {
10531
- reverse = !1,
10532
- unit = "character",
10533
- distance = 1,
10534
- includeObjectNodes = !1
10535
- } = options;
10536
- let {
10537
- at = editor.selection,
10538
- hanging = !1
10539
- } = options;
10540
- if (!at)
10541
- return;
10542
- let isCollapsed = !1;
10543
- if (isRange(at) && isCollapsedRange(at) && (isCollapsed = !0, at = at.anchor), isPoint(at)) {
10544
- const furthestObjectNode = getHighestObjectNode(editor, at.path);
10545
- if (!includeObjectNodes && furthestObjectNode)
10546
- at = furthestObjectNode.path;
10547
- else {
10548
- const opts = {
10549
- unit,
10550
- distance
10551
- }, target = reverse ? before(editor, at, opts) || start(editor, []) : after(editor, at, opts) || end(editor, []);
10552
- at = {
10553
- anchor: at,
10554
- focus: target
10555
- }, hanging = !0;
10556
- }
10557
- }
10558
- if (isPath(at)) {
10559
- removeNodes(editor, {
10560
- at,
10561
- includeObjectNodes
10562
- });
10563
- return;
10564
- }
10565
- if (isCollapsedRange(at))
9911
+ const match2 = isSpan({
9912
+ schema: editor.schema
9913
+ }, node) ? (n) => isSpan({
9914
+ schema: editor.schema
9915
+ }, n) : (n) => isSpan({
9916
+ schema: editor.schema
9917
+ }, n) || isObjectNode({
9918
+ schema: editor.schema
9919
+ }, n), nodeEntry = getNode(editor, at.path), entry = nodeEntry && match2(nodeEntry.node) ? nodeEntry : void 0;
9920
+ if (!entry)
10566
9921
  return;
10567
- if (!hanging) {
10568
- const [, end2] = rangeEdges(at), endOfDoc = end(editor, []);
10569
- pointEquals(end2, endOfDoc) || (at = unhangRange(editor, at));
10570
- }
10571
- let [start$1, end$1] = rangeEdges(at);
10572
- const startBlock = getAncestorTextBlock(editor, start$1.path), endBlock = getAncestorTextBlock(editor, end$1.path), isAcrossBlocks = startBlock && endBlock && !pathEquals(startBlock.path, endBlock.path), isSingleText = pathEquals(start$1.path, end$1.path), startNonEditable = includeObjectNodes ? null : getHighestObjectNode(editor, start$1.path), endNonEditable = includeObjectNodes ? null : getHighestObjectNode(editor, end$1.path);
10573
- if (startNonEditable) {
10574
- const beforePoint = before(editor, start$1);
10575
- beforePoint && startBlock && isAncestorPath(startBlock.path, beforePoint.path) && (start$1 = beforePoint);
10576
- }
10577
- if (endNonEditable) {
10578
- const afterPoint = after(editor, end$1);
10579
- afterPoint && endBlock && isAncestorPath(endBlock.path, afterPoint.path) && (end$1 = afterPoint);
10580
- }
10581
- const matches = [];
10582
- let lastPath;
10583
- for (const entry of getNodes(editor, {
10584
- from: start$1.path,
10585
- to: end$1.path
10586
- })) {
10587
- const {
10588
- node,
10589
- path: entryPath
10590
- } = entry;
10591
- lastPath && comparePaths(entryPath, lastPath) === 0 || (!includeObjectNodes && isObjectNode({
10592
- schema: editor.schema
10593
- }, node) || !isCommonPath(entryPath, start$1.path) && !isCommonPath(entryPath, end$1.path)) && (matches.push(entry), lastPath = entryPath);
9922
+ const matchPath2 = entry.path, ref = pathRef(editor, matchPath2), isAtEnd = isEnd(editor, at, matchPath2);
9923
+ isEdge(editor, at, matchPath2) || applySplitNode(editor, at.path, at.offset);
9924
+ const path2 = ref.unref(), insertPath = isAtEnd ? nextPath(path2) : path2;
9925
+ editor.apply({
9926
+ type: "insert_node",
9927
+ path: insertPath,
9928
+ node
9929
+ });
9930
+ const point2 = end(editor, insertPath);
9931
+ point2 && applySelect(editor, point2);
9932
+ });
9933
+ }
9934
+ function previousPath(path2) {
9935
+ if (path2.length === 0)
9936
+ throw new Error(`Cannot get the previous path of a root path [${path2}], because it has no previous index.`);
9937
+ const last = path2[path2.length - 1];
9938
+ if (last <= 0)
9939
+ throw new Error(`Cannot get the previous path of a first child path [${path2}] because it would result in a negative index.`);
9940
+ return path2.slice(0, -1).concat(last - 1);
9941
+ }
9942
+ function applyMergeNode(editor, path2, position) {
9943
+ const nodeEntry = getNode(editor, path2);
9944
+ if (!nodeEntry)
9945
+ return;
9946
+ const node = nodeEntry.node, prevPath = previousPath(path2);
9947
+ for (const ref of editor.pathRefs) {
9948
+ const current = ref.current;
9949
+ current && (ref.current = transformPathForMerge(current, path2, position));
9950
+ }
9951
+ for (const ref of editor.pointRefs) {
9952
+ const current = ref.current;
9953
+ current && (ref.current = transformPointForMerge(current, path2, position));
9954
+ }
9955
+ for (const ref of editor.rangeRefs) {
9956
+ const current = ref.current;
9957
+ if (current) {
9958
+ const anchor = transformPointForMerge(current.anchor, path2, position), focus = transformPointForMerge(current.focus, path2, position);
9959
+ anchor && focus ? ref.current = {
9960
+ anchor,
9961
+ focus
9962
+ } : (ref.current = null, ref.unref());
10594
9963
  }
10595
- const pathRefs = Array.from(matches, (entry) => pathRef(editor, entry.path)), startRef = pointRef(editor, start$1), endRef = pointRef(editor, end$1);
10596
- let removedText = "";
10597
- if (!isSingleText && !startNonEditable) {
10598
- const point22 = startRef.current, nodeEntry = getSpanNode(editor, point22.path);
10599
- if (nodeEntry) {
10600
- const node = nodeEntry.node, {
10601
- path: path2
10602
- } = point22, {
10603
- offset
10604
- } = start$1, text = node.text.slice(offset);
10605
- text.length > 0 && (editor.apply({
10606
- type: "remove_text",
10607
- path: path2,
10608
- offset,
10609
- text
10610
- }), removedText = text);
10611
- }
9964
+ }
9965
+ if (editor.selection) {
9966
+ const anchor = transformPointForMerge(editor.selection.anchor, path2, position), focus = transformPointForMerge(editor.selection.focus, path2, position);
9967
+ anchor && focus && (editor.selection = {
9968
+ anchor,
9969
+ focus
9970
+ });
9971
+ }
9972
+ const pathRefs = new Set(editor.pathRefs), pointRefs = new Set(editor.pointRefs), rangeRefs = new Set(editor.rangeRefs);
9973
+ editor.pathRefs.clear(), editor.pointRefs.clear(), editor.rangeRefs.clear();
9974
+ const savedSelection = editor.selection, editorAny = editor, savedPendingDiffs = editorAny.pendingDiffs, savedPendingSelection = editorAny.pendingSelection, savedPendingAction = editorAny.pendingAction;
9975
+ if (Array.isArray(savedPendingDiffs) && savedPendingDiffs.length > 0 && (editorAny.pendingDiffs = savedPendingDiffs.map((textDiff) => transformTextDiffForMerge(textDiff, path2, position)).filter(Boolean)), savedPendingSelection && typeof savedPendingSelection == "object" && "anchor" in savedPendingSelection && "focus" in savedPendingSelection) {
9976
+ const sel = savedPendingSelection, anchor = transformPointForMerge(sel.anchor, path2, position), focus = transformPointForMerge(sel.focus, path2, position);
9977
+ editorAny.pendingSelection = anchor && focus ? {
9978
+ anchor,
9979
+ focus
9980
+ } : null;
9981
+ }
9982
+ if (savedPendingAction && typeof savedPendingAction == "object" && "at" in savedPendingAction) {
9983
+ const action = savedPendingAction;
9984
+ if ("offset" in action.at && typeof action.at.offset == "number") {
9985
+ const at = transformPointForMerge(action.at, path2, position);
9986
+ editorAny.pendingAction = at ? {
9987
+ ...action,
9988
+ at
9989
+ } : null;
9990
+ } else if (isRange(action.at)) {
9991
+ const anchor = transformPointForMerge(action.at.anchor, path2, position), focus = transformPointForMerge(action.at.focus, path2, position);
9992
+ editorAny.pendingAction = anchor && focus ? {
9993
+ ...action,
9994
+ at: {
9995
+ anchor,
9996
+ focus
9997
+ }
9998
+ } : null;
10612
9999
  }
10613
- if (pathRefs.reverse().map((r) => r.unref()).filter((r) => r !== null).forEach((p) => {
10614
- removeNodes(editor, {
10615
- at: p,
10616
- includeObjectNodes
10617
- });
10618
- }), !endNonEditable) {
10619
- const point22 = endRef.current, endNodeEntry = getSpanNode(editor, point22.path);
10620
- if (endNodeEntry) {
10621
- const node = endNodeEntry.node, {
10622
- path: path2
10623
- } = point22, offset = isSingleText ? start$1.offset : 0, text = node.text.slice(offset, end$1.offset);
10624
- text.length > 0 && (editor.apply({
10625
- type: "remove_text",
10000
+ }
10001
+ const preTransformedPendingDiffs = editorAny.pendingDiffs, preTransformedPendingSelection = editorAny.pendingSelection, preTransformedPendingAction = editorAny.pendingAction;
10002
+ editorAny.pendingDiffs = [], editorAny.pendingSelection = null, editorAny.pendingAction = null;
10003
+ try {
10004
+ withoutNormalizing(editor, () => {
10005
+ if (isSpan({
10006
+ schema: editor.schema
10007
+ }, node))
10008
+ node.text.length > 0 && editor.apply({
10009
+ type: "insert_text",
10010
+ path: prevPath,
10011
+ offset: position,
10012
+ text: node.text
10013
+ }), editor.apply({
10014
+ type: "remove_node",
10626
10015
  path: path2,
10627
- offset,
10628
- text
10629
- }), removedText = text);
10630
- }
10631
- }
10632
- if (!isSingleText && isAcrossBlocks && endRef.current && startRef.current) {
10633
- const mergeAt = endRef.current, mergeMatch = (n) => isTextBlock({
10016
+ node
10017
+ });
10018
+ else if (isTextBlock({
10634
10019
  schema: editor.schema
10635
- }, n), current = getAncestor(editor, mergeAt.path, mergeMatch), beforePoint = before(editor, mergeAt), prev = beforePoint ? getNodes(editor, {
10636
- to: beforePoint.path,
10637
- match: mergeMatch,
10638
- reverse: !0
10639
- }).next().value : void 0;
10640
- if (current && prev) {
10641
- const {
10642
- node: mergeNode,
10643
- path: mergePath
10644
- } = current, {
10645
- node: prevNode,
10646
- path: prevPath
10647
- } = prev;
10648
- if (mergePath.length !== 0 && prevPath.length !== 0) {
10649
- const newPath = nextPath(prevPath), common = commonPath(mergePath, prevPath), isPreviousSibling = isSiblingPath(mergePath, prevPath), editorLevels = pathLevels(mergePath).filter((levelPath) => levelPath.length > 0).map((levelPath) => getNode(editor, levelPath)).filter((entry) => entry !== void 0).map((entry) => entry.node).slice(Math.max(0, common.length - 1)).slice(0, -1), hasSingleChildNest = (node) => {
10650
- if (isTextBlock({
10651
- schema: editor.schema
10652
- }, node)) {
10653
- const elementChildren = node.children;
10654
- return elementChildren.length === 1 ? hasSingleChildNest(elementChildren[0]) : !1;
10655
- } else return !isEditor(node);
10656
- }, emptyAncestor = getAncestors(editor, mergePath).reverse().find((ancestor) => editorLevels.includes(ancestor.node) && hasSingleChildNest(ancestor.node)), emptyRef = emptyAncestor && pathRef(editor, emptyAncestor.path);
10657
- let position;
10658
- if (isSpan({
10659
- schema: editor.schema
10660
- }, mergeNode) && isSpan({
10661
- schema: editor.schema
10662
- }, prevNode))
10663
- position = prevNode.text.length;
10664
- else if (isTextBlock({
10665
- schema: editor.schema
10666
- }, mergeNode) && isTextBlock({
10667
- schema: editor.schema
10668
- }, prevNode))
10669
- position = prevNode.children.length;
10670
- else
10671
- throw new Error(`Cannot merge the node at path [${mergePath}] with the previous sibling because it is not the same kind: ${safeStringify(mergeNode)} ${safeStringify(prevNode)}`);
10672
- if (!isPreviousSibling) {
10673
- const moveNodeEntry = getNode(editor, mergePath);
10674
- if (moveNodeEntry) {
10675
- const moveNode = moveNodeEntry.node;
10676
- editor.apply({
10677
- type: "remove_node",
10678
- path: mergePath,
10679
- node: moveNode
10680
- }), editor.apply({
10681
- type: "insert_node",
10682
- path: newPath,
10683
- node: moveNode
10684
- });
10685
- }
10686
- }
10687
- if (emptyRef && removeNodes(editor, {
10688
- at: emptyRef.current,
10689
- includeObjectNodes
10690
- }), shouldMergeNodesRemovePrevNode(editor, {
10691
- node: prevNode,
10692
- path: prevPath
10693
- }, {
10694
- node: mergeNode,
10695
- path: mergePath
10696
- }))
10697
- removeNodes(editor, {
10698
- at: prevPath,
10699
- includeObjectNodes
10700
- });
10701
- else {
10702
- const pteEditor = editor;
10703
- if (isTextBlock({
10704
- schema: editor.schema
10705
- }, mergeNode) && isTextBlock({
10706
- schema: editor.schema
10707
- }, prevNode) && Array.isArray(mergeNode.markDefs) && mergeNode.markDefs.length > 0) {
10708
- const targetPath = isPreviousSibling ? prevPath : previousPath(newPath), oldDefs = Array.isArray(prevNode.markDefs) && prevNode.markDefs || [], newMarkDefs = [...new Map([...oldDefs, ...mergeNode.markDefs].map((def) => [def._key, def])).values()];
10709
- applySetNode(pteEditor, {
10710
- markDefs: newMarkDefs
10711
- }, targetPath);
10712
- }
10713
- applyMergeNode(pteEditor, newPath, position);
10714
- }
10715
- emptyRef && emptyRef.unref();
10716
- }
10020
+ }, node)) {
10021
+ for (let i = 0; i < node.children.length; i++)
10022
+ editor.apply({
10023
+ type: "insert_node",
10024
+ path: [...prevPath, position + i],
10025
+ node: node.children[i]
10026
+ });
10027
+ editor.apply({
10028
+ type: "remove_node",
10029
+ path: path2,
10030
+ node
10031
+ });
10717
10032
  }
10718
- }
10719
- isCollapsed && reverse && unit === "character" && removedText.length > 1 && removedText.match(/[\u0980-\u09FF\u0E00-\u0E7F\u1000-\u109F\u0900-\u097F\u1780-\u17FF\u0D00-\u0D7F\u0B00-\u0B7F\u0A00-\u0A7F\u0B80-\u0BFF\u0C00-\u0C7F]+/) && insertText(editor, removedText.slice(0, removedText.length - distance));
10720
- const startUnref = startRef.unref(), endUnref = endRef.unref(), point2 = reverse ? startUnref || endUnref : endUnref || startUnref;
10721
- options.at == null && point2 && editor.select(point2);
10722
- });
10033
+ });
10034
+ } finally {
10035
+ editor.selection = savedSelection;
10036
+ for (const ref of pathRefs)
10037
+ editor.pathRefs.add(ref);
10038
+ for (const ref of pointRefs)
10039
+ editor.pointRefs.add(ref);
10040
+ for (const ref of rangeRefs)
10041
+ editor.rangeRefs.add(ref);
10042
+ editorAny.pendingDiffs = preTransformedPendingDiffs, editorAny.pendingSelection = preTransformedPendingSelection, editorAny.pendingAction = preTransformedPendingAction;
10043
+ }
10044
+ }
10045
+ function transformTextDiffForMerge(textDiff, mergePath, position) {
10046
+ const {
10047
+ path: path2,
10048
+ diff: diff2,
10049
+ id
10050
+ } = textDiff;
10051
+ if (!pathEquals(mergePath, path2)) {
10052
+ const newPath = transformPathForMerge(path2, mergePath, position);
10053
+ return newPath ? {
10054
+ diff: diff2,
10055
+ id,
10056
+ path: newPath
10057
+ } : null;
10058
+ }
10059
+ return {
10060
+ diff: {
10061
+ start: diff2.start + position,
10062
+ end: diff2.end + position,
10063
+ text: diff2.text
10064
+ },
10065
+ id,
10066
+ path: transformPathForMerge(path2, mergePath, position)
10067
+ };
10068
+ }
10069
+ function transformPathForMerge(path2, mergePath, position) {
10070
+ const p = [...path2];
10071
+ return pathEquals(mergePath, p) || pathEndsBefore(mergePath, p) ? p[mergePath.length - 1] = p[mergePath.length - 1] - 1 : isAncestorPath(mergePath, p) && (p[mergePath.length - 1] = p[mergePath.length - 1] - 1, p[mergePath.length] = p[mergePath.length] + position), p;
10072
+ }
10073
+ function transformPointForMerge(point2, mergePath, position) {
10074
+ let {
10075
+ path: path2,
10076
+ offset
10077
+ } = point2;
10078
+ return pathEquals(mergePath, path2) && (offset += position), path2 = transformPathForMerge(path2, mergePath, position), {
10079
+ path: path2,
10080
+ offset
10081
+ };
10082
+ }
10083
+ function createSpanNode(context) {
10084
+ return {
10085
+ _type: context.schema.span.name,
10086
+ _key: context.keyGenerator(),
10087
+ text: "",
10088
+ marks: []
10089
+ };
10723
10090
  }
10724
- function insertNodes(editor, nodes, options = {}) {
10091
+ const matchPath = (editor, path2) => {
10092
+ const matchedEntry = getNode(editor, path2);
10093
+ if (!matchedEntry)
10094
+ return () => !1;
10095
+ const matchedNode = matchedEntry.node;
10096
+ return (n) => n === matchedNode;
10097
+ };
10098
+ function removeNodes(editor, options = {}) {
10725
10099
  withoutNormalizing(editor, () => {
10726
10100
  const {
10727
10101
  hanging = !1,
10728
- includeObjectNodes = !1,
10729
- mode = "lowest",
10730
- batchDirty = !0
10102
+ mode = "lowest"
10731
10103
  } = options;
10732
10104
  let {
10733
- at,
10734
- match: match2,
10735
- select: select2
10105
+ at = editor.selection,
10106
+ match: match2
10736
10107
  } = options;
10737
- if (nodes.length === 0)
10108
+ if (!at)
10738
10109
  return;
10739
- const node = nodes[0];
10740
- if (at || (at = getDefaultInsertLocation(editor), select2 !== !1 && (select2 = !0)), select2 == null && (select2 = !1), isRange(at))
10741
- if (hanging || (at = unhangRange(editor, at)), isCollapsedRange(at))
10742
- at = at.anchor;
10743
- else {
10744
- const [, end2] = rangeEdges(at), endPointRef = pointRef(editor, end2);
10745
- deleteText(editor, {
10746
- at
10747
- }), at = endPointRef.unref();
10110
+ match2 == null && (match2 = isPath(at) ? matchPath(editor, at) : (n) => isTextBlockNode({
10111
+ schema: editor.schema
10112
+ }, n)), !hanging && isRange(at) && (at = unhangRange(editor, at));
10113
+ let from, to;
10114
+ if (isRange(at)) {
10115
+ const [start2, end2] = rangeEdges(at);
10116
+ from = start2.path, to = end2.path;
10117
+ } else isPath(at) ? (from = path(editor, at, {
10118
+ edge: "start"
10119
+ }), to = path(editor, at, {
10120
+ edge: "end"
10121
+ })) : (from = at.path, to = at.path);
10122
+ const depths = [];
10123
+ let hit;
10124
+ for (const {
10125
+ node,
10126
+ path: nodePath
10127
+ } of getNodes(editor, {
10128
+ from,
10129
+ to,
10130
+ match: (n, p) => match2(n, p)
10131
+ })) {
10132
+ const isLower = hit && comparePaths(nodePath, hit[1]) === 0;
10133
+ if (mode === "highest" && isLower)
10134
+ continue;
10135
+ if (mode === "lowest" && isLower) {
10136
+ hit = [node, nodePath];
10137
+ continue;
10748
10138
  }
10749
- if (isPoint(at)) {
10750
- match2 == null && (isSpan({
10751
- schema: editor.schema
10752
- }, node) ? match2 = (n) => isSpan({
10753
- schema: editor.schema
10754
- }, n) : editor.isInline(node) ? match2 = (n) => isSpan({
10755
- schema: editor.schema
10756
- }, n) || editor.isInline(n) : match2 = (n) => isTextBlockNode({
10757
- schema: editor.schema
10758
- }, n));
10759
- const entry = firstNodeWithMode(editor, {
10760
- from: path(editor, at.path, {
10761
- edge: "start"
10762
- }),
10763
- to: path(editor, at.path, {
10764
- edge: "end"
10765
- }),
10766
- match: match2,
10767
- mode
10768
- });
10769
- if (entry) {
10770
- const matchPath2 = entry.path, matchPathRef = pathRef(editor, matchPath2), isAtEnd = isEnd(editor, at, matchPath2);
10771
- {
10772
- const splitAt = at, beforeRef = pointRef(editor, splitAt, {
10773
- affinity: "backward"
10139
+ const emit2 = mode === "lowest" ? hit : [node, nodePath];
10140
+ emit2 && depths.push(emit2), hit = [node, nodePath];
10141
+ }
10142
+ mode === "lowest" && hit && depths.push(hit);
10143
+ const pathRefs = Array.from(depths, ([, p]) => pathRef(editor, p));
10144
+ for (const ref of pathRefs) {
10145
+ const path2 = ref.unref();
10146
+ if (path2) {
10147
+ const removedEntry = getNode(editor, path2);
10148
+ if (removedEntry) {
10149
+ const removedNode = removedEntry.node;
10150
+ editor.apply({
10151
+ type: "remove_node",
10152
+ path: path2,
10153
+ node: removedNode
10774
10154
  });
10775
- let afterRef;
10776
- try {
10777
- const highest = firstNodeWithMode(editor, {
10778
- from: splitAt.path,
10779
- to: splitAt.path,
10780
- match: match2,
10781
- mode
10782
- });
10783
- if (highest) {
10784
- afterRef = pointRef(editor, splitAt);
10785
- const depth = splitAt.path.length, highestPath = highest.path, lowestPath = splitAt.path.slice(0, depth);
10786
- let position = splitAt.offset;
10787
- const levelEntries = pathLevels(lowestPath).filter((levelPath) => levelPath.length > 0).map((levelPath) => getNode(editor, levelPath)).filter((entry2) => entry2 !== void 0).reverse();
10788
- for (const {
10789
- path: nodePath
10790
- } of levelEntries) {
10791
- let split = !1;
10792
- if (nodePath.length < highestPath.length || nodePath.length === 0)
10793
- break;
10794
- const point2 = beforeRef.current, isEndOfNode = isEnd(editor, point2, nodePath);
10795
- isEdge(editor, point2, nodePath) || (split = !0, applySplitNode(editor, nodePath, position)), position = nodePath[nodePath.length - 1] + (split || isEndOfNode ? 1 : 0);
10796
- }
10797
- }
10798
- } finally {
10799
- beforeRef.unref(), afterRef?.unref();
10800
- }
10801
10155
  }
10802
- const path2 = matchPathRef.unref();
10803
- at = isAtEnd ? nextPath(path2) : path2;
10804
- } else
10805
- return;
10156
+ }
10806
10157
  }
10807
- const parentPath_ = parentPath(at);
10808
- let index = at[at.length - 1];
10809
- if (!includeObjectNodes) {
10810
- const parentNodePath = path(editor, parentPath_), parentNodeEntry = getNode(editor, parentNodePath);
10811
- if (parentNodeEntry && isObjectNode({
10158
+ });
10159
+ }
10160
+ const normalizeNode = (editor, entry) => {
10161
+ const [node, path2] = entry, nodeRecord = node;
10162
+ if (isEditor(node) && node.children.length === 0) {
10163
+ withoutPatching(editor, () => {
10164
+ applyInsertNodeAtPath(editor, createPlaceholderBlock(editor), [0]);
10165
+ });
10166
+ return;
10167
+ }
10168
+ if (isTextBlock({
10169
+ schema: editor.schema
10170
+ }, node)) {
10171
+ const children = getChildren(editor, path2);
10172
+ for (const {
10173
+ node: child,
10174
+ path: childPath
10175
+ } of children) {
10176
+ const childIndex = childPath[childPath.length - 1], nextNode = node.children[childIndex + 1];
10177
+ if (isSpan({
10178
+ schema: editor.schema
10179
+ }, child) && isSpan({
10812
10180
  schema: editor.schema
10813
- }, parentNodeEntry.node) ? parentNodeEntry : getAncestorObjectNode(editor, parentPath_))
10181
+ }, nextNode) && child.marks?.every((mark) => nextNode.marks?.includes(mark)) && nextNode.marks?.every((mark) => child.marks?.includes(mark))) {
10182
+ debug$1.normalization("merging spans with same marks");
10183
+ const mergePath = [...path2, childIndex + 1];
10184
+ applyMergeNode(editor, mergePath, child.text.length);
10814
10185
  return;
10186
+ }
10815
10187
  }
10816
- if (batchDirty) {
10817
- const batchedOps = [], newDirtyPaths = pathLevels(parentPath_);
10818
- batchDirtyPaths(editor, () => {
10819
- for (const node2 of nodes) {
10820
- const path2 = parentPath_.concat(index);
10821
- index++;
10822
- const op = {
10823
- type: "insert_node",
10824
- path: path2,
10825
- node: node2
10826
- };
10827
- if (editor.apply(op), at = nextPath(at), batchedOps.push(op), !isSpan(editor, node2))
10828
- for (const {
10829
- path: p
10830
- } of getNodeDescendants(editor, node2))
10831
- newDirtyPaths.push(path2.concat(p));
10188
+ }
10189
+ if (nodeRecord._type === void 0 && path2.length > 0) {
10190
+ const parent = getNode(editor, parentPath(path2));
10191
+ if (parent && isTextBlock({
10192
+ schema: editor.schema
10193
+ }, parent.node)) {
10194
+ debug$1.normalization("Setting span type on node without a type"), editor.apply({
10195
+ type: "set_node",
10196
+ path: path2,
10197
+ properties: {},
10198
+ newProperties: {
10199
+ _type: editor.schema.span.name
10832
10200
  }
10833
- }, () => {
10834
- updateDirtyPaths(editor, newDirtyPaths, (p) => {
10835
- let newPath = p;
10836
- for (const op of batchedOps)
10837
- if (operationCanTransformPath(op) && (newPath = transformPath(newPath, op), !newPath))
10838
- return null;
10839
- return newPath;
10840
- });
10841
10201
  });
10842
- } else
10843
- for (const node2 of nodes) {
10844
- const path2 = parentPath_.concat(index);
10845
- index++, editor.apply({
10846
- type: "insert_node",
10202
+ return;
10203
+ }
10204
+ }
10205
+ if (nodeRecord._key === void 0 && path2.length > 0) {
10206
+ debug$1.normalization("Setting missing key on node"), editor.apply({
10207
+ type: "set_node",
10208
+ path: path2,
10209
+ properties: {},
10210
+ newProperties: {
10211
+ _key: editor.keyGenerator()
10212
+ }
10213
+ });
10214
+ return;
10215
+ }
10216
+ if (path2.length > 0 && nodeRecord._key !== void 0) {
10217
+ const parent = getParent(editor, path2), siblings = parent ? getChildren(editor, parent.path) : editor.children.map((child, index) => ({
10218
+ node: child,
10219
+ path: [index]
10220
+ }));
10221
+ for (const sibling of siblings) {
10222
+ if (pathEquals(sibling.path, path2))
10223
+ break;
10224
+ if (sibling.node._key === nodeRecord._key) {
10225
+ debug$1.normalization("Fixing duplicate key on node"), editor.apply({
10226
+ type: "set_node",
10847
10227
  path: path2,
10848
- node: node2
10849
- }), at = nextPath(at);
10228
+ properties: {},
10229
+ newProperties: {
10230
+ _key: editor.keyGenerator()
10231
+ }
10232
+ });
10233
+ return;
10850
10234
  }
10851
- if (at = previousPath(at), select2) {
10852
- const point2 = end(editor, at);
10853
- point2 && editor.select(point2);
10854
10235
  }
10855
- });
10856
- }
10857
- function firstNodeWithMode(editor, options) {
10858
- const {
10859
- from,
10860
- to,
10861
- match: match2,
10862
- mode
10863
- } = options;
10864
- let hit;
10865
- for (const {
10866
- node,
10867
- path: nodePath
10868
- } of getNodes(editor, {
10869
- from,
10870
- to,
10871
- match: match2
10872
- })) {
10873
- const entry = {
10874
- node,
10875
- path: nodePath
10876
- }, isLower = hit && comparePaths(nodePath, hit.path) === 0;
10877
- if (mode === "highest" && isLower)
10878
- continue;
10879
- if (mode === "lowest" && isLower) {
10880
- hit = entry;
10881
- continue;
10236
+ }
10237
+ if (isTextBlockNode({
10238
+ schema: editor.schema
10239
+ }, node) && !Array.isArray(node.markDefs)) {
10240
+ debug$1.normalization("adding .markDefs to block node"), applySetNode(editor, {
10241
+ markDefs: []
10242
+ }, path2);
10243
+ return;
10244
+ }
10245
+ {
10246
+ const defaultStyle = editor.schema.styles.at(0)?.name;
10247
+ if (defaultStyle && isTextBlockNode({
10248
+ schema: editor.schema
10249
+ }, node) && typeof node.style > "u") {
10250
+ debug$1.normalization("adding .style to block node"), applySetNode(editor, {
10251
+ style: defaultStyle
10252
+ }, path2);
10253
+ return;
10882
10254
  }
10883
- const emit2 = mode === "lowest" ? hit : entry;
10884
- if (emit2)
10885
- return emit2;
10886
- hit = entry;
10887
10255
  }
10888
- return hit;
10889
- }
10890
- const normalizeNode = (editor, entry) => {
10891
- const [node, path2] = entry;
10892
10256
  if (isSpan({
10893
10257
  schema: editor.schema
10894
- }, node) || isObjectNode({
10895
- schema: editor.schema
10896
- }, node))
10258
+ }, node) && !Array.isArray(node.marks)) {
10259
+ debug$1.normalization("Adding .marks to span node"), applySetNode(editor, {
10260
+ marks: []
10261
+ }, path2);
10897
10262
  return;
10898
- node.children ??= [];
10899
- let element = node;
10900
- if (element !== editor && element.children.length === 0) {
10901
- const child = editor.createSpan();
10902
- insertNodes(editor, [child], {
10903
- at: path2.concat(0),
10904
- includeObjectNodes: !0
10905
- });
10906
- const refetched = getTextBlockNode(editor, path2)?.node;
10907
- if (!refetched)
10263
+ }
10264
+ if (isSpan({
10265
+ schema: editor.schema
10266
+ }, node)) {
10267
+ const blockPath = parentPath(path2);
10268
+ if (!getTextBlockNode(editor, blockPath))
10269
+ return;
10270
+ const decorators = editor.schema.decorators.map((decorator) => decorator.name), annotations = node.marks?.filter((mark) => !decorators.includes(mark));
10271
+ if (node.text === "" && annotations && annotations.length > 0) {
10272
+ debug$1.normalization("removing annotations from empty span node"), applySetNode(editor, {
10273
+ marks: node.marks?.filter((mark) => decorators.includes(mark))
10274
+ }, path2);
10275
+ return;
10276
+ }
10277
+ }
10278
+ if (isTextBlock({
10279
+ schema: editor.schema
10280
+ }, node)) {
10281
+ const decorators = editor.schema.decorators.map((decorator) => decorator.name);
10282
+ for (const {
10283
+ node: child,
10284
+ path: childPath
10285
+ } of getChildren(editor, path2))
10286
+ if (isSpan({
10287
+ schema: editor.schema
10288
+ }, child)) {
10289
+ const marks = child.marks ?? [], orphanedAnnotations = marks.filter((mark) => !decorators.includes(mark) && !node.markDefs?.find((def) => def._key === mark));
10290
+ if (orphanedAnnotations.length > 0) {
10291
+ debug$1.normalization("removing orphaned annotations from span node"), applySetNode(editor, {
10292
+ marks: marks.filter((mark) => !orphanedAnnotations.includes(mark))
10293
+ }, childPath);
10294
+ return;
10295
+ }
10296
+ }
10297
+ }
10298
+ if (isSpan({
10299
+ schema: editor.schema
10300
+ }, node)) {
10301
+ const blockPath = parentPath(path2), blockEntry2 = getTextBlockNode(editor, blockPath);
10302
+ if (blockEntry2) {
10303
+ const block = blockEntry2.node, decorators = editor.schema.decorators.map((decorator) => decorator.name), marks = node.marks ?? [], orphanedAnnotations = marks.filter((mark) => !decorators.includes(mark) && !block.markDefs?.find((def) => def._key === mark));
10304
+ if (orphanedAnnotations.length > 0) {
10305
+ debug$1.normalization("removing orphaned annotations from span node"), applySetNode(editor, {
10306
+ marks: marks.filter((mark) => !orphanedAnnotations.includes(mark))
10307
+ }, path2);
10308
+ return;
10309
+ }
10310
+ }
10311
+ }
10312
+ if (isTextBlock({
10313
+ schema: editor.schema
10314
+ }, node)) {
10315
+ const markDefs = node.markDefs ?? [], markDefKeys = /* @__PURE__ */ new Set(), newMarkDefs = [];
10316
+ for (const markDef of markDefs)
10317
+ markDefKeys.has(markDef._key) || (markDefKeys.add(markDef._key), newMarkDefs.push(markDef));
10318
+ if (markDefs.length !== newMarkDefs.length) {
10319
+ debug$1.normalization("removing duplicate markDefs"), applySetNode(editor, {
10320
+ markDefs: newMarkDefs
10321
+ }, path2);
10322
+ return;
10323
+ }
10324
+ }
10325
+ if (isTextBlock({
10326
+ schema: editor.schema
10327
+ }, node)) {
10328
+ const newMarkDefs = (node.markDefs || []).filter((def) => node.children.find((child) => isSpan({
10329
+ schema: editor.schema
10330
+ }, child) && Array.isArray(child.marks) && child.marks.includes(def._key)));
10331
+ if (node.markDefs && !isEqualMarkDefs(newMarkDefs, node.markDefs)) {
10332
+ debug$1.normalization("removing markDef not in use"), applySetNode(editor, {
10333
+ markDefs: newMarkDefs
10334
+ }, path2);
10908
10335
  return;
10909
- element = refetched;
10336
+ }
10910
10337
  }
10911
- const firstChild = element.children[0];
10912
- if (!isEditor(element) && (editor.isInline(element) || isSpan({
10338
+ if (isSpanNode({
10913
10339
  schema: editor.schema
10914
- }, firstChild) || isObjectNode({
10340
+ }, node)) {
10341
+ if (typeof node.text != "string") {
10342
+ debug$1.normalization("Adding .text to span node"), editor.apply({
10343
+ type: "set_node",
10344
+ path: path2,
10345
+ properties: {},
10346
+ newProperties: {
10347
+ text: ""
10348
+ }
10349
+ });
10350
+ return;
10351
+ }
10352
+ return;
10353
+ }
10354
+ if (!isObjectNode({
10915
10355
  schema: editor.schema
10916
- }, firstChild) || isTextBlock({
10356
+ }, node) && isTextBlockNode({
10917
10357
  schema: editor.schema
10918
- }, firstChild) && editor.isInline(firstChild)))
10358
+ }, node)) {
10359
+ if (!Array.isArray(node.children)) {
10360
+ editor.apply({
10361
+ type: "set_node",
10362
+ path: path2,
10363
+ properties: {},
10364
+ newProperties: {
10365
+ children: []
10366
+ }
10367
+ });
10368
+ return;
10369
+ }
10370
+ let element = node;
10371
+ if (element.children.length === 0) {
10372
+ const child = createSpanNode(editor);
10373
+ editor.apply({
10374
+ type: "insert_node",
10375
+ path: path2.concat(0),
10376
+ node: child
10377
+ });
10378
+ const refetched = getTextBlockNode(editor, path2)?.node;
10379
+ if (!refetched)
10380
+ return;
10381
+ element = refetched;
10382
+ }
10919
10383
  for (let n = 0; n < element.children.length; n++) {
10920
10384
  const child = element.children[n], prev = element.children[n - 1];
10921
10385
  if (isSpan({
@@ -10953,54 +10417,17 @@ const normalizeNode = (editor, entry) => {
10953
10417
  element = refetched, n--;
10954
10418
  }
10955
10419
  }
10956
- } else if (isTextBlock({
10957
- schema: editor.schema
10958
- }, child))
10959
- if (editor.isInline(child)) {
10960
- if (prev == null || !isSpan({
10961
- schema: editor.schema
10962
- }, prev)) {
10963
- const newChild = editor.createSpan();
10964
- insertNodes(editor, [newChild], {
10965
- at: path2.concat(n),
10966
- includeObjectNodes: !0
10967
- });
10968
- const refetched = getTextBlockNode(editor, path2)?.node;
10969
- if (!refetched)
10970
- return;
10971
- element = refetched, n++;
10972
- }
10973
- if (n === element.children.length - 1) {
10974
- const newChild = editor.createSpan();
10975
- insertNodes(editor, [newChild], {
10976
- at: path2.concat(n + 1),
10977
- includeObjectNodes: !0
10978
- });
10979
- const refetched = getTextBlockNode(editor, path2)?.node;
10980
- if (!refetched)
10981
- return;
10982
- element = refetched, n++;
10983
- }
10984
- } else {
10985
- removeNodes(editor, {
10986
- at: path2.concat(n),
10987
- includeObjectNodes: !0
10988
- });
10989
- const refetched = getTextBlockNode(editor, path2)?.node;
10990
- if (!refetched)
10991
- return;
10992
- element = refetched, n--;
10993
- }
10994
- else if (isObjectNode({
10420
+ } else if (isObjectNode({
10995
10421
  schema: editor.schema
10996
10422
  }, child)) {
10997
10423
  if (prev == null || !isSpan({
10998
10424
  schema: editor.schema
10999
10425
  }, prev)) {
11000
- const newChild = editor.createSpan();
11001
- insertNodes(editor, [newChild], {
11002
- at: path2.concat(n),
11003
- includeObjectNodes: !0
10426
+ const newChild = createSpanNode(editor);
10427
+ editor.apply({
10428
+ type: "insert_node",
10429
+ path: path2.concat(n),
10430
+ node: newChild
11004
10431
  });
11005
10432
  const refetched = getTextBlockNode(editor, path2)?.node;
11006
10433
  if (!refetched)
@@ -11008,10 +10435,11 @@ const normalizeNode = (editor, entry) => {
11008
10435
  element = refetched, n++;
11009
10436
  }
11010
10437
  if (n === element.children.length - 1) {
11011
- const newChild = editor.createSpan();
11012
- insertNodes(editor, [newChild], {
11013
- at: path2.concat(n + 1),
11014
- includeObjectNodes: !0
10438
+ const newChild = createSpanNode(editor);
10439
+ editor.apply({
10440
+ type: "insert_node",
10441
+ path: path2.concat(n + 1),
10442
+ node: newChild
11015
10443
  });
11016
10444
  const refetched = getTextBlockNode(editor, path2)?.node;
11017
10445
  if (!refetched)
@@ -11020,28 +10448,8 @@ const normalizeNode = (editor, entry) => {
11020
10448
  }
11021
10449
  }
11022
10450
  }
11023
- else
11024
- for (let n = 0; n < element.children.length; n++) {
11025
- const child = element.children[n];
11026
- if (isSpan({
11027
- schema: editor.schema
11028
- }, child) || isTextBlock({
11029
- schema: editor.schema
11030
- }, child) && editor.isInline(child)) {
11031
- if (removeNodes(editor, {
11032
- at: path2.concat(n),
11033
- includeObjectNodes: !0
11034
- }), path2.length === 0)
11035
- element = editor;
11036
- else {
11037
- const refetched = getTextBlockNode(editor, path2)?.node;
11038
- if (!refetched)
11039
- return;
11040
- element = refetched;
11041
- }
11042
- n--;
11043
- }
11044
- }
10451
+ return;
10452
+ }
11045
10453
  };
11046
10454
  function select(editor, target) {
11047
10455
  const {
@@ -11081,7 +10489,7 @@ const shouldNormalize = (_editor, {
11081
10489
  if (iteration > maxIterations)
11082
10490
  throw new Error(`Could not completely normalize the editor after ${maxIterations} iterations! This is usually due to incorrect normalization logic that leaves a node in an invalid state.`);
11083
10491
  return !0;
11084
- }, createEditor = (context) => {
10492
+ }, createEditor = () => {
11085
10493
  const e = {
11086
10494
  [EDITOR_BRAND]: !0,
11087
10495
  children: [],
@@ -11095,24 +10503,15 @@ const shouldNormalize = (_editor, {
11095
10503
  dirtyPathKeys: /* @__PURE__ */ new Set(),
11096
10504
  flushing: !1,
11097
10505
  normalizing: !0,
11098
- batchingDirtyPaths: !1,
11099
10506
  pathRefs: /* @__PURE__ */ new Set(),
11100
10507
  pointRefs: /* @__PURE__ */ new Set(),
11101
10508
  rangeRefs: /* @__PURE__ */ new Set(),
11102
- createSpan: () => ({
11103
- _type: context.schema.span.name,
11104
- _key: context.keyGenerator(),
11105
- text: "",
11106
- marks: []
11107
- }),
11108
- isInline: () => !1,
11109
10509
  onChange: () => {
11110
10510
  },
11111
10511
  // Core
11112
10512
  apply: (...args) => apply(e, ...args),
11113
10513
  // Editor
11114
10514
  normalizeNode: (...args) => normalizeNode(e, ...args),
11115
- getDirtyPaths: (...args) => getDirtyPaths(e, ...args),
11116
10515
  shouldNormalize: (...args) => shouldNormalize(e, ...args),
11117
10516
  // Overrideable commands
11118
10517
  select: (...args) => select(e, ...args),
@@ -11475,11 +10874,8 @@ const withDOM = (editor) => {
11475
10874
  };
11476
10875
  function createSlateEditor(config) {
11477
10876
  debug$1.setup("creating new slate editor instance");
11478
- const context = config.editorActor.getSnapshot().context, placeholderBlock = createPlaceholderBlock(context), editor = createEditor({
11479
- schema: context.schema,
11480
- keyGenerator: context.keyGenerator
11481
- });
11482
- editor.editableTypes = /* @__PURE__ */ new Set(), editor.decoratedRanges = [], editor.decoratorState = {}, editor.blockIndexMap = /* @__PURE__ */ new Map(), editor.history = {
10877
+ const context = config.editorActor.getSnapshot().context, placeholderBlock = createPlaceholderBlock(context), editor = createEditor();
10878
+ editor.schema = context.schema, editor.keyGenerator = context.keyGenerator, editor.editableTypes = /* @__PURE__ */ new Set(), editor.decoratedRanges = [], editor.decoratorState = {}, editor.blockIndexMap = /* @__PURE__ */ new Map(), editor.history = {
11483
10879
  undos: [],
11484
10880
  redos: []
11485
10881
  }, editor.lastSelection = null, editor.lastSlateSelection = null, editor.listIndexMap = /* @__PURE__ */ new Map(), editor.remotePatches = [], editor.undoStepId = void 0, editor.children = [placeholderBlock], editor.isDeferringMutations = !1, editor.isNormalizingNode = !1, editor.isPatching = !0, editor.isPerformingBehaviorOperation = !1, editor.isProcessingRemoteChanges = !1, editor.isRedoing = !1, editor.isUndoing = !1, editor.withHistory = !0;
@@ -13235,7 +12631,7 @@ const removeAnnotationOperationImplementation = ({
13235
12631
  if (isTextBlockNode(context, slateBlock)) {
13236
12632
  const filteredProps = {};
13237
12633
  for (const key of Object.keys(operation.props))
13238
- if (!(key === "_type" || key === "children")) {
12634
+ if (key !== "_type") {
13239
12635
  if (key === "_key") {
13240
12636
  filteredProps[key] = operation.props[key];
13241
12637
  continue;
@@ -13292,7 +12688,7 @@ const removeAnnotationOperationImplementation = ({
13292
12688
  if (!slateBlock)
13293
12689
  throw new Error(`Unable to find block at ${safeStringify(operation.at)}`);
13294
12690
  if (isTextBlockNode(context, slateBlock)) {
13295
- const propsToRemove = operation.props.filter((prop) => prop !== "_type" && prop !== "_key" && prop !== "children"), unsetProps2 = {};
12691
+ const propsToRemove = operation.props.filter((prop) => prop !== "_type" && prop !== "_key"), unsetProps2 = {};
13296
12692
  for (const prop of propsToRemove)
13297
12693
  unsetProps2[prop] = null;
13298
12694
  applySetNode(operation.editor, unsetProps2, [blockIndex]), operation.props.includes("_key") && applySetNode(operation.editor, {
@@ -13411,19 +12807,14 @@ const removeAnnotationOperationImplementation = ({
13411
12807
  }, child)) {
13412
12808
  const newNode = {};
13413
12809
  for (const prop of operation.props)
13414
- if (prop !== "text" && prop !== "_type") {
12810
+ if (prop !== "_type") {
13415
12811
  if (prop === "_key") {
13416
12812
  newNode._key = context.keyGenerator();
13417
12813
  continue;
13418
12814
  }
13419
12815
  newNode[prop] = null;
13420
12816
  }
13421
- applySetNode(operation.editor, newNode, childPath), operation.props.includes("text") && operation.editor.apply({
13422
- type: "remove_text",
13423
- path: childPath,
13424
- offset: 0,
13425
- text: child.text
13426
- });
12817
+ applySetNode(operation.editor, newNode, childPath);
13427
12818
  return;
13428
12819
  }
13429
12820
  if (isObjectNode({
@@ -13492,125 +12883,401 @@ const removeAnnotationOperationImplementation = ({
13492
12883
  if (!blockEntry)
13493
12884
  return;
13494
12885
  const {
13495
- node: block,
13496
- path: blockPath
13497
- } = blockEntry, lonelyEmptySpan = isTextBlock({
13498
- schema: editor.schema
13499
- }, block) && block.children.length === 1 && isSpan({
12886
+ node: block,
12887
+ path: blockPath
12888
+ } = blockEntry, lonelyEmptySpan = isTextBlock({
12889
+ schema: editor.schema
12890
+ }, block) && block.children.length === 1 && isSpan({
12891
+ schema: editor.schema
12892
+ }, block.children[0]) && block.children[0].text === "" ? block.children[0] : void 0;
12893
+ if (lonelyEmptySpan) {
12894
+ const existingMarks = lonelyEmptySpan.marks ?? [], existingMarksWithoutDecorator = existingMarks.filter((existingMark) => existingMark !== mark), newMarks = existingMarks.length === existingMarksWithoutDecorator.length ? [...existingMarks, mark] : existingMarksWithoutDecorator;
12895
+ for (const {
12896
+ path: spanPath
12897
+ } of Array.from(getNodes(editor, {
12898
+ at: blockPath,
12899
+ match: (node) => isSpan({
12900
+ schema: editor.schema
12901
+ }, node)
12902
+ })))
12903
+ applySetNode(editor, {
12904
+ marks: newMarks
12905
+ }, spanPath);
12906
+ } else
12907
+ editor.decoratorState[mark] = !0;
12908
+ }
12909
+ if (editor.selection) {
12910
+ const selection = editor.selection;
12911
+ editor.selection = {
12912
+ ...selection
12913
+ };
12914
+ }
12915
+ }
12916
+ }, decoratorRemoveOperationImplementation = ({
12917
+ context,
12918
+ operation
12919
+ }) => {
12920
+ const editor = operation.editor, mark = operation.decorator, at = operation.at ? toSlateRange({
12921
+ context: {
12922
+ schema: context.schema,
12923
+ value: operation.editor.children,
12924
+ selection: operation.at
12925
+ },
12926
+ blockIndexMap: operation.editor.blockIndexMap
12927
+ }) : editor.selection;
12928
+ if (at) {
12929
+ if (isExpandedRange(at)) {
12930
+ const ref = rangeRef(editor, at, {
12931
+ affinity: "inward"
12932
+ }), decoratorLeafEntry = getNode(editor, at.anchor.path), decoratorLeaf = decoratorLeafEntry && isLeaf(editor, decoratorLeafEntry.path) ? decoratorLeafEntry.node : void 0;
12933
+ if (!(decoratorLeaf && isCollapsedRange(at) && isSpan({
12934
+ schema: editor.schema
12935
+ }, decoratorLeaf) && decoratorLeaf.text.length > 0)) {
12936
+ const [start2, end2] = rangeEdges(at);
12937
+ (!isEnd(editor, end2, end2.path) || !isEdge(editor, end2, end2.path)) && applySplitNode(editor, end2.path, end2.offset), (!isStart(editor, start2, start2.path) || !isEdge(editor, start2, start2.path)) && applySplitNode(editor, start2.path, start2.offset);
12938
+ }
12939
+ const updatedAt = ref.unref();
12940
+ if (updatedAt) {
12941
+ const splitTextNodes = [...getNodes(editor, {
12942
+ from: rangeStart(updatedAt).path,
12943
+ to: rangeEnd(updatedAt).path,
12944
+ match: (n) => isSpan({
12945
+ schema: editor.schema
12946
+ }, n)
12947
+ })];
12948
+ for (const {
12949
+ node,
12950
+ path: nodePath
12951
+ } of splitTextNodes) {
12952
+ if (!isSpan({
12953
+ schema: editor.schema
12954
+ }, node))
12955
+ continue;
12956
+ const block = editor.children[nodePath[0]];
12957
+ isTextBlock({
12958
+ schema: editor.schema
12959
+ }, block) && block.children.includes(node) && applySetNode(editor, {
12960
+ marks: (Array.isArray(node.marks) ? node.marks : []).filter((eMark) => eMark !== mark),
12961
+ _type: context.schema.span.name
12962
+ }, nodePath);
12963
+ }
12964
+ }
12965
+ } else {
12966
+ const blockEntry = getNode(editor, path(editor, at, {
12967
+ depth: 1
12968
+ }));
12969
+ if (!blockEntry)
12970
+ return;
12971
+ const {
12972
+ node: block,
12973
+ path: blockPath
12974
+ } = blockEntry, lonelyEmptySpan = isTextBlock({
12975
+ schema: editor.schema
12976
+ }, block) && block.children.length === 1 && isSpan({
12977
+ schema: editor.schema
12978
+ }, block.children[0]) && block.children[0].text === "" ? block.children[0] : void 0;
12979
+ if (lonelyEmptySpan) {
12980
+ const existingMarksWithoutDecorator = (lonelyEmptySpan.marks ?? []).filter((existingMark) => existingMark !== mark);
12981
+ for (const {
12982
+ path: spanPath
12983
+ } of Array.from(getNodes(editor, {
12984
+ at: blockPath,
12985
+ match: (node) => isSpan({
12986
+ schema: editor.schema
12987
+ }, node)
12988
+ })))
12989
+ applySetNode(editor, {
12990
+ marks: existingMarksWithoutDecorator
12991
+ }, spanPath);
12992
+ } else
12993
+ editor.decoratorState[mark] = !1;
12994
+ }
12995
+ if (editor.selection) {
12996
+ const selection = editor.selection;
12997
+ editor.selection = {
12998
+ ...selection
12999
+ };
13000
+ }
13001
+ }
13002
+ };
13003
+ function pointRef(editor, point2, options = {}) {
13004
+ const {
13005
+ affinity = "forward"
13006
+ } = options, ref = {
13007
+ current: point2,
13008
+ affinity,
13009
+ unref() {
13010
+ const {
13011
+ current
13012
+ } = ref;
13013
+ return editor.pointRefs.delete(ref), ref.current = null, current;
13014
+ }
13015
+ };
13016
+ return editor.pointRefs.add(ref), ref;
13017
+ }
13018
+ function shouldMergeNodesRemovePrevNode(editor, prev, _current) {
13019
+ let isEmptyElement = !1;
13020
+ if (isTextBlock({
13021
+ schema: editor.schema
13022
+ }, prev.node)) {
13023
+ const prevChildren = prev.node.children;
13024
+ isEmptyElement = prevChildren.length === 0 || prevChildren.length === 1 && isSpan({
13025
+ schema: editor.schema
13026
+ }, prevChildren[0]) && prevChildren[0].text === "";
13027
+ }
13028
+ return isEmptyElement || isSpan({
13029
+ schema: editor.schema
13030
+ }, prev.node) && prev.node.text === "" && prev.path[prev.path.length - 1] !== 0;
13031
+ }
13032
+ function isCommonPath(path2, another) {
13033
+ return path2.length <= another.length && comparePaths(path2, another) === 0;
13034
+ }
13035
+ const getDefaultInsertLocation = (editor) => editor.selection ? editor.selection : editor.children.length > 0 ? end(editor, []) : [0];
13036
+ function insertText(editor, text, options = {}) {
13037
+ withoutNormalizing(editor, () => {
13038
+ const {
13039
+ includeObjectNodes = !1
13040
+ } = options;
13041
+ let {
13042
+ at = getDefaultInsertLocation(editor)
13043
+ } = options;
13044
+ if (isPath(at) && (at = range(editor, at)), isRange(at))
13045
+ if (isCollapsedRange(at))
13046
+ at = at.anchor;
13047
+ else {
13048
+ const end2 = rangeEnd(at);
13049
+ if (!includeObjectNodes) {
13050
+ const endPath = path(editor, end2), endEntry = getNode(editor, endPath);
13051
+ if (endEntry && isObjectNode({
13052
+ schema: editor.schema
13053
+ }, endEntry.node) ? endEntry : getAncestorObjectNode(editor, end2.path))
13054
+ return;
13055
+ }
13056
+ const start2 = rangeStart(at), startRef = pointRef(editor, start2), endRef = pointRef(editor, end2);
13057
+ deleteText(editor, {
13058
+ at,
13059
+ includeObjectNodes
13060
+ });
13061
+ const startPoint = startRef.unref(), endPoint = endRef.unref();
13062
+ at = startPoint || endPoint, editor.setSelection({
13063
+ anchor: at,
13064
+ focus: at
13065
+ });
13066
+ }
13067
+ if (!includeObjectNodes) {
13068
+ const atPath = path(editor, at), atEntry = getNode(editor, atPath);
13069
+ if (atEntry && isObjectNode({
13070
+ schema: editor.schema
13071
+ }, atEntry.node) ? atEntry : getAncestorObjectNode(editor, at.path))
13072
+ return;
13073
+ }
13074
+ const {
13075
+ path: path$1,
13076
+ offset
13077
+ } = at;
13078
+ text.length > 0 && editor.apply({
13079
+ type: "insert_text",
13080
+ path: path$1,
13081
+ offset,
13082
+ text
13083
+ });
13084
+ });
13085
+ }
13086
+ function deleteText(editor, options = {}) {
13087
+ withoutNormalizing(editor, () => {
13088
+ const {
13089
+ reverse = !1,
13090
+ unit = "character",
13091
+ distance = 1,
13092
+ includeObjectNodes = !1
13093
+ } = options;
13094
+ let {
13095
+ at = editor.selection,
13096
+ hanging = !1
13097
+ } = options;
13098
+ if (!at)
13099
+ return;
13100
+ let isCollapsed = !1;
13101
+ if (isRange(at) && isCollapsedRange(at) && (isCollapsed = !0, at = at.anchor), isPoint(at)) {
13102
+ const furthestObjectNode = getHighestObjectNode(editor, at.path);
13103
+ if (!includeObjectNodes && furthestObjectNode)
13104
+ at = furthestObjectNode.path;
13105
+ else {
13106
+ const opts = {
13107
+ unit,
13108
+ distance
13109
+ }, target = reverse ? before(editor, at, opts) || start(editor, []) : after(editor, at, opts) || end(editor, []);
13110
+ at = {
13111
+ anchor: at,
13112
+ focus: target
13113
+ }, hanging = !0;
13114
+ }
13115
+ }
13116
+ if (isPath(at)) {
13117
+ removeNodes(editor, {
13118
+ at,
13119
+ includeObjectNodes
13120
+ });
13121
+ return;
13122
+ }
13123
+ if (isCollapsedRange(at))
13124
+ return;
13125
+ if (!hanging) {
13126
+ const [, end2] = rangeEdges(at), endOfDoc = end(editor, []);
13127
+ pointEquals(end2, endOfDoc) || (at = unhangRange(editor, at));
13128
+ }
13129
+ let [start$1, end$1] = rangeEdges(at);
13130
+ const startBlock = getAncestorTextBlock(editor, start$1.path), endBlock = getAncestorTextBlock(editor, end$1.path), isAcrossBlocks = startBlock && endBlock && !pathEquals(startBlock.path, endBlock.path), isSingleText = pathEquals(start$1.path, end$1.path), startNonEditable = includeObjectNodes ? null : getHighestObjectNode(editor, start$1.path), endNonEditable = includeObjectNodes ? null : getHighestObjectNode(editor, end$1.path);
13131
+ if (startNonEditable) {
13132
+ const beforePoint = before(editor, start$1);
13133
+ beforePoint && startBlock && isAncestorPath(startBlock.path, beforePoint.path) && (start$1 = beforePoint);
13134
+ }
13135
+ if (endNonEditable) {
13136
+ const afterPoint = after(editor, end$1);
13137
+ afterPoint && endBlock && isAncestorPath(endBlock.path, afterPoint.path) && (end$1 = afterPoint);
13138
+ }
13139
+ const matches = [];
13140
+ let lastPath;
13141
+ for (const entry of getNodes(editor, {
13142
+ from: start$1.path,
13143
+ to: end$1.path
13144
+ })) {
13145
+ const {
13146
+ node,
13147
+ path: entryPath
13148
+ } = entry;
13149
+ lastPath && comparePaths(entryPath, lastPath) === 0 || (!includeObjectNodes && isObjectNode({
13500
13150
  schema: editor.schema
13501
- }, block.children[0]) && block.children[0].text === "" ? block.children[0] : void 0;
13502
- if (lonelyEmptySpan) {
13503
- const existingMarks = lonelyEmptySpan.marks ?? [], existingMarksWithoutDecorator = existingMarks.filter((existingMark) => existingMark !== mark), newMarks = existingMarks.length === existingMarksWithoutDecorator.length ? [...existingMarks, mark] : existingMarksWithoutDecorator;
13504
- for (const {
13505
- path: spanPath
13506
- } of Array.from(getNodes(editor, {
13507
- at: blockPath,
13508
- match: (node) => isSpan({
13509
- schema: editor.schema
13510
- }, node)
13511
- })))
13512
- applySetNode(editor, {
13513
- marks: newMarks
13514
- }, spanPath);
13515
- } else
13516
- editor.decoratorState[mark] = !0;
13151
+ }, node) || !isCommonPath(entryPath, start$1.path) && !isCommonPath(entryPath, end$1.path)) && (matches.push(entry), lastPath = entryPath);
13517
13152
  }
13518
- if (editor.selection) {
13519
- const selection = editor.selection;
13520
- editor.selection = {
13521
- ...selection
13522
- };
13153
+ const pathRefs = Array.from(matches, (entry) => pathRef(editor, entry.path)), startRef = pointRef(editor, start$1), endRef = pointRef(editor, end$1);
13154
+ let removedText = "";
13155
+ if (!isSingleText && !startNonEditable) {
13156
+ const point22 = startRef.current, nodeEntry = getSpanNode(editor, point22.path);
13157
+ if (nodeEntry) {
13158
+ const node = nodeEntry.node, {
13159
+ path: path2
13160
+ } = point22, {
13161
+ offset
13162
+ } = start$1, text = node.text.slice(offset);
13163
+ text.length > 0 && (editor.apply({
13164
+ type: "remove_text",
13165
+ path: path2,
13166
+ offset,
13167
+ text
13168
+ }), removedText = text);
13169
+ }
13523
13170
  }
13524
- }
13525
- }, decoratorRemoveOperationImplementation = ({
13526
- context,
13527
- operation
13528
- }) => {
13529
- const editor = operation.editor, mark = operation.decorator, at = operation.at ? toSlateRange({
13530
- context: {
13531
- schema: context.schema,
13532
- value: operation.editor.children,
13533
- selection: operation.at
13534
- },
13535
- blockIndexMap: operation.editor.blockIndexMap
13536
- }) : editor.selection;
13537
- if (at) {
13538
- if (isExpandedRange(at)) {
13539
- const ref = rangeRef(editor, at, {
13540
- affinity: "inward"
13541
- }), decoratorLeafEntry = getNode(editor, at.anchor.path), decoratorLeaf = decoratorLeafEntry && isLeaf(editor, decoratorLeafEntry.path) ? decoratorLeafEntry.node : void 0;
13542
- if (!(decoratorLeaf && isCollapsedRange(at) && isSpan({
13543
- schema: editor.schema
13544
- }, decoratorLeaf) && decoratorLeaf.text.length > 0)) {
13545
- const [start2, end2] = rangeEdges(at);
13546
- (!isEnd(editor, end2, end2.path) || !isEdge(editor, end2, end2.path)) && applySplitNode(editor, end2.path, end2.offset), (!isStart(editor, start2, start2.path) || !isEdge(editor, start2, start2.path)) && applySplitNode(editor, start2.path, start2.offset);
13171
+ if (pathRefs.reverse().map((r) => r.unref()).filter((r) => r !== null).forEach((p) => {
13172
+ removeNodes(editor, {
13173
+ at: p,
13174
+ includeObjectNodes
13175
+ });
13176
+ }), !endNonEditable) {
13177
+ const point22 = endRef.current, endNodeEntry = getSpanNode(editor, point22.path);
13178
+ if (endNodeEntry) {
13179
+ const node = endNodeEntry.node, {
13180
+ path: path2
13181
+ } = point22, offset = isSingleText ? start$1.offset : 0, text = node.text.slice(offset, end$1.offset);
13182
+ text.length > 0 && (editor.apply({
13183
+ type: "remove_text",
13184
+ path: path2,
13185
+ offset,
13186
+ text
13187
+ }), removedText = text);
13547
13188
  }
13548
- const updatedAt = ref.unref();
13549
- if (updatedAt) {
13550
- const splitTextNodes = [...getNodes(editor, {
13551
- from: rangeStart(updatedAt).path,
13552
- to: rangeEnd(updatedAt).path,
13553
- match: (n) => isSpan({
13189
+ }
13190
+ if (!isSingleText && isAcrossBlocks && endRef.current && startRef.current) {
13191
+ const mergeAt = endRef.current, mergeMatch = (n) => isTextBlock({
13192
+ schema: editor.schema
13193
+ }, n), current = getAncestor(editor, mergeAt.path, mergeMatch), beforePoint = before(editor, mergeAt), prev = beforePoint ? getNodes(editor, {
13194
+ to: beforePoint.path,
13195
+ match: mergeMatch,
13196
+ reverse: !0
13197
+ }).next().value : void 0;
13198
+ if (current && prev) {
13199
+ const {
13200
+ node: mergeNode,
13201
+ path: mergePath
13202
+ } = current, {
13203
+ node: prevNode,
13204
+ path: prevPath
13205
+ } = prev;
13206
+ if (mergePath.length !== 0 && prevPath.length !== 0) {
13207
+ const newPath = nextPath(prevPath), common = commonPath(mergePath, prevPath), isPreviousSibling = isSiblingPath(mergePath, prevPath), editorLevels = pathLevels(mergePath).filter((levelPath) => levelPath.length > 0).map((levelPath) => getNode(editor, levelPath)).filter((entry) => entry !== void 0).map((entry) => entry.node).slice(Math.max(0, common.length - 1)).slice(0, -1), hasSingleChildNest = (node) => {
13208
+ if (isTextBlock({
13209
+ schema: editor.schema
13210
+ }, node)) {
13211
+ const elementChildren = node.children;
13212
+ return elementChildren.length === 1 ? hasSingleChildNest(elementChildren[0]) : !1;
13213
+ } else return !isEditor(node);
13214
+ }, emptyAncestor = getAncestors(editor, mergePath).reverse().find((ancestor) => editorLevels.includes(ancestor.node) && hasSingleChildNest(ancestor.node)), emptyRef = emptyAncestor && pathRef(editor, emptyAncestor.path);
13215
+ let position;
13216
+ if (isSpan({
13554
13217
  schema: editor.schema
13555
- }, n)
13556
- })];
13557
- for (const {
13558
- node,
13559
- path: nodePath
13560
- } of splitTextNodes) {
13561
- if (!isSpan({
13218
+ }, mergeNode) && isSpan({
13562
13219
  schema: editor.schema
13563
- }, node))
13564
- continue;
13565
- const block = editor.children[nodePath[0]];
13566
- isTextBlock({
13220
+ }, prevNode))
13221
+ position = prevNode.text.length;
13222
+ else if (isTextBlock({
13567
13223
  schema: editor.schema
13568
- }, block) && block.children.includes(node) && applySetNode(editor, {
13569
- marks: (Array.isArray(node.marks) ? node.marks : []).filter((eMark) => eMark !== mark),
13570
- _type: context.schema.span.name
13571
- }, nodePath);
13224
+ }, mergeNode) && isTextBlock({
13225
+ schema: editor.schema
13226
+ }, prevNode))
13227
+ position = prevNode.children.length;
13228
+ else
13229
+ throw new Error(`Cannot merge the node at path [${mergePath}] with the previous sibling because it is not the same kind: ${safeStringify(mergeNode)} ${safeStringify(prevNode)}`);
13230
+ if (!isPreviousSibling) {
13231
+ const moveNodeEntry = getNode(editor, mergePath);
13232
+ if (moveNodeEntry) {
13233
+ const moveNode = moveNodeEntry.node;
13234
+ editor.apply({
13235
+ type: "remove_node",
13236
+ path: mergePath,
13237
+ node: moveNode
13238
+ }), editor.apply({
13239
+ type: "insert_node",
13240
+ path: newPath,
13241
+ node: moveNode
13242
+ });
13243
+ }
13244
+ }
13245
+ if (emptyRef && removeNodes(editor, {
13246
+ at: emptyRef.current,
13247
+ includeObjectNodes
13248
+ }), shouldMergeNodesRemovePrevNode(editor, {
13249
+ node: prevNode,
13250
+ path: prevPath
13251
+ }, {
13252
+ node: mergeNode,
13253
+ path: mergePath
13254
+ }))
13255
+ removeNodes(editor, {
13256
+ at: prevPath,
13257
+ includeObjectNodes
13258
+ });
13259
+ else {
13260
+ const pteEditor = editor;
13261
+ if (isTextBlock({
13262
+ schema: editor.schema
13263
+ }, mergeNode) && isTextBlock({
13264
+ schema: editor.schema
13265
+ }, prevNode) && Array.isArray(mergeNode.markDefs) && mergeNode.markDefs.length > 0) {
13266
+ const targetPath = isPreviousSibling ? prevPath : previousPath(newPath), oldDefs = Array.isArray(prevNode.markDefs) && prevNode.markDefs || [], newMarkDefs = [...new Map([...oldDefs, ...mergeNode.markDefs].map((def) => [def._key, def])).values()];
13267
+ applySetNode(pteEditor, {
13268
+ markDefs: newMarkDefs
13269
+ }, targetPath);
13270
+ }
13271
+ applyMergeNode(pteEditor, newPath, position);
13272
+ }
13273
+ emptyRef && emptyRef.unref();
13572
13274
  }
13573
13275
  }
13574
- } else {
13575
- const blockEntry = getNode(editor, path(editor, at, {
13576
- depth: 1
13577
- }));
13578
- if (!blockEntry)
13579
- return;
13580
- const {
13581
- node: block,
13582
- path: blockPath
13583
- } = blockEntry, lonelyEmptySpan = isTextBlock({
13584
- schema: editor.schema
13585
- }, block) && block.children.length === 1 && isSpan({
13586
- schema: editor.schema
13587
- }, block.children[0]) && block.children[0].text === "" ? block.children[0] : void 0;
13588
- if (lonelyEmptySpan) {
13589
- const existingMarksWithoutDecorator = (lonelyEmptySpan.marks ?? []).filter((existingMark) => existingMark !== mark);
13590
- for (const {
13591
- path: spanPath
13592
- } of Array.from(getNodes(editor, {
13593
- at: blockPath,
13594
- match: (node) => isSpan({
13595
- schema: editor.schema
13596
- }, node)
13597
- })))
13598
- applySetNode(editor, {
13599
- marks: existingMarksWithoutDecorator
13600
- }, spanPath);
13601
- } else
13602
- editor.decoratorState[mark] = !1;
13603
- }
13604
- if (editor.selection) {
13605
- const selection = editor.selection;
13606
- editor.selection = {
13607
- ...selection
13608
- };
13609
13276
  }
13610
- }
13611
- };
13612
- function isInline(context, path2) {
13613
- return !isBlock(context, path2);
13277
+ isCollapsed && reverse && unit === "character" && removedText.length > 1 && removedText.match(/[\u0980-\u09FF\u0E00-\u0E7F\u1000-\u109F\u0900-\u097F\u1780-\u17FF\u0D00-\u0D7F\u0B00-\u0B7F\u0A00-\u0A7F\u0B80-\u0BFF\u0C00-\u0C7F]+/) && insertText(editor, removedText.slice(0, removedText.length - distance));
13278
+ const startUnref = startRef.unref(), endUnref = endRef.unref(), point2 = reverse ? startUnref || endUnref : endUnref || startUnref;
13279
+ options.at == null && point2 && editor.select(point2);
13280
+ });
13614
13281
  }
13615
13282
  const deleteOperationImplementation = ({
13616
13283
  context,
@@ -18692,8 +18359,11 @@ function updateBlock({
18692
18359
  }) {
18693
18360
  const slateBlock = toSlateBlock(block, {
18694
18361
  schemaTypes: context.schema
18695
- });
18696
- applySetNode(slateEditor, slateBlock, [index]);
18362
+ }), {
18363
+ children: _children,
18364
+ ...blockProps
18365
+ } = slateBlock;
18366
+ applySetNode(slateEditor, blockProps, [index]);
18697
18367
  const oldRecord = oldSlateBlock, newRecord = slateBlock, removedProperties = {};
18698
18368
  for (const key of Object.keys(oldRecord))
18699
18369
  key === "children" || key === "text" || newRecord.hasOwnProperty(key) || (removedProperties[key] = oldRecord[key]);
@@ -18728,7 +18398,12 @@ function updateBlock({
18728
18398
  }, oldBlockChild) && currentBlockChild.text !== oldBlockChild.text, path2 = [index, currentBlockChildIndex];
18729
18399
  if (isChildChanged)
18730
18400
  if (currentBlockChild._key === oldBlockChild?._key && currentBlockChild._type === oldBlockChild?._type) {
18731
- debug$1.syncValue("Updating changed child", currentBlockChild, oldBlockChild), applySetNode(slateEditor, currentBlockChild, path2);
18401
+ debug$1.syncValue("Updating changed child", currentBlockChild, oldBlockChild);
18402
+ const {
18403
+ text: _text,
18404
+ ...childProps
18405
+ } = currentBlockChild;
18406
+ applySetNode(slateEditor, childProps, path2);
18732
18407
  const isSpanNode2 = isSpan({
18733
18408
  schema: context.schema
18734
18409
  }, currentBlockChild) && isSpan({