@ant-design/agentic-ui 2.30.21 → 2.30.23

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.
Files changed (107) hide show
  1. package/dist/Bubble/MessagesContent/MarkdownPreview.d.ts +0 -58
  2. package/dist/Bubble/MessagesContent/MarkdownPreview.js +79 -155
  3. package/dist/Bubble/OpenAIMessageBubble/index.d.ts +11 -0
  4. package/dist/Bubble/OpenAIMessageBubble/index.js +8 -0
  5. package/dist/Bubble/OpenAIMessageBubble/mapOllamaMessages.d.ts +7 -0
  6. package/dist/Bubble/OpenAIMessageBubble/mapOllamaMessages.js +136 -0
  7. package/dist/Bubble/OpenAIMessageBubble/mapOpenAIMessages.d.ts +8 -0
  8. package/dist/Bubble/OpenAIMessageBubble/mapOpenAIMessages.js +156 -0
  9. package/dist/Bubble/OpenAIMessageBubble/mapOpenClawMessages.d.ts +8 -0
  10. package/dist/Bubble/OpenAIMessageBubble/mapOpenClawMessages.js +127 -0
  11. package/dist/Bubble/OpenAIMessageBubble/normalizeOllamaMessages.d.ts +16 -0
  12. package/dist/Bubble/OpenAIMessageBubble/normalizeOllamaMessages.js +110 -0
  13. package/dist/Bubble/OpenAIMessageBubble/normalizeOpenClawMessages.d.ts +10 -0
  14. package/dist/Bubble/OpenAIMessageBubble/normalizeOpenClawMessages.js +61 -0
  15. package/dist/Bubble/OpenAIMessageBubble/ollamaTypes.d.ts +48 -0
  16. package/dist/Bubble/OpenAIMessageBubble/ollamaTypes.js +1 -0
  17. package/dist/Bubble/OpenAIMessageBubble/openClawTypes.d.ts +27 -0
  18. package/dist/Bubble/OpenAIMessageBubble/openClawTypes.js +1 -0
  19. package/dist/Bubble/OpenAIMessageBubble/types.d.ts +71 -0
  20. package/dist/Bubble/OpenAIMessageBubble/types.js +1 -0
  21. package/dist/Bubble/OpenAIMessageBubble/useOllamaMessageBubbleData.d.ts +7 -0
  22. package/dist/Bubble/OpenAIMessageBubble/useOllamaMessageBubbleData.js +23 -0
  23. package/dist/Bubble/OpenAIMessageBubble/useOpenAIMessageBubbleData.d.ts +6 -0
  24. package/dist/Bubble/OpenAIMessageBubble/useOpenAIMessageBubbleData.js +20 -0
  25. package/dist/Bubble/OpenAIMessageBubble/useOpenClawMessageBubbleData.d.ts +7 -0
  26. package/dist/Bubble/OpenAIMessageBubble/useOpenClawMessageBubbleData.js +22 -0
  27. package/dist/Bubble/index.d.ts +2 -0
  28. package/dist/Bubble/index.js +1 -0
  29. package/dist/Hooks/useAutoScroll.js +6 -4
  30. package/dist/MarkdownEditor/BaseMarkdownEditor.d.ts +1 -50
  31. package/dist/MarkdownEditor/BaseMarkdownEditor.js +11 -55
  32. package/dist/MarkdownEditor/editor/Editor.js +35 -21
  33. package/dist/MarkdownEditor/editor/elements/Code/index.js +1 -0
  34. package/dist/MarkdownEditor/editor/elements/Table/SimpleTable.js +5 -1
  35. package/dist/MarkdownEditor/editor/elements/Table/commands/tableCommands.js +24 -8
  36. package/dist/MarkdownEditor/editor/elements/index.js +18 -14
  37. package/dist/MarkdownEditor/editor/plugins/elements.d.ts +2 -0
  38. package/dist/MarkdownEditor/editor/plugins/elements.js +4 -2
  39. package/dist/MarkdownEditor/editor/plugins/handlePaste.js +46 -35
  40. package/dist/MarkdownEditor/editor/plugins/hotKeyCommands/backspace.js +133 -133
  41. package/dist/MarkdownEditor/editor/plugins/hotKeyCommands/enter.js +156 -140
  42. package/dist/MarkdownEditor/editor/plugins/hotKeyCommands/match.d.ts +2 -1
  43. package/dist/MarkdownEditor/editor/plugins/hotKeyCommands/match.js +23 -4
  44. package/dist/MarkdownEditor/editor/plugins/hotKeyCommands/tab.js +40 -36
  45. package/dist/MarkdownEditor/editor/plugins/useKeyboard.js +46 -44
  46. package/dist/MarkdownEditor/editor/plugins/withCodeTagPlugin.js +1 -13
  47. package/dist/MarkdownEditor/editor/store.d.ts +15 -1
  48. package/dist/MarkdownEditor/editor/store.js +45 -34
  49. package/dist/MarkdownEditor/editor/tools/InsertAutocomplete.js +15 -11
  50. package/dist/MarkdownEditor/editor/utils/editorCommands.js +98 -17
  51. package/dist/MarkdownEditor/editor/utils/editorUtils.d.ts +11 -0
  52. package/dist/MarkdownEditor/editor/utils/editorUtils.js +43 -6
  53. package/dist/MarkdownEditor/editor/utils/keyboard.js +14 -12
  54. package/dist/MarkdownEditor/types.d.ts +36 -414
  55. package/dist/MarkdownEditor/types.js +1 -4
  56. package/dist/MarkdownInputField/AttachmentButton/AttachmentFileList/AttachmentFileListItem.d.ts +1 -1
  57. package/dist/MarkdownInputField/AttachmentButton/AttachmentFileList/AttachmentFileListItem.js +4 -5
  58. package/dist/MarkdownInputField/AttachmentButton/AttachmentFileList/index.d.ts +1 -1
  59. package/dist/MarkdownInputField/AttachmentButton/index.d.ts +1 -1
  60. package/dist/MarkdownInputField/MarkdownInputField.js +8 -1
  61. package/dist/MarkdownInputField/SendActions/index.js +7 -4
  62. package/dist/MarkdownInputField/SendButton/index.d.ts +6 -0
  63. package/dist/MarkdownInputField/SendButton/index.js +6 -0
  64. package/dist/MarkdownInputField/hooks/useMarkdownInputFieldHandlers.d.ts +2 -1
  65. package/dist/MarkdownInputField/hooks/useMarkdownInputFieldHandlers.js +12 -3
  66. package/dist/MarkdownInputField/hooks/useMarkdownInputFieldRefs.d.ts +1 -0
  67. package/dist/MarkdownInputField/hooks/useMarkdownInputFieldRefs.js +36 -5
  68. package/dist/MarkdownInputField/utils/renderHelpers.js +5 -0
  69. package/dist/MarkdownRenderer/AnimationText.d.ts +1 -5
  70. package/dist/MarkdownRenderer/AnimationText.js +2 -8
  71. package/dist/MarkdownRenderer/CharacterQueue.d.ts +0 -2
  72. package/dist/MarkdownRenderer/CharacterQueue.js +2 -2
  73. package/dist/MarkdownRenderer/FncRefForMarkdown.d.ts +24 -0
  74. package/dist/MarkdownRenderer/FncRefForMarkdown.js +65 -0
  75. package/dist/MarkdownRenderer/MarkdownRenderer.d.ts +1 -9
  76. package/dist/MarkdownRenderer/MarkdownRenderer.js +25 -18
  77. package/dist/MarkdownRenderer/StreamingCursor.d.ts +4 -0
  78. package/dist/MarkdownRenderer/StreamingCursor.js +20 -0
  79. package/dist/MarkdownRenderer/extractFootnoteDefinitions.d.ts +13 -0
  80. package/dist/MarkdownRenderer/extractFootnoteDefinitions.js +40 -0
  81. package/dist/MarkdownRenderer/markdownReactShared.d.ts +11 -38
  82. package/dist/MarkdownRenderer/markdownReactShared.js +28 -54
  83. package/dist/MarkdownRenderer/renderers/ChartRenderer.js +9 -1
  84. package/dist/MarkdownRenderer/renderers/CodeRenderer.d.ts +4 -1
  85. package/dist/MarkdownRenderer/renderers/CodeRenderer.js +27 -3
  86. package/dist/MarkdownRenderer/renderers/SchemaRenderer.d.ts +2 -0
  87. package/dist/MarkdownRenderer/renderers/SchemaRenderer.js +33 -5
  88. package/dist/MarkdownRenderer/streaming/MarkdownBlockPiece.d.ts +1 -3
  89. package/dist/MarkdownRenderer/streaming/MarkdownBlockPiece.js +16 -28
  90. package/dist/MarkdownRenderer/streaming/useStreamingMarkdownReact.js +2 -1
  91. package/dist/MarkdownRenderer/style.js +18 -0
  92. package/dist/MarkdownRenderer/types.d.ts +17 -93
  93. package/dist/MarkdownRenderer/useMarkdownToReact.js +1 -1
  94. package/dist/MarkdownRenderer/useStreaming.d.ts +1 -10
  95. package/dist/MarkdownRenderer/useStreaming.js +5 -13
  96. package/dist/Plugins/mermaid/MermaidRendererImpl.js +481 -7
  97. package/dist/Plugins/mermaid/style.js +71 -22
  98. package/dist/Plugins/mermaid/useMermaidRender.d.ts +2 -1
  99. package/dist/Plugins/mermaid/useMermaidRender.js +41 -13
  100. package/dist/Plugins/mermaid/utils.d.ts +16 -0
  101. package/dist/Plugins/mermaid/utils.js +197 -5
  102. package/dist/ThoughtChainList/MarkdownEditor.d.ts +1 -35
  103. package/dist/ThoughtChainList/MarkdownEditor.js +5 -44
  104. package/dist/Workspace/Browser/index.js +19 -1
  105. package/dist/Workspace/RealtimeFollow/index.d.ts +3 -0
  106. package/dist/Workspace/RealtimeFollow/index.js +5 -3
  107. package/package.json +8 -7
@@ -116,16 +116,20 @@ var SPECIAL_ENTER_BLOCK_TYPES = new Set([
116
116
  // 从 editorProps.jinja 读取(BaseMarkdownEditor 已写入 effectiveJinja),支持插件配置的 trigger
117
117
  var effectiveJinja = editorProps === null || editorProps === void 0 ? void 0 : editorProps.jinja;
118
118
  var jinjaTrigger = (effectiveJinja === null || effectiveJinja === void 0 ? void 0 : effectiveJinja.templatePanel) && _type_of(effectiveJinja.templatePanel) === 'object' && effectiveJinja.templatePanel.trigger || '{}';
119
+ var matchInputToNodeRef = useRef(false);
120
+ matchInputToNodeRef.current = (props === null || props === void 0 ? void 0 : (_props_markdown = props.markdown) === null || _props_markdown === void 0 ? void 0 : _props_markdown.matchInputToNode) === true;
119
121
  var matchKeyRef = useRef(null);
120
122
  if (matchKeyRef.current === null) {
121
- matchKeyRef.current = new MatchKey(markdownEditorRef);
123
+ matchKeyRef.current = new MatchKey(markdownEditorRef, function() {
124
+ return matchInputToNodeRef.current;
125
+ });
122
126
  }
123
127
  return useMemo(function() {
124
128
  var tab = new TabKey(markdownEditorRef.current);
125
129
  var backspace = new BackspaceKey(markdownEditorRef.current);
126
130
  var enter = new EnterKey(store, backspace);
127
131
  return function(e) {
128
- var _props_markdown, _e_nativeEvent, _node_;
132
+ var _e_nativeEvent, _node_, _e_nativeEvent1;
129
133
  // 只读模式下跳过所有键盘处理,提升性能
130
134
  if (props.readonly) return;
131
135
  // 处理表格键盘事件
@@ -173,10 +177,10 @@ var SPECIAL_ENTER_BLOCK_TYPES = new Set([
173
177
  if (isHotkey('mod+shift+s', e)) {
174
178
  e.preventDefault();
175
179
  }
176
- // 仅当显式开启 matchInputToNode 时才执行输入转节点(如 "- " 转列表),默认关闭
177
- // IME 输入法组合期间不触发,避免输入「-」后按空格选字时误转为列表
178
- if ((props === null || props === void 0 ? void 0 : (_props_markdown = props.markdown) === null || _props_markdown === void 0 ? void 0 : _props_markdown.matchInputToNode) === true && !((_e_nativeEvent = e.nativeEvent) === null || _e_nativeEvent === void 0 ? void 0 : _e_nativeEvent.isComposing)) {
179
- if (matchKeyRef.current.run(e)) return;
180
+ // Markdown 短语法转节点(``` / --- / 列表等)由 MatchKey 处理
181
+ // IME 组合期间不触发,避免选字时误转
182
+ if (!((_e_nativeEvent = e.nativeEvent) === null || _e_nativeEvent === void 0 ? void 0 : _e_nativeEvent.isComposing) && matchKeyRef.current.run(e)) {
183
+ return;
180
184
  }
181
185
  if (e.key.toLowerCase().startsWith('arrow')) {
182
186
  if ([
@@ -250,48 +254,47 @@ var SPECIAL_ENTER_BLOCK_TYPES = new Set([
250
254
  // 不在特殊块中,让 MarkdownInputField 处理发送
251
255
  return;
252
256
  }
253
- var _Editor_nodes2 = _sliced_to_array(Editor.nodes(markdownEditorRef.current, {
257
+ var sel = markdownEditorRef.current.selection;
258
+ if (!sel || !Range.isCollapsed(sel)) {
259
+ return;
260
+ }
261
+ var blockIter = Editor.nodes(markdownEditorRef.current, {
262
+ at: sel.anchor,
254
263
  match: function match(n) {
255
264
  return Element.isElement(n);
256
265
  },
257
266
  mode: 'lowest'
258
- }), 1), node2 = _Editor_nodes2[0];
259
- if (!node2) return;
260
- if ((node2 === null || node2 === void 0 ? void 0 : (_node_ = node2[0]) === null || _node_ === void 0 ? void 0 : _node_.type) === 'paragraph') {
261
- var _Editor_nodes3 = _sliced_to_array(Editor.nodes(markdownEditorRef.current, {
262
- match: function match(n) {
263
- return Element.isElement(n) && n.type === 'paragraph';
264
- },
265
- mode: 'lowest'
266
- }), 1), paraNode = _Editor_nodes3[0];
267
- var node3 = paraNode;
268
- if (node3) {
269
- var _e_nativeEvent1;
270
- var sel = markdownEditorRef.current.selection;
271
- // Jinja 触发:基于光标位置检测,支持在任意位置输入 {}(含两个模板中间)
272
- if (jinjaTemplatePanelEnabled && e.key.length === 1 && !((_e_nativeEvent1 = e.nativeEvent) === null || _e_nativeEvent1 === void 0 ? void 0 : _e_nativeEvent1.isComposing) && sel && Range.isCollapsed(sel) && Path.isAncestor(node3[1], sel.anchor.path) && setOpenJinjaTemplate && setJinjaAnchorPath) {
273
- var strBeforeCursor = Editor.string(markdownEditorRef.current, Editor.range(markdownEditorRef.current, Editor.start(markdownEditorRef.current, node3[1]), sel.anchor));
274
- var strAfterKeyAtCursor = strBeforeCursor + (e.key.length === 1 ? e.key : '');
275
- if (strAfterKeyAtCursor.endsWith(jinjaTrigger)) {
276
- setJinjaAnchorPath(node3[1]);
277
- setTimeout(function() {
278
- return setOpenJinjaTemplate(true);
279
- });
280
- return;
281
- }
282
- }
267
+ });
268
+ var blockFirst = blockIter.next();
269
+ if (blockFirst.done) {
270
+ return;
271
+ }
272
+ var node2 = blockFirst.value;
273
+ if ((node2 === null || node2 === void 0 ? void 0 : (_node_ = node2[0]) === null || _node_ === void 0 ? void 0 : _node_.type) !== 'paragraph') {
274
+ return;
275
+ }
276
+ // Jinja 触发:基于光标位置检测,支持在任意位置输入 {}(含两个模板中间)
277
+ if (jinjaTemplatePanelEnabled && e.key.length === 1 && !((_e_nativeEvent1 = e.nativeEvent) === null || _e_nativeEvent1 === void 0 ? void 0 : _e_nativeEvent1.isComposing) && Path.isAncestor(node2[1], sel.anchor.path) && setOpenJinjaTemplate && setJinjaAnchorPath) {
278
+ var strBeforeCursor = Editor.string(markdownEditorRef.current, Editor.range(markdownEditorRef.current, Editor.start(markdownEditorRef.current, node2[1]), sel.anchor));
279
+ var strAfterKeyAtCursor = strBeforeCursor + (e.key.length === 1 ? e.key : '');
280
+ if (strAfterKeyAtCursor.endsWith(jinjaTrigger)) {
281
+ setJinjaAnchorPath(node2[1]);
282
+ setTimeout(function() {
283
+ return setOpenJinjaTemplate(true);
284
+ });
285
+ return;
283
286
  }
284
- if (node3 && node3[0].children.length === 1 && !EditorUtils.isDirtLeaf(node3[0].children[0]) && (e.key === 'Backspace' || /^[^\n]$/.test(e.key))) {
285
- var str = Node.string(node3[0]) || '';
286
- var codeMatch = str.match(/^```([\w+\-#]+)$/i);
287
- if (codeMatch) {} else {
288
- var insertMatch = str.match(/^\/([^\n]+)?$/i);
289
- if (insertMatch && !(!Path.hasPrevious(node3[1]) && Node.parent(markdownEditorRef.current, node3[1]).type === 'list-item')) {
290
- setOpenInsertCompletion === null || setOpenInsertCompletion === void 0 ? void 0 : setOpenInsertCompletion(true);
291
- setTimeout(function() {
292
- insertCompletionText$.next(insertMatch[1]);
293
- });
294
- }
287
+ }
288
+ if (node2[0].children.length === 1 && !EditorUtils.isDirtLeaf(node2[0].children[0]) && (e.key === 'Backspace' || /^[^\n]$/.test(e.key))) {
289
+ var str = Node.string(node2[0]) || '';
290
+ var codeMatch = str.match(/^```([\w+\-#]+)$/i);
291
+ if (!codeMatch) {
292
+ var insertMatch = str.match(/^\/([^\n]+)?$/i);
293
+ if (insertMatch && !(!Path.hasPrevious(node2[1]) && Node.parent(markdownEditorRef.current, node2[1]).type === 'list-item')) {
294
+ setOpenInsertCompletion === null || setOpenInsertCompletion === void 0 ? void 0 : setOpenInsertCompletion(true);
295
+ setTimeout(function() {
296
+ insertCompletionText$.next(insertMatch[1]);
297
+ });
295
298
  }
296
299
  }
297
300
  }
@@ -299,7 +302,6 @@ var SPECIAL_ENTER_BLOCK_TYPES = new Set([
299
302
  }, [
300
303
  markdownEditorRef.current,
301
304
  props === null || props === void 0 ? void 0 : props.readonly,
302
- props === null || props === void 0 ? void 0 : (_props_markdown = props.markdown) === null || _props_markdown === void 0 ? void 0 : _props_markdown.matchInputToNode,
303
305
  openInsertCompletion,
304
306
  insertCompletionText$,
305
307
  setOpenInsertCompletion,
@@ -168,19 +168,7 @@ import { hasRange } from "./utils";
168
168
  }
169
169
  }
170
170
  if ((currentNode1 === null || currentNode1 === void 0 ? void 0 : currentNode1.tag) && operation.text.trim().length > 0 && currentNode1.text.trim().length === 0) {
171
- Editor.withoutNormalizing(editor, function() {
172
- Transforms.removeNodes(editor, {
173
- at: operation.path
174
- });
175
- Transforms.insertNodes(editor, _object_spread_props(_object_spread({}, currentNode1), {
176
- tag: true,
177
- code: true,
178
- text: operation.text
179
- }), {
180
- at: operation.path,
181
- select: true
182
- });
183
- });
171
+ apply(operation);
184
172
  return true;
185
173
  }
186
174
  }
@@ -203,6 +203,18 @@ export declare class EditorStore {
203
203
  * 取消当前正在进行的 setMDContent 操作
204
204
  */
205
205
  cancelSetMDContent(): void;
206
+ /**
207
+ * 安全地取消编辑器选区。
208
+ *
209
+ * ReactEditor.deselect() 内部调用 window.getSelection().removeAllRanges(),
210
+ * 当编辑器处于聚焦状态时,浏览器要求必须存在活跃选区才能操作,
211
+ * 否则抛出 InvalidStateError("Failed to execute 'collapseToEnd' on 'Selection'")。
212
+ *
213
+ * 双重防御策略:
214
+ * 1. isFocused 检查 —— 大多数情况下直接跳过(性能优先)
215
+ * 2. try-catch —— 覆盖 isFocused 与 deselect 之间的竞态窗口
216
+ */
217
+ private _safeDeselect;
206
218
  /**
207
219
  * 使用 requestAnimationFrame 分批解析和设置内容
208
220
  * 边解析边插入,实时显示内容
@@ -650,7 +662,9 @@ export declare class EditorStore {
650
662
  maxResults?: number;
651
663
  }): {
652
664
  path: Path;
653
- range: import("slate").BaseRange;
665
+ range: import("slate").BaseRange; /**
666
+ * 更新结构不同的表格
667
+ */
654
668
  node: any;
655
669
  matchedText: string;
656
670
  offset: {
@@ -237,9 +237,13 @@ export var EditorStoreContext = createContext(null);
237
237
  value: function focus() {
238
238
  var editor = this._editor.current;
239
239
  try {
240
- // 1. 确保编辑器获得焦点
240
+ // 1. 确保编辑器获得焦点(异步,需要单独 try-catch 防止白屏)
241
241
  setTimeout(function() {
242
- return ReactEditor.focus(editor);
242
+ try {
243
+ ReactEditor.focus(editor);
244
+ } catch (e) {
245
+ console.error('ReactEditor.focus 失败:', e);
246
+ }
243
247
  }, 0);
244
248
  // 2. 处理空文档情况
245
249
  if (editor.children.length === 0) {
@@ -400,8 +404,7 @@ export var EditorStoreContext = createContext(null);
400
404
  * Clears all content from the editor, replacing it with an empty paragraph.
401
405
  */ key: "clearContent",
402
406
  value: function clearContent() {
403
- this._editor.current.selection = null;
404
- this._editor.current.children = [
407
+ EditorUtils.replaceEditorContent(this._editor.current, [
405
408
  {
406
409
  type: 'paragraph',
407
410
  children: [
@@ -410,7 +413,7 @@ export var EditorStoreContext = createContext(null);
410
413
  }
411
414
  ]
412
415
  }
413
- ];
416
+ ]);
414
417
  }
415
418
  },
416
419
  {
@@ -474,9 +477,9 @@ export var EditorStoreContext = createContext(null);
474
477
  */ function _setShortContent(md, plugins, onProgress) {
475
478
  try {
476
479
  var nodeList = parserMdToSchema(md, plugins).schema;
480
+ this._editor.current.selection = null;
477
481
  this.setContent(nodeList);
478
- this._editor.current.children = nodeList;
479
- ReactEditor.deselect(this._editor.current);
482
+ this._safeDeselect();
480
483
  onProgress === null || onProgress === void 0 ? void 0 : onProgress(1);
481
484
  } catch (error) {
482
485
  console.error('Failed to set MD content:', error);
@@ -492,9 +495,9 @@ export var EditorStoreContext = createContext(null);
492
495
  try {
493
496
  var allNodes = this._parseChunksToNodes(chunks, plugins);
494
497
  if (allNodes.length > 0) {
498
+ this._editor.current.selection = null;
495
499
  this.setContent(allNodes);
496
- this._editor.current.children = allNodes;
497
- ReactEditor.deselect(this._editor.current);
500
+ this._safeDeselect();
498
501
  }
499
502
  onProgress === null || onProgress === void 0 ? void 0 : onProgress(1);
500
503
  } catch (error) {
@@ -547,6 +550,27 @@ export var EditorStoreContext = createContext(null);
547
550
  }
548
551
  }
549
552
  },
553
+ {
554
+ key: "_safeDeselect",
555
+ value: /**
556
+ * 安全地取消编辑器选区。
557
+ *
558
+ * ReactEditor.deselect() 内部调用 window.getSelection().removeAllRanges(),
559
+ * 当编辑器处于聚焦状态时,浏览器要求必须存在活跃选区才能操作,
560
+ * 否则抛出 InvalidStateError("Failed to execute 'collapseToEnd' on 'Selection'")。
561
+ *
562
+ * 双重防御策略:
563
+ * 1. isFocused 检查 —— 大多数情况下直接跳过(性能优先)
564
+ * 2. try-catch —— 覆盖 isFocused 与 deselect 之间的竞态窗口
565
+ */ function _safeDeselect() {
566
+ if (ReactEditor.isFocused(this._editor.current)) return;
567
+ try {
568
+ ReactEditor.deselect(this._editor.current);
569
+ } catch (unused) {
570
+ // InvalidStateError:编辑器在 isFocused 检查与 deselect 调用之间获得了焦点,忽略即可
571
+ }
572
+ }
573
+ },
550
574
  {
551
575
  key: "_parseAndSetContentWithRAF",
552
576
  value: /**
@@ -599,9 +623,7 @@ export var EditorStoreContext = createContext(null);
599
623
  var schema = parserMdToSchema(chunk, plugins).schema;
600
624
  if (schema.length > 0) {
601
625
  if (isFirstBatch) {
602
- // 第一批:清空并插入
603
- _this._editor.current.children = schema;
604
- _this._editor.current.onChange();
626
+ EditorUtils.replaceEditorContent(_this._editor.current, schema);
605
627
  isFirstBatch = false;
606
628
  } else {
607
629
  // 后续批次:追加节点
@@ -634,7 +656,7 @@ export var EditorStoreContext = createContext(null);
634
656
  rafId = requestAnimationFrame(parseAndInsertNextBatch);
635
657
  } else {
636
658
  // 所有内容处理完成
637
- ReactEditor.deselect(_this._editor.current);
659
+ _this._safeDeselect();
638
660
  rafId = null;
639
661
  _this._currentAbortController = null;
640
662
  resolve();
@@ -885,11 +907,14 @@ export var EditorStoreContext = createContext(null);
885
907
  * @param newNode - 新节点
886
908
  * @private
887
909
  */ function _replaceNodeAt(path, newNode) {
888
- Transforms.removeNodes(this._editor.current, {
889
- at: path
890
- });
891
- Transforms.insertNodes(this._editor.current, newNode, {
892
- at: path
910
+ var _this = this;
911
+ Editor.withoutNormalizing(this._editor.current, function() {
912
+ Transforms.removeNodes(_this._editor.current, {
913
+ at: path
914
+ });
915
+ Transforms.insertNodes(_this._editor.current, newNode, {
916
+ at: path
917
+ });
893
918
  });
894
919
  }
895
920
  },
@@ -900,21 +925,7 @@ export var EditorStoreContext = createContext(null);
900
925
  * @param nodeList - 要设置为编辑器内容的节点列表
901
926
  */ key: "setContent",
902
927
  value: function setContent(nodeList) {
903
- var currentChildren = this._editor.current.children;
904
- this._editor.current.children = nodeList;
905
- this._editor.current.onChange();
906
- // 检查最后一个节点是否以换行符结尾
907
- var lastNode = currentChildren[currentChildren.length - 1];
908
- if (lastNode && Text.isText(lastNode)) {
909
- var text = Node.string(lastNode);
910
- if (!text.endsWith('\n')) {
911
- this._editor.current.insertText('\n', {
912
- at: [
913
- currentChildren.length - 1
914
- ]
915
- });
916
- }
917
- }
928
+ EditorUtils.replaceEditorContent(this._editor.current, nodeList);
918
929
  }
919
930
  },
920
931
  {
@@ -954,7 +965,7 @@ export var EditorStoreContext = createContext(null);
954
965
  }
955
966
  } catch (error) {
956
967
  console.error('Failed to update nodes with optimized method:', error);
957
- this._editor.current.children = nodeList;
968
+ EditorUtils.replaceEditorContent(this._editor.current, nodeList);
958
969
  }
959
970
  }
960
971
  },
@@ -936,18 +936,22 @@ export var InsertAutocomplete = function InsertAutocomplete(props) {
936
936
  isTop: EditorUtils.isTop(markdownEditorRef.current, node[1])
937
937
  };
938
938
  if ((node === null || node === void 0 ? void 0 : (_node_ = node[0]) === null || _node_ === void 0 ? void 0 : _node_.type) === 'paragraph') {
939
- var el = ReactEditor.toDOMNode(markdownEditorRef.current, node[0]);
940
- if (el) {
941
- var position = calculatePosition(el, document.body);
942
- if (position) {
943
- setState(position);
944
- } else {
945
- setState({
946
- top: 0,
947
- left: 0,
948
- bottom: undefined
949
- });
939
+ try {
940
+ var el = ReactEditor.toDOMNode(markdownEditorRef.current, node[0]);
941
+ if (el) {
942
+ var position = calculatePosition(el, document.body);
943
+ if (position) {
944
+ setState(position);
945
+ } else {
946
+ setState({
947
+ top: 0,
948
+ left: 0,
949
+ bottom: undefined
950
+ });
951
+ }
950
952
  }
953
+ } catch (unused) {
954
+ // node may not be mounted yet; position update skipped
951
955
  }
952
956
  }
953
957
  setupEventListeners();
@@ -98,6 +98,73 @@ import { EditorUtils } from "./editorUtils";
98
98
  }
99
99
  });
100
100
  }
101
+ /** 光标所在段落/标题;避免 getCurrentNodes 取到 list-item 等子块导致插入路径错误 */ function resolveParagraphOrHead(editor, preferred) {
102
+ if ((preferred === null || preferred === void 0 ? void 0 : preferred[0]) && [
103
+ 'paragraph',
104
+ 'head'
105
+ ].includes(preferred[0].type)) {
106
+ return preferred;
107
+ }
108
+ var selection = editor.selection;
109
+ if (selection) {
110
+ var above = Editor.above(editor, {
111
+ at: selection.anchor,
112
+ match: function match(n) {
113
+ return Element.isElement(n) && [
114
+ 'paragraph',
115
+ 'head'
116
+ ].includes(n.type);
117
+ }
118
+ });
119
+ if (above) {
120
+ return above;
121
+ }
122
+ }
123
+ var nodesResult = Editor.nodes(editor, {
124
+ at: [],
125
+ match: function match(n) {
126
+ return Element.isElement(n) && [
127
+ 'paragraph',
128
+ 'head'
129
+ ].includes(n.type);
130
+ },
131
+ mode: 'lowest'
132
+ });
133
+ if (Array.isArray(nodesResult) && nodesResult.length > 0) {
134
+ var entry = nodesResult[0];
135
+ if ((entry === null || entry === void 0 ? void 0 : entry[0]) && [
136
+ 'paragraph',
137
+ 'head'
138
+ ].includes(entry[0].type)) {
139
+ return entry;
140
+ }
141
+ return undefined;
142
+ }
143
+ var iter = nodesResult;
144
+ if (iter && typeof iter.next === 'function') {
145
+ var first = iter.next();
146
+ return first.done ? undefined : first.value;
147
+ }
148
+ return undefined;
149
+ }
150
+ function firstLowestElement(editor) {
151
+ var nodesResult = Editor.nodes(editor, {
152
+ at: [],
153
+ match: function match(n) {
154
+ return Element.isElement(n);
155
+ },
156
+ mode: 'lowest'
157
+ });
158
+ if (Array.isArray(nodesResult) && nodesResult.length > 0) {
159
+ return nodesResult[0];
160
+ }
161
+ var iter = nodesResult;
162
+ if (iter && typeof iter.next === 'function') {
163
+ var first = iter.next();
164
+ return first.done ? undefined : first.value;
165
+ }
166
+ return undefined;
167
+ }
101
168
  /**
102
169
  * 插入表格
103
170
  *
@@ -108,38 +175,44 @@ import { EditorUtils } from "./editorUtils";
108
175
  * @param editor Slate 编辑器实例
109
176
  * @param node 可选的节点,如果不提供则从编辑器获取
110
177
  */ export function insertTable(editor, node) {
111
- var _currentNode_, _currentNode_1;
112
- var currentNode = node || Array.from(getCurrentNodes(editor))[0];
178
+ var _resolveParagraphOrHead;
179
+ var _node_, _node_1, _currentNode_;
180
+ if ((node === null || node === void 0 ? void 0 : (_node_ = node[0]) === null || _node_ === void 0 ? void 0 : _node_.type) === 'column-cell') {
181
+ NativeTableEditor.insertTable(editor, {
182
+ rows: 3,
183
+ cols: 3,
184
+ at: _to_consumable_array(node[1]).concat([
185
+ 0
186
+ ])
187
+ });
188
+ return;
189
+ }
190
+ if (node !== undefined && ![
191
+ 'paragraph',
192
+ 'head'
193
+ ].includes((_node_1 = node[0]) === null || _node_1 === void 0 ? void 0 : _node_1.type)) {
194
+ return;
195
+ }
196
+ var currentNode = node === undefined ? (_resolveParagraphOrHead = resolveParagraphOrHead(editor)) !== null && _resolveParagraphOrHead !== void 0 ? _resolveParagraphOrHead : firstLowestElement(editor) : resolveParagraphOrHead(editor, node);
113
197
  if (currentNode && [
114
198
  'paragraph',
115
199
  'head'
116
200
  ].includes(currentNode === null || currentNode === void 0 ? void 0 : (_currentNode_ = currentNode[0]) === null || _currentNode_ === void 0 ? void 0 : _currentNode_.type)) {
117
- var _currentNode_2, _currentNode_3;
118
- var path = (currentNode === null || currentNode === void 0 ? void 0 : (_currentNode_2 = currentNode[0]) === null || _currentNode_2 === void 0 ? void 0 : _currentNode_2.type) === 'paragraph' && !Node.string(currentNode[0]) ? currentNode[1] : Path.next(currentNode[1]);
201
+ var _currentNode_1, _currentNode_2;
202
+ var path = (currentNode === null || currentNode === void 0 ? void 0 : (_currentNode_1 = currentNode[0]) === null || _currentNode_1 === void 0 ? void 0 : _currentNode_1.type) === 'paragraph' && !Node.string(currentNode[0]) ? currentNode[1] : Path.next(currentNode[1]);
119
203
  // 使用原生表格编辑器插入表格
120
204
  NativeTableEditor.insertTable(editor, {
121
205
  rows: 3,
122
206
  cols: 3,
123
207
  at: path
124
208
  });
125
- if ((currentNode === null || currentNode === void 0 ? void 0 : (_currentNode_3 = currentNode[0]) === null || _currentNode_3 === void 0 ? void 0 : _currentNode_3.type) === 'paragraph' && !Node.string(currentNode[0])) {
209
+ if ((currentNode === null || currentNode === void 0 ? void 0 : (_currentNode_2 = currentNode[0]) === null || _currentNode_2 === void 0 ? void 0 : _currentNode_2.type) === 'paragraph' && !Node.string(currentNode[0])) {
126
210
  Transforms.delete(editor, {
127
211
  at: Path.next(path)
128
212
  });
129
213
  }
130
214
  Transforms.select(editor, Editor.start(editor, path));
131
215
  }
132
- if (currentNode && [
133
- 'column-cell'
134
- ].includes(currentNode === null || currentNode === void 0 ? void 0 : (_currentNode_1 = currentNode[0]) === null || _currentNode_1 === void 0 ? void 0 : _currentNode_1.type)) {
135
- NativeTableEditor.insertTable(editor, {
136
- rows: 3,
137
- cols: 3,
138
- at: _to_consumable_array(currentNode[1]).concat([
139
- 0
140
- ])
141
- });
142
- }
143
216
  }
144
217
  /**
145
218
  * 插入代码块
@@ -151,7 +224,15 @@ import { EditorUtils } from "./editorUtils";
151
224
  * @param type 可选的代码块类型,'mermaid'表示流程图,'html'表示HTML渲染
152
225
  * @param node 可选的节点,如果不提供则从编辑器获取
153
226
  */ export function insertCodeBlock(editor, type, node) {
154
- var currentNode = node || Array.from(getCurrentNodes(editor))[0];
227
+ var _resolveParagraphOrHead;
228
+ var _node_;
229
+ if (node !== undefined && ![
230
+ 'paragraph',
231
+ 'head'
232
+ ].includes((_node_ = node[0]) === null || _node_ === void 0 ? void 0 : _node_.type)) {
233
+ return;
234
+ }
235
+ var currentNode = node === undefined ? (_resolveParagraphOrHead = resolveParagraphOrHead(editor)) !== null && _resolveParagraphOrHead !== void 0 ? _resolveParagraphOrHead : firstLowestElement(editor) : resolveParagraphOrHead(editor, node);
155
236
  if (currentNode && currentNode[0] && [
156
237
  'paragraph',
157
238
  'head'
@@ -11,6 +11,17 @@ export declare class EditorUtils {
11
11
  readonly text: "";
12
12
  }];
13
13
  };
14
+ /**
15
+ * 通过 Slate Transforms API 安全替换编辑器全部内容。
16
+ * 避免直接赋值 editor.children,确保 Operation/History/Normalizer 管线正常运行。
17
+ *
18
+ * @param editor - 编辑器实例
19
+ * @param nodes - 新的节点列表
20
+ * @param options.withoutHistory - 是否跳过 History 记录(默认 true,适用于外部数据同步场景)
21
+ */
22
+ static replaceEditorContent(editor: Editor, nodes: Node[], options?: {
23
+ withoutHistory?: boolean;
24
+ }): void;
14
25
  static hasPath(editor: Editor, path: Path): boolean;
15
26
  static focus(editor: Editor): void;
16
27
  static blur(editor: Editor): void;
@@ -135,6 +135,7 @@ function _unsupported_iterable_to_array(o, minLen) {
135
135
  if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
136
136
  }
137
137
  /* eslint-disable no-param-reassign */ import { Editor, Element, Node, Path, Point, Range, Text, Transforms } from "slate";
138
+ import { HistoryEditor } from "slate-history";
138
139
  import { ReactEditor } from "slate-react";
139
140
  import { getMediaType } from "./dom";
140
141
  export var EditorUtils = /*#__PURE__*/ function() {
@@ -156,6 +157,44 @@ export var EditorUtils = /*#__PURE__*/ function() {
156
157
  };
157
158
  }
158
159
  },
160
+ {
161
+ key: "replaceEditorContent",
162
+ value: /**
163
+ * 通过 Slate Transforms API 安全替换编辑器全部内容。
164
+ * 避免直接赋值 editor.children,确保 Operation/History/Normalizer 管线正常运行。
165
+ *
166
+ * @param editor - 编辑器实例
167
+ * @param nodes - 新的节点列表
168
+ * @param options.withoutHistory - 是否跳过 History 记录(默认 true,适用于外部数据同步场景)
169
+ */ function replaceEditorContent(editor, nodes, options) {
170
+ var _ref = options || {}, _ref_withoutHistory = _ref.withoutHistory, withoutHistory = _ref_withoutHistory === void 0 ? true : _ref_withoutHistory;
171
+ var doReplace = function doReplace() {
172
+ Editor.withoutNormalizing(editor, function() {
173
+ if (editor.selection) {
174
+ Transforms.deselect(editor);
175
+ }
176
+ var totalChildren = editor.children.length;
177
+ for(var i = totalChildren - 1; i >= 0; i--){
178
+ Transforms.removeNodes(editor, {
179
+ at: [
180
+ i
181
+ ]
182
+ });
183
+ }
184
+ Transforms.insertNodes(editor, nodes, {
185
+ at: [
186
+ 0
187
+ ]
188
+ });
189
+ });
190
+ };
191
+ if (withoutHistory && HistoryEditor.isHistoryEditor(editor)) {
192
+ HistoryEditor.withoutSaving(editor, doReplace);
193
+ } else {
194
+ doReplace();
195
+ }
196
+ }
197
+ },
159
198
  {
160
199
  key: "hasPath",
161
200
  value: function hasPath(editor, path) {
@@ -485,18 +524,16 @@ export var EditorUtils = /*#__PURE__*/ function() {
485
524
  * @param insertNodes - 可选的插入节点数组。如果未提供,则使用默认段落节点
486
525
  * @param force - 可选的布尔值或历史记录对象。如果为布尔值,则强制重置历史记录;如果为历史记录对象,则使用提供的历史记录
487
526
  */ function reset(editor, insertNodes, force) {
488
- var nodesToInsert = insertNodes || [
527
+ var nodesToInsert = JSON.parse(JSON.stringify(insertNodes || [
489
528
  EditorUtils.p
490
- ];
491
- // 深克隆节点以避免引用问题
492
- editor.children = JSON.parse(JSON.stringify(nodesToInsert));
493
- if (force) {
529
+ ]));
530
+ EditorUtils.replaceEditorContent(editor, nodesToInsert);
531
+ if (force && HistoryEditor.isHistoryEditor(editor)) {
494
532
  editor.history = typeof force === 'boolean' ? {
495
533
  redos: [],
496
534
  undos: []
497
535
  } : force;
498
536
  }
499
- editor.onChange();
500
537
  }
501
538
  },
502
539
  {