@h-ai/ui 0.1.0-alpha.67 → 0.1.0-alpha.68
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/README.en.md +31 -5
- package/README.ja.md +31 -5
- package/README.md +64 -38
- package/dist/components/compounds/Accordion.svelte +24 -0
- package/dist/components/compounds/Accordion.svelte.d.ts +34 -0
- package/dist/components/compounds/ActionSheet.svelte +24 -0
- package/dist/components/compounds/ActionSheet.svelte.d.ts +38 -0
- package/dist/components/compounds/Alert.svelte +15 -4
- package/dist/components/compounds/Alert.svelte.d.ts +10 -0
- package/dist/components/compounds/AppBar.svelte +24 -0
- package/dist/components/compounds/AppBar.svelte.d.ts +33 -0
- package/dist/components/compounds/BottomNav.svelte +37 -0
- package/dist/components/compounds/BottomNav.svelte.d.ts +43 -0
- package/dist/components/compounds/Breadcrumb.svelte +11 -0
- package/dist/components/compounds/Breadcrumb.svelte.d.ts +20 -0
- package/dist/components/compounds/Calendar.svelte +20 -6
- package/dist/components/compounds/Calendar.svelte.d.ts +20 -6
- package/dist/components/compounds/Card.svelte +10 -0
- package/dist/components/compounds/Card.svelte.d.ts +10 -0
- package/dist/components/compounds/Combobox.svelte +35 -18
- package/dist/components/compounds/Combobox.svelte.d.ts +35 -18
- package/dist/components/compounds/Confirm.svelte +11 -0
- package/dist/components/compounds/Confirm.svelte.d.ts +21 -0
- package/dist/components/compounds/DataTable.svelte +40 -17
- package/dist/components/compounds/DataTable.svelte.d.ts +9 -13
- package/dist/components/compounds/DatePicker.svelte +20 -6
- package/dist/components/compounds/DatePicker.svelte.d.ts +20 -6
- package/dist/components/compounds/Drawer.svelte +11 -0
- package/dist/components/compounds/Drawer.svelte.d.ts +21 -0
- package/dist/components/compounds/Dropdown.svelte +10 -0
- package/dist/components/compounds/Dropdown.svelte.d.ts +10 -0
- package/dist/components/compounds/Empty.svelte +16 -5
- package/dist/components/compounds/Empty.svelte.d.ts +20 -0
- package/dist/components/compounds/Form.svelte +37 -2
- package/dist/components/compounds/Form.svelte.d.ts +20 -0
- package/dist/components/compounds/FormField.svelte +11 -0
- package/dist/components/compounds/FormField.svelte.d.ts +20 -0
- package/dist/components/compounds/FormLayout.svelte +13 -1
- package/dist/components/compounds/FormLayout.svelte.d.ts +13 -0
- package/dist/components/compounds/InfiniteScroll.svelte +24 -0
- package/dist/components/compounds/InfiniteScroll.svelte.d.ts +34 -0
- package/dist/components/compounds/MessageBoxContainer.svelte +11 -0
- package/dist/components/compounds/MessageBoxContainer.svelte.d.ts +21 -0
- package/dist/components/compounds/MessageBoxDialog.svelte +14 -0
- package/dist/components/compounds/MessageBoxDialog.svelte.d.ts +21 -0
- package/dist/components/compounds/MessageContainer.svelte +11 -0
- package/dist/components/compounds/MessageContainer.svelte.d.ts +21 -0
- package/dist/components/compounds/Modal.svelte +10 -0
- package/dist/components/compounds/Modal.svelte.d.ts +10 -0
- package/dist/components/compounds/PageHeader.svelte +21 -8
- package/dist/components/compounds/PageHeader.svelte.d.ts +21 -8
- package/dist/components/compounds/Pagination.svelte +34 -8
- package/dist/components/compounds/Pagination.svelte.d.ts +20 -0
- package/dist/components/compounds/Popover.svelte +11 -0
- package/dist/components/compounds/Popover.svelte.d.ts +20 -0
- package/dist/components/compounds/PullRefresh.svelte +24 -0
- package/dist/components/compounds/PullRefresh.svelte.d.ts +32 -0
- package/dist/components/compounds/Result.svelte +11 -0
- package/dist/components/compounds/Result.svelte.d.ts +20 -0
- package/dist/components/compounds/SafeArea.svelte +24 -0
- package/dist/components/compounds/SafeArea.svelte.d.ts +32 -0
- package/dist/components/compounds/Skeleton.svelte +10 -0
- package/dist/components/compounds/Skeleton.svelte.d.ts +10 -0
- package/dist/components/compounds/Steps.svelte +11 -0
- package/dist/components/compounds/Steps.svelte.d.ts +20 -0
- package/dist/components/compounds/SwipeCell.svelte +24 -0
- package/dist/components/compounds/SwipeCell.svelte.d.ts +37 -0
- package/dist/components/compounds/TableToolbar.svelte +66 -28
- package/dist/components/compounds/TableToolbar.svelte.d.ts +29 -19
- package/dist/components/compounds/Tabs.svelte +58 -10
- package/dist/components/compounds/Tabs.svelte.d.ts +10 -0
- package/dist/components/compounds/TagInput.svelte +11 -0
- package/dist/components/compounds/TagInput.svelte.d.ts +20 -0
- package/dist/components/compounds/Timeline.svelte +24 -0
- package/dist/components/compounds/Timeline.svelte.d.ts +34 -0
- package/dist/components/compounds/ToastContainer.svelte +11 -0
- package/dist/components/compounds/ToastContainer.svelte.d.ts +26 -0
- package/dist/components/compounds/Tooltip.svelte +11 -0
- package/dist/components/compounds/Tooltip.svelte.d.ts +22 -0
- package/dist/components/compounds/accordion-types.d.ts +10 -1
- package/dist/components/compounds/action-sheet-types.d.ts +9 -0
- package/dist/components/compounds/bottom-nav-types.d.ts +9 -0
- package/dist/components/compounds/swipe-cell-types.d.ts +9 -0
- package/dist/components/compounds/timeline-types.d.ts +9 -0
- package/dist/components/control-size.d.ts +17 -0
- package/dist/components/control-size.js +8 -0
- package/dist/components/primitives/Avatar.svelte +10 -0
- package/dist/components/primitives/Avatar.svelte.d.ts +10 -0
- package/dist/components/primitives/Badge.svelte +10 -0
- package/dist/components/primitives/Badge.svelte.d.ts +10 -0
- package/dist/components/primitives/BareButton.svelte +11 -0
- package/dist/components/primitives/BareButton.svelte.d.ts +20 -0
- package/dist/components/primitives/BareInput.svelte +11 -0
- package/dist/components/primitives/BareInput.svelte.d.ts +20 -0
- package/dist/components/primitives/Button.svelte +10 -0
- package/dist/components/primitives/Button.svelte.d.ts +10 -0
- package/dist/components/primitives/Checkbox.svelte +11 -0
- package/dist/components/primitives/Checkbox.svelte.d.ts +20 -0
- package/dist/components/primitives/IconButton.svelte +11 -0
- package/dist/components/primitives/IconButton.svelte.d.ts +20 -0
- package/dist/components/primitives/Input.svelte +10 -0
- package/dist/components/primitives/Input.svelte.d.ts +10 -0
- package/dist/components/primitives/Progress.svelte +11 -0
- package/dist/components/primitives/Progress.svelte.d.ts +20 -0
- package/dist/components/primitives/Radio.svelte +11 -0
- package/dist/components/primitives/Radio.svelte.d.ts +20 -0
- package/dist/components/primitives/Range.svelte +24 -0
- package/dist/components/primitives/Range.svelte.d.ts +34 -0
- package/dist/components/primitives/Rating.svelte +24 -0
- package/dist/components/primitives/Rating.svelte.d.ts +34 -0
- package/dist/components/primitives/Select.svelte +11 -0
- package/dist/components/primitives/Select.svelte.d.ts +21 -0
- package/dist/components/primitives/Spinner.svelte +11 -0
- package/dist/components/primitives/Spinner.svelte.d.ts +20 -0
- package/dist/components/primitives/Switch.svelte +11 -0
- package/dist/components/primitives/Switch.svelte.d.ts +20 -0
- package/dist/components/primitives/Tag.svelte +11 -0
- package/dist/components/primitives/Tag.svelte.d.ts +20 -0
- package/dist/components/primitives/Textarea.svelte +11 -0
- package/dist/components/primitives/Textarea.svelte.d.ts +21 -0
- package/dist/components/primitives/ToggleCheckbox.svelte +11 -0
- package/dist/components/primitives/ToggleCheckbox.svelte.d.ts +20 -0
- package/dist/components/primitives/ToggleInput.svelte +11 -0
- package/dist/components/primitives/ToggleInput.svelte.d.ts +20 -0
- package/dist/components/primitives/ToggleRadio.svelte +11 -0
- package/dist/components/primitives/ToggleRadio.svelte.d.ts +20 -0
- package/dist/components/scenes/ai/AiDocumentDownloadMenu.svelte +27 -0
- package/dist/components/scenes/ai/AiDocumentDownloadMenu.svelte.d.ts +27 -0
- package/dist/components/scenes/ai/AiDocumentEditor.svelte +79 -0
- package/dist/components/scenes/ai/AiDocumentEditor.svelte.d.ts +23 -0
- package/dist/components/scenes/ai/MarkdownRenderer.svelte +11 -0
- package/dist/components/scenes/ai/MarkdownRenderer.svelte.d.ts +28 -0
- package/dist/components/scenes/ai/code-preview.d.ts +28 -0
- package/dist/components/scenes/ai/code-preview.js +20 -0
- package/dist/components/scenes/ai/document-download.d.ts +52 -0
- package/dist/components/scenes/ai/document-download.js +30 -2
- package/dist/components/scenes/ai/document-parse.d.ts +71 -14
- package/dist/components/scenes/ai/document-parse.js +19 -9
- package/dist/components/scenes/ai/document-types.d.ts +222 -88
- package/dist/components/scenes/ai/editor-markdown-extensions.d.ts +16 -0
- package/dist/components/scenes/ai/editor-markdown-extensions.js +16 -0
- package/dist/components/scenes/ai/highlight.d.ts +11 -0
- package/dist/components/scenes/ai/highlight.js +11 -0
- package/dist/components/scenes/ai/markdown-parse.d.ts +8 -2
- package/dist/components/scenes/ai/markdown-parse.js +2 -2
- package/dist/components/scenes/ai/mermaid-host-sync.d.ts +38 -0
- package/dist/components/scenes/ai/mermaid-host-sync.js +30 -0
- package/dist/components/scenes/ai/mermaid-render.d.ts +23 -0
- package/dist/components/scenes/ai/mermaid-render.js +23 -0
- package/dist/components/scenes/ai/safe-html.d.ts +54 -6
- package/dist/components/scenes/ai/safe-html.js +54 -6
- package/dist/components/scenes/ai/table/AiTableEditor.svelte +48 -0
- package/dist/components/scenes/ai/table/AiTableEditor.svelte.d.ts +24 -0
- package/dist/components/scenes/ai/table/table-types.d.ts +79 -0
- package/dist/components/scenes/app/FeedbackModal.svelte +45 -5
- package/dist/components/scenes/app/FeedbackModal.svelte.d.ts +45 -5
- package/dist/components/scenes/app/LanguageSwitch.svelte +29 -19
- package/dist/components/scenes/app/LanguageSwitch.svelte.d.ts +28 -19
- package/dist/components/scenes/app/SettingsLayout.svelte +21 -9
- package/dist/components/scenes/app/SettingsLayout.svelte.d.ts +21 -9
- package/dist/components/scenes/app/SettingsModal.svelte +23 -0
- package/dist/components/scenes/app/SettingsModal.svelte.d.ts +23 -0
- package/dist/components/scenes/app/ThemeColorPicker.svelte +31 -0
- package/dist/components/scenes/app/ThemeColorPicker.svelte.d.ts +31 -0
- package/dist/components/scenes/app/ThemeSelector.svelte +21 -6
- package/dist/components/scenes/app/ThemeSelector.svelte.d.ts +21 -6
- package/dist/components/scenes/app/ThemeToggle.svelte +21 -4
- package/dist/components/scenes/app/ThemeToggle.svelte.d.ts +21 -4
- package/dist/components/scenes/app/index.d.ts +1 -1
- package/dist/components/scenes/app/index.js +1 -1
- package/dist/components/scenes/charts/Chart.svelte +11 -0
- package/dist/components/scenes/charts/Chart.svelte.d.ts +20 -0
- package/dist/components/scenes/charts/chart-theme.d.ts +25 -1
- package/dist/components/scenes/charts/chart-theme.js +25 -1
- package/dist/components/scenes/charts/chart-types.d.ts +83 -7
- package/dist/components/scenes/charts/renderers/LineChart.svelte +53 -0
- package/dist/components/scenes/charts/renderers/LineChart.svelte.d.ts +13 -0
- package/dist/components/scenes/crud/CrudDeleteConfirm.svelte +10 -0
- package/dist/components/scenes/crud/CrudDeleteConfirm.svelte.d.ts +10 -0
- package/dist/components/scenes/crud/CrudDetailDrawer.svelte +8 -0
- package/dist/components/scenes/crud/CrudDetailDrawer.svelte.d.ts +8 -0
- package/dist/components/scenes/crud/CrudDetailPanel.svelte +18 -0
- package/dist/components/scenes/crud/CrudDetailPanel.svelte.d.ts +18 -0
- package/dist/components/scenes/crud/CrudEditPanel.svelte +10 -0
- package/dist/components/scenes/crud/CrudEditPanel.svelte.d.ts +10 -0
- package/dist/components/scenes/crud/CrudFilterBar.svelte +18 -0
- package/dist/components/scenes/crud/CrudFilterBar.svelte.d.ts +18 -0
- package/dist/components/scenes/crud/CrudPage.svelte +37 -5
- package/dist/components/scenes/crud/CrudPage.svelte.d.ts +35 -3
- package/dist/components/scenes/crud/crud-controller.svelte.d.ts +142 -23
- package/dist/components/scenes/crud/crud-controller.svelte.js +22 -11
- package/dist/components/scenes/crud/crud-form-validation.d.ts +12 -0
- package/dist/components/scenes/crud/crud-form-validation.js +12 -0
- package/dist/components/scenes/crud/crud-types.d.ts +79 -8
- package/dist/components/scenes/crud/nav-adapter.d.ts +14 -0
- package/dist/components/scenes/crud/nav-adapter.js +8 -0
- package/dist/components/scenes/crypto/EncryptedInput.svelte +24 -0
- package/dist/components/scenes/crypto/EncryptedInput.svelte.d.ts +34 -0
- package/dist/components/scenes/crypto/HashDisplay.svelte +11 -0
- package/dist/components/scenes/crypto/HashDisplay.svelte.d.ts +21 -0
- package/dist/components/scenes/crypto/SignatureDisplay.svelte +11 -0
- package/dist/components/scenes/crypto/SignatureDisplay.svelte.d.ts +21 -0
- package/dist/components/scenes/error/ErrorPage.svelte +8 -1
- package/dist/components/scenes/error/ErrorPage.svelte.d.ts +8 -1
- package/dist/components/scenes/error/error-presets.d.ts +40 -4
- package/dist/components/scenes/error/error-presets.js +22 -2
- package/dist/components/scenes/guide/GuideHost.svelte +27 -0
- package/dist/components/scenes/guide/GuideHost.svelte.d.ts +27 -0
- package/dist/components/scenes/guide/HelpCenter.svelte +27 -0
- package/dist/components/scenes/guide/HelpCenter.svelte.d.ts +27 -0
- package/dist/components/scenes/iam/AuthPanel.svelte +26 -2
- package/dist/components/scenes/iam/AuthPanel.svelte.d.ts +25 -0
- package/dist/components/scenes/iam/AuthShell.svelte +8 -3
- package/dist/components/scenes/iam/AuthShell.svelte.d.ts +8 -3
- package/dist/components/scenes/iam/ChangePasswordForm.svelte +10 -0
- package/dist/components/scenes/iam/ChangePasswordForm.svelte.d.ts +10 -0
- package/dist/components/scenes/iam/ForgotPasswordForm.svelte +11 -0
- package/dist/components/scenes/iam/ForgotPasswordForm.svelte.d.ts +21 -0
- package/dist/components/scenes/iam/LoginForm.svelte +24 -31
- package/dist/components/scenes/iam/LoginForm.svelte.d.ts +10 -0
- package/dist/components/scenes/iam/PasswordInput.svelte +23 -0
- package/dist/components/scenes/iam/PasswordInput.svelte.d.ts +23 -0
- package/dist/components/scenes/iam/PermGuard.svelte +21 -11
- package/dist/components/scenes/iam/PermGuard.svelte.d.ts +30 -0
- package/dist/components/scenes/iam/RegisterForm.svelte +10 -0
- package/dist/components/scenes/iam/RegisterForm.svelte.d.ts +10 -0
- package/dist/components/scenes/iam/ResetPasswordForm.svelte +10 -0
- package/dist/components/scenes/iam/ResetPasswordForm.svelte.d.ts +10 -0
- package/dist/components/scenes/iam/UserProfile.svelte +11 -0
- package/dist/components/scenes/iam/UserProfile.svelte.d.ts +21 -0
- package/dist/components/scenes/iam/auth-error-message.d.ts +10 -0
- package/dist/components/scenes/iam/auth-error-message.js +10 -0
- package/dist/components/scenes/iam/password-utils.d.ts +39 -1
- package/dist/components/scenes/iam/password-utils.js +39 -1
- package/dist/components/scenes/iam/permission-context.svelte.d.ts +33 -23
- package/dist/components/scenes/iam/permission-context.svelte.js +20 -22
- package/dist/components/scenes/storage/AvatarUpload.svelte +11 -0
- package/dist/components/scenes/storage/AvatarUpload.svelte.d.ts +20 -0
- package/dist/components/scenes/storage/FileList.svelte +13 -2
- package/dist/components/scenes/storage/FileList.svelte.d.ts +20 -0
- package/dist/components/scenes/storage/FileUpload.svelte +37 -2
- package/dist/components/scenes/storage/FileUpload.svelte.d.ts +21 -0
- package/dist/components/scenes/storage/ImageUpload.svelte +11 -0
- package/dist/components/scenes/storage/ImageUpload.svelte.d.ts +21 -0
- package/dist/components/scenes/types.d.ts +352 -11
- package/dist/guide-storage.d.ts +13 -1
- package/dist/guide-storage.js +13 -1
- package/dist/guide-types.d.ts +67 -2
- package/dist/guide.svelte.d.ts +22 -1
- package/dist/guide.svelte.js +22 -1
- package/dist/i18n.svelte.d.ts +64 -3
- package/dist/i18n.svelte.js +99 -18
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -2
- package/dist/internal/browser-safety.d.ts +51 -2
- package/dist/internal/browser-safety.js +45 -7
- package/dist/internal/form-context.d.ts +73 -0
- package/dist/internal/form-context.js +57 -0
- package/dist/internal/form-validation.svelte.d.ts +42 -0
- package/dist/internal/form-validation.svelte.js +26 -0
- package/dist/internal/icon-safety.d.ts +7 -0
- package/dist/internal/icon-safety.js +7 -0
- package/dist/internal/locale.d.ts +19 -0
- package/dist/internal/locale.js +21 -0
- package/dist/message.svelte.d.ts +90 -0
- package/dist/message.svelte.js +84 -0
- package/dist/messagebox.svelte.d.ts +61 -13
- package/dist/messagebox.svelte.js +55 -13
- package/dist/messages/en-US.json +6 -1
- package/dist/messages/ja-JP.json +389 -0
- package/dist/messages/zh-CN.json +6 -1
- package/dist/messages.d.ts +24 -3
- package/dist/messages.js +18 -3
- package/dist/styles/design-tokens.css +4 -2
- package/dist/styles/global.css +28 -8
- package/dist/styles/theme.css +2 -0
- package/dist/theme-config.d.ts +173 -0
- package/dist/theme-config.js +143 -0
- package/dist/toast.svelte.d.ts +114 -4
- package/dist/toast.svelte.js +108 -4
- package/dist/types.d.ts +526 -9
- package/dist/utils/platform.svelte.d.ts +28 -15
- package/dist/utils/platform.svelte.js +19 -14
- package/dist/utils.d.ts +102 -0
- package/dist/utils.js +93 -0
- package/package.json +66 -6
|
@@ -2,10 +2,26 @@ import type { Token, TokenizerAndRendererExtension } from 'marked';
|
|
|
2
2
|
/**
|
|
3
3
|
* Markdown heading 提取目录时需要一个“纯文本标题”。
|
|
4
4
|
* 这里显式递归常见 inline token,保证 `<hai-span>`、链接、强调等都能回落成纯文本。
|
|
5
|
+
* @param tokens - Marked token 列表。
|
|
6
|
+
* @returns 递归提取的纯文本,用于标题和目录生成。
|
|
7
|
+
*
|
|
8
|
+
* @example 模块内部上下文
|
|
9
|
+
* ```ts
|
|
10
|
+
* const text = extractPlainTextFromTokens([{ type: 'text', raw: '简介', text: '简介' }])
|
|
11
|
+
* ```
|
|
5
12
|
*/
|
|
6
13
|
export declare function extractPlainTextFromTokens(tokens: Token[] | undefined): string;
|
|
7
14
|
/**
|
|
8
15
|
* ChatWorkspace 编辑器会把“非标准 Markdown”能力写成自定义标签,
|
|
9
16
|
* 这里把它们注册为 marked 扩展,保证普通 Markdown 和编辑器增强能力共享同一条渲染链路。
|
|
17
|
+
* @returns 受控格式的 Marked tokenizer/renderer 扩展。
|
|
18
|
+
*
|
|
19
|
+
* @example 模块内部上下文
|
|
20
|
+
* ```ts
|
|
21
|
+
* const { Marked } = await import('marked')
|
|
22
|
+
* const extensions = createEditorMarkdownExtensions()
|
|
23
|
+
* const parser = new Marked({ extensions })
|
|
24
|
+
* const html = parser.parse('**重点**')
|
|
25
|
+
* ```
|
|
10
26
|
*/
|
|
11
27
|
export declare function createEditorMarkdownExtensions(): TokenizerAndRendererExtension[];
|
|
@@ -14,6 +14,13 @@ const HAI_HIGHLIGHT_REGEX = /^==((?:\\.|[\s\S])+?)==/;
|
|
|
14
14
|
/**
|
|
15
15
|
* Markdown heading 提取目录时需要一个“纯文本标题”。
|
|
16
16
|
* 这里显式递归常见 inline token,保证 `<hai-span>`、链接、强调等都能回落成纯文本。
|
|
17
|
+
* @param tokens - Marked token 列表。
|
|
18
|
+
* @returns 递归提取的纯文本,用于标题和目录生成。
|
|
19
|
+
*
|
|
20
|
+
* @example 模块内部上下文
|
|
21
|
+
* ```ts
|
|
22
|
+
* const text = extractPlainTextFromTokens([{ type: 'text', raw: '简介', text: '简介' }])
|
|
23
|
+
* ```
|
|
17
24
|
*/
|
|
18
25
|
export function extractPlainTextFromTokens(tokens) {
|
|
19
26
|
if (!tokens || tokens.length === 0) {
|
|
@@ -74,6 +81,15 @@ function parseHaiSpanAttributes(rawAttributes) {
|
|
|
74
81
|
/**
|
|
75
82
|
* ChatWorkspace 编辑器会把“非标准 Markdown”能力写成自定义标签,
|
|
76
83
|
* 这里把它们注册为 marked 扩展,保证普通 Markdown 和编辑器增强能力共享同一条渲染链路。
|
|
84
|
+
* @returns 受控格式的 Marked tokenizer/renderer 扩展。
|
|
85
|
+
*
|
|
86
|
+
* @example 模块内部上下文
|
|
87
|
+
* ```ts
|
|
88
|
+
* const { Marked } = await import('marked')
|
|
89
|
+
* const extensions = createEditorMarkdownExtensions()
|
|
90
|
+
* const parser = new Marked({ extensions })
|
|
91
|
+
* const html = parser.parse('**重点**')
|
|
92
|
+
* ```
|
|
77
93
|
*/
|
|
78
94
|
export function createEditorMarkdownExtensions() {
|
|
79
95
|
return [
|
|
@@ -11,6 +11,11 @@
|
|
|
11
11
|
*
|
|
12
12
|
* @param lang - 语言标识符(支持别名如 js、ts、py)
|
|
13
13
|
* @returns 是否支持该语言
|
|
14
|
+
*
|
|
15
|
+
* @example 模块内部上下文
|
|
16
|
+
* ```ts
|
|
17
|
+
* const supported = isLanguageSupported('typescript')
|
|
18
|
+
* ```
|
|
14
19
|
*/
|
|
15
20
|
export declare function isLanguageSupported(lang: string): boolean;
|
|
16
21
|
/**
|
|
@@ -22,5 +27,11 @@ export declare function isLanguageSupported(lang: string): boolean;
|
|
|
22
27
|
* @param text - 代码文本
|
|
23
28
|
* @param lang - 语言标识符
|
|
24
29
|
* @returns 高亮后的 HTML 片段
|
|
30
|
+
*
|
|
31
|
+
* @example 模块内部上下文
|
|
32
|
+
* ```ts
|
|
33
|
+
* const html = highlightCode('const count = 42', 'typescript')
|
|
34
|
+
* // 返回已转义/高亮后的代码 HTML,未知语言回退安全纯文本。
|
|
35
|
+
* ```
|
|
25
36
|
*/
|
|
26
37
|
export declare function highlightCode(text: string, lang: string): string;
|
|
@@ -128,6 +128,11 @@ function extractCodeInnerHtml(html) {
|
|
|
128
128
|
*
|
|
129
129
|
* @param lang - 语言标识符(支持别名如 js、ts、py)
|
|
130
130
|
* @returns 是否支持该语言
|
|
131
|
+
*
|
|
132
|
+
* @example 模块内部上下文
|
|
133
|
+
* ```ts
|
|
134
|
+
* const supported = isLanguageSupported('typescript')
|
|
135
|
+
* ```
|
|
131
136
|
*/
|
|
132
137
|
export function isLanguageSupported(lang) {
|
|
133
138
|
return resolveLang(lang) !== null;
|
|
@@ -141,6 +146,12 @@ export function isLanguageSupported(lang) {
|
|
|
141
146
|
* @param text - 代码文本
|
|
142
147
|
* @param lang - 语言标识符
|
|
143
148
|
* @returns 高亮后的 HTML 片段
|
|
149
|
+
*
|
|
150
|
+
* @example 模块内部上下文
|
|
151
|
+
* ```ts
|
|
152
|
+
* const html = highlightCode('const count = 42', 'typescript')
|
|
153
|
+
* // 返回已转义/高亮后的代码 HTML,未知语言回退安全纯文本。
|
|
154
|
+
* ```
|
|
144
155
|
*/
|
|
145
156
|
export function highlightCode(text, lang) {
|
|
146
157
|
const resolved = resolveLang(lang);
|
|
@@ -7,6 +7,12 @@
|
|
|
7
7
|
*/
|
|
8
8
|
/**
|
|
9
9
|
* Markdown 解析配置
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* import type { MarkdownParseOptions } from '@h-ai/ui'
|
|
14
|
+
* const example: MarkdownParseOptions = { enableHighlight: true, allowHtmlTags: false, showCopyButton: true }
|
|
15
|
+
* ```
|
|
10
16
|
*/
|
|
11
17
|
export interface MarkdownParseOptions {
|
|
12
18
|
/** 是否启用代码语法高亮(默认 true) */
|
|
@@ -27,8 +33,8 @@ export interface MarkdownParseOptions {
|
|
|
27
33
|
*
|
|
28
34
|
* @example
|
|
29
35
|
* ```ts
|
|
30
|
-
*
|
|
31
|
-
*
|
|
36
|
+
* import { parseMarkdown } from '@h-ai/ui'
|
|
37
|
+
* const html = parseMarkdown('# 简介\n**重点**', { allowHtmlTags: false })
|
|
32
38
|
* ```
|
|
33
39
|
*/
|
|
34
40
|
export declare function parseMarkdown(content: string, options?: MarkdownParseOptions): string;
|
|
@@ -152,8 +152,8 @@ function getOptionsKey(options) {
|
|
|
152
152
|
*
|
|
153
153
|
* @example
|
|
154
154
|
* ```ts
|
|
155
|
-
*
|
|
156
|
-
*
|
|
155
|
+
* import { parseMarkdown } from '@h-ai/ui'
|
|
156
|
+
* const html = parseMarkdown('# 简介\n**重点**', { allowHtmlTags: false })
|
|
157
157
|
* ```
|
|
158
158
|
*/
|
|
159
159
|
export function parseMarkdown(content, options) {
|
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Mermaid 图表通过 {@html} 插入占位节点后异步渲染。流式输出时,HTML 占位可能不变,
|
|
5
5
|
* 但源码正文会持续变化,因此必须用源码签名判断是否需要重渲染。
|
|
6
|
+
*
|
|
7
|
+
* @example 模块内部上下文
|
|
8
|
+
* ```ts
|
|
9
|
+
* const example: MermaidHostRenderActionInput = { status: 'ready', renderedSignature: 'old-source', nextSignature: 'new-source' }
|
|
10
|
+
* ```
|
|
6
11
|
*/
|
|
7
12
|
export interface MermaidHostRenderActionInput {
|
|
8
13
|
/** 当前 host 上记录的渲染状态。 */
|
|
@@ -12,6 +17,14 @@ export interface MermaidHostRenderActionInput {
|
|
|
12
17
|
/** 本次 Markdown 解析得到的最新源码签名。 */
|
|
13
18
|
nextSignature: string;
|
|
14
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* 异步 Mermaid 渲染决策;仅 shouldRender=true 时携带提交 token。
|
|
22
|
+
*
|
|
23
|
+
* @example 模块内部上下文
|
|
24
|
+
* ```ts
|
|
25
|
+
* const example: MermaidHostRenderAction = { shouldRender: true, token: 'diagram-1-source' }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
15
28
|
export type MermaidHostRenderAction = {
|
|
16
29
|
shouldRender: false;
|
|
17
30
|
} | {
|
|
@@ -22,13 +35,38 @@ export type MermaidHostRenderAction = {
|
|
|
22
35
|
* 为 Mermaid block 生成稳定签名。
|
|
23
36
|
*
|
|
24
37
|
* 签名同时包含 block id 与源码正文,避免流式阶段占位 HTML 未变化时漏掉源码更新。
|
|
38
|
+
* @param blockId - 当前代码块的稳定 ID。
|
|
39
|
+
* @param code - Mermaid 或待渲染的代码源码。
|
|
40
|
+
* @returns 绑定块 id 和完整源码的稳定签名。
|
|
41
|
+
*
|
|
42
|
+
* @example 模块内部上下文
|
|
43
|
+
* ```ts
|
|
44
|
+
* const signature = createMermaidSourceSignature('diagram-1', 'graph TD; A-->B')
|
|
45
|
+
* ```
|
|
25
46
|
*/
|
|
26
47
|
export declare function createMermaidSourceSignature(blockId: string, code: string): string;
|
|
27
48
|
/**
|
|
28
49
|
* 判断 Mermaid host 是否需要发起一次新的异步渲染。
|
|
50
|
+
* @param input - 当前状态及目标源码签名。
|
|
51
|
+
* @returns 是否重渲染的决策,需要时携带提交 token。
|
|
52
|
+
*
|
|
53
|
+
* @example 模块内部上下文
|
|
54
|
+
* ```ts
|
|
55
|
+
* const action = getMermaidHostRenderAction({ status: 'ready', renderedSignature: 'old', nextSignature: 'new' })
|
|
56
|
+
* if (action.shouldRender) { const token = action.token }
|
|
57
|
+
* ```
|
|
29
58
|
*/
|
|
30
59
|
export declare function getMermaidHostRenderAction(input: MermaidHostRenderActionInput): MermaidHostRenderAction;
|
|
31
60
|
/**
|
|
32
61
|
* 判断异步 Mermaid 渲染结果是否仍对应当前 host 源码。
|
|
62
|
+
* @param renderToken - 异步渲染启动时捕获的 token。
|
|
63
|
+
* @param currentSignature - 宿主当前源码签名。
|
|
64
|
+
* @returns 渲染 token 是否仍匹配当前源码签名。
|
|
65
|
+
*
|
|
66
|
+
* @example 模块内部上下文
|
|
67
|
+
* ```ts
|
|
68
|
+
* const accepted = isCurrentMermaidRenderToken('current-source', 'current-source')
|
|
69
|
+
* const stale = isCurrentMermaidRenderToken('old-source', 'current-source')
|
|
70
|
+
* ```
|
|
33
71
|
*/
|
|
34
72
|
export declare function isCurrentMermaidRenderToken(renderToken: string, currentSignature: string | undefined): boolean;
|
|
@@ -3,17 +3,38 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Mermaid 图表通过 {@html} 插入占位节点后异步渲染。流式输出时,HTML 占位可能不变,
|
|
5
5
|
* 但源码正文会持续变化,因此必须用源码签名判断是否需要重渲染。
|
|
6
|
+
*
|
|
7
|
+
* @example 模块内部上下文
|
|
8
|
+
* ```ts
|
|
9
|
+
* const example: MermaidHostRenderActionInput = { status: 'ready', renderedSignature: 'old-source', nextSignature: 'new-source' }
|
|
10
|
+
* ```
|
|
6
11
|
*/
|
|
7
12
|
/**
|
|
8
13
|
* 为 Mermaid block 生成稳定签名。
|
|
9
14
|
*
|
|
10
15
|
* 签名同时包含 block id 与源码正文,避免流式阶段占位 HTML 未变化时漏掉源码更新。
|
|
16
|
+
* @param blockId - 当前代码块的稳定 ID。
|
|
17
|
+
* @param code - Mermaid 或待渲染的代码源码。
|
|
18
|
+
* @returns 绑定块 id 和完整源码的稳定签名。
|
|
19
|
+
*
|
|
20
|
+
* @example 模块内部上下文
|
|
21
|
+
* ```ts
|
|
22
|
+
* const signature = createMermaidSourceSignature('diagram-1', 'graph TD; A-->B')
|
|
23
|
+
* ```
|
|
11
24
|
*/
|
|
12
25
|
export function createMermaidSourceSignature(blockId, code) {
|
|
13
26
|
return JSON.stringify([blockId, code]);
|
|
14
27
|
}
|
|
15
28
|
/**
|
|
16
29
|
* 判断 Mermaid host 是否需要发起一次新的异步渲染。
|
|
30
|
+
* @param input - 当前状态及目标源码签名。
|
|
31
|
+
* @returns 是否重渲染的决策,需要时携带提交 token。
|
|
32
|
+
*
|
|
33
|
+
* @example 模块内部上下文
|
|
34
|
+
* ```ts
|
|
35
|
+
* const action = getMermaidHostRenderAction({ status: 'ready', renderedSignature: 'old', nextSignature: 'new' })
|
|
36
|
+
* if (action.shouldRender) { const token = action.token }
|
|
37
|
+
* ```
|
|
17
38
|
*/
|
|
18
39
|
export function getMermaidHostRenderAction(input) {
|
|
19
40
|
const status = input.status?.trim();
|
|
@@ -29,6 +50,15 @@ export function getMermaidHostRenderAction(input) {
|
|
|
29
50
|
}
|
|
30
51
|
/**
|
|
31
52
|
* 判断异步 Mermaid 渲染结果是否仍对应当前 host 源码。
|
|
53
|
+
* @param renderToken - 异步渲染启动时捕获的 token。
|
|
54
|
+
* @param currentSignature - 宿主当前源码签名。
|
|
55
|
+
* @returns 渲染 token 是否仍匹配当前源码签名。
|
|
56
|
+
*
|
|
57
|
+
* @example 模块内部上下文
|
|
58
|
+
* ```ts
|
|
59
|
+
* const accepted = isCurrentMermaidRenderToken('current-source', 'current-source')
|
|
60
|
+
* const stale = isCurrentMermaidRenderToken('old-source', 'current-source')
|
|
61
|
+
* ```
|
|
32
62
|
*/
|
|
33
63
|
export function isCurrentMermaidRenderToken(renderToken, currentSignature) {
|
|
34
64
|
return renderToken === currentSignature;
|
|
@@ -6,14 +6,37 @@
|
|
|
6
6
|
*/
|
|
7
7
|
/**
|
|
8
8
|
* 判断 fence 语言是否为 mermaid。
|
|
9
|
+
* @param language - 待识别的语言标记。
|
|
10
|
+
* @returns 语言标记是否属于 Mermaid。
|
|
11
|
+
*
|
|
12
|
+
* @example 模块内部上下文
|
|
13
|
+
* ```ts
|
|
14
|
+
* const supported = isMermaidLanguage('mermaid')
|
|
15
|
+
* ```
|
|
9
16
|
*/
|
|
10
17
|
export declare function isMermaidLanguage(language: string | undefined | null): boolean;
|
|
11
18
|
/**
|
|
12
19
|
* 把 mermaid 源码渲染为 SVG 字符串;语法错误时抛出由调用方兜底展示。
|
|
20
|
+
* @param code - Mermaid 或待渲染的代码源码。
|
|
21
|
+
* @returns 严格模式渲染并移除样式节点后的 SVG。
|
|
22
|
+
* @throws 浏览器渲染、第三方解析或下载失败时抛出异常,由交互边界显示错误。
|
|
23
|
+
*
|
|
24
|
+
* @example 模块内部上下文
|
|
25
|
+
* ```ts
|
|
26
|
+
* const svg = await renderMermaidDiagram('graph TD; A-->B')
|
|
27
|
+
* // 在浏览器异步渲染,失败由调用交互边界处理。
|
|
28
|
+
* ```
|
|
13
29
|
*/
|
|
14
30
|
export declare function renderMermaidDiagram(code: string): Promise<string>;
|
|
15
31
|
/**
|
|
16
32
|
* Mermaid 11.x 会在 SVG 内写入很长的 style 标签内容;在 contenteditable 预览区里,
|
|
17
33
|
* 部分浏览器会把这些 CSS 当成正文显示。这里保留 SVG 图形,剥离内联样式文本。
|
|
34
|
+
* @param svg - 待移除样式节点的 SVG。
|
|
35
|
+
* @returns 移除 style 元素后的 SVG 字符串。
|
|
36
|
+
*
|
|
37
|
+
* @example 模块内部上下文
|
|
38
|
+
* ```ts
|
|
39
|
+
* const svg = stripMermaidSvgStyleElements('<svg><style>.x{fill:red}</style><path d="M0 0"/></svg>')
|
|
40
|
+
* ```
|
|
18
41
|
*/
|
|
19
42
|
export declare function stripMermaidSvgStyleElements(svg: string): string;
|
|
@@ -10,6 +10,13 @@ let mermaidLoader = null;
|
|
|
10
10
|
let renderSeq = 0;
|
|
11
11
|
/**
|
|
12
12
|
* 判断 fence 语言是否为 mermaid。
|
|
13
|
+
* @param language - 待识别的语言标记。
|
|
14
|
+
* @returns 语言标记是否属于 Mermaid。
|
|
15
|
+
*
|
|
16
|
+
* @example 模块内部上下文
|
|
17
|
+
* ```ts
|
|
18
|
+
* const supported = isMermaidLanguage('mermaid')
|
|
19
|
+
* ```
|
|
13
20
|
*/
|
|
14
21
|
export function isMermaidLanguage(language) {
|
|
15
22
|
return (language ?? '').trim().toLowerCase() === 'mermaid';
|
|
@@ -33,6 +40,15 @@ async function loadMermaid() {
|
|
|
33
40
|
}
|
|
34
41
|
/**
|
|
35
42
|
* 把 mermaid 源码渲染为 SVG 字符串;语法错误时抛出由调用方兜底展示。
|
|
43
|
+
* @param code - Mermaid 或待渲染的代码源码。
|
|
44
|
+
* @returns 严格模式渲染并移除样式节点后的 SVG。
|
|
45
|
+
* @throws 浏览器渲染、第三方解析或下载失败时抛出异常,由交互边界显示错误。
|
|
46
|
+
*
|
|
47
|
+
* @example 模块内部上下文
|
|
48
|
+
* ```ts
|
|
49
|
+
* const svg = await renderMermaidDiagram('graph TD; A-->B')
|
|
50
|
+
* // 在浏览器异步渲染,失败由调用交互边界处理。
|
|
51
|
+
* ```
|
|
36
52
|
*/
|
|
37
53
|
export async function renderMermaidDiagram(code) {
|
|
38
54
|
const mermaid = await loadMermaid();
|
|
@@ -43,6 +59,13 @@ export async function renderMermaidDiagram(code) {
|
|
|
43
59
|
/**
|
|
44
60
|
* Mermaid 11.x 会在 SVG 内写入很长的 style 标签内容;在 contenteditable 预览区里,
|
|
45
61
|
* 部分浏览器会把这些 CSS 当成正文显示。这里保留 SVG 图形,剥离内联样式文本。
|
|
62
|
+
* @param svg - 待移除样式节点的 SVG。
|
|
63
|
+
* @returns 移除 style 元素后的 SVG 字符串。
|
|
64
|
+
*
|
|
65
|
+
* @example 模块内部上下文
|
|
66
|
+
* ```ts
|
|
67
|
+
* const svg = stripMermaidSvgStyleElements('<svg><style>.x{fill:red}</style><path d="M0 0"/></svg>')
|
|
68
|
+
* ```
|
|
46
69
|
*/
|
|
47
70
|
export function stripMermaidSvgStyleElements(svg) {
|
|
48
71
|
return svg.replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, '');
|
|
@@ -1,16 +1,64 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @h-ai/ui —
|
|
2
|
+
* @h-ai/ui — Markdown 渲染的安全 HTML 工具。
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Markdown 默认将原始 HTML 当作纯文本转义。
|
|
5
|
+
* 显式允许 HTML 后,也只重建白名单中的安全标签与
|
|
6
|
+
* 属性;不支持或危险的标记仍按文字转义。
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* 将候选文本中的 HTML 特殊字符转义为可安全展示的纯文本。
|
|
10
|
+
* @param text - 待处理文本。
|
|
11
|
+
* @returns HTML 特殊字符被转义的字符串。
|
|
12
|
+
*
|
|
13
|
+
* @example 模块内部上下文
|
|
14
|
+
* ```ts
|
|
15
|
+
* const escaped = escapeHtml('<b>文本</b>')
|
|
16
|
+
* ```
|
|
7
17
|
*/
|
|
8
18
|
export declare function escapeHtml(text: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* 拒绝脚本等危险协议,只输出允许的链接地址。
|
|
21
|
+
* @param href - 待验证的链接候选地址。
|
|
22
|
+
* @returns 允许的链接地址,不安全或空输入返回空字符串。
|
|
23
|
+
*
|
|
24
|
+
* @example 模块内部上下文
|
|
25
|
+
* ```ts
|
|
26
|
+
* const safe = sanitizeLinkHref('javascript:alert(1)')
|
|
27
|
+
* // 不安全协议变为空字符串,不能直接渲染原始 href。
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
9
30
|
export declare function sanitizeLinkHref(href: string | null | undefined): string;
|
|
31
|
+
/**
|
|
32
|
+
* 识别外部链接,供渲染器添加相应的 rel/target 安全属性。
|
|
33
|
+
* @param href - 待验证的链接候选地址。
|
|
34
|
+
* @returns 地址是否为需要外链安全属性的外部链接。
|
|
35
|
+
*
|
|
36
|
+
* @example 模块内部上下文
|
|
37
|
+
* ```ts
|
|
38
|
+
* const external = isExternalLinkHref('https://example.com/help')
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
10
41
|
export declare function isExternalLinkHref(href: string): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* 拒绝危险图片来源,保留允许的远程、相对或受控数据地址。
|
|
44
|
+
* @param src - 待验证的图片候选地址。
|
|
45
|
+
* @returns 允许的图片地址,不安全或空输入返回空字符串。
|
|
46
|
+
*
|
|
47
|
+
* @example 模块内部上下文
|
|
48
|
+
* ```ts
|
|
49
|
+
* const safe = sanitizeImageSrc('https://example.com/image.png')
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
11
52
|
export declare function sanitizeImageSrc(src: string | null | undefined): string;
|
|
12
53
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
54
|
+
* 消毒 Markdown 中嵌入的原始 HTML 片段。
|
|
55
|
+
* 只重建白名单标签,其余内容保持转义。
|
|
56
|
+
* @param fragment - 待消毒的 HTML 片段。
|
|
57
|
+
* @returns 仅保留白名单标签和安全属性的 HTML。
|
|
58
|
+
*
|
|
59
|
+
* @example 模块内部上下文
|
|
60
|
+
* ```ts
|
|
61
|
+
* const safe = sanitizeMarkdownHtml('<p onclick="alert(1)">正文</p>')
|
|
62
|
+
* ```
|
|
15
63
|
*/
|
|
16
64
|
export declare function sanitizeMarkdownHtml(fragment: string): string;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @h-ai/ui —
|
|
2
|
+
* @h-ai/ui — Markdown 渲染的安全 HTML 工具。
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Markdown 默认将原始 HTML 当作纯文本转义。
|
|
5
|
+
* 显式允许 HTML 后,也只重建白名单中的安全标签与
|
|
6
|
+
* 属性;不支持或危险的标记仍按文字转义。
|
|
7
7
|
*/
|
|
8
8
|
const SAFE_LINK_HREF_REGEX = /^(?:https?:\/\/|\/|#|mailto:)/i;
|
|
9
9
|
const SAFE_IMAGE_SRC_REGEX = /^(?:https?:\/\/|\/|data:image\/)/i;
|
|
@@ -63,6 +63,16 @@ const ALIGNABLE_HTML_TAGS = new Set([
|
|
|
63
63
|
'td',
|
|
64
64
|
'th',
|
|
65
65
|
]);
|
|
66
|
+
/**
|
|
67
|
+
* 将候选文本中的 HTML 特殊字符转义为可安全展示的纯文本。
|
|
68
|
+
* @param text - 待处理文本。
|
|
69
|
+
* @returns HTML 特殊字符被转义的字符串。
|
|
70
|
+
*
|
|
71
|
+
* @example 模块内部上下文
|
|
72
|
+
* ```ts
|
|
73
|
+
* const escaped = escapeHtml('<b>文本</b>')
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
66
76
|
export function escapeHtml(text) {
|
|
67
77
|
return text
|
|
68
78
|
.replace(/&/g, '&')
|
|
@@ -71,13 +81,44 @@ export function escapeHtml(text) {
|
|
|
71
81
|
.replace(/"/g, '"')
|
|
72
82
|
.replace(/'/g, ''');
|
|
73
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* 拒绝脚本等危险协议,只输出允许的链接地址。
|
|
86
|
+
* @param href - 待验证的链接候选地址。
|
|
87
|
+
* @returns 允许的链接地址,不安全或空输入返回空字符串。
|
|
88
|
+
*
|
|
89
|
+
* @example 模块内部上下文
|
|
90
|
+
* ```ts
|
|
91
|
+
* const safe = sanitizeLinkHref('javascript:alert(1)')
|
|
92
|
+
* // 不安全协议变为空字符串,不能直接渲染原始 href。
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
74
95
|
export function sanitizeLinkHref(href) {
|
|
75
96
|
const normalized = href?.trim() ?? '';
|
|
76
97
|
return SAFE_LINK_HREF_REGEX.test(normalized) ? normalized : '';
|
|
77
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* 识别外部链接,供渲染器添加相应的 rel/target 安全属性。
|
|
101
|
+
* @param href - 待验证的链接候选地址。
|
|
102
|
+
* @returns 地址是否为需要外链安全属性的外部链接。
|
|
103
|
+
*
|
|
104
|
+
* @example 模块内部上下文
|
|
105
|
+
* ```ts
|
|
106
|
+
* const external = isExternalLinkHref('https://example.com/help')
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
78
109
|
export function isExternalLinkHref(href) {
|
|
79
110
|
return /^https?:\/\//i.test(href);
|
|
80
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* 拒绝危险图片来源,保留允许的远程、相对或受控数据地址。
|
|
114
|
+
* @param src - 待验证的图片候选地址。
|
|
115
|
+
* @returns 允许的图片地址,不安全或空输入返回空字符串。
|
|
116
|
+
*
|
|
117
|
+
* @example 模块内部上下文
|
|
118
|
+
* ```ts
|
|
119
|
+
* const safe = sanitizeImageSrc('https://example.com/image.png')
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
81
122
|
export function sanitizeImageSrc(src) {
|
|
82
123
|
const normalized = src?.trim() ?? '';
|
|
83
124
|
return SAFE_IMAGE_SRC_REGEX.test(normalized) ? normalized : '';
|
|
@@ -265,8 +306,15 @@ function sanitizeHtmlTag(rawTag) {
|
|
|
265
306
|
: `<${tagName}${attributeText}>`;
|
|
266
307
|
}
|
|
267
308
|
/**
|
|
268
|
-
*
|
|
269
|
-
*
|
|
309
|
+
* 消毒 Markdown 中嵌入的原始 HTML 片段。
|
|
310
|
+
* 只重建白名单标签,其余内容保持转义。
|
|
311
|
+
* @param fragment - 待消毒的 HTML 片段。
|
|
312
|
+
* @returns 仅保留白名单标签和安全属性的 HTML。
|
|
313
|
+
*
|
|
314
|
+
* @example 模块内部上下文
|
|
315
|
+
* ```ts
|
|
316
|
+
* const safe = sanitizeMarkdownHtml('<p onclick="alert(1)">正文</p>')
|
|
317
|
+
* ```
|
|
270
318
|
*/
|
|
271
319
|
export function sanitizeMarkdownHtml(fragment) {
|
|
272
320
|
if (!fragment) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<!--
|
|
2
|
+
@component AiTableEditor
|
|
2
3
|
=============================================================================
|
|
3
4
|
@h-ai/ui - AiTableEditor 组件
|
|
4
5
|
=============================================================================
|
|
@@ -10,6 +11,16 @@
|
|
|
10
11
|
|
|
11
12
|
使用 Svelte 5 Runes ($props, $state, $derived, $effect)
|
|
12
13
|
=============================================================================
|
|
14
|
+
|
|
15
|
+
@example
|
|
16
|
+
```ts
|
|
17
|
+
import { mount, unmount } from 'svelte'
|
|
18
|
+
import type { ComponentProps } from 'svelte'
|
|
19
|
+
import { AiTableEditor } from '@h-ai/ui'
|
|
20
|
+
const props: ComponentProps<typeof AiTableEditor> = { title: '销量', tableData: { table_columns: [{ key: 'sales', label: '销量', type: 'number' }], table_rows: [{ row_id: 'r1', sales: 42 }] } }
|
|
21
|
+
const component = mount(AiTableEditor, { target: document.body, props })
|
|
22
|
+
await unmount(component)
|
|
23
|
+
```
|
|
13
24
|
-->
|
|
14
25
|
<script lang='ts'>
|
|
15
26
|
import type { DataAttributes } from '../../../../types.js'
|
|
@@ -28,6 +39,14 @@
|
|
|
28
39
|
import { cn, getDataAttributes } from '../../../../utils.js'
|
|
29
40
|
import AiDocumentDownloadMenu from '../AiDocumentDownloadMenu.svelte'
|
|
30
41
|
|
|
42
|
+
/**
|
|
43
|
+
* 流式表格 JSON 中提取的数组片段;complete=false 时不能当作完整最终数据。
|
|
44
|
+
*
|
|
45
|
+
* @example 模块内部上下文
|
|
46
|
+
* ```ts
|
|
47
|
+
* const example: ExtractedArrayChunk = { source: '[{"row_id":"r1"}]', complete: true }
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
31
50
|
interface ExtractedArrayChunk {
|
|
32
51
|
/** 从原始字符串里截取到的数组片段(可能是不完整数组)。 */
|
|
33
52
|
source: string
|
|
@@ -35,8 +54,24 @@
|
|
|
35
54
|
complete: boolean
|
|
36
55
|
}
|
|
37
56
|
|
|
57
|
+
/**
|
|
58
|
+
* 拖放行相对目标行的插入方向。
|
|
59
|
+
*
|
|
60
|
+
* @example 模块内部上下文
|
|
61
|
+
* ```ts
|
|
62
|
+
* const example: AiTableRowDropPosition = 'before'
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
38
65
|
type AiTableRowDropPosition = 'before' | 'after'
|
|
39
66
|
|
|
67
|
+
/**
|
|
68
|
+
* 表格拖放产生的新快照和前后索引;未变更时 nextData 为 null。
|
|
69
|
+
*
|
|
70
|
+
* @example 模块内部上下文
|
|
71
|
+
* ```ts
|
|
72
|
+
* const example: ReorderedTableResult = { nextData: { table_columns: [{ key: 'sales', label: '销量', type: 'number' }], table_rows: [{ row_id: 'r1', sales: 42 }] }, fromIndex: 1, toIndex: 0 }
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
40
75
|
interface ReorderedTableResult {
|
|
41
76
|
/** 重排后的完整表格快照;未真正变更顺序时为 `null`。 */
|
|
42
77
|
nextData: AiTableData | null
|
|
@@ -683,6 +718,19 @@
|
|
|
683
718
|
clearScheduledCellChange()
|
|
684
719
|
}
|
|
685
720
|
|
|
721
|
+
/**
|
|
722
|
+
* 立即交付尚在防抖窗口中的单元格修改,关闭或保存前可通过组件引用调用。
|
|
723
|
+
* @returns 无返回值;立即交付最后一份待发送的单元格修改。
|
|
724
|
+
*
|
|
725
|
+
* @example
|
|
726
|
+
* ```ts
|
|
727
|
+
* import { mount, unmount } from 'svelte'
|
|
728
|
+
* import { AiTableEditor } from '@h-ai/ui'
|
|
729
|
+
* const editor = mount(AiTableEditor, { target: document.body, props: { tableData: { table_columns: [{ key: 'sales', label: '销量', type: 'number' }], table_rows: [{ row_id: 'r1', sales: 42 }] } } })
|
|
730
|
+
* editor.flushPendingTableChange()
|
|
731
|
+
* await unmount(editor)
|
|
732
|
+
* ```
|
|
733
|
+
*/
|
|
686
734
|
export function flushPendingTableChange(): void {
|
|
687
735
|
const pendingPayload = pendingCellChangePayload
|
|
688
736
|
if (!pendingPayload) {
|
|
@@ -1,6 +1,30 @@
|
|
|
1
1
|
import type { DataAttributes } from '../../../../types.js';
|
|
2
2
|
import type { AiTableEditorProps } from './table-types.js';
|
|
3
3
|
type $$ComponentProps = AiTableEditorProps & DataAttributes;
|
|
4
|
+
/**
|
|
5
|
+
* AiTableEditor
|
|
6
|
+
* =============================================================================
|
|
7
|
+
* @h-ai/ui - AiTableEditor 组件
|
|
8
|
+
* =============================================================================
|
|
9
|
+
* 面向 AI 场景的可编辑表格查看器,支持:
|
|
10
|
+
* - 从结构化数据或 JSON 文本渲染表格
|
|
11
|
+
* - 流式残缺 JSON 的增量容错解析(列/行可分段出现)
|
|
12
|
+
* - 单元格编辑、行新增、行删除、拖拽排序
|
|
13
|
+
* - 复制表格(TSV)与下载表格(CSV)
|
|
14
|
+
*
|
|
15
|
+
* 使用 Svelte 5 Runes ($props, $state, $derived, $effect)
|
|
16
|
+
* =============================================================================
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* import { mount, unmount } from 'svelte'
|
|
21
|
+
* import type { ComponentProps } from 'svelte'
|
|
22
|
+
* import { AiTableEditor } from '@h-ai/ui'
|
|
23
|
+
* const props: ComponentProps<typeof AiTableEditor> = { title: '销量', tableData: { table_columns: [{ key: 'sales', label: '销量', type: 'number' }], table_rows: [{ row_id: 'r1', sales: 42 }] } }
|
|
24
|
+
* const component = mount(AiTableEditor, { target: document.body, props })
|
|
25
|
+
* await unmount(component)
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
4
28
|
declare const AiTableEditor: import("svelte").Component<$$ComponentProps, {
|
|
5
29
|
flushPendingTableChange: () => void;
|
|
6
30
|
}, "editorScrollHost">;
|