@ant-design/agentic-ui 2.29.28 → 2.29.29

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.
@@ -136,6 +136,10 @@ function _sliced_to_array(arr, i) {
136
136
  function _to_consumable_array(arr) {
137
137
  return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
138
138
  }
139
+ function _type_of(obj) {
140
+ "@swc/helpers - typeof";
141
+ return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
142
+ }
139
143
  function _unsupported_iterable_to_array(o, minLen) {
140
144
  if (!o) return;
141
145
  if (typeof o === "string") return _array_like_to_array(o, minLen);
@@ -161,6 +165,7 @@ import { withErrorReporting } from "./editor/plugins/catchError";
161
165
  import { EditorStore, EditorStoreContext } from "./editor/store";
162
166
  import { InsertAutocomplete } from "./editor/tools/InsertAutocomplete";
163
167
  import { InsertLink } from "./editor/tools/InsertLink";
168
+ import { JinjaTemplatePanel } from "./editor/tools/JinjaTemplatePanel";
164
169
  import { TocHeading } from "./editor/tools/Leading";
165
170
  import { FloatBar } from "./editor/tools/ToolBar/FloatBar";
166
171
  import ToolBar from "./editor/tools/ToolBar/ToolBar";
@@ -244,7 +249,7 @@ var I18nBoundary = function I18nBoundary(param) {
244
249
  * - 提供Markdown解析和渲染
245
250
  */ export var BaseMarkdownEditor = function BaseMarkdownEditor(props) {
246
251
  var _props_typewriter, _props_readonly;
247
- var _props_floatBar, _props_floatBar1, _props_textAreaProps;
252
+ var _props_jinja, _effectiveJinja_templatePanel, _props_floatBar, _props_floatBar1, _props_textAreaProps;
248
253
  var initValue = props.initValue, width = props.width, _props_toolBar = props.toolBar, toolBar = _props_toolBar === void 0 ? {} : _props_toolBar, editorRef = props.editorRef, _props_toc = props.toc, toc = _props_toc === void 0 ? false : _props_toc, readonly = props.readonly, lazy = props.lazy, style = props.style, _props_contentStyle = props.contentStyle, contentStyle = _props_contentStyle === void 0 ? {
249
254
  height: '100%'
250
255
  } : _props_contentStyle, editorStyle = props.editorStyle, height = props.height, children = props.children, rest = _object_without_properties(props, [
@@ -395,6 +400,18 @@ var I18nBoundary = function I18nBoundary(param) {
395
400
  return new Subject();
396
401
  }, []);
397
402
  var _useState6 = _sliced_to_array(useState(null), 2), domRect = _useState6[0], setDomRect = _useState6[1];
403
+ var jinjaEnabled = ((_props_jinja = props.jinja) === null || _props_jinja === void 0 ? void 0 : _props_jinja.enable) === true || Array.isArray(props.plugins) && props.plugins.some(function(p) {
404
+ return p.jinja === true;
405
+ });
406
+ var pluginWithJinja = Array.isArray(props.plugins) ? props.plugins.find(function(p) {
407
+ return p.jinja === true;
408
+ }) : undefined;
409
+ var effectiveJinja = props.jinja ? props.jinja : (pluginWithJinja === null || pluginWithJinja === void 0 ? void 0 : pluginWithJinja.jinjaConfig) ? pluginWithJinja.jinjaConfig : pluginWithJinja ? {
410
+ enable: true
411
+ } : undefined;
412
+ var jinjaTemplatePanelEnabled = jinjaEnabled && effectiveJinja !== undefined && effectiveJinja !== null && effectiveJinja.templatePanel !== false && (_type_of(effectiveJinja.templatePanel) !== 'object' || ((_effectiveJinja_templatePanel = effectiveJinja.templatePanel) === null || _effectiveJinja_templatePanel === void 0 ? void 0 : _effectiveJinja_templatePanel.enable) !== false);
413
+ var _useState7 = _sliced_to_array(useState(false), 2), openJinjaTemplate = _useState7[0], setOpenJinjaTemplate = _useState7[1];
414
+ var _useState8 = _sliced_to_array(useState(null), 2), jinjaAnchorPath = _useState8[0], setJinjaAnchorPath = _useState8[1];
398
415
  var _obj;
399
416
  return wrapSSR(/*#__PURE__*/ React.createElement(I18nBoundary, null, /*#__PURE__*/ React.createElement(PluginContext.Provider, {
400
417
  value: props.plugins || []
@@ -414,9 +431,17 @@ var I18nBoundary = function I18nBoundary(param) {
414
431
  setDomRect: setDomRect,
415
432
  typewriter: (_props_typewriter = props.typewriter) !== null && _props_typewriter !== void 0 ? _props_typewriter : false,
416
433
  readonly: (_props_readonly = props.readonly) !== null && _props_readonly !== void 0 ? _props_readonly : false,
417
- editorProps: props || {},
434
+ editorProps: effectiveJinja !== undefined ? _object_spread_props(_object_spread({}, props), {
435
+ jinja: effectiveJinja
436
+ }) : props || {},
418
437
  markdownEditorRef: markdownEditorRef,
419
- markdownContainerRef: markdownContainerRef
438
+ markdownContainerRef: markdownContainerRef,
439
+ openJinjaTemplate: openJinjaTemplate,
440
+ setOpenJinjaTemplate: setOpenJinjaTemplate,
441
+ jinjaAnchorPath: jinjaAnchorPath,
442
+ setJinjaAnchorPath: setJinjaAnchorPath,
443
+ jinjaEnabled: jinjaEnabled,
444
+ jinjaTemplatePanelEnabled: jinjaTemplatePanelEnabled
420
445
  }
421
446
  }, /*#__PURE__*/ React.createElement("div", {
422
447
  id: props.id ? String(props.id) || undefined : undefined,
@@ -473,5 +498,5 @@ var I18nBoundary = function I18nBoundary(param) {
473
498
  comment: props.comment
474
499
  }) : null), readonly || (props === null || props === void 0 ? void 0 : (_props_textAreaProps = props.textAreaProps) === null || _props_textAreaProps === void 0 ? void 0 : _props_textAreaProps.enable) || (props === null || props === void 0 ? void 0 : props.reportMode) ? null : /*#__PURE__*/ React.createElement("div", {
475
500
  className: classNames("".concat(baseClassName, "-focus"))
476
- }), readonly ? /*#__PURE__*/ React.createElement(React.Fragment, null) : /*#__PURE__*/ React.createElement(React.Fragment, null, /*#__PURE__*/ React.createElement(InsertLink, null), /*#__PURE__*/ React.createElement(InsertAutocomplete, (props === null || props === void 0 ? void 0 : props.insertAutocompleteProps) || {})), children)))));
501
+ }), readonly ? /*#__PURE__*/ React.createElement(React.Fragment, null) : /*#__PURE__*/ React.createElement(React.Fragment, null, /*#__PURE__*/ React.createElement(InsertLink, null), /*#__PURE__*/ React.createElement(InsertAutocomplete, (props === null || props === void 0 ? void 0 : props.insertAutocompleteProps) || {}), jinjaTemplatePanelEnabled ? /*#__PURE__*/ React.createElement(JinjaTemplatePanel, null) : null), children)))));
477
502
  };
@@ -325,7 +325,7 @@ var defaultAllowedTypes = [
325
325
  */ export var SlateMarkdownEditor = function SlateMarkdownEditor(props) {
326
326
  var _markdownEditorRef_current, _props_textAreaProps, _props_comment, _markdownEditorRef_current1;
327
327
  // 所有hooks必须在组件顶部按固定顺序调用
328
- var _useEditorStore = useEditorStore(), store = _useEditorStore.store, markdownEditorRef = _useEditorStore.markdownEditorRef, markdownContainerRef = _useEditorStore.markdownContainerRef, readonly = _useEditorStore.readonly, setDomRect = _useEditorStore.setDomRect;
328
+ var _useEditorStore = useEditorStore(), store = _useEditorStore.store, markdownEditorRef = _useEditorStore.markdownEditorRef, markdownContainerRef = _useEditorStore.markdownContainerRef, readonly = _useEditorStore.readonly, setDomRect = _useEditorStore.setDomRect, jinjaEnabled = _useEditorStore.jinjaEnabled;
329
329
  // 懒加载元素索引计数器
330
330
  var lazyElementIndexRef = useRef(0);
331
331
  // 用于标记是否已在当前渲染周期重置过索引
@@ -357,7 +357,7 @@ var defaultAllowedTypes = [
357
357
  var plugins = useContext(PluginContext);
358
358
  var onKeyDown = useKeyboard(store, markdownEditorRef, props);
359
359
  var onChange = useOnchange(markdownEditorRef.current, props.onChange);
360
- var high = useHighlight(store);
360
+ var high = useHighlight(store, jinjaEnabled);
361
361
  var childrenIsEmpty = useMemo(function() {
362
362
  var _markdownEditorRef_current;
363
363
  if (!((_markdownEditorRef_current = markdownEditorRef.current) === null || _markdownEditorRef_current === void 0 ? void 0 : _markdownEditorRef_current.children)) return false;
@@ -410,6 +410,15 @@ var MLeafComponent = function MLeafComponent(props) {
410
410
  if (leaf.html) {
411
411
  prefixClassName = classNames(mdEditorBaseClass + '-m-html');
412
412
  }
413
+ if (leaf.jinjaVariable) {
414
+ prefixClassName = classNames(prefixClassName, "".concat(mdEditorBaseClass, "-jinja-variable"));
415
+ }
416
+ if (leaf.jinjaTag) {
417
+ prefixClassName = classNames(prefixClassName, "".concat(mdEditorBaseClass, "-jinja-tag"));
418
+ }
419
+ if (leaf.jinjaComment) {
420
+ prefixClassName = classNames(prefixClassName, "".concat(mdEditorBaseClass, "-jinja-comment"));
421
+ }
413
422
  if (leaf.current) {
414
423
  style.background = '#f59e0b';
415
424
  }
@@ -5,4 +5,4 @@ export declare const cacheTextNode: WeakMap<object, {
5
5
  range: Range[];
6
6
  }>;
7
7
  export declare const clearInlineKatex: (editor: Editor) => void;
8
- export declare function useHighlight(store?: EditorStore): ([node, path]: NodeEntry) => Range[];
8
+ export declare function useHighlight(store?: EditorStore, jinjaEnabled?: boolean): ([node, path]: NodeEntry) => Range[];
@@ -91,6 +91,9 @@ var HTML_REG = /<[a-z]+[\s"'=:;()\w\-[\]/.]*\/?>(.*<\/[a-z]+>:?)?/g;
91
91
  var LINK_REG = /(https?|ftp):\/\/[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]/gi;
92
92
  var FOOTNOTE_REG = /\[\^[^\]]+\]/g;
93
93
  var TABLE_ROW_REG = /^\|([^|]+\|)+$/;
94
+ /** 至少一个非 } 字符,避免匹配 {{}}、{{ 等不完整表达式 */ var JINJA_VARIABLE_REG = /\{\{[^}]+\}\}/g;
95
+ /** 至少一个非 % 字符,避免匹配 {%%} */ var JINJA_TAG_REG = /\{%[^%]+%\}/g;
96
+ /** 单行内注释,避免跨多行高亮造成大段误匹配(编辑器场景) */ var JINJA_COMMENT_REG = /\{#[^\n]*?#\}/g;
94
97
  export var cacheTextNode = new WeakMap();
95
98
  export var clearInlineKatex = function clearInlineKatex(editor) {
96
99
  var inlineMath = Array.from(Editor.nodes(editor, {
@@ -172,7 +175,24 @@ var processLinkMatches = function processLinkMatches(text, path, childIndex) {
172
175
  }
173
176
  return ranges;
174
177
  };
175
- export function useHighlight(store) {
178
+ var processJinjaMatches = function processJinjaMatches(text, path, childIndex) {
179
+ var ranges = [];
180
+ var collect = function collect(reg, prop) {
181
+ reg.lastIndex = 0;
182
+ var match;
183
+ while((match = reg.exec(text)) !== null){
184
+ var index = match.index;
185
+ if (typeof index === 'number') {
186
+ ranges.push(createRange(path, childIndex, index, match[0].length, _define_property({}, prop, true)));
187
+ }
188
+ }
189
+ };
190
+ collect(JINJA_VARIABLE_REG, 'jinjaVariable');
191
+ collect(JINJA_TAG_REG, 'jinjaTag');
192
+ collect(JINJA_COMMENT_REG, 'jinjaComment');
193
+ return ranges;
194
+ };
195
+ export function useHighlight(store, jinjaEnabled) {
176
196
  return function(param) {
177
197
  var _param = _sliced_to_array(param, 2), node = _param[0], path = _param[1];
178
198
  // 快速路径:非元素节点或不在高亮节点列表中
@@ -204,6 +224,10 @@ export function useHighlight(store) {
204
224
  var _allTextRanges1;
205
225
  (_allTextRanges1 = allTextRanges).push.apply(_allTextRanges1, _to_consumable_array(processLinkMatches(child.text, path, i)));
206
226
  }
227
+ if (jinjaEnabled && child.text && !EditorUtils.isDirtLeaf(child)) {
228
+ var _allTextRanges2;
229
+ (_allTextRanges2 = allTextRanges).push.apply(_allTextRanges2, _to_consumable_array(processJinjaMatches(child.text, path, i)));
230
+ }
207
231
  }
208
232
  // 统一缓存
209
233
  cacheTextNode.set(node, {
@@ -36,6 +36,10 @@ function _non_iterable_rest() {
36
36
  function _sliced_to_array(arr, i) {
37
37
  return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
38
38
  }
39
+ function _type_of(obj) {
40
+ "@swc/helpers - typeof";
41
+ return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
42
+ }
39
43
  function _unsupported_iterable_to_array(o, minLen) {
40
44
  if (!o) return;
41
45
  if (typeof o === "string") return _array_like_to_array(o, minLen);
@@ -94,7 +98,10 @@ import { useEditorStore } from "../store";
94
98
  * - 与编辑器状态深度集成,实现上下文相关的行为
95
99
  * - 提供良好的用户体验和 Markdown 编辑效率
96
100
  */ export var useKeyboard = function useKeyboard(store, markdownEditorRef, props) {
97
- var _useEditorStore = useEditorStore(), openInsertCompletion = _useEditorStore.openInsertCompletion, insertCompletionText$ = _useEditorStore.insertCompletionText$, setOpenInsertCompletion = _useEditorStore.setOpenInsertCompletion;
101
+ var _useEditorStore = useEditorStore(), openInsertCompletion = _useEditorStore.openInsertCompletion, insertCompletionText$ = _useEditorStore.insertCompletionText$, setOpenInsertCompletion = _useEditorStore.setOpenInsertCompletion, openJinjaTemplate = _useEditorStore.openJinjaTemplate, setOpenJinjaTemplate = _useEditorStore.setOpenJinjaTemplate, setJinjaAnchorPath = _useEditorStore.setJinjaAnchorPath, jinjaTemplatePanelEnabled = _useEditorStore.jinjaTemplatePanelEnabled, editorProps = _useEditorStore.editorProps;
102
+ // 从 editorProps.jinja 读取(BaseMarkdownEditor 已写入 effectiveJinja),支持插件配置的 trigger
103
+ var effectiveJinja = editorProps === null || editorProps === void 0 ? void 0 : editorProps.jinja;
104
+ var jinjaTrigger = (effectiveJinja === null || effectiveJinja === void 0 ? void 0 : effectiveJinja.templatePanel) && _type_of(effectiveJinja.templatePanel) === 'object' && effectiveJinja.templatePanel.trigger || '{}';
98
105
  return useMemo(function() {
99
106
  var tab = new TabKey(markdownEditorRef.current);
100
107
  var backspace = new BackspaceKey(markdownEditorRef.current);
@@ -114,6 +121,10 @@ import { useEditorStore } from "../store";
114
121
  e.preventDefault();
115
122
  return;
116
123
  }
124
+ if (openJinjaTemplate && (isHotkey('up', e) || isHotkey('down', e))) {
125
+ e.preventDefault();
126
+ return;
127
+ }
117
128
  if (isHotkey('mod+ArrowDown', e)) {
118
129
  e.preventDefault();
119
130
  Transforms.select(markdownEditorRef.current, Editor.end(markdownEditorRef.current, []));
@@ -239,6 +250,15 @@ import { useEditorStore } from "../store";
239
250
  var str = Node.string(node3[0]) || '';
240
251
  var codeMatch = str.match(/^```([\w+\-#]+)$/i);
241
252
  if (codeMatch) {} else {
253
+ var strAfterKey = str + (e.key.length === 1 ? e.key : '');
254
+ // 仅在实际输入一个字符且刚好补全 trigger 时打开面板,避免 Backspace 等导致误打开
255
+ if (jinjaTemplatePanelEnabled && e.key.length === 1 && strAfterKey === jinjaTrigger && setOpenJinjaTemplate && setJinjaAnchorPath) {
256
+ setJinjaAnchorPath(node3[1]);
257
+ setTimeout(function() {
258
+ return setOpenJinjaTemplate(true);
259
+ });
260
+ return;
261
+ }
242
262
  var insertMatch = str.match(/^\/([^\n]+)?$/i);
243
263
  if (insertMatch && !(!Path.hasPrevious(node3[1]) && Node.parent(markdownEditorRef.current, node3[1]).type === 'list-item')) {
244
264
  setOpenInsertCompletion === null || setOpenInsertCompletion === void 0 ? void 0 : setOpenInsertCompletion(true);
@@ -252,6 +272,14 @@ import { useEditorStore } from "../store";
252
272
  };
253
273
  }, [
254
274
  markdownEditorRef.current,
255
- props === null || props === void 0 ? void 0 : props.readonly
275
+ props === null || props === void 0 ? void 0 : props.readonly,
276
+ openInsertCompletion,
277
+ insertCompletionText$,
278
+ setOpenInsertCompletion,
279
+ openJinjaTemplate,
280
+ setOpenJinjaTemplate,
281
+ setJinjaAnchorPath,
282
+ jinjaTemplatePanelEnabled,
283
+ jinjaTrigger
256
284
  ]);
257
285
  };
@@ -46,6 +46,18 @@ export interface EditorStoreContextType {
46
46
  openInsertCompletion?: boolean;
47
47
  /** 设置打开插入自动完成状态 */
48
48
  setOpenInsertCompletion?: (open: boolean) => void;
49
+ /** 是否打开 Jinja 模板面板 */
50
+ openJinjaTemplate?: boolean;
51
+ /** 设置打开 Jinja 模板面板状态 */
52
+ setOpenJinjaTemplate?: (open: boolean) => void;
53
+ /** Jinja 弹层插入锚点 path(当前段落节点 path) */
54
+ jinjaAnchorPath?: number[] | null;
55
+ /** 设置 Jinja 弹层锚点 path */
56
+ setJinjaAnchorPath?: (path: number[] | null) => void;
57
+ /** 是否启用 Jinja(总开关,用于语法高亮等) */
58
+ jinjaEnabled?: boolean;
59
+ /** 是否启用 Jinja 模板面板(用于触发与弹层) */
60
+ jinjaTemplatePanelEnabled?: boolean;
49
61
  /** 编辑器属性配置 */
50
62
  editorProps: MarkdownEditorProps;
51
63
  /** Markdown编辑器引用 */
@@ -163,7 +163,13 @@ export var EditorStoreContext = createContext(null);
163
163
  readonly: true,
164
164
  typewriter: false,
165
165
  editorProps: {},
166
- markdownEditorRef: {}
166
+ markdownEditorRef: {},
167
+ openJinjaTemplate: false,
168
+ setOpenJinjaTemplate: undefined,
169
+ jinjaAnchorPath: null,
170
+ setJinjaAnchorPath: undefined,
171
+ jinjaEnabled: false,
172
+ jinjaTemplatePanelEnabled: false
167
173
  };
168
174
  };
169
175
  /** 支持键入操作的标签类型列表 */ var SUPPORT_TYPING_TAG = [
@@ -529,6 +529,16 @@ var genStyle = function genStyle(token) {
529
529
  '& &-m-html': {
530
530
  color: 'rgba(0,0,0,0.45)'
531
531
  },
532
+ '& &-jinja-variable': {
533
+ color: 'var(--color-primary-control-fill-primary, #1677ff)'
534
+ },
535
+ '& &-jinja-tag': {
536
+ color: 'var(--color-orange-6, #d46b08)'
537
+ },
538
+ '& &-jinja-comment': {
539
+ color: 'var(--color-text-tertiary, rgba(0,0,0,0.25))',
540
+ fontStyle: 'italic'
541
+ },
532
542
  '&:not(:last-child)': {
533
543
  marginBottom: '0.5em'
534
544
  },
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const JinjaTemplatePanel: React.FC;
@@ -0,0 +1,327 @@
1
+ function _array_like_to_array(arr, len) {
2
+ if (len == null || len > arr.length) len = arr.length;
3
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
4
+ return arr2;
5
+ }
6
+ function _array_with_holes(arr) {
7
+ if (Array.isArray(arr)) return arr;
8
+ }
9
+ function _define_property(obj, key, value) {
10
+ if (key in obj) {
11
+ Object.defineProperty(obj, key, {
12
+ value: value,
13
+ enumerable: true,
14
+ configurable: true,
15
+ writable: true
16
+ });
17
+ } else {
18
+ obj[key] = value;
19
+ }
20
+ return obj;
21
+ }
22
+ function _iterable_to_array_limit(arr, i) {
23
+ var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
24
+ if (_i == null) return;
25
+ var _arr = [];
26
+ var _n = true;
27
+ var _d = false;
28
+ var _s, _e;
29
+ try {
30
+ for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
31
+ _arr.push(_s.value);
32
+ if (i && _arr.length === i) break;
33
+ }
34
+ } catch (err) {
35
+ _d = true;
36
+ _e = err;
37
+ } finally{
38
+ try {
39
+ if (!_n && _i["return"] != null) _i["return"]();
40
+ } finally{
41
+ if (_d) throw _e;
42
+ }
43
+ }
44
+ return _arr;
45
+ }
46
+ function _non_iterable_rest() {
47
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
48
+ }
49
+ function _sliced_to_array(arr, i) {
50
+ return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
51
+ }
52
+ function _type_of(obj) {
53
+ "@swc/helpers - typeof";
54
+ return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
55
+ }
56
+ function _unsupported_iterable_to_array(o, minLen) {
57
+ if (!o) return;
58
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
59
+ var n = Object.prototype.toString.call(o).slice(8, -1);
60
+ if (n === "Object" && o.constructor) n = o.constructor.name;
61
+ if (n === "Map" || n === "Set") return Array.from(n);
62
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
63
+ }
64
+ import { ConfigProvider, Typography } from "antd";
65
+ import classNames from "clsx";
66
+ import isHotkey from "is-hotkey";
67
+ import React, { useCallback, useEffect, useRef, useState } from "react";
68
+ import ReactDOM from "react-dom";
69
+ import { Editor, Transforms } from "slate";
70
+ import { ReactEditor } from "slate-react";
71
+ import { useEditorStore } from "../../store";
72
+ import { getOffsetLeft } from "../../utils/dom";
73
+ import { EditorUtils } from "../../utils/editorUtils";
74
+ import { JINJA_PANEL_PREFIX_CLS, useJinjaTemplatePanelStyle } from "./style";
75
+ import { JINJA_DOC_LINK, JINJA_TEMPLATE_DATA } from "./templates";
76
+ var PANEL_MAX_HEIGHT = 320;
77
+ function getPosition(nodeEl) {
78
+ var rect = nodeEl.getBoundingClientRect();
79
+ var left = getOffsetLeft(nodeEl, document.body) + 0;
80
+ var top = rect.bottom + window.scrollY;
81
+ var viewportHeight = document.documentElement.clientHeight;
82
+ var spaceBelow = viewportHeight - rect.bottom;
83
+ if (spaceBelow < PANEL_MAX_HEIGHT && rect.top > PANEL_MAX_HEIGHT) {
84
+ return {
85
+ left: left,
86
+ bottom: viewportHeight - rect.top
87
+ };
88
+ }
89
+ return {
90
+ left: left,
91
+ top: top
92
+ };
93
+ }
94
+ export var JinjaTemplatePanel = function JinjaTemplatePanel() {
95
+ var _ref, _ref1, _ref2, _ref3;
96
+ var _context_getPrefixCls;
97
+ var _useEditorStore = useEditorStore(), markdownEditorRef = _useEditorStore.markdownEditorRef, markdownContainerRef = _useEditorStore.markdownContainerRef, openJinjaTemplate = _useEditorStore.openJinjaTemplate, setOpenJinjaTemplate = _useEditorStore.setOpenJinjaTemplate, jinjaAnchorPath = _useEditorStore.jinjaAnchorPath, setJinjaAnchorPath = _useEditorStore.setJinjaAnchorPath, editorProps = _useEditorStore.editorProps;
98
+ var jinjaConfig = editorProps === null || editorProps === void 0 ? void 0 : editorProps.jinja;
99
+ var templatePanelConfig = (jinjaConfig === null || jinjaConfig === void 0 ? void 0 : jinjaConfig.templatePanel) && _type_of(jinjaConfig.templatePanel) === 'object' ? jinjaConfig.templatePanel : undefined;
100
+ var trigger = (_ref = templatePanelConfig === null || templatePanelConfig === void 0 ? void 0 : templatePanelConfig.trigger) !== null && _ref !== void 0 ? _ref : '{}';
101
+ var docLink = (_ref1 = jinjaConfig === null || jinjaConfig === void 0 ? void 0 : jinjaConfig.docLink) !== null && _ref1 !== void 0 ? _ref1 : JINJA_DOC_LINK;
102
+ var notFoundContent = (_ref2 = templatePanelConfig === null || templatePanelConfig === void 0 ? void 0 : templatePanelConfig.notFoundContent) !== null && _ref2 !== void 0 ? _ref2 : null;
103
+ var itemsConfig = templatePanelConfig === null || templatePanelConfig === void 0 ? void 0 : templatePanelConfig.items;
104
+ var _useState = _sliced_to_array(useState(JINJA_TEMPLATE_DATA), 2), items = _useState[0], setItems = _useState[1];
105
+ var _useState1 = _sliced_to_array(useState(false), 2), loading = _useState1[0], setLoading = _useState1[1];
106
+ var _useState2 = _sliced_to_array(useState(0), 2), activeIndex = _useState2[0], setActiveIndex = _useState2[1];
107
+ var _useState3 = _sliced_to_array(useState({
108
+ left: 0
109
+ }), 2), position = _useState3[0], setPosition = _useState3[1];
110
+ var domRef = useRef(null);
111
+ var context = React.useContext(ConfigProvider.ConfigContext);
112
+ var prefixCls = (_ref3 = context === null || context === void 0 ? void 0 : (_context_getPrefixCls = context.getPrefixCls) === null || _context_getPrefixCls === void 0 ? void 0 : _context_getPrefixCls.call(context, 'md-editor-jinja-panel')) !== null && _ref3 !== void 0 ? _ref3 : JINJA_PANEL_PREFIX_CLS;
113
+ var _useJinjaTemplatePanelStyle = useJinjaTemplatePanelStyle(prefixCls), wrapSSR = _useJinjaTemplatePanelStyle.wrapSSR, hashId = _useJinjaTemplatePanelStyle.hashId;
114
+ var close = useCallback(function() {
115
+ setOpenJinjaTemplate === null || setOpenJinjaTemplate === void 0 ? void 0 : setOpenJinjaTemplate(false);
116
+ setJinjaAnchorPath === null || setJinjaAnchorPath === void 0 ? void 0 : setJinjaAnchorPath(null);
117
+ setActiveIndex(0);
118
+ }, [
119
+ setOpenJinjaTemplate,
120
+ setJinjaAnchorPath
121
+ ]);
122
+ var handleClickOutside = useCallback(function(e) {
123
+ var target = e.target;
124
+ if (domRef.current && !domRef.current.contains(target)) {
125
+ close();
126
+ }
127
+ }, [
128
+ close
129
+ ]);
130
+ useEffect(function() {
131
+ if (!openJinjaTemplate) return;
132
+ if (typeof itemsConfig === 'function') {
133
+ setLoading(true);
134
+ var editor = markdownEditorRef === null || markdownEditorRef === void 0 ? void 0 : markdownEditorRef.current;
135
+ itemsConfig({
136
+ editor: editor
137
+ }).then(function(list) {
138
+ setItems(Array.isArray(list) ? list : JINJA_TEMPLATE_DATA);
139
+ }).catch(function(err) {
140
+ setItems(JINJA_TEMPLATE_DATA);
141
+ if (process.env.NODE_ENV !== 'production') {
142
+ console.error('[JinjaTemplatePanel] Failed to load template items:', err);
143
+ }
144
+ }).finally(function() {
145
+ return setLoading(false);
146
+ });
147
+ } else if (Array.isArray(itemsConfig)) {
148
+ setItems(itemsConfig);
149
+ } else {
150
+ setItems(JINJA_TEMPLATE_DATA);
151
+ }
152
+ }, [
153
+ openJinjaTemplate,
154
+ itemsConfig,
155
+ markdownEditorRef
156
+ ]);
157
+ useEffect(function() {
158
+ if (!openJinjaTemplate || !jinjaAnchorPath || !(markdownEditorRef === null || markdownEditorRef === void 0 ? void 0 : markdownEditorRef.current)) return;
159
+ var editor = markdownEditorRef.current;
160
+ try {
161
+ var _Editor_node = _sliced_to_array(Editor.node(editor, jinjaAnchorPath), 1), node = _Editor_node[0];
162
+ if (node) {
163
+ var el = ReactEditor.toDOMNode(editor, node);
164
+ if (el) {
165
+ var pos = getPosition(el);
166
+ setPosition(pos);
167
+ }
168
+ }
169
+ } catch (unused) {
170
+ setPosition({
171
+ left: 0
172
+ });
173
+ }
174
+ }, [
175
+ openJinjaTemplate,
176
+ jinjaAnchorPath,
177
+ markdownEditorRef
178
+ ]);
179
+ useEffect(function() {
180
+ if (!openJinjaTemplate) return;
181
+ if (typeof window === 'undefined') return;
182
+ window.addEventListener('click', handleClickOutside);
183
+ return function() {
184
+ return window.removeEventListener('click', handleClickOutside);
185
+ };
186
+ }, [
187
+ openJinjaTemplate,
188
+ handleClickOutside
189
+ ]);
190
+ var insertTemplate = useCallback(function(item) {
191
+ var editor = markdownEditorRef === null || markdownEditorRef === void 0 ? void 0 : markdownEditorRef.current;
192
+ if (!editor || !jinjaAnchorPath || !setOpenJinjaTemplate) return;
193
+ try {
194
+ var _Editor_before;
195
+ var end = Editor.end(editor, jinjaAnchorPath);
196
+ var start = (_Editor_before = Editor.before(editor, end, {
197
+ distance: trigger.length
198
+ })) !== null && _Editor_before !== void 0 ? _Editor_before : end;
199
+ Transforms.delete(editor, {
200
+ at: {
201
+ anchor: start,
202
+ focus: end
203
+ }
204
+ });
205
+ Transforms.insertText(editor, item.template, {
206
+ at: start
207
+ });
208
+ EditorUtils.focus(editor);
209
+ } finally{
210
+ close();
211
+ }
212
+ }, [
213
+ markdownEditorRef,
214
+ jinjaAnchorPath,
215
+ trigger.length,
216
+ setOpenJinjaTemplate,
217
+ close
218
+ ]);
219
+ var keydown = useCallback(function(e) {
220
+ if (!openJinjaTemplate) return;
221
+ if (isHotkey('esc', e)) {
222
+ e.preventDefault();
223
+ close();
224
+ EditorUtils.focus(markdownEditorRef === null || markdownEditorRef === void 0 ? void 0 : markdownEditorRef.current);
225
+ return;
226
+ }
227
+ if (e.key === 'ArrowUp') {
228
+ e.preventDefault();
229
+ setActiveIndex(function(i) {
230
+ return i > 0 ? i - 1 : items.length - 1;
231
+ });
232
+ return;
233
+ }
234
+ if (e.key === 'ArrowDown') {
235
+ e.preventDefault();
236
+ setActiveIndex(function(i) {
237
+ return i < items.length - 1 ? i + 1 : 0;
238
+ });
239
+ return;
240
+ }
241
+ if (e.key === 'Enter' && items[activeIndex]) {
242
+ e.preventDefault();
243
+ e.stopPropagation();
244
+ insertTemplate(items[activeIndex]);
245
+ }
246
+ }, [
247
+ openJinjaTemplate,
248
+ close,
249
+ markdownEditorRef,
250
+ items,
251
+ activeIndex,
252
+ insertTemplate
253
+ ]);
254
+ useEffect(function() {
255
+ var container = markdownContainerRef === null || markdownContainerRef === void 0 ? void 0 : markdownContainerRef.current;
256
+ if (!container) return;
257
+ container.addEventListener('keydown', keydown);
258
+ return function() {
259
+ return container.removeEventListener('keydown', keydown);
260
+ };
261
+ }, [
262
+ markdownContainerRef,
263
+ keydown
264
+ ]);
265
+ useEffect(function() {
266
+ setActiveIndex(0);
267
+ }, [
268
+ items
269
+ ]);
270
+ if (!openJinjaTemplate) return null;
271
+ var panel = wrapSSR(/*#__PURE__*/ React.createElement("div", {
272
+ ref: domRef,
273
+ role: "listbox",
274
+ "aria-label": "Jinja template list",
275
+ className: classNames(prefixCls, hashId),
276
+ style: {
277
+ position: 'absolute',
278
+ zIndex: 9999,
279
+ left: position.left,
280
+ top: position.top,
281
+ bottom: position.bottom
282
+ },
283
+ onMouseDown: function onMouseDown(e) {
284
+ return e.preventDefault();
285
+ }
286
+ }, /*#__PURE__*/ React.createElement("div", {
287
+ className: "".concat(prefixCls, "__content")
288
+ }, docLink ? /*#__PURE__*/ React.createElement("div", {
289
+ className: "".concat(prefixCls, "__doc-link")
290
+ }, /*#__PURE__*/ React.createElement(Typography.Link, {
291
+ href: docLink,
292
+ target: "_blank",
293
+ rel: "noopener noreferrer",
294
+ "aria-label": "打开 Jinja 使用说明(新窗口)"
295
+ }, "使用说明")) : null, /*#__PURE__*/ React.createElement("div", {
296
+ className: "".concat(prefixCls, "__list-box")
297
+ }, loading ? /*#__PURE__*/ React.createElement("div", {
298
+ style: {
299
+ padding: 12,
300
+ color: 'var(--color-text-secondary)'
301
+ }
302
+ }, "加载中...") : items.length === 0 ? notFoundContent !== null && notFoundContent !== void 0 ? notFoundContent : /*#__PURE__*/ React.createElement("div", {
303
+ style: {
304
+ padding: 12,
305
+ color: 'var(--color-text-secondary)'
306
+ }
307
+ }, "暂无模板") : items.map(function(item, i) {
308
+ return /*#__PURE__*/ React.createElement("div", {
309
+ key: i,
310
+ role: "option",
311
+ "aria-selected": i === activeIndex,
312
+ className: classNames("".concat(prefixCls, "__item"), _define_property({}, "".concat(prefixCls, "__item--active"), i === activeIndex)),
313
+ onMouseDown: function onMouseDown(e) {
314
+ e.preventDefault();
315
+ insertTemplate(item);
316
+ },
317
+ onMouseEnter: function onMouseEnter() {
318
+ return setActiveIndex(i);
319
+ }
320
+ }, /*#__PURE__*/ React.createElement("span", {
321
+ className: "".concat(prefixCls, "__item-title")
322
+ }, item.title), item.description ? /*#__PURE__*/ React.createElement("span", {
323
+ className: "".concat(prefixCls, "__item-desc")
324
+ }, item.description) : null);
325
+ })))));
326
+ return /*#__PURE__*/ ReactDOM.createPortal(panel, document.body);
327
+ };
@@ -0,0 +1,9 @@
1
+ /// <reference types="react" />
2
+ export declare const JINJA_PANEL_PREFIX_CLS = "md-editor-jinja-panel";
3
+ export declare function useJinjaTemplatePanelStyle(prefixCls?: string): {
4
+ hashId: string;
5
+ wrapSSR: (node: import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>) => import("react").JSX.Element;
6
+ } | {
7
+ wrapSSR: (node: any) => any;
8
+ hashId: string;
9
+ };
@@ -0,0 +1,131 @@
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 { resetComponent, useEditorStyleRegister } from "../../../../Hooks/useStyle";
54
+ export var JINJA_PANEL_PREFIX_CLS = 'md-editor-jinja-panel';
55
+ var genJinjaPanelStyle = function genJinjaPanelStyle(token) {
56
+ return _define_property({}, token.componentCls, {
57
+ boxSizing: 'border-box',
58
+ display: 'flex',
59
+ flexDirection: 'column',
60
+ maxHeight: 320,
61
+ minWidth: 240,
62
+ overflow: 'hidden',
63
+ borderRadius: token.borderRadius,
64
+ backgroundColor: token.colorBgContainer,
65
+ boxShadow: token.boxShadowSecondary,
66
+ border: "1px solid ".concat(token.colorBorder),
67
+ '&__content': {
68
+ display: 'flex',
69
+ flexDirection: 'column',
70
+ flex: 1,
71
+ overflow: 'hidden'
72
+ },
73
+ '&__doc-link': {
74
+ padding: '8px 12px',
75
+ fontSize: token.fontSizeSM,
76
+ color: token.colorLink,
77
+ borderBottom: "1px solid ".concat(token.colorBorder),
78
+ a: {
79
+ color: 'inherit',
80
+ textDecoration: 'none',
81
+ '&:hover': {
82
+ textDecoration: 'underline'
83
+ },
84
+ '&:focus-visible': {
85
+ outline: "2px solid ".concat(token.colorPrimary),
86
+ outlineOffset: 2,
87
+ borderRadius: token.borderRadiusSM
88
+ }
89
+ }
90
+ },
91
+ '&__list-box': {
92
+ flex: 1,
93
+ overflowY: 'auto',
94
+ padding: '4px 0'
95
+ },
96
+ '&__item': {
97
+ display: 'flex',
98
+ flexDirection: 'column',
99
+ gap: 2,
100
+ padding: '8px 12px',
101
+ cursor: 'pointer',
102
+ '&:hover': {
103
+ backgroundColor: token.colorFillTertiary
104
+ },
105
+ '&--active': {
106
+ backgroundColor: token.controlItemBgHover
107
+ }
108
+ },
109
+ '&__item-title': {
110
+ fontSize: token.fontSize,
111
+ fontWeight: token.fontWeightStrong,
112
+ color: token.colorText
113
+ },
114
+ '&__item-desc': {
115
+ fontSize: token.fontSizeSM,
116
+ color: token.colorTextSecondary
117
+ }
118
+ });
119
+ };
120
+ export function useJinjaTemplatePanelStyle(prefixCls) {
121
+ var componentCls = '.' + (prefixCls || JINJA_PANEL_PREFIX_CLS);
122
+ return useEditorStyleRegister('JinjaTemplatePanel-' + (prefixCls || JINJA_PANEL_PREFIX_CLS), function(token) {
123
+ var editorToken = _object_spread_props(_object_spread({}, token), {
124
+ componentCls: componentCls
125
+ });
126
+ return [
127
+ resetComponent(editorToken),
128
+ genJinjaPanelStyle(editorToken)
129
+ ];
130
+ });
131
+ }
@@ -0,0 +1,5 @@
1
+ import type { JinjaTemplateItem } from '../../../types';
2
+ /** 内置 Jinja 模板数据,与 agent-ui-pc JinjaTemplateData 文案一致 */
3
+ export declare const JINJA_TEMPLATE_DATA: JinjaTemplateItem[];
4
+ /** 默认使用说明链接,未配置 jinja.docLink 时使用 */
5
+ export declare const JINJA_DOC_LINK = "https://jinja.palletsprojects.com/";
@@ -0,0 +1,28 @@
1
+ /** 内置 Jinja 模板数据,与 agent-ui-pc JinjaTemplateData 文案一致 */ export var JINJA_TEMPLATE_DATA = [
2
+ {
3
+ title: '变量插值',
4
+ description: '{{ variable }}',
5
+ template: '{{ }}'
6
+ },
7
+ {
8
+ title: '条件语句',
9
+ description: '{% if condition %}...{% endif %}',
10
+ template: '{% if %}\n \n{% endif %}'
11
+ },
12
+ {
13
+ title: '循环遍历',
14
+ description: '{% for item in list %}...{% endfor %}',
15
+ template: '{% for in %}\n \n{% endfor %}'
16
+ },
17
+ {
18
+ title: '过滤器',
19
+ description: '{{ value | filter }}',
20
+ template: '{{ | }}'
21
+ },
22
+ {
23
+ title: '设置变量',
24
+ description: '{% set name = value %}',
25
+ template: '{% set = %}'
26
+ }
27
+ ];
28
+ /** 默认使用说明链接,未配置 jinja.docLink 时使用 */ export var JINJA_DOC_LINK = 'https://jinja.palletsprojects.com/';
@@ -228,6 +228,9 @@ export type CustomLeaf<T = Record<string, any>> = {
228
228
  fnc?: boolean;
229
229
  fnd?: boolean;
230
230
  comment?: boolean;
231
+ jinjaVariable?: boolean;
232
+ jinjaTag?: boolean;
233
+ jinjaComment?: boolean;
231
234
  selection?: BaseRange;
232
235
  id?: string;
233
236
  data?: Record<string, any>;
@@ -2,6 +2,7 @@ import { Node } from 'mdast';
2
2
  import React from 'react';
3
3
  import { Editor, NodeEntry } from 'slate';
4
4
  import { ElementProps, Elements } from './el';
5
+ import type { JinjaConfig } from './types';
5
6
  export type MarkdownEditorPlugin = {
6
7
  elements?: Record<string, React.ComponentType<ElementProps<any>>>;
7
8
  parseMarkdown?: {
@@ -15,5 +16,9 @@ export type MarkdownEditorPlugin = {
15
16
  withEditor?: (editor: Editor) => Editor;
16
17
  hotkeys?: Record<string, (editor: Editor) => void>;
17
18
  onPaste?: (text: string) => boolean;
19
+ /** 启用 Jinja 能力(模板面板 + 语法高亮),与 props.jinja?.enable 二选一 */
20
+ jinja?: true;
21
+ /** 通过插件启用时的默认 Jinja 配置(当未传 props.jinja 时使用) */
22
+ jinjaConfig?: JinjaConfig;
18
23
  };
19
24
  export declare const PluginContext: React.Context<MarkdownEditorPlugin[]>;
@@ -0,0 +1,21 @@
1
+ import type { MarkdownEditorPlugin } from '../plugin';
2
+ import type { JinjaConfig } from '../types';
3
+ /** createJinjaPlugin 的配置:不含 enable,插件语义即“启用 Jinja”,内部始终 enable: true */
4
+ export type JinjaPluginOptions = Omit<Partial<JinjaConfig>, 'enable'>;
5
+ /**
6
+ * 创建 Jinja 插件,启用模板面板(输入 `{}` 触发)与编辑器内 Jinja 语法高亮。
7
+ * 可通过 props.jinja 配置,或仅通过插件启用并在此传入默认配置。
8
+ * 不在 options 中接受 enable,插件即表示启用,产出配置始终 enable: true。
9
+ *
10
+ * @param options 可选,与 props.jinja 同结构(不含 enable),用于通过插件启用时提供默认配置
11
+ * @returns MarkdownEditorPlugin & { jinja: true; jinjaConfig?: JinjaConfig }
12
+ */
13
+ export declare function createJinjaPlugin(options?: JinjaPluginOptions): MarkdownEditorPlugin & {
14
+ jinja: true;
15
+ jinjaConfig?: JinjaConfig;
16
+ };
17
+ /** 默认 Jinja 插件实例,可直接用于 plugins={[jinjaPlugin]} */
18
+ export declare const jinjaPlugin: MarkdownEditorPlugin & {
19
+ jinja: true;
20
+ jinjaConfig?: JinjaConfig | undefined;
21
+ };
@@ -0,0 +1,70 @@
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
+ /**
54
+ * 创建 Jinja 插件,启用模板面板(输入 `{}` 触发)与编辑器内 Jinja 语法高亮。
55
+ * 可通过 props.jinja 配置,或仅通过插件启用并在此传入默认配置。
56
+ * 不在 options 中接受 enable,插件即表示启用,产出配置始终 enable: true。
57
+ *
58
+ * @param options 可选,与 props.jinja 同结构(不含 enable),用于通过插件启用时提供默认配置
59
+ * @returns MarkdownEditorPlugin & { jinja: true; jinjaConfig?: JinjaConfig }
60
+ */ export function createJinjaPlugin(options) {
61
+ var jinjaConfig = options ? _object_spread_props(_object_spread({}, options), {
62
+ enable: true
63
+ }) : undefined;
64
+ return _object_spread({
65
+ jinja: true
66
+ }, jinjaConfig ? {
67
+ jinjaConfig: jinjaConfig
68
+ } : {});
69
+ }
70
+ /** 默认 Jinja 插件实例,可直接用于 plugins={[jinjaPlugin]} */ export var jinjaPlugin = createJinjaPlugin();
@@ -1,7 +1,7 @@
1
1
  import type { Ace } from 'ace-builds';
2
2
  import { AnchorProps, ImageProps } from 'antd';
3
3
  import React from 'react';
4
- import { BaseEditor, Selection } from 'slate';
4
+ import { BaseEditor, Editor, Selection } from 'slate';
5
5
  import { HistoryEditor } from 'slate-history';
6
6
  import { ReactEditor, RenderElementProps } from 'slate-react';
7
7
  import { TagPopupProps } from './editor/elements/TagPopup';
@@ -42,6 +42,39 @@ export type CommentDataType = {
42
42
  avatar?: string;
43
43
  };
44
44
  };
45
+ /** Jinja 模板项,与 agent-ui-pc JinjaTemplateData 一致 */
46
+ export type JinjaTemplateItem = {
47
+ title: string;
48
+ description?: string;
49
+ template: string;
50
+ };
51
+ /** 模板列表:静态数组或异步加载(与 TagPopupProps.items 一致) */
52
+ export type JinjaTemplatePanelItems = JinjaTemplateItem[] | ((params?: {
53
+ editor?: Editor;
54
+ }) => Promise<JinjaTemplateItem[]>);
55
+ /** 模板面板配置(与 tag 配置做成一样,支持 items 异步) */
56
+ export interface JinjaTemplatePanelConfig {
57
+ /** 是否开启 {} 触发与模板面板,默认 true */
58
+ enable?: boolean;
59
+ /** 触发符,默认 '{}' */
60
+ trigger?: string;
61
+ /**
62
+ * 模板列表:静态数组或异步加载
63
+ * 不传时使用内置 JINJA_TEMPLATE_DATA
64
+ */
65
+ items?: JinjaTemplatePanelItems;
66
+ /** 无数据时展示,同 TagPopupProps.notFoundContent */
67
+ notFoundContent?: React.ReactNode;
68
+ }
69
+ /** Jinja 配置:总开关、使用说明链接、模板面板 */
70
+ export interface JinjaConfig {
71
+ /** 总开关:为 true 时启用 Jinja 语法高亮;同时若未关闭 templatePanel 则启用模板面板 */
72
+ enable: boolean;
73
+ /** 使用说明链接,供模板面板「使用说明」使用 */
74
+ docLink?: string;
75
+ /** 模板面板配置(与 tag 配置做成一样,支持 items 异步) */
76
+ templatePanel?: boolean | JinjaTemplatePanelConfig;
77
+ }
45
78
  /**
46
79
  * 编辑器接口定义
47
80
  * @interface IEditor
@@ -338,6 +371,10 @@ export type MarkdownEditorProps = {
338
371
  enabled?: boolean;
339
372
  allowedTypes?: string[];
340
373
  };
374
+ /**
375
+ * Jinja 配置:语法高亮与模板面板(输入 `{}` 触发)
376
+ */
377
+ jinja?: JinjaConfig;
341
378
  /**
342
379
  * 插件配置
343
380
  */
@@ -46,5 +46,5 @@ export type ThoughtChainProps = TaskListProps;
46
46
  * />
47
47
  * ```
48
48
  */
49
- export declare const TaskList: React.MemoExoticComponent<({ items, className, expandedKeys, onExpandedKeysChange, }: TaskListProps) => any>;
49
+ export declare const TaskList: React.MemoExoticComponent<({ items, className, expandedKeys, onExpandedKeysChange }: TaskListProps) => any>;
50
50
  export {};
package/dist/index.d.ts CHANGED
@@ -11,14 +11,14 @@ import './root.css';
11
11
  export type { RenderElementProps } from 'slate-react';
12
12
  export * from './Types';
13
13
  export * from './AgenticLayout';
14
- export { default as Workspace } from './Workspace';
15
14
  export * from './Workspace';
15
+ export { default as Workspace } from './Workspace';
16
16
  export * from './Workspace/types';
17
17
  export * from './Bubble';
18
18
  export * from './Bubble/List';
19
+ export * from './Bubble/MessagesContent/VoiceButton/types';
19
20
  export * from './Bubble/type';
20
21
  export * from './Bubble/types/DocInfo';
21
- export * from './Bubble/MessagesContent/VoiceButton/types';
22
22
  export * from './ChatBootPage';
23
23
  export * from './ChatLayout';
24
24
  export * from './ThoughtChainList';
@@ -32,10 +32,11 @@ export * from './History/types';
32
32
  export * from './History/types/HistoryData';
33
33
  export * from './History/types/HistoryList';
34
34
  export * from './MarkdownEditor';
35
- export * from './MarkdownEditor/types';
36
35
  export * from './MarkdownEditor/el';
37
- export * from './MarkdownEditor/plugin';
38
36
  export { useSelStatus } from './MarkdownEditor/hooks/editor';
37
+ export * from './MarkdownEditor/plugin';
38
+ export { createJinjaPlugin, jinjaPlugin, type JinjaPluginOptions, } from './MarkdownEditor/plugins/jinja';
39
+ export * from './MarkdownEditor/types';
39
40
  export * from './MarkdownEditor/editor/components/index';
40
41
  export * from './MarkdownEditor/editor/elements/Table/Table';
41
42
  export * from './MarkdownEditor/editor/elements/Table/TableContext';
@@ -45,45 +46,45 @@ export * from './MarkdownEditor/editor/parser/parserSlateNodeToMarkdown';
45
46
  export * from './MarkdownEditor/editor/store';
46
47
  export * from './MarkdownEditor/editor/utils';
47
48
  export * from './MarkdownEditor/editor/utils/docx/index';
48
- export * from './MarkdownEditor/editor/utils/markdownToHtml';
49
49
  export * from './MarkdownEditor/editor/utils/htmlToMarkdown';
50
+ export * from './MarkdownEditor/editor/utils/markdownToHtml';
50
51
  export * from './MarkdownEditor/utils/native-table/native-table-editor';
51
- export * from './MarkdownInputField/MarkdownInputField';
52
52
  export * from './MarkdownInputField/AttachmentButton';
53
- export * from './MarkdownInputField/AttachmentButton/types';
54
53
  export * from './MarkdownInputField/AttachmentButton/AttachmentFileList';
55
54
  export * from './MarkdownInputField/AttachmentButton/AttachmentFileList/AttachmentFileListItem';
55
+ export * from './MarkdownInputField/AttachmentButton/types';
56
56
  export * from './MarkdownInputField/AttachmentButton/utils';
57
+ export { ActionItemContainer } from './MarkdownInputField/BeforeToolContainer/BeforeToolContainer';
57
58
  export * from './MarkdownInputField/FileMapView';
59
+ export * from './MarkdownInputField/MarkdownInputField';
58
60
  export * from './MarkdownInputField/VoiceInput';
59
- export { ActionItemContainer } from './MarkdownInputField/BeforeToolContainer/BeforeToolContainer';
60
61
  export * from './Schema';
61
- export * from './Schema/types';
62
62
  export * from './Schema/SchemaRenderer/templateEngine';
63
+ export * from './Schema/types';
63
64
  export * from './Schema/validator';
64
- export * from './Plugins/formatter';
65
65
  export * from './Plugins/chart';
66
- export * from './Plugins/mermaid';
67
66
  export * from './Plugins/code/components';
67
+ export * from './Plugins/formatter';
68
+ export * from './Plugins/mermaid';
68
69
  export * from './AILabel';
69
70
  export * from './AnswerAlert';
70
71
  export * from './BackTo';
71
- export * from './WelcomeMessage';
72
72
  export { default as Quote } from './Quote';
73
73
  export type { QuoteProps } from './Quote';
74
+ export * from './WelcomeMessage';
74
75
  export * from './Components/ActionIconBox';
75
76
  export { ActionItemBox } from './Components/ActionItemBox';
76
77
  export * from './Components/Button';
78
+ export * from './Components/GradientText';
77
79
  export * from './Components/LayoutHeader';
78
80
  export * from './Components/Loading';
79
81
  export * from './Components/lotties';
80
- export * from './Components/SuggestionList';
81
- export * from './Components/VisualList';
82
82
  export * from './Components/Robot';
83
83
  export { default as Robot } from './Components/Robot';
84
- export * from './Components/GradientText';
84
+ export * from './Components/SuggestionList';
85
85
  export * from './Components/TextAnimate';
86
86
  export * from './Components/TypingAnimation';
87
+ export * from './Components/VisualList';
87
88
  export * from './Hooks/useAutoScroll';
88
89
  export { useLanguage } from './Hooks/useLanguage';
89
90
  export * from './Hooks/useRefFunction';
package/dist/index.js CHANGED
@@ -11,15 +11,15 @@
11
11
  export * from "./Types";
12
12
  // ─── 布局组件 ────────────────────────────────────────────────────────────────
13
13
  export * from "./AgenticLayout";
14
- export { default as Workspace } from "./Workspace";
15
14
  export * from "./Workspace";
15
+ export { default as Workspace } from "./Workspace";
16
16
  export * from "./Workspace/types";
17
17
  // ─── 聊天气泡 ────────────────────────────────────────────────────────────────
18
18
  export * from "./Bubble";
19
19
  export * from "./Bubble/List";
20
+ export * from "./Bubble/MessagesContent/VoiceButton/types";
20
21
  export * from "./Bubble/type";
21
22
  export * from "./Bubble/types/DocInfo";
22
- export * from "./Bubble/MessagesContent/VoiceButton/types";
23
23
  // ─── 聊天启动页 ──────────────────────────────────────────────────────────────
24
24
  export * from "./ChatBootPage";
25
25
  export * from "./ChatLayout";
@@ -38,10 +38,11 @@ export * from "./History/types/HistoryData";
38
38
  export * from "./History/types/HistoryList";
39
39
  // ─── Markdown 编辑器 ─────────────────────────────────────────────────────────
40
40
  export * from "./MarkdownEditor";
41
- export * from "./MarkdownEditor/types";
42
41
  export * from "./MarkdownEditor/el";
43
- export * from "./MarkdownEditor/plugin";
44
42
  export { useSelStatus } from "./MarkdownEditor/hooks/editor";
43
+ export * from "./MarkdownEditor/plugin";
44
+ export { createJinjaPlugin, jinjaPlugin } from "./MarkdownEditor/plugins/jinja";
45
+ export * from "./MarkdownEditor/types";
45
46
  // MarkdownEditor 内部工具(保持向后兼容,后续版本考虑收敛)
46
47
  export * from "./MarkdownEditor/editor/components/index";
47
48
  export * from "./MarkdownEditor/editor/elements/Table/Table";
@@ -52,49 +53,49 @@ export * from "./MarkdownEditor/editor/parser/parserSlateNodeToMarkdown";
52
53
  export * from "./MarkdownEditor/editor/store";
53
54
  export * from "./MarkdownEditor/editor/utils";
54
55
  export * from "./MarkdownEditor/editor/utils/docx/index";
55
- export * from "./MarkdownEditor/editor/utils/markdownToHtml";
56
56
  export * from "./MarkdownEditor/editor/utils/htmlToMarkdown";
57
+ export * from "./MarkdownEditor/editor/utils/markdownToHtml";
57
58
  export * from "./MarkdownEditor/utils/native-table/native-table-editor";
58
59
  // ─── Markdown 输入框 ─────────────────────────────────────────────────────────
59
- export * from "./MarkdownInputField/MarkdownInputField";
60
60
  export * from "./MarkdownInputField/AttachmentButton";
61
- export * from "./MarkdownInputField/AttachmentButton/types";
62
61
  export * from "./MarkdownInputField/AttachmentButton/AttachmentFileList";
63
62
  export * from "./MarkdownInputField/AttachmentButton/AttachmentFileList/AttachmentFileListItem";
63
+ export * from "./MarkdownInputField/AttachmentButton/types";
64
64
  export * from "./MarkdownInputField/AttachmentButton/utils";
65
+ export { ActionItemContainer } from "./MarkdownInputField/BeforeToolContainer/BeforeToolContainer";
65
66
  export * from "./MarkdownInputField/FileMapView";
67
+ export * from "./MarkdownInputField/MarkdownInputField";
66
68
  export * from "./MarkdownInputField/VoiceInput";
67
- export { ActionItemContainer } from "./MarkdownInputField/BeforeToolContainer/BeforeToolContainer";
68
69
  // ─── Schema ──────────────────────────────────────────────────────────────────
69
70
  export * from "./Schema";
70
- export * from "./Schema/types";
71
71
  export * from "./Schema/SchemaRenderer/templateEngine";
72
+ export * from "./Schema/types";
72
73
  export * from "./Schema/validator";
73
74
  // ─── 插件 ────────────────────────────────────────────────────────────────────
74
- export * from "./Plugins/formatter";
75
75
  export * from "./Plugins/chart";
76
- export * from "./Plugins/mermaid";
77
76
  export * from "./Plugins/code/components";
77
+ export * from "./Plugins/formatter";
78
+ export * from "./Plugins/mermaid";
78
79
  // ─── 基础 UI 组件 ────────────────────────────────────────────────────────────
79
80
  export * from "./AILabel";
80
81
  export * from "./AnswerAlert";
81
82
  export * from "./BackTo";
82
- export * from "./WelcomeMessage";
83
83
  export { default as Quote } from "./Quote";
84
+ export * from "./WelcomeMessage";
84
85
  // ─── 通用子组件 ──────────────────────────────────────────────────────────────
85
86
  export * from "./Components/ActionIconBox";
86
87
  export { ActionItemBox } from "./Components/ActionItemBox";
87
88
  export * from "./Components/Button";
89
+ export * from "./Components/GradientText";
88
90
  export * from "./Components/LayoutHeader";
89
91
  export * from "./Components/Loading";
90
92
  export * from "./Components/lotties";
91
- export * from "./Components/SuggestionList";
92
- export * from "./Components/VisualList";
93
93
  export * from "./Components/Robot";
94
94
  export { default as Robot } from "./Components/Robot";
95
- export * from "./Components/GradientText";
95
+ export * from "./Components/SuggestionList";
96
96
  export * from "./Components/TextAnimate";
97
97
  export * from "./Components/TypingAnimation";
98
+ export * from "./Components/VisualList";
98
99
  // ─── Hooks ───────────────────────────────────────────────────────────────────
99
100
  export * from "./Hooks/useAutoScroll";
100
101
  export { useLanguage } from "./Hooks/useLanguage";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ant-design/agentic-ui",
3
- "version": "2.29.28",
3
+ "version": "2.29.29",
4
4
  "description": "面向智能体的 UI 组件库,提供多步推理可视化、工具调用展示、任务执行协同等 Agentic UI 能力",
5
5
  "repository": "git@github.com:ant-design/agentic-ui.git",
6
6
  "license": "MIT",
@@ -24,6 +24,7 @@
24
24
  "lint:css": "stylelint \"{src,test}/**/*.{css,less}\"",
25
25
  "lint:es": "eslint \"{src,test}/**/*.{js,jsx,ts,tsx}\"",
26
26
  "prepare": "husky install && dumi setup",
27
+ "prepublishOnly": "father doctor && pnpm run test && pnpm run build",
27
28
  "prettier": "prettier --write \"{src,docs,test}/**/*.{js,jsx,ts,tsx,css,less,json,md}\"",
28
29
  "preview": "pnpm dumi preview",
29
30
  "report:demo": "node scripts/generateDemoReport.js",