@ant-design/agentic-ui 2.28.1 → 2.28.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import { RenderLeafProps } from 'slate-react';
3
+ import { MarkdownEditorProps } from '../../../types';
4
+ interface CommentLeafProps {
5
+ children: React.ReactNode;
6
+ leaf: RenderLeafProps['leaf'];
7
+ hashId: string;
8
+ comment: MarkdownEditorProps['comment'];
9
+ }
10
+ export declare const CommentLeaf: React.MemoExoticComponent<({ children, leaf, hashId, comment, }: CommentLeafProps) => React.JSX.Element>;
11
+ export {};
@@ -0,0 +1,69 @@
1
+ import React, { useMemo } from "react";
2
+ import { debugInfo } from "../../../../Utils/debugUtils";
3
+ import { useEditorStore } from "../../store";
4
+ import { CommentView } from "../Comment";
5
+ /**
6
+ * 比较函数,用于优化 CommentLeaf 组件的渲染性能
7
+ */ var areCommentLeafPropsEqual = function(prevProps, nextProps) {
8
+ // 首先进行快速引用比较
9
+ if (prevProps.leaf === nextProps.leaf && prevProps.children === nextProps.children && prevProps.hashId === nextProps.hashId && prevProps.comment === nextProps.comment) {
10
+ return true;
11
+ }
12
+ // 比较基本 props
13
+ if (prevProps.hashId !== nextProps.hashId || prevProps.children !== nextProps.children || prevProps.comment !== nextProps.comment) {
14
+ return false;
15
+ }
16
+ // 比较 leaf 对象的关键属性
17
+ if (prevProps.leaf !== nextProps.leaf) {
18
+ var prevLeaf = prevProps.leaf;
19
+ var nextLeaf = nextProps.leaf;
20
+ // 比较 comment 相关的关键属性
21
+ if (prevLeaf.comment !== nextLeaf.comment || prevLeaf.id !== nextLeaf.id || prevLeaf.selection !== nextLeaf.selection || prevLeaf.data !== nextLeaf.data) {
22
+ return false;
23
+ }
24
+ }
25
+ return true;
26
+ };
27
+ /**
28
+ * CommentLeaf 组件:专门处理 comment(评论)类型的叶子节点
29
+ * 这是一个包装器组件,用于包裹需要显示评论的 DOM 元素
30
+ */ var CommentLeafComponent = function(param) {
31
+ var children = param.children, leaf = param.leaf, hashId = param.hashId, comment = param.comment;
32
+ var setShowComment = useEditorStore().setShowComment;
33
+ // 使用 useMemo 优化计算逻辑(必须在所有条件返回之前调用)
34
+ var commentId = useMemo(function() {
35
+ return "comment-".concat(leaf === null || leaf === void 0 ? void 0 : leaf.id);
36
+ }, [
37
+ leaf === null || leaf === void 0 ? void 0 : leaf.id
38
+ ]);
39
+ var commentItem = useMemo(function() {
40
+ return (leaf === null || leaf === void 0 ? void 0 : leaf.comment) ? leaf.data : null;
41
+ }, [
42
+ leaf === null || leaf === void 0 ? void 0 : leaf.comment,
43
+ leaf === null || leaf === void 0 ? void 0 : leaf.data
44
+ ]);
45
+ debugInfo('CommentLeaf - 渲染评论节点', {
46
+ hasComment: !!leaf.comment,
47
+ commentId: leaf === null || leaf === void 0 ? void 0 : leaf.id
48
+ });
49
+ // 如果没有评论,直接返回子元素
50
+ if (!leaf.comment) {
51
+ debugInfo('CommentLeaf - 无评论,直接返回子元素');
52
+ return /*#__PURE__*/ React.createElement(React.Fragment, null, children);
53
+ }
54
+ debugInfo('CommentLeaf - 返回带评论的 DOM', {
55
+ commentId: leaf === null || leaf === void 0 ? void 0 : leaf.id,
56
+ hasCommentItem: !!(leaf === null || leaf === void 0 ? void 0 : leaf.comment)
57
+ });
58
+ // 如果有评论,用 CommentView 包裹
59
+ return /*#__PURE__*/ React.createElement(CommentView, {
60
+ id: commentId,
61
+ comment: comment,
62
+ hashId: hashId,
63
+ selection: leaf === null || leaf === void 0 ? void 0 : leaf.selection,
64
+ commentItem: commentItem,
65
+ setShowComment: setShowComment
66
+ }, children);
67
+ };
68
+ // 使用 React.memo 优化 CommentLeaf 组件的性能
69
+ export var CommentLeaf = /*#__PURE__*/ React.memo(CommentLeafComponent, areCommentLeafPropsEqual);
@@ -0,0 +1,15 @@
1
+ import React, { CSSProperties } from 'react';
2
+ import { RenderLeafProps } from 'slate-react';
3
+ import { MarkdownEditorProps } from '../../../types';
4
+ interface FncLeafProps extends RenderLeafProps {
5
+ hashId: string;
6
+ fncProps: MarkdownEditorProps['fncProps'];
7
+ linkConfig?: MarkdownEditorProps['linkConfig'];
8
+ style?: CSSProperties;
9
+ prefixClassName?: string;
10
+ }
11
+ /**
12
+ * FncLeaf 组件:专门处理 fnc(函数调用)和 fnd(函数定义)类型的叶子节点
13
+ */
14
+ export declare const FncLeaf: ({ attributes, children, leaf, hashId, fncProps, linkConfig, style, prefixClassName, }: FncLeafProps) => React.JSX.Element;
15
+ export {};
@@ -0,0 +1,208 @@
1
+ function _define_property(obj, key, value) {
2
+ if (key in obj) {
3
+ Object.defineProperty(obj, key, {
4
+ value: value,
5
+ enumerable: true,
6
+ configurable: true,
7
+ writable: true
8
+ });
9
+ } else {
10
+ obj[key] = value;
11
+ }
12
+ return obj;
13
+ }
14
+ function _object_spread(target) {
15
+ for(var i = 1; i < arguments.length; i++){
16
+ var source = arguments[i] != null ? arguments[i] : {};
17
+ var ownKeys = Object.keys(source);
18
+ if (typeof Object.getOwnPropertySymbols === "function") {
19
+ ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
20
+ return Object.getOwnPropertyDescriptor(source, sym).enumerable;
21
+ }));
22
+ }
23
+ ownKeys.forEach(function(key) {
24
+ _define_property(target, key, source[key]);
25
+ });
26
+ }
27
+ return target;
28
+ }
29
+ function ownKeys(object, enumerableOnly) {
30
+ var keys = Object.keys(object);
31
+ if (Object.getOwnPropertySymbols) {
32
+ var symbols = Object.getOwnPropertySymbols(object);
33
+ if (enumerableOnly) {
34
+ symbols = symbols.filter(function(sym) {
35
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
36
+ });
37
+ }
38
+ keys.push.apply(keys, symbols);
39
+ }
40
+ return keys;
41
+ }
42
+ function _object_spread_props(target, source) {
43
+ source = source != null ? source : {};
44
+ if (Object.getOwnPropertyDescriptors) {
45
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
46
+ } else {
47
+ ownKeys(Object(source)).forEach(function(key) {
48
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
49
+ });
50
+ }
51
+ return target;
52
+ }
53
+ import { ConfigProvider } from "antd";
54
+ import classNames from "classnames";
55
+ import React, { useCallback, useContext, useMemo } from "react";
56
+ import { isMobileDevice } from "../../../../MarkdownInputField/AttachmentButton/utils";
57
+ import { debugInfo } from "../../../../Utils/debugUtils";
58
+ import { dragStart } from "../index";
59
+ /**
60
+ * FncLeaf 组件:专门处理 fnc(函数调用)和 fnd(函数定义)类型的叶子节点
61
+ */ export var FncLeaf = function(param) {
62
+ var attributes = param.attributes, children = param.children, leaf = param.leaf, hashId = param.hashId, fncProps = param.fncProps, linkConfig = param.linkConfig, _param_style = param.style, style = _param_style === void 0 ? {} : _param_style, _param_prefixClassName = param.prefixClassName, prefixClassName = _param_prefixClassName === void 0 ? '' : _param_prefixClassName;
63
+ var _leaf_text;
64
+ var context = useContext(ConfigProvider.ConfigContext);
65
+ var mdEditorBaseClass = context === null || context === void 0 ? void 0 : context.getPrefixCls('agentic-md-editor-content');
66
+ var isMobile = isMobileDevice();
67
+ var hasFnc = leaf.fnc || leaf.identifier;
68
+ debugInfo('FncLeaf - 渲染 fnc 节点', {
69
+ hasFnc: !!leaf.fnc,
70
+ hasIdentifier: !!leaf.identifier,
71
+ hasFnd: !!leaf.fnd,
72
+ text: (_leaf_text = leaf.text) === null || _leaf_text === void 0 ? void 0 : _leaf_text.substring(0, 50)
73
+ });
74
+ // 使用 useMemo 优化 className 计算
75
+ var fncClassName = useMemo(function() {
76
+ var _obj;
77
+ return classNames(prefixClassName === null || prefixClassName === void 0 ? void 0 : prefixClassName.trim(), hashId, (_obj = {}, _define_property(_obj, "".concat(mdEditorBaseClass, "-fnc"), leaf.fnc), _define_property(_obj, "".concat(mdEditorBaseClass, "-fnd"), leaf.fnd), _obj));
78
+ }, [
79
+ prefixClassName,
80
+ hashId,
81
+ mdEditorBaseClass,
82
+ leaf.fnc,
83
+ leaf.fnd
84
+ ]);
85
+ // 使用 useMemo 优化文本格式化计算
86
+ var formattedText = useMemo(function() {
87
+ if (leaf.fnc || leaf.identifier) {
88
+ var _leaf_text_replaceAll_replaceAll, _leaf_text_replaceAll, _leaf_text;
89
+ return ((_leaf_text = leaf.text) === null || _leaf_text === void 0 ? void 0 : (_leaf_text_replaceAll = _leaf_text.replaceAll(']', '')) === null || _leaf_text_replaceAll === void 0 ? void 0 : (_leaf_text_replaceAll_replaceAll = _leaf_text_replaceAll.replaceAll('[^DOC_', '')) === null || _leaf_text_replaceAll_replaceAll === void 0 ? void 0 : _leaf_text_replaceAll_replaceAll.replaceAll('[^', '')) || '';
90
+ }
91
+ return children;
92
+ }, [
93
+ leaf.fnc,
94
+ leaf.identifier,
95
+ leaf.text,
96
+ children
97
+ ]);
98
+ // 使用 useMemo 优化 data-fnc-name 和 data-fnd-name 计算
99
+ var dataFncName = useMemo(function() {
100
+ var _leaf_text;
101
+ return leaf.fnc ? (_leaf_text = leaf.text) === null || _leaf_text === void 0 ? void 0 : _leaf_text.replace(/\[\^(.+)]:?/g, '$1') : undefined;
102
+ }, [
103
+ leaf.fnc,
104
+ leaf.text
105
+ ]);
106
+ var dataFndName = useMemo(function() {
107
+ var _leaf_text;
108
+ return leaf.fnd ? (_leaf_text = leaf.text) === null || _leaf_text === void 0 ? void 0 : _leaf_text.replace(/\[\^(.+)]:?/g, '$1') : undefined;
109
+ }, [
110
+ leaf.fnd,
111
+ leaf.text
112
+ ]);
113
+ // 使用 useMemo 优化 style 对象
114
+ var mergedStyle = useMemo(function() {
115
+ return _object_spread({
116
+ fontSize: leaf.fnc ? 10 : undefined
117
+ }, style);
118
+ }, [
119
+ leaf.fnc,
120
+ style
121
+ ]);
122
+ // 使用 useCallback 优化 onClick 处理函数
123
+ var handleClick = useCallback(function(e) {
124
+ debugInfo('FncLeaf - onClick 事件', {
125
+ isMobile: isMobile,
126
+ hasFnc: hasFnc,
127
+ detail: e.detail,
128
+ hasUrl: !!leaf.url
129
+ });
130
+ // 在手机上,如果是 fnc,阻止点击事件(使用长按代替)
131
+ if (isMobile && hasFnc) {
132
+ debugInfo('FncLeaf - 移动端阻止 fnc 点击');
133
+ e.preventDefault();
134
+ return;
135
+ }
136
+ if (hasFnc) {
137
+ e.preventDefault();
138
+ e.stopPropagation();
139
+ if (fncProps === null || fncProps === void 0 ? void 0 : fncProps.onOriginUrlClick) {
140
+ debugInfo('FncLeaf - 触发 fnc 点击');
141
+ fncProps.onOriginUrlClick(leaf === null || leaf === void 0 ? void 0 : leaf.identifier);
142
+ }
143
+ // 如果同时有 URL,也要处理 URL 打开逻辑
144
+ if (leaf.url) {
145
+ if (linkConfig === null || linkConfig === void 0 ? void 0 : linkConfig.onClick) {
146
+ var res = linkConfig.onClick(leaf.url);
147
+ debugInfo('FncLeaf - 链接点击处理', {
148
+ result: res
149
+ });
150
+ if (res === false) {
151
+ return false;
152
+ }
153
+ }
154
+ if ((linkConfig === null || linkConfig === void 0 ? void 0 : linkConfig.openInNewTab) !== false) {
155
+ debugInfo('FncLeaf - 新标签页打开链接', {
156
+ url: leaf.url
157
+ });
158
+ window.open(leaf.url, '_blank');
159
+ } else {
160
+ debugInfo('FncLeaf - 当前窗口打开链接', {
161
+ url: leaf.url
162
+ });
163
+ window.location.href = leaf.url;
164
+ }
165
+ }
166
+ return false;
167
+ }
168
+ }, [
169
+ isMobile,
170
+ hasFnc,
171
+ fncProps,
172
+ leaf === null || leaf === void 0 ? void 0 : leaf.identifier,
173
+ leaf === null || leaf === void 0 ? void 0 : leaf.url,
174
+ linkConfig
175
+ ]);
176
+ // 使用 useMemo 优化自定义渲染的 children 计算
177
+ var customRenderChildren = useMemo(function() {
178
+ var _leaf_text_toLocaleUpperCase, _leaf_text;
179
+ return ((_leaf_text = leaf.text) === null || _leaf_text === void 0 ? void 0 : (_leaf_text_toLocaleUpperCase = _leaf_text.toLocaleUpperCase()) === null || _leaf_text_toLocaleUpperCase === void 0 ? void 0 : _leaf_text_toLocaleUpperCase.replaceAll('[^', '').replaceAll(']', '')) || '';
180
+ }, [
181
+ leaf.text
182
+ ]);
183
+ var dom = /*#__PURE__*/ React.createElement("span", _object_spread_props(_object_spread({}, attributes), {
184
+ "data-be": "text",
185
+ draggable: false,
186
+ onDragStart: dragStart,
187
+ onClick: handleClick,
188
+ contentEditable: leaf.fnc ? false : undefined,
189
+ "data-fnc": leaf.fnc || leaf.identifier ? 'fnc' : undefined,
190
+ "data-fnd": leaf.fnd ? 'fnd' : undefined,
191
+ "data-fnc-name": dataFncName,
192
+ "data-fnd-name": dataFndName,
193
+ className: fncClassName ? fncClassName : undefined,
194
+ style: mergedStyle
195
+ }), formattedText);
196
+ // 如果提供了自定义渲染函数,使用它
197
+ if ((fncProps === null || fncProps === void 0 ? void 0 : fncProps.render) && (leaf.fnc || leaf.identifier)) {
198
+ var _fncProps_render;
199
+ debugInfo('FncLeaf - 使用 fnc 自定义渲染', {
200
+ hasFnc: !!leaf.fnc,
201
+ hasIdentifier: !!leaf.identifier
202
+ });
203
+ dom = /*#__PURE__*/ React.createElement(React.Fragment, null, (_fncProps_render = fncProps.render) === null || _fncProps_render === void 0 ? void 0 : _fncProps_render.call(fncProps, _object_spread_props(_object_spread({}, leaf), {
204
+ children: customRenderChildren
205
+ }), dom));
206
+ }
207
+ return dom;
208
+ };
@@ -105,10 +105,10 @@ import { useSelStatus } from "../../../hooks/editor";
105
105
  import { useEditorStore } from "../../store";
106
106
  import { DragHandle } from "../../tools/DragHandle";
107
107
  export var Paragraph = function(props) {
108
- var _props_element_children, _markdownEditorRef_current;
108
+ var _markdownEditorRef_current;
109
109
  debugInfo('Paragraph - 渲染段落', {
110
110
  align: props.element.align,
111
- childrenCount: (_props_element_children = props.element.children) === null || _props_element_children === void 0 ? void 0 : _props_element_children.length
111
+ children: props.element.children
112
112
  });
113
113
  var _useEditorStore = useEditorStore(), store = _useEditorStore.store, markdownEditorRef = _useEditorStore.markdownEditorRef, markdownContainerRef = _useEditorStore.markdownContainerRef, readonly = _useEditorStore.readonly, editorProps = _useEditorStore.editorProps;
114
114
  var locale = useContext(I18nContext).locale;
@@ -13,6 +13,18 @@ import { Media } from './Media';
13
13
  import { Mermaid } from './Mermaid';
14
14
  import { Paragraph } from './Paragraph';
15
15
  import { Schema } from './Schema';
16
+ /**
17
+ * 性能优化说明:
18
+ *
19
+ * 本文件中的 MElement 和 MLeaf 组件使用了 React.memo 进行性能优化:
20
+ *
21
+ * 1. **避免不必要的重新渲染**:使用自定义比较函数确保只有在 props 真正变化时才重新渲染
22
+ * 2. **快速引用比较**:首先进行引用比较,这是最快的比较方式
23
+ * 4. **批量属性检查**:对 MLeaf 组件使用数组批量检查关键属性
24
+ *
25
+ * 性能测试结果显示约 43% 的渲染性能提升,在相同 props 的情况下避免了重复渲染。
26
+ */
27
+ export declare const dragStart: (e: React.DragEvent) => void;
16
28
  export declare const MElement: React.MemoExoticComponent<(props: RenderElementProps & {
17
29
  readonly?: boolean;
18
30
  }) => React.JSX.Element>;
@@ -52,11 +52,10 @@ function _object_spread_props(target, source) {
52
52
  }
53
53
  import { ConfigProvider } from "antd";
54
54
  import classNames from "classnames";
55
- import React, { useContext, useRef } from "react";
55
+ import React, { useContext } from "react";
56
56
  import { Editor, Path, Transforms } from "slate";
57
57
  import { ReactEditor } from "slate-react";
58
58
  import { I18nContext } from "../../../I18n";
59
- import { isMobileDevice } from "../../../MarkdownInputField/AttachmentButton/utils";
60
59
  import { debugInfo } from "../../../Utils/debugUtils";
61
60
  import { useEditorStore } from "../store";
62
61
  import { EditorUtils } from "../utils/editorUtils";
@@ -64,7 +63,8 @@ import { Blockquote } from "./Blockquote";
64
63
  import { Break } from "./Break";
65
64
  import { WarpCard } from "./Card";
66
65
  import { Code } from "./Code";
67
- import { CommentView } from "./Comment";
66
+ import { CommentLeaf } from "./CommentLeaf";
67
+ import { FncLeaf } from "./FncLeaf";
68
68
  import { FootnoteDefinition } from "./FootnoteDefinition";
69
69
  import { FootnoteReference } from "./FootnoteReference";
70
70
  import { Head } from "./Head";
@@ -90,7 +90,7 @@ import { TagPopup } from "./TagPopup";
90
90
  * 4. **批量属性检查**:对 MLeaf 组件使用数组批量检查关键属性
91
91
  *
92
92
  * 性能测试结果显示约 43% 的渲染性能提升,在相同 props 的情况下避免了重复渲染。
93
- */ var dragStart = function(e) {
93
+ */ export var dragStart = function(e) {
94
94
  e.preventDefault();
95
95
  e.stopPropagation();
96
96
  };
@@ -319,8 +319,8 @@ export var MElement = /*#__PURE__*/ React.memo(MElementComponent, areElementProp
319
319
  return true;
320
320
  };
321
321
  var MLeafComponent = function(props) {
322
- var _leaf_text, _leaf_text1, _leaf_text2, _leaf_text_replaceAll_replaceAll, _leaf_text_replaceAll, _leaf_text3, _props_fncProps, _props_leaf, _props_leaf1;
323
- var _useEditorStore = useEditorStore(), markdownEditorRef = _useEditorStore.markdownEditorRef, markdownContainerRef = _useEditorStore.markdownContainerRef, setShowComment = _useEditorStore.setShowComment;
322
+ var _leaf_text;
323
+ var _useEditorStore = useEditorStore(), markdownEditorRef = _useEditorStore.markdownEditorRef, markdownContainerRef = _useEditorStore.markdownContainerRef;
324
324
  var context = useContext(ConfigProvider.ConfigContext);
325
325
  var locale = useContext(I18nContext).locale;
326
326
  var mdEditorBaseClass = context === null || context === void 0 ? void 0 : context.getPrefixCls('agentic-md-editor-content');
@@ -489,79 +489,48 @@ var MLeafComponent = function(props) {
489
489
  });
490
490
  }
491
491
  };
492
- var handleFncOpen = function() {
493
- var _props_fncProps, _props_fncProps1;
494
- debugInfo('MLeafComponent - handleFncOpen', {
495
- identifier: leaf === null || leaf === void 0 ? void 0 : leaf.identifier,
496
- hasFncProps: !!props.fncProps,
497
- hasOnOriginUrlClick: !!((_props_fncProps = props.fncProps) === null || _props_fncProps === void 0 ? void 0 : _props_fncProps.onOriginUrlClick)
492
+ // 如果检测到 fnc、identifier fnd,使用 FncLeaf 组件
493
+ var hasFnc = leaf.fnc || leaf.identifier || leaf.fnd;
494
+ var hasComment = !!leaf.comment;
495
+ if (hasFnc) {
496
+ debugInfo('MLeafComponent - 使用 FncLeaf 组件', {
497
+ hasFnc: !!leaf.fnc,
498
+ hasIdentifier: !!leaf.identifier,
499
+ hasFnd: !!leaf.fnd
498
500
  });
499
- if ((_props_fncProps1 = props.fncProps) === null || _props_fncProps1 === void 0 ? void 0 : _props_fncProps1.onOriginUrlClick) {
500
- props.fncProps.onOriginUrlClick(leaf === null || leaf === void 0 ? void 0 : leaf.identifier);
501
- }
502
- };
503
- var isMobile = isMobileDevice();
504
- var hasFnc = leaf.fnc || leaf.identifier;
505
- // 长按处理:用于手机端打开 fnc
506
- var longPressTimerRef = useRef(null);
507
- var touchStartTimeRef = useRef(0);
508
- var isLongPressRef = useRef(false);
509
- var handleTouchStart = function() {
510
- if (!hasFnc) return;
511
- isLongPressRef.current = false;
512
- touchStartTimeRef.current = Date.now();
513
- longPressTimerRef.current = setTimeout(function() {
514
- isLongPressRef.current = true;
515
- handleFncOpen();
516
- }, 500); // 500ms 长按时间
517
- };
518
- var handleTouchEnd = function(e) {
519
- if (!hasFnc) return;
520
- if (longPressTimerRef.current) {
521
- clearTimeout(longPressTimerRef.current);
522
- longPressTimerRef.current = null;
501
+ var baseClassName = classNames(prefixClassName === null || prefixClassName === void 0 ? void 0 : prefixClassName.trim(), props.hashId);
502
+ var fncDom = /*#__PURE__*/ React.createElement(FncLeaf, _object_spread_props(_object_spread({}, props), {
503
+ hashId: props.hashId,
504
+ fncProps: props.fncProps,
505
+ linkConfig: props.linkConfig,
506
+ style: style,
507
+ prefixClassName: baseClassName
508
+ }));
509
+ // 如果有评论,使用 CommentLeaf 包裹 fnc DOM
510
+ if (hasComment) {
511
+ return /*#__PURE__*/ React.createElement(CommentLeaf, {
512
+ leaf: props.leaf,
513
+ hashId: props.hashId,
514
+ comment: props.comment
515
+ }, fncDom);
523
516
  }
524
- // 如果是短按(小于 500ms),在手机上阻止默认行为
525
- var touchDuration = Date.now() - touchStartTimeRef.current;
526
- if (touchDuration < 500 && isMobile) {
527
- e.preventDefault();
528
- }
529
- };
530
- var handleTouchCancel = function() {
531
- if (longPressTimerRef.current) {
532
- clearTimeout(longPressTimerRef.current);
533
- longPressTimerRef.current = null;
534
- }
535
- isLongPressRef.current = false;
536
- };
537
- var _obj;
538
- var fncClassName = classNames(prefixClassName === null || prefixClassName === void 0 ? void 0 : prefixClassName.trim(), props.hashId, (_obj = {}, _define_property(_obj, "".concat(mdEditorBaseClass, "-fnc"), leaf.fnc), _define_property(_obj, "".concat(mdEditorBaseClass, "-fnd"), leaf.fnd), _define_property(_obj, "".concat(mdEditorBaseClass, "-comment"), leaf.comment), _obj));
517
+ return fncDom;
518
+ }
519
+ var baseClassName1 = classNames(prefixClassName === null || prefixClassName === void 0 ? void 0 : prefixClassName.trim(), props.hashId);
539
520
  var dom = /*#__PURE__*/ React.createElement("span", _object_spread_props(_object_spread({}, props.attributes), {
540
521
  "data-be": "text",
541
522
  draggable: false,
542
523
  onDragStart: dragStart,
543
524
  onClick: function(e) {
544
- var _props_fncProps, _props_linkConfig, _props_linkConfig1, _props_linkConfig2;
525
+ var _props_linkConfig, _props_linkConfig1, _props_linkConfig2;
545
526
  debugInfo('MLeafComponent - onClick 事件', {
546
- isMobile: isMobile,
547
- hasFnc: hasFnc,
548
527
  detail: e.detail,
549
528
  hasUrl: !!leaf.url
550
529
  });
551
- // 在手机上,如果是 fnc,阻止点击事件(使用长按代替)
552
- if (isMobile && hasFnc) {
553
- debugInfo('MLeafComponent - 移动端阻止 fnc 点击');
554
- e.preventDefault();
555
- return;
556
- }
557
530
  if (e.detail === 2) {
558
531
  debugInfo('MLeafComponent - 双击选择格式');
559
532
  selectFormat();
560
533
  }
561
- if ((_props_fncProps = props.fncProps) === null || _props_fncProps === void 0 ? void 0 : _props_fncProps.onOriginUrlClick) {
562
- debugInfo('MLeafComponent - 触发 fnc 点击');
563
- props.fncProps.onOriginUrlClick(leaf === null || leaf === void 0 ? void 0 : leaf.identifier);
564
- }
565
534
  if ((_props_linkConfig = props.linkConfig) === null || _props_linkConfig === void 0 ? void 0 : _props_linkConfig.onClick) {
566
535
  var _props_linkConfig3;
567
536
  var res = (_props_linkConfig3 = props.linkConfig) === null || _props_linkConfig3 === void 0 ? void 0 : _props_linkConfig3.onClick(leaf.url);
@@ -585,47 +554,20 @@ var MLeafComponent = function(props) {
585
554
  window.location.href = leaf.url;
586
555
  }
587
556
  },
588
- onTouchStart: hasFnc ? handleTouchStart : undefined,
589
- onTouchEnd: hasFnc ? handleTouchEnd : undefined,
590
- onTouchCancel: hasFnc ? handleTouchCancel : undefined,
591
- contentEditable: leaf.fnc ? false : undefined,
592
- "data-fnc": leaf.fnc || leaf.identifier ? 'fnc' : undefined,
593
- "data-fnd": leaf.fnd ? 'fnd' : undefined,
594
557
  "data-comment": leaf.comment ? 'comment' : undefined,
595
- "data-fnc-name": leaf.fnc ? (_leaf_text1 = leaf.text) === null || _leaf_text1 === void 0 ? void 0 : _leaf_text1.replace(/\[\^(.+)]:?/g, '$1') : undefined,
596
558
  "data-url": leaf.url ? 'url' : undefined,
597
- "data-fnd-name": leaf.fnd ? (_leaf_text2 = leaf.text) === null || _leaf_text2 === void 0 ? void 0 : _leaf_text2.replace(/\[\^(.+)]:?/g, '$1') : undefined,
598
- className: fncClassName ? fncClassName : undefined,
599
- style: _object_spread({
600
- fontSize: leaf.fnc ? 10 : undefined
601
- }, style)
602
- }), leaf.fnc || leaf.identifier ? (_leaf_text3 = leaf.text) === null || _leaf_text3 === void 0 ? void 0 : (_leaf_text_replaceAll = _leaf_text3.replaceAll(']', '')) === null || _leaf_text_replaceAll === void 0 ? void 0 : (_leaf_text_replaceAll_replaceAll = _leaf_text_replaceAll.replaceAll('[^DOC_', '')) === null || _leaf_text_replaceAll_replaceAll === void 0 ? void 0 : _leaf_text_replaceAll_replaceAll.replaceAll('[^', '') : children);
603
- if (((_props_fncProps = props.fncProps) === null || _props_fncProps === void 0 ? void 0 : _props_fncProps.render) && (leaf.fnc || leaf.identifier)) {
604
- var _leaf_text_toLocaleUpperCase, _leaf_text4, _props_fncProps_render, _props_fncProps1;
605
- debugInfo('MLeafComponent - 使用 fnc 自定义渲染', {
606
- hasFnc: !!leaf.fnc,
607
- hasIdentifier: !!leaf.identifier
608
- });
609
- dom = /*#__PURE__*/ React.createElement(React.Fragment, null, (_props_fncProps_render = (_props_fncProps1 = props.fncProps).render) === null || _props_fncProps_render === void 0 ? void 0 : _props_fncProps_render.call(_props_fncProps1, _object_spread_props(_object_spread({}, leaf), {
610
- children: ((_leaf_text4 = leaf.text) === null || _leaf_text4 === void 0 ? void 0 : (_leaf_text_toLocaleUpperCase = _leaf_text4.toLocaleUpperCase()) === null || _leaf_text_toLocaleUpperCase === void 0 ? void 0 : _leaf_text_toLocaleUpperCase.replaceAll('[^', '').replaceAll(']', '')) || ''
611
- }), dom));
612
- }
613
- if (!props.leaf.comment) {
614
- debugInfo('MLeafComponent - 返回 DOM(无评论)');
615
- return dom;
559
+ className: baseClassName1 ? baseClassName1 : undefined,
560
+ style: style
561
+ }), children);
562
+ // 如果有评论,使用 CommentLeaf 包裹普通 DOM
563
+ if (hasComment) {
564
+ return /*#__PURE__*/ React.createElement(CommentLeaf, {
565
+ leaf: props.leaf,
566
+ hashId: props.hashId,
567
+ comment: props.comment
568
+ }, dom);
616
569
  }
617
- debugInfo('MLeafComponent - 返回带评论的 DOM', {
618
- commentId: (_props_leaf = props.leaf) === null || _props_leaf === void 0 ? void 0 : _props_leaf.id,
619
- hasCommentItem: !!(leaf === null || leaf === void 0 ? void 0 : leaf.comment)
620
- });
621
- return /*#__PURE__*/ React.createElement(CommentView, {
622
- id: "comment-".concat((_props_leaf1 = props.leaf) === null || _props_leaf1 === void 0 ? void 0 : _props_leaf1.id),
623
- comment: props.comment,
624
- hashId: props.hashId,
625
- selection: leaf === null || leaf === void 0 ? void 0 : leaf.selection,
626
- commentItem: (leaf === null || leaf === void 0 ? void 0 : leaf.comment) ? leaf.data : null,
627
- setShowComment: setShowComment
628
- }, dom);
570
+ return dom;
629
571
  };
630
572
  // 使用 React.memo 优化 MLeaf 组件的性能
631
573
  export var MLeaf = /*#__PURE__*/ React.memo(MLeafComponent, areLeafPropsEqual);
@@ -9,6 +9,19 @@ function _array_with_holes(arr) {
9
9
  function _array_without_holes(arr) {
10
10
  if (Array.isArray(arr)) return _array_like_to_array(arr);
11
11
  }
12
+ function _define_property(obj, key, value) {
13
+ if (key in obj) {
14
+ Object.defineProperty(obj, key, {
15
+ value: value,
16
+ enumerable: true,
17
+ configurable: true,
18
+ writable: true
19
+ });
20
+ } else {
21
+ obj[key] = value;
22
+ }
23
+ return obj;
24
+ }
12
25
  function _iterable_to_array(iter) {
13
26
  if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
14
27
  }
@@ -42,6 +55,21 @@ function _non_iterable_rest() {
42
55
  function _non_iterable_spread() {
43
56
  throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
44
57
  }
58
+ function _object_spread(target) {
59
+ for(var i = 1; i < arguments.length; i++){
60
+ var source = arguments[i] != null ? arguments[i] : {};
61
+ var ownKeys = Object.keys(source);
62
+ if (typeof Object.getOwnPropertySymbols === "function") {
63
+ ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
64
+ return Object.getOwnPropertyDescriptor(source, sym).enumerable;
65
+ }));
66
+ }
67
+ ownKeys.forEach(function(key) {
68
+ _define_property(target, key, source[key]);
69
+ });
70
+ }
71
+ return target;
72
+ }
45
73
  function _sliced_to_array(arr, i) {
46
74
  return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
47
75
  }
@@ -58,8 +86,11 @@ function _unsupported_iterable_to_array(o, minLen) {
58
86
  }
59
87
  import { Editor, Element, Node, Path } from "slate";
60
88
  import { EditorUtils } from "../utils/editorUtils";
61
- var htmlReg = /<[a-z]+[\s"'=:;()\w\-[\]/.]*\/?>(.*<\/[a-z]+>:?)?/g;
62
- var linkReg = /(https?|ftp):\/\/[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]/gi;
89
+ // 预编译正则表达式,避免重复创建
90
+ var HTML_REG = /<[a-z]+[\s"'=:;()\w\-[\]/.]*\/?>(.*<\/[a-z]+>:?)?/g;
91
+ var LINK_REG = /(https?|ftp):\/\/[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]/gi;
92
+ var FOOTNOTE_REG = /\[\^[^\]]+\]/g;
93
+ var TABLE_ROW_REG = /^\|([^|]+\|)+$/;
63
94
  export var cacheTextNode = new WeakMap();
64
95
  export var clearInlineKatex = function(editor) {
65
96
  var inlineMath = Array.from(Editor.nodes(editor, {
@@ -68,10 +99,14 @@ export var clearInlineKatex = function(editor) {
68
99
  },
69
100
  at: []
70
101
  }));
71
- inlineMath.map(function(c) {
102
+ inlineMath.forEach(function(c) {
72
103
  return cacheTextNode.delete(c[0]);
73
104
  });
74
105
  };
106
+ var PARAGRAPH_TYPES = new Set([
107
+ 'paragraph',
108
+ 'table-cell'
109
+ ]);
75
110
  var highlightNodes = new Set([
76
111
  'paragraph',
77
112
  'table-cell',
@@ -80,198 +115,137 @@ var highlightNodes = new Set([
80
115
  'head',
81
116
  'inline-katex'
82
117
  ]);
118
+ // 创建 range 对象的工厂函数,复用 path 数组
119
+ var createRange = function(path, childIndex, offset, length) {
120
+ var props = arguments.length > 4 && arguments[4] !== void 0 ? arguments[4] : {};
121
+ var childPath = path.concat(childIndex);
122
+ return _object_spread({
123
+ anchor: {
124
+ path: childPath,
125
+ offset: offset
126
+ },
127
+ focus: {
128
+ path: childPath,
129
+ offset: offset + length
130
+ }
131
+ }, props);
132
+ };
133
+ // 处理文本节点的匹配逻辑
134
+ var processTextMatches = function(text, path, childIndex) {
135
+ var ranges = [];
136
+ // 匹配 footnote reference
137
+ var match;
138
+ FOOTNOTE_REG.lastIndex = 0;
139
+ while((match = FOOTNOTE_REG.exec(text)) !== null){
140
+ var index = match.index;
141
+ if (typeof index === 'number') {
142
+ ranges.push(createRange(path, childIndex, index, match[0].length, {
143
+ fnc: true,
144
+ fnd: false
145
+ }));
146
+ }
147
+ }
148
+ // 匹配 HTML
149
+ HTML_REG.lastIndex = 0;
150
+ while((match = HTML_REG.exec(text)) !== null){
151
+ var index1 = match.index;
152
+ if (typeof index1 === 'number') {
153
+ ranges.push(createRange(path, childIndex, index1, match[0].length, {
154
+ html: true
155
+ }));
156
+ }
157
+ }
158
+ return ranges;
159
+ };
160
+ // 处理链接匹配
161
+ var processLinkMatches = function(text, path, childIndex) {
162
+ var ranges = [];
163
+ var match;
164
+ LINK_REG.lastIndex = 0;
165
+ while((match = LINK_REG.exec(text)) !== null){
166
+ var index = match.index;
167
+ if (typeof index === 'number') {
168
+ ranges.push(createRange(path, childIndex, index, match[0].length, {
169
+ link: match[0]
170
+ }));
171
+ }
172
+ }
173
+ return ranges;
174
+ };
83
175
  export function useHighlight(store) {
84
176
  return function(param) {
85
177
  var _param = _sliced_to_array(param, 2), node = _param[0], path = _param[1];
86
- if (Element.isElement(node) && highlightNodes.has(node.type)) {
87
- var ranges = (store === null || store === void 0 ? void 0 : store.highlightCache.get(node)) || [];
88
- var cacheText = cacheTextNode.get(node);
89
- // footnote
90
- if ([
91
- 'paragraph',
92
- 'table-cell'
93
- ].includes(node.type)) {
94
- for(var i = 0; i < node.children.length; i++){
95
- var c = node.children[i];
96
- if (c.text && !EditorUtils.isDirtLeaf(c)) {
97
- if (cacheText && Path.equals(cacheText.path, path)) {
98
- var _ranges;
99
- (_ranges = ranges).push.apply(_ranges, _to_consumable_array(cacheText.range));
100
- } else {
101
- var _ranges1;
102
- var textRanges = [];
103
- var matchHtml = c.text.matchAll(htmlReg);
104
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
105
- try {
106
- for(var _iterator = matchHtml[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
107
- var m = _step.value;
108
- textRanges.push({
109
- anchor: {
110
- path: _to_consumable_array(path).concat([
111
- i
112
- ]),
113
- offset: m.index
114
- },
115
- focus: {
116
- path: _to_consumable_array(path).concat([
117
- i
118
- ]),
119
- offset: m.index + m[0].length
120
- },
121
- html: true
122
- });
123
- }
124
- } catch (err) {
125
- _didIteratorError = true;
126
- _iteratorError = err;
127
- } finally{
128
- try {
129
- if (!_iteratorNormalCompletion && _iterator.return != null) {
130
- _iterator.return();
131
- }
132
- } finally{
133
- if (_didIteratorError) {
134
- throw _iteratorError;
135
- }
136
- }
137
- }
138
- var match = c.text.matchAll(/\[\^.+?]:?/g);
139
- var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
140
- try {
141
- for(var _iterator1 = match[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
142
- var m1 = _step1.value;
143
- if (typeof m1.index !== 'number') continue;
144
- textRanges.push({
145
- anchor: {
146
- path: _to_consumable_array(path).concat([
147
- i
148
- ]),
149
- offset: m1.index
150
- },
151
- focus: {
152
- path: _to_consumable_array(path).concat([
153
- i
154
- ]),
155
- offset: m1.index + m1[0].length
156
- },
157
- fnc: !m1[0].endsWith(':'),
158
- fnd: m1[0].endsWith(':')
159
- });
160
- }
161
- } catch (err) {
162
- _didIteratorError1 = true;
163
- _iteratorError1 = err;
164
- } finally{
165
- try {
166
- if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
167
- _iterator1.return();
168
- }
169
- } finally{
170
- if (_didIteratorError1) {
171
- throw _iteratorError1;
172
- }
173
- }
174
- }
175
- cacheTextNode.set(node, {
176
- path: path,
177
- range: textRanges
178
- });
179
- (_ranges1 = ranges).push.apply(_ranges1, _to_consumable_array(textRanges));
180
- }
178
+ // 快速路径:非元素节点或不在高亮节点列表中
179
+ if (!Element.isElement(node) || !highlightNodes.has(node.type)) {
180
+ return [];
181
+ }
182
+ var ranges = (store === null || store === void 0 ? void 0 : store.highlightCache.get(node)) || [];
183
+ var cacheText = cacheTextNode.get(node);
184
+ var isCached = cacheText && Path.equals(cacheText.path, path);
185
+ // 处理 paragraph 和 table-cell
186
+ if (PARAGRAPH_TYPES.has(node.type)) {
187
+ if (isCached) {
188
+ var _ranges;
189
+ (_ranges = ranges).push.apply(_ranges, _to_consumable_array(cacheText.range));
190
+ } else {
191
+ var _ranges1;
192
+ var allTextRanges = [];
193
+ var children = node.children;
194
+ var childrenLength = children.length;
195
+ for(var i = 0; i < childrenLength; i++){
196
+ var child = children[i];
197
+ // 处理 footnote 和 HTML
198
+ if (child.text && !EditorUtils.isDirtLeaf(child)) {
199
+ var _allTextRanges;
200
+ (_allTextRanges = allTextRanges).push.apply(_allTextRanges, _to_consumable_array(processTextMatches(child.text, path, i)));
181
201
  }
182
- if (c.text && !c.url && !c.docId && !c.hash) {
183
- var _ranges2;
184
- var textRanges1 = [];
185
- var links = c.text.matchAll(linkReg);
186
- var _iteratorNormalCompletion2 = true, _didIteratorError2 = false, _iteratorError2 = undefined;
187
- try {
188
- for(var _iterator2 = links[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true){
189
- var m2 = _step2.value;
190
- textRanges1.push({
191
- anchor: {
192
- path: _to_consumable_array(path).concat([
193
- i
194
- ]),
195
- offset: m2.index
196
- },
197
- focus: {
198
- path: _to_consumable_array(path).concat([
199
- i
200
- ]),
201
- offset: m2.index + m2[0].length
202
- },
203
- link: m2[0]
204
- });
205
- }
206
- } catch (err) {
207
- _didIteratorError2 = true;
208
- _iteratorError2 = err;
209
- } finally{
210
- try {
211
- if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
212
- _iterator2.return();
213
- }
214
- } finally{
215
- if (_didIteratorError2) {
216
- throw _iteratorError2;
217
- }
218
- }
219
- }
220
- (_ranges2 = ranges).push.apply(_ranges2, _to_consumable_array(textRanges1));
202
+ // 处理链接
203
+ if (child.text && !child.url && !child.docId && !child.hash) {
204
+ var _allTextRanges1;
205
+ (_allTextRanges1 = allTextRanges).push.apply(_allTextRanges1, _to_consumable_array(processLinkMatches(child.text, path, i)));
221
206
  }
222
207
  }
208
+ // 统一缓存
209
+ cacheTextNode.set(node, {
210
+ path: path,
211
+ range: allTextRanges
212
+ });
213
+ (_ranges1 = ranges).push.apply(_ranges1, _to_consumable_array(allTextRanges));
223
214
  }
224
- if (node.type === 'paragraph' && node.children.length === 1 && !EditorUtils.isDirtLeaf(node.children[0])) {
225
- if (cacheText && Path.equals(cacheText.path, path)) {
226
- var _ranges3;
227
- (_ranges3 = ranges).push.apply(_ranges3, _to_consumable_array(cacheText.range));
228
- } else {
229
- var str = Node.string(node);
230
- if (str.startsWith('```')) {
231
- ranges.push({
232
- anchor: {
233
- path: _to_consumable_array(path).concat([
234
- 0
235
- ]),
236
- offset: 0
237
- },
238
- focus: {
239
- path: _to_consumable_array(path).concat([
240
- 0
241
- ]),
242
- offset: 3
243
- },
244
- color: '#a3a3a3'
245
- });
246
- cacheTextNode.set(node, {
247
- path: path,
248
- range: ranges
249
- });
250
- } else if (/^\|([^|]+\|)+$/.test(str)) {
251
- ranges.push({
252
- anchor: {
253
- path: _to_consumable_array(path).concat([
254
- 0
255
- ]),
256
- offset: 0
257
- },
258
- focus: {
259
- path: _to_consumable_array(path).concat([
260
- 0
261
- ]),
262
- offset: str.length
263
- },
264
- color: '#a3a3a3'
265
- });
266
- cacheTextNode.set(node, {
267
- path: path,
268
- range: ranges
269
- });
270
- }
215
+ }
216
+ // 处理特殊段落(代码块或表格行)
217
+ if (node.type === 'paragraph' && node.children.length === 1 && !EditorUtils.isDirtLeaf(node.children[0])) {
218
+ if (isCached) {
219
+ var _ranges2;
220
+ (_ranges2 = ranges).push.apply(_ranges2, _to_consumable_array(cacheText.range));
221
+ } else {
222
+ var str = Node.string(node);
223
+ var strLength = str.length;
224
+ if (str.startsWith('```')) {
225
+ var range = createRange(path, 0, 0, 3, {
226
+ color: '#a3a3a3'
227
+ });
228
+ ranges.push(range);
229
+ cacheTextNode.set(node, {
230
+ path: path,
231
+ range: [
232
+ range
233
+ ]
234
+ });
235
+ } else if (TABLE_ROW_REG.test(str)) {
236
+ var range1 = createRange(path, 0, 0, strLength, {
237
+ color: '#a3a3a3'
238
+ });
239
+ ranges.push(range1);
240
+ cacheTextNode.set(node, {
241
+ path: path,
242
+ range: [
243
+ range1
244
+ ]
245
+ });
271
246
  }
272
247
  }
273
- return ranges;
274
248
  }
275
- return [];
249
+ return ranges;
276
250
  };
277
251
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ant-design/agentic-ui",
3
- "version": "2.28.1",
3
+ "version": "2.28.2",
4
4
  "description": "面向智能体的 UI 组件库,提供多步推理可视化、工具调用展示、任务执行协同等 Agentic UI 能力",
5
5
  "repository": "git@github.com:ant-design/agentic-ui.git",
6
6
  "license": "MIT",