@portabletext/editor 6.6.0 → 6.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/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];
@@ -4366,7 +4369,7 @@ const RestoreDOM = IS_ANDROID ? RestoreDOMComponent : ({
4366
4369
  let blockPath = indexedPath;
4367
4370
  isTextBlockNode({
4368
4371
  schema: editor.schema
4369
- }, node) && !editor.isInline(node) || (blockPath = getAncestorTextBlock(editor, indexedPath)?.path ?? indexedPath.slice(0, 1));
4372
+ }, node) || (blockPath = getAncestorTextBlock(editor, indexedPath)?.path ?? indexedPath.slice(0, 1));
4370
4373
  const range$1 = range(editor, blockPath);
4371
4374
  editor.select(range$1);
4372
4375
  return;
@@ -5786,7 +5789,7 @@ function RenderElement(props) {
5786
5789
  let t12;
5787
5790
  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
5791
  }
5789
- if (slateStatic.isInline(props.element)) {
5792
+ if (isInline(slateStatic, props.indexedPath)) {
5790
5793
  let t02;
5791
5794
  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
5795
  }
@@ -7348,34 +7351,15 @@ function createEditableAPI(editor, editorActor) {
7348
7351
  return ![schema.block.name, schema.span.name].includes(element._type);
7349
7352
  },
7350
7353
  findByPath: (path2) => {
7351
- const blockKey = getBlockKeyFromSelectionPoint({
7352
- path: path2
7353
- });
7354
- if (!blockKey)
7354
+ const indexedPath = keyedPathToIndexedPath(editor, path2, editor.blockIndexMap);
7355
+ if (!indexedPath)
7355
7356
  return [void 0, void 0];
7356
- const blockIndex = editor.blockIndexMap.get(blockKey);
7357
- if (blockIndex === void 0)
7358
- 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];
7357
+ const result = getNode({
7358
+ schema: editor.schema,
7359
+ editableTypes: editor.editableTypes,
7360
+ value: editor.children
7361
+ }, indexedPath);
7362
+ return result ? [result.node, path2] : [void 0, void 0];
7379
7363
  },
7380
7364
  findDOMNode: (element) => {
7381
7365
  let node;
@@ -7790,915 +7774,303 @@ function createHistoryPlugin({
7790
7774
  }, editor;
7791
7775
  };
7792
7776
  }
7793
- function isEnd(editor, point2, at) {
7794
- const editorEnd = end(editor, at);
7795
- return pointEquals(point2, editorEnd);
7777
+ function cloneDiff(diff2) {
7778
+ const [type, patch] = diff2;
7779
+ return [type, patch];
7796
7780
  }
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);
7781
+ function getCommonOverlap(textA, textB) {
7782
+ let text1 = textA, text2 = textB;
7783
+ const text1Length = text1.length, text2Length = text2.length;
7784
+ if (text1Length === 0 || text2Length === 0) return 0;
7785
+ text1Length > text2Length ? text1 = text1.substring(text1Length - text2Length) : text1Length < text2Length && (text2 = text2.substring(0, text1Length));
7786
+ const textLength = Math.min(text1Length, text2Length);
7787
+ if (text1 === text2) return textLength;
7788
+ let best = 0, length = 1;
7789
+ for (let found = 0; found !== -1; ) {
7790
+ const pattern = text1.substring(textLength - length);
7791
+ if (found = text2.indexOf(pattern), found === -1) return best;
7792
+ length += found, (found === 0 || text1.substring(textLength - length) === text2.substring(0, length)) && (best = length, length++);
7793
+ }
7794
+ return best;
7802
7795
  }
7803
- function isEdge(editor, point2, at) {
7804
- return isStart(editor, point2, at) || isEnd(editor, point2, at);
7796
+ function getCommonPrefix(text1, text2) {
7797
+ if (!text1 || !text2 || text1[0] !== text2[0]) return 0;
7798
+ let pointerMin = 0, pointerMax = Math.min(text1.length, text2.length), pointerMid = pointerMax, pointerStart = 0;
7799
+ for (; pointerMin < pointerMid; ) text1.substring(pointerStart, pointerMid) === text2.substring(pointerStart, pointerMid) ? (pointerMin = pointerMid, pointerStart = pointerMin) : pointerMax = pointerMid, pointerMid = Math.floor((pointerMax - pointerMin) / 2 + pointerMin);
7800
+ return pointerMid;
7805
7801
  }
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;
7802
+ function getCommonSuffix(text1, text2) {
7803
+ if (!text1 || !text2 || text1[text1.length - 1] !== text2[text2.length - 1]) return 0;
7804
+ let pointerMin = 0, pointerMax = Math.min(text1.length, text2.length), pointerMid = pointerMax, pointerEnd = 0;
7805
+ 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);
7806
+ return pointerMid;
7820
7807
  }
7821
- function isNormalizing(editor) {
7822
- return editor.normalizing;
7808
+ function isHighSurrogate(char) {
7809
+ const charCode = char.charCodeAt(0);
7810
+ return charCode >= 55296 && charCode <= 56319;
7823
7811
  }
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
- });
7812
+ function isLowSurrogate(char) {
7813
+ const charCode = char.charCodeAt(0);
7814
+ return charCode >= 56320 && charCode <= 57343;
7815
+ }
7816
+ function bisect(text1, text2, deadline) {
7817
+ 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);
7818
+ for (let x = 0; x < vLength; x++) v1[x] = -1, v2[x] = -1;
7819
+ v1[vOffset + 1] = 0, v2[vOffset + 1] = 0;
7820
+ const delta = text1Length - text2Length, front = delta % 2 !== 0;
7821
+ let k1start = 0, k1end = 0, k2start = 0, k2end = 0;
7822
+ for (let d = 0; d < maxD && !(Date.now() > deadline); d++) {
7823
+ for (let k1 = -d + k1start; k1 <= d - k1end; k1 += 2) {
7824
+ const k1Offset = vOffset + k1;
7825
+ let x1;
7826
+ k1 === -d || k1 !== d && v1[k1Offset - 1] < v1[k1Offset + 1] ? x1 = v1[k1Offset + 1] : x1 = v1[k1Offset - 1] + 1;
7827
+ let y1 = x1 - k1;
7828
+ for (; x1 < text1Length && y1 < text2Length && text1.charAt(x1) === text2.charAt(y1); ) x1++, y1++;
7829
+ if (v1[k1Offset] = x1, x1 > text1Length) k1end += 2;
7830
+ else if (y1 > text2Length) k1start += 2;
7831
+ else if (front) {
7832
+ const k2Offset = vOffset + delta - k1;
7833
+ if (k2Offset >= 0 && k2Offset < vLength && v2[k2Offset] !== -1) {
7834
+ const x2 = text1Length - v2[k2Offset];
7835
+ if (x1 >= x2) return bisectSplit(text1, text2, x1, y1, deadline);
7871
7836
  }
7872
- iteration++, dirtyPaths = getDirtyPaths2(editor);
7873
7837
  }
7874
- });
7838
+ }
7839
+ for (let k2 = -d + k2start; k2 <= d - k2end; k2 += 2) {
7840
+ const k2Offset = vOffset + k2;
7841
+ let x2;
7842
+ k2 === -d || k2 !== d && v2[k2Offset - 1] < v2[k2Offset + 1] ? x2 = v2[k2Offset + 1] : x2 = v2[k2Offset - 1] + 1;
7843
+ let y2 = x2 - k2;
7844
+ for (; x2 < text1Length && y2 < text2Length && text1.charAt(text1Length - x2 - 1) === text2.charAt(text2Length - y2 - 1); ) x2++, y2++;
7845
+ if (v2[k2Offset] = x2, x2 > text1Length) k2end += 2;
7846
+ else if (y2 > text2Length) k2start += 2;
7847
+ else if (!front) {
7848
+ const k1Offset = vOffset + delta - k2;
7849
+ if (k1Offset >= 0 && k1Offset < vLength && v1[k1Offset] !== -1) {
7850
+ const x1 = v1[k1Offset], y1 = vOffset + x1 - k1Offset;
7851
+ if (x2 = text1Length - x2, x1 >= x2) return bisectSplit(text1, text2, x1, y1, deadline);
7852
+ }
7853
+ }
7854
+ }
7875
7855
  }
7856
+ return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]];
7876
7857
  }
7877
- function setNormalizing(editor, isNormalizing2) {
7878
- editor.normalizing = isNormalizing2;
7858
+ function bisectSplit(text1, text2, x, y, deadline) {
7859
+ const text1a = text1.substring(0, x), text2a = text2.substring(0, y), text1b = text1.substring(x), text2b = text2.substring(y), diffs = doDiff(text1a, text2a, {
7860
+ checkLines: !1,
7861
+ deadline
7862
+ }), diffsb = doDiff(text1b, text2b, {
7863
+ checkLines: !1,
7864
+ deadline
7865
+ });
7866
+ return diffs.concat(diffsb);
7879
7867
  }
7880
- function withoutNormalizing(editor, fn) {
7881
- const value = isNormalizing(editor);
7882
- setNormalizing(editor, !1);
7883
- try {
7884
- fn();
7885
- } finally {
7886
- setNormalizing(editor, value);
7868
+ function findHalfMatch(text1, text2, timeout = 1) {
7869
+ if (timeout <= 0) return null;
7870
+ const longText = text1.length > text2.length ? text1 : text2, shortText = text1.length > text2.length ? text2 : text1;
7871
+ if (longText.length < 4 || shortText.length * 2 < longText.length) return null;
7872
+ const halfMatch1 = halfMatchI(longText, shortText, Math.ceil(longText.length / 4)), halfMatch2 = halfMatchI(longText, shortText, Math.ceil(longText.length / 2));
7873
+ let halfMatch;
7874
+ if (halfMatch1 && halfMatch2) halfMatch = halfMatch1[4].length > halfMatch2[4].length ? halfMatch1 : halfMatch2;
7875
+ else {
7876
+ if (!halfMatch1 && !halfMatch2) return null;
7877
+ halfMatch2 ? halfMatch1 || (halfMatch = halfMatch2) : halfMatch = halfMatch1;
7887
7878
  }
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];
7879
+ if (!halfMatch) throw new Error("Unable to find a half match.");
7880
+ let text1A, text1B, text2A, text2B;
7881
+ 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]);
7882
+ const midCommon = halfMatch[4];
7883
+ return [text1A, text1B, text2A, text2B, midCommon];
7901
7884
  }
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"));
7885
+ function halfMatchI(longText, shortText, i) {
7886
+ const seed = longText.slice(i, i + Math.floor(longText.length / 4));
7887
+ let j = -1, bestCommon = "", bestLongTextA, bestLongTextB, bestShortTextA, bestShortTextB;
7888
+ for (; (j = shortText.indexOf(seed, j + 1)) !== -1; ) {
7889
+ const prefixLength = getCommonPrefix(longText.slice(i), shortText.slice(j)), suffixLength = getCommonSuffix(longText.slice(0, i), shortText.slice(0, j));
7890
+ 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
7891
  }
7911
- for (const ref of editor.pointRefs) {
7912
- const current = ref.current;
7913
- current && (ref.current = transformPointForSplit(current, path2, position, ref.affinity ?? "forward"));
7892
+ return bestCommon.length * 2 >= longText.length ? [bestLongTextA || "", bestLongTextB || "", bestShortTextA || "", bestShortTextB || "", bestCommon || ""] : null;
7893
+ }
7894
+ function charsToLines(diffs, lineArray) {
7895
+ for (let x = 0; x < diffs.length; x++) {
7896
+ const chars = diffs[x][1], text = [];
7897
+ for (let y = 0; y < chars.length; y++) text[y] = lineArray[chars.charCodeAt(y)];
7898
+ diffs[x][1] = text.join("");
7914
7899
  }
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());
7900
+ }
7901
+ function linesToChars(textA, textB) {
7902
+ const lineArray = [], lineHash = {};
7903
+ lineArray[0] = "";
7904
+ function diffLinesToMunge(text) {
7905
+ let chars = "", lineStart = 0, lineEnd = -1, lineArrayLength = lineArray.length;
7906
+ for (; lineEnd < text.length - 1; ) {
7907
+ lineEnd = text.indexOf(`
7908
+ `, lineStart), lineEnd === -1 && (lineEnd = text.length - 1);
7909
+ let line = text.slice(lineStart, lineEnd + 1);
7910
+ (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
7911
  }
7912
+ return chars;
7924
7913
  }
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
7914
+ let maxLines = 4e4;
7915
+ const chars1 = diffLinesToMunge(textA);
7916
+ maxLines = 65535;
7917
+ const chars2 = diffLinesToMunge(textB);
7918
+ return {
7919
+ chars1,
7920
+ chars2,
7921
+ lineArray
8002
7922
  };
8003
7923
  }
8004
- function applyInsertNodeAtPath(editor, node, path2) {
8005
- editor.apply({
8006
- type: "insert_node",
8007
- path: path2,
8008
- node
7924
+ function doLineModeDiff(textA, textB, opts) {
7925
+ let text1 = textA, text2 = textB;
7926
+ const a = linesToChars(text1, text2);
7927
+ text1 = a.chars1, text2 = a.chars2;
7928
+ const linearray = a.lineArray;
7929
+ let diffs = doDiff(text1, text2, {
7930
+ checkLines: !1,
7931
+ deadline: opts.deadline
8009
7932
  });
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
7933
+ charsToLines(diffs, linearray), diffs = cleanupSemantic(diffs), diffs.push([DIFF_EQUAL, ""]);
7934
+ let pointer = 0, countDelete = 0, countInsert = 0, textDelete = "", textInsert = "";
7935
+ for (; pointer < diffs.length; ) {
7936
+ switch (diffs[pointer][0]) {
7937
+ case DIFF_INSERT:
7938
+ countInsert++, textInsert += diffs[pointer][1];
7939
+ break;
7940
+ case DIFF_DELETE:
7941
+ countDelete++, textDelete += diffs[pointer][1];
7942
+ break;
7943
+ case DIFF_EQUAL:
7944
+ if (countDelete >= 1 && countInsert >= 1) {
7945
+ diffs.splice(pointer - countDelete - countInsert, countDelete + countInsert), pointer = pointer - countDelete - countInsert;
7946
+ const aa = doDiff(textDelete, textInsert, {
7947
+ checkLines: !1,
7948
+ deadline: opts.deadline
7949
+ });
7950
+ for (let j = aa.length - 1; j >= 0; j--) diffs.splice(pointer, 0, aa[j]);
7951
+ pointer += aa.length;
8101
7952
  }
8102
- } : null;
7953
+ countInsert = 0, countDelete = 0, textDelete = "", textInsert = "";
7954
+ break;
7955
+ default:
7956
+ throw new Error("Unknown diff operation.");
8103
7957
  }
7958
+ pointer++;
8104
7959
  }
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
- }
7960
+ return diffs.pop(), diffs;
8148
7961
  }
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;
7962
+ function computeDiff(text1, text2, opts) {
7963
+ let diffs;
7964
+ if (!text1) return [[DIFF_INSERT, text2]];
7965
+ if (!text2) return [[DIFF_DELETE, text1]];
7966
+ const longtext = text1.length > text2.length ? text1 : text2, shorttext = text1.length > text2.length ? text2 : text1, i = longtext.indexOf(shorttext);
7967
+ 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;
7968
+ if (shorttext.length === 1) return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]];
7969
+ const halfMatch = findHalfMatch(text1, text2);
7970
+ if (halfMatch) {
7971
+ 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);
7972
+ return diffsA.concat([[DIFF_EQUAL, midCommon]], diffsB);
8162
7973
  }
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
- };
7974
+ return opts.checkLines && text1.length > 100 && text2.length > 100 ? doLineModeDiff(text1, text2, opts) : bisect(text1, text2, opts.deadline);
8172
7975
  }
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;
7976
+ 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, {
7977
+ enumerable: !0,
7978
+ configurable: !0,
7979
+ writable: !0,
7980
+ value
7981
+ }) : obj[key] = value, __spreadValues$2 = (a, b) => {
7982
+ for (var prop in b || (b = {})) __hasOwnProp$2.call(b, prop) && __defNormalProp$2(a, prop, b[prop]);
7983
+ if (__getOwnPropSymbols$2) for (var prop of __getOwnPropSymbols$2(b)) __propIsEnum$2.call(b, prop) && __defNormalProp$2(a, prop, b[prop]);
7984
+ return a;
7985
+ };
7986
+ const DIFF_DELETE = -1, DIFF_INSERT = 1, DIFF_EQUAL = 0;
7987
+ function diff(textA, textB, opts) {
7988
+ if (textA === null || textB === null) throw new Error("Null input. (diff)");
7989
+ const diffs = doDiff(textA, textB, createInternalOpts(opts || {}));
7990
+ return adjustDiffForSurrogatePairs(diffs), diffs;
8176
7991
  }
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
- };
7992
+ function doDiff(textA, textB, options) {
7993
+ let text1 = textA, text2 = textB;
7994
+ if (text1 === text2) return text1 ? [[DIFF_EQUAL, text1]] : [];
7995
+ let commonlength = getCommonPrefix(text1, text2);
7996
+ const commonprefix = text1.substring(0, commonlength);
7997
+ text1 = text1.substring(commonlength), text2 = text2.substring(commonlength), commonlength = getCommonSuffix(text1, text2);
7998
+ const commonsuffix = text1.substring(text1.length - commonlength);
7999
+ text1 = text1.substring(0, text1.length - commonlength), text2 = text2.substring(0, text2.length - commonlength);
8000
+ let diffs = computeDiff(text1, text2, options);
8001
+ return commonprefix && diffs.unshift([DIFF_EQUAL, commonprefix]), commonsuffix && diffs.push([DIFF_EQUAL, commonsuffix]), diffs = cleanupMerge(diffs), diffs;
8186
8002
  }
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
- });
8003
+ function createDeadLine(timeout) {
8004
+ let t = 1;
8005
+ return typeof timeout < "u" && (t = timeout <= 0 ? Number.MAX_VALUE : timeout), Date.now() + t * 1e3;
8202
8006
  }
8203
- function withNormalizeNode(editor, fn) {
8204
- const prev = editor.isNormalizingNode;
8205
- editor.isNormalizingNode = !0, fn(), editor.isNormalizingNode = prev;
8007
+ function createInternalOpts(opts) {
8008
+ return __spreadValues$2({
8009
+ checkLines: !0,
8010
+ deadline: createDeadLine(opts.timeout || 1)
8011
+ }, opts);
8206
8012
  }
8207
- function withoutPatching(editor, fn) {
8208
- const prev = editor.isPatching;
8209
- editor.isPatching = !1, fn(), editor.isPatching = prev;
8013
+ function combineChar(data, char, dir) {
8014
+ return dir === 1 ? data + char : char + data;
8210
8015
  }
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;
8016
+ function splitChar(data, dir) {
8017
+ return dir === 1 ? [data.substring(0, data.length - 1), data[data.length - 1]] : [data.substring(1), data[0]];
8439
8018
  }
8440
- function isLowSurrogate(char) {
8441
- const charCode = char.charCodeAt(0);
8442
- return charCode >= 56320 && charCode <= 57343;
8019
+ function hasSharedChar(diffs, i, j, dir) {
8020
+ 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
8021
  }
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);
8022
+ function deisolateChar(diffs, i, dir) {
8023
+ const inv = dir === 1 ? -1 : 1;
8024
+ let insertIdx = null, deleteIdx = null, j = i + dir;
8025
+ for (; j >= 0 && j < diffs.length && (insertIdx === null || deleteIdx === null); j += dir) {
8026
+ const [op, text2] = diffs[j];
8027
+ if (text2.length !== 0) {
8028
+ if (op === DIFF_INSERT) {
8029
+ insertIdx === null && (insertIdx = j);
8030
+ continue;
8031
+ } else if (op === DIFF_DELETE) {
8032
+ deleteIdx === null && (deleteIdx = j);
8033
+ continue;
8034
+ } else if (op === DIFF_EQUAL) {
8035
+ if (insertIdx === null && deleteIdx === null) {
8036
+ const [rest, char2] = splitChar(diffs[i][1], dir);
8037
+ diffs[i][1] = rest, diffs[j][1] = combineChar(diffs[j][1], char2, inv);
8038
+ return;
8480
8039
  }
8040
+ break;
8481
8041
  }
8482
8042
  }
8483
8043
  }
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;
8044
+ if (insertIdx !== null && deleteIdx !== null && hasSharedChar(diffs, insertIdx, deleteIdx, dir)) {
8045
+ const [insertText2, insertChar] = splitChar(diffs[insertIdx][1], inv), [deleteText2] = splitChar(diffs[deleteIdx][1], inv);
8046
+ diffs[insertIdx][1] = insertText2, diffs[deleteIdx][1] = deleteText2, diffs[i][1] = combineChar(diffs[i][1], insertChar, dir);
8047
+ return;
8506
8048
  }
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];
8049
+ const [text, char] = splitChar(diffs[i][1], dir);
8050
+ 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
8051
  }
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));
8052
+ function adjustDiffForSurrogatePairs(diffs) {
8053
+ for (let i = 0; i < diffs.length; i++) {
8054
+ const [diffType, diffText] = diffs[i];
8055
+ if (diffText.length === 0) continue;
8056
+ const firstChar = diffText[0], lastChar = diffText[diffText.length - 1];
8057
+ isHighSurrogate(lastChar) && diffType === DIFF_EQUAL && deisolateChar(diffs, i, 1), isLowSurrogate(firstChar) && diffType === DIFF_EQUAL && deisolateChar(diffs, i, -1);
8519
8058
  }
8520
- return bestCommon.length * 2 >= longText.length ? [bestLongTextA || "", bestLongTextB || "", bestShortTextA || "", bestShortTextB || "", bestCommon || ""] : null;
8059
+ for (let i = 0; i < diffs.length; i++) diffs[i][1].length === 0 && diffs.splice(i, 1);
8521
8060
  }
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("");
8061
+ function cleanupSemantic(rawDiffs) {
8062
+ let diffs = rawDiffs.map((diff2) => cloneDiff(diff2)), hasChanges = !1;
8063
+ const equalities = [];
8064
+ let equalitiesLength = 0, lastEquality = null, pointer = 0, lengthInsertions1 = 0, lengthDeletions1 = 0, lengthInsertions2 = 0, lengthDeletions2 = 0;
8065
+ 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++;
8066
+ for (hasChanges && (diffs = cleanupMerge(diffs)), diffs = cleanupSemanticLossless(diffs), pointer = 1; pointer < diffs.length; ) {
8067
+ if (diffs[pointer - 1][0] === DIFF_DELETE && diffs[pointer][0] === DIFF_INSERT) {
8068
+ const deletion = diffs[pointer - 1][1], insertion = diffs[pointer][1], overlapLength1 = getCommonOverlap(deletion, insertion), overlapLength2 = getCommonOverlap(insertion, deletion);
8069
+ 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++;
8070
+ }
8071
+ pointer++;
8527
8072
  }
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;
8073
+ return diffs;
8702
8074
  }
8703
8075
  const nonAlphaNumericRegex = /[^a-zA-Z0-9]/, whitespaceRegex = /\s/, linebreakRegex = /[\r\n]/, blanklineEndRegex = /\n\r?\n$/, blanklineStartRegex = /^\r?\n\r?\n/;
8704
8076
  function cleanupSemanticLossless(rawDiffs) {
@@ -9038,6 +8410,35 @@ function parse(textline) {
9038
8410
  function toInt(num) {
9039
8411
  return parseInt(num, 10);
9040
8412
  }
8413
+ function pathRef(editor, path2, options = {}) {
8414
+ const {
8415
+ affinity = "forward"
8416
+ } = options, ref = {
8417
+ current: path2,
8418
+ affinity,
8419
+ unref() {
8420
+ const {
8421
+ current
8422
+ } = ref;
8423
+ return editor.pathRefs.delete(ref), ref.current = null, current;
8424
+ }
8425
+ };
8426
+ return editor.pathRefs.add(ref), ref;
8427
+ }
8428
+ function applySetNode(editor, props, path2) {
8429
+ const nodeEntry = getNode(editor, path2);
8430
+ if (!nodeEntry)
8431
+ return;
8432
+ const nodeRecord = nodeEntry.node, propsRecord = props, properties = {}, newProperties = {};
8433
+ for (const key of Object.keys(propsRecord))
8434
+ propsRecord[key] !== nodeRecord[key] && (nodeRecord.hasOwnProperty(key) && (properties[key] = nodeRecord[key]), propsRecord[key] != null && (newProperties[key] = propsRecord[key]));
8435
+ (Object.keys(newProperties).length > 0 || Object.keys(properties).length > 0) && editor.apply({
8436
+ type: "set_node",
8437
+ path: path2,
8438
+ properties,
8439
+ newProperties
8440
+ });
8441
+ }
9041
8442
  function toSlateBlock(block, {
9042
8443
  schemaTypes
9043
8444
  }) {
@@ -9283,7 +8684,7 @@ function setPatch(editor, patch) {
9283
8684
  } else
9284
8685
  return applySetNode(editor, updatedBlock, [block.index]), !0;
9285
8686
  }
9286
- if (blockIsTextBlock && patch.path[1] !== "children") {
8687
+ if (blockIsTextBlock && (patch.path.length === 2 || patch.path[1] !== "children")) {
9287
8688
  const updatedBlock = applyAll(block.node, [{
9288
8689
  ...patch,
9289
8690
  path: patch.path.slice(1)
@@ -9568,13 +8969,13 @@ function setNodePatch(schema, children, operation) {
9568
8969
  const patches = [], _key = operation.newProperties._key;
9569
8970
  _key !== void 0 && patches.push(set(_key, [blockIndex, "_key"]));
9570
8971
  for (const [key, propertyValue] of Object.entries(operation.newProperties))
9571
- key === "_key" || key === "children" || patches.push(set(propertyValue, [{
8972
+ key !== "_key" && patches.push(set(propertyValue, [{
9572
8973
  _key: block._key
9573
8974
  }, key]));
9574
8975
  for (const key of Object.keys(operation.properties))
9575
- key === "_key" || key === "children" || key in operation.newProperties || patches.push(unset([{
8976
+ key !== "_key" && (key in operation.newProperties || patches.push(unset([{
9576
8977
  _key: block._key
9577
- }, key]));
8978
+ }, key])));
9578
8979
  return patches;
9579
8980
  }
9580
8981
  } else if (operation.path.length === 2) {
@@ -9593,7 +8994,7 @@ function setNodePatch(schema, children, operation) {
9593
8994
  _key: blockKey
9594
8995
  }, "children", block.children.indexOf(child), "_key"]));
9595
8996
  for (const [key, propertyValue] of Object.entries(operation.newProperties))
9596
- key === "_key" || key === "children" || patches.push(set(propertyValue, [{
8997
+ key !== "_key" && patches.push(set(propertyValue, [{
9597
8998
  _key: blockKey
9598
8999
  }, "children", {
9599
9000
  _key: childKey
@@ -9673,6 +9074,75 @@ function removeNodePatch(schema, beforeValue, operation) {
9673
9074
  } else
9674
9075
  return [];
9675
9076
  }
9077
+ function isNormalizing(editor) {
9078
+ return editor.normalizing;
9079
+ }
9080
+ function setNormalizing(editor, isNormalizing2) {
9081
+ editor.normalizing = isNormalizing2;
9082
+ }
9083
+ function withoutNormalizing(editor, fn) {
9084
+ const value = isNormalizing(editor);
9085
+ setNormalizing(editor, !1);
9086
+ try {
9087
+ fn();
9088
+ } finally {
9089
+ setNormalizing(editor, value);
9090
+ }
9091
+ normalize(editor);
9092
+ }
9093
+ function normalize(editor, options = {}) {
9094
+ const {
9095
+ force = !1,
9096
+ operation
9097
+ } = options, getDirtyPaths = (editor2) => editor2.dirtyPaths, getDirtyPathKeys = (editor2) => editor2.dirtyPathKeys, popDirtyPath = (editor2) => {
9098
+ const path2 = getDirtyPaths(editor2).pop(), key = path2.length === 1 ? String(path2[0]) : path2.length === 2 ? `${path2[0]},${path2[1]}` : path2.join(",");
9099
+ return getDirtyPathKeys(editor2).delete(key), path2;
9100
+ };
9101
+ if (isNormalizing(editor)) {
9102
+ if (force) {
9103
+ const allPaths = Array.from(getNodes(editor), (entry) => entry.path), allPathKeys = new Set(allPaths.map((p) => p.join(",")));
9104
+ editor.dirtyPaths = allPaths, editor.dirtyPathKeys = allPathKeys;
9105
+ }
9106
+ getDirtyPaths(editor).length !== 0 && withoutNormalizing(editor, () => {
9107
+ for (const dirtyPath of getDirtyPaths(editor))
9108
+ if (dirtyPath.length !== 0 && hasNode(editor, dirtyPath)) {
9109
+ const entry = getNode(editor, dirtyPath);
9110
+ if (!entry)
9111
+ continue;
9112
+ const entryNode = entry.node;
9113
+ isTextBlock({
9114
+ schema: editor.schema
9115
+ }, entryNode) && entryNode.children.length === 0 && (editor.isNormalizingNode = !0, editor.normalizeNode([entry.node, entry.path], {
9116
+ operation
9117
+ }), editor.isNormalizingNode = !1);
9118
+ }
9119
+ let dirtyPaths = getDirtyPaths(editor);
9120
+ const initialDirtyPathsLength = dirtyPaths.length;
9121
+ let iteration = 0;
9122
+ for (; dirtyPaths.length !== 0; ) {
9123
+ if (!editor.shouldNormalize({
9124
+ dirtyPaths,
9125
+ iteration,
9126
+ initialDirtyPathsLength,
9127
+ operation
9128
+ }))
9129
+ return;
9130
+ const dirtyPath = popDirtyPath(editor);
9131
+ if (dirtyPath.length === 0)
9132
+ editor.isNormalizingNode = !0, editor.normalizeNode([editor, dirtyPath], {
9133
+ operation
9134
+ }), editor.isNormalizingNode = !1;
9135
+ else if (hasNode(editor, dirtyPath)) {
9136
+ const entry = getNode(editor, dirtyPath);
9137
+ entry && (editor.isNormalizingNode = !0, editor.normalizeNode([entry.node, entry.path], {
9138
+ operation
9139
+ }), editor.isNormalizingNode = !1);
9140
+ }
9141
+ iteration++, dirtyPaths = getDirtyPaths(editor);
9142
+ }
9143
+ });
9144
+ }
9145
+ }
9676
9146
  function withRemoteChanges(editor, fn) {
9677
9147
  const prev = editor.isProcessingRemoteChanges;
9678
9148
  editor.isProcessingRemoteChanges = !0, fn(), editor.isProcessingRemoteChanges = prev;
@@ -9681,6 +9151,10 @@ function pluginWithoutHistory(editor, fn) {
9681
9151
  const prev = editor.withHistory;
9682
9152
  editor.withHistory = !1, fn(), editor.withHistory = prev;
9683
9153
  }
9154
+ function withoutPatching(editor, fn) {
9155
+ const prev = editor.isPatching;
9156
+ editor.isPatching = !1, fn(), editor.isPatching = prev;
9157
+ }
9684
9158
  function createPatchesPlugin({
9685
9159
  editorActor,
9686
9160
  relayActor,
@@ -9772,136 +9246,8 @@ function createPatchesPlugin({
9772
9246
  }, editor;
9773
9247
  };
9774
9248
  }
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
- function updateSelectionPlugin({
9904
- editor,
9249
+ function updateSelectionPlugin({
9250
+ editor,
9905
9251
  editorActor
9906
9252
  }) {
9907
9253
  const updateSelection = () => {
@@ -9963,21 +9309,100 @@ const plugins = (editor, options) => {
9963
9309
  const e = editor, {
9964
9310
  editorActor,
9965
9311
  relayActor
9966
- } = options, uniqueKeysPlugin = createUniqueKeysPlugin(editorActor), schemaPlugin = createSchemaPlugin({
9967
- editorActor
9968
- }), patchesPlugin = createPatchesPlugin({
9312
+ } = options, patchesPlugin = createPatchesPlugin({
9969
9313
  editorActor,
9970
9314
  relayActor,
9971
9315
  subscriptions: options.subscriptions
9972
9316
  }), historyPlugin = createHistoryPlugin({
9973
9317
  editorActor,
9974
9318
  subscriptions: options.subscriptions
9975
- }), normalizationPlugin = createNormalizationPlugin(editorActor);
9976
- return createBehaviorApiPlugin(editorActor)(schemaPlugin(uniqueKeysPlugin(normalizationPlugin(historyPlugin(patchesPlugin(updateValuePlugin(editorActor.getSnapshot().context, updateSelectionPlugin({
9319
+ });
9320
+ return createBehaviorApiPlugin(editorActor)(historyPlugin(patchesPlugin(updateValuePlugin(editorActor.getSnapshot().context, updateSelectionPlugin({
9977
9321
  editorActor,
9978
9322
  editor: e
9979
- }))))))));
9980
- }, PathRef = {
9323
+ })))));
9324
+ };
9325
+ function pathLevels(path2) {
9326
+ const list = [];
9327
+ for (let i = 0; i <= path2.length; i++)
9328
+ list.push(path2.slice(0, i));
9329
+ return list;
9330
+ }
9331
+ function getChildFieldName(context, path2) {
9332
+ let nodeChildren = getNodeChildren({
9333
+ schema: context.schema,
9334
+ editableTypes: context.editableTypes
9335
+ }, {
9336
+ value: context.value
9337
+ }, void 0, "");
9338
+ for (let i = 0; i < path2.length; i++) {
9339
+ if (!nodeChildren)
9340
+ return;
9341
+ const index = path2.at(i);
9342
+ if (index === void 0)
9343
+ return;
9344
+ const node = nodeChildren.children.at(index);
9345
+ if (!node)
9346
+ return;
9347
+ if (i === path2.length - 1)
9348
+ return getNodeChildren({
9349
+ schema: context.schema,
9350
+ editableTypes: context.editableTypes
9351
+ }, node, nodeChildren.scope, nodeChildren.scopePath)?.fieldName;
9352
+ nodeChildren = getNodeChildren({
9353
+ schema: context.schema,
9354
+ editableTypes: context.editableTypes
9355
+ }, node, nodeChildren.scope, nodeChildren.scopePath);
9356
+ }
9357
+ }
9358
+ function getDirtyIndexedPaths(context, op) {
9359
+ switch (op.type) {
9360
+ case "insert_text":
9361
+ case "remove_text":
9362
+ case "set_node": {
9363
+ const {
9364
+ path: path2
9365
+ } = op, levels = pathLevels(path2);
9366
+ if (op.type === "set_node") {
9367
+ const childFieldName = getChildFieldName(context, path2);
9368
+ if (childFieldName) {
9369
+ const newChildren = op.newProperties[childFieldName];
9370
+ if (Array.isArray(newChildren))
9371
+ for (let i = 0; i < newChildren.length; i++) {
9372
+ const child = newChildren[i];
9373
+ if (typeof child != "object" || child === null)
9374
+ continue;
9375
+ const childPath = [...path2, i];
9376
+ levels.push(childPath);
9377
+ for (const entry of getNodeDescendants(context, child))
9378
+ levels.push(childPath.concat(entry.path));
9379
+ }
9380
+ }
9381
+ }
9382
+ return levels;
9383
+ }
9384
+ case "insert_node": {
9385
+ const {
9386
+ node,
9387
+ path: path2
9388
+ } = op, levels = pathLevels(path2);
9389
+ if (isSpan(context, node))
9390
+ return levels;
9391
+ for (const entry of getNodeDescendants(context, node))
9392
+ levels.push(path2.concat(entry.path));
9393
+ return levels;
9394
+ }
9395
+ case "remove_node": {
9396
+ const {
9397
+ path: path2
9398
+ } = op;
9399
+ return [...pathLevels(path2).slice(0, -1)];
9400
+ }
9401
+ default:
9402
+ return [];
9403
+ }
9404
+ }
9405
+ const PathRef = {
9981
9406
  transform(ref, op) {
9982
9407
  const {
9983
9408
  current
@@ -10062,7 +9487,7 @@ function replaceChildren(xs, index, removeCount, ...newValues) {
10062
9487
  }
10063
9488
  const removeChildren = replaceChildren, modifyDescendant = (root, path2, schema, f) => {
10064
9489
  if (path2.length === 0)
10065
- throw new Error("Cannot modify the editor");
9490
+ return;
10066
9491
  const editableTypes = isEditor(root) ? root.editableTypes : /* @__PURE__ */ new Set(), context = {
10067
9492
  schema,
10068
9493
  editableTypes
@@ -10070,28 +9495,42 @@ const removeChildren = replaceChildren, modifyDescendant = (root, path2, schema,
10070
9495
  schema
10071
9496
  }, root) ? root : void 0;
10072
9497
  if (!typedRoot)
10073
- throw new Error("Cannot modify descendant: root has no children");
9498
+ return;
10074
9499
  const nodeEntry = getNode({
10075
9500
  ...context,
10076
9501
  value: typedRoot.children
10077
9502
  }, path2);
10078
9503
  if (!nodeEntry)
10079
- throw new Error(`Cannot find a descendant at path [${path2}]`);
9504
+ return;
10080
9505
  const node = nodeEntry.node, slicedPath = path2.slice();
10081
9506
  let modifiedNode = f(node);
9507
+ const fieldNames = [];
9508
+ {
9509
+ let currentNode = {
9510
+ value: typedRoot.children
9511
+ }, scope, scopePath = "";
9512
+ for (let i = 0; i < path2.length; i++) {
9513
+ const result = getNodeChildren(context, currentNode, scope, scopePath);
9514
+ if (!result)
9515
+ return;
9516
+ fieldNames.push(result.fieldName);
9517
+ const child = result.children.at(path2.at(i));
9518
+ if (!child)
9519
+ return;
9520
+ currentNode = child, scope = result.scope, scopePath = result.scopePath;
9521
+ }
9522
+ }
10082
9523
  for (; slicedPath.length > 1; ) {
10083
- const index2 = slicedPath.pop(), ancestorEntry = getNode({
9524
+ const index2 = slicedPath.pop(), level = slicedPath.length, fieldName = fieldNames.at(level), ancestorEntry = getNode({
10084
9525
  ...context,
10085
9526
  value: typedRoot.children
10086
9527
  }, slicedPath);
10087
9528
  if (!ancestorEntry)
10088
- throw new Error(`Cannot find ancestor at path [${slicedPath}]`);
10089
- const ancestorNode = ancestorEntry.node;
9529
+ return;
9530
+ const ancestorNode = ancestorEntry.node, ancestorRecord = ancestorNode, currentChildren = Array.isArray(ancestorRecord[fieldName]) ? ancestorRecord[fieldName] : [];
10090
9531
  modifiedNode = {
10091
9532
  ...ancestorNode,
10092
- children: replaceChildren(isTextBlock({
10093
- schema
10094
- }, ancestorNode) ? ancestorNode.children : [], index2, 1, modifiedNode)
9533
+ [fieldName]: replaceChildren(currentChildren, index2, 1, modifiedNode)
10095
9534
  };
10096
9535
  }
10097
9536
  const index = slicedPath.pop(), newRootChildren = replaceChildren(isEditor(root) || isTextBlock({
@@ -10101,35 +9540,32 @@ const removeChildren = replaceChildren, modifyDescendant = (root, path2, schema,
10101
9540
  }, modifyChildren = (root, path2, schema, f) => {
10102
9541
  path2.length === 0 ? root.children = f(isEditor(root) || isTextBlock({
10103
9542
  schema
10104
- }, root) ? root.children : []) : modifyDescendant(root, path2, schema, (node) => {
10105
- if (isSpan({
10106
- schema
10107
- }, node) || isObjectNode({
9543
+ }, root) ? root.children : []) : modifyDescendant(root, path2, schema, (node) => ({
9544
+ ...node,
9545
+ children: f(isTextBlock({
10108
9546
  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
- });
9547
+ }, node) ? node.children : [])
9548
+ }));
9549
+ }, modifyLeaf = (root, path2, schema, f) => modifyDescendant(root, path2, schema, (node) => isSpan({
9550
+ schema
9551
+ }, node) ? f(node) : node);
10125
9552
  function applyOperation(editor, op) {
10126
9553
  let transformSelection = !1;
10127
9554
  switch (op.type) {
10128
9555
  case "insert_node": {
10129
9556
  const {
10130
- path: path2,
9557
+ path: path2
9558
+ } = op;
9559
+ let {
10131
9560
  node
10132
9561
  } = op;
9562
+ if (!editor.isProcessingRemoteChanges && !editor.isUndoing && !editor.isRedoing && node._key !== void 0) {
9563
+ const insertParentPath = parentPath(path2);
9564
+ (insertParentPath.length === 0 ? editor.children : getChildren(editor, insertParentPath).map((entry) => entry.node)).some((sibling) => sibling._key === node._key) && (node = {
9565
+ ...node,
9566
+ _key: editor.keyGenerator()
9567
+ }, op.node = node);
9568
+ }
10133
9569
  modifyChildren(editor, parentPath(path2), editor.schema, (children) => {
10134
9570
  const index = path2[path2.length - 1];
10135
9571
  if (index > children.length)
@@ -10226,15 +9662,13 @@ function applyOperation(editor, op) {
10226
9662
  ...node
10227
9663
  };
10228
9664
  for (const key in newProperties) {
10229
- if (key === "children")
10230
- throw new Error(`Cannot set the "${key}" property of nodes!`);
10231
9665
  const value = newProperties[key];
10232
9666
  value == null ? delete newNode[key] : newNode[key] = value;
10233
9667
  }
10234
9668
  for (const key in properties)
10235
9669
  newProperties.hasOwnProperty(key) || delete newNode[key];
10236
9670
  return newNode;
10237
- });
9671
+ }), transformSelection = !0;
10238
9672
  break;
10239
9673
  }
10240
9674
  case "set_selection": {
@@ -10278,15 +9712,6 @@ function applyOperation(editor, op) {
10278
9712
  rangeEquals(selection, editor.selection) || (editor.selection = selection);
10279
9713
  }
10280
9714
  }
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
9715
  function updateDirtyPaths(editor, newDirtyPaths, transform) {
10291
9716
  const oldDirtyPaths = editor.dirtyPaths, oldDirtyPathKeys = editor.dirtyPathKeys;
10292
9717
  let dirtyPaths, dirtyPathKeys;
@@ -10315,607 +9740,640 @@ const apply = (editor, op) => {
10315
9740
  PointRef.transform(ref, op);
10316
9741
  for (const ref of editor.rangeRefs)
10317
9742
  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, {
9743
+ 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;
9744
+ if (updateDirtyPaths(editor, getDirtyIndexedPaths(editor, op), transform), applyOperation(editor, op), editor.operations.push(op), normalize(editor, {
10323
9745
  operation: op
10324
- }), op.type === "set_selection" && (editor.marks = null), editor.flushing || (editor.flushing = !0, Promise.resolve().then(() => {
9746
+ }), op.type === "set_selection")
9747
+ if (editor.marks = null, op.properties && op.newProperties && op.properties.anchor && op.properties.focus && op.newProperties.anchor && op.newProperties.focus) {
9748
+ const previousSelectionIsCollapsed = isCollapsedRange({
9749
+ anchor: op.properties.anchor,
9750
+ focus: op.properties.focus
9751
+ }), newSelectionIsCollapsed = isCollapsedRange({
9752
+ anchor: op.newProperties.anchor,
9753
+ focus: op.newProperties.focus
9754
+ });
9755
+ if (previousSelectionIsCollapsed && newSelectionIsCollapsed) {
9756
+ 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;
9757
+ !movedToNextSpan && !movedToPreviousSpan && (editor.decoratorState = {});
9758
+ }
9759
+ } else
9760
+ editor.decoratorState = {};
9761
+ editor.flushing || (editor.flushing = !0, Promise.resolve().then(() => {
10325
9762
  editor.flushing = !1, editor.onChange({
10326
9763
  operation: op
10327
9764
  }), editor.operations = [];
10328
9765
  }));
10329
9766
  };
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;
9767
+ function isEnd(editor, point2, at) {
9768
+ const editorEnd = end(editor, at);
9769
+ return pointEquals(point2, editorEnd);
10337
9770
  }
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;
9771
+ function isStart(editor, point2, at) {
9772
+ if (point2.offset !== 0)
9773
+ return !1;
9774
+ const editorStart = start(editor, at);
9775
+ return pointEquals(point2, editorStart);
10344
9776
  }
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)];
9777
+ function isEdge(editor, point2, at) {
9778
+ return isStart(editor, point2, at) || isEnd(editor, point2, at);
9779
+ }
9780
+ function rangeRefAffinities(range2, affinity) {
9781
+ if (affinity === "inward") {
9782
+ const isCollapsed = isCollapsedRange(range2);
9783
+ if (isForwardRange(range2)) {
9784
+ const anchorAffinity = "forward";
9785
+ return [anchorAffinity, isCollapsed ? anchorAffinity : "backward"];
9786
+ } else {
9787
+ const anchorAffinity = "backward";
9788
+ return [anchorAffinity, isCollapsed ? anchorAffinity : "forward"];
10371
9789
  }
10372
- default:
10373
- return [];
9790
+ } else return affinity === "outward" ? isForwardRange(range2) ? ["backward", "forward"] : ["forward", "backward"] : [affinity, affinity];
9791
+ }
9792
+ function applySplitNode(editor, path2, position) {
9793
+ const nodeEntry = getNode(editor, path2);
9794
+ if (!nodeEntry)
9795
+ return;
9796
+ const node = nodeEntry.node;
9797
+ for (const ref of editor.pathRefs) {
9798
+ const current = ref.current;
9799
+ current && (ref.current = transformPathForSplit(current, path2, position, ref.affinity ?? "forward"));
10374
9800
  }
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;
9801
+ for (const ref of editor.pointRefs) {
9802
+ const current = ref.current;
9803
+ current && (ref.current = transformPointForSplit(current, path2, position, ref.affinity ?? "forward"));
9804
+ }
9805
+ for (const ref of editor.rangeRefs) {
9806
+ const current = ref.current;
9807
+ if (current) {
9808
+ const [anchorAffinity, focusAffinity] = rangeRefAffinities(current, ref.affinity), anchor = transformPointForSplit(current.anchor, path2, position, anchorAffinity ?? "forward"), focus = transformPointForSplit(current.focus, path2, position, focusAffinity ?? "forward");
9809
+ anchor && focus ? ref.current = {
9810
+ anchor,
9811
+ focus
9812
+ } : (ref.current = null, ref.unref());
10387
9813
  }
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
9814
  }
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
9815
+ if (editor.selection) {
9816
+ const anchor = transformPointForSplit(editor.selection.anchor, path2, position, "forward"), focus = transformPointForSplit(editor.selection.focus, path2, position, "forward");
9817
+ anchor && focus && (editor.selection = {
9818
+ anchor,
9819
+ focus
9820
+ });
9821
+ }
9822
+ const pathRefs = new Set(editor.pathRefs), pointRefs = new Set(editor.pointRefs), rangeRefs = new Set(editor.rangeRefs);
9823
+ editor.pathRefs.clear(), editor.pointRefs.clear(), editor.rangeRefs.clear();
9824
+ const savedSelection = editor.selection;
9825
+ try {
9826
+ withoutNormalizing(editor, () => {
9827
+ if (isSpan({
9828
+ schema: editor.schema
9829
+ }, node)) {
9830
+ const {
9831
+ text: _text,
9832
+ ...properties
9833
+ } = node, afterText = node.text.slice(position), newNode = {
9834
+ ...properties,
9835
+ text: afterText
9836
+ };
9837
+ editor.apply({
9838
+ type: "remove_text",
9839
+ path: path2,
9840
+ offset: position,
9841
+ text: afterText
9842
+ }), editor.apply({
9843
+ type: "insert_node",
9844
+ path: nextPath(path2),
9845
+ node: newNode
10438
9846
  });
10439
- }
10440
- if (!includeObjectNodes) {
10441
- const atPath = path(editor, at), atEntry = getNode(editor, atPath);
10442
- if (atEntry && isObjectNode({
9847
+ } else if (isTextBlock({
10443
9848
  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;
9849
+ }, node)) {
9850
+ const {
9851
+ children: _children,
9852
+ ...properties
9853
+ } = node, children = node.children, afterChildren = children.slice(position), newNode = {
9854
+ ...properties,
9855
+ children: afterChildren
9856
+ };
9857
+ for (let i = children.length - 1; i >= position; i--)
10518
9858
  editor.apply({
10519
9859
  type: "remove_node",
10520
- path: path2,
10521
- node: removedNode
9860
+ path: [...path2, i],
9861
+ node: children[i]
10522
9862
  });
10523
- }
9863
+ editor.apply({
9864
+ type: "insert_node",
9865
+ path: nextPath(path2),
9866
+ node: newNode
9867
+ });
10524
9868
  }
10525
- }
9869
+ });
9870
+ } finally {
9871
+ editor.selection = savedSelection;
9872
+ for (const ref of pathRefs)
9873
+ editor.pathRefs.add(ref);
9874
+ for (const ref of pointRefs)
9875
+ editor.pointRefs.add(ref);
9876
+ for (const ref of rangeRefs)
9877
+ editor.rangeRefs.add(ref);
9878
+ }
9879
+ }
9880
+ function transformPathForSplit(path2, splitPath, position, affinity = "forward") {
9881
+ const p = [...path2];
9882
+ 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;
9883
+ }
9884
+ function transformPointForSplit(point2, splitPath, position, affinity = "forward") {
9885
+ let {
9886
+ path: path2,
9887
+ offset
9888
+ } = point2;
9889
+ return pathEquals(splitPath, path2) ? (position < offset || position === offset && affinity === "forward") && (offset -= position, path2 = transformPathForSplit(path2, splitPath, position, "forward")) : path2 = transformPathForSplit(path2, splitPath, position, affinity), {
9890
+ path: path2,
9891
+ offset
9892
+ };
9893
+ }
9894
+ function applyInsertNodeAtPath(editor, node, path2) {
9895
+ editor.apply({
9896
+ type: "insert_node",
9897
+ path: path2,
9898
+ node
10526
9899
  });
9900
+ const point2 = end(editor, path2);
9901
+ point2 && applySelect(editor, point2);
10527
9902
  }
10528
- function deleteText(editor, options = {}) {
9903
+ function applyInsertNodeAtPoint(editor, node, at) {
10529
9904
  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))
9905
+ const match2 = isSpan({
9906
+ schema: editor.schema
9907
+ }, node) ? (n) => isSpan({
9908
+ schema: editor.schema
9909
+ }, n) : (n) => isSpan({
9910
+ schema: editor.schema
9911
+ }, n) || isObjectNode({
9912
+ schema: editor.schema
9913
+ }, n), nodeEntry = getNode(editor, at.path), entry = nodeEntry && match2(nodeEntry.node) ? nodeEntry : void 0;
9914
+ if (!entry)
10566
9915
  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);
9916
+ const matchPath2 = entry.path, ref = pathRef(editor, matchPath2), isAtEnd = isEnd(editor, at, matchPath2);
9917
+ isEdge(editor, at, matchPath2) || applySplitNode(editor, at.path, at.offset);
9918
+ const path2 = ref.unref(), insertPath = isAtEnd ? nextPath(path2) : path2;
9919
+ editor.apply({
9920
+ type: "insert_node",
9921
+ path: insertPath,
9922
+ node
9923
+ });
9924
+ const point2 = end(editor, insertPath);
9925
+ point2 && applySelect(editor, point2);
9926
+ });
9927
+ }
9928
+ function previousPath(path2) {
9929
+ if (path2.length === 0)
9930
+ throw new Error(`Cannot get the previous path of a root path [${path2}], because it has no previous index.`);
9931
+ const last = path2[path2.length - 1];
9932
+ if (last <= 0)
9933
+ throw new Error(`Cannot get the previous path of a first child path [${path2}] because it would result in a negative index.`);
9934
+ return path2.slice(0, -1).concat(last - 1);
9935
+ }
9936
+ function applyMergeNode(editor, path2, position) {
9937
+ const nodeEntry = getNode(editor, path2);
9938
+ if (!nodeEntry)
9939
+ return;
9940
+ const node = nodeEntry.node, prevPath = previousPath(path2);
9941
+ for (const ref of editor.pathRefs) {
9942
+ const current = ref.current;
9943
+ current && (ref.current = transformPathForMerge(current, path2, position));
9944
+ }
9945
+ for (const ref of editor.pointRefs) {
9946
+ const current = ref.current;
9947
+ current && (ref.current = transformPointForMerge(current, path2, position));
9948
+ }
9949
+ for (const ref of editor.rangeRefs) {
9950
+ const current = ref.current;
9951
+ if (current) {
9952
+ const anchor = transformPointForMerge(current.anchor, path2, position), focus = transformPointForMerge(current.focus, path2, position);
9953
+ anchor && focus ? ref.current = {
9954
+ anchor,
9955
+ focus
9956
+ } : (ref.current = null, ref.unref());
10594
9957
  }
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
- }
9958
+ }
9959
+ if (editor.selection) {
9960
+ const anchor = transformPointForMerge(editor.selection.anchor, path2, position), focus = transformPointForMerge(editor.selection.focus, path2, position);
9961
+ anchor && focus && (editor.selection = {
9962
+ anchor,
9963
+ focus
9964
+ });
9965
+ }
9966
+ const pathRefs = new Set(editor.pathRefs), pointRefs = new Set(editor.pointRefs), rangeRefs = new Set(editor.rangeRefs);
9967
+ editor.pathRefs.clear(), editor.pointRefs.clear(), editor.rangeRefs.clear();
9968
+ const savedSelection = editor.selection, editorAny = editor, savedPendingDiffs = editorAny.pendingDiffs, savedPendingSelection = editorAny.pendingSelection, savedPendingAction = editorAny.pendingAction;
9969
+ 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) {
9970
+ const sel = savedPendingSelection, anchor = transformPointForMerge(sel.anchor, path2, position), focus = transformPointForMerge(sel.focus, path2, position);
9971
+ editorAny.pendingSelection = anchor && focus ? {
9972
+ anchor,
9973
+ focus
9974
+ } : null;
9975
+ }
9976
+ if (savedPendingAction && typeof savedPendingAction == "object" && "at" in savedPendingAction) {
9977
+ const action = savedPendingAction;
9978
+ if ("offset" in action.at && typeof action.at.offset == "number") {
9979
+ const at = transformPointForMerge(action.at, path2, position);
9980
+ editorAny.pendingAction = at ? {
9981
+ ...action,
9982
+ at
9983
+ } : null;
9984
+ } else if (isRange(action.at)) {
9985
+ const anchor = transformPointForMerge(action.at.anchor, path2, position), focus = transformPointForMerge(action.at.focus, path2, position);
9986
+ editorAny.pendingAction = anchor && focus ? {
9987
+ ...action,
9988
+ at: {
9989
+ anchor,
9990
+ focus
9991
+ }
9992
+ } : null;
10612
9993
  }
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",
9994
+ }
9995
+ const preTransformedPendingDiffs = editorAny.pendingDiffs, preTransformedPendingSelection = editorAny.pendingSelection, preTransformedPendingAction = editorAny.pendingAction;
9996
+ editorAny.pendingDiffs = [], editorAny.pendingSelection = null, editorAny.pendingAction = null;
9997
+ try {
9998
+ withoutNormalizing(editor, () => {
9999
+ if (isSpan({
10000
+ schema: editor.schema
10001
+ }, node))
10002
+ node.text.length > 0 && editor.apply({
10003
+ type: "insert_text",
10004
+ path: prevPath,
10005
+ offset: position,
10006
+ text: node.text
10007
+ }), editor.apply({
10008
+ type: "remove_node",
10626
10009
  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({
10010
+ node
10011
+ });
10012
+ else if (isTextBlock({
10634
10013
  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
- }
10014
+ }, node)) {
10015
+ for (let i = 0; i < node.children.length; i++)
10016
+ editor.apply({
10017
+ type: "insert_node",
10018
+ path: [...prevPath, position + i],
10019
+ node: node.children[i]
10020
+ });
10021
+ editor.apply({
10022
+ type: "remove_node",
10023
+ path: path2,
10024
+ node
10025
+ });
10717
10026
  }
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
- });
10027
+ });
10028
+ } finally {
10029
+ editor.selection = savedSelection;
10030
+ for (const ref of pathRefs)
10031
+ editor.pathRefs.add(ref);
10032
+ for (const ref of pointRefs)
10033
+ editor.pointRefs.add(ref);
10034
+ for (const ref of rangeRefs)
10035
+ editor.rangeRefs.add(ref);
10036
+ editorAny.pendingDiffs = preTransformedPendingDiffs, editorAny.pendingSelection = preTransformedPendingSelection, editorAny.pendingAction = preTransformedPendingAction;
10037
+ }
10038
+ }
10039
+ function transformTextDiffForMerge(textDiff, mergePath, position) {
10040
+ const {
10041
+ path: path2,
10042
+ diff: diff2,
10043
+ id
10044
+ } = textDiff;
10045
+ if (!pathEquals(mergePath, path2)) {
10046
+ const newPath = transformPathForMerge(path2, mergePath, position);
10047
+ return newPath ? {
10048
+ diff: diff2,
10049
+ id,
10050
+ path: newPath
10051
+ } : null;
10052
+ }
10053
+ return {
10054
+ diff: {
10055
+ start: diff2.start + position,
10056
+ end: diff2.end + position,
10057
+ text: diff2.text
10058
+ },
10059
+ id,
10060
+ path: transformPathForMerge(path2, mergePath, position)
10061
+ };
10062
+ }
10063
+ function transformPathForMerge(path2, mergePath, position) {
10064
+ const p = [...path2];
10065
+ 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;
10066
+ }
10067
+ function transformPointForMerge(point2, mergePath, position) {
10068
+ let {
10069
+ path: path2,
10070
+ offset
10071
+ } = point2;
10072
+ return pathEquals(mergePath, path2) && (offset += position), path2 = transformPathForMerge(path2, mergePath, position), {
10073
+ path: path2,
10074
+ offset
10075
+ };
10076
+ }
10077
+ function createSpanNode(context) {
10078
+ return {
10079
+ _type: context.schema.span.name,
10080
+ _key: context.keyGenerator(),
10081
+ text: "",
10082
+ marks: []
10083
+ };
10723
10084
  }
10724
- function insertNodes(editor, nodes, options = {}) {
10085
+ const matchPath = (editor, path2) => {
10086
+ const matchedEntry = getNode(editor, path2);
10087
+ if (!matchedEntry)
10088
+ return () => !1;
10089
+ const matchedNode = matchedEntry.node;
10090
+ return (n) => n === matchedNode;
10091
+ };
10092
+ function removeNodes(editor, options = {}) {
10725
10093
  withoutNormalizing(editor, () => {
10726
10094
  const {
10727
10095
  hanging = !1,
10728
- includeObjectNodes = !1,
10729
- mode = "lowest",
10730
- batchDirty = !0
10096
+ mode = "lowest"
10731
10097
  } = options;
10732
10098
  let {
10733
- at,
10734
- match: match2,
10735
- select: select2
10099
+ at = editor.selection,
10100
+ match: match2
10736
10101
  } = options;
10737
- if (nodes.length === 0)
10102
+ if (!at)
10738
10103
  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();
10104
+ match2 == null && (match2 = isPath(at) ? matchPath(editor, at) : (n) => isTextBlockNode({
10105
+ schema: editor.schema
10106
+ }, n)), !hanging && isRange(at) && (at = unhangRange(editor, at));
10107
+ let from, to;
10108
+ if (isRange(at)) {
10109
+ const [start2, end2] = rangeEdges(at);
10110
+ from = start2.path, to = end2.path;
10111
+ } else isPath(at) ? (from = path(editor, at, {
10112
+ edge: "start"
10113
+ }), to = path(editor, at, {
10114
+ edge: "end"
10115
+ })) : (from = at.path, to = at.path);
10116
+ const depths = [];
10117
+ let hit;
10118
+ for (const {
10119
+ node,
10120
+ path: nodePath
10121
+ } of getNodes(editor, {
10122
+ from,
10123
+ to,
10124
+ match: (n, p) => match2(n, p)
10125
+ })) {
10126
+ const isLower = hit && comparePaths(nodePath, hit[1]) === 0;
10127
+ if (mode === "highest" && isLower)
10128
+ continue;
10129
+ if (mode === "lowest" && isLower) {
10130
+ hit = [node, nodePath];
10131
+ continue;
10748
10132
  }
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"
10133
+ const emit2 = mode === "lowest" ? hit : [node, nodePath];
10134
+ emit2 && depths.push(emit2), hit = [node, nodePath];
10135
+ }
10136
+ mode === "lowest" && hit && depths.push(hit);
10137
+ const pathRefs = Array.from(depths, ([, p]) => pathRef(editor, p));
10138
+ for (const ref of pathRefs) {
10139
+ const path2 = ref.unref();
10140
+ if (path2) {
10141
+ const removedEntry = getNode(editor, path2);
10142
+ if (removedEntry) {
10143
+ const removedNode = removedEntry.node;
10144
+ editor.apply({
10145
+ type: "remove_node",
10146
+ path: path2,
10147
+ node: removedNode
10774
10148
  });
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
10149
  }
10802
- const path2 = matchPathRef.unref();
10803
- at = isAtEnd ? nextPath(path2) : path2;
10804
- } else
10805
- return;
10150
+ }
10806
10151
  }
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({
10152
+ });
10153
+ }
10154
+ const normalizeNode = (editor, entry) => {
10155
+ const [node, path2] = entry, nodeRecord = node;
10156
+ if (isEditor(node) && node.children.length === 0) {
10157
+ withoutPatching(editor, () => {
10158
+ applyInsertNodeAtPath(editor, createPlaceholderBlock(editor), [0]);
10159
+ });
10160
+ return;
10161
+ }
10162
+ if (isTextBlock({
10163
+ schema: editor.schema
10164
+ }, node)) {
10165
+ const children = getChildren(editor, path2);
10166
+ for (const {
10167
+ node: child,
10168
+ path: childPath
10169
+ } of children) {
10170
+ const childIndex = childPath[childPath.length - 1], nextNode = node.children[childIndex + 1];
10171
+ if (isSpan({
10172
+ schema: editor.schema
10173
+ }, child) && isSpan({
10812
10174
  schema: editor.schema
10813
- }, parentNodeEntry.node) ? parentNodeEntry : getAncestorObjectNode(editor, parentPath_))
10175
+ }, nextNode) && child.marks?.every((mark) => nextNode.marks?.includes(mark)) && nextNode.marks?.every((mark) => child.marks?.includes(mark))) {
10176
+ debug$1.normalization("merging spans with same marks");
10177
+ const mergePath = [...path2, childIndex + 1];
10178
+ applyMergeNode(editor, mergePath, child.text.length);
10814
10179
  return;
10180
+ }
10815
10181
  }
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));
10182
+ }
10183
+ if (nodeRecord._type === void 0 && path2.length > 0) {
10184
+ const parent = getNode(editor, parentPath(path2));
10185
+ if (parent && isTextBlock({
10186
+ schema: editor.schema
10187
+ }, parent.node)) {
10188
+ debug$1.normalization("Setting span type on node without a type"), editor.apply({
10189
+ type: "set_node",
10190
+ path: path2,
10191
+ properties: {},
10192
+ newProperties: {
10193
+ _type: editor.schema.span.name
10832
10194
  }
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
10195
  });
10842
- } else
10843
- for (const node2 of nodes) {
10844
- const path2 = parentPath_.concat(index);
10845
- index++, editor.apply({
10846
- type: "insert_node",
10196
+ return;
10197
+ }
10198
+ }
10199
+ if (nodeRecord._key === void 0 && path2.length > 0) {
10200
+ debug$1.normalization("Setting missing key on node"), editor.apply({
10201
+ type: "set_node",
10202
+ path: path2,
10203
+ properties: {},
10204
+ newProperties: {
10205
+ _key: editor.keyGenerator()
10206
+ }
10207
+ });
10208
+ return;
10209
+ }
10210
+ if (path2.length > 0 && nodeRecord._key !== void 0) {
10211
+ const parent = getParent(editor, path2), siblings = parent ? getChildren(editor, parent.path) : editor.children.map((child, index) => ({
10212
+ node: child,
10213
+ path: [index]
10214
+ }));
10215
+ for (const sibling of siblings) {
10216
+ if (pathEquals(sibling.path, path2))
10217
+ break;
10218
+ if (sibling.node._key === nodeRecord._key) {
10219
+ debug$1.normalization("Fixing duplicate key on node"), editor.apply({
10220
+ type: "set_node",
10847
10221
  path: path2,
10848
- node: node2
10849
- }), at = nextPath(at);
10222
+ properties: {},
10223
+ newProperties: {
10224
+ _key: editor.keyGenerator()
10225
+ }
10226
+ });
10227
+ return;
10850
10228
  }
10851
- if (at = previousPath(at), select2) {
10852
- const point2 = end(editor, at);
10853
- point2 && editor.select(point2);
10854
10229
  }
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;
10230
+ }
10231
+ if (isTextBlockNode({
10232
+ schema: editor.schema
10233
+ }, node) && !Array.isArray(node.markDefs)) {
10234
+ debug$1.normalization("adding .markDefs to block node"), applySetNode(editor, {
10235
+ markDefs: []
10236
+ }, path2);
10237
+ return;
10238
+ }
10239
+ {
10240
+ const defaultStyle = editor.schema.styles.at(0)?.name;
10241
+ if (defaultStyle && isTextBlockNode({
10242
+ schema: editor.schema
10243
+ }, node) && typeof node.style > "u") {
10244
+ debug$1.normalization("adding .style to block node"), applySetNode(editor, {
10245
+ style: defaultStyle
10246
+ }, path2);
10247
+ return;
10882
10248
  }
10883
- const emit2 = mode === "lowest" ? hit : entry;
10884
- if (emit2)
10885
- return emit2;
10886
- hit = entry;
10887
10249
  }
10888
- return hit;
10889
- }
10890
- const normalizeNode = (editor, entry) => {
10891
- const [node, path2] = entry;
10892
10250
  if (isSpan({
10893
10251
  schema: editor.schema
10894
- }, node) || isObjectNode({
10895
- schema: editor.schema
10896
- }, node))
10252
+ }, node) && !Array.isArray(node.marks)) {
10253
+ debug$1.normalization("Adding .marks to span node"), applySetNode(editor, {
10254
+ marks: []
10255
+ }, path2);
10897
10256
  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)
10257
+ }
10258
+ if (isSpan({
10259
+ schema: editor.schema
10260
+ }, node)) {
10261
+ const blockPath = parentPath(path2);
10262
+ if (!getTextBlockNode(editor, blockPath))
10263
+ return;
10264
+ const decorators = editor.schema.decorators.map((decorator) => decorator.name), annotations = node.marks?.filter((mark) => !decorators.includes(mark));
10265
+ if (node.text === "" && annotations && annotations.length > 0) {
10266
+ debug$1.normalization("removing annotations from empty span node"), applySetNode(editor, {
10267
+ marks: node.marks?.filter((mark) => decorators.includes(mark))
10268
+ }, path2);
10269
+ return;
10270
+ }
10271
+ }
10272
+ if (isTextBlock({
10273
+ schema: editor.schema
10274
+ }, node)) {
10275
+ const decorators = editor.schema.decorators.map((decorator) => decorator.name);
10276
+ for (const {
10277
+ node: child,
10278
+ path: childPath
10279
+ } of getChildren(editor, path2))
10280
+ if (isSpan({
10281
+ schema: editor.schema
10282
+ }, child)) {
10283
+ const marks = child.marks ?? [], orphanedAnnotations = marks.filter((mark) => !decorators.includes(mark) && !node.markDefs?.find((def) => def._key === mark));
10284
+ if (orphanedAnnotations.length > 0) {
10285
+ debug$1.normalization("removing orphaned annotations from span node"), applySetNode(editor, {
10286
+ marks: marks.filter((mark) => !orphanedAnnotations.includes(mark))
10287
+ }, childPath);
10288
+ return;
10289
+ }
10290
+ }
10291
+ }
10292
+ if (isSpan({
10293
+ schema: editor.schema
10294
+ }, node)) {
10295
+ const blockPath = parentPath(path2), blockEntry2 = getTextBlockNode(editor, blockPath);
10296
+ if (blockEntry2) {
10297
+ 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));
10298
+ if (orphanedAnnotations.length > 0) {
10299
+ debug$1.normalization("removing orphaned annotations from span node"), applySetNode(editor, {
10300
+ marks: marks.filter((mark) => !orphanedAnnotations.includes(mark))
10301
+ }, path2);
10302
+ return;
10303
+ }
10304
+ }
10305
+ }
10306
+ if (isTextBlock({
10307
+ schema: editor.schema
10308
+ }, node)) {
10309
+ const markDefs = node.markDefs ?? [], markDefKeys = /* @__PURE__ */ new Set(), newMarkDefs = [];
10310
+ for (const markDef of markDefs)
10311
+ markDefKeys.has(markDef._key) || (markDefKeys.add(markDef._key), newMarkDefs.push(markDef));
10312
+ if (markDefs.length !== newMarkDefs.length) {
10313
+ debug$1.normalization("removing duplicate markDefs"), applySetNode(editor, {
10314
+ markDefs: newMarkDefs
10315
+ }, path2);
10316
+ return;
10317
+ }
10318
+ }
10319
+ if (isTextBlock({
10320
+ schema: editor.schema
10321
+ }, node)) {
10322
+ const newMarkDefs = (node.markDefs || []).filter((def) => node.children.find((child) => isSpan({
10323
+ schema: editor.schema
10324
+ }, child) && Array.isArray(child.marks) && child.marks.includes(def._key)));
10325
+ if (node.markDefs && !isEqualMarkDefs(newMarkDefs, node.markDefs)) {
10326
+ debug$1.normalization("removing markDef not in use"), applySetNode(editor, {
10327
+ markDefs: newMarkDefs
10328
+ }, path2);
10908
10329
  return;
10909
- element = refetched;
10330
+ }
10910
10331
  }
10911
- const firstChild = element.children[0];
10912
- if (!isEditor(element) && (editor.isInline(element) || isSpan({
10332
+ if (isSpanNode({
10913
10333
  schema: editor.schema
10914
- }, firstChild) || isObjectNode({
10334
+ }, node)) {
10335
+ if (typeof node.text != "string") {
10336
+ debug$1.normalization("Adding .text to span node"), editor.apply({
10337
+ type: "set_node",
10338
+ path: path2,
10339
+ properties: {},
10340
+ newProperties: {
10341
+ text: ""
10342
+ }
10343
+ });
10344
+ return;
10345
+ }
10346
+ return;
10347
+ }
10348
+ if (!isObjectNode({
10915
10349
  schema: editor.schema
10916
- }, firstChild) || isTextBlock({
10350
+ }, node) && isTextBlockNode({
10917
10351
  schema: editor.schema
10918
- }, firstChild) && editor.isInline(firstChild)))
10352
+ }, node)) {
10353
+ if (!Array.isArray(node.children)) {
10354
+ editor.apply({
10355
+ type: "set_node",
10356
+ path: path2,
10357
+ properties: {},
10358
+ newProperties: {
10359
+ children: []
10360
+ }
10361
+ });
10362
+ return;
10363
+ }
10364
+ let element = node;
10365
+ if (element.children.length === 0) {
10366
+ const child = createSpanNode(editor);
10367
+ editor.apply({
10368
+ type: "insert_node",
10369
+ path: path2.concat(0),
10370
+ node: child
10371
+ });
10372
+ const refetched = getTextBlockNode(editor, path2)?.node;
10373
+ if (!refetched)
10374
+ return;
10375
+ element = refetched;
10376
+ }
10919
10377
  for (let n = 0; n < element.children.length; n++) {
10920
10378
  const child = element.children[n], prev = element.children[n - 1];
10921
10379
  if (isSpan({
@@ -10953,54 +10411,17 @@ const normalizeNode = (editor, entry) => {
10953
10411
  element = refetched, n--;
10954
10412
  }
10955
10413
  }
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({
10414
+ } else if (isObjectNode({
10995
10415
  schema: editor.schema
10996
10416
  }, child)) {
10997
10417
  if (prev == null || !isSpan({
10998
10418
  schema: editor.schema
10999
10419
  }, prev)) {
11000
- const newChild = editor.createSpan();
11001
- insertNodes(editor, [newChild], {
11002
- at: path2.concat(n),
11003
- includeObjectNodes: !0
10420
+ const newChild = createSpanNode(editor);
10421
+ editor.apply({
10422
+ type: "insert_node",
10423
+ path: path2.concat(n),
10424
+ node: newChild
11004
10425
  });
11005
10426
  const refetched = getTextBlockNode(editor, path2)?.node;
11006
10427
  if (!refetched)
@@ -11008,10 +10429,11 @@ const normalizeNode = (editor, entry) => {
11008
10429
  element = refetched, n++;
11009
10430
  }
11010
10431
  if (n === element.children.length - 1) {
11011
- const newChild = editor.createSpan();
11012
- insertNodes(editor, [newChild], {
11013
- at: path2.concat(n + 1),
11014
- includeObjectNodes: !0
10432
+ const newChild = createSpanNode(editor);
10433
+ editor.apply({
10434
+ type: "insert_node",
10435
+ path: path2.concat(n + 1),
10436
+ node: newChild
11015
10437
  });
11016
10438
  const refetched = getTextBlockNode(editor, path2)?.node;
11017
10439
  if (!refetched)
@@ -11020,28 +10442,8 @@ const normalizeNode = (editor, entry) => {
11020
10442
  }
11021
10443
  }
11022
10444
  }
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
- }
10445
+ return;
10446
+ }
11045
10447
  };
11046
10448
  function select(editor, target) {
11047
10449
  const {
@@ -11081,7 +10483,7 @@ const shouldNormalize = (_editor, {
11081
10483
  if (iteration > maxIterations)
11082
10484
  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
10485
  return !0;
11084
- }, createEditor = (context) => {
10486
+ }, createEditor = () => {
11085
10487
  const e = {
11086
10488
  [EDITOR_BRAND]: !0,
11087
10489
  children: [],
@@ -11095,24 +10497,15 @@ const shouldNormalize = (_editor, {
11095
10497
  dirtyPathKeys: /* @__PURE__ */ new Set(),
11096
10498
  flushing: !1,
11097
10499
  normalizing: !0,
11098
- batchingDirtyPaths: !1,
11099
10500
  pathRefs: /* @__PURE__ */ new Set(),
11100
10501
  pointRefs: /* @__PURE__ */ new Set(),
11101
10502
  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
10503
  onChange: () => {
11110
10504
  },
11111
10505
  // Core
11112
10506
  apply: (...args) => apply(e, ...args),
11113
10507
  // Editor
11114
10508
  normalizeNode: (...args) => normalizeNode(e, ...args),
11115
- getDirtyPaths: (...args) => getDirtyPaths(e, ...args),
11116
10509
  shouldNormalize: (...args) => shouldNormalize(e, ...args),
11117
10510
  // Overrideable commands
11118
10511
  select: (...args) => select(e, ...args),
@@ -11475,11 +10868,8 @@ const withDOM = (editor) => {
11475
10868
  };
11476
10869
  function createSlateEditor(config) {
11477
10870
  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 = {
10871
+ const context = config.editorActor.getSnapshot().context, placeholderBlock = createPlaceholderBlock(context), editor = createEditor();
10872
+ 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
10873
  undos: [],
11484
10874
  redos: []
11485
10875
  }, 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 +12625,7 @@ const removeAnnotationOperationImplementation = ({
13235
12625
  if (isTextBlockNode(context, slateBlock)) {
13236
12626
  const filteredProps = {};
13237
12627
  for (const key of Object.keys(operation.props))
13238
- if (!(key === "_type" || key === "children")) {
12628
+ if (key !== "_type") {
13239
12629
  if (key === "_key") {
13240
12630
  filteredProps[key] = operation.props[key];
13241
12631
  continue;
@@ -13292,7 +12682,7 @@ const removeAnnotationOperationImplementation = ({
13292
12682
  if (!slateBlock)
13293
12683
  throw new Error(`Unable to find block at ${safeStringify(operation.at)}`);
13294
12684
  if (isTextBlockNode(context, slateBlock)) {
13295
- const propsToRemove = operation.props.filter((prop) => prop !== "_type" && prop !== "_key" && prop !== "children"), unsetProps2 = {};
12685
+ const propsToRemove = operation.props.filter((prop) => prop !== "_type" && prop !== "_key"), unsetProps2 = {};
13296
12686
  for (const prop of propsToRemove)
13297
12687
  unsetProps2[prop] = null;
13298
12688
  applySetNode(operation.editor, unsetProps2, [blockIndex]), operation.props.includes("_key") && applySetNode(operation.editor, {
@@ -13411,19 +12801,14 @@ const removeAnnotationOperationImplementation = ({
13411
12801
  }, child)) {
13412
12802
  const newNode = {};
13413
12803
  for (const prop of operation.props)
13414
- if (prop !== "text" && prop !== "_type") {
12804
+ if (prop !== "_type") {
13415
12805
  if (prop === "_key") {
13416
12806
  newNode._key = context.keyGenerator();
13417
12807
  continue;
13418
12808
  }
13419
12809
  newNode[prop] = null;
13420
12810
  }
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
- });
12811
+ applySetNode(operation.editor, newNode, childPath);
13427
12812
  return;
13428
12813
  }
13429
12814
  if (isObjectNode({
@@ -13492,125 +12877,401 @@ const removeAnnotationOperationImplementation = ({
13492
12877
  if (!blockEntry)
13493
12878
  return;
13494
12879
  const {
13495
- node: block,
13496
- path: blockPath
13497
- } = blockEntry, lonelyEmptySpan = isTextBlock({
13498
- schema: editor.schema
13499
- }, block) && block.children.length === 1 && isSpan({
12880
+ node: block,
12881
+ path: blockPath
12882
+ } = blockEntry, lonelyEmptySpan = isTextBlock({
12883
+ schema: editor.schema
12884
+ }, block) && block.children.length === 1 && isSpan({
12885
+ schema: editor.schema
12886
+ }, block.children[0]) && block.children[0].text === "" ? block.children[0] : void 0;
12887
+ if (lonelyEmptySpan) {
12888
+ const existingMarks = lonelyEmptySpan.marks ?? [], existingMarksWithoutDecorator = existingMarks.filter((existingMark) => existingMark !== mark), newMarks = existingMarks.length === existingMarksWithoutDecorator.length ? [...existingMarks, mark] : existingMarksWithoutDecorator;
12889
+ for (const {
12890
+ path: spanPath
12891
+ } of Array.from(getNodes(editor, {
12892
+ at: blockPath,
12893
+ match: (node) => isSpan({
12894
+ schema: editor.schema
12895
+ }, node)
12896
+ })))
12897
+ applySetNode(editor, {
12898
+ marks: newMarks
12899
+ }, spanPath);
12900
+ } else
12901
+ editor.decoratorState[mark] = !0;
12902
+ }
12903
+ if (editor.selection) {
12904
+ const selection = editor.selection;
12905
+ editor.selection = {
12906
+ ...selection
12907
+ };
12908
+ }
12909
+ }
12910
+ }, decoratorRemoveOperationImplementation = ({
12911
+ context,
12912
+ operation
12913
+ }) => {
12914
+ const editor = operation.editor, mark = operation.decorator, at = operation.at ? toSlateRange({
12915
+ context: {
12916
+ schema: context.schema,
12917
+ value: operation.editor.children,
12918
+ selection: operation.at
12919
+ },
12920
+ blockIndexMap: operation.editor.blockIndexMap
12921
+ }) : editor.selection;
12922
+ if (at) {
12923
+ if (isExpandedRange(at)) {
12924
+ const ref = rangeRef(editor, at, {
12925
+ affinity: "inward"
12926
+ }), decoratorLeafEntry = getNode(editor, at.anchor.path), decoratorLeaf = decoratorLeafEntry && isLeaf(editor, decoratorLeafEntry.path) ? decoratorLeafEntry.node : void 0;
12927
+ if (!(decoratorLeaf && isCollapsedRange(at) && isSpan({
12928
+ schema: editor.schema
12929
+ }, decoratorLeaf) && decoratorLeaf.text.length > 0)) {
12930
+ const [start2, end2] = rangeEdges(at);
12931
+ (!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);
12932
+ }
12933
+ const updatedAt = ref.unref();
12934
+ if (updatedAt) {
12935
+ const splitTextNodes = [...getNodes(editor, {
12936
+ from: rangeStart(updatedAt).path,
12937
+ to: rangeEnd(updatedAt).path,
12938
+ match: (n) => isSpan({
12939
+ schema: editor.schema
12940
+ }, n)
12941
+ })];
12942
+ for (const {
12943
+ node,
12944
+ path: nodePath
12945
+ } of splitTextNodes) {
12946
+ if (!isSpan({
12947
+ schema: editor.schema
12948
+ }, node))
12949
+ continue;
12950
+ const block = editor.children[nodePath[0]];
12951
+ isTextBlock({
12952
+ schema: editor.schema
12953
+ }, block) && block.children.includes(node) && applySetNode(editor, {
12954
+ marks: (Array.isArray(node.marks) ? node.marks : []).filter((eMark) => eMark !== mark),
12955
+ _type: context.schema.span.name
12956
+ }, nodePath);
12957
+ }
12958
+ }
12959
+ } else {
12960
+ const blockEntry = getNode(editor, path(editor, at, {
12961
+ depth: 1
12962
+ }));
12963
+ if (!blockEntry)
12964
+ return;
12965
+ const {
12966
+ node: block,
12967
+ path: blockPath
12968
+ } = blockEntry, lonelyEmptySpan = isTextBlock({
12969
+ schema: editor.schema
12970
+ }, block) && block.children.length === 1 && isSpan({
12971
+ schema: editor.schema
12972
+ }, block.children[0]) && block.children[0].text === "" ? block.children[0] : void 0;
12973
+ if (lonelyEmptySpan) {
12974
+ const existingMarksWithoutDecorator = (lonelyEmptySpan.marks ?? []).filter((existingMark) => existingMark !== mark);
12975
+ for (const {
12976
+ path: spanPath
12977
+ } of Array.from(getNodes(editor, {
12978
+ at: blockPath,
12979
+ match: (node) => isSpan({
12980
+ schema: editor.schema
12981
+ }, node)
12982
+ })))
12983
+ applySetNode(editor, {
12984
+ marks: existingMarksWithoutDecorator
12985
+ }, spanPath);
12986
+ } else
12987
+ editor.decoratorState[mark] = !1;
12988
+ }
12989
+ if (editor.selection) {
12990
+ const selection = editor.selection;
12991
+ editor.selection = {
12992
+ ...selection
12993
+ };
12994
+ }
12995
+ }
12996
+ };
12997
+ function pointRef(editor, point2, options = {}) {
12998
+ const {
12999
+ affinity = "forward"
13000
+ } = options, ref = {
13001
+ current: point2,
13002
+ affinity,
13003
+ unref() {
13004
+ const {
13005
+ current
13006
+ } = ref;
13007
+ return editor.pointRefs.delete(ref), ref.current = null, current;
13008
+ }
13009
+ };
13010
+ return editor.pointRefs.add(ref), ref;
13011
+ }
13012
+ function shouldMergeNodesRemovePrevNode(editor, prev, _current) {
13013
+ let isEmptyElement = !1;
13014
+ if (isTextBlock({
13015
+ schema: editor.schema
13016
+ }, prev.node)) {
13017
+ const prevChildren = prev.node.children;
13018
+ isEmptyElement = prevChildren.length === 0 || prevChildren.length === 1 && isSpan({
13019
+ schema: editor.schema
13020
+ }, prevChildren[0]) && prevChildren[0].text === "";
13021
+ }
13022
+ return isEmptyElement || isSpan({
13023
+ schema: editor.schema
13024
+ }, prev.node) && prev.node.text === "" && prev.path[prev.path.length - 1] !== 0;
13025
+ }
13026
+ function isCommonPath(path2, another) {
13027
+ return path2.length <= another.length && comparePaths(path2, another) === 0;
13028
+ }
13029
+ const getDefaultInsertLocation = (editor) => editor.selection ? editor.selection : editor.children.length > 0 ? end(editor, []) : [0];
13030
+ function insertText(editor, text, options = {}) {
13031
+ withoutNormalizing(editor, () => {
13032
+ const {
13033
+ includeObjectNodes = !1
13034
+ } = options;
13035
+ let {
13036
+ at = getDefaultInsertLocation(editor)
13037
+ } = options;
13038
+ if (isPath(at) && (at = range(editor, at)), isRange(at))
13039
+ if (isCollapsedRange(at))
13040
+ at = at.anchor;
13041
+ else {
13042
+ const end2 = rangeEnd(at);
13043
+ if (!includeObjectNodes) {
13044
+ const endPath = path(editor, end2), endEntry = getNode(editor, endPath);
13045
+ if (endEntry && isObjectNode({
13046
+ schema: editor.schema
13047
+ }, endEntry.node) ? endEntry : getAncestorObjectNode(editor, end2.path))
13048
+ return;
13049
+ }
13050
+ const start2 = rangeStart(at), startRef = pointRef(editor, start2), endRef = pointRef(editor, end2);
13051
+ deleteText(editor, {
13052
+ at,
13053
+ includeObjectNodes
13054
+ });
13055
+ const startPoint = startRef.unref(), endPoint = endRef.unref();
13056
+ at = startPoint || endPoint, editor.setSelection({
13057
+ anchor: at,
13058
+ focus: at
13059
+ });
13060
+ }
13061
+ if (!includeObjectNodes) {
13062
+ const atPath = path(editor, at), atEntry = getNode(editor, atPath);
13063
+ if (atEntry && isObjectNode({
13064
+ schema: editor.schema
13065
+ }, atEntry.node) ? atEntry : getAncestorObjectNode(editor, at.path))
13066
+ return;
13067
+ }
13068
+ const {
13069
+ path: path$1,
13070
+ offset
13071
+ } = at;
13072
+ text.length > 0 && editor.apply({
13073
+ type: "insert_text",
13074
+ path: path$1,
13075
+ offset,
13076
+ text
13077
+ });
13078
+ });
13079
+ }
13080
+ function deleteText(editor, options = {}) {
13081
+ withoutNormalizing(editor, () => {
13082
+ const {
13083
+ reverse = !1,
13084
+ unit = "character",
13085
+ distance = 1,
13086
+ includeObjectNodes = !1
13087
+ } = options;
13088
+ let {
13089
+ at = editor.selection,
13090
+ hanging = !1
13091
+ } = options;
13092
+ if (!at)
13093
+ return;
13094
+ let isCollapsed = !1;
13095
+ if (isRange(at) && isCollapsedRange(at) && (isCollapsed = !0, at = at.anchor), isPoint(at)) {
13096
+ const furthestObjectNode = getHighestObjectNode(editor, at.path);
13097
+ if (!includeObjectNodes && furthestObjectNode)
13098
+ at = furthestObjectNode.path;
13099
+ else {
13100
+ const opts = {
13101
+ unit,
13102
+ distance
13103
+ }, target = reverse ? before(editor, at, opts) || start(editor, []) : after(editor, at, opts) || end(editor, []);
13104
+ at = {
13105
+ anchor: at,
13106
+ focus: target
13107
+ }, hanging = !0;
13108
+ }
13109
+ }
13110
+ if (isPath(at)) {
13111
+ removeNodes(editor, {
13112
+ at,
13113
+ includeObjectNodes
13114
+ });
13115
+ return;
13116
+ }
13117
+ if (isCollapsedRange(at))
13118
+ return;
13119
+ if (!hanging) {
13120
+ const [, end2] = rangeEdges(at), endOfDoc = end(editor, []);
13121
+ pointEquals(end2, endOfDoc) || (at = unhangRange(editor, at));
13122
+ }
13123
+ let [start$1, end$1] = rangeEdges(at);
13124
+ 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);
13125
+ if (startNonEditable) {
13126
+ const beforePoint = before(editor, start$1);
13127
+ beforePoint && startBlock && isAncestorPath(startBlock.path, beforePoint.path) && (start$1 = beforePoint);
13128
+ }
13129
+ if (endNonEditable) {
13130
+ const afterPoint = after(editor, end$1);
13131
+ afterPoint && endBlock && isAncestorPath(endBlock.path, afterPoint.path) && (end$1 = afterPoint);
13132
+ }
13133
+ const matches = [];
13134
+ let lastPath;
13135
+ for (const entry of getNodes(editor, {
13136
+ from: start$1.path,
13137
+ to: end$1.path
13138
+ })) {
13139
+ const {
13140
+ node,
13141
+ path: entryPath
13142
+ } = entry;
13143
+ lastPath && comparePaths(entryPath, lastPath) === 0 || (!includeObjectNodes && isObjectNode({
13500
13144
  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;
13145
+ }, node) || !isCommonPath(entryPath, start$1.path) && !isCommonPath(entryPath, end$1.path)) && (matches.push(entry), lastPath = entryPath);
13517
13146
  }
13518
- if (editor.selection) {
13519
- const selection = editor.selection;
13520
- editor.selection = {
13521
- ...selection
13522
- };
13147
+ const pathRefs = Array.from(matches, (entry) => pathRef(editor, entry.path)), startRef = pointRef(editor, start$1), endRef = pointRef(editor, end$1);
13148
+ let removedText = "";
13149
+ if (!isSingleText && !startNonEditable) {
13150
+ const point22 = startRef.current, nodeEntry = getSpanNode(editor, point22.path);
13151
+ if (nodeEntry) {
13152
+ const node = nodeEntry.node, {
13153
+ path: path2
13154
+ } = point22, {
13155
+ offset
13156
+ } = start$1, text = node.text.slice(offset);
13157
+ text.length > 0 && (editor.apply({
13158
+ type: "remove_text",
13159
+ path: path2,
13160
+ offset,
13161
+ text
13162
+ }), removedText = text);
13163
+ }
13523
13164
  }
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);
13165
+ if (pathRefs.reverse().map((r) => r.unref()).filter((r) => r !== null).forEach((p) => {
13166
+ removeNodes(editor, {
13167
+ at: p,
13168
+ includeObjectNodes
13169
+ });
13170
+ }), !endNonEditable) {
13171
+ const point22 = endRef.current, endNodeEntry = getSpanNode(editor, point22.path);
13172
+ if (endNodeEntry) {
13173
+ const node = endNodeEntry.node, {
13174
+ path: path2
13175
+ } = point22, offset = isSingleText ? start$1.offset : 0, text = node.text.slice(offset, end$1.offset);
13176
+ text.length > 0 && (editor.apply({
13177
+ type: "remove_text",
13178
+ path: path2,
13179
+ offset,
13180
+ text
13181
+ }), removedText = text);
13547
13182
  }
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({
13183
+ }
13184
+ if (!isSingleText && isAcrossBlocks && endRef.current && startRef.current) {
13185
+ const mergeAt = endRef.current, mergeMatch = (n) => isTextBlock({
13186
+ schema: editor.schema
13187
+ }, n), current = getAncestor(editor, mergeAt.path, mergeMatch), beforePoint = before(editor, mergeAt), prev = beforePoint ? getNodes(editor, {
13188
+ to: beforePoint.path,
13189
+ match: mergeMatch,
13190
+ reverse: !0
13191
+ }).next().value : void 0;
13192
+ if (current && prev) {
13193
+ const {
13194
+ node: mergeNode,
13195
+ path: mergePath
13196
+ } = current, {
13197
+ node: prevNode,
13198
+ path: prevPath
13199
+ } = prev;
13200
+ if (mergePath.length !== 0 && prevPath.length !== 0) {
13201
+ 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) => {
13202
+ if (isTextBlock({
13203
+ schema: editor.schema
13204
+ }, node)) {
13205
+ const elementChildren = node.children;
13206
+ return elementChildren.length === 1 ? hasSingleChildNest(elementChildren[0]) : !1;
13207
+ } else return !isEditor(node);
13208
+ }, emptyAncestor = getAncestors(editor, mergePath).reverse().find((ancestor) => editorLevels.includes(ancestor.node) && hasSingleChildNest(ancestor.node)), emptyRef = emptyAncestor && pathRef(editor, emptyAncestor.path);
13209
+ let position;
13210
+ if (isSpan({
13554
13211
  schema: editor.schema
13555
- }, n)
13556
- })];
13557
- for (const {
13558
- node,
13559
- path: nodePath
13560
- } of splitTextNodes) {
13561
- if (!isSpan({
13212
+ }, mergeNode) && isSpan({
13562
13213
  schema: editor.schema
13563
- }, node))
13564
- continue;
13565
- const block = editor.children[nodePath[0]];
13566
- isTextBlock({
13214
+ }, prevNode))
13215
+ position = prevNode.text.length;
13216
+ else if (isTextBlock({
13567
13217
  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);
13218
+ }, mergeNode) && isTextBlock({
13219
+ schema: editor.schema
13220
+ }, prevNode))
13221
+ position = prevNode.children.length;
13222
+ else
13223
+ 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)}`);
13224
+ if (!isPreviousSibling) {
13225
+ const moveNodeEntry = getNode(editor, mergePath);
13226
+ if (moveNodeEntry) {
13227
+ const moveNode = moveNodeEntry.node;
13228
+ editor.apply({
13229
+ type: "remove_node",
13230
+ path: mergePath,
13231
+ node: moveNode
13232
+ }), editor.apply({
13233
+ type: "insert_node",
13234
+ path: newPath,
13235
+ node: moveNode
13236
+ });
13237
+ }
13238
+ }
13239
+ if (emptyRef && removeNodes(editor, {
13240
+ at: emptyRef.current,
13241
+ includeObjectNodes
13242
+ }), shouldMergeNodesRemovePrevNode(editor, {
13243
+ node: prevNode,
13244
+ path: prevPath
13245
+ }, {
13246
+ node: mergeNode,
13247
+ path: mergePath
13248
+ }))
13249
+ removeNodes(editor, {
13250
+ at: prevPath,
13251
+ includeObjectNodes
13252
+ });
13253
+ else {
13254
+ const pteEditor = editor;
13255
+ if (isTextBlock({
13256
+ schema: editor.schema
13257
+ }, mergeNode) && isTextBlock({
13258
+ schema: editor.schema
13259
+ }, prevNode) && Array.isArray(mergeNode.markDefs) && mergeNode.markDefs.length > 0) {
13260
+ 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()];
13261
+ applySetNode(pteEditor, {
13262
+ markDefs: newMarkDefs
13263
+ }, targetPath);
13264
+ }
13265
+ applyMergeNode(pteEditor, newPath, position);
13266
+ }
13267
+ emptyRef && emptyRef.unref();
13572
13268
  }
13573
13269
  }
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
13270
  }
13610
- }
13611
- };
13612
- function isInline(context, path2) {
13613
- return !isBlock(context, path2);
13271
+ 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));
13272
+ const startUnref = startRef.unref(), endUnref = endRef.unref(), point2 = reverse ? startUnref || endUnref : endUnref || startUnref;
13273
+ options.at == null && point2 && editor.select(point2);
13274
+ });
13614
13275
  }
13615
13276
  const deleteOperationImplementation = ({
13616
13277
  context,
@@ -18692,8 +18353,11 @@ function updateBlock({
18692
18353
  }) {
18693
18354
  const slateBlock = toSlateBlock(block, {
18694
18355
  schemaTypes: context.schema
18695
- });
18696
- applySetNode(slateEditor, slateBlock, [index]);
18356
+ }), {
18357
+ children: _children,
18358
+ ...blockProps
18359
+ } = slateBlock;
18360
+ applySetNode(slateEditor, blockProps, [index]);
18697
18361
  const oldRecord = oldSlateBlock, newRecord = slateBlock, removedProperties = {};
18698
18362
  for (const key of Object.keys(oldRecord))
18699
18363
  key === "children" || key === "text" || newRecord.hasOwnProperty(key) || (removedProperties[key] = oldRecord[key]);
@@ -18728,7 +18392,12 @@ function updateBlock({
18728
18392
  }, oldBlockChild) && currentBlockChild.text !== oldBlockChild.text, path2 = [index, currentBlockChildIndex];
18729
18393
  if (isChildChanged)
18730
18394
  if (currentBlockChild._key === oldBlockChild?._key && currentBlockChild._type === oldBlockChild?._type) {
18731
- debug$1.syncValue("Updating changed child", currentBlockChild, oldBlockChild), applySetNode(slateEditor, currentBlockChild, path2);
18395
+ debug$1.syncValue("Updating changed child", currentBlockChild, oldBlockChild);
18396
+ const {
18397
+ text: _text,
18398
+ ...childProps
18399
+ } = currentBlockChild;
18400
+ applySetNode(slateEditor, childProps, path2);
18732
18401
  const isSpanNode2 = isSpan({
18733
18402
  schema: context.schema
18734
18403
  }, currentBlockChild) && isSpan({