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.
Files changed (35) hide show
  1. package/README.md +18 -19
  2. package/dist/button-Bz0s_F3s.js +5 -0
  3. package/dist/{button-D8xx1WIP.js → button-dU2iYZBS.js} +1 -1
  4. package/dist/{code-CP6mPwkq.js → code-BfJ58lYO.js} +7 -7
  5. package/dist/code-block-BFUXyGQH.js +9 -0
  6. package/dist/{code-block-D2zjJAww.css → code-block-Bv8s2E8I.css} +5 -0
  7. package/dist/{code-block-C4D_QNTq.js → code-block-CZHD64ft.js} +5 -5
  8. package/dist/{composables-qhB1h_ed.js → composables-BwAY_BDJ.js} +124 -31
  9. package/dist/dropdown-RWgcV-8w.js +5 -0
  10. package/dist/error-component-CR9t-T1D.js +4 -0
  11. package/dist/{error-component-CzarUjhh.js → error-component-CiIR_1Cg.js} +1 -1
  12. package/dist/{image-heJSlrNv.js → image-BporCeem.js} +53 -49
  13. package/dist/index.d.ts +47 -33
  14. package/dist/index.js +23 -323
  15. package/dist/{inline-math-B4XO1wMP.js → inline-math-BfG4600m.js} +2 -2
  16. package/dist/{link-DOtoFtxu.js → link-D-OnakwP.js} +2 -2
  17. package/dist/{math-Byka28HI.js → math-CvKkCYb9.js} +2 -2
  18. package/dist/{mermaid-X0AFRzfF.js → mermaid-FgnWaZtT.js} +16 -8
  19. package/dist/{previewers-Drlf7IQF.js → previewers-CoU4RlpQ.js} +1 -1
  20. package/dist/{segmented-BEtO1eyl.js → segmented-Baxxk3UJ.js} +1 -1
  21. package/dist/segmented-C0uEAYuJ.js +6 -0
  22. package/dist/{shiki-vToM7Pz1.js → shiki-BHOZKGKS.js} +1 -1
  23. package/dist/{table-DjkiVd9L.js → table-B__TdLr7.js} +9 -4
  24. package/dist/{tooltip-RiXixMIt.js → tooltip-CA6Kp7Ek.js} +1 -1
  25. package/dist/tooltip-DoIUaZgq.js +4 -0
  26. package/dist/zoom-container-BPbftW_I.js +6 -0
  27. package/dist/{zoom-container-BfUO3Ocp.js → zoom-container-Dlqv-z-t.js} +2 -2
  28. package/package.json +15 -11
  29. package/dist/button-BClRCjnc.js +0 -5
  30. package/dist/code-block-Dzw63Lki.js +0 -9
  31. package/dist/dropdown-Ca_PKF_d.js +0 -5
  32. package/dist/error-component-CLEJmPmM.js +0 -4
  33. package/dist/segmented-CWoQcX-H.js +0 -6
  34. package/dist/tooltip-Ac_2x9ps.js +0 -4
  35. 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="#">📚 Documentation</a> |
12
- <a href="#">🤹‍♂️ Playground</a>
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
- - 🚀 **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
- - 📐 **Beautiful LaTeX equations** - Render beautiful LaTeX equations 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
- - **Beautiful built-in typography** - No atomic CSS required (Tailwind/UnoCSS), self-contained styles
34
- - 🎨 **Theme-aware scoped styles** - Scoped styles under `.stream-markdown` with semantic `data-stream-markdown` attributes, following [shadcn/ui](https://ui.shadcn.com/) design system
35
- - 🌏 **CJK language support** - Following `streamdown` design, handles emphasis with ideographic punctuation
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 substantial source code from it.
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
 
@@ -0,0 +1,5 @@
1
+ import "./composables-BwAY_BDJ.js";
2
+ import "./tooltip-CA6Kp7Ek.js";
3
+ import { t as button_default } from "./button-dU2iYZBS.js";
4
+
5
+ export { button_default as default };
@@ -1,4 +1,4 @@
1
- import { t as tooltip_default } from "./tooltip-RiXixMIt.js";
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-Drlf7IQF.js";
2
- import { r as useShiki } from "./composables-qhB1h_ed.js";
3
- import "./tooltip-RiXixMIt.js";
4
- import "./button-D8xx1WIP.js";
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-C4D_QNTq.js";
7
- import "./segmented-BEtO1eyl.js";
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-vToM7Pz1.js"))
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-Drlf7IQF.js";
2
- import { F as LANGUAGE_ALIAS, I as LANGUAGE_EXTENSIONS, L as LANGUAGE_ICONS, O as save, R as useControls, i as useMermaid, j as ICONS, l as useI18n, z as useContext } from "./composables-qhB1h_ed.js";
3
- import { t as button_default } from "./button-D8xx1WIP.js";
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-BEtO1eyl.js";
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-CP6mPwkq.js"));
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 true;
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 === true;
58
+ return current;
52
59
  } catch {
53
- return false;
60
+ return;
54
61
  }
55
62
  }
56
- return { isControlEnabled };
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.99.0/helpers/typeof.js
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.99.0/helpers/toPrimitive.js
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.99.0/helpers/toPropertyKey.js
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.99.0/helpers/defineProperty.js
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.99.0/helpers/checkPrivateRedeclaration.js
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.99.0/helpers/classPrivateFieldInitSpec.js
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.99.0/helpers/assertClassBrand.js
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.99.0/helpers/classPrivateFieldGet2.js
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.99.0/helpers/classPrivateFieldSet2.js
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
- const { createHighlighter } = await import("shiki");
1395
- highlighter = await createHighlighter({
1396
- themes: [await getTheme()],
1397
- langs: [await getLanguage()],
1398
- langAlias: {
1399
- ...LANGUAGE_ALIAS,
1400
- ...langAlias.value
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, LANGUAGE_ALIAS as F, LANGUAGE_EXTENSIONS as I, LANGUAGE_ICONS as L, DEFAULT_HARDEN_OPTIONS as M, DEFAULT_DARK_THEME as N, save as O, DEFAULT_LIGHT_THEME as P, useControls as R, findLastLeafNode as S, hasMermaid as T, escapeMarkdownTableCell as _, useMathRenderer as a, tableDataToMarkdown as b, useKatex as c, currentLocale as d, loadLocaleMessages as f, useHardenSanitizers as g, useHslTheme as h, useMermaid as i, ICONS as j, svgToPngBlob as k, useI18n as l, localesGlob as m, useTippy as n, throttle as o, localeMessages as p, useShiki as r, _defineProperty as s, useZoom as t, SUPPORT_LANGUAGES as u, extractTableDataFromElement as v, hasKatex as w, tableDataToTSV as x, tableDataToCSV as y, useContext as z };
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 };
@@ -0,0 +1,5 @@
1
+ import "./composables-BwAY_BDJ.js";
2
+ import "./tooltip-CA6Kp7Ek.js";
3
+ import { n as dropdown_default } from "./button-dU2iYZBS.js";
4
+
5
+ export { dropdown_default as default };
@@ -0,0 +1,4 @@
1
+ import "./composables-BwAY_BDJ.js";
2
+ import { t as error_component_default } from "./error-component-CiIR_1Cg.js";
3
+
4
+ export { error_component_default as default };
@@ -1,4 +1,4 @@
1
- import { j as ICONS, l as useI18n } from "./composables-qhB1h_ed.js";
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 { O as save, R as useControls, g as useHardenSanitizers, j as ICONS, l as useI18n } from "./composables-qhB1h_ed.js";
2
- import "./tooltip-RiXixMIt.js";
3
- import { t as button_default } from "./button-D8xx1WIP.js";
4
- import { t as error_component_default } from "./error-component-CzarUjhh.js";
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(() => loadError.value && fallback.value ? fallback.value : props.node.url);
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, [!unref(isHardenUrl) ? (openBlock(), createElementBlock("div", {
162
- key: 0,
163
- ref_key: "maskRef",
164
- ref: maskRef,
165
- "data-stream-markdown": "image-mask"
166
- }, [!isLoading.value && showDownload.value ? (openBlock(), createBlock(button_default, {
167
- key: 0,
168
- "data-stream-markdown": "image-download-button",
169
- icon: unref(ICONS).download,
170
- name: unref(t)("button.download"),
171
- "icon-class": "test",
172
- "icon-width": 16,
173
- "icon-height": 16,
174
- "button-style": { backgroundColor: "color-mix(in oklab, var(--background) 90%, transparent)" },
175
- onClick: handleDownload
176
- }, null, 8, ["icon", "name"])) : createCommentVNode("v-if", true)], 512)) : createCommentVNode("v-if", true), createVNode(Transition, {
177
- name: "img-switch",
178
- mode: "out-in"
179
- }, {
180
- default: withCtx(() => [!isLoading.value && !unref(isHardenUrl) && typeof unref(transformedUrl) === "string" ? (openBlock(), createElementBlock("img", {
181
- ref_key: "imgRef",
182
- ref: imgRef,
183
- key: unref(transformedUrl),
184
- "data-stream-markdown": "image",
185
- src: unref(transformedUrl),
186
- alt: alt.value,
187
- title: title.value,
188
- style: normalizeStyle({
189
- opacity: isLoading.value ? 0 : 1,
190
- cursor: isLoading.value ? "default" : "pointer"
191
- }),
192
- loading: "lazy",
193
- decoding: "async",
194
- "data-zoomable": "",
195
- onLoad: handleLoaded,
196
- onError: handleError
197
- }, null, 44, _hoisted_2)) : (isLoading.value || !imageLoaded.value) && !unref(isHardenUrl) ? (openBlock(), createBlock(spin_default, { key: 1 })) : (openBlock(), createBlock(resolveDynamicComponent(Error.value), mergeProps({
198
- key: 2,
199
- variant: unref(isHardenUrl) ? "harden-image" : "image"
200
- }, props), {
201
- default: withCtx(() => [createTextVNode(toDisplayString(title.value), 1)]),
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
- }, 16, ["variant"]))]),
204
- _: 1
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
  });