@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.
- package/dist/Bubble/MessagesContent/style.js +3 -1
- package/dist/Bubble/style.js +35 -13
- package/dist/ChatLayout/index.js +9 -1
- package/dist/ChatLayout/style.js +16 -13
- package/dist/Components/ActionIconBox/index.js +4 -0
- package/dist/Components/Button/IconButton/style.js +1 -1
- package/dist/Components/Button/ToggleButton/style.js +1 -1
- package/dist/History/components/HistoryList.d.ts +2 -12
- package/dist/History/components/HistoryList.js +48 -43
- package/dist/History/style.d.ts +4 -0
- package/dist/History/style.js +3 -2
- package/dist/Hooks/useAutoScroll.js +38 -14
- package/dist/Hooks/useLanguage.d.ts +1 -0
- package/dist/I18n/locales.d.ts +1 -0
- package/dist/I18n/locales.js +2 -0
- package/dist/MarkdownEditor/BaseMarkdownEditor.js +2 -1
- package/dist/MarkdownEditor/editor/Editor.js +22 -6
- package/dist/MarkdownEditor/editor/elements/AgenticUiBlocks/AgenticUiFileMapBlock.d.ts +4 -0
- package/dist/MarkdownEditor/editor/elements/AgenticUiBlocks/AgenticUiFileMapBlock.js +83 -0
- package/dist/MarkdownEditor/editor/elements/AgenticUiBlocks/agenticUiEmbedUtils.d.ts +10 -0
- package/dist/MarkdownEditor/editor/elements/AgenticUiBlocks/agenticUiEmbedUtils.js +44 -0
- package/dist/MarkdownEditor/editor/elements/Paragraph/index.js +27 -5
- package/dist/MarkdownEditor/editor/elements/index.js +3 -0
- package/dist/MarkdownEditor/editor/parser/parse/parseCode.js +2 -1
- package/dist/MarkdownEditor/editor/parser/parserSlateNodeToMarkdown.js +1 -0
- package/dist/MarkdownEditor/editor/plugins/handlePaste.js +2 -1
- package/dist/MarkdownEditor/editor/style.js +7 -3
- package/dist/MarkdownEditor/editor/tools/JinjaTemplatePanel/index.js +2 -2
- package/dist/MarkdownEditor/types.d.ts +10 -0
- package/dist/MarkdownInputField/AttachmentButton/AttachmentFileList/AttachmentFileIcon.js +1 -1
- package/dist/MarkdownInputField/AttachmentButton/AttachmentFileList/style.js +3 -3
- package/dist/MarkdownInputField/FileMapView/style.js +3 -2
- package/dist/MarkdownInputField/SkillModeBar/style.js +1 -1
- package/dist/MarkdownInputField/style.js +1 -1
- package/dist/MarkdownRenderer/MarkdownRenderer.js +10 -2
- package/dist/MarkdownRenderer/index.d.ts +4 -1
- package/dist/MarkdownRenderer/index.js +3 -0
- package/dist/MarkdownRenderer/markdownReactShared.d.ts +35 -28
- package/dist/MarkdownRenderer/markdownReactShared.js +179 -58
- package/dist/MarkdownRenderer/renderers/AgenticUiFileMapBlockRenderer.d.ts +6 -0
- package/dist/MarkdownRenderer/renderers/AgenticUiFileMapBlockRenderer.js +79 -0
- package/dist/MarkdownRenderer/renderers/index.d.ts +3 -0
- package/dist/MarkdownRenderer/renderers/index.js +3 -0
- package/dist/MarkdownRenderer/streaming/useStreamingMarkdownReact.js +3 -2
- package/dist/MarkdownRenderer/types.d.ts +21 -0
- package/dist/MarkdownRenderer/useStreaming.js +40 -13
- package/dist/Plugins/chart/components/ChartContainer/ChartErrorBoundary.d.ts +2 -0
- package/dist/Plugins/code/components/CodeRenderer.js +22 -6
- package/dist/Plugins/code/components/CodeToolbar.d.ts +2 -0
- package/dist/Plugins/code/components/CodeToolbar.js +11 -4
- package/dist/Plugins/code/hooks/useToolbarConfig.d.ts +3 -1
- package/dist/Plugins/code/hooks/useToolbarConfig.js +5 -3
- package/dist/Plugins/code/utils/index.d.ts +1 -0
- package/dist/Plugins/code/utils/index.js +1 -0
- package/dist/Plugins/code/utils/localPreview.d.ts +12 -0
- package/dist/Plugins/code/utils/localPreview.js +190 -0
- package/dist/ThoughtChainList/style.js +1 -1
- package/dist/ToolUseBarThink/style.js +1 -1
- package/dist/Workspace/Browser/index.d.ts +6 -0
- package/dist/Workspace/Browser/index.js +22 -13
- package/dist/Workspace/Browser/style.js +14 -15
- package/dist/Workspace/File/FileComponent.js +4 -4
- package/dist/Workspace/File/PreviewComponent.js +4 -4
- package/dist/Workspace/File/style.js +33 -39
- package/dist/Workspace/RealtimeFollow/style.js +78 -85
- package/dist/Workspace/style.js +41 -53
- 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 +
|
|
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,
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
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
|
-
|
|
123
|
-
|
|
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,
|
|
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 = ((
|
|
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
|
-
(
|
|
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
|
}
|
|
@@ -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
|
|
@@ -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',
|
|
@@ -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;
|