vue-stream-markdown 0.1.2 → 0.1.4
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 +8 -0
- package/dist/button-D6ccVxGm.js +5 -0
- package/dist/{button-vKhxUL3C.js → button-jFTF378X.js} +1 -1
- package/dist/{code-_dL6Qk0F.js → code-BxWvKFxG.js} +8 -8
- package/dist/code-block-B72JfFy-.js +9 -0
- package/dist/{code-block-wYeMwBck.js → code-block-uZcUI59D.js} +40 -29
- package/dist/{composables-CZ7YmjNl.js → composables-Cx0nvyHl.js} +124 -25
- package/dist/dropdown-oiCw8QVq.js +5 -0
- package/dist/error-component-8y13-fYG.js +4 -0
- package/dist/{error-component-ChEpOmSX.js → error-component-Bhl770lu.js} +4 -3
- package/dist/{image-DB-4Sv8R.js → image-BDtPwitR.js} +6 -5
- package/dist/index.css +58 -73
- package/dist/index.d.ts +112 -53
- package/dist/index.js +76 -19
- package/dist/{inline-math-rChhv_1j.js → inline-math-CAqboT7h.js} +12 -15
- package/dist/{link-CJk67Kbh.js → link-C8BSlPhZ.js} +2 -2
- package/dist/{math-ZLxqHT_f.js → math-CT1TB2pK.js} +12 -15
- package/dist/{mermaid-CNFU7Pg8.js → mermaid-CYrA8rCl.js} +5 -5
- package/dist/{previewers-CMreQ4TA.js → previewers-ByaS2Ksa.js} +1 -1
- package/dist/segmented-B4IEw3wg.js +6 -0
- package/dist/{segmented-RoWxDIP3.js → segmented-DBW9ignu.js} +1 -1
- package/dist/{shiki-4529WbJJ.js → shiki-bQYWLdW3.js} +9 -14
- package/dist/{renderer-CZ41eK_V.js → shiki-token-renderer-D164wC7Y.js} +10 -23
- package/dist/{table-BmGwZIPR.js → table-l_3z210v.js} +6 -5
- package/dist/{tooltip-KcTe6tBF.js → tooltip-3UDC9mw-.js} +1 -1
- package/dist/tooltip-CAoc_U1X.js +4 -0
- package/dist/vanilla-CFWVwBvD.js +39 -0
- package/dist/vanilla-De7W3PpS.js +4 -0
- package/dist/zoom-container-DBgGdbJS.js +6 -0
- package/dist/{zoom-container-D1Mys9gv.js → zoom-container-gjQ0EMyk.js} +18 -5
- package/package.json +1 -1
- package/dist/button-DBgeYAZy.js +0 -5
- package/dist/code-block-DGZ48hb0.js +0 -9
- package/dist/dropdown-DR-uQ215.js +0 -5
- package/dist/error-component-CKCT9gXy.js +0 -4
- package/dist/segmented-63wrfRNo.js +0 -6
- package/dist/tooltip--rusT8LZ.js +0 -4
- package/dist/vanilla-CA9QO96X.js +0 -3
- package/dist/vanilla-DkX6g0dm.js +0 -87
- 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.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as tooltip_default } from "./tooltip-
|
|
1
|
+
import { t as tooltip_default } from "./tooltip-3UDC9mw-.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 { i as useShiki } from "./composables-
|
|
3
|
-
import "./tooltip-
|
|
4
|
-
import "./button-
|
|
1
|
+
import "./previewers-ByaS2Ksa.js";
|
|
2
|
+
import { i as useShiki } from "./composables-Cx0nvyHl.js";
|
|
3
|
+
import "./tooltip-3UDC9mw-.js";
|
|
4
|
+
import "./button-jFTF378X.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-uZcUI59D.js";
|
|
7
|
+
import "./segmented-DBW9ignu.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-
|
|
86
|
-
shiki: defineAsyncComponent(() => import("./shiki-
|
|
85
|
+
vanilla: defineAsyncComponent(() => import("./vanilla-De7W3PpS.js")),
|
|
86
|
+
shiki: defineAsyncComponent(() => import("./shiki-bQYWLdW3.js"))
|
|
87
87
|
};
|
|
88
88
|
const component = computed(() => {
|
|
89
89
|
if (hasShiki.value) return components.shiki;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import "./previewers-ByaS2Ksa.js";
|
|
2
|
+
import "./composables-Cx0nvyHl.js";
|
|
3
|
+
import "./tooltip-3UDC9mw-.js";
|
|
4
|
+
import "./button-jFTF378X.js";
|
|
5
|
+
import "./modal-CuQR21UD.js";
|
|
6
|
+
import { t as code_block_default } from "./code-block-uZcUI59D.js";
|
|
7
|
+
import "./segmented-DBW9ignu.js";
|
|
8
|
+
|
|
9
|
+
export { code_block_default as default };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { t as CODE_PREVIEWERS } from "./previewers-
|
|
2
|
-
import { B as useContext, I as LANGUAGE_ALIAS, L as LANGUAGE_EXTENSIONS,
|
|
3
|
-
import { t as button_default } from "./button-
|
|
1
|
+
import { t as CODE_PREVIEWERS } from "./previewers-ByaS2Ksa.js";
|
|
2
|
+
import { B as useContext, I as LANGUAGE_ALIAS, L as LANGUAGE_EXTENSIONS, O as save, R as LANGUAGE_ICONS, V as useCodeOptions, a as useMermaid, u as useI18n, z as useControls } from "./composables-Cx0nvyHl.js";
|
|
3
|
+
import { t as button_default } from "./button-jFTF378X.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-DBW9ignu.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
|
|
|
@@ -104,14 +104,15 @@ var preview_segmented_vue_vue_type_script_setup_true_lang_default = /* @__PURE__
|
|
|
104
104
|
const mode = useModel(__props, "mode");
|
|
105
105
|
const collapsed = useModel(__props, "collapsed");
|
|
106
106
|
const { t } = useI18n();
|
|
107
|
+
const { icons } = useContext();
|
|
107
108
|
const SEGMENTED_OPTIONS = computed(() => [{
|
|
108
109
|
label: t("button.preview"),
|
|
109
110
|
value: "preview",
|
|
110
|
-
icon:
|
|
111
|
+
icon: icons.value.preview
|
|
111
112
|
}, {
|
|
112
113
|
label: t("button.source"),
|
|
113
114
|
value: "source",
|
|
114
|
-
icon:
|
|
115
|
+
icon: icons.value.code
|
|
115
116
|
}]);
|
|
116
117
|
return (_ctx, _cache) => {
|
|
117
118
|
return openBlock(), createBlock(segmented_default, {
|
|
@@ -204,11 +205,12 @@ var index_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCo
|
|
|
204
205
|
},
|
|
205
206
|
setup(__props) {
|
|
206
207
|
const props = __props;
|
|
207
|
-
const { controls, previewers } = toRefs(props);
|
|
208
|
+
const { controls, previewers, codeOptions } = toRefs(props);
|
|
208
209
|
const { t } = useI18n();
|
|
210
|
+
const { icons } = useContext();
|
|
209
211
|
const { isControlEnabled } = useControls({ controls });
|
|
210
212
|
const { installed: hasMermaid } = useMermaid();
|
|
211
|
-
const CodeNode = defineAsyncComponent(() => import("./code-
|
|
213
|
+
const CodeNode = defineAsyncComponent(() => import("./code-BxWvKFxG.js"));
|
|
212
214
|
const { onCopied } = useContext();
|
|
213
215
|
const { copy, copied } = useClipboard({ legacy: true });
|
|
214
216
|
const { saveMermaid } = useMermaid();
|
|
@@ -221,30 +223,39 @@ var index_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCo
|
|
|
221
223
|
if (LANGUAGE_ALIAS[lang]) return LANGUAGE_ALIAS[lang];
|
|
222
224
|
return lang;
|
|
223
225
|
});
|
|
224
|
-
const showLanguageIcon =
|
|
225
|
-
|
|
226
|
-
|
|
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;
|
|
226
|
+
const { showLanguageIcon, showLanguageName } = useCodeOptions({
|
|
227
|
+
codeOptions,
|
|
228
|
+
language
|
|
231
229
|
});
|
|
232
230
|
const showLanguageTitle = computed(() => showLanguageIcon.value || showLanguageName.value);
|
|
233
231
|
const showCollapse = computed(() => isControlEnabled("code.collapse"));
|
|
234
232
|
const showCopy = computed(() => isControlEnabled("code.copy"));
|
|
235
233
|
const showDownload = computed(() => isControlEnabled("code.download"));
|
|
236
234
|
const showFullscreen = computed(() => isControlEnabled("code.fullscreen"));
|
|
237
|
-
const icon = computed(() =>
|
|
235
|
+
const icon = computed(() => {
|
|
236
|
+
var _codeOptions$value;
|
|
237
|
+
const custom = (_codeOptions$value = codeOptions.value) === null || _codeOptions$value === void 0 || (_codeOptions$value = _codeOptions$value.language) === null || _codeOptions$value === void 0 || (_codeOptions$value = _codeOptions$value[language.value]) === null || _codeOptions$value === void 0 ? void 0 : _codeOptions$value.languageIcon;
|
|
238
|
+
if (typeof custom === "object") return custom;
|
|
239
|
+
return LANGUAGE_ICONS[language.value] || LANGUAGE_ICONS.text;
|
|
240
|
+
});
|
|
238
241
|
const previewable = computed(() => {
|
|
239
242
|
if (previewers.value === false) return false;
|
|
240
|
-
const mermaid = language.value === "mermaid" && hasMermaid.value;
|
|
241
243
|
const html = language.value === "html" && !props.node.loading;
|
|
244
|
+
const mermaid = language.value === "mermaid" && hasMermaid.value;
|
|
245
|
+
if (previewers.value === true) {
|
|
246
|
+
if (language.value === "html" && html) return true;
|
|
247
|
+
if (language.value === "mermaid" && mermaid) return true;
|
|
248
|
+
return false;
|
|
249
|
+
}
|
|
242
250
|
if (typeof previewers.value === "object") {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
251
|
+
if (previewers.value[language.value] === false) return false;
|
|
252
|
+
if (language.value === "html" && html) return true;
|
|
253
|
+
if (language.value === "mermaid" && mermaid) return true;
|
|
254
|
+
const component = previewers.value[language.value];
|
|
255
|
+
if (typeof component === "object" && !props.node.loading) return !!component;
|
|
256
|
+
return false;
|
|
246
257
|
}
|
|
247
|
-
return
|
|
258
|
+
return false;
|
|
248
259
|
});
|
|
249
260
|
const PreviewComponent = computed(() => {
|
|
250
261
|
if (!previewers.value || typeof previewers.value === "boolean") return CODE_PREVIEWERS[language.value];
|
|
@@ -275,7 +286,7 @@ var index_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCo
|
|
|
275
286
|
{
|
|
276
287
|
name: t("button.collapse"),
|
|
277
288
|
key: "collapse",
|
|
278
|
-
icon:
|
|
289
|
+
icon: icons.value.collapse,
|
|
279
290
|
iconStyle: {
|
|
280
291
|
transform: collapsed.value ? "rotate(180deg)" : void 0,
|
|
281
292
|
transition: "transform var(--default-transition-duration)"
|
|
@@ -286,7 +297,7 @@ var index_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCo
|
|
|
286
297
|
{
|
|
287
298
|
name: t("button.copy"),
|
|
288
299
|
key: "copy",
|
|
289
|
-
icon: copied.value ?
|
|
300
|
+
icon: copied.value ? icons.value.check : icons.value.copy,
|
|
290
301
|
visible: () => showCopy.value,
|
|
291
302
|
onClick: () => {
|
|
292
303
|
if (!props.node.value) return;
|
|
@@ -297,7 +308,7 @@ var index_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCo
|
|
|
297
308
|
{
|
|
298
309
|
name: t("button.download"),
|
|
299
310
|
key: "download",
|
|
300
|
-
icon:
|
|
311
|
+
icon: icons.value.download,
|
|
301
312
|
options: downloadOptions.value.length > 0 ? downloadOptions.value : void 0,
|
|
302
313
|
visible: () => showDownload.value && !!LANGUAGE_EXTENSIONS[language.value],
|
|
303
314
|
onClick: (_event, item) => {
|
|
@@ -313,7 +324,7 @@ var index_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCo
|
|
|
313
324
|
{
|
|
314
325
|
name: fullscreen.value ? t("button.minimize") : t("button.maximize"),
|
|
315
326
|
key: "fullscreen",
|
|
316
|
-
icon: fullscreen.value ?
|
|
327
|
+
icon: fullscreen.value ? icons.value.minimize : icons.value.maximize,
|
|
317
328
|
visible: () => showFullscreen.value,
|
|
318
329
|
onClick: () => fullscreen.value = !fullscreen.value
|
|
319
330
|
}
|
|
@@ -337,8 +348,8 @@ var index_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCo
|
|
|
337
348
|
key: 0,
|
|
338
349
|
icon: icon.value,
|
|
339
350
|
language: language.value,
|
|
340
|
-
"show-icon": showLanguageIcon
|
|
341
|
-
"show-name": showLanguageName
|
|
351
|
+
"show-icon": unref(showLanguageIcon),
|
|
352
|
+
"show-name": unref(showLanguageName)
|
|
342
353
|
}, null, 8, [
|
|
343
354
|
"icon",
|
|
344
355
|
"language",
|
|
@@ -370,8 +381,8 @@ var index_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCo
|
|
|
370
381
|
key: 0,
|
|
371
382
|
icon: icon.value,
|
|
372
383
|
language: language.value,
|
|
373
|
-
"show-icon": showLanguageIcon
|
|
374
|
-
"show-name": showLanguageName
|
|
384
|
+
"show-icon": unref(showLanguageIcon),
|
|
385
|
+
"show-name": unref(showLanguageName)
|
|
375
386
|
}, null, 8, [
|
|
376
387
|
"icon",
|
|
377
388
|
"language",
|
|
@@ -6,10 +6,37 @@ 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() {
|
|
12
38
|
const context = injectContext();
|
|
39
|
+
const icons = computed(() => unref(context.icons) ?? {});
|
|
13
40
|
const isDark = computed(() => unref(context.isDark) ?? false);
|
|
14
41
|
function provideContext(ctx) {
|
|
15
42
|
provide(CONTEXT_KEY, {
|
|
@@ -24,6 +51,7 @@ function useContext() {
|
|
|
24
51
|
context,
|
|
25
52
|
provideContext,
|
|
26
53
|
injectContext,
|
|
54
|
+
icons,
|
|
27
55
|
isDark,
|
|
28
56
|
get getContainer() {
|
|
29
57
|
return context.getContainer || (() => void 0);
|
|
@@ -624,21 +652,6 @@ const SHADCN_SCHEMAS = [
|
|
|
624
652
|
|
|
625
653
|
//#endregion
|
|
626
654
|
//#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
655
|
function parseUrl(url, defaultOrigin) {
|
|
643
656
|
if (typeof url !== "string") return null;
|
|
644
657
|
try {
|
|
@@ -649,13 +662,33 @@ function parseUrl(url, defaultOrigin) {
|
|
|
649
662
|
} catch {
|
|
650
663
|
return null;
|
|
651
664
|
}
|
|
665
|
+
if (url.startsWith("/") || url.startsWith("./") || url.startsWith("../")) try {
|
|
666
|
+
return new URL(url, "http://example.com");
|
|
667
|
+
} catch {
|
|
668
|
+
return null;
|
|
669
|
+
}
|
|
652
670
|
return null;
|
|
653
671
|
}
|
|
654
672
|
}
|
|
655
673
|
function isPathRelativeUrl(url) {
|
|
656
674
|
if (typeof url !== "string") return false;
|
|
657
|
-
return url.startsWith("/");
|
|
675
|
+
return url.startsWith("/") || url.startsWith("./") || url.startsWith("../");
|
|
658
676
|
}
|
|
677
|
+
const safeProtocols = new Set([
|
|
678
|
+
"https:",
|
|
679
|
+
"http:",
|
|
680
|
+
"irc:",
|
|
681
|
+
"ircs:",
|
|
682
|
+
"mailto:",
|
|
683
|
+
"xmpp:",
|
|
684
|
+
"blob:"
|
|
685
|
+
]);
|
|
686
|
+
const blockedProtocols = new Set([
|
|
687
|
+
"javascript:",
|
|
688
|
+
"data:",
|
|
689
|
+
"file:",
|
|
690
|
+
"vbscript:"
|
|
691
|
+
]);
|
|
659
692
|
function transformUrl(url, allowedPrefixes, defaultOrigin, allowDataImages = false, isImage = false, allowedProtocols = []) {
|
|
660
693
|
if (!url) return null;
|
|
661
694
|
if (typeof url === "string" && url.startsWith("#") && !isImage) try {
|
|
@@ -1397,7 +1430,11 @@ function useShiki(options) {
|
|
|
1397
1430
|
const darkTheme = computed(() => shikiTheme.value[1] ?? DEFAULT_DARK_THEME);
|
|
1398
1431
|
const langAlias = computed(() => {
|
|
1399
1432
|
var _unref2;
|
|
1400
|
-
|
|
1433
|
+
const data = ((_unref2 = unref(options === null || options === void 0 ? void 0 : options.shikiOptions)) === null || _unref2 === void 0 ? void 0 : _unref2.langAlias) ?? {};
|
|
1434
|
+
return {
|
|
1435
|
+
...LANGUAGE_ALIAS,
|
|
1436
|
+
...data
|
|
1437
|
+
};
|
|
1401
1438
|
});
|
|
1402
1439
|
const codeToTokenOptions = computed(() => {
|
|
1403
1440
|
var _unref3;
|
|
@@ -1415,7 +1452,7 @@ function useShiki(options) {
|
|
|
1415
1452
|
return theme.id;
|
|
1416
1453
|
}
|
|
1417
1454
|
async function getLanguage() {
|
|
1418
|
-
if (
|
|
1455
|
+
if (langAlias.value[lang.value]) return langAlias.value[lang.value];
|
|
1419
1456
|
const { bundledLanguagesInfo } = await import("shiki");
|
|
1420
1457
|
const language = bundledLanguagesInfo.find((l) => {
|
|
1421
1458
|
var _l$aliases;
|
|
@@ -1443,10 +1480,7 @@ function useShiki(options) {
|
|
|
1443
1480
|
return createHighlighter({
|
|
1444
1481
|
themes: [await getTheme()],
|
|
1445
1482
|
langs: [await getLanguage()],
|
|
1446
|
-
langAlias:
|
|
1447
|
-
...LANGUAGE_ALIAS,
|
|
1448
|
-
...langAlias.value
|
|
1449
|
-
}
|
|
1483
|
+
langAlias: langAlias.value
|
|
1450
1484
|
});
|
|
1451
1485
|
})();
|
|
1452
1486
|
highlighter = await createHighlighterPromise;
|
|
@@ -1561,6 +1595,8 @@ function useZoom(options = {}) {
|
|
|
1561
1595
|
x: 0,
|
|
1562
1596
|
y: 0
|
|
1563
1597
|
});
|
|
1598
|
+
const isPinching = ref(false);
|
|
1599
|
+
const touchZoomState = ref(null);
|
|
1564
1600
|
const transformStyle = computed(() => ({ transform: `translate(${translateX.value}px, ${translateY.value}px) scale(${zoom.value})` }));
|
|
1565
1601
|
function zoomIn() {
|
|
1566
1602
|
if (zoom.value < maxZoom) zoom.value = Math.min(zoom.value + zoomStep, maxZoom);
|
|
@@ -1577,6 +1613,7 @@ function useZoom(options = {}) {
|
|
|
1577
1613
|
zoom.value = Math.min(Math.max(value, minZoom), maxZoom);
|
|
1578
1614
|
}
|
|
1579
1615
|
function startDrag(e) {
|
|
1616
|
+
if (isPinching.value) return;
|
|
1580
1617
|
isDragging.value = true;
|
|
1581
1618
|
dragStart.value = {
|
|
1582
1619
|
x: e.clientX - translateX.value,
|
|
@@ -1587,7 +1624,7 @@ function useZoom(options = {}) {
|
|
|
1587
1624
|
}
|
|
1588
1625
|
}
|
|
1589
1626
|
function onDrag(e) {
|
|
1590
|
-
if (!isDragging.value) return;
|
|
1627
|
+
if (!isDragging.value || isPinching.value) return;
|
|
1591
1628
|
translateX.value = e.clientX - dragStart.value.x;
|
|
1592
1629
|
translateY.value = e.clientY - dragStart.value.y;
|
|
1593
1630
|
}
|
|
@@ -1615,6 +1652,65 @@ function useZoom(options = {}) {
|
|
|
1615
1652
|
}
|
|
1616
1653
|
}
|
|
1617
1654
|
}
|
|
1655
|
+
function getTouchDistance(touch1, touch2) {
|
|
1656
|
+
const dx = touch1.clientX - touch2.clientX;
|
|
1657
|
+
const dy = touch1.clientY - touch2.clientY;
|
|
1658
|
+
return Math.sqrt(dx * dx + dy * dy);
|
|
1659
|
+
}
|
|
1660
|
+
function handleTouchStart(event, containerElement) {
|
|
1661
|
+
if (event.touches.length === 2) {
|
|
1662
|
+
event.preventDefault();
|
|
1663
|
+
isPinching.value = true;
|
|
1664
|
+
const touch1 = event.touches[0];
|
|
1665
|
+
const touch2 = event.touches[1];
|
|
1666
|
+
const distance = getTouchDistance(touch1, touch2);
|
|
1667
|
+
const centerX = (touch1.clientX + touch2.clientX) / 2;
|
|
1668
|
+
const centerY = (touch1.clientY + touch2.clientY) / 2;
|
|
1669
|
+
const rect = containerElement.getBoundingClientRect();
|
|
1670
|
+
const containerCenterX = rect.width / 2;
|
|
1671
|
+
const containerCenterY = rect.height / 2;
|
|
1672
|
+
const offsetX = centerX - rect.left - containerCenterX;
|
|
1673
|
+
const offsetY = centerY - rect.top - containerCenterY;
|
|
1674
|
+
touchZoomState.value = {
|
|
1675
|
+
initialDistance: distance,
|
|
1676
|
+
initialZoom: zoom.value,
|
|
1677
|
+
initialTranslateX: translateX.value,
|
|
1678
|
+
initialTranslateY: translateY.value,
|
|
1679
|
+
centerX: offsetX,
|
|
1680
|
+
centerY: offsetY
|
|
1681
|
+
};
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1684
|
+
function handleTouchMove(event, containerElement) {
|
|
1685
|
+
if (event.touches.length === 2 && touchZoomState.value) {
|
|
1686
|
+
event.preventDefault();
|
|
1687
|
+
const touch1 = event.touches[0];
|
|
1688
|
+
const touch2 = event.touches[1];
|
|
1689
|
+
const scale = getTouchDistance(touch1, touch2) / touchZoomState.value.initialDistance;
|
|
1690
|
+
const newZoom = touchZoomState.value.initialZoom * scale;
|
|
1691
|
+
const clampedZoom = Math.min(Math.max(newZoom, minZoom), maxZoom);
|
|
1692
|
+
if (clampedZoom !== zoom.value) {
|
|
1693
|
+
const centerX = (touch1.clientX + touch2.clientX) / 2;
|
|
1694
|
+
const centerY = (touch1.clientY + touch2.clientY) / 2;
|
|
1695
|
+
const rect = containerElement.getBoundingClientRect();
|
|
1696
|
+
const containerCenterX = rect.width / 2;
|
|
1697
|
+
const containerCenterY = rect.height / 2;
|
|
1698
|
+
const offsetX = centerX - rect.left - containerCenterX;
|
|
1699
|
+
const offsetY = centerY - rect.top - containerCenterY;
|
|
1700
|
+
const contentFocalX = (touchZoomState.value.centerX - touchZoomState.value.initialTranslateX) / touchZoomState.value.initialZoom;
|
|
1701
|
+
const contentFocalY = (touchZoomState.value.centerY - touchZoomState.value.initialTranslateY) / touchZoomState.value.initialZoom;
|
|
1702
|
+
zoom.value = clampedZoom;
|
|
1703
|
+
translateX.value = offsetX - contentFocalX * clampedZoom;
|
|
1704
|
+
translateY.value = offsetY - contentFocalY * clampedZoom;
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
1707
|
+
}
|
|
1708
|
+
function handleTouchEnd(event) {
|
|
1709
|
+
if (event.touches.length < 2) {
|
|
1710
|
+
touchZoomState.value = null;
|
|
1711
|
+
isPinching.value = false;
|
|
1712
|
+
}
|
|
1713
|
+
}
|
|
1618
1714
|
function getState() {
|
|
1619
1715
|
return {
|
|
1620
1716
|
zoom: zoom.value,
|
|
@@ -1642,9 +1738,12 @@ function useZoom(options = {}) {
|
|
|
1642
1738
|
stopDrag,
|
|
1643
1739
|
handleWheel,
|
|
1644
1740
|
getState,
|
|
1645
|
-
setState
|
|
1741
|
+
setState,
|
|
1742
|
+
handleTouchStart,
|
|
1743
|
+
handleTouchMove,
|
|
1744
|
+
handleTouchEnd
|
|
1646
1745
|
};
|
|
1647
1746
|
}
|
|
1648
1747
|
|
|
1649
1748
|
//#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 };
|
|
1749
|
+
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 };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { B as useContext, u as useI18n } from "./composables-Cx0nvyHl.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
|
|
@@ -25,6 +25,7 @@ var error_component_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ *
|
|
|
25
25
|
setup(__props) {
|
|
26
26
|
const props = __props;
|
|
27
27
|
const { t } = useI18n();
|
|
28
|
+
const { icons } = useContext();
|
|
28
29
|
const messages = computed(() => ({
|
|
29
30
|
"vanilla": t("error.vanilla"),
|
|
30
31
|
"image": t("error.image"),
|
|
@@ -35,8 +36,8 @@ var error_component_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ *
|
|
|
35
36
|
}));
|
|
36
37
|
const icon = computed(() => {
|
|
37
38
|
if (props.icon) return props.icon;
|
|
38
|
-
if (
|
|
39
|
-
return
|
|
39
|
+
if (icons.value[props.variant]) return icons.value[props.variant];
|
|
40
|
+
return icons.value[props.variant.replace("harden-", "")] || icons.value.error;
|
|
40
41
|
});
|
|
41
42
|
const message = computed(() => props.message ? props.message : messages.value[props.variant] || messages.value.vanilla);
|
|
42
43
|
const isHarden = computed(() => {
|
|
@@ -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 { B as useContext, O as save, g as useHardenSanitizers, u as useI18n, z as useControls } from "./composables-Cx0nvyHl.js";
|
|
2
|
+
import "./tooltip-3UDC9mw-.js";
|
|
3
|
+
import { t as button_default } from "./button-jFTF378X.js";
|
|
4
|
+
import { t as error_component_default } from "./error-component-Bhl770lu.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
|
|
|
@@ -84,6 +84,7 @@ var image_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCo
|
|
|
84
84
|
const props = __props;
|
|
85
85
|
const fileExtensionPattern = /\.[^/.]+$/;
|
|
86
86
|
const { t } = useI18n();
|
|
87
|
+
const { icons } = useContext();
|
|
87
88
|
const { controls, hardenOptions } = toRefs(props);
|
|
88
89
|
const { isControlEnabled } = useControls({ controls });
|
|
89
90
|
const imgRef = ref();
|
|
@@ -167,7 +168,7 @@ var image_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCo
|
|
|
167
168
|
}, [!isLoading.value && showDownload.value ? (openBlock(), createBlock(button_default, {
|
|
168
169
|
key: 0,
|
|
169
170
|
"data-stream-markdown": "image-download-button",
|
|
170
|
-
icon: unref(
|
|
171
|
+
icon: unref(icons).download,
|
|
171
172
|
name: unref(t)("button.download"),
|
|
172
173
|
"icon-class": "test",
|
|
173
174
|
"icon-width": 16,
|