vue-stream-markdown 0.0.0-alpha.0 → 0.1.1
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 +18 -19
- package/dist/button-Bz0s_F3s.js +5 -0
- package/dist/{button-D8xx1WIP.js → button-dU2iYZBS.js} +1 -1
- package/dist/{code-CP6mPwkq.js → code-BfJ58lYO.js} +7 -7
- package/dist/code-block-BFUXyGQH.js +9 -0
- package/dist/{code-block-D2zjJAww.css → code-block-Bv8s2E8I.css} +5 -0
- package/dist/{code-block-C4D_QNTq.js → code-block-CZHD64ft.js} +5 -5
- package/dist/{composables-qhB1h_ed.js → composables-BwAY_BDJ.js} +124 -31
- package/dist/dropdown-RWgcV-8w.js +5 -0
- package/dist/error-component-CR9t-T1D.js +4 -0
- package/dist/{error-component-CzarUjhh.js → error-component-CiIR_1Cg.js} +1 -1
- package/dist/{image-heJSlrNv.js → image-BporCeem.js} +53 -49
- package/dist/index.d.ts +47 -33
- package/dist/index.js +23 -323
- package/dist/{inline-math-B4XO1wMP.js → inline-math-BfG4600m.js} +2 -2
- package/dist/{link-DOtoFtxu.js → link-D-OnakwP.js} +2 -2
- package/dist/{math-Byka28HI.js → math-CvKkCYb9.js} +2 -2
- package/dist/{mermaid-X0AFRzfF.js → mermaid-FgnWaZtT.js} +16 -8
- package/dist/{previewers-Drlf7IQF.js → previewers-CoU4RlpQ.js} +1 -1
- package/dist/{segmented-BEtO1eyl.js → segmented-Baxxk3UJ.js} +1 -1
- package/dist/segmented-C0uEAYuJ.js +6 -0
- package/dist/{shiki-vToM7Pz1.js → shiki-BHOZKGKS.js} +1 -1
- package/dist/{table-DjkiVd9L.js → table-B__TdLr7.js} +9 -4
- package/dist/{tooltip-RiXixMIt.js → tooltip-CA6Kp7Ek.js} +1 -1
- package/dist/tooltip-DoIUaZgq.js +4 -0
- package/dist/zoom-container-BPbftW_I.js +6 -0
- package/dist/{zoom-container-BfUO3Ocp.js → zoom-container-Dlqv-z-t.js} +2 -2
- package/package.json +15 -11
- package/dist/button-BClRCjnc.js +0 -5
- package/dist/code-block-Dzw63Lki.js +0 -9
- package/dist/dropdown-Ca_PKF_d.js +0 -5
- package/dist/error-component-CLEJmPmM.js +0 -4
- package/dist/segmented-CWoQcX-H.js +0 -6
- package/dist/tooltip-Ac_2x9ps.js +0 -4
- package/dist/zoom-container-BDEP09K9.js +0 -6
package/README.md
CHANGED
|
@@ -5,40 +5,38 @@
|
|
|
5
5
|
|
|
6
6
|
A markdown renderer specially optimized for streaming scenarios, inspired by [streamdown](https://streamdown.ai/). Designed to achieve smoother streaming rendering through syntax inference and highly customizable rendering elements.
|
|
7
7
|
|
|
8
|
+
```sh
|
|
9
|
+
pnpm add vue-stream-markdown
|
|
10
|
+
```
|
|
11
|
+
|
|
8
12
|
<br>
|
|
9
13
|
|
|
10
14
|
<p align="center">
|
|
11
|
-
<a href="
|
|
12
|
-
<a href="
|
|
15
|
+
<a href="https://docs-vue-stream-markdown.netlify.app/">📚 Documentation</a> |
|
|
16
|
+
<a href="https://play-vue-stream-markdown.netlify.app/">🤹♂️ Playground</a>
|
|
13
17
|
</p>
|
|
14
18
|
|
|
15
19
|
<br>
|
|
16
20
|
|
|
17
|
-
```sh
|
|
18
|
-
pnpm add vue-stream-markdown
|
|
19
|
-
```
|
|
20
|
-
|
|
21
21
|
<p align='center'>
|
|
22
22
|
<img src='./assets/screenshot.png' />
|
|
23
23
|
</p>
|
|
24
24
|
|
|
25
25
|
## Features
|
|
26
26
|
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
-
|
|
35
|
-
-
|
|
36
|
-
- 🛡️ **Content hardening & security** - Built-in protection against malicious Markdown with URL validation and protocol blocking
|
|
37
|
-
- 🔒 **TypeScript type safety** - Comprehensive type definitions with full IntelliSense support
|
|
27
|
+
- **Streaming-optimized rendering** - Incomplete node completion with loading states for images, tables, and code blocks to prevent visual jitter
|
|
28
|
+
- **Incremental rendering** - Leverages [Shiki](https://shiki.style/)'s `codeToTokens` API for token-level updates, reducing DOM recreation overhead
|
|
29
|
+
- **Progressive Mermaid rendering** - Throttled, streaming-friendly diagram rendering with loading states
|
|
30
|
+
- **Streaming LaTeX rendering** - Progressive math equation rendering with KaTeX support
|
|
31
|
+
- **Interactive controls** - Copy and download buttons for images, tables, and code blocks
|
|
32
|
+
- **Fully customizable** - Replace any AST node with your own Vue components
|
|
33
|
+
- **Theme-aware scoped styles** - Scoped styles under `.stream-markdown` with semantic `data-stream-markdown` attributes, following [shadcn/ui](https://ui.shadcn.com/) design system
|
|
34
|
+
- **Beautiful built-in typography** - No atomic CSS required (Tailwind/UnoCSS), self-contained styles
|
|
35
|
+
- **Content hardening & security** - Built-in protection against malicious Markdown with URL validation and protocol blocking
|
|
38
36
|
|
|
39
37
|
## Usage
|
|
40
38
|
|
|
41
|
-
For detailed usage and API documentation, please refer to the [Documentation](
|
|
39
|
+
For detailed usage and API documentation, please refer to the [Documentation](https://docs-vue-stream-markdown.netlify.app/).
|
|
42
40
|
|
|
43
41
|
```vue
|
|
44
42
|
<script setup lang="ts">
|
|
@@ -57,7 +55,7 @@ const content = ref('# Hello World\n\nThis is a markdown content.')
|
|
|
57
55
|
|
|
58
56
|
## Credit
|
|
59
57
|
|
|
60
|
-
This project is inspired by [streamdown](https://streamdown.ai/) and even uses
|
|
58
|
+
This project is inspired by [streamdown](https://streamdown.ai/) and even uses some source code from it.
|
|
61
59
|
|
|
62
60
|
This project also uses and benefits from:
|
|
63
61
|
|
|
@@ -65,6 +63,7 @@ This project also uses and benefits from:
|
|
|
65
63
|
- [Shiki](https://shiki.style/) - Beautiful syntax highlighting
|
|
66
64
|
- [Mermaid](https://mermaid.js.org/) - Diagramming and charting tool
|
|
67
65
|
- [KaTeX](https://katex.org/) - Fast math typesetting library for the web
|
|
66
|
+
- [Remend](https://github.com/vercel/streamdown/tree/main/packages/remend) - Intelligently parses and styles incomplete Markdown blocks
|
|
68
67
|
|
|
69
68
|
## Troubleshooting
|
|
70
69
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as tooltip_default } from "./tooltip-
|
|
1
|
+
import { t as tooltip_default } from "./tooltip-CA6Kp7Ek.js";
|
|
2
2
|
import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, defineComponent, h, normalizeClass, normalizeStyle, openBlock, ref, renderList, renderSlot, resolveDynamicComponent, toDisplayString, withCtx } from "vue";
|
|
3
3
|
|
|
4
4
|
//#region src/components/dropdown.vue?vue&type=script&setup=true&lang.ts
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import "./previewers-
|
|
2
|
-
import {
|
|
3
|
-
import "./tooltip-
|
|
4
|
-
import "./button-
|
|
1
|
+
import "./previewers-CoU4RlpQ.js";
|
|
2
|
+
import { i as useShiki } from "./composables-BwAY_BDJ.js";
|
|
3
|
+
import "./tooltip-CA6Kp7Ek.js";
|
|
4
|
+
import "./button-dU2iYZBS.js";
|
|
5
5
|
import "./modal-CuQR21UD.js";
|
|
6
|
-
import { t as code_block_default } from "./code-block-
|
|
7
|
-
import "./segmented-
|
|
6
|
+
import { t as code_block_default } from "./code-block-CZHD64ft.js";
|
|
7
|
+
import "./segmented-Baxxk3UJ.js";
|
|
8
8
|
import { computed, createBlock, createCommentVNode, defineAsyncComponent, defineComponent, mergeProps, normalizeProps, openBlock, resolveDynamicComponent, withCtx } from "vue";
|
|
9
9
|
|
|
10
10
|
//#region src/components/renderers/code/index.vue?vue&type=script&setup=true&lang.ts
|
|
@@ -83,7 +83,7 @@ var index_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCo
|
|
|
83
83
|
const { installed: hasShiki } = useShiki();
|
|
84
84
|
const components = {
|
|
85
85
|
vanilla: defineAsyncComponent(() => import("./vanilla-CA9QO96X.js")),
|
|
86
|
-
shiki: defineAsyncComponent(() => import("./shiki-
|
|
86
|
+
shiki: defineAsyncComponent(() => import("./shiki-BHOZKGKS.js"))
|
|
87
87
|
};
|
|
88
88
|
const component = computed(() => {
|
|
89
89
|
if (hasShiki.value) return components.shiki;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import "./previewers-CoU4RlpQ.js";
|
|
2
|
+
import "./composables-BwAY_BDJ.js";
|
|
3
|
+
import "./tooltip-CA6Kp7Ek.js";
|
|
4
|
+
import "./button-dU2iYZBS.js";
|
|
5
|
+
import "./modal-CuQR21UD.js";
|
|
6
|
+
import { t as code_block_default } from "./code-block-CZHD64ft.js";
|
|
7
|
+
import "./segmented-Baxxk3UJ.js";
|
|
8
|
+
|
|
9
|
+
export { code_block_default as default };
|
|
@@ -38,6 +38,11 @@
|
|
|
38
38
|
display: flex;
|
|
39
39
|
position: relative;
|
|
40
40
|
}
|
|
41
|
+
@media (max-width: 1024px) {
|
|
42
|
+
.stream-markdown [data-stream-markdown="code-block-header"] {
|
|
43
|
+
padding-inline: .5rem;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
41
46
|
.stream-markdown [data-stream-markdown="code-block-content"] {
|
|
42
47
|
overflow: auto;
|
|
43
48
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { t as CODE_PREVIEWERS } from "./previewers-
|
|
2
|
-
import {
|
|
3
|
-
import { t as button_default } from "./button-
|
|
1
|
+
import { t as CODE_PREVIEWERS } from "./previewers-CoU4RlpQ.js";
|
|
2
|
+
import { B as useContext, I as LANGUAGE_ALIAS, L as LANGUAGE_EXTENSIONS, M as ICONS, O as save, R as LANGUAGE_ICONS, a as useMermaid, u as useI18n, z as useControls } from "./composables-BwAY_BDJ.js";
|
|
3
|
+
import { t as button_default } from "./button-dU2iYZBS.js";
|
|
4
4
|
import { t as modal_default } from "./modal-CuQR21UD.js";
|
|
5
|
-
import { t as segmented_default } from "./segmented-
|
|
5
|
+
import { t as segmented_default } from "./segmented-Baxxk3UJ.js";
|
|
6
6
|
import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineAsyncComponent, defineComponent, mergeProps, normalizeClass, normalizeProps, openBlock, ref, renderList, renderSlot, resolveDynamicComponent, toDisplayString, toRefs, unref, useModel, vShow, watch, withCtx, withDirectives } from "vue";
|
|
7
7
|
import { useClipboard } from "@vueuse/core";
|
|
8
8
|
|
|
@@ -208,7 +208,7 @@ var index_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCo
|
|
|
208
208
|
const { t } = useI18n();
|
|
209
209
|
const { isControlEnabled } = useControls({ controls });
|
|
210
210
|
const { installed: hasMermaid } = useMermaid();
|
|
211
|
-
const CodeNode = defineAsyncComponent(() => import("./code-
|
|
211
|
+
const CodeNode = defineAsyncComponent(() => import("./code-BfJ58lYO.js"));
|
|
212
212
|
const { onCopied } = useContext();
|
|
213
213
|
const { copy, copied } = useClipboard({ legacy: true });
|
|
214
214
|
const { saveMermaid } = useMermaid();
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { computed, defineAsyncComponent, inject, provide, ref, unref, watch, watchEffect } from "vue";
|
|
1
|
+
import { computed, defineAsyncComponent, inject, onBeforeUnmount, provide, ref, toValue, unref, watch, watchEffect } from "vue";
|
|
2
|
+
import { useStyleTag } from "@vueuse/core";
|
|
2
3
|
import { setDefaultProps } from "vue-tippy";
|
|
3
4
|
import "tippy.js/dist/tippy.css";
|
|
4
5
|
import "tippy.js/themes/light.css";
|
|
@@ -38,22 +39,31 @@ function useContext() {
|
|
|
38
39
|
function useControls(options) {
|
|
39
40
|
const controls = computed(() => unref(options.controls) ?? true);
|
|
40
41
|
function isControlEnabled(key) {
|
|
42
|
+
try {
|
|
43
|
+
return getControlValue(key) !== false;
|
|
44
|
+
} catch {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function getControlValue(key) {
|
|
41
49
|
try {
|
|
42
50
|
const config = controls.value;
|
|
43
51
|
if (typeof config === "boolean") return config;
|
|
44
52
|
const path = key.split(".");
|
|
45
53
|
let current = config;
|
|
46
54
|
for (const part of path) {
|
|
47
|
-
if (current === void 0 || current === null || typeof current !== "object") return
|
|
55
|
+
if (current === void 0 || current === null || typeof current !== "object") return void 0;
|
|
48
56
|
current = current[part];
|
|
49
|
-
if (typeof current === "boolean") return current;
|
|
50
57
|
}
|
|
51
|
-
return current
|
|
58
|
+
return current;
|
|
52
59
|
} catch {
|
|
53
|
-
return
|
|
60
|
+
return;
|
|
54
61
|
}
|
|
55
62
|
}
|
|
56
|
-
return {
|
|
63
|
+
return {
|
|
64
|
+
isControlEnabled,
|
|
65
|
+
getControlValue
|
|
66
|
+
};
|
|
57
67
|
}
|
|
58
68
|
|
|
59
69
|
//#endregion
|
|
@@ -64,7 +74,6 @@ const LANGUAGE_ALIAS = {};
|
|
|
64
74
|
const LANGUAGE_EXTENSIONS = {
|
|
65
75
|
"1c-query": "1cq",
|
|
66
76
|
"1c": "1c",
|
|
67
|
-
"文言": "wy",
|
|
68
77
|
"abap": "abap",
|
|
69
78
|
"actionscript-3": "as",
|
|
70
79
|
"ada": "ada",
|
|
@@ -367,7 +376,8 @@ const LANGUAGE_EXTENSIONS = {
|
|
|
367
376
|
"yml": "yml",
|
|
368
377
|
"zenscript": "zs",
|
|
369
378
|
"zig": "zig",
|
|
370
|
-
"zsh": "zsh"
|
|
379
|
+
"zsh": "zsh",
|
|
380
|
+
"文言": "wy"
|
|
371
381
|
};
|
|
372
382
|
const LANGUAGE_ICONS = {
|
|
373
383
|
"adoc": defineAsyncComponent(() => import("./asciidoc-BabXBDAL.js")),
|
|
@@ -576,6 +586,42 @@ const ICONS = {
|
|
|
576
586
|
zoomOut: defineAsyncComponent(() => import("./zoomOut-qlzQyQli.js"))
|
|
577
587
|
};
|
|
578
588
|
|
|
589
|
+
//#endregion
|
|
590
|
+
//#region src/constants/theme.ts
|
|
591
|
+
const SHADCN_SCHEMAS = [
|
|
592
|
+
"background",
|
|
593
|
+
"foreground",
|
|
594
|
+
"card",
|
|
595
|
+
"card-foreground",
|
|
596
|
+
"popover",
|
|
597
|
+
"popover-foreground",
|
|
598
|
+
"primary",
|
|
599
|
+
"primary-foreground",
|
|
600
|
+
"secondary",
|
|
601
|
+
"secondary-foreground",
|
|
602
|
+
"muted",
|
|
603
|
+
"muted-foreground",
|
|
604
|
+
"accent",
|
|
605
|
+
"accent-foreground",
|
|
606
|
+
"destructive",
|
|
607
|
+
"border",
|
|
608
|
+
"input",
|
|
609
|
+
"ring",
|
|
610
|
+
"chart-1",
|
|
611
|
+
"chart-2",
|
|
612
|
+
"chart-3",
|
|
613
|
+
"chart-4",
|
|
614
|
+
"chart-5",
|
|
615
|
+
"sidebar",
|
|
616
|
+
"sidebar-foreground",
|
|
617
|
+
"sidebar-primary",
|
|
618
|
+
"sidebar-primary-foreground",
|
|
619
|
+
"sidebar-accent",
|
|
620
|
+
"sidebar-accent-foreground",
|
|
621
|
+
"sidebar-border",
|
|
622
|
+
"sidebar-ring"
|
|
623
|
+
];
|
|
624
|
+
|
|
579
625
|
//#endregion
|
|
580
626
|
//#region src/utils/harden.ts
|
|
581
627
|
const safeProtocols = new Set([
|
|
@@ -916,10 +962,6 @@ function useHardenSanitizers(options) {
|
|
|
916
962
|
};
|
|
917
963
|
}
|
|
918
964
|
|
|
919
|
-
//#endregion
|
|
920
|
-
//#region src/composables/use-hsl-theme.ts
|
|
921
|
-
function useHslTheme() {}
|
|
922
|
-
|
|
923
965
|
//#endregion
|
|
924
966
|
//#region src/locales/index.ts
|
|
925
967
|
const SUPPORT_LANGUAGES = ["en-US", "zh-CN"];
|
|
@@ -999,7 +1041,7 @@ function useKatex() {
|
|
|
999
1041
|
}
|
|
1000
1042
|
|
|
1001
1043
|
//#endregion
|
|
1002
|
-
//#region \0@oxc-project+runtime@0.
|
|
1044
|
+
//#region \0@oxc-project+runtime@0.101.0/helpers/typeof.js
|
|
1003
1045
|
function _typeof(o) {
|
|
1004
1046
|
"@babel/helpers - typeof";
|
|
1005
1047
|
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o$1) {
|
|
@@ -1010,7 +1052,7 @@ function _typeof(o) {
|
|
|
1010
1052
|
}
|
|
1011
1053
|
|
|
1012
1054
|
//#endregion
|
|
1013
|
-
//#region \0@oxc-project+runtime@0.
|
|
1055
|
+
//#region \0@oxc-project+runtime@0.101.0/helpers/toPrimitive.js
|
|
1014
1056
|
function toPrimitive(t, r) {
|
|
1015
1057
|
if ("object" != _typeof(t) || !t) return t;
|
|
1016
1058
|
var e = t[Symbol.toPrimitive];
|
|
@@ -1023,14 +1065,14 @@ function toPrimitive(t, r) {
|
|
|
1023
1065
|
}
|
|
1024
1066
|
|
|
1025
1067
|
//#endregion
|
|
1026
|
-
//#region \0@oxc-project+runtime@0.
|
|
1068
|
+
//#region \0@oxc-project+runtime@0.101.0/helpers/toPropertyKey.js
|
|
1027
1069
|
function toPropertyKey(t) {
|
|
1028
1070
|
var i = toPrimitive(t, "string");
|
|
1029
1071
|
return "symbol" == _typeof(i) ? i : i + "";
|
|
1030
1072
|
}
|
|
1031
1073
|
|
|
1032
1074
|
//#endregion
|
|
1033
|
-
//#region \0@oxc-project+runtime@0.
|
|
1075
|
+
//#region \0@oxc-project+runtime@0.101.0/helpers/defineProperty.js
|
|
1034
1076
|
function _defineProperty(e, r, t) {
|
|
1035
1077
|
return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
|
1036
1078
|
value: t,
|
|
@@ -1041,32 +1083,32 @@ function _defineProperty(e, r, t) {
|
|
|
1041
1083
|
}
|
|
1042
1084
|
|
|
1043
1085
|
//#endregion
|
|
1044
|
-
//#region \0@oxc-project+runtime@0.
|
|
1086
|
+
//#region \0@oxc-project+runtime@0.101.0/helpers/checkPrivateRedeclaration.js
|
|
1045
1087
|
function _checkPrivateRedeclaration(e, t) {
|
|
1046
1088
|
if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object");
|
|
1047
1089
|
}
|
|
1048
1090
|
|
|
1049
1091
|
//#endregion
|
|
1050
|
-
//#region \0@oxc-project+runtime@0.
|
|
1092
|
+
//#region \0@oxc-project+runtime@0.101.0/helpers/classPrivateFieldInitSpec.js
|
|
1051
1093
|
function _classPrivateFieldInitSpec(e, t, a) {
|
|
1052
1094
|
_checkPrivateRedeclaration(e, t), t.set(e, a);
|
|
1053
1095
|
}
|
|
1054
1096
|
|
|
1055
1097
|
//#endregion
|
|
1056
|
-
//#region \0@oxc-project+runtime@0.
|
|
1098
|
+
//#region \0@oxc-project+runtime@0.101.0/helpers/assertClassBrand.js
|
|
1057
1099
|
function _assertClassBrand(e, t, n) {
|
|
1058
1100
|
if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n;
|
|
1059
1101
|
throw new TypeError("Private element is not present on this object");
|
|
1060
1102
|
}
|
|
1061
1103
|
|
|
1062
1104
|
//#endregion
|
|
1063
|
-
//#region \0@oxc-project+runtime@0.
|
|
1105
|
+
//#region \0@oxc-project+runtime@0.101.0/helpers/classPrivateFieldGet2.js
|
|
1064
1106
|
function _classPrivateFieldGet2(s, a) {
|
|
1065
1107
|
return s.get(_assertClassBrand(s, a));
|
|
1066
1108
|
}
|
|
1067
1109
|
|
|
1068
1110
|
//#endregion
|
|
1069
|
-
//#region \0@oxc-project+runtime@0.
|
|
1111
|
+
//#region \0@oxc-project+runtime@0.101.0/helpers/classPrivateFieldSet2.js
|
|
1070
1112
|
function _classPrivateFieldSet2(s, a, r) {
|
|
1071
1113
|
return s.set(_assertClassBrand(s, a), r), r;
|
|
1072
1114
|
}
|
|
@@ -1343,6 +1385,7 @@ function useMermaid(options) {
|
|
|
1343
1385
|
//#endregion
|
|
1344
1386
|
//#region src/composables/use-shiki.ts
|
|
1345
1387
|
let highlighter = null;
|
|
1388
|
+
let createHighlighterPromise = null;
|
|
1346
1389
|
function useShiki(options) {
|
|
1347
1390
|
const installed = ref(false);
|
|
1348
1391
|
const lang = computed(() => unref(options === null || options === void 0 ? void 0 : options.lang) ?? "plaintext");
|
|
@@ -1382,6 +1425,10 @@ function useShiki(options) {
|
|
|
1382
1425
|
return "plaintext";
|
|
1383
1426
|
}
|
|
1384
1427
|
async function getHighlighter() {
|
|
1428
|
+
if (createHighlighterPromise) {
|
|
1429
|
+
highlighter = await createHighlighterPromise;
|
|
1430
|
+
createHighlighterPromise = null;
|
|
1431
|
+
}
|
|
1385
1432
|
if (highlighter) {
|
|
1386
1433
|
const loadedLangs = highlighter.getLoadedLanguages();
|
|
1387
1434
|
const loadedThemes = highlighter.getLoadedThemes();
|
|
@@ -1391,15 +1438,19 @@ function useShiki(options) {
|
|
|
1391
1438
|
for (const theme of themes) if (!loadedThemes.includes(theme)) await highlighter.loadTheme(theme);
|
|
1392
1439
|
return highlighter;
|
|
1393
1440
|
}
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1441
|
+
createHighlighterPromise = (async () => {
|
|
1442
|
+
const { createHighlighter } = await import("shiki");
|
|
1443
|
+
return createHighlighter({
|
|
1444
|
+
themes: [await getTheme()],
|
|
1445
|
+
langs: [await getLanguage()],
|
|
1446
|
+
langAlias: {
|
|
1447
|
+
...LANGUAGE_ALIAS,
|
|
1448
|
+
...langAlias.value
|
|
1449
|
+
}
|
|
1450
|
+
});
|
|
1451
|
+
})();
|
|
1452
|
+
highlighter = await createHighlighterPromise;
|
|
1453
|
+
createHighlighterPromise = null;
|
|
1403
1454
|
return highlighter;
|
|
1404
1455
|
}
|
|
1405
1456
|
async function codeToTokens(code) {
|
|
@@ -1434,6 +1485,48 @@ function useShiki(options) {
|
|
|
1434
1485
|
};
|
|
1435
1486
|
}
|
|
1436
1487
|
|
|
1488
|
+
//#endregion
|
|
1489
|
+
//#region src/composables/use-tailwind-v3-theme.ts
|
|
1490
|
+
const reg = /^(?:hsl|rgb|oklch|lab|lch)\(/;
|
|
1491
|
+
function useTailwindV3Theme(options) {
|
|
1492
|
+
const { id, css, load, unload, isLoaded } = useStyleTag("", {
|
|
1493
|
+
id: "stream-markdown-tailwind-v3-theme",
|
|
1494
|
+
immediate: false
|
|
1495
|
+
});
|
|
1496
|
+
const styleScope = computed(() => unref(options.styleScope) || ".stream-markdown");
|
|
1497
|
+
const element = computed(() => {
|
|
1498
|
+
return toValue(options.element) || (typeof window !== "undefined" ? document.body : void 0);
|
|
1499
|
+
});
|
|
1500
|
+
function generateCSS() {
|
|
1501
|
+
if (!element.value || typeof window === "undefined") return;
|
|
1502
|
+
const computedStyle = window.getComputedStyle(element.value);
|
|
1503
|
+
const cssVariables = [];
|
|
1504
|
+
for (const schema of SHADCN_SCHEMAS) {
|
|
1505
|
+
const name = `--${schema}`;
|
|
1506
|
+
const value = computedStyle.getPropertyValue(name).trim();
|
|
1507
|
+
if (value && !reg.test(value)) cssVariables.push(` ${name}: hsl(${value});`);
|
|
1508
|
+
}
|
|
1509
|
+
if (cssVariables.length > 0) {
|
|
1510
|
+
css.value = `${styleScope.value} {\n${cssVariables.join("\n")}\n}`;
|
|
1511
|
+
load();
|
|
1512
|
+
} else {
|
|
1513
|
+
css.value = "";
|
|
1514
|
+
unload();
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
watchEffect(generateCSS);
|
|
1518
|
+
onBeforeUnmount(unload);
|
|
1519
|
+
return {
|
|
1520
|
+
element,
|
|
1521
|
+
id,
|
|
1522
|
+
css,
|
|
1523
|
+
load,
|
|
1524
|
+
unload,
|
|
1525
|
+
isLoaded,
|
|
1526
|
+
generateCSS
|
|
1527
|
+
};
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1437
1530
|
//#endregion
|
|
1438
1531
|
//#region src/composables/use-tippy.ts
|
|
1439
1532
|
function useTippy(options) {
|
|
@@ -1564,4 +1657,4 @@ function useZoom(options = {}) {
|
|
|
1564
1657
|
}
|
|
1565
1658
|
|
|
1566
1659
|
//#endregion
|
|
1567
|
-
export { transformUrl as A, findNodeParent as C, flow as D, hasShiki as E,
|
|
1660
|
+
export { transformUrl as A, useContext as B, findNodeParent as C, flow as D, hasShiki as E, DEFAULT_LIGHT_THEME as F, LANGUAGE_ALIAS as I, LANGUAGE_EXTENSIONS as L, ICONS as M, DEFAULT_HARDEN_OPTIONS as N, save as O, DEFAULT_DARK_THEME as P, LANGUAGE_ICONS as R, findLastLeafNode as S, hasMermaid as T, escapeMarkdownTableCell as _, useMermaid as a, tableDataToMarkdown as b, _defineProperty as c, SUPPORT_LANGUAGES as d, currentLocale as f, useHardenSanitizers as g, localesGlob as h, useShiki as i, SHADCN_SCHEMAS as j, svgToPngBlob as k, useKatex as l, localeMessages as m, useTippy as n, useMathRenderer as o, loadLocaleMessages as p, useTailwindV3Theme as r, throttle as s, useZoom as t, useI18n as u, extractTableDataFromElement as v, hasKatex as w, tableDataToTSV as x, tableDataToCSV as y, useControls as z };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { M as ICONS, u as useI18n } from "./composables-BwAY_BDJ.js";
|
|
2
2
|
import { computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, defineComponent, openBlock, renderSlot, resolveDynamicComponent, toDisplayString } from "vue";
|
|
3
3
|
|
|
4
4
|
//#region src/components/error-component.vue?vue&type=script&setup=true&lang.ts
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import "./tooltip-
|
|
3
|
-
import { t as button_default } from "./button-
|
|
4
|
-
import { t as error_component_default } from "./error-component-
|
|
1
|
+
import { M as ICONS, O as save, g as useHardenSanitizers, u as useI18n, z as useControls } from "./composables-BwAY_BDJ.js";
|
|
2
|
+
import "./tooltip-CA6Kp7Ek.js";
|
|
3
|
+
import { t as button_default } from "./button-dU2iYZBS.js";
|
|
4
|
+
import { t as error_component_default } from "./error-component-CiIR_1Cg.js";
|
|
5
5
|
import { t as spin_default } from "./spin-Ds5W7qC_.js";
|
|
6
6
|
import { Transition, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, mergeProps, normalizeStyle, openBlock, ref, resolveDynamicComponent, toDisplayString, toRefs, unref, withCtx } from "vue";
|
|
7
7
|
|
|
@@ -97,7 +97,7 @@ var image_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCo
|
|
|
97
97
|
var _props$imageOptions;
|
|
98
98
|
return ((_props$imageOptions = props.imageOptions) === null || _props$imageOptions === void 0 ? void 0 : _props$imageOptions.fallback) ?? "";
|
|
99
99
|
});
|
|
100
|
-
const imageSrc = computed(() =>
|
|
100
|
+
const imageSrc = computed(() => fallbackAttempted.value && fallback.value ? fallback.value : props.node.url);
|
|
101
101
|
const { transformedUrl, isHardenUrl } = useHardenSanitizers({
|
|
102
102
|
url: imageSrc,
|
|
103
103
|
hardenOptions,
|
|
@@ -158,51 +158,55 @@ var image_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCo
|
|
|
158
158
|
style: normalizeStyle({ width: isLoading.value || !imageLoaded.value ? "100%" : "auto" }),
|
|
159
159
|
onMouseenter: handleMouseEnter,
|
|
160
160
|
onMouseleave: handleMouseLeave
|
|
161
|
-
}, [createElementVNode("div", _hoisted_1, [
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
name: "
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
161
|
+
}, [createElementVNode("div", _hoisted_1, [
|
|
162
|
+
!unref(isHardenUrl) ? (openBlock(), createElementBlock("div", {
|
|
163
|
+
key: 0,
|
|
164
|
+
ref_key: "maskRef",
|
|
165
|
+
ref: maskRef,
|
|
166
|
+
"data-stream-markdown": "image-mask"
|
|
167
|
+
}, [!isLoading.value && showDownload.value ? (openBlock(), createBlock(button_default, {
|
|
168
|
+
key: 0,
|
|
169
|
+
"data-stream-markdown": "image-download-button",
|
|
170
|
+
icon: unref(ICONS).download,
|
|
171
|
+
name: unref(t)("button.download"),
|
|
172
|
+
"icon-class": "test",
|
|
173
|
+
"icon-width": 16,
|
|
174
|
+
"icon-height": 16,
|
|
175
|
+
"button-style": { backgroundColor: "color-mix(in oklab, var(--background) 90%, transparent)" },
|
|
176
|
+
onClick: handleDownload
|
|
177
|
+
}, null, 8, ["icon", "name"])) : createCommentVNode("v-if", true)], 512)) : createCommentVNode("v-if", true),
|
|
178
|
+
(isLoading.value || !imageLoaded.value) && !unref(isHardenUrl) ? (openBlock(), createBlock(spin_default, { key: 1 })) : createCommentVNode("v-if", true),
|
|
179
|
+
createVNode(Transition, {
|
|
180
|
+
name: "img-switch",
|
|
181
|
+
mode: "out-in"
|
|
182
|
+
}, {
|
|
183
|
+
default: withCtx(() => [!isLoading.value && !unref(isHardenUrl) && typeof unref(transformedUrl) === "string" ? (openBlock(), createElementBlock("img", {
|
|
184
|
+
ref_key: "imgRef",
|
|
185
|
+
ref: imgRef,
|
|
186
|
+
key: unref(transformedUrl),
|
|
187
|
+
"data-stream-markdown": "image",
|
|
188
|
+
src: unref(transformedUrl),
|
|
189
|
+
alt: alt.value,
|
|
190
|
+
title: title.value,
|
|
191
|
+
style: normalizeStyle({
|
|
192
|
+
opacity: isLoading.value ? 0 : 1,
|
|
193
|
+
cursor: isLoading.value ? "default" : "pointer"
|
|
194
|
+
}),
|
|
195
|
+
loading: "lazy",
|
|
196
|
+
decoding: "async",
|
|
197
|
+
"data-zoomable": "",
|
|
198
|
+
onLoad: handleLoaded,
|
|
199
|
+
onError: handleError
|
|
200
|
+
}, null, 44, _hoisted_2)) : unref(isHardenUrl) || loadError.value ? (openBlock(), createBlock(resolveDynamicComponent(Error.value), mergeProps({
|
|
201
|
+
key: 1,
|
|
202
|
+
variant: unref(isHardenUrl) ? "harden-image" : "image"
|
|
203
|
+
}, props), {
|
|
204
|
+
default: withCtx(() => [createTextVNode(toDisplayString(title.value), 1)]),
|
|
205
|
+
_: 1
|
|
206
|
+
}, 16, ["variant"])) : createCommentVNode("v-if", true)]),
|
|
202
207
|
_: 1
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
})]), showCaption.value && title.value ? (openBlock(), createElementBlock("figcaption", _hoisted_3, toDisplayString(title.value), 1)) : createCommentVNode("v-if", true)], 36);
|
|
208
|
+
})
|
|
209
|
+
]), showCaption.value && title.value ? (openBlock(), createElementBlock("figcaption", _hoisted_3, toDisplayString(title.value), 1)) : createCommentVNode("v-if", true)], 36);
|
|
206
210
|
};
|
|
207
211
|
}
|
|
208
212
|
});
|