@h-ai/ui 0.1.0-alpha.29 → 0.1.0-alpha.31
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.md +50 -3
- package/dist/components/compounds/Accordion.svelte +6 -3
- package/dist/components/compounds/Accordion.svelte.d.ts +3 -1
- package/dist/components/compounds/ActionSheet.svelte +11 -8
- package/dist/components/compounds/ActionSheet.svelte.d.ts +3 -1
- package/dist/components/compounds/Alert.svelte +6 -4
- package/dist/components/compounds/Alert.svelte.d.ts +3 -2
- package/dist/components/compounds/AppBar.svelte +13 -9
- package/dist/components/compounds/AppBar.svelte.d.ts +3 -1
- package/dist/components/compounds/BottomNav.svelte +13 -10
- package/dist/components/compounds/BottomNav.svelte.d.ts +3 -1
- package/dist/components/compounds/Breadcrumb.svelte +6 -4
- package/dist/components/compounds/Breadcrumb.svelte.d.ts +3 -2
- package/dist/components/compounds/Calendar.svelte +7 -2
- package/dist/components/compounds/Calendar.svelte.d.ts +3 -1
- package/dist/components/compounds/Card.svelte +6 -4
- package/dist/components/compounds/Card.svelte.d.ts +3 -2
- package/dist/components/compounds/Combobox.svelte +6 -2
- package/dist/components/compounds/Combobox.svelte.d.ts +3 -1
- package/dist/components/compounds/Confirm.svelte +9 -7
- package/dist/components/compounds/Confirm.svelte.d.ts +3 -2
- package/dist/components/compounds/DataTable.svelte +6 -2
- package/dist/components/compounds/DataTable.svelte.d.ts +2 -1
- package/dist/components/compounds/DatePicker.svelte +7 -2
- package/dist/components/compounds/DatePicker.svelte.d.ts +3 -1
- package/dist/components/compounds/Drawer.svelte +6 -4
- package/dist/components/compounds/Drawer.svelte.d.ts +3 -2
- package/dist/components/compounds/Dropdown.svelte +6 -4
- package/dist/components/compounds/Dropdown.svelte.d.ts +3 -2
- package/dist/components/compounds/Empty.svelte +6 -4
- package/dist/components/compounds/Empty.svelte.d.ts +3 -2
- package/dist/components/compounds/Form.svelte +11 -9
- package/dist/components/compounds/Form.svelte.d.ts +3 -2
- package/dist/components/compounds/FormField.svelte +6 -4
- package/dist/components/compounds/FormField.svelte.d.ts +3 -2
- package/dist/components/compounds/InfiniteScroll.svelte +10 -7
- package/dist/components/compounds/InfiniteScroll.svelte.d.ts +3 -1
- package/dist/components/compounds/MessageBoxContainer.svelte +6 -1
- package/dist/components/compounds/MessageBoxContainer.svelte.d.ts +3 -17
- package/dist/components/compounds/MessageBoxDialog.svelte +9 -7
- package/dist/components/compounds/MessageBoxDialog.svelte.d.ts +2 -1
- package/dist/components/compounds/MessageContainer.svelte +43 -66
- package/dist/components/compounds/MessageContainer.svelte.d.ts +2 -1
- package/dist/components/compounds/Modal.svelte +29 -43
- package/dist/components/compounds/Modal.svelte.d.ts +3 -2
- package/dist/components/compounds/PageHeader.svelte +6 -2
- package/dist/components/compounds/PageHeader.svelte.d.ts +3 -1
- package/dist/components/compounds/Pagination.svelte +6 -4
- package/dist/components/compounds/Pagination.svelte.d.ts +3 -2
- package/dist/components/compounds/Popover.svelte +10 -8
- package/dist/components/compounds/Popover.svelte.d.ts +3 -2
- package/dist/components/compounds/PullRefresh.svelte +11 -8
- package/dist/components/compounds/PullRefresh.svelte.d.ts +3 -1
- package/dist/components/compounds/Result.svelte +6 -4
- package/dist/components/compounds/Result.svelte.d.ts +3 -2
- package/dist/components/compounds/SafeArea.svelte +6 -3
- package/dist/components/compounds/SafeArea.svelte.d.ts +3 -1
- package/dist/components/compounds/Skeleton.svelte +6 -4
- package/dist/components/compounds/Skeleton.svelte.d.ts +3 -2
- package/dist/components/compounds/Steps.svelte +6 -4
- package/dist/components/compounds/Steps.svelte.d.ts +3 -2
- package/dist/components/compounds/SwipeCell.svelte +6 -3
- package/dist/components/compounds/SwipeCell.svelte.d.ts +3 -1
- package/dist/components/compounds/Tabs.svelte +6 -4
- package/dist/components/compounds/Tabs.svelte.d.ts +3 -2
- package/dist/components/compounds/TagInput.svelte +11 -9
- package/dist/components/compounds/TagInput.svelte.d.ts +3 -2
- package/dist/components/compounds/Timeline.svelte +6 -3
- package/dist/components/compounds/Timeline.svelte.d.ts +3 -1
- package/dist/components/compounds/ToastContainer.svelte +6 -2
- package/dist/components/compounds/ToastContainer.svelte.d.ts +2 -1
- package/dist/components/compounds/Tooltip.svelte +6 -4
- package/dist/components/compounds/Tooltip.svelte.d.ts +3 -2
- package/dist/components/primitives/Avatar.svelte +6 -4
- package/dist/components/primitives/Avatar.svelte.d.ts +3 -2
- package/dist/components/primitives/Badge.svelte +6 -4
- package/dist/components/primitives/Badge.svelte.d.ts +3 -2
- package/dist/components/primitives/BareButton.svelte +15 -12
- package/dist/components/primitives/BareButton.svelte.d.ts +3 -2
- package/dist/components/primitives/BareInput.svelte +37 -34
- package/dist/components/primitives/BareInput.svelte.d.ts +3 -2
- package/dist/components/primitives/Button.svelte +12 -10
- package/dist/components/primitives/Button.svelte.d.ts +3 -2
- package/dist/components/primitives/Checkbox.svelte +6 -4
- package/dist/components/primitives/Checkbox.svelte.d.ts +3 -2
- package/dist/components/primitives/IconButton.svelte +6 -4
- package/dist/components/primitives/IconButton.svelte.d.ts +3 -2
- package/dist/components/primitives/Input.svelte +6 -4
- package/dist/components/primitives/Input.svelte.d.ts +3 -2
- package/dist/components/primitives/Progress.svelte +6 -4
- package/dist/components/primitives/Progress.svelte.d.ts +3 -2
- package/dist/components/primitives/Radio.svelte +6 -4
- package/dist/components/primitives/Radio.svelte.d.ts +2 -2
- package/dist/components/primitives/Range.svelte +6 -3
- package/dist/components/primitives/Range.svelte.d.ts +3 -1
- package/dist/components/primitives/Rating.svelte +6 -3
- package/dist/components/primitives/Rating.svelte.d.ts +3 -1
- package/dist/components/primitives/Select.svelte +255 -48
- package/dist/components/primitives/Select.svelte.d.ts +2 -2
- package/dist/components/primitives/Spinner.svelte +6 -4
- package/dist/components/primitives/Spinner.svelte.d.ts +3 -2
- package/dist/components/primitives/Switch.svelte +6 -4
- package/dist/components/primitives/Switch.svelte.d.ts +3 -2
- package/dist/components/primitives/Tag.svelte +6 -4
- package/dist/components/primitives/Tag.svelte.d.ts +3 -2
- package/dist/components/primitives/Textarea.svelte +34 -19
- package/dist/components/primitives/Textarea.svelte.d.ts +3 -2
- package/dist/components/primitives/ToggleCheckbox.svelte +13 -10
- package/dist/components/primitives/ToggleCheckbox.svelte.d.ts +3 -2
- package/dist/components/primitives/ToggleInput.svelte +13 -10
- package/dist/components/primitives/ToggleInput.svelte.d.ts +3 -2
- package/dist/components/primitives/ToggleRadio.svelte +13 -10
- package/dist/components/primitives/ToggleRadio.svelte.d.ts +3 -2
- package/dist/components/scenes/ai/AiDocumentDownloadMenu.svelte +8 -5
- package/dist/components/scenes/ai/AiDocumentDownloadMenu.svelte.d.ts +3 -1
- package/dist/components/scenes/ai/AiDocumentEditor.svelte +40 -10
- package/dist/components/scenes/ai/AiDocumentEditor.svelte.d.ts +3 -1
- package/dist/components/scenes/ai/MarkdownRenderer.svelte +49 -7
- package/dist/components/scenes/ai/MarkdownRenderer.svelte.d.ts +3 -1
- package/dist/components/scenes/ai/document-parse.d.ts +2 -0
- package/dist/components/scenes/ai/document-parse.js +16 -17
- package/dist/components/scenes/ai/document-types.d.ts +6 -1
- package/dist/components/scenes/ai/markdown-parse.d.ts +2 -0
- package/dist/components/scenes/ai/markdown-parse.js +17 -20
- package/dist/components/scenes/ai/safe-html.d.ts +16 -0
- package/dist/components/scenes/ai/safe-html.js +284 -0
- package/dist/components/scenes/ai/table/AiTableEditor.svelte +6 -3
- package/dist/components/scenes/ai/table/AiTableEditor.svelte.d.ts +3 -1
- package/dist/components/scenes/ai/table/table-types.d.ts +2 -1
- package/dist/components/scenes/app/FeedbackModal.svelte +5 -2
- package/dist/components/scenes/app/FeedbackModal.svelte.d.ts +3 -1
- package/dist/components/scenes/app/LanguageSwitch.svelte +6 -2
- package/dist/components/scenes/app/LanguageSwitch.svelte.d.ts +3 -1
- package/dist/components/scenes/app/SettingsLayout.svelte +6 -3
- package/dist/components/scenes/app/SettingsLayout.svelte.d.ts +2 -1
- package/dist/components/scenes/app/SettingsModal.svelte +6 -3
- package/dist/components/scenes/app/SettingsModal.svelte.d.ts +3 -1
- package/dist/components/scenes/app/ThemeColorPicker.svelte +6 -3
- package/dist/components/scenes/app/ThemeColorPicker.svelte.d.ts +3 -1
- package/dist/components/scenes/app/ThemeSelector.svelte +6 -3
- package/dist/components/scenes/app/ThemeSelector.svelte.d.ts +3 -1
- package/dist/components/scenes/app/ThemeToggle.svelte +6 -2
- package/dist/components/scenes/app/ThemeToggle.svelte.d.ts +3 -1
- package/dist/components/scenes/crud/CrudDeleteConfirm.svelte +16 -11
- package/dist/components/scenes/crud/CrudDeleteConfirm.svelte.d.ts +2 -1
- package/dist/components/scenes/crud/CrudDetailDrawer.svelte +6 -3
- package/dist/components/scenes/crud/CrudDetailDrawer.svelte.d.ts +2 -2
- package/dist/components/scenes/crud/CrudDetailPanel.svelte +6 -3
- package/dist/components/scenes/crud/CrudDetailPanel.svelte.d.ts +2 -2
- package/dist/components/scenes/crud/CrudEditPanel.svelte +6 -3
- package/dist/components/scenes/crud/CrudEditPanel.svelte.d.ts +2 -2
- package/dist/components/scenes/crud/CrudFilterBar.svelte +6 -2
- package/dist/components/scenes/crud/CrudFilterBar.svelte.d.ts +2 -1
- package/dist/components/scenes/crud/CrudPage.svelte +6 -2
- package/dist/components/scenes/crud/CrudPage.svelte.d.ts +2 -1
- package/dist/components/scenes/crud/crud-types.d.ts +2 -2
- package/dist/components/scenes/crypto/EncryptedInput.svelte +6 -3
- package/dist/components/scenes/crypto/EncryptedInput.svelte.d.ts +3 -2
- package/dist/components/scenes/crypto/HashDisplay.svelte +6 -3
- package/dist/components/scenes/crypto/HashDisplay.svelte.d.ts +3 -1
- package/dist/components/scenes/crypto/SignatureDisplay.svelte +6 -3
- package/dist/components/scenes/crypto/SignatureDisplay.svelte.d.ts +3 -1
- package/dist/components/scenes/error/ErrorPage.svelte +6 -3
- package/dist/components/scenes/error/ErrorPage.svelte.d.ts +2 -1
- package/dist/components/scenes/iam/AuthShell.svelte +6 -3
- package/dist/components/scenes/iam/AuthShell.svelte.d.ts +2 -1
- package/dist/components/scenes/iam/ChangePasswordForm.svelte +6 -3
- package/dist/components/scenes/iam/ChangePasswordForm.svelte.d.ts +3 -1
- package/dist/components/scenes/iam/ForgotPasswordForm.svelte +6 -3
- package/dist/components/scenes/iam/ForgotPasswordForm.svelte.d.ts +3 -1
- package/dist/components/scenes/iam/LoginForm.svelte +6 -3
- package/dist/components/scenes/iam/LoginForm.svelte.d.ts +3 -1
- package/dist/components/scenes/iam/PasswordInput.svelte +6 -4
- package/dist/components/scenes/iam/PasswordInput.svelte.d.ts +3 -2
- package/dist/components/scenes/iam/RegisterForm.svelte +6 -4
- package/dist/components/scenes/iam/RegisterForm.svelte.d.ts +3 -1
- package/dist/components/scenes/iam/ResetPasswordForm.svelte +6 -3
- package/dist/components/scenes/iam/ResetPasswordForm.svelte.d.ts +3 -1
- package/dist/components/scenes/iam/UserProfile.svelte +6 -3
- package/dist/components/scenes/iam/UserProfile.svelte.d.ts +3 -1
- package/dist/components/scenes/storage/AvatarUpload.svelte +11 -8
- package/dist/components/scenes/storage/AvatarUpload.svelte.d.ts +3 -1
- package/dist/components/scenes/storage/FileList.svelte +6 -3
- package/dist/components/scenes/storage/FileList.svelte.d.ts +3 -1
- package/dist/components/scenes/storage/FileUpload.svelte +6 -3
- package/dist/components/scenes/storage/FileUpload.svelte.d.ts +3 -1
- package/dist/components/scenes/storage/ImageUpload.svelte +12 -9
- package/dist/components/scenes/storage/ImageUpload.svelte.d.ts +3 -1
- package/dist/components/scenes/types.d.ts +20 -16
- package/dist/styles/global.css +5 -0
- package/dist/types.d.ts +48 -41
- package/dist/utils.d.ts +6 -1
- package/dist/utils.js +16 -1
- package/package.json +2 -2
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
=============================================================================
|
|
9
9
|
-->
|
|
10
10
|
<script lang='ts'>
|
|
11
|
-
import type { ToggleCheckboxProps } from '../../types.js'
|
|
11
|
+
import type { DataAttributes, ToggleCheckboxProps } from '../../types.js'
|
|
12
|
+
import { getDataAttributes } from '../../utils.js'
|
|
12
13
|
|
|
13
14
|
let {
|
|
14
15
|
checked = $bindable(false),
|
|
@@ -17,20 +18,22 @@
|
|
|
17
18
|
disabled = false,
|
|
18
19
|
class: className = '',
|
|
19
20
|
onchange,
|
|
20
|
-
|
|
21
|
+
...restProps
|
|
22
|
+
}: ToggleCheckboxProps & DataAttributes = $props()
|
|
21
23
|
|
|
24
|
+
const dataAttributes = $derived(getDataAttributes(restProps))
|
|
22
25
|
function handleChange(e: Event & { currentTarget: HTMLInputElement }) {
|
|
23
26
|
checked = e.currentTarget.checked
|
|
24
27
|
onchange?.(checked)
|
|
25
28
|
}
|
|
26
29
|
</script>
|
|
27
30
|
|
|
28
|
-
<input
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
<input {...dataAttributes}
|
|
32
|
+
{id}
|
|
33
|
+
{name}
|
|
34
|
+
type='checkbox'
|
|
35
|
+
class={className}
|
|
36
|
+
{disabled}
|
|
37
|
+
checked={checked}
|
|
38
|
+
onchange={handleChange}
|
|
36
39
|
/>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { ToggleCheckboxProps } from '../../types.js';
|
|
2
|
-
|
|
1
|
+
import type { DataAttributes, ToggleCheckboxProps } from '../../types.js';
|
|
2
|
+
type $$ComponentProps = ToggleCheckboxProps & DataAttributes;
|
|
3
|
+
declare const ToggleCheckbox: import("svelte").Component<$$ComponentProps, {}, "checked">;
|
|
3
4
|
type ToggleCheckbox = ReturnType<typeof ToggleCheckbox>;
|
|
4
5
|
export default ToggleCheckbox;
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
=============================================================================
|
|
9
9
|
-->
|
|
10
10
|
<script lang='ts'>
|
|
11
|
-
import type { ToggleCheckboxProps } from '../../types.js'
|
|
11
|
+
import type { DataAttributes, ToggleCheckboxProps } from '../../types.js'
|
|
12
|
+
import { getDataAttributes } from '../../utils.js'
|
|
12
13
|
|
|
13
14
|
let {
|
|
14
15
|
checked = $bindable(false),
|
|
@@ -17,20 +18,22 @@
|
|
|
17
18
|
disabled = false,
|
|
18
19
|
class: className = '',
|
|
19
20
|
onchange,
|
|
20
|
-
|
|
21
|
+
...restProps
|
|
22
|
+
}: ToggleCheckboxProps & DataAttributes = $props()
|
|
21
23
|
|
|
24
|
+
const dataAttributes = $derived(getDataAttributes(restProps))
|
|
22
25
|
function handleChange(e: Event & { currentTarget: HTMLInputElement }) {
|
|
23
26
|
checked = e.currentTarget.checked
|
|
24
27
|
onchange?.(checked)
|
|
25
28
|
}
|
|
26
29
|
</script>
|
|
27
30
|
|
|
28
|
-
<input
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
<input {...dataAttributes}
|
|
32
|
+
{id}
|
|
33
|
+
{name}
|
|
34
|
+
type='checkbox'
|
|
35
|
+
class={className}
|
|
36
|
+
{disabled}
|
|
37
|
+
checked={checked}
|
|
38
|
+
onchange={handleChange}
|
|
36
39
|
/>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { ToggleCheckboxProps } from '../../types.js';
|
|
2
|
-
|
|
1
|
+
import type { DataAttributes, ToggleCheckboxProps } from '../../types.js';
|
|
2
|
+
type $$ComponentProps = ToggleCheckboxProps & DataAttributes;
|
|
3
|
+
declare const ToggleInput: import("svelte").Component<$$ComponentProps, {}, "checked">;
|
|
3
4
|
type ToggleInput = ReturnType<typeof ToggleInput>;
|
|
4
5
|
export default ToggleInput;
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
=============================================================================
|
|
9
9
|
-->
|
|
10
10
|
<script lang='ts'>
|
|
11
|
-
import type { ToggleRadioProps } from '../../types.js'
|
|
11
|
+
import type { DataAttributes, ToggleRadioProps } from '../../types.js'
|
|
12
|
+
import { getDataAttributes } from '../../utils.js'
|
|
12
13
|
|
|
13
14
|
let {
|
|
14
15
|
checked = $bindable(false),
|
|
@@ -17,20 +18,22 @@
|
|
|
17
18
|
disabled = false,
|
|
18
19
|
class: className = '',
|
|
19
20
|
onchange,
|
|
20
|
-
|
|
21
|
+
...restProps
|
|
22
|
+
}: ToggleRadioProps & DataAttributes = $props()
|
|
21
23
|
|
|
24
|
+
const dataAttributes = $derived(getDataAttributes(restProps))
|
|
22
25
|
function handleChange(e: Event & { currentTarget: HTMLInputElement }) {
|
|
23
26
|
checked = e.currentTarget.checked
|
|
24
27
|
onchange?.(checked)
|
|
25
28
|
}
|
|
26
29
|
</script>
|
|
27
30
|
|
|
28
|
-
<input
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
<input {...dataAttributes}
|
|
32
|
+
{id}
|
|
33
|
+
{name}
|
|
34
|
+
type='radio'
|
|
35
|
+
class={className}
|
|
36
|
+
{disabled}
|
|
37
|
+
checked={checked}
|
|
38
|
+
onchange={handleChange}
|
|
36
39
|
/>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { ToggleRadioProps } from '../../types.js';
|
|
2
|
-
|
|
1
|
+
import type { DataAttributes, ToggleRadioProps } from '../../types.js';
|
|
2
|
+
type $$ComponentProps = ToggleRadioProps & DataAttributes;
|
|
3
|
+
declare const ToggleRadio: import("svelte").Component<$$ComponentProps, {}, "checked">;
|
|
3
4
|
type ToggleRadio = ReturnType<typeof ToggleRadio>;
|
|
4
5
|
export default ToggleRadio;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
<script lang='ts'>
|
|
2
|
+
import type { DataAttributes } from '../../../types.js'
|
|
2
3
|
import type {
|
|
3
4
|
MarkdownSourceKind,
|
|
4
5
|
MarkdownToolbarDownloadAction,
|
|
5
6
|
} from './document-types.js'
|
|
6
7
|
import { uiM } from '../../../messages.js'
|
|
7
|
-
import { cn } from '../../../utils.js'
|
|
8
|
+
import { cn, getDataAttributes } from '../../../utils.js'
|
|
8
9
|
import {
|
|
9
10
|
downloadAiDocument,
|
|
10
11
|
resolveDocumentDownloadActions,
|
|
@@ -62,8 +63,10 @@
|
|
|
62
63
|
triggerClass = '',
|
|
63
64
|
menuClass = '',
|
|
64
65
|
itemClass = '',
|
|
65
|
-
|
|
66
|
+
...restProps
|
|
67
|
+
}: AiDocumentDownloadMenuProps & DataAttributes = $props()
|
|
66
68
|
|
|
69
|
+
const dataAttributes = $derived(getDataAttributes(restProps))
|
|
67
70
|
// menuWrapEl 只负责识别外部点击,以便菜单展开后能自然收起。
|
|
68
71
|
let menuWrapEl: HTMLDivElement | undefined = $state()
|
|
69
72
|
// open 由组件内部维护,左右两侧可以直接复用,不需要额外再托管弹层状态。
|
|
@@ -118,9 +121,9 @@
|
|
|
118
121
|
}
|
|
119
122
|
</script>
|
|
120
123
|
|
|
121
|
-
<div
|
|
122
|
-
|
|
123
|
-
|
|
124
|
+
<div {...dataAttributes}
|
|
125
|
+
bind:this={menuWrapEl}
|
|
126
|
+
class={cn('hai-ai-download-menu', className)}
|
|
124
127
|
>
|
|
125
128
|
<button
|
|
126
129
|
type='button'
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { DataAttributes } from '../../../types.js';
|
|
1
2
|
import type { MarkdownSourceKind, MarkdownToolbarDownloadAction } from './document-types.js';
|
|
2
3
|
interface AiDocumentDownloadMenuProps {
|
|
3
4
|
/** 触发下载时导出的原始内容。 */
|
|
@@ -33,6 +34,7 @@ interface AiDocumentDownloadMenuProps {
|
|
|
33
34
|
/** 菜单项自定义类名。 */
|
|
34
35
|
itemClass?: string;
|
|
35
36
|
}
|
|
36
|
-
|
|
37
|
+
type $$ComponentProps = AiDocumentDownloadMenuProps & DataAttributes;
|
|
38
|
+
declare const AiDocumentDownloadMenu: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
37
39
|
type AiDocumentDownloadMenu = ReturnType<typeof AiDocumentDownloadMenu>;
|
|
38
40
|
export default AiDocumentDownloadMenu;
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
=============================================================================
|
|
12
12
|
-->
|
|
13
13
|
<script lang='ts'>
|
|
14
|
+
import type { DataAttributes } from '../../../types.js'
|
|
14
15
|
import type {
|
|
15
16
|
AiDocumentEditorProps,
|
|
16
17
|
MarkdownBlockFormatKind,
|
|
@@ -27,7 +28,7 @@
|
|
|
27
28
|
import { tick } from 'svelte'
|
|
28
29
|
import { writeTextToClipboard } from '../../../internal/browser-safety.js'
|
|
29
30
|
import { uiM } from '../../../messages.js'
|
|
30
|
-
import { cn } from '../../../utils.js'
|
|
31
|
+
import { cn, getDataAttributes } from '../../../utils.js'
|
|
31
32
|
import AiDocumentDownloadMenu from './AiDocumentDownloadMenu.svelte'
|
|
32
33
|
import {
|
|
33
34
|
createBuiltInCodePreview,
|
|
@@ -239,6 +240,8 @@
|
|
|
239
240
|
sourceKind = 'markdown',
|
|
240
241
|
// sourceKind=code 时的默认语言提示。
|
|
241
242
|
codeLanguage,
|
|
243
|
+
// 正文字号,number 会按 px 处理。
|
|
244
|
+
fontSize,
|
|
242
245
|
// 外层自定义类名。
|
|
243
246
|
class: className = '',
|
|
244
247
|
// 是否显示代码块复制按钮。
|
|
@@ -249,6 +252,8 @@
|
|
|
249
252
|
showCodePreviewToggle = false,
|
|
250
253
|
// 是否显式允许内置 HTML / JS / CSS 预览执行高风险内容。
|
|
251
254
|
allowUnsafeCodePreview = false,
|
|
255
|
+
// 是否按安全白名单解析原始 HTML 标签。
|
|
256
|
+
allowHtmlTags = false,
|
|
252
257
|
// 代码预览切换模式下展示在语言标签旁的提示文案。
|
|
253
258
|
codePreviewHint = '',
|
|
254
259
|
// 是否启用语法高亮。
|
|
@@ -319,8 +324,10 @@
|
|
|
319
324
|
oncopyselection,
|
|
320
325
|
// 选区注释回调。
|
|
321
326
|
onannotation,
|
|
322
|
-
|
|
327
|
+
...restProps
|
|
328
|
+
}: AiDocumentEditorProps & DataAttributes = $props()
|
|
323
329
|
|
|
330
|
+
const dataAttributes = $derived(getDataAttributes(restProps))
|
|
324
331
|
// outlineCollapsedInitialized 用来把 `initialOutlineCollapsed` 只消费一次,避免用户手动展开后又被 props 回写覆盖。
|
|
325
332
|
let outlineCollapsedInitialized = $state(false)
|
|
326
333
|
// 当前目录是否折叠。
|
|
@@ -409,6 +416,7 @@
|
|
|
409
416
|
codeViewPreviewLabel: uiM('file_list_preview'),
|
|
410
417
|
codePreviewHint: normalizedCodePreviewHint,
|
|
411
418
|
breaks,
|
|
419
|
+
allowHtmlTags,
|
|
412
420
|
}),
|
|
413
421
|
)
|
|
414
422
|
// html 是最终注入正文的内容。
|
|
@@ -463,6 +471,25 @@
|
|
|
463
471
|
editable ? 'hai-markdown-editable' : '',
|
|
464
472
|
),
|
|
465
473
|
)
|
|
474
|
+
const normalizedFontSize = $derived(resolveFontSize(fontSize))
|
|
475
|
+
const documentStyle = $derived(
|
|
476
|
+
normalizedFontSize
|
|
477
|
+
? `--hai-markdown-font-size:${normalizedFontSize};`
|
|
478
|
+
: undefined,
|
|
479
|
+
)
|
|
480
|
+
|
|
481
|
+
function resolveFontSize(value: AiDocumentEditorProps['fontSize']): string | undefined {
|
|
482
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
483
|
+
return `${value}px`
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
if (typeof value === 'string') {
|
|
487
|
+
const normalized = value.trim()
|
|
488
|
+
return normalized || undefined
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
return undefined
|
|
492
|
+
}
|
|
466
493
|
|
|
467
494
|
$effect(() => {
|
|
468
495
|
void html
|
|
@@ -933,6 +960,7 @@
|
|
|
933
960
|
enableHighlight,
|
|
934
961
|
showCopyButton: false,
|
|
935
962
|
breaks,
|
|
963
|
+
allowHtmlTags,
|
|
936
964
|
})
|
|
937
965
|
|
|
938
966
|
host.innerHTML = `<div class="hai-md-preview-card"><div class="hai-md-preview-head">${previewTitle}</div>${previewDesc}<div class="hai-md-preview-rendered">${markdownHtml}</div></div>`
|
|
@@ -2340,7 +2368,7 @@
|
|
|
2340
2368
|
}
|
|
2341
2369
|
</script>
|
|
2342
2370
|
|
|
2343
|
-
<section class={cn('hai-ai-doc-pane', className)}>
|
|
2371
|
+
<section {...dataAttributes} class={cn('hai-ai-doc-pane', className)}>
|
|
2344
2372
|
<div class='hai-ai-doc-shell'>
|
|
2345
2373
|
{#if showToolbar}
|
|
2346
2374
|
<header class='hai-ai-doc-topbar'>
|
|
@@ -3135,6 +3163,7 @@
|
|
|
3135
3163
|
<article
|
|
3136
3164
|
bind:this={previewHost}
|
|
3137
3165
|
class={readerDocumentClass}
|
|
3166
|
+
style={documentStyle}
|
|
3138
3167
|
contenteditable={editable}
|
|
3139
3168
|
role='document'
|
|
3140
3169
|
onmousemove={handlePreviewMouseMove}
|
|
@@ -3990,6 +4019,7 @@
|
|
|
3990
4019
|
}
|
|
3991
4020
|
|
|
3992
4021
|
.hai-markdown-document {
|
|
4022
|
+
font-size: var(--hai-markdown-font-size, 1rem);
|
|
3993
4023
|
width: 100%;
|
|
3994
4024
|
min-width: 0;
|
|
3995
4025
|
max-width: 52.5rem;
|
|
@@ -4042,29 +4072,29 @@
|
|
|
4042
4072
|
}
|
|
4043
4073
|
|
|
4044
4074
|
.hai-markdown :global(h1) {
|
|
4045
|
-
font-size: 2.
|
|
4075
|
+
font-size: 2.2em;
|
|
4046
4076
|
padding-bottom: 0.45em;
|
|
4047
4077
|
border-bottom: 1px solid oklch(var(--bc) / 0.12);
|
|
4048
4078
|
}
|
|
4049
4079
|
|
|
4050
4080
|
.hai-markdown :global(h2) {
|
|
4051
|
-
font-size: 1.
|
|
4081
|
+
font-size: 1.48em;
|
|
4052
4082
|
}
|
|
4053
4083
|
|
|
4054
4084
|
.hai-markdown :global(h3) {
|
|
4055
|
-
font-size: 1.
|
|
4085
|
+
font-size: 1.18em;
|
|
4056
4086
|
}
|
|
4057
4087
|
|
|
4058
4088
|
.hai-markdown :global(h4) {
|
|
4059
|
-
font-size: 1.
|
|
4089
|
+
font-size: 1.02em;
|
|
4060
4090
|
}
|
|
4061
4091
|
|
|
4062
4092
|
.hai-markdown :global(h5) {
|
|
4063
|
-
font-size: 0.
|
|
4093
|
+
font-size: 0.95em;
|
|
4064
4094
|
}
|
|
4065
4095
|
|
|
4066
4096
|
.hai-markdown :global(h6) {
|
|
4067
|
-
font-size: 0.
|
|
4097
|
+
font-size: 0.88em;
|
|
4068
4098
|
color: oklch(var(--bc) / 0.7);
|
|
4069
4099
|
}
|
|
4070
4100
|
|
|
@@ -4261,7 +4291,7 @@
|
|
|
4261
4291
|
font-family:
|
|
4262
4292
|
ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas,
|
|
4263
4293
|
'Liberation Mono', monospace;
|
|
4264
|
-
font-size: 0.
|
|
4294
|
+
font-size: 0.875em;
|
|
4265
4295
|
line-height: 1.45;
|
|
4266
4296
|
tab-size: 2;
|
|
4267
4297
|
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import type { DataAttributes } from '../../../types.js';
|
|
1
2
|
import type { AiDocumentEditorProps } from './document-types.js';
|
|
2
|
-
|
|
3
|
+
type $$ComponentProps = AiDocumentEditorProps & DataAttributes;
|
|
4
|
+
declare const AiDocumentEditor: import("svelte").Component<$$ComponentProps, {}, "editorScrollHost" | "previewHost">;
|
|
3
5
|
type AiDocumentEditor = ReturnType<typeof AiDocumentEditor>;
|
|
4
6
|
export default AiDocumentEditor;
|
|
@@ -16,24 +16,53 @@
|
|
|
16
16
|
=============================================================================
|
|
17
17
|
-->
|
|
18
18
|
<script lang='ts'>
|
|
19
|
+
import type { DataAttributes } from '../../../types.js'
|
|
19
20
|
import type { MarkdownRendererProps } from '../types.js'
|
|
20
21
|
import { writeTextToClipboard } from '../../../internal/browser-safety.js'
|
|
21
|
-
import { cn } from '../../../utils.js'
|
|
22
|
+
import { cn, getDataAttributes } from '../../../utils.js'
|
|
22
23
|
import { parseMarkdown } from './markdown-parse.js'
|
|
23
24
|
|
|
24
25
|
const {
|
|
25
26
|
content = '',
|
|
27
|
+
fontSize,
|
|
26
28
|
class: className = '',
|
|
27
29
|
showCopyButton = true,
|
|
28
30
|
enableHighlight = true,
|
|
29
31
|
breaks = true,
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
allowHtmlTags = false,
|
|
33
|
+
...restProps
|
|
34
|
+
}: MarkdownRendererProps & DataAttributes = $props()
|
|
35
|
+
|
|
36
|
+
const dataAttributes = $derived(getDataAttributes(restProps))
|
|
37
|
+
const normalizedFontSize = $derived(resolveFontSize(fontSize))
|
|
38
|
+
const markdownStyle = $derived(
|
|
39
|
+
normalizedFontSize
|
|
40
|
+
? `--hai-markdown-font-size:${normalizedFontSize};`
|
|
41
|
+
: undefined,
|
|
42
|
+
)
|
|
32
43
|
/** 解析后的 HTML */
|
|
33
44
|
const html = $derived(
|
|
34
|
-
parseMarkdown(content, {
|
|
45
|
+
parseMarkdown(content, {
|
|
46
|
+
enableHighlight,
|
|
47
|
+
showCopyButton,
|
|
48
|
+
breaks,
|
|
49
|
+
allowHtmlTags,
|
|
50
|
+
}),
|
|
35
51
|
)
|
|
36
52
|
|
|
53
|
+
function resolveFontSize(value: MarkdownRendererProps['fontSize']): string | undefined {
|
|
54
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
55
|
+
return `${value}px`
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (typeof value === 'string') {
|
|
59
|
+
const normalized = value.trim()
|
|
60
|
+
return normalized || undefined
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return undefined
|
|
64
|
+
}
|
|
65
|
+
|
|
37
66
|
/**
|
|
38
67
|
* 事件代理:处理代码块复制按钮点击
|
|
39
68
|
*/
|
|
@@ -62,10 +91,10 @@
|
|
|
62
91
|
}
|
|
63
92
|
</script>
|
|
64
93
|
|
|
65
|
-
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
66
|
-
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
67
94
|
<div
|
|
95
|
+
{...dataAttributes}
|
|
68
96
|
class={cn('hai-markdown', className)}
|
|
97
|
+
style={markdownStyle}
|
|
69
98
|
onclick={handleClick}
|
|
70
99
|
>
|
|
71
100
|
<!-- eslint-disable-next-line svelte/no-at-html-tags -- Markdown HTML 渲染 -->
|
|
@@ -80,6 +109,7 @@
|
|
|
80
109
|
* ========================================================================= */
|
|
81
110
|
|
|
82
111
|
.hai-markdown {
|
|
112
|
+
font-size: var(--hai-markdown-font-size, 1rem);
|
|
83
113
|
line-height: 1.75;
|
|
84
114
|
color: inherit;
|
|
85
115
|
word-wrap: break-word;
|
|
@@ -170,6 +200,18 @@
|
|
|
170
200
|
color: oklch(var(--bc) / 0.55);
|
|
171
201
|
}
|
|
172
202
|
|
|
203
|
+
.hai-markdown :global(u) {
|
|
204
|
+
text-decoration-thickness: 0.08em;
|
|
205
|
+
text-underline-offset: 0.14em;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
.hai-markdown :global(mark) {
|
|
209
|
+
padding: 0 0.12em;
|
|
210
|
+
border-radius: 0.25rem;
|
|
211
|
+
background: oklch(var(--wa, 0.9 0.14 90) / 0.34);
|
|
212
|
+
color: inherit;
|
|
213
|
+
}
|
|
214
|
+
|
|
173
215
|
/* ─── 行内代码 ─── */
|
|
174
216
|
|
|
175
217
|
.hai-markdown :global(:not(pre) > code) {
|
|
@@ -244,7 +286,7 @@
|
|
|
244
286
|
|
|
245
287
|
.hai-markdown :global(.hai-md-code-block code) {
|
|
246
288
|
font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace;
|
|
247
|
-
font-size: 0.
|
|
289
|
+
font-size: 0.875em;
|
|
248
290
|
line-height: 1.6;
|
|
249
291
|
tab-size: 2;
|
|
250
292
|
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import type { DataAttributes } from '../../../types.js';
|
|
1
2
|
import type { MarkdownRendererProps } from '../types.js';
|
|
2
|
-
|
|
3
|
+
type $$ComponentProps = MarkdownRendererProps & DataAttributes;
|
|
4
|
+
declare const MarkdownRenderer: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
3
5
|
type MarkdownRenderer = ReturnType<typeof MarkdownRenderer>;
|
|
4
6
|
export default MarkdownRenderer;
|
|
@@ -21,6 +21,8 @@ export interface MarkdownDocumentParseOptions {
|
|
|
21
21
|
codePreviewHint?: string;
|
|
22
22
|
/** Whether soft line breaks are converted to <br>. */
|
|
23
23
|
breaks?: boolean;
|
|
24
|
+
/** Whether raw HTML tags are parsed through a safe allowlist. */
|
|
25
|
+
allowHtmlTags?: boolean;
|
|
24
26
|
}
|
|
25
27
|
export interface MarkdownRenderResult {
|
|
26
28
|
/** Rendered HTML output. */
|
|
@@ -7,6 +7,7 @@ import { Marked } from 'marked';
|
|
|
7
7
|
import { createEditorMarkdownExtensions, extractPlainTextFromTokens, } from './editor-markdown-extensions.js';
|
|
8
8
|
import { highlightCode, isLanguageSupported } from './highlight.js';
|
|
9
9
|
import { isMermaidLanguage } from './mermaid-render.js';
|
|
10
|
+
import { escapeHtml, isExternalLinkHref, sanitizeImageSrc, sanitizeLinkHref, sanitizeMarkdownHtml, } from './safe-html.js';
|
|
10
11
|
/** Default parsing options for document mode. */
|
|
11
12
|
const DEFAULT_OPTIONS = {
|
|
12
13
|
enableHighlight: true,
|
|
@@ -17,19 +18,15 @@ const DEFAULT_OPTIONS = {
|
|
|
17
18
|
codeViewPreviewLabel: 'Preview',
|
|
18
19
|
codePreviewHint: '',
|
|
19
20
|
breaks: true,
|
|
21
|
+
allowHtmlTags: false,
|
|
20
22
|
};
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
.replace(/&/g, '&')
|
|
29
|
-
.replace(/</g, '<')
|
|
30
|
-
.replace(/>/g, '>')
|
|
31
|
-
.replace(/"/g, '"')
|
|
32
|
-
.replace(/'/g, ''');
|
|
23
|
+
function readHtmlTokenSource(token) {
|
|
24
|
+
if ('raw' in token && typeof token.raw === 'string') {
|
|
25
|
+
return token.raw;
|
|
26
|
+
}
|
|
27
|
+
return 'text' in token && typeof token.text === 'string'
|
|
28
|
+
? token.text
|
|
29
|
+
: '';
|
|
33
30
|
}
|
|
34
31
|
/**
|
|
35
32
|
* Create a URL-safe heading slug while keeping letters and digits.
|
|
@@ -166,16 +163,18 @@ function createRendererObject(options, state) {
|
|
|
166
163
|
+ `</div>`;
|
|
167
164
|
},
|
|
168
165
|
html(token) {
|
|
169
|
-
|
|
166
|
+
const source = readHtmlTokenSource(token);
|
|
167
|
+
return options.allowHtmlTags
|
|
168
|
+
? sanitizeMarkdownHtml(source)
|
|
169
|
+
: escapeHtml(source);
|
|
170
170
|
},
|
|
171
171
|
link({ href, title, tokens }) {
|
|
172
172
|
// text preserves inline markdown within the link label.
|
|
173
173
|
const text = this.parser.parseInline(tokens);
|
|
174
174
|
// safeHref strips potentially unsafe protocols.
|
|
175
|
-
const safeHref =
|
|
175
|
+
const safeHref = sanitizeLinkHref(href);
|
|
176
176
|
// isExternal controls whether target/_blank is added.
|
|
177
|
-
const isExternal = safeHref
|
|
178
|
-
&& (safeHref.startsWith('http://') || safeHref.startsWith('https://'));
|
|
177
|
+
const isExternal = safeHref && isExternalLinkHref(safeHref);
|
|
179
178
|
// attrs is the flattened HTML attribute string.
|
|
180
179
|
const attrs = [
|
|
181
180
|
`href="${escapeHtml(safeHref)}"`,
|
|
@@ -186,7 +185,7 @@ function createRendererObject(options, state) {
|
|
|
186
185
|
},
|
|
187
186
|
image({ href, title, text }) {
|
|
188
187
|
// safeSrc prevents dangerous image protocols.
|
|
189
|
-
const safeSrc =
|
|
188
|
+
const safeSrc = sanitizeImageSrc(href);
|
|
190
189
|
// attrs is the flattened HTML attribute string.
|
|
191
190
|
const attrs = [
|
|
192
191
|
`src="${escapeHtml(safeSrc)}"`,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { DataAttributes } from '../../../types.js';
|
|
1
2
|
/**
|
|
2
3
|
* Markdown source type, used to distinguish plain markdown, document panel, or code-only rendering.
|
|
3
4
|
*/
|
|
@@ -126,7 +127,7 @@ export interface MarkdownToolbarDownloadAction {
|
|
|
126
127
|
type BivariantCallback<Args extends unknown[], Return = void> = {
|
|
127
128
|
bivarianceHack: (...args: Args) => Return;
|
|
128
129
|
}['bivarianceHack'];
|
|
129
|
-
export interface AiDocumentEditorProps {
|
|
130
|
+
export interface AiDocumentEditorProps extends DataAttributes {
|
|
130
131
|
/** Markdown source content. */
|
|
131
132
|
content?: string;
|
|
132
133
|
/** Document title displayed in the header. */
|
|
@@ -135,6 +136,8 @@ export interface AiDocumentEditorProps {
|
|
|
135
136
|
sourceKind?: MarkdownSourceKind;
|
|
136
137
|
/** Default language when sourceKind is `code`. */
|
|
137
138
|
codeLanguage?: string;
|
|
139
|
+
/** Content font size. Numbers are interpreted as px. */
|
|
140
|
+
fontSize?: string | number;
|
|
138
141
|
/** Custom class for the outer container. */
|
|
139
142
|
class?: string;
|
|
140
143
|
/** Whether to show the copy button on code blocks. */
|
|
@@ -143,6 +146,8 @@ export interface AiDocumentEditorProps {
|
|
|
143
146
|
showRunButton?: boolean;
|
|
144
147
|
/** Whether to show the code/preview toggle on code blocks. */
|
|
145
148
|
showCodePreviewToggle?: boolean;
|
|
149
|
+
/** Whether to parse raw HTML tags through a safe allowlist. */
|
|
150
|
+
allowHtmlTags?: boolean;
|
|
146
151
|
/**
|
|
147
152
|
* 是否启用内置的高风险代码预览。
|
|
148
153
|
*
|