@ant-design/agentic-ui 2.30.26 → 2.30.27
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/dist/MarkdownEditor/BaseMarkdownEditor.js +17 -4
- package/dist/MarkdownEditor/editor/elements/Paragraph/ReadonlyParagraph.d.ts +2 -2
- package/dist/MarkdownEditor/editor/elements/Paragraph/ReadonlyParagraph.js +2 -8
- package/dist/MarkdownEditor/editor/elements/Paragraph/index.js +25 -14
- package/dist/MarkdownEditor/editor/plugins/withSanitizeInvalidChildren.js +11 -0
- package/dist/MarkdownEditor/editor/store.d.ts +0 -3
- package/dist/MarkdownEditor/editor/utils/editorUtils.d.ts +6 -0
- package/dist/MarkdownEditor/editor/utils/editorUtils.js +28 -1
- package/package.json +1 -2
|
@@ -231,6 +231,8 @@ var I18nBoundary = function I18nBoundary(param) {
|
|
|
231
231
|
// markdown 编辑器实例
|
|
232
232
|
var markdownEditorRef = useRef(composeEditors(withMarkdown(withReact(withHistory(createEditor()))), props.plugins || []));
|
|
233
233
|
var markdownContainerRef = useRef(null);
|
|
234
|
+
var pluginsForInitParseRef = useRef(props.plugins);
|
|
235
|
+
pluginsForInitParseRef.current = props.plugins;
|
|
234
236
|
// 错误捕获
|
|
235
237
|
useEffect(function() {
|
|
236
238
|
withErrorReporting(markdownEditorRef.current);
|
|
@@ -282,7 +284,7 @@ var I18nBoundary = function I18nBoundary(param) {
|
|
|
282
284
|
* 初始化 schema
|
|
283
285
|
*/ var initSchemaValue = useMemo(function() {
|
|
284
286
|
// 安全地获取解析结果,确保 list 始终是数组
|
|
285
|
-
var parseResult = parserMdToSchema(initValue || '',
|
|
287
|
+
var parseResult = parserMdToSchema(initValue || '', pluginsForInitParseRef.current || []);
|
|
286
288
|
var list = (parseResult === null || parseResult === void 0 ? void 0 : parseResult.schema) || [];
|
|
287
289
|
// 非只读时保证末尾有可编辑块:解析结果常已含空段落(如空 initValue),
|
|
288
290
|
// 再追加会导致 Slate 根下两个空段,Paragraph 的占位符依赖 children.length===1 而失效
|
|
@@ -296,7 +298,7 @@ var I18nBoundary = function I18nBoundary(param) {
|
|
|
296
298
|
EditorUtils.p
|
|
297
299
|
])));
|
|
298
300
|
// 过滤掉无效的空节点
|
|
299
|
-
|
|
301
|
+
var filtered = (schema === null || schema === void 0 ? void 0 : schema.filter(function(item) {
|
|
300
302
|
if (item.type === 'paragraph' && item.children.length === 0) {
|
|
301
303
|
return false;
|
|
302
304
|
}
|
|
@@ -310,8 +312,13 @@ var I18nBoundary = function I18nBoundary(param) {
|
|
|
310
312
|
return false;
|
|
311
313
|
}
|
|
312
314
|
return true;
|
|
313
|
-
});
|
|
314
|
-
|
|
315
|
+
})) || [];
|
|
316
|
+
return EditorUtils.coalesceRootAllEmptyParagraphs(filtered);
|
|
317
|
+
}, [
|
|
318
|
+
initValue,
|
|
319
|
+
props.readonly,
|
|
320
|
+
props.initSchemaValue
|
|
321
|
+
]);
|
|
315
322
|
// 初始化实例
|
|
316
323
|
var instance = useMemo(function() {
|
|
317
324
|
return {
|
|
@@ -347,6 +354,12 @@ var I18nBoundary = function I18nBoundary(param) {
|
|
|
347
354
|
var _useState2 = _sliced_to_array(useState([]), 2), showCommentList = _useState2[0], setShowComment = _useState2[1];
|
|
348
355
|
// schema 数据
|
|
349
356
|
var _useState3 = _sliced_to_array(useState(initSchemaValue), 2), schema = _useState3[0], setSchema = _useState3[1];
|
|
357
|
+
// initSchemaValue 随 initValue / initSchemaValue prop 变化时同步到 state,供 Toc 等与编辑器树一致
|
|
358
|
+
useEffect(function() {
|
|
359
|
+
setSchema(initSchemaValue);
|
|
360
|
+
}, [
|
|
361
|
+
initSchemaValue
|
|
362
|
+
]);
|
|
350
363
|
var _useState4 = _sliced_to_array(useState(false), 2), openInsertCompletion = _useState4[0], setOpenInsertCompletion = _useState4[1];
|
|
351
364
|
var _useState5 = _sliced_to_array(useState(false), 2), refreshFloatBar = _useState5[0], setRefreshFloatBar = _useState5[1];
|
|
352
365
|
var insertCompletionText$ = useMemo(function() {
|
|
@@ -8,7 +8,7 @@ import { ElementProps, ParagraphNode } from '../../../el';
|
|
|
8
8
|
*
|
|
9
9
|
* @component
|
|
10
10
|
* @description 只读段落预览组件,用于预览模式下的段落渲染
|
|
11
|
-
* @param {ElementProps<ParagraphNode>} props -
|
|
11
|
+
* @param {ElementProps<ParagraphNode>} props - 段落组件属性
|
|
12
12
|
* @param {ParagraphNode} props.element - 段落节点元素
|
|
13
13
|
* @param {React.ReactNode} props.children - 子组件内容
|
|
14
14
|
* @param {Object} props.attributes - 元素属性
|
|
@@ -23,7 +23,7 @@ import { ElementProps, ParagraphNode } from '../../../el';
|
|
|
23
23
|
* </ReadonlyParagraph>
|
|
24
24
|
* ```
|
|
25
25
|
*
|
|
26
|
-
* @returns {React.ReactElement}
|
|
26
|
+
* @returns {React.ReactElement}
|
|
27
27
|
*
|
|
28
28
|
* @remarks
|
|
29
29
|
* - 移除拖拽手柄(DragHandle)
|
|
@@ -52,7 +52,6 @@ function _object_spread_props(target, source) {
|
|
|
52
52
|
}
|
|
53
53
|
import classNames from "clsx";
|
|
54
54
|
import React from "react";
|
|
55
|
-
import { Element, Node } from "slate";
|
|
56
55
|
/**
|
|
57
56
|
* ReadonlyParagraph 组件 - 只读段落预览组件
|
|
58
57
|
*
|
|
@@ -61,7 +60,7 @@ import { Element, Node } from "slate";
|
|
|
61
60
|
*
|
|
62
61
|
* @component
|
|
63
62
|
* @description 只读段落预览组件,用于预览模式下的段落渲染
|
|
64
|
-
* @param {ElementProps<ParagraphNode>} props -
|
|
63
|
+
* @param {ElementProps<ParagraphNode>} props - 段落组件属性
|
|
65
64
|
* @param {ParagraphNode} props.element - 段落节点元素
|
|
66
65
|
* @param {React.ReactNode} props.children - 子组件内容
|
|
67
66
|
* @param {Object} props.attributes - 元素属性
|
|
@@ -76,7 +75,7 @@ import { Element, Node } from "slate";
|
|
|
76
75
|
* </ReadonlyParagraph>
|
|
77
76
|
* ```
|
|
78
77
|
*
|
|
79
|
-
* @returns {React.ReactElement}
|
|
78
|
+
* @returns {React.ReactElement}
|
|
80
79
|
*
|
|
81
80
|
* @remarks
|
|
82
81
|
* - 移除拖拽手柄(DragHandle)
|
|
@@ -87,17 +86,12 @@ import { Element, Node } from "slate";
|
|
|
87
86
|
*/ export var ReadonlyParagraph = /*#__PURE__*/ React.memo(function(props) {
|
|
88
87
|
var _props_element_align;
|
|
89
88
|
var _props_element_otherProps;
|
|
90
|
-
var str = Node.string(props.element).trim();
|
|
91
89
|
var align = (_props_element_align = props.element.align) !== null && _props_element_align !== void 0 ? _props_element_align : (_props_element_otherProps = props.element.otherProps) === null || _props_element_otherProps === void 0 ? void 0 : _props_element_otherProps.align;
|
|
92
|
-
var hasNestedElement = props.element.children.some(function(child) {
|
|
93
|
-
return Element.isElement(child);
|
|
94
|
-
});
|
|
95
90
|
return /*#__PURE__*/ React.createElement("div", _object_spread_props(_object_spread({}, props.attributes), {
|
|
96
91
|
"data-be": 'paragraph',
|
|
97
92
|
className: classNames({}),
|
|
98
93
|
"data-align": align,
|
|
99
94
|
style: {
|
|
100
|
-
display: str || hasNestedElement ? undefined : 'none',
|
|
101
95
|
textAlign: align
|
|
102
96
|
}
|
|
103
97
|
}), props.children);
|
|
@@ -97,12 +97,13 @@ function _unsupported_iterable_to_array(o, minLen) {
|
|
|
97
97
|
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
|
|
98
98
|
}
|
|
99
99
|
import classNames from "clsx";
|
|
100
|
-
import React, { useContext } from "react";
|
|
101
|
-
import {
|
|
100
|
+
import React, { useContext, useEffect, useState } from "react";
|
|
101
|
+
import { Node } from "slate";
|
|
102
102
|
import { I18nContext } from "../../../../I18n";
|
|
103
103
|
import { debugInfo } from "../../../../Utils/debugUtils";
|
|
104
104
|
import { useSelStatus } from "../../../hooks/editor";
|
|
105
105
|
import { useEditorStore } from "../../store";
|
|
106
|
+
import { DragHandle } from "../../tools/DragHandle";
|
|
106
107
|
export var Paragraph = function Paragraph(props) {
|
|
107
108
|
var _props_element_align;
|
|
108
109
|
var _props_element_otherProps, _markdownEditorRef_current;
|
|
@@ -114,6 +115,25 @@ export var Paragraph = function Paragraph(props) {
|
|
|
114
115
|
var _useEditorStore = useEditorStore(), store = _useEditorStore.store, markdownEditorRef = _useEditorStore.markdownEditorRef, markdownContainerRef = _useEditorStore.markdownContainerRef, readonly = _useEditorStore.readonly, editorProps = _useEditorStore.editorProps;
|
|
115
116
|
var locale = useContext(I18nContext).locale;
|
|
116
117
|
var _useSelStatus = _sliced_to_array(useSelStatus(props.element), 1), selected = _useSelStatus[0];
|
|
118
|
+
var _useState = _sliced_to_array(useState(false), 2), isComposing = _useState[0], setIsComposing = _useState[1];
|
|
119
|
+
useEffect(function() {
|
|
120
|
+
var container = markdownContainerRef.current;
|
|
121
|
+
if (!container) return;
|
|
122
|
+
var observer = new MutationObserver(function() {
|
|
123
|
+
setIsComposing(container.hasAttribute('data-composition'));
|
|
124
|
+
});
|
|
125
|
+
observer.observe(container, {
|
|
126
|
+
attributes: true,
|
|
127
|
+
attributeFilter: [
|
|
128
|
+
'data-composition'
|
|
129
|
+
]
|
|
130
|
+
});
|
|
131
|
+
return function() {
|
|
132
|
+
return observer.disconnect();
|
|
133
|
+
};
|
|
134
|
+
}, [
|
|
135
|
+
markdownContainerRef
|
|
136
|
+
]);
|
|
117
137
|
return React.useMemo(function() {
|
|
118
138
|
var _props_element_children_every, _props_element_children, _props_element, _markdownEditorRef_current;
|
|
119
139
|
var str = Node.string(props.element).trim();
|
|
@@ -123,17 +143,10 @@ export var Paragraph = function Paragraph(props) {
|
|
|
123
143
|
readonly: readonly,
|
|
124
144
|
align: align
|
|
125
145
|
});
|
|
126
|
-
// 检查是否为空:trim 后的字符串为空(包括只包含空格的情况),且所有子节点都是纯文本节点(没有 type、code、tag)
|
|
127
|
-
// 当只输入空格时,trim() 后为空字符串,应该显示 placeholder
|
|
128
146
|
var hasOnlyTextNodes = (_props_element = props.element) === null || _props_element === void 0 ? void 0 : (_props_element_children = _props_element.children) === null || _props_element_children === void 0 ? void 0 : (_props_element_children_every = _props_element_children.every) === null || _props_element_children_every === void 0 ? void 0 : _props_element_children_every.call(_props_element_children, function(child) {
|
|
129
147
|
return !child.type && !child.code && !child.tag;
|
|
130
148
|
});
|
|
131
|
-
var
|
|
132
|
-
return Element.isElement(child);
|
|
133
|
-
});
|
|
134
|
-
// 组合输入进行中时,Slate 模型尚未更新(字符还在 IME 候选区),
|
|
135
|
-
// 此时强制视为非空以隐藏占位符,避免用户输入时占位符仍然可见。
|
|
136
|
-
var isEmpty = !str && ((_markdownEditorRef_current = markdownEditorRef.current) === null || _markdownEditorRef_current === void 0 ? void 0 : _markdownEditorRef_current.children.length) === 1 && hasOnlyTextNodes ? true : undefined;
|
|
149
|
+
var isEmpty = !str && !isComposing && ((_markdownEditorRef_current = markdownEditorRef.current) === null || _markdownEditorRef_current === void 0 ? void 0 : _markdownEditorRef_current.children.length) === 1 && hasOnlyTextNodes ? true : undefined;
|
|
137
150
|
return /*#__PURE__*/ React.createElement("div", _object_spread_props(_object_spread({}, props.attributes), {
|
|
138
151
|
"data-be": 'paragraph',
|
|
139
152
|
"data-drag-el": true,
|
|
@@ -147,16 +160,14 @@ export var Paragraph = function Paragraph(props) {
|
|
|
147
160
|
},
|
|
148
161
|
"data-empty": isEmpty,
|
|
149
162
|
style: {
|
|
150
|
-
display: str || hasNestedElement ? undefined : 'none',
|
|
151
163
|
textAlign: align
|
|
152
164
|
}
|
|
153
|
-
}), props.children);
|
|
165
|
+
}), /*#__PURE__*/ React.createElement(DragHandle, null), props.children);
|
|
154
166
|
}, [
|
|
155
|
-
props.element,
|
|
156
167
|
props.element.children,
|
|
157
168
|
align,
|
|
158
|
-
readonly,
|
|
159
169
|
selected,
|
|
170
|
+
isComposing,
|
|
160
171
|
(_markdownEditorRef_current = markdownEditorRef.current) === null || _markdownEditorRef_current === void 0 ? void 0 : _markdownEditorRef_current.children.length,
|
|
161
172
|
editorProps.titlePlaceholderContent
|
|
162
173
|
]);
|
|
@@ -323,6 +323,17 @@ var repairBrokenChildArrays = function repairBrokenChildArrays(editor) {
|
|
|
323
323
|
normalizeNode(entry);
|
|
324
324
|
return;
|
|
325
325
|
}
|
|
326
|
+
// 清空后 Slate 规范化可能再插一个空段,根上出现多个仅空文本的 paragraph;
|
|
327
|
+
// 与 replaceEditorContent 已插入的一块叠成双 DOM(见 debug H6)。
|
|
328
|
+
var validTop = childList.filter(isValidChild);
|
|
329
|
+
if (validTop.length > 1) {
|
|
330
|
+
var collapsed = EditorUtils.coalesceRootAllEmptyParagraphs(validTop);
|
|
331
|
+
if (collapsed.length < validTop.length) {
|
|
332
|
+
EditorUtils.replaceEditorContent(editor, collapsed);
|
|
333
|
+
normalizeNode(entry);
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
326
337
|
normalizeNode(entry);
|
|
327
338
|
return;
|
|
328
339
|
}
|
|
@@ -11,6 +11,12 @@ export declare class EditorUtils {
|
|
|
11
11
|
readonly text: "";
|
|
12
12
|
}];
|
|
13
13
|
};
|
|
14
|
+
/**
|
|
15
|
+
* 当根节点全部为「仅空白」的段落时,合并为单个空段。
|
|
16
|
+
* 避免解析 `\\n\\n` 或外部 schema 产生多个空段,导致 Slate/占位与双 DOM。
|
|
17
|
+
* 仅一个根块时原样返回,以保留单空段上的 align 等段落级字段。
|
|
18
|
+
*/
|
|
19
|
+
static coalesceRootAllEmptyParagraphs(nodes: Node[]): Node[];
|
|
14
20
|
/**
|
|
15
21
|
* 通过 Slate Transforms API 安全替换编辑器全部内容。
|
|
16
22
|
* 避免直接赋值 editor.children,确保 Operation/History/Normalizer 管线正常运行。
|
|
@@ -157,6 +157,32 @@ export var EditorUtils = /*#__PURE__*/ function() {
|
|
|
157
157
|
};
|
|
158
158
|
}
|
|
159
159
|
},
|
|
160
|
+
{
|
|
161
|
+
key: "coalesceRootAllEmptyParagraphs",
|
|
162
|
+
value: /**
|
|
163
|
+
* 当根节点全部为「仅空白」的段落时,合并为单个空段。
|
|
164
|
+
* 避免解析 `\\n\\n` 或外部 schema 产生多个空段,导致 Slate/占位与双 DOM。
|
|
165
|
+
* 仅一个根块时原样返回,以保留单空段上的 align 等段落级字段。
|
|
166
|
+
*/ function coalesceRootAllEmptyParagraphs(nodes) {
|
|
167
|
+
if (!(nodes === null || nodes === void 0 ? void 0 : nodes.length)) {
|
|
168
|
+
return [
|
|
169
|
+
JSON.parse(JSON.stringify(EditorUtils.p))
|
|
170
|
+
];
|
|
171
|
+
}
|
|
172
|
+
if (nodes.length === 1) {
|
|
173
|
+
return nodes;
|
|
174
|
+
}
|
|
175
|
+
var onlyEmptyParagraphs = nodes.every(function(n) {
|
|
176
|
+
return Element.isElement(n) && n.type === 'paragraph' && Node.string(n).trim() === '';
|
|
177
|
+
});
|
|
178
|
+
if (onlyEmptyParagraphs) {
|
|
179
|
+
return [
|
|
180
|
+
JSON.parse(JSON.stringify(EditorUtils.p))
|
|
181
|
+
];
|
|
182
|
+
}
|
|
183
|
+
return nodes;
|
|
184
|
+
}
|
|
185
|
+
},
|
|
160
186
|
{
|
|
161
187
|
key: "replaceEditorContent",
|
|
162
188
|
value: /**
|
|
@@ -169,6 +195,7 @@ export var EditorUtils = /*#__PURE__*/ function() {
|
|
|
169
195
|
*/ function replaceEditorContent(editor, nodes, options) {
|
|
170
196
|
var _ref = options || {}, _ref_withoutHistory = _ref.withoutHistory, withoutHistory = _ref_withoutHistory === void 0 ? true : _ref_withoutHistory;
|
|
171
197
|
var doReplace = function doReplace() {
|
|
198
|
+
var normalized = EditorUtils.coalesceRootAllEmptyParagraphs(nodes);
|
|
172
199
|
Editor.withoutNormalizing(editor, function() {
|
|
173
200
|
if (editor.selection) {
|
|
174
201
|
Transforms.deselect(editor);
|
|
@@ -181,7 +208,7 @@ export var EditorUtils = /*#__PURE__*/ function() {
|
|
|
181
208
|
]
|
|
182
209
|
});
|
|
183
210
|
}
|
|
184
|
-
Transforms.insertNodes(editor,
|
|
211
|
+
Transforms.insertNodes(editor, normalized, {
|
|
185
212
|
at: [
|
|
186
213
|
0
|
|
187
214
|
]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ant-design/agentic-ui",
|
|
3
|
-
"version": "2.30.
|
|
3
|
+
"version": "2.30.27",
|
|
4
4
|
"description": "面向智能体的 UI 组件库,提供多步推理可视化、工具调用展示、任务执行协同等 Agentic UI 能力",
|
|
5
5
|
"repository": "git@github.com:ant-design/agentic-ui.git",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,7 +25,6 @@
|
|
|
25
25
|
"lint:es": "eslint \"{src,test}/**/*.{js,jsx,ts,tsx}\"",
|
|
26
26
|
"playwright:install": "playwright install --with-deps chromium",
|
|
27
27
|
"prepare": "husky install && dumi setup",
|
|
28
|
-
"prepublishOnly": "npm run build",
|
|
29
28
|
"prettier": "prettier --write \"{src,docs,test}/**/*.{js,jsx,ts,tsx,css,less,json,md}\"",
|
|
30
29
|
"preview": "pnpm dumi preview",
|
|
31
30
|
"report:demo": "node scripts/generateDemoReport.js",
|