@ant-design/agentic-ui 2.30.10 → 2.30.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/dist/Bubble/MessagesContent/style.js +3 -1
  2. package/dist/Bubble/style.js +35 -13
  3. package/dist/ChatLayout/index.js +9 -1
  4. package/dist/ChatLayout/style.js +16 -13
  5. package/dist/Components/ActionIconBox/index.js +4 -0
  6. package/dist/Components/Button/IconButton/style.js +1 -1
  7. package/dist/Components/Button/ToggleButton/style.js +1 -1
  8. package/dist/History/components/HistoryList.d.ts +2 -12
  9. package/dist/History/components/HistoryList.js +48 -43
  10. package/dist/History/style.d.ts +4 -0
  11. package/dist/History/style.js +3 -2
  12. package/dist/Hooks/useAutoScroll.js +38 -14
  13. package/dist/Hooks/useLanguage.d.ts +1 -0
  14. package/dist/I18n/locales.d.ts +1 -0
  15. package/dist/I18n/locales.js +2 -0
  16. package/dist/MarkdownEditor/BaseMarkdownEditor.js +2 -1
  17. package/dist/MarkdownEditor/editor/Editor.js +22 -6
  18. package/dist/MarkdownEditor/editor/elements/AgenticUiBlocks/AgenticUiFileMapBlock.d.ts +4 -0
  19. package/dist/MarkdownEditor/editor/elements/AgenticUiBlocks/AgenticUiFileMapBlock.js +83 -0
  20. package/dist/MarkdownEditor/editor/elements/AgenticUiBlocks/agenticUiEmbedUtils.d.ts +10 -0
  21. package/dist/MarkdownEditor/editor/elements/AgenticUiBlocks/agenticUiEmbedUtils.js +44 -0
  22. package/dist/MarkdownEditor/editor/elements/Paragraph/index.js +27 -5
  23. package/dist/MarkdownEditor/editor/elements/index.js +3 -0
  24. package/dist/MarkdownEditor/editor/parser/parse/parseCode.js +2 -1
  25. package/dist/MarkdownEditor/editor/parser/parserSlateNodeToMarkdown.js +1 -0
  26. package/dist/MarkdownEditor/editor/plugins/handlePaste.js +2 -1
  27. package/dist/MarkdownEditor/editor/style.js +7 -3
  28. package/dist/MarkdownEditor/editor/tools/JinjaTemplatePanel/index.js +2 -2
  29. package/dist/MarkdownEditor/types.d.ts +10 -0
  30. package/dist/MarkdownInputField/AttachmentButton/AttachmentFileList/AttachmentFileIcon.js +1 -1
  31. package/dist/MarkdownInputField/AttachmentButton/AttachmentFileList/style.js +3 -3
  32. package/dist/MarkdownInputField/FileMapView/style.js +3 -2
  33. package/dist/MarkdownInputField/SkillModeBar/style.js +1 -1
  34. package/dist/MarkdownInputField/style.js +1 -1
  35. package/dist/MarkdownRenderer/MarkdownRenderer.js +10 -2
  36. package/dist/MarkdownRenderer/index.d.ts +4 -1
  37. package/dist/MarkdownRenderer/index.js +3 -0
  38. package/dist/MarkdownRenderer/markdownReactShared.d.ts +35 -28
  39. package/dist/MarkdownRenderer/markdownReactShared.js +179 -58
  40. package/dist/MarkdownRenderer/renderers/AgenticUiFileMapBlockRenderer.d.ts +6 -0
  41. package/dist/MarkdownRenderer/renderers/AgenticUiFileMapBlockRenderer.js +79 -0
  42. package/dist/MarkdownRenderer/renderers/index.d.ts +3 -0
  43. package/dist/MarkdownRenderer/renderers/index.js +3 -0
  44. package/dist/MarkdownRenderer/streaming/useStreamingMarkdownReact.js +3 -2
  45. package/dist/MarkdownRenderer/types.d.ts +21 -0
  46. package/dist/MarkdownRenderer/useStreaming.js +40 -13
  47. package/dist/Plugins/chart/components/ChartContainer/ChartErrorBoundary.d.ts +2 -0
  48. package/dist/Plugins/code/components/CodeRenderer.js +22 -6
  49. package/dist/Plugins/code/components/CodeToolbar.d.ts +2 -0
  50. package/dist/Plugins/code/components/CodeToolbar.js +11 -4
  51. package/dist/Plugins/code/hooks/useToolbarConfig.d.ts +3 -1
  52. package/dist/Plugins/code/hooks/useToolbarConfig.js +5 -3
  53. package/dist/Plugins/code/utils/index.d.ts +1 -0
  54. package/dist/Plugins/code/utils/index.js +1 -0
  55. package/dist/Plugins/code/utils/localPreview.d.ts +12 -0
  56. package/dist/Plugins/code/utils/localPreview.js +190 -0
  57. package/dist/ThoughtChainList/style.js +1 -1
  58. package/dist/ToolUseBarThink/style.js +1 -1
  59. package/dist/Workspace/Browser/index.d.ts +6 -0
  60. package/dist/Workspace/Browser/index.js +22 -13
  61. package/dist/Workspace/Browser/style.js +14 -15
  62. package/dist/Workspace/File/FileComponent.js +4 -4
  63. package/dist/Workspace/File/PreviewComponent.js +4 -4
  64. package/dist/Workspace/File/style.js +33 -39
  65. package/dist/Workspace/RealtimeFollow/style.js +78 -85
  66. package/dist/Workspace/style.js +41 -53
  67. package/package.json +1 -2
@@ -18,13 +18,14 @@ import { shouldResetRevisionProgress } from "./revisionPolicy";
18
18
  ]);
19
19
  var prefixCls = (options === null || options === void 0 ? void 0 : options.prefixCls) || 'ant-agentic-md-editor';
20
20
  var components = useMemo(function() {
21
- return buildEditorAlignedComponents(prefixCls, (options === null || options === void 0 ? void 0 : options.components) || {}, options === null || options === void 0 ? void 0 : options.streaming, options === null || options === void 0 ? void 0 : options.linkConfig, options === null || options === void 0 ? void 0 : options.streamingParagraphAnimation);
21
+ return buildEditorAlignedComponents(prefixCls, (options === null || options === void 0 ? void 0 : options.components) || {}, options === null || options === void 0 ? void 0 : options.streaming, options === null || options === void 0 ? void 0 : options.linkConfig, options === null || options === void 0 ? void 0 : options.streamingParagraphAnimation, options === null || options === void 0 ? void 0 : options.eleRender);
22
22
  }, [
23
23
  prefixCls,
24
24
  options === null || options === void 0 ? void 0 : options.components,
25
25
  options === null || options === void 0 ? void 0 : options.streaming,
26
26
  options === null || options === void 0 ? void 0 : options.linkConfig,
27
- options === null || options === void 0 ? void 0 : options.streamingParagraphAnimation
27
+ options === null || options === void 0 ? void 0 : options.streamingParagraphAnimation,
28
+ options === null || options === void 0 ? void 0 : options.eleRender
28
29
  ]);
29
30
  return useMemo(function() {
30
31
  if (!content) {
@@ -1,6 +1,19 @@
1
1
  import type React from 'react';
2
2
  import type { MarkdownRemarkPlugin, MarkdownToHtmlConfig } from '../MarkdownEditor/editor/utils/markdownToHtml';
3
3
  import type { MarkdownEditorPlugin } from '../MarkdownEditor/plugin';
4
+ /**
5
+ * markdown 渲染模式下传给 eleRender 的元素属性,
6
+ * 包含 HTML 标签名、hast 节点及所有原生 HTML 属性。
7
+ */
8
+ export interface MarkdownRendererEleProps {
9
+ /** HTML tag name, e.g. 'p', 'h1', 'blockquote', 'pre' */
10
+ tagName: string;
11
+ /** The original hast node */
12
+ node?: any;
13
+ /** Rendered children */
14
+ children?: React.ReactNode;
15
+ [key: string]: any;
16
+ }
4
17
  export interface CharacterQueueOptions {
5
18
  /** 每帧输出的最大字符数,默认 3 */
6
19
  charsPerFrame?: number;
@@ -79,6 +92,14 @@ export interface MarkdownRendererProps {
79
92
  /** 自定义渲染函数,接收解析后的 JSON value,返回 React 节点 */
80
93
  render?: (value: any) => React.ReactNode;
81
94
  };
95
+ /**
96
+ * 自定义元素渲染函数(markdown 渲染模式)
97
+ * 与 Slate 模式的 eleItemRender 对应,允许拦截并替换任意块级/行内元素的渲染结果。
98
+ * @param props - 元素属性(tagName、node、children 等)
99
+ * @param defaultDom - 默认渲染结果
100
+ * @returns 自定义渲染节点,或 undefined 时回退到 defaultDom
101
+ */
102
+ eleRender?: (props: MarkdownRendererEleProps, defaultDom: React.ReactNode) => React.ReactNode;
82
103
  }
83
104
  export interface MarkdownRendererRef {
84
105
  /** 获取渲染容器的 DOM 元素 */
@@ -102,26 +102,53 @@ var STREAM_INCOMPLETE_REGEX = {
102
102
  ]
103
103
  };
104
104
  var STREAMING_LOADING_PLACEHOLDER = '...';
105
+ var parsePipeRowCells = function parsePipeRowCells(line) {
106
+ var trimmedLine = line.trim();
107
+ if (!trimmedLine.startsWith('|') || !trimmedLine.endsWith('|')) {
108
+ return null;
109
+ }
110
+ var cells = trimmedLine.split('|').slice(1, -1).map(function(cell) {
111
+ return cell.trim();
112
+ });
113
+ if (!cells.length) return null;
114
+ return cells;
115
+ };
116
+ var isTableSeparatorCell = function isTableSeparatorCell(cell) {
117
+ return /^:?-{3,}:?$/.test(cell);
118
+ };
105
119
  /**
106
120
  * 判断表格是否仍不完整。
107
- * 等待 header + separator + 至少一行数据(3 行)后提交。
121
+ * 等待 header + separator + 第一行数据完整闭合后提交。
108
122
  */ var isTableIncomplete = function isTableIncomplete(markdown) {
123
+ var _firstDataRowTrimmed_match;
109
124
  if (markdown.includes('\n\n')) return false;
110
- var lines = markdown.split('\n');
125
+ var lines = markdown.replace(/\r\n/g, '\n').split('\n');
111
126
  // 需要至少 3 行:header | separator | 第一行数据
112
127
  if (lines.length < 3) return true;
113
- var _lines = _sliced_to_array(lines, 2), header = _lines[0], separator = _lines[1];
114
- if (!/^\|.*\|$/.test(header.trim())) return false;
115
- var columns = separator.trim().split('|').map(function(c) {
116
- return c.trim();
117
- }).filter(Boolean);
118
- var isSeparatorValid = columns.every(function(col, i) {
119
- return i === columns.length - 1 ? col === ':' || /^:?-+:?$/.test(col) : /^:?-+:?$/.test(col);
120
- });
128
+ var _lines = _sliced_to_array(lines, 3), header = _lines[0], separator = _lines[1], firstDataRow = _lines[2];
129
+ var headerCells = parsePipeRowCells(header);
130
+ if (!headerCells) return false;
131
+ var separatorCells = parsePipeRowCells(separator);
132
+ if (!separatorCells || separatorCells.length !== headerCells.length) {
133
+ return false;
134
+ }
135
+ var isSeparatorValid = separatorCells.every(isTableSeparatorCell);
121
136
  if (!isSeparatorValid) return false;
122
- // separator 完整但还没有数据行
123
- if (lines.length <= 2) return true;
124
- // 有数据行了,不再缓存
137
+ var firstDataRowTrimmed = (firstDataRow === null || firstDataRow === void 0 ? void 0 : firstDataRow.trim()) || '';
138
+ // 第三行仍为空,说明首行数据尚未到达,继续缓存避免提前渲染 table header
139
+ if (!firstDataRowTrimmed) return true;
140
+ // 第三行不是表格行,视为当前表格 token 已完成(例如 header-only 表格后接普通文本)
141
+ if (!firstDataRowTrimmed.startsWith('|')) return false;
142
+ var minPipeDelimiterCount = headerCells.length + 1;
143
+ var currentPipeDelimiterCount = ((_firstDataRowTrimmed_match = firstDataRowTrimmed.match(/\|/g)) === null || _firstDataRowTrimmed_match === void 0 ? void 0 : _firstDataRowTrimmed_match.length) || 0;
144
+ // 管道分隔符数量不足,说明第一行数据还未输入完整
145
+ if (currentPipeDelimiterCount < minPipeDelimiterCount) return true;
146
+ // 第一行数据必须是闭合的管道行(以 | 结尾),否则继续缓存
147
+ if (!firstDataRowTrimmed.endsWith('|')) return true;
148
+ var firstDataRowCells = parsePipeRowCells(firstDataRow);
149
+ if (!firstDataRowCells || firstDataRowCells.length !== headerCells.length) {
150
+ return true;
151
+ }
125
152
  return false;
126
153
  };
127
154
  var _obj;
@@ -393,6 +393,7 @@ declare class ChartErrorBoundary extends React.Component<ChartErrorBoundaryProps
393
393
  'browser.searching': string;
394
394
  'layout.header.title': string;
395
395
  theme: string;
396
+ localPreview: string;
396
397
  expandCollapse: string;
397
398
  moreActions: string;
398
399
  clickToRetry: string;
@@ -786,6 +787,7 @@ declare class ChartErrorBoundary extends React.Component<ChartErrorBoundaryProps
786
787
  'browser.searching': string;
787
788
  'layout.header.title': string;
788
789
  theme: string;
790
+ localPreview: string;
789
791
  expandCollapse: string;
790
792
  moreActions: string;
791
793
  clickToRetry: string;
@@ -100,10 +100,11 @@ function _unsupported_iterable_to_array(o, minLen) {
100
100
  * @fileoverview 代码渲染器组件
101
101
  * 封装代码编辑器的所有渲染逻辑
102
102
  */ import { ConfigProvider, Skeleton, theme as antdTheme } from "antd";
103
- import React, { useEffect, useMemo, useState } from "react";
103
+ import React, { useCallback, useEffect, useMemo, useState } from "react";
104
104
  import { MarkdownEditor } from "../../../MarkdownEditor";
105
105
  import { useEditorStore } from "../../../MarkdownEditor/editor/store";
106
106
  import { useCodeEditorState, useRenderConditions, useToolbarConfig } from "../hooks";
107
+ import { openHtmlLocalPreview, openMarkdownLocalPreview } from "../utils/localPreview";
107
108
  import { AceEditor, AceEditorContainer, CodeContainer, CodeToolbar, HtmlPreview, ThinkBlock } from "./index";
108
109
  /**
109
110
  * 检测 HTML 代码中是否包含 JavaScript
@@ -154,7 +155,7 @@ import { AceEditor, AceEditorContainer, CodeContainer, CodeToolbar, HtmlPreview,
154
155
  * - 支持代码框选中状态管理
155
156
  */ export function CodeRenderer(props) {
156
157
  var _ref;
157
- var _editorProps_codeProps, _props_element_language, _props_element, _props_element1, _props_element_otherProps, _props_element2, _props_element_otherProps1, _props_element3, _editorProps_codeProps1, _editorProps_codeProps2;
158
+ var _editorProps_codeProps, _props_element_language, _props_element, _props_element1, _props_element2, _props_element_otherProps, _props_element3, _props_element_otherProps1, _props_element4, _editorProps_codeProps1, _editorProps_codeProps2;
158
159
  var _useEditorStore = useEditorStore(), editorProps = _useEditorStore.editorProps, readonly = _useEditorStore.readonly;
159
160
  // 使用状态管理Hook
160
161
  var _useCodeEditorState = useCodeEditorState(props.element), state = _useCodeEditorState.state, update = _useCodeEditorState.update, path = _useCodeEditorState.path, handleCloseClick = _useCodeEditorState.handleCloseClick, handleHtmlPreviewClose = _useCodeEditorState.handleHtmlPreviewClose, handleShowBorderChange = _useCodeEditorState.handleShowBorderChange, handleHideChange = _useCodeEditorState.handleHideChange;
@@ -203,6 +204,19 @@ import { AceEditor, AceEditorContainer, CodeContainer, CodeToolbar, HtmlPreview,
203
204
  return prev === 'preview' ? 'code' : 'preview';
204
205
  });
205
206
  };
207
+ // 本地预览处理函数
208
+ var handleLocalPreview = useCallback(function() {
209
+ var _props_element;
210
+ var value = ((_props_element = props.element) === null || _props_element === void 0 ? void 0 : _props_element.value) || '';
211
+ if (language === 'markdown') {
212
+ openMarkdownLocalPreview(value);
213
+ } else if (language === 'html') {
214
+ openHtmlLocalPreview(value);
215
+ }
216
+ }, [
217
+ language,
218
+ (_props_element2 = props.element) === null || _props_element2 === void 0 ? void 0 : _props_element2.value
219
+ ]);
206
220
  // 使用工具栏配置Hook
207
221
  var toolbarProps = useToolbarConfig({
208
222
  element: props.element,
@@ -211,10 +225,11 @@ import { AceEditor, AceEditorContainer, CodeContainer, CodeToolbar, HtmlPreview,
211
225
  setLanguage: setLanguage,
212
226
  onSelectionChange: setIsSelected,
213
227
  onViewModeToggle: handleViewModeToggle,
214
- viewMode: viewMode
228
+ viewMode: viewMode,
229
+ onLocalPreview: handleLocalPreview
215
230
  }).toolbarProps;
216
231
  // 检查代码块是否未闭合
217
- var isUnclosed = ((_props_element2 = props.element) === null || _props_element2 === void 0 ? void 0 : (_props_element_otherProps = _props_element2.otherProps) === null || _props_element_otherProps === void 0 ? void 0 : _props_element_otherProps.finished) === false;
232
+ var isUnclosed = ((_props_element3 = props.element) === null || _props_element3 === void 0 ? void 0 : (_props_element_otherProps = _props_element3.otherProps) === null || _props_element_otherProps === void 0 ? void 0 : _props_element_otherProps.finished) === false;
218
233
  // 5 秒超时机制:如果代码块未闭合,5 秒后自动设置为完成
219
234
  useEffect(function() {
220
235
  if (isUnclosed && !readonly) {
@@ -237,7 +252,7 @@ import { AceEditor, AceEditorContainer, CodeContainer, CodeToolbar, HtmlPreview,
237
252
  }, [
238
253
  isUnclosed,
239
254
  readonly,
240
- (_props_element3 = props.element) === null || _props_element3 === void 0 ? void 0 : (_props_element_otherProps1 = _props_element3.otherProps) === null || _props_element_otherProps1 === void 0 ? void 0 : _props_element_otherProps1.finished,
255
+ (_props_element4 = props.element) === null || _props_element4 === void 0 ? void 0 : (_props_element_otherProps1 = _props_element4.otherProps) === null || _props_element_otherProps1 === void 0 ? void 0 : _props_element_otherProps1.finished,
241
256
  update
242
257
  ]);
243
258
  // 如果禁用了 HTML 预览或包含 JavaScript,强制使用代码模式
@@ -342,6 +357,7 @@ import { AceEditor, AceEditorContainer, CodeContainer, CodeToolbar, HtmlPreview,
342
357
  handleHtmlPreviewClose,
343
358
  viewMode,
344
359
  handleViewModeToggle,
345
- disableHtmlPreview
360
+ disableHtmlPreview,
361
+ handleLocalPreview
346
362
  ]);
347
363
  }
@@ -31,6 +31,8 @@ export interface CodeToolbarProps {
31
31
  viewMode?: 'preview' | 'code';
32
32
  /** 展开/收起回调 */
33
33
  onExpandToggle?: () => void;
34
+ /** 本地预览回调(在新标签页打开 HTML/Markdown 预览) */
35
+ onLocalPreview?: () => void;
34
36
  }
35
37
  /**
36
38
  * 代码编辑器工具栏组件
@@ -3,7 +3,7 @@
3
3
  * 提供代码块的各种操作功能,包括语言切换、复制、运行等
4
4
  * @author Code Plugin Team
5
5
  */ import { CloseCircleOutlined } from "@ant-design/icons";
6
- import { ChevronsUpDown, Copy, Moon } from "@sofa-design/icons";
6
+ import { ArrowUpRight, ChevronsUpDown, Copy, Moon } from "@sofa-design/icons";
7
7
  import { Segmented } from "antd";
8
8
  import copy from "copy-to-clipboard";
9
9
  import React, { useContext, useMemo } from "react";
@@ -77,14 +77,14 @@ import { LoadImage } from "./LoadImage";
77
77
  * ```
78
78
  */ export var CodeToolbar = function CodeToolbar(props) {
79
79
  var _ref;
80
- var _editorProps_codeProps, _editorProps_codeProps1, _element_language, _element_language1, _i18n_locale, _i18n_locale1, _i18n_locale2, _i18n_locale3;
80
+ var _editorProps_codeProps, _editorProps_codeProps1, _element_language, _element_language1, _i18n_locale, _i18n_locale1, _i18n_locale2, _i18n_locale3, _i18n_locale4;
81
81
  // 获取国际化上下文
82
82
  var i18n = useContext(I18nContext);
83
83
  // 获取编辑器配置
84
84
  var editorProps = useEditorStore().editorProps;
85
85
  var disableHtmlPreview = (_ref = (_editorProps_codeProps = editorProps.codeProps) === null || _editorProps_codeProps === void 0 ? void 0 : _editorProps_codeProps.disableHtmlPreview) !== null && _ref !== void 0 ? _ref : false;
86
86
  var viewModeLabels = (_editorProps_codeProps1 = editorProps.codeProps) === null || _editorProps_codeProps1 === void 0 ? void 0 : _editorProps_codeProps1.viewModeLabels;
87
- var element = props.element, readonly = props.readonly, onCloseClick = props.onCloseClick, languageSelectorProps = props.languageSelectorProps, onViewModeToggle = props.onViewModeToggle, theme = props.theme, isExpanded = props.isExpanded, onExpandToggle = props.onExpandToggle, setTheme = props.setTheme, _props_viewMode = props.viewMode, viewMode = _props_viewMode === void 0 ? 'code' : _props_viewMode;
87
+ var element = props.element, readonly = props.readonly, onCloseClick = props.onCloseClick, languageSelectorProps = props.languageSelectorProps, onViewModeToggle = props.onViewModeToggle, theme = props.theme, isExpanded = props.isExpanded, onExpandToggle = props.onExpandToggle, setTheme = props.setTheme, _props_viewMode = props.viewMode, viewMode = _props_viewMode === void 0 ? 'code' : _props_viewMode, onLocalPreview = props.onLocalPreview;
88
88
  // 检测 HTML 代码中是否包含 JavaScript
89
89
  var hasJavaScript = useMemo(function() {
90
90
  var _element_language;
@@ -216,5 +216,12 @@ import { LoadImage } from "./LoadImage";
216
216
  onClick: function onClick() {
217
217
  onExpandToggle === null || onExpandToggle === void 0 ? void 0 : onExpandToggle();
218
218
  }
219
- }, /*#__PURE__*/ React.createElement(ChevronsUpDown, null))));
219
+ }, /*#__PURE__*/ React.createElement(ChevronsUpDown, null)), ((element === null || element === void 0 ? void 0 : element.language) === 'html' || (element === null || element === void 0 ? void 0 : element.language) === 'markdown') && onLocalPreview && /*#__PURE__*/ React.createElement(ActionIconBox, {
220
+ title: (i18n === null || i18n === void 0 ? void 0 : (_i18n_locale4 = i18n.locale) === null || _i18n_locale4 === void 0 ? void 0 : _i18n_locale4.localPreview) || '本地预览',
221
+ theme: theme === 'chaos' ? 'dark' : 'light',
222
+ onClick: function onClick(e) {
223
+ e.stopPropagation();
224
+ onLocalPreview();
225
+ }
226
+ }, /*#__PURE__*/ React.createElement(ArrowUpRight, null))));
220
227
  };
@@ -13,8 +13,9 @@ interface UseToolbarConfigProps {
13
13
  onSelectionChange?: (selected: boolean) => void;
14
14
  onViewModeToggle?: () => void;
15
15
  viewMode?: 'preview' | 'code';
16
+ onLocalPreview?: () => void;
16
17
  }
17
- export declare function useToolbarConfig({ element, readonly, onCloseClick, setLanguage, isSelected, onSelectionChange, onViewModeToggle, viewMode, }: UseToolbarConfigProps): {
18
+ export declare function useToolbarConfig({ element, readonly, onCloseClick, setLanguage, isSelected, onSelectionChange, onViewModeToggle, viewMode, onLocalPreview, }: UseToolbarConfigProps): {
18
19
  toolbarProps: {
19
20
  element: CodeNode;
20
21
  readonly: boolean;
@@ -24,6 +25,7 @@ export declare function useToolbarConfig({ element, readonly, onCloseClick, setL
24
25
  onSelectionChange: ((selected: boolean) => void) | undefined;
25
26
  onViewModeToggle: (() => void) | undefined;
26
27
  viewMode: "code" | "preview" | undefined;
28
+ onLocalPreview: (() => void) | undefined;
27
29
  };
28
30
  };
29
31
  export {};
@@ -3,7 +3,7 @@
3
3
  * 负责组装工具栏的属性和事件处理
4
4
  */ import { useCallback } from "react";
5
5
  export function useToolbarConfig(param) {
6
- var element = param.element, readonly = param.readonly, onCloseClick = param.onCloseClick, setLanguage = param.setLanguage, isSelected = param.isSelected, onSelectionChange = param.onSelectionChange, onViewModeToggle = param.onViewModeToggle, viewMode = param.viewMode;
6
+ var element = param.element, readonly = param.readonly, onCloseClick = param.onCloseClick, setLanguage = param.setLanguage, isSelected = param.isSelected, onSelectionChange = param.onSelectionChange, onViewModeToggle = param.onViewModeToggle, viewMode = param.viewMode, onLocalPreview = param.onLocalPreview;
7
7
  // 组装语言选择器属性
8
8
  var languageSelectorProps = useCallback(function() {
9
9
  return {
@@ -27,7 +27,8 @@ export function useToolbarConfig(param) {
27
27
  isSelected: isSelected,
28
28
  onSelectionChange: onSelectionChange,
29
29
  onViewModeToggle: onViewModeToggle,
30
- viewMode: viewMode
30
+ viewMode: viewMode,
31
+ onLocalPreview: onLocalPreview
31
32
  };
32
33
  }, [
33
34
  element,
@@ -37,7 +38,8 @@ export function useToolbarConfig(param) {
37
38
  isSelected,
38
39
  onSelectionChange,
39
40
  onViewModeToggle,
40
- viewMode
41
+ viewMode,
42
+ onLocalPreview
41
43
  ])();
42
44
  return {
43
45
  toolbarProps: toolbarProps
@@ -4,3 +4,4 @@
4
4
  * @author Code Plugin Team
5
5
  */
6
6
  export { langOptions } from './langOptions';
7
+ export { openHtmlLocalPreview, openMarkdownLocalPreview, } from './localPreview';
@@ -3,3 +3,4 @@
3
3
  * 提供工具函数和配置的集中导出
4
4
  * @author Code Plugin Team
5
5
  */ export { langOptions } from "./langOptions";
6
+ export { openHtmlLocalPreview, openMarkdownLocalPreview } from "./localPreview";
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @fileoverview 本地预览工具函数
3
+ * 支持在新窗口打开 HTML 或 Markdown(转为 HTML 后)内容
4
+ */
5
+ /**
6
+ * 在新标签页打开 HTML 内容的本地预览(允许执行 JavaScript)
7
+ */
8
+ export declare function openHtmlLocalPreview(htmlCode: string): void;
9
+ /**
10
+ * 将 Markdown 转换为 HTML 后在新标签页打开本地预览
11
+ */
12
+ export declare function openMarkdownLocalPreview(markdownCode: string): Promise<void>;
@@ -0,0 +1,190 @@
1
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
2
+ try {
3
+ var info = gen[key](arg);
4
+ var value = info.value;
5
+ } catch (error) {
6
+ reject(error);
7
+ return;
8
+ }
9
+ if (info.done) {
10
+ resolve(value);
11
+ } else {
12
+ Promise.resolve(value).then(_next, _throw);
13
+ }
14
+ }
15
+ function _async_to_generator(fn) {
16
+ return function() {
17
+ var self = this, args = arguments;
18
+ return new Promise(function(resolve, reject) {
19
+ var gen = fn.apply(self, args);
20
+ function _next(value) {
21
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
22
+ }
23
+ function _throw(err) {
24
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
25
+ }
26
+ _next(undefined);
27
+ });
28
+ };
29
+ }
30
+ function _ts_generator(thisArg, body) {
31
+ var f, y, t, _ = {
32
+ label: 0,
33
+ sent: function() {
34
+ if (t[0] & 1) throw t[1];
35
+ return t[1];
36
+ },
37
+ trys: [],
38
+ ops: []
39
+ }, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype), d = Object.defineProperty;
40
+ return d(g, "next", {
41
+ value: verb(0)
42
+ }), d(g, "throw", {
43
+ value: verb(1)
44
+ }), d(g, "return", {
45
+ value: verb(2)
46
+ }), typeof Symbol === "function" && d(g, Symbol.iterator, {
47
+ value: function() {
48
+ return this;
49
+ }
50
+ }), g;
51
+ function verb(n) {
52
+ return function(v) {
53
+ return step([
54
+ n,
55
+ v
56
+ ]);
57
+ };
58
+ }
59
+ function step(op) {
60
+ if (f) throw new TypeError("Generator is already executing.");
61
+ while(g && (g = 0, op[0] && (_ = 0)), _)try {
62
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
63
+ if (y = 0, t) op = [
64
+ op[0] & 2,
65
+ t.value
66
+ ];
67
+ switch(op[0]){
68
+ case 0:
69
+ case 1:
70
+ t = op;
71
+ break;
72
+ case 4:
73
+ _.label++;
74
+ return {
75
+ value: op[1],
76
+ done: false
77
+ };
78
+ case 5:
79
+ _.label++;
80
+ y = op[1];
81
+ op = [
82
+ 0
83
+ ];
84
+ continue;
85
+ case 7:
86
+ op = _.ops.pop();
87
+ _.trys.pop();
88
+ continue;
89
+ default:
90
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
91
+ _ = 0;
92
+ continue;
93
+ }
94
+ if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
95
+ _.label = op[1];
96
+ break;
97
+ }
98
+ if (op[0] === 6 && _.label < t[1]) {
99
+ _.label = t[1];
100
+ t = op;
101
+ break;
102
+ }
103
+ if (t && _.label < t[2]) {
104
+ _.label = t[2];
105
+ _.ops.push(op);
106
+ break;
107
+ }
108
+ if (t[2]) _.ops.pop();
109
+ _.trys.pop();
110
+ continue;
111
+ }
112
+ op = body.call(thisArg, _);
113
+ } catch (e) {
114
+ op = [
115
+ 6,
116
+ e
117
+ ];
118
+ y = 0;
119
+ } finally{
120
+ f = t = 0;
121
+ }
122
+ if (op[0] & 5) throw op[1];
123
+ return {
124
+ value: op[0] ? op[1] : void 0,
125
+ done: true
126
+ };
127
+ }
128
+ }
129
+ /**
130
+ * @fileoverview 本地预览工具函数
131
+ * 支持在新窗口打开 HTML 或 Markdown(转为 HTML 后)内容
132
+ */ import { markdownToHtml } from "../../../MarkdownEditor/editor/utils/markdownToHtml";
133
+ var MARKDOWN_PREVIEW_STYLE = "\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n line-height: 1.6;\n color: #24292e;\n max-width: 900px;\n margin: 0 auto;\n padding: 32px 24px;\n background: #fff;\n }\n h1, h2, h3, h4, h5, h6 {\n border-bottom: 1px solid #eaecef;\n padding-bottom: 0.3em;\n margin-top: 24px;\n margin-bottom: 16px;\n font-weight: 600;\n line-height: 1.25;\n }\n pre {\n background: #f6f8fa;\n border-radius: 6px;\n padding: 16px;\n overflow: auto;\n font-size: 85%;\n line-height: 1.45;\n }\n code {\n background: rgba(175, 184, 193, 0.2);\n border-radius: 3px;\n font-size: 85%;\n padding: 0.2em 0.4em;\n }\n pre code {\n background: transparent;\n padding: 0;\n font-size: inherit;\n }\n blockquote {\n border-left: 4px solid #d0d7de;\n color: #57606a;\n margin: 0;\n padding: 0 1em;\n }\n table {\n border-collapse: collapse;\n width: 100%;\n }\n th, td {\n border: 1px solid #d0d7de;\n padding: 6px 13px;\n }\n tr:nth-child(even) {\n background: #f6f8fa;\n }\n img {\n max-width: 100%;\n }\n a {\n color: #0969da;\n text-decoration: none;\n }\n a:hover {\n text-decoration: underline;\n }\n hr {\n border: none;\n border-top: 1px solid #d0d7de;\n }\n";
134
+ function buildHtmlDocument(body, title) {
135
+ return '<!DOCTYPE html>\n<html lang="en">\n<head>\n <meta charset="UTF-8" />\n <meta name="viewport" content="width=device-width, initial-scale=1.0" />\n <title>'.concat(title, '</title>\n <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css" crossorigin="anonymous" />\n</head>\n<body>\n').concat(body, "\n</body>\n</html>");
136
+ }
137
+ function openBlobInNewTab(html) {
138
+ var blob = new Blob([
139
+ html
140
+ ], {
141
+ type: 'text/html'
142
+ });
143
+ var url = URL.createObjectURL(blob);
144
+ var win = window.open(url, '_blank');
145
+ if (win) {
146
+ // 在新窗口加载完毕后释放 Blob URL
147
+ win.addEventListener('load', function() {
148
+ return URL.revokeObjectURL(url);
149
+ }, {
150
+ once: true
151
+ });
152
+ } else {
153
+ // 弹窗被拦截时延迟释放
154
+ setTimeout(function() {
155
+ return URL.revokeObjectURL(url);
156
+ }, 10000);
157
+ }
158
+ }
159
+ /**
160
+ * 在新标签页打开 HTML 内容的本地预览(允许执行 JavaScript)
161
+ */ export function openHtmlLocalPreview(htmlCode) {
162
+ var needsDocumentWrapper = !/<html[\s>]/i.test(htmlCode) && !/<!DOCTYPE/i.test(htmlCode);
163
+ var fullHtml = needsDocumentWrapper ? buildHtmlDocument(htmlCode, 'HTML Preview') : htmlCode;
164
+ openBlobInNewTab(fullHtml);
165
+ }
166
+ /**
167
+ * 将 Markdown 转换为 HTML 后在新标签页打开本地预览
168
+ */ export function openMarkdownLocalPreview(markdownCode) {
169
+ return _async_to_generator(function() {
170
+ var bodyHtml, fullHtml;
171
+ return _ts_generator(this, function(_state) {
172
+ switch(_state.label){
173
+ case 0:
174
+ return [
175
+ 4,
176
+ markdownToHtml(markdownCode, undefined, {
177
+ openLinksInNewTab: true
178
+ })
179
+ ];
180
+ case 1:
181
+ bodyHtml = _state.sent();
182
+ fullHtml = '<!DOCTYPE html>\n<html lang="en">\n<head>\n <meta charset="UTF-8" />\n <meta name="viewport" content="width=device-width, initial-scale=1.0" />\n <title>Markdown Preview</title>\n <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css" crossorigin="anonymous" />\n <style>'.concat(MARKDOWN_PREVIEW_STYLE, "</style>\n</head>\n<body>\n").concat(bodyHtml, "\n</body>\n</html>");
183
+ openBlobInNewTab(fullHtml);
184
+ return [
185
+ 2
186
+ ];
187
+ }
188
+ });
189
+ })();
190
+ }
@@ -87,7 +87,7 @@ var genStyle = function genStyle(token) {
87
87
  zIndex: 1,
88
88
  backgroundSize: '150%',
89
89
  backgroundPosition: '0 0',
90
- backgroundImage: "conic-gradient(\n from var(--angle) at 50% 50%,\n rgba(46, 255, 127, 0.7) 0deg,\n rgba(120, 133, 255, 1) 90deg,\n rgba(255, 0, 153, 0.4) 180deg,\n rgba(0, 221, 255, 0.62) 270deg,\n rgba(46, 255, 127, 0.7) 360deg\n )",
90
+ backgroundImage: "conic-gradient(\n from var(--angle, 0deg) at 50% 50%,\n rgba(46, 255, 127, 0.7) 0deg,\n rgba(120, 133, 255, 1) 90deg,\n rgba(255, 0, 153, 0.4) 180deg,\n rgba(0, 221, 255, 0.62) 270deg,\n rgba(46, 255, 127, 0.7) 360deg\n )",
91
91
  animationName: 'spin',
92
92
  animationDuration: '2s',
93
93
  animationTimingFunction: 'linear',
@@ -186,7 +186,7 @@ var genStyle = function genStyle(token) {
186
186
  '&-light': {
187
187
  color: 'var(--color-gray-text-secondary)',
188
188
  '&:hover': {
189
- color: 'var(--color-gray-text)'
189
+ color: 'var(--color-gray-text, var(--color-gray-text-default))'
190
190
  }
191
191
  }
192
192
  },
@@ -20,6 +20,7 @@ export interface BrowserItemProps {
20
20
  itemStyle?: React.CSSProperties;
21
21
  className?: string;
22
22
  onLocate?: (item: BrowserItem) => void;
23
+ onOpen?: (item: BrowserItem) => void;
23
24
  }
24
25
  export declare const BrowserItemComponent: React.FC<BrowserItemProps>;
25
26
  export interface BrowserHeaderProps {
@@ -38,6 +39,7 @@ export interface BrowserListProps {
38
39
  loading?: boolean;
39
40
  loadingText?: string;
40
41
  onLocate?: (item: BrowserItem) => void;
42
+ onOpen?: (item: BrowserItem) => void;
41
43
  }
42
44
  export declare const BrowserList: React.FC<BrowserListProps>;
43
45
  export type BrowserProps = {
@@ -57,6 +59,10 @@ export type BrowserProps = {
57
59
  emptyText?: string;
58
60
  loadingText?: string;
59
61
  onLocate?: (item: BrowserItem) => void;
62
+ /**
63
+ * 点击链接时的回调,提供后将拦截默认的新标签页打开行为
64
+ */
65
+ onOpen?: (item: BrowserItem) => void;
60
66
  };
61
67
  declare const Browser: React.FC<BrowserProps>;
62
68
  export default Browser;