vue-stream-markdown 0.1.2 → 0.1.3

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 (40) hide show
  1. package/README.md +8 -0
  2. package/dist/button-2wMU7qkH.js +5 -0
  3. package/dist/{button-vKhxUL3C.js → button-CJyeXWq2.js} +1 -1
  4. package/dist/{code-_dL6Qk0F.js → code-CJ4tMt6L.js} +8 -8
  5. package/dist/code-block-BucFZooo.js +9 -0
  6. package/dist/{code-block-wYeMwBck.js → code-block-CQ4lgva1.js} +13 -17
  7. package/dist/{composables-CZ7YmjNl.js → composables-Cj6_jbwr.js} +48 -17
  8. package/dist/dropdown-dsCfq0Hl.js +5 -0
  9. package/dist/error-component-B0mmLhh6.js +4 -0
  10. package/dist/{error-component-ChEpOmSX.js → error-component-ClGLfmwy.js} +1 -1
  11. package/dist/{image-DB-4Sv8R.js → image-xeiC5YFM.js} +4 -4
  12. package/dist/index.css +58 -73
  13. package/dist/index.d.ts +58 -28
  14. package/dist/index.js +63 -17
  15. package/dist/{inline-math-rChhv_1j.js → inline-math-C2NUSasr.js} +12 -15
  16. package/dist/{link-CJk67Kbh.js → link-BceXudNH.js} +2 -2
  17. package/dist/{math-ZLxqHT_f.js → math-DXOLG3Xg.js} +12 -15
  18. package/dist/{mermaid-CNFU7Pg8.js → mermaid-CU4hpB6S.js} +5 -5
  19. package/dist/{previewers-CMreQ4TA.js → previewers-qHMi6xZ3.js} +1 -1
  20. package/dist/segmented-BeHqXuFx.js +6 -0
  21. package/dist/{segmented-RoWxDIP3.js → segmented-CF6exjdD.js} +1 -1
  22. package/dist/{shiki-4529WbJJ.js → shiki-BlfngIRi.js} +9 -14
  23. package/dist/{renderer-CZ41eK_V.js → shiki-token-renderer-D164wC7Y.js} +10 -23
  24. package/dist/{table-BmGwZIPR.js → table-C5VHgkTQ.js} +3 -3
  25. package/dist/tooltip-BzVZqo7w.js +4 -0
  26. package/dist/{tooltip-KcTe6tBF.js → tooltip-gxsqaBNg.js} +1 -1
  27. package/dist/vanilla-CKj7EQLx.js +4 -0
  28. package/dist/vanilla-D5DzB31q.js +39 -0
  29. package/dist/zoom-container-CwEDlKRx.js +6 -0
  30. package/dist/{zoom-container-D1Mys9gv.js → zoom-container-D_fBClW2.js} +2 -2
  31. package/package.json +1 -1
  32. package/dist/button-DBgeYAZy.js +0 -5
  33. package/dist/code-block-DGZ48hb0.js +0 -9
  34. package/dist/dropdown-DR-uQ215.js +0 -5
  35. package/dist/error-component-CKCT9gXy.js +0 -4
  36. package/dist/segmented-63wrfRNo.js +0 -6
  37. package/dist/tooltip--rusT8LZ.js +0 -4
  38. package/dist/vanilla-CA9QO96X.js +0 -3
  39. package/dist/vanilla-DkX6g0dm.js +0 -87
  40. package/dist/zoom-container-C-CB2LTY.js +0 -6
package/README.md CHANGED
@@ -66,6 +66,14 @@ This project also uses and benefits from:
66
66
  - [KaTeX](https://katex.org/) - Fast math typesetting library for the web
67
67
  - [Remend](https://github.com/vercel/streamdown/tree/main/packages/remend) - Intelligently parses and styles incomplete Markdown blocks
68
68
 
69
+ ### Code Sources
70
+ - [markstream-vue](https://github.com/Simon-He95/markstream-vue) - The original inspiration for learning AST-based custom markdown rendering, and the source of the animation implementation used in this project
71
+ - [ast-explorer](https://github.com/sxzz/ast-explorer) - Learned AST knowledge from this project, and the playground layout inspiration and AST syntax tree filtering code are derived from it
72
+
73
+ ## Acknowledgments
74
+
75
+ I would like to express my sincere gratitude to those who provided guidance and support during the project selection phase and promotion phase of this project. Without their encouragement and support, I would not have been able to complete this work. In particular, the [streamdown](https://streamdown.ai/) community provided excellent code guidance and even helped fix several issues.
76
+
69
77
  ## Troubleshooting
70
78
 
71
79
  The playground supports generating shareable links and provides streaming controls (forward/backward navigation) for debugging streaming rendering issues.
@@ -0,0 +1,5 @@
1
+ import "./composables-Cj6_jbwr.js";
2
+ import "./tooltip-gxsqaBNg.js";
3
+ import { t as button_default } from "./button-CJyeXWq2.js";
4
+
5
+ export { button_default as default };
@@ -1,4 +1,4 @@
1
- import { t as tooltip_default } from "./tooltip-KcTe6tBF.js";
1
+ import { t as tooltip_default } from "./tooltip-gxsqaBNg.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-CMreQ4TA.js";
2
- import { i as useShiki } from "./composables-CZ7YmjNl.js";
3
- import "./tooltip-KcTe6tBF.js";
4
- import "./button-vKhxUL3C.js";
1
+ import "./previewers-qHMi6xZ3.js";
2
+ import { i as useShiki } from "./composables-Cj6_jbwr.js";
3
+ import "./tooltip-gxsqaBNg.js";
4
+ import "./button-CJyeXWq2.js";
5
5
  import "./modal-CuQR21UD.js";
6
- import { t as code_block_default } from "./code-block-wYeMwBck.js";
7
- import "./segmented-RoWxDIP3.js";
6
+ import { t as code_block_default } from "./code-block-CQ4lgva1.js";
7
+ import "./segmented-CF6exjdD.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
@@ -82,8 +82,8 @@ var index_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCo
82
82
  const languageClass = computed(() => `language-${props.node.lang}`);
83
83
  const { installed: hasShiki } = useShiki();
84
84
  const components = {
85
- vanilla: defineAsyncComponent(() => import("./vanilla-CA9QO96X.js")),
86
- shiki: defineAsyncComponent(() => import("./shiki-4529WbJJ.js"))
85
+ vanilla: defineAsyncComponent(() => import("./vanilla-CKj7EQLx.js")),
86
+ shiki: defineAsyncComponent(() => import("./shiki-BlfngIRi.js"))
87
87
  };
88
88
  const component = computed(() => {
89
89
  if (hasShiki.value) return components.shiki;
@@ -0,0 +1,9 @@
1
+ import "./previewers-qHMi6xZ3.js";
2
+ import "./composables-Cj6_jbwr.js";
3
+ import "./tooltip-gxsqaBNg.js";
4
+ import "./button-CJyeXWq2.js";
5
+ import "./modal-CuQR21UD.js";
6
+ import { t as code_block_default } from "./code-block-CQ4lgva1.js";
7
+ import "./segmented-CF6exjdD.js";
8
+
9
+ export { code_block_default as default };
@@ -1,8 +1,8 @@
1
- import { t as CODE_PREVIEWERS } from "./previewers-CMreQ4TA.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-CZ7YmjNl.js";
3
- import { t as button_default } from "./button-vKhxUL3C.js";
1
+ import { t as CODE_PREVIEWERS } from "./previewers-qHMi6xZ3.js";
2
+ import { B as useContext, I as LANGUAGE_ALIAS, L as LANGUAGE_EXTENSIONS, M as ICONS, O as save, R as LANGUAGE_ICONS, V as useCodeOptions, a as useMermaid, u as useI18n, z as useControls } from "./composables-Cj6_jbwr.js";
3
+ import { t as button_default } from "./button-CJyeXWq2.js";
4
4
  import { t as modal_default } from "./modal-CuQR21UD.js";
5
- import { t as segmented_default } from "./segmented-RoWxDIP3.js";
5
+ import { t as segmented_default } from "./segmented-CF6exjdD.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
 
@@ -204,11 +204,11 @@ var index_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCo
204
204
  },
205
205
  setup(__props) {
206
206
  const props = __props;
207
- const { controls, previewers } = toRefs(props);
207
+ const { controls, previewers, codeOptions } = toRefs(props);
208
208
  const { t } = useI18n();
209
209
  const { isControlEnabled } = useControls({ controls });
210
210
  const { installed: hasMermaid } = useMermaid();
211
- const CodeNode = defineAsyncComponent(() => import("./code-_dL6Qk0F.js"));
211
+ const CodeNode = defineAsyncComponent(() => import("./code-CJ4tMt6L.js"));
212
212
  const { onCopied } = useContext();
213
213
  const { copy, copied } = useClipboard({ legacy: true });
214
214
  const { saveMermaid } = useMermaid();
@@ -221,13 +221,9 @@ var index_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCo
221
221
  if (LANGUAGE_ALIAS[lang]) return LANGUAGE_ALIAS[lang];
222
222
  return lang;
223
223
  });
224
- const showLanguageIcon = computed(() => {
225
- var _props$codeOptions;
226
- return typeof ((_props$codeOptions = props.codeOptions) === null || _props$codeOptions === void 0 ? void 0 : _props$codeOptions.languageIcon) === "boolean" ? props.codeOptions.languageIcon : true;
227
- });
228
- const showLanguageName = computed(() => {
229
- var _props$codeOptions2;
230
- return typeof ((_props$codeOptions2 = props.codeOptions) === null || _props$codeOptions2 === void 0 ? void 0 : _props$codeOptions2.languageName) === "boolean" ? props.codeOptions.languageName : true;
224
+ const { showLanguageIcon, showLanguageName } = useCodeOptions({
225
+ codeOptions,
226
+ language
231
227
  });
232
228
  const showLanguageTitle = computed(() => showLanguageIcon.value || showLanguageName.value);
233
229
  const showCollapse = computed(() => isControlEnabled("code.collapse"));
@@ -337,8 +333,8 @@ var index_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCo
337
333
  key: 0,
338
334
  icon: icon.value,
339
335
  language: language.value,
340
- "show-icon": showLanguageIcon.value,
341
- "show-name": showLanguageName.value
336
+ "show-icon": unref(showLanguageIcon),
337
+ "show-name": unref(showLanguageName)
342
338
  }, null, 8, [
343
339
  "icon",
344
340
  "language",
@@ -370,8 +366,8 @@ var index_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCo
370
366
  key: 0,
371
367
  icon: icon.value,
372
368
  language: language.value,
373
- "show-icon": showLanguageIcon.value,
374
- "show-name": showLanguageName.value
369
+ "show-icon": unref(showLanguageIcon),
370
+ "show-name": unref(showLanguageName)
375
371
  }, null, 8, [
376
372
  "icon",
377
373
  "language",
@@ -6,6 +6,32 @@ import "tippy.js/themes/light.css";
6
6
  import "tippy.js/dist/border.css";
7
7
  import "tippy.js/dist/svg-arrow.css";
8
8
 
9
+ //#region src/composables/use-code-options.ts
10
+ function useCodeOptions(options) {
11
+ const language = computed(() => unref(options.language) || "");
12
+ const codeOptions = computed(() => unref(options.codeOptions));
13
+ const languageCodeOptions = computed(() => {
14
+ var _codeOptions$value;
15
+ return ((_codeOptions$value = codeOptions.value) === null || _codeOptions$value === void 0 || (_codeOptions$value = _codeOptions$value.language) === null || _codeOptions$value === void 0 ? void 0 : _codeOptions$value[language.value]) ?? codeOptions.value;
16
+ });
17
+ return {
18
+ languageCodeOptions,
19
+ showLanguageIcon: computed(() => {
20
+ var _languageCodeOptions$;
21
+ return typeof ((_languageCodeOptions$ = languageCodeOptions.value) === null || _languageCodeOptions$ === void 0 ? void 0 : _languageCodeOptions$.languageIcon) === "boolean" ? languageCodeOptions.value.languageIcon : true;
22
+ }),
23
+ showLanguageName: computed(() => {
24
+ var _languageCodeOptions$2;
25
+ return typeof ((_languageCodeOptions$2 = languageCodeOptions.value) === null || _languageCodeOptions$2 === void 0 ? void 0 : _languageCodeOptions$2.languageName) === "boolean" ? languageCodeOptions.value.languageName : true;
26
+ }),
27
+ showLineNumbers: computed(() => {
28
+ var _languageCodeOptions$3;
29
+ return typeof ((_languageCodeOptions$3 = languageCodeOptions.value) === null || _languageCodeOptions$3 === void 0 ? void 0 : _languageCodeOptions$3.lineNumbers) === "boolean" ? languageCodeOptions.value.lineNumbers : true;
30
+ })
31
+ };
32
+ }
33
+
34
+ //#endregion
9
35
  //#region src/composables/use-context.ts
10
36
  const CONTEXT_KEY = Symbol("stream-markdown-context");
11
37
  function useContext() {
@@ -624,21 +650,6 @@ const SHADCN_SCHEMAS = [
624
650
 
625
651
  //#endregion
626
652
  //#region src/utils/harden.ts
627
- const safeProtocols = new Set([
628
- "https:",
629
- "http:",
630
- "irc:",
631
- "ircs:",
632
- "mailto:",
633
- "xmpp:",
634
- "blob:"
635
- ]);
636
- const blockedProtocols = new Set([
637
- "javascript:",
638
- "data:",
639
- "file:",
640
- "vbscript:"
641
- ]);
642
653
  function parseUrl(url, defaultOrigin) {
643
654
  if (typeof url !== "string") return null;
644
655
  try {
@@ -649,13 +660,33 @@ function parseUrl(url, defaultOrigin) {
649
660
  } catch {
650
661
  return null;
651
662
  }
663
+ if (url.startsWith("/") || url.startsWith("./") || url.startsWith("../")) try {
664
+ return new URL(url, "http://example.com");
665
+ } catch {
666
+ return null;
667
+ }
652
668
  return null;
653
669
  }
654
670
  }
655
671
  function isPathRelativeUrl(url) {
656
672
  if (typeof url !== "string") return false;
657
- return url.startsWith("/");
673
+ return url.startsWith("/") || url.startsWith("./") || url.startsWith("../");
658
674
  }
675
+ const safeProtocols = new Set([
676
+ "https:",
677
+ "http:",
678
+ "irc:",
679
+ "ircs:",
680
+ "mailto:",
681
+ "xmpp:",
682
+ "blob:"
683
+ ]);
684
+ const blockedProtocols = new Set([
685
+ "javascript:",
686
+ "data:",
687
+ "file:",
688
+ "vbscript:"
689
+ ]);
659
690
  function transformUrl(url, allowedPrefixes, defaultOrigin, allowDataImages = false, isImage = false, allowedProtocols = []) {
660
691
  if (!url) return null;
661
692
  if (typeof url === "string" && url.startsWith("#") && !isImage) try {
@@ -1647,4 +1678,4 @@ function useZoom(options = {}) {
1647
1678
  }
1648
1679
 
1649
1680
  //#endregion
1650
- 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 };
1681
+ 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, useCodeOptions as V, 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-Cj6_jbwr.js";
2
+ import "./tooltip-gxsqaBNg.js";
3
+ import { n as dropdown_default } from "./button-CJyeXWq2.js";
4
+
5
+ export { dropdown_default as default };
@@ -0,0 +1,4 @@
1
+ import "./composables-Cj6_jbwr.js";
2
+ import { t as error_component_default } from "./error-component-ClGLfmwy.js";
3
+
4
+ export { error_component_default as default };
@@ -1,4 +1,4 @@
1
- import { M as ICONS, u as useI18n } from "./composables-CZ7YmjNl.js";
1
+ import { M as ICONS, u as useI18n } from "./composables-Cj6_jbwr.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 { M as ICONS, O as save, g as useHardenSanitizers, u as useI18n, z as useControls } from "./composables-CZ7YmjNl.js";
2
- import "./tooltip-KcTe6tBF.js";
3
- import { t as button_default } from "./button-vKhxUL3C.js";
4
- import { t as error_component_default } from "./error-component-ChEpOmSX.js";
1
+ import { M as ICONS, O as save, g as useHardenSanitizers, u as useI18n, z as useControls } from "./composables-Cj6_jbwr.js";
2
+ import "./tooltip-gxsqaBNg.js";
3
+ import { t as button_default } from "./button-CJyeXWq2.js";
4
+ import { t as error_component_default } from "./error-component-ClGLfmwy.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
 
package/dist/index.css CHANGED
@@ -24,20 +24,6 @@
24
24
  padding: 0;
25
25
  }
26
26
 
27
- .stream-markdown .tippy-box {
28
- background: var(--popover);
29
- color: var(--popover-foreground);
30
- border: 1px solid var(--border);
31
- }
32
-
33
- .stream-markdown .tippy-arrow {
34
- color: var(--popover);
35
- }
36
-
37
- .stream-markdown .tippy-box > .tippy-svg-arrow {
38
- border-top-color: var(--popover);
39
- }
40
-
41
27
  .stream-markdown ::-webkit-scrollbar {
42
28
  width: 6px;
43
29
  height: 6px;
@@ -57,6 +43,20 @@
57
43
  opacity: 0.5;
58
44
  }
59
45
 
46
+ .stream-markdown .tippy-box {
47
+ background: var(--popover);
48
+ color: var(--popover-foreground);
49
+ border: 1px solid var(--border);
50
+ }
51
+
52
+ .stream-markdown .tippy-arrow {
53
+ color: var(--popover);
54
+ }
55
+
56
+ .stream-markdown .tippy-box > .tippy-svg-arrow {
57
+ border-top-color: var(--popover);
58
+ }
59
+
60
60
  .stream-markdown [data-stream-markdown='button'] {
61
61
  display: flex;
62
62
  align-items: center;
@@ -160,15 +160,6 @@
160
160
  overflow: auto;
161
161
  }
162
162
 
163
- .stream-markdown .modal-enter-from,
164
- .stream-markdown .modal-leave-to {
165
- opacity: 0;
166
- }
167
- .stream-markdown .modal-enter-active,
168
- .stream-markdown .modal-leave-active {
169
- transition: opacity var(--default-transition-duration) ease;
170
- }
171
-
172
163
  .stream-markdown [data-stream-markdown='modal-header'] > :first-child {
173
164
  flex: 1;
174
165
  }
@@ -215,15 +206,6 @@
215
206
  animation: spin 1s linear infinite;
216
207
  }
217
208
 
218
- @keyframes spin {
219
- from {
220
- transform: rotate(0deg);
221
- }
222
- to {
223
- transform: rotate(360deg);
224
- }
225
- }
226
-
227
209
  .stream-markdown [data-stream-markdown='table'] {
228
210
  width: 100%;
229
211
  border-collapse: collapse;
@@ -335,7 +317,7 @@
335
317
 
336
318
  @media (max-width: 1024px) {
337
319
  .stream-markdown [data-stream-markdown='code-block-header'] {
338
- padding-inline: 0.5rem;
320
+ padding-inline: 0.75rem;
339
321
  }
340
322
  }
341
323
 
@@ -488,23 +470,6 @@
488
470
  right: 0.5rem;
489
471
  }
490
472
 
491
- .stream-markdown .img-switch-enter-active,
492
- .stream-markdown .img-switch-leave-active {
493
- transition:
494
- opacity var(--default-transition-duration) ease,
495
- transform var(--default-transition-duration) ease;
496
- }
497
- .stream-markdown .img-switch-enter-from,
498
- .stream-markdown .img-switch-leave-to {
499
- opacity: 0;
500
- transform: translateY(6px);
501
- }
502
- .stream-markdown .img-switch-enter-to,
503
- .stream-markdown .img-switch-leave-from {
504
- opacity: 1;
505
- transform: translateY(0);
506
- }
507
-
508
473
  .stream-markdown [data-stream-markdown='inline-code'] {
509
474
  background-color: var(--muted);
510
475
  border-radius: 0.25rem;
@@ -517,16 +482,6 @@
517
482
  overflow-wrap: break-word;
518
483
  }
519
484
 
520
- .stream-markdown .inline-math-enter-active,
521
- .stream-markdown .inline-math-leave-active {
522
- transition: opacity var (--default-transition-duration) ease;
523
- }
524
-
525
- .stream-markdown .inline-math-enter-from,
526
- .stream-markdown .inline-math-leave-to {
527
- opacity: 0;
528
- }
529
-
530
485
  .stream-markdown [data-stream-markdown='link'] {
531
486
  color: var(--primary);
532
487
  text-decoration: underline;
@@ -579,16 +534,6 @@
579
534
  margin-block: 1rem;
580
535
  }
581
536
 
582
- .stream-markdown .math-enter-active,
583
- .stream-markdown .math-leave-active {
584
- transition: opacity var (--default-transition-duration) ease;
585
- }
586
-
587
- .stream-markdown .math-enter-from,
588
- .stream-markdown .math-leave-to {
589
- opacity: 0;
590
- }
591
-
592
537
  .stream-markdown [data-stream-markdown='paragraph'] {
593
538
  margin-bottom: 1rem;
594
539
  vertical-align: middle;
@@ -639,14 +584,17 @@
639
584
  .stream-markdown [data-stream-markdown='code'],
640
585
  .stream-markdown [data-stream-markdown='code'] code {
641
586
  font-family: var(--font-mono);
587
+ font-size: 0.875rem;
642
588
  }
643
589
 
644
- .stream-markdown [data-stream-markdown='code'] .line {
590
+ .stream-markdown [data-stream-markdown='code'] [data-stream-markdown='code-line'] {
645
591
  display: block;
646
592
  position: relative;
593
+ font-size: 0.875rem;
594
+ min-height: 1rem;
647
595
  }
648
596
 
649
- .stream-markdown [data-stream-markdown='code'] .line::before {
597
+ .stream-markdown [data-stream-markdown='code'] [data-stream-markdown='code-line']::before {
650
598
  display: inline-block;
651
599
  width: 1rem;
652
600
  margin-right: 1rem;
@@ -659,10 +607,47 @@
659
607
  user-select: none;
660
608
  }
661
609
 
662
- .stream-markdown [data-stream-markdown='code'][data-show-line-numbers='false'] .line::before {
610
+ .stream-markdown
611
+ [data-stream-markdown='code'][data-show-line-numbers='false']
612
+ [data-stream-markdown='code-line']::before {
663
613
  display: none;
664
614
  }
665
615
 
666
616
  .stream-markdown [data-stream-markdown='code'] {
667
617
  padding: 1rem;
668
618
  }
619
+
620
+ .stream-markdown .modal-enter-from,
621
+ .stream-markdown .modal-leave-to {
622
+ opacity: 0;
623
+ }
624
+ .stream-markdown .modal-enter-active,
625
+ .stream-markdown .modal-leave-active {
626
+ transition: opacity var(--default-transition-duration) ease;
627
+ }
628
+
629
+ .stream-markdown .img-switch-enter-active,
630
+ .stream-markdown .img-switch-leave-active {
631
+ transition:
632
+ opacity var(--default-transition-duration) ease,
633
+ transform var(--default-transition-duration) ease;
634
+ }
635
+ .stream-markdown .img-switch-enter-from,
636
+ .stream-markdown .img-switch-leave-to {
637
+ opacity: 0;
638
+ transform: translateY(6px);
639
+ }
640
+ .stream-markdown .img-switch-enter-to,
641
+ .stream-markdown .img-switch-leave-from {
642
+ opacity: 1;
643
+ transform: translateY(0);
644
+ }
645
+
646
+ @keyframes spin {
647
+ from {
648
+ transform: rotate(0deg);
649
+ }
650
+ to {
651
+ transform: rotate(360deg);
652
+ }
653
+ }