@hejiayue/x-markdown-test 0.0.1-beta.135 → 0.0.1-beta.138
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/dist/x-markdown.cjs19.js +1 -1
- package/dist/x-markdown.cjs24.js +1 -1
- package/dist/x-markdown.cjs27.js +1 -1
- package/dist/x-markdown.cjs27.js.map +1 -1
- package/dist/x-markdown.cjs29.js +2 -0
- package/dist/x-markdown.cjs29.js.map +1 -0
- package/dist/x-markdown.cjs31.js +1 -1
- package/dist/x-markdown.cjs31.js.map +1 -1
- package/dist/x-markdown.cjs32.js +2 -0
- package/dist/x-markdown.cjs32.js.map +1 -0
- package/dist/x-markdown.cjs7.js +1 -1
- package/dist/x-markdown.cjs7.js.map +1 -1
- package/dist/x-markdown.es19.js +1 -1
- package/dist/x-markdown.es24.js +1 -1
- package/dist/x-markdown.es27.js +139 -5
- package/dist/x-markdown.es27.js.map +1 -1
- package/dist/x-markdown.es29.js +8 -0
- package/dist/x-markdown.es29.js.map +1 -0
- package/dist/x-markdown.es31.js +2 -121
- package/dist/x-markdown.es31.js.map +1 -1
- package/dist/x-markdown.es32.js +125 -0
- package/dist/x-markdown.es32.js.map +1 -0
- package/dist/x-markdown.es7.js +32 -8
- package/dist/x-markdown.es7.js.map +1 -1
- package/package.json +5 -3
- package/src/vite-plugin.js +120 -0
- package/dist/x-markdown.cjs28.js +0 -2
- package/dist/x-markdown.cjs28.js.map +0 -1
- package/dist/x-markdown.cjs33.js +0 -2
- package/dist/x-markdown.cjs33.js.map +0 -1
- package/dist/x-markdown.es28.js +0 -142
- package/dist/x-markdown.es28.js.map +0 -1
- package/dist/x-markdown.es33.js +0 -6
- package/dist/x-markdown.es33.js.map +0 -1
package/dist/x-markdown.es31.js
CHANGED
|
@@ -1,124 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
const _hoisted_1 = { class: "x-md-syntax-code-block" };
|
|
4
|
-
const _hoisted_2 = { class: "x-md-code-content" };
|
|
5
|
-
const _hoisted_3 = { key: 0 };
|
|
6
|
-
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
7
|
-
...{
|
|
8
|
-
name: "SyntaxCodeBlock"
|
|
9
|
-
},
|
|
10
|
-
__name: "SyntaxCodeBlock",
|
|
11
|
-
props: {
|
|
12
|
-
code: {},
|
|
13
|
-
language: {},
|
|
14
|
-
lightTheme: { default: "vitesse-light" },
|
|
15
|
-
darkTheme: { default: "vitesse-dark" },
|
|
16
|
-
isDark: { type: Boolean, default: false },
|
|
17
|
-
colorReplacements: {},
|
|
18
|
-
codeMaxHeight: {},
|
|
19
|
-
enableAnimate: { type: Boolean, default: false }
|
|
20
|
-
},
|
|
21
|
-
setup(__props, { expose: __expose }) {
|
|
22
|
-
const props = __props;
|
|
23
|
-
const code = computed(() => props.code.trim());
|
|
24
|
-
const language = computed(() => props.language || "text");
|
|
25
|
-
const actualTheme = computed(() => props.isDark ? props.darkTheme : props.lightTheme);
|
|
26
|
-
const { lines, preStyle } = useHighlight(code, {
|
|
27
|
-
language,
|
|
28
|
-
theme: actualTheme,
|
|
29
|
-
colorReplacements: props.colorReplacements
|
|
30
|
-
});
|
|
31
|
-
const applyColorReplacement = (color, replacements) => {
|
|
32
|
-
if (!replacements) return color;
|
|
33
|
-
return replacements[color.toLowerCase()] || color;
|
|
34
|
-
};
|
|
35
|
-
const normalizeStyleKeys = (style) => {
|
|
36
|
-
const normalized = {};
|
|
37
|
-
Object.entries(style).forEach(([key, value]) => {
|
|
38
|
-
const camelKey = key.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
|
|
39
|
-
normalized[camelKey] = value;
|
|
40
|
-
});
|
|
41
|
-
return normalized;
|
|
42
|
-
};
|
|
43
|
-
const getTokenStyle = (token) => {
|
|
44
|
-
if (!token) {
|
|
45
|
-
return {};
|
|
46
|
-
}
|
|
47
|
-
if (token.htmlStyle) {
|
|
48
|
-
const baseStyle = normalizeStyleKeys(token.htmlStyle);
|
|
49
|
-
if (!props.colorReplacements) return baseStyle;
|
|
50
|
-
const style2 = { ...baseStyle };
|
|
51
|
-
if (style2.color && typeof style2.color === "string") {
|
|
52
|
-
style2.color = applyColorReplacement(style2.color, props.colorReplacements);
|
|
53
|
-
}
|
|
54
|
-
if (style2.backgroundColor && typeof style2.backgroundColor === "string") {
|
|
55
|
-
style2.backgroundColor = applyColorReplacement(style2.backgroundColor, props.colorReplacements);
|
|
56
|
-
}
|
|
57
|
-
return style2;
|
|
58
|
-
}
|
|
59
|
-
const style = {};
|
|
60
|
-
if (token.color) {
|
|
61
|
-
style.color = props.colorReplacements ? applyColorReplacement(token.color, props.colorReplacements) : token.color;
|
|
62
|
-
}
|
|
63
|
-
if (token.fontStyle === "italic") {
|
|
64
|
-
style.fontStyle = "italic";
|
|
65
|
-
}
|
|
66
|
-
if (token.fontWeight) {
|
|
67
|
-
style.fontWeight = token.fontWeight;
|
|
68
|
-
}
|
|
69
|
-
return style;
|
|
70
|
-
};
|
|
71
|
-
const showFallback = computed(() => !lines.value?.length);
|
|
72
|
-
const codeContainerStyle = computed(() => ({
|
|
73
|
-
...preStyle.value,
|
|
74
|
-
maxHeight: props.codeMaxHeight
|
|
75
|
-
}));
|
|
76
|
-
__expose({
|
|
77
|
-
lines,
|
|
78
|
-
code,
|
|
79
|
-
language,
|
|
80
|
-
actualTheme
|
|
81
|
-
});
|
|
82
|
-
return (_ctx, _cache) => {
|
|
83
|
-
return openBlock(), createElementBlock("div", _hoisted_1, [
|
|
84
|
-
showFallback.value ? (openBlock(), createElementBlock("pre", {
|
|
85
|
-
key: 0,
|
|
86
|
-
style: normalizeStyle(codeContainerStyle.value)
|
|
87
|
-
}, [
|
|
88
|
-
createElementVNode("code", null, toDisplayString(code.value), 1)
|
|
89
|
-
], 4)) : (openBlock(), createElementBlock("pre", {
|
|
90
|
-
key: 1,
|
|
91
|
-
class: normalizeClass(["shiki", actualTheme.value]),
|
|
92
|
-
style: normalizeStyle(codeContainerStyle.value),
|
|
93
|
-
tabindex: "0"
|
|
94
|
-
}, [
|
|
95
|
-
_cache[4] || (_cache[4] = createTextVNode(" ", -1)),
|
|
96
|
-
createElementVNode("code", _hoisted_2, [
|
|
97
|
-
_cache[2] || (_cache[2] = createTextVNode("\n ", -1)),
|
|
98
|
-
(openBlock(true), createElementBlock(Fragment, null, renderList(unref(lines), (line, i) => {
|
|
99
|
-
return openBlock(), createElementBlock("span", {
|
|
100
|
-
key: i,
|
|
101
|
-
class: "x-md-code-line"
|
|
102
|
-
}, [
|
|
103
|
-
_cache[0] || (_cache[0] = createTextVNode("\n ", -1)),
|
|
104
|
-
!line.length ? (openBlock(), createElementBlock("span", _hoisted_3, " ")) : (openBlock(true), createElementBlock(Fragment, { key: 1 }, renderList(line, (token, j) => {
|
|
105
|
-
return openBlock(), createElementBlock("span", {
|
|
106
|
-
key: j,
|
|
107
|
-
style: normalizeStyle(getTokenStyle(token)),
|
|
108
|
-
class: normalizeClass({ "x-md-animated-word": props.enableAnimate })
|
|
109
|
-
}, toDisplayString(token.content), 7);
|
|
110
|
-
}), 128)),
|
|
111
|
-
_cache[1] || (_cache[1] = createTextVNode("\n ", -1))
|
|
112
|
-
]);
|
|
113
|
-
}), 128)),
|
|
114
|
-
_cache[3] || (_cache[3] = createTextVNode("\n ", -1))
|
|
115
|
-
]),
|
|
116
|
-
_cache[5] || (_cache[5] = createTextVNode("\n ", -1))
|
|
117
|
-
], 6))
|
|
118
|
-
]);
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
});
|
|
1
|
+
import _sfc_main from "./x-markdown.es27.js";
|
|
2
|
+
/* empty css */
|
|
122
3
|
export {
|
|
123
4
|
_sfc_main as default
|
|
124
5
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"x-markdown.es31.js","sources":[
|
|
1
|
+
{"version":3,"file":"x-markdown.es31.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { defineComponent, computed, createElementBlock, openBlock, normalizeStyle, createElementVNode, toDisplayString, normalizeClass, createTextVNode, Fragment, renderList, unref } from "vue";
|
|
2
|
+
import { useHighlight } from "./x-markdown.es7.js";
|
|
3
|
+
const _hoisted_1 = { class: "x-md-syntax-code-block" };
|
|
4
|
+
const _hoisted_2 = { class: "x-md-code-content" };
|
|
5
|
+
const _hoisted_3 = { key: 0 };
|
|
6
|
+
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
7
|
+
...{
|
|
8
|
+
name: "SyntaxCodeBlock"
|
|
9
|
+
},
|
|
10
|
+
__name: "SyntaxCodeBlock",
|
|
11
|
+
props: {
|
|
12
|
+
code: {},
|
|
13
|
+
language: {},
|
|
14
|
+
lightTheme: { default: "vitesse-light" },
|
|
15
|
+
darkTheme: { default: "vitesse-dark" },
|
|
16
|
+
isDark: { type: Boolean, default: false },
|
|
17
|
+
colorReplacements: {},
|
|
18
|
+
codeMaxHeight: {},
|
|
19
|
+
enableAnimate: { type: Boolean, default: false }
|
|
20
|
+
},
|
|
21
|
+
setup(__props, { expose: __expose }) {
|
|
22
|
+
const props = __props;
|
|
23
|
+
const code = computed(() => props.code.trim());
|
|
24
|
+
const language = computed(() => props.language || "text");
|
|
25
|
+
const actualTheme = computed(() => props.isDark ? props.darkTheme : props.lightTheme);
|
|
26
|
+
const { lines, preStyle } = useHighlight(code, {
|
|
27
|
+
language,
|
|
28
|
+
theme: actualTheme,
|
|
29
|
+
colorReplacements: props.colorReplacements
|
|
30
|
+
});
|
|
31
|
+
const applyColorReplacement = (color, replacements) => {
|
|
32
|
+
if (!replacements) return color;
|
|
33
|
+
return replacements[color.toLowerCase()] || color;
|
|
34
|
+
};
|
|
35
|
+
const normalizeStyleKeys = (style) => {
|
|
36
|
+
const normalized = {};
|
|
37
|
+
Object.entries(style).forEach(([key, value]) => {
|
|
38
|
+
const camelKey = key.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
|
|
39
|
+
normalized[camelKey] = value;
|
|
40
|
+
});
|
|
41
|
+
return normalized;
|
|
42
|
+
};
|
|
43
|
+
const getTokenStyle = (token) => {
|
|
44
|
+
if (!token) {
|
|
45
|
+
return {};
|
|
46
|
+
}
|
|
47
|
+
if (token.htmlStyle) {
|
|
48
|
+
const baseStyle = normalizeStyleKeys(token.htmlStyle);
|
|
49
|
+
if (!props.colorReplacements) return baseStyle;
|
|
50
|
+
const style2 = { ...baseStyle };
|
|
51
|
+
if (style2.color && typeof style2.color === "string") {
|
|
52
|
+
style2.color = applyColorReplacement(style2.color, props.colorReplacements);
|
|
53
|
+
}
|
|
54
|
+
if (style2.backgroundColor && typeof style2.backgroundColor === "string") {
|
|
55
|
+
style2.backgroundColor = applyColorReplacement(style2.backgroundColor, props.colorReplacements);
|
|
56
|
+
}
|
|
57
|
+
return style2;
|
|
58
|
+
}
|
|
59
|
+
const style = {};
|
|
60
|
+
if (token.color) {
|
|
61
|
+
style.color = props.colorReplacements ? applyColorReplacement(token.color, props.colorReplacements) : token.color;
|
|
62
|
+
}
|
|
63
|
+
if (token.fontStyle === "italic") {
|
|
64
|
+
style.fontStyle = "italic";
|
|
65
|
+
}
|
|
66
|
+
if (token.fontWeight) {
|
|
67
|
+
style.fontWeight = token.fontWeight;
|
|
68
|
+
}
|
|
69
|
+
return style;
|
|
70
|
+
};
|
|
71
|
+
const showFallback = computed(() => !lines.value?.length);
|
|
72
|
+
const codeContainerStyle = computed(() => ({
|
|
73
|
+
...preStyle.value,
|
|
74
|
+
maxHeight: props.codeMaxHeight
|
|
75
|
+
}));
|
|
76
|
+
__expose({
|
|
77
|
+
lines,
|
|
78
|
+
code,
|
|
79
|
+
language,
|
|
80
|
+
actualTheme
|
|
81
|
+
});
|
|
82
|
+
return (_ctx, _cache) => {
|
|
83
|
+
return openBlock(), createElementBlock("div", _hoisted_1, [
|
|
84
|
+
showFallback.value ? (openBlock(), createElementBlock("pre", {
|
|
85
|
+
key: 0,
|
|
86
|
+
style: normalizeStyle(codeContainerStyle.value)
|
|
87
|
+
}, [
|
|
88
|
+
createElementVNode("code", null, toDisplayString(code.value), 1)
|
|
89
|
+
], 4)) : (openBlock(), createElementBlock("pre", {
|
|
90
|
+
key: 1,
|
|
91
|
+
class: normalizeClass(["shiki", actualTheme.value]),
|
|
92
|
+
style: normalizeStyle(codeContainerStyle.value),
|
|
93
|
+
tabindex: "0"
|
|
94
|
+
}, [
|
|
95
|
+
_cache[4] || (_cache[4] = createTextVNode(" ", -1)),
|
|
96
|
+
createElementVNode("code", _hoisted_2, [
|
|
97
|
+
_cache[2] || (_cache[2] = createTextVNode("\n ", -1)),
|
|
98
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList(unref(lines), (line, i) => {
|
|
99
|
+
return openBlock(), createElementBlock("span", {
|
|
100
|
+
key: i,
|
|
101
|
+
class: "x-md-code-line"
|
|
102
|
+
}, [
|
|
103
|
+
_cache[0] || (_cache[0] = createTextVNode("\n ", -1)),
|
|
104
|
+
!line.length ? (openBlock(), createElementBlock("span", _hoisted_3, " ")) : (openBlock(true), createElementBlock(Fragment, { key: 1 }, renderList(line, (token, j) => {
|
|
105
|
+
return openBlock(), createElementBlock("span", {
|
|
106
|
+
key: j,
|
|
107
|
+
style: normalizeStyle(getTokenStyle(token)),
|
|
108
|
+
class: normalizeClass({ "x-md-animated-word": props.enableAnimate })
|
|
109
|
+
}, toDisplayString(token.content), 7);
|
|
110
|
+
}), 128)),
|
|
111
|
+
_cache[1] || (_cache[1] = createTextVNode("\n ", -1))
|
|
112
|
+
]);
|
|
113
|
+
}), 128)),
|
|
114
|
+
_cache[3] || (_cache[3] = createTextVNode("\n ", -1))
|
|
115
|
+
]),
|
|
116
|
+
_cache[5] || (_cache[5] = createTextVNode("\n ", -1))
|
|
117
|
+
], 6))
|
|
118
|
+
]);
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
export {
|
|
123
|
+
_sfc_main as default
|
|
124
|
+
};
|
|
125
|
+
//# sourceMappingURL=x-markdown.es32.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"x-markdown.es32.js","sources":["../src/components/CodeBlock/SyntaxCodeBlock.vue"],"sourcesContent":["<template>\r\n <div class=\"x-md-syntax-code-block\">\r\n <pre v-if=\"showFallback\" :style=\"codeContainerStyle\"><code>{{ code }}</code></pre>\r\n <pre v-else :class=\"['shiki', actualTheme]\" :style=\"codeContainerStyle\" tabindex=\"0\">\r\n <code class=\"x-md-code-content\">\r\n <span v-for=\"(line, i) in lines\" :key=\"i\" class=\"x-md-code-line\">\r\n <span v-if=\"!line.length\"> </span>\r\n <span \r\n v-else \r\n v-for=\"(token, j) in line\" \r\n :key=\"j\" \r\n :style=\"getTokenStyle(token)\"\r\n :class=\"{ 'x-md-animated-word': props.enableAnimate }\"\r\n >{{ token.content }}</span>\r\n </span>\r\n </code>\r\n </pre>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { computed, type CSSProperties } from 'vue'\r\nimport { useHighlight } from '../../hooks/useHighlight'\r\nimport type { SyntaxCodeBlockProps } from './types'\r\n\r\ninterface HighlightToken {\r\n content?: string\r\n color?: string\r\n fontStyle?: 'italic' | null\r\n fontWeight?: 'normal' | 'bold' | null\r\n htmlStyle?: Record<string, string>\r\n}\r\n\r\ndefineOptions({\r\n name: 'SyntaxCodeBlock',\r\n})\r\n\r\nconst props = withDefaults(defineProps<SyntaxCodeBlockProps>(), {\r\n lightTheme: 'vitesse-light',\r\n darkTheme: 'vitesse-dark',\r\n isDark: false,\r\n enableAnimate: false,\r\n})\r\n\r\nconst code = computed(() => props.code.trim())\r\n\r\nconst language = computed(() => props.language || 'text')\r\n\r\nconst actualTheme = computed(() => (props.isDark ? props.darkTheme : props.lightTheme))\r\n\r\nconst { lines, preStyle } = useHighlight(code, {\r\n language,\r\n theme: actualTheme,\r\n colorReplacements: props.colorReplacements,\r\n})\r\n\r\nconst applyColorReplacement = (color: string, replacements?: Record<string, string>) => {\r\n if (!replacements) return color\r\n return replacements[color.toLowerCase()] || color\r\n}\r\n\r\nconst normalizeStyleKeys = (style: Record<string, string | number>): CSSProperties => {\r\n const normalized: CSSProperties = {}\r\n Object.entries(style).forEach(([key, value]) => {\r\n const camelKey = key.replace(/-([a-z])/g, (_, char) => char.toUpperCase())\r\n ;(normalized as Record<string, string | number>)[camelKey] = value\r\n })\r\n return normalized\r\n}\r\n\r\nconst getTokenStyle = (token: HighlightToken | null | undefined): CSSProperties => {\r\n // 处理 null/undefined token\r\n if (!token) {\r\n return {}\r\n }\r\n\r\n // 优先使用 htmlStyle(如果存在)\r\n if (token.htmlStyle) {\r\n const baseStyle = normalizeStyleKeys(token.htmlStyle)\r\n\r\n if (!props.colorReplacements) return baseStyle\r\n\r\n const style = { ...baseStyle }\r\n\r\n if (style.color && typeof style.color === 'string') {\r\n style.color = applyColorReplacement(style.color, props.colorReplacements)\r\n }\r\n if (style.backgroundColor && typeof style.backgroundColor === 'string') {\r\n style.backgroundColor = applyColorReplacement(style.backgroundColor, props.colorReplacements)\r\n }\r\n\r\n return style\r\n }\r\n\r\n // 直接使用 token 的 color、fontStyle、fontWeight 属性\r\n const style: CSSProperties = {}\r\n\r\n if (token.color) {\r\n style.color = props.colorReplacements\r\n ? applyColorReplacement(token.color, props.colorReplacements)\r\n : token.color\r\n }\r\n\r\n if (token.fontStyle === 'italic') {\r\n style.fontStyle = 'italic'\r\n }\r\n\r\n if (token.fontWeight) {\r\n style.fontWeight = token.fontWeight\r\n }\r\n\r\n return style\r\n}\r\n\r\nconst showFallback = computed(() => !lines.value?.length)\r\n\r\nconst codeContainerStyle = computed(() => ({\r\n ...preStyle.value,\r\n maxHeight: props.codeMaxHeight,\r\n}))\r\n\r\ndefineExpose({\r\n lines,\r\n code,\r\n language,\r\n actualTheme,\r\n})\r\n</script>\r\n\r\n<style scoped>\r\n.x-md-syntax-code-block {\r\n width: 100%;\r\n}\r\n\r\n.x-md-syntax-code-block pre {\r\n margin: 0;\r\n padding: 16px;\r\n overflow: auto;\r\n background: transparent !important;\r\n}\r\n\r\n.x-md-code-content {\r\n display: flex;\r\n flex-direction: column;\r\n}\r\n\r\n.x-md-code-line {\r\n width: 100%;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n display: flex;\r\n}\r\n</style>"],"names":["style","_openBlock","_createElementBlock","_createElementVNode","_Fragment","_renderList","_unref","_normalizeStyle","_normalizeClass","_toDisplayString"],"mappings":"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"}
|
package/dist/x-markdown.es7.js
CHANGED
|
@@ -1,21 +1,43 @@
|
|
|
1
1
|
import { ref, computed, isRef, toValue, watch, onUnmounted } from "vue";
|
|
2
2
|
let shikiModulePromise = null;
|
|
3
3
|
let shikiStreamModulePromise = null;
|
|
4
|
-
let
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
let hasShownShikiHint = false;
|
|
5
|
+
let hasShownShikiStreamHint = false;
|
|
6
|
+
const showShikiHint = () => {
|
|
7
|
+
if (hasShownShikiHint) return;
|
|
8
|
+
hasShownShikiHint = true;
|
|
8
9
|
console.log(
|
|
9
|
-
"%c[x-markdown]%c
|
|
10
|
+
"%c[x-markdown]%c Shiki 代码高亮库未安装,已降级为纯文本模式",
|
|
10
11
|
"font-weight: bold; color: #0066cc;",
|
|
11
12
|
"color: #666;"
|
|
12
13
|
);
|
|
13
14
|
console.log(
|
|
14
|
-
"%c
|
|
15
|
+
"%c如需语法高亮功能,请安装:",
|
|
15
16
|
"color: #666; font-weight: bold;"
|
|
16
17
|
);
|
|
17
18
|
console.log(
|
|
18
|
-
"%c pnpm add shiki
|
|
19
|
+
"%c pnpm add shiki",
|
|
20
|
+
"color: #00aa00; font-family: monospace;"
|
|
21
|
+
);
|
|
22
|
+
console.log(
|
|
23
|
+
"%c安装后请重启开发服务器",
|
|
24
|
+
"color: #999; font-size: 12px;"
|
|
25
|
+
);
|
|
26
|
+
};
|
|
27
|
+
const showShikiStreamHint = () => {
|
|
28
|
+
if (hasShownShikiStreamHint) return;
|
|
29
|
+
hasShownShikiStreamHint = true;
|
|
30
|
+
console.log(
|
|
31
|
+
"%c[x-markdown]%c shiki-stream 未安装,已降级为非流式高亮",
|
|
32
|
+
"font-weight: bold; color: #0066cc;",
|
|
33
|
+
"color: #666;"
|
|
34
|
+
);
|
|
35
|
+
console.log(
|
|
36
|
+
"%c如需流式代码高亮功能(推荐用于 AI 场景),请安装:",
|
|
37
|
+
"color: #666; font-weight: bold;"
|
|
38
|
+
);
|
|
39
|
+
console.log(
|
|
40
|
+
"%c pnpm add shiki-stream",
|
|
19
41
|
"color: #00aa00; font-family: monospace;"
|
|
20
42
|
);
|
|
21
43
|
console.log(
|
|
@@ -178,7 +200,7 @@ function useHighlight(text, options) {
|
|
|
178
200
|
lines: [[{ content: text.value }]],
|
|
179
201
|
preStyle: void 0
|
|
180
202
|
};
|
|
181
|
-
|
|
203
|
+
showShikiHint();
|
|
182
204
|
return;
|
|
183
205
|
}
|
|
184
206
|
highlighter = await mod.createHighlighter({
|
|
@@ -201,6 +223,8 @@ function useHighlight(text, options) {
|
|
|
201
223
|
lang: currentLang,
|
|
202
224
|
theme: currentTheme
|
|
203
225
|
});
|
|
226
|
+
} else {
|
|
227
|
+
showShikiStreamHint();
|
|
204
228
|
}
|
|
205
229
|
previousText = "";
|
|
206
230
|
const themeInfo = highlighter.getTheme(currentTheme);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"x-markdown.es7.js","sources":["../src/hooks/useHighlight.ts"],"sourcesContent":["import { ref, watch, onUnmounted, computed, isRef, toValue, type Ref, type MaybeRef, type CSSProperties } from 'vue'\r\n\r\ninterface HighlightToken {\r\n content?: string\r\n color?: string\r\n fontStyle?: 'italic' | null\r\n fontWeight?: 'normal' | 'bold' | null\r\n htmlStyle?: Record<string, string>\r\n}\r\n\r\ninterface StreamingHighlightResult {\r\n colorReplacements?: Record<string, string>\r\n lines: HighlightToken[][]\r\n preStyle?: CSSProperties\r\n}\r\n\r\ninterface UseHighlightOptions {\r\n language: MaybeRef<string>\r\n theme?: string | Ref<string>\r\n colorReplacements?: Record<string, string>\r\n}\r\n\r\nlet shikiModulePromise: Promise<any | null> | null = null\r\nlet shikiStreamModulePromise: Promise<any | null> | null = null\r\nlet hasShownDependencyHint = false\r\n\r\n\r\nconst showDependencyHint = () => {\r\n if (hasShownDependencyHint) return\r\n hasShownDependencyHint = true\r\n\r\n console.log(\r\n '%c[x-markdown]%c 代码高亮功能已降级为纯文本模式',\r\n 'font-weight: bold; color: #0066cc;',\r\n 'color: #666;'\r\n )\r\n console.log(\r\n '%c如需语法高亮功能,请安装以下依赖:',\r\n 'color: #666; font-weight: bold;'\r\n )\r\n console.log(\r\n '%c pnpm add shiki shiki-stream',\r\n 'color: #00aa00; font-family: monospace;'\r\n )\r\n console.log(\r\n '%c安装后请重启开发服务器',\r\n 'color: #999; font-size: 12px;'\r\n )\r\n}\r\n\r\nconst loadShiki = async () => {\r\n if (!shikiModulePromise) {\r\n shikiModulePromise = (async () => {\r\n try {\r\n const mod = await import('shiki')\r\n return mod\r\n } catch {\r\n // 静默失败,返回 null\r\n return null\r\n }\r\n })()\r\n }\r\n return shikiModulePromise\r\n}\r\n\r\nconst loadShikiStream = async () => {\r\n if (!shikiStreamModulePromise) {\r\n shikiStreamModulePromise = (async () => {\r\n try {\r\n const mod = await import('shiki-stream')\r\n return mod\r\n } catch {\r\n // 静默失败,返回 null\r\n return null\r\n }\r\n })()\r\n }\r\n return shikiStreamModulePromise\r\n}\r\n\r\nconst tokensToLineTokens = (tokens: HighlightToken[]): HighlightToken[][] => {\r\n if (!tokens.length) return [[]]\r\n\r\n const lines: HighlightToken[][] = [[]]\r\n let currentLine = lines[0]\r\n\r\n const startNewLine = () => {\r\n currentLine = []\r\n lines.push(currentLine)\r\n }\r\n\r\n tokens.forEach((token) => {\r\n const content = token.content ?? ''\r\n\r\n if (content === '\\n') {\r\n startNewLine()\r\n return\r\n }\r\n\r\n if (!content.includes('\\n')) {\r\n currentLine.push(token)\r\n return\r\n }\r\n\r\n const segments = content.split('\\n')\r\n segments.forEach((segment, index) => {\r\n if (segment) {\r\n currentLine.push({\r\n ...token,\r\n content: segment,\r\n })\r\n }\r\n\r\n if (index < segments.length - 1) {\r\n startNewLine()\r\n }\r\n })\r\n })\r\n\r\n return lines.length === 0 ? [[]] : lines\r\n}\r\n\r\nconst createPreStyle = (bg?: string, fg?: string): CSSProperties | undefined => {\r\n if (!bg && !fg) return undefined\r\n return {\r\n backgroundColor: bg,\r\n color: fg,\r\n }\r\n}\r\n\r\nexport function useHighlight(text: Ref<string>, options: UseHighlightOptions) {\r\n const streaming = ref<StreamingHighlightResult>()\r\n const isLoading = ref(false)\r\n const error = ref<Error | null>(null)\r\n\r\n let tokenizer: any | null = null\r\n let previousText = ''\r\n let highlighter: any | null = null\r\n let currentUsedLang = ''\r\n let lastRequestedLang = ''\r\n\r\n const effectiveTheme = computed(() => {\r\n const theme = isRef(options.theme) ? options.theme.value : options.theme\r\n return theme || 'slack-dark'\r\n })\r\n\r\n const effectiveLanguage = computed(() => {\r\n return toValue(options.language) || 'text'\r\n })\r\n\r\n const lines = computed(() => streaming.value?.lines || [[]])\r\n const preStyle = computed(() => streaming.value?.preStyle)\r\n\r\n const updateTokens = async (nextText: string, forceReset = false) => {\r\n // 当有 tokenizer 时使用流式处理\r\n if (tokenizer) {\r\n if (forceReset) {\r\n tokenizer.clear()\r\n previousText = ''\r\n }\r\n\r\n const canAppend = !forceReset && nextText.startsWith(previousText)\r\n let chunk = nextText\r\n\r\n if (canAppend) {\r\n chunk = nextText.slice(previousText.length)\r\n } else if (!forceReset) {\r\n tokenizer.clear()\r\n }\r\n\r\n previousText = nextText\r\n\r\n if (!chunk) {\r\n const mergedTokens = [...tokenizer.tokensStable, ...tokenizer.tokensUnstable]\r\n streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: mergedTokens.length ? tokensToLineTokens(mergedTokens) : [[]],\r\n preStyle: streaming.value?.preStyle,\r\n }\r\n return\r\n }\r\n\r\n try {\r\n await tokenizer.enqueue(chunk)\r\n\r\n const mergedTokens = [...tokenizer.tokensStable, ...tokenizer.tokensUnstable]\r\n\r\n streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: tokensToLineTokens(mergedTokens),\r\n preStyle: streaming.value?.preStyle,\r\n }\r\n } catch (err) {\r\n console.error('[x-markdown] Streaming highlighting failed:', err)\r\n error.value = err as Error\r\n }\r\n } else if (highlighter) {\r\n // 当没有 tokenizer 但有 highlighter 时,使用非流式方式高亮\r\n // 这发生在 shiki 可用但 shiki-stream 不可用时\r\n try {\r\n const currentLang = currentUsedLang || 'plaintext'\r\n const currentTheme = effectiveTheme.value\r\n const tokens = highlighter.codeToTokens(nextText, {\r\n lang: currentLang,\r\n theme: currentTheme,\r\n })\r\n\r\n streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: tokensToLineTokens(tokens),\r\n preStyle: streaming.value?.preStyle,\r\n }\r\n } catch (err) {\r\n console.error('[x-markdown] Direct highlighting failed:', err)\r\n // 降级为纯文本\r\n streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: [[{ content: nextText }]],\r\n preStyle: streaming.value?.preStyle,\r\n }\r\n }\r\n }\r\n }\r\n\r\n const initHighlighter = async () => {\r\n isLoading.value = true\r\n error.value = null\r\n\r\n let currentLang = effectiveLanguage.value\r\n const currentTheme = effectiveTheme.value\r\n\r\n try {\r\n const mod = await loadShiki()\r\n if (!mod) {\r\n // 静默降级为纯文本\r\n streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: [[{ content: text.value }]],\r\n preStyle: undefined,\r\n }\r\n showDependencyHint()\r\n return\r\n }\r\n\r\n // shiki 3.x API\r\n highlighter = await mod.createHighlighter({\r\n themes: [currentTheme],\r\n langs: [], // 将动态加载语言\r\n })\r\n\r\n lastRequestedLang = currentLang\r\n\r\n try {\r\n await highlighter.loadLanguage(currentLang as any)\r\n currentUsedLang = currentLang\r\n } catch {\r\n currentLang = 'plaintext'\r\n currentUsedLang = 'plaintext'\r\n }\r\n\r\n // 动态加载 shiki-stream\r\n const shikiStreamMod = await loadShikiStream()\r\n if (shikiStreamMod) {\r\n tokenizer = new shikiStreamMod.ShikiStreamTokenizer({\r\n highlighter: highlighter,\r\n lang: currentLang,\r\n theme: currentTheme,\r\n })\r\n }\r\n\r\n previousText = ''\r\n\r\n const themeInfo = highlighter.getTheme(currentTheme)\r\n const preStyleValue = createPreStyle(themeInfo?.bg, themeInfo?.fg)\r\n\r\n if (text.value) {\r\n await updateTokens(text.value, true)\r\n if (streaming.value) {\r\n streaming.value.preStyle = preStyleValue\r\n }\r\n } else {\r\n streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: [[]],\r\n preStyle: preStyleValue,\r\n }\r\n }\r\n } catch (err) {\r\n // 静默降级\r\n streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: [[{ content: text.value }]],\r\n preStyle: undefined,\r\n }\r\n } finally {\r\n isLoading.value = false\r\n }\r\n }\r\n\r\n watch(\r\n () => [effectiveLanguage.value, effectiveTheme.value],\r\n async ([newLang]) => {\r\n const requestedLang = newLang as string\r\n\r\n if (\r\n highlighter &&\r\n currentUsedLang === 'plaintext' &&\r\n requestedLang !== lastRequestedLang &&\r\n requestedLang !== 'plaintext'\r\n ) {\r\n try {\r\n await highlighter.loadLanguage(requestedLang as any)\r\n initHighlighter()\r\n return\r\n } catch {\r\n lastRequestedLang = requestedLang\r\n return\r\n }\r\n }\r\n\r\n initHighlighter()\r\n },\r\n { immediate: true },\r\n )\r\n\r\n watch(text, async (newText) => {\r\n const requestedLang = effectiveLanguage.value\r\n if (\r\n highlighter &&\r\n currentUsedLang === 'plaintext' &&\r\n requestedLang !== lastRequestedLang &&\r\n requestedLang !== 'plaintext'\r\n ) {\r\n try {\r\n await highlighter.loadLanguage(requestedLang as any)\r\n await initHighlighter()\r\n return\r\n } catch {\r\n lastRequestedLang = requestedLang\r\n }\r\n }\r\n\r\n if (tokenizer || highlighter) {\r\n // 当有 tokenizer 或 highlighter 时都调用 updateTokens\r\n // updateTokens 内部会处理两种情况\r\n updateTokens(newText)\r\n } else {\r\n // 两者都没有时降级为纯文本\r\n streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: [[{ content: newText }]],\r\n preStyle: streaming.value?.preStyle,\r\n }\r\n }\r\n })\r\n\r\n onUnmounted(() => {\r\n tokenizer?.clear()\r\n tokenizer = null\r\n previousText = ''\r\n })\r\n\r\n return {\r\n streaming,\r\n lines,\r\n preStyle,\r\n isLoading,\r\n error,\r\n }\r\n}\r\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"x-markdown.es7.js","sources":["../src/hooks/useHighlight.ts"],"sourcesContent":["import { ref, watch, onUnmounted, computed, isRef, toValue, type Ref, type MaybeRef, type CSSProperties } from 'vue'\r\n\r\ninterface HighlightToken {\r\n content?: string\r\n color?: string\r\n fontStyle?: 'italic' | null\r\n fontWeight?: 'normal' | 'bold' | null\r\n htmlStyle?: Record<string, string>\r\n}\r\n\r\ninterface StreamingHighlightResult {\r\n colorReplacements?: Record<string, string>\r\n lines: HighlightToken[][]\r\n preStyle?: CSSProperties\r\n}\r\n\r\ninterface UseHighlightOptions {\r\n language: MaybeRef<string>\r\n theme?: string | Ref<string>\r\n colorReplacements?: Record<string, string>\r\n}\r\n\r\nlet shikiModulePromise: Promise<any | null> | null = null\r\nlet shikiStreamModulePromise: Promise<any | null> | null = null\r\nlet hasShownShikiHint = false\r\nlet hasShownShikiStreamHint = false\r\n\r\n\r\nconst showShikiHint = () => {\r\n if (hasShownShikiHint) return\r\n hasShownShikiHint = true\r\n\r\n console.log(\r\n '%c[x-markdown]%c Shiki 代码高亮库未安装,已降级为纯文本模式',\r\n 'font-weight: bold; color: #0066cc;',\r\n 'color: #666;'\r\n )\r\n console.log(\r\n '%c如需语法高亮功能,请安装:',\r\n 'color: #666; font-weight: bold;'\r\n )\r\n console.log(\r\n '%c pnpm add shiki',\r\n 'color: #00aa00; font-family: monospace;'\r\n )\r\n console.log(\r\n '%c安装后请重启开发服务器',\r\n 'color: #999; font-size: 12px;'\r\n )\r\n}\r\n\r\nconst showShikiStreamHint = () => {\r\n if (hasShownShikiStreamHint) return\r\n hasShownShikiStreamHint = true\r\n\r\n console.log(\r\n '%c[x-markdown]%c shiki-stream 未安装,已降级为非流式高亮',\r\n 'font-weight: bold; color: #0066cc;',\r\n 'color: #666;'\r\n )\r\n console.log(\r\n '%c如需流式代码高亮功能(推荐用于 AI 场景),请安装:',\r\n 'color: #666; font-weight: bold;'\r\n )\r\n console.log(\r\n '%c pnpm add shiki-stream',\r\n 'color: #00aa00; font-family: monospace;'\r\n )\r\n console.log(\r\n '%c安装后请重启开发服务器',\r\n 'color: #999; font-size: 12px;'\r\n )\r\n}\r\n\r\nconst loadShiki = async () => {\r\n if (!shikiModulePromise) {\r\n shikiModulePromise = (async () => {\r\n try {\r\n const mod = await import('shiki')\r\n return mod\r\n } catch {\r\n // 静默失败,返回 null\r\n return null\r\n }\r\n })()\r\n }\r\n return shikiModulePromise\r\n}\r\n\r\nconst loadShikiStream = async () => {\r\n if (!shikiStreamModulePromise) {\r\n shikiStreamModulePromise = (async () => {\r\n try {\r\n const mod = await import('shiki-stream')\r\n return mod\r\n } catch {\r\n // 静默失败,返回 null\r\n return null\r\n }\r\n })()\r\n }\r\n return shikiStreamModulePromise\r\n}\r\n\r\nconst tokensToLineTokens = (tokens: HighlightToken[]): HighlightToken[][] => {\r\n if (!tokens.length) return [[]]\r\n\r\n const lines: HighlightToken[][] = [[]]\r\n let currentLine = lines[0]\r\n\r\n const startNewLine = () => {\r\n currentLine = []\r\n lines.push(currentLine)\r\n }\r\n\r\n tokens.forEach((token) => {\r\n const content = token.content ?? ''\r\n\r\n if (content === '\\n') {\r\n startNewLine()\r\n return\r\n }\r\n\r\n if (!content.includes('\\n')) {\r\n currentLine.push(token)\r\n return\r\n }\r\n\r\n const segments = content.split('\\n')\r\n segments.forEach((segment, index) => {\r\n if (segment) {\r\n currentLine.push({\r\n ...token,\r\n content: segment,\r\n })\r\n }\r\n\r\n if (index < segments.length - 1) {\r\n startNewLine()\r\n }\r\n })\r\n })\r\n\r\n return lines.length === 0 ? [[]] : lines\r\n}\r\n\r\nconst createPreStyle = (bg?: string, fg?: string): CSSProperties | undefined => {\r\n if (!bg && !fg) return undefined\r\n return {\r\n backgroundColor: bg,\r\n color: fg,\r\n }\r\n}\r\n\r\nexport function useHighlight(text: Ref<string>, options: UseHighlightOptions) {\r\n const streaming = ref<StreamingHighlightResult>()\r\n const isLoading = ref(false)\r\n const error = ref<Error | null>(null)\r\n\r\n let tokenizer: any | null = null\r\n let previousText = ''\r\n let highlighter: any | null = null\r\n let currentUsedLang = ''\r\n let lastRequestedLang = ''\r\n\r\n const effectiveTheme = computed(() => {\r\n const theme = isRef(options.theme) ? options.theme.value : options.theme\r\n return theme || 'slack-dark'\r\n })\r\n\r\n const effectiveLanguage = computed(() => {\r\n return toValue(options.language) || 'text'\r\n })\r\n\r\n const lines = computed(() => streaming.value?.lines || [[]])\r\n const preStyle = computed(() => streaming.value?.preStyle)\r\n\r\n const updateTokens = async (nextText: string, forceReset = false) => {\r\n // 当有 tokenizer 时使用流式处理\r\n if (tokenizer) {\r\n if (forceReset) {\r\n tokenizer.clear()\r\n previousText = ''\r\n }\r\n\r\n const canAppend = !forceReset && nextText.startsWith(previousText)\r\n let chunk = nextText\r\n\r\n if (canAppend) {\r\n chunk = nextText.slice(previousText.length)\r\n } else if (!forceReset) {\r\n tokenizer.clear()\r\n }\r\n\r\n previousText = nextText\r\n\r\n if (!chunk) {\r\n const mergedTokens = [...tokenizer.tokensStable, ...tokenizer.tokensUnstable]\r\n streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: mergedTokens.length ? tokensToLineTokens(mergedTokens) : [[]],\r\n preStyle: streaming.value?.preStyle,\r\n }\r\n return\r\n }\r\n\r\n try {\r\n await tokenizer.enqueue(chunk)\r\n\r\n const mergedTokens = [...tokenizer.tokensStable, ...tokenizer.tokensUnstable]\r\n\r\n streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: tokensToLineTokens(mergedTokens),\r\n preStyle: streaming.value?.preStyle,\r\n }\r\n } catch (err) {\r\n console.error('[x-markdown] Streaming highlighting failed:', err)\r\n error.value = err as Error\r\n }\r\n } else if (highlighter) {\r\n // 当没有 tokenizer 但有 highlighter 时,使用非流式方式高亮\r\n // 这发生在 shiki 可用但 shiki-stream 不可用时\r\n try {\r\n const currentLang = currentUsedLang || 'plaintext'\r\n const currentTheme = effectiveTheme.value\r\n const tokens = highlighter.codeToTokens(nextText, {\r\n lang: currentLang,\r\n theme: currentTheme,\r\n })\r\n\r\n streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: tokensToLineTokens(tokens),\r\n preStyle: streaming.value?.preStyle,\r\n }\r\n } catch (err) {\r\n console.error('[x-markdown] Direct highlighting failed:', err)\r\n // 降级为纯文本\r\n streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: [[{ content: nextText }]],\r\n preStyle: streaming.value?.preStyle,\r\n }\r\n }\r\n }\r\n }\r\n\r\n const initHighlighter = async () => {\r\n isLoading.value = true\r\n error.value = null\r\n\r\n let currentLang = effectiveLanguage.value\r\n const currentTheme = effectiveTheme.value\r\n\r\n try {\r\n const mod = await loadShiki()\r\n if (!mod) {\r\n // shiki 完全不可用\r\n streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: [[{ content: text.value }]],\r\n preStyle: undefined,\r\n }\r\n showShikiHint()\r\n return\r\n }\r\n\r\n // shiki 3.x API\r\n highlighter = await mod.createHighlighter({\r\n themes: [currentTheme],\r\n langs: [], // 将动态加载语言\r\n })\r\n\r\n lastRequestedLang = currentLang\r\n\r\n try {\r\n await highlighter.loadLanguage(currentLang as any)\r\n currentUsedLang = currentLang\r\n } catch {\r\n currentLang = 'plaintext'\r\n currentUsedLang = 'plaintext'\r\n }\r\n\r\n // 动态加载 shiki-stream\r\n const shikiStreamMod = await loadShikiStream()\r\n if (shikiStreamMod) {\r\n tokenizer = new shikiStreamMod.ShikiStreamTokenizer({\r\n highlighter: highlighter,\r\n lang: currentLang,\r\n theme: currentTheme,\r\n })\r\n } else {\r\n // shiki 可用但 shiki-stream 不可用\r\n showShikiStreamHint()\r\n }\r\n\r\n previousText = ''\r\n\r\n const themeInfo = highlighter.getTheme(currentTheme)\r\n const preStyleValue = createPreStyle(themeInfo?.bg, themeInfo?.fg)\r\n\r\n if (text.value) {\r\n await updateTokens(text.value, true)\r\n if (streaming.value) {\r\n streaming.value.preStyle = preStyleValue\r\n }\r\n } else {\r\n streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: [[]],\r\n preStyle: preStyleValue,\r\n }\r\n }\r\n } catch (err) {\r\n // 静默降级\r\n streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: [[{ content: text.value }]],\r\n preStyle: undefined,\r\n }\r\n } finally {\r\n isLoading.value = false\r\n }\r\n }\r\n\r\n watch(\r\n () => [effectiveLanguage.value, effectiveTheme.value],\r\n async ([newLang]) => {\r\n const requestedLang = newLang as string\r\n\r\n if (\r\n highlighter &&\r\n currentUsedLang === 'plaintext' &&\r\n requestedLang !== lastRequestedLang &&\r\n requestedLang !== 'plaintext'\r\n ) {\r\n try {\r\n await highlighter.loadLanguage(requestedLang as any)\r\n initHighlighter()\r\n return\r\n } catch {\r\n lastRequestedLang = requestedLang\r\n return\r\n }\r\n }\r\n\r\n initHighlighter()\r\n },\r\n { immediate: true },\r\n )\r\n\r\n watch(text, async (newText) => {\r\n const requestedLang = effectiveLanguage.value\r\n if (\r\n highlighter &&\r\n currentUsedLang === 'plaintext' &&\r\n requestedLang !== lastRequestedLang &&\r\n requestedLang !== 'plaintext'\r\n ) {\r\n try {\r\n await highlighter.loadLanguage(requestedLang as any)\r\n await initHighlighter()\r\n return\r\n } catch {\r\n lastRequestedLang = requestedLang\r\n }\r\n }\r\n\r\n if (tokenizer || highlighter) {\r\n // 当有 tokenizer 或 highlighter 时都调用 updateTokens\r\n // updateTokens 内部会处理两种情况\r\n updateTokens(newText)\r\n } else {\r\n // 两者都没有时降级为纯文本\r\n streaming.value = {\r\n colorReplacements: options.colorReplacements,\r\n lines: [[{ content: newText }]],\r\n preStyle: streaming.value?.preStyle,\r\n }\r\n }\r\n })\r\n\r\n onUnmounted(() => {\r\n tokenizer?.clear()\r\n tokenizer = null\r\n previousText = ''\r\n })\r\n\r\n return {\r\n streaming,\r\n lines,\r\n preStyle,\r\n isLoading,\r\n error,\r\n }\r\n}\r\n"],"names":[],"mappings":";AAsBA,IAAI,qBAAiD;AACrD,IAAI,2BAAuD;AAC3D,IAAI,oBAAoB;AACxB,IAAI,0BAA0B;AAG9B,MAAM,gBAAgB,MAAM;AAC1B,MAAI,kBAAmB;AACvB,sBAAoB;AAEpB,UAAQ;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEF,UAAQ;AAAA,IACN;AAAA,IACA;AAAA,EAAA;AAEF,UAAQ;AAAA,IACN;AAAA,IACA;AAAA,EAAA;AAEF,UAAQ;AAAA,IACN;AAAA,IACA;AAAA,EAAA;AAEJ;AAEA,MAAM,sBAAsB,MAAM;AAChC,MAAI,wBAAyB;AAC7B,4BAA0B;AAE1B,UAAQ;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEF,UAAQ;AAAA,IACN;AAAA,IACA;AAAA,EAAA;AAEF,UAAQ;AAAA,IACN;AAAA,IACA;AAAA,EAAA;AAEF,UAAQ;AAAA,IACN;AAAA,IACA;AAAA,EAAA;AAEJ;AAEA,MAAM,YAAY,YAAY;AAC5B,MAAI,CAAC,oBAAoB;AACvB,0BAAsB,YAAY;AAChC,UAAI;AACF,cAAM,MAAM,MAAM,OAAO,OAAO;AAChC,eAAO;AAAA,MACT,QAAQ;AAEN,eAAO;AAAA,MACT;AAAA,IACF,GAAA;AAAA,EACF;AACA,SAAO;AACT;AAEA,MAAM,kBAAkB,YAAY;AAClC,MAAI,CAAC,0BAA0B;AAC7B,gCAA4B,YAAY;AACtC,UAAI;AACF,cAAM,MAAM,MAAM,OAAO,cAAc;AACvC,eAAO;AAAA,MACT,QAAQ;AAEN,eAAO;AAAA,MACT;AAAA,IACF,GAAA;AAAA,EACF;AACA,SAAO;AACT;AAEA,MAAM,qBAAqB,CAAC,WAAiD;AAC3E,MAAI,CAAC,OAAO,OAAQ,QAAO,CAAC,CAAA,CAAE;AAE9B,QAAM,QAA4B,CAAC,EAAE;AACrC,MAAI,cAAc,MAAM,CAAC;AAEzB,QAAM,eAAe,MAAM;AACzB,kBAAc,CAAA;AACd,UAAM,KAAK,WAAW;AAAA,EACxB;AAEA,SAAO,QAAQ,CAAC,UAAU;AACxB,UAAM,UAAU,MAAM,WAAW;AAEjC,QAAI,YAAY,MAAM;AACpB,mBAAA;AACA;AAAA,IACF;AAEA,QAAI,CAAC,QAAQ,SAAS,IAAI,GAAG;AAC3B,kBAAY,KAAK,KAAK;AACtB;AAAA,IACF;AAEA,UAAM,WAAW,QAAQ,MAAM,IAAI;AACnC,aAAS,QAAQ,CAAC,SAAS,UAAU;AACnC,UAAI,SAAS;AACX,oBAAY,KAAK;AAAA,UACf,GAAG;AAAA,UACH,SAAS;AAAA,QAAA,CACV;AAAA,MACH;AAEA,UAAI,QAAQ,SAAS,SAAS,GAAG;AAC/B,qBAAA;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AAED,SAAO,MAAM,WAAW,IAAI,CAAC,CAAA,CAAE,IAAI;AACrC;AAEA,MAAM,iBAAiB,CAAC,IAAa,OAA2C;AAC9E,MAAI,CAAC,MAAM,CAAC,GAAI,QAAO;AACvB,SAAO;AAAA,IACL,iBAAiB;AAAA,IACjB,OAAO;AAAA,EAAA;AAEX;AAEO,SAAS,aAAa,MAAmB,SAA8B;AAC5E,QAAM,YAAY,IAAA;AAClB,QAAM,YAAY,IAAI,KAAK;AAC3B,QAAM,QAAQ,IAAkB,IAAI;AAEpC,MAAI,YAAwB;AAC5B,MAAI,eAAe;AACnB,MAAI,cAA0B;AAC9B,MAAI,kBAAkB;AACtB,MAAI,oBAAoB;AAExB,QAAM,iBAAiB,SAAS,MAAM;AACpC,UAAM,QAAQ,MAAM,QAAQ,KAAK,IAAI,QAAQ,MAAM,QAAQ,QAAQ;AACnE,WAAO,SAAS;AAAA,EAClB,CAAC;AAED,QAAM,oBAAoB,SAAS,MAAM;AACvC,WAAO,QAAQ,QAAQ,QAAQ,KAAK;AAAA,EACtC,CAAC;AAED,QAAM,QAAQ,SAAS,MAAM,UAAU,OAAO,SAAS,CAAC,CAAA,CAAE,CAAC;AAC3D,QAAM,WAAW,SAAS,MAAM,UAAU,OAAO,QAAQ;AAEzD,QAAM,eAAe,OAAO,UAAkB,aAAa,UAAU;AAEnE,QAAI,WAAW;AACb,UAAI,YAAY;AACd,kBAAU,MAAA;AACV,uBAAe;AAAA,MACjB;AAEA,YAAM,YAAY,CAAC,cAAc,SAAS,WAAW,YAAY;AACjE,UAAI,QAAQ;AAEZ,UAAI,WAAW;AACb,gBAAQ,SAAS,MAAM,aAAa,MAAM;AAAA,MAC5C,WAAW,CAAC,YAAY;AACtB,kBAAU,MAAA;AAAA,MACZ;AAEA,qBAAe;AAEf,UAAI,CAAC,OAAO;AACV,cAAM,eAAe,CAAC,GAAG,UAAU,cAAc,GAAG,UAAU,cAAc;AAC5E,kBAAU,QAAQ;AAAA,UAChB,mBAAmB,QAAQ;AAAA,UAC3B,OAAO,aAAa,SAAS,mBAAmB,YAAY,IAAI,CAAC,EAAE;AAAA,UACnE,UAAU,UAAU,OAAO;AAAA,QAAA;AAE7B;AAAA,MACF;AAEA,UAAI;AACF,cAAM,UAAU,QAAQ,KAAK;AAE7B,cAAM,eAAe,CAAC,GAAG,UAAU,cAAc,GAAG,UAAU,cAAc;AAE5E,kBAAU,QAAQ;AAAA,UAChB,mBAAmB,QAAQ;AAAA,UAC3B,OAAO,mBAAmB,YAAY;AAAA,UACtC,UAAU,UAAU,OAAO;AAAA,QAAA;AAAA,MAE/B,SAAS,KAAK;AACZ,gBAAQ,MAAM,+CAA+C,GAAG;AAChE,cAAM,QAAQ;AAAA,MAChB;AAAA,IACF,WAAW,aAAa;AAGtB,UAAI;AACF,cAAM,cAAc,mBAAmB;AACvC,cAAM,eAAe,eAAe;AACpC,cAAM,SAAS,YAAY,aAAa,UAAU;AAAA,UAChD,MAAM;AAAA,UACN,OAAO;AAAA,QAAA,CACR;AAED,kBAAU,QAAQ;AAAA,UAChB,mBAAmB,QAAQ;AAAA,UAC3B,OAAO,mBAAmB,MAAM;AAAA,UAChC,UAAU,UAAU,OAAO;AAAA,QAAA;AAAA,MAE/B,SAAS,KAAK;AACZ,gBAAQ,MAAM,4CAA4C,GAAG;AAE7D,kBAAU,QAAQ;AAAA,UAChB,mBAAmB,QAAQ;AAAA,UAC3B,OAAO,CAAC,CAAC,EAAE,SAAS,SAAA,CAAU,CAAC;AAAA,UAC/B,UAAU,UAAU,OAAO;AAAA,QAAA;AAAA,MAE/B;AAAA,IACF;AAAA,EACF;AAEA,QAAM,kBAAkB,YAAY;AAClC,cAAU,QAAQ;AAClB,UAAM,QAAQ;AAEd,QAAI,cAAc,kBAAkB;AACpC,UAAM,eAAe,eAAe;AAEpC,QAAI;AACF,YAAM,MAAM,MAAM,UAAA;AAClB,UAAI,CAAC,KAAK;AAER,kBAAU,QAAQ;AAAA,UAChB,mBAAmB,QAAQ;AAAA,UAC3B,OAAO,CAAC,CAAC,EAAE,SAAS,KAAK,MAAA,CAAO,CAAC;AAAA,UACjC,UAAU;AAAA,QAAA;AAEZ,sBAAA;AACA;AAAA,MACF;AAGA,oBAAc,MAAM,IAAI,kBAAkB;AAAA,QACxC,QAAQ,CAAC,YAAY;AAAA,QACrB,OAAO,CAAA;AAAA;AAAA,MAAC,CACT;AAED,0BAAoB;AAEpB,UAAI;AACF,cAAM,YAAY,aAAa,WAAkB;AACjD,0BAAkB;AAAA,MACpB,QAAQ;AACN,sBAAc;AACd,0BAAkB;AAAA,MACpB;AAGA,YAAM,iBAAiB,MAAM,gBAAA;AAC7B,UAAI,gBAAgB;AAClB,oBAAY,IAAI,eAAe,qBAAqB;AAAA,UAClD;AAAA,UACA,MAAM;AAAA,UACN,OAAO;AAAA,QAAA,CACR;AAAA,MACH,OAAO;AAEL,4BAAA;AAAA,MACF;AAEA,qBAAe;AAEf,YAAM,YAAY,YAAY,SAAS,YAAY;AACnD,YAAM,gBAAgB,eAAe,WAAW,IAAI,WAAW,EAAE;AAEjE,UAAI,KAAK,OAAO;AACd,cAAM,aAAa,KAAK,OAAO,IAAI;AACnC,YAAI,UAAU,OAAO;AACnB,oBAAU,MAAM,WAAW;AAAA,QAC7B;AAAA,MACF,OAAO;AACL,kBAAU,QAAQ;AAAA,UAChB,mBAAmB,QAAQ;AAAA,UAC3B,OAAO,CAAC,CAAA,CAAE;AAAA,UACV,UAAU;AAAA,QAAA;AAAA,MAEd;AAAA,IACF,SAAS,KAAK;AAEZ,gBAAU,QAAQ;AAAA,QAChB,mBAAmB,QAAQ;AAAA,QAC3B,OAAO,CAAC,CAAC,EAAE,SAAS,KAAK,MAAA,CAAO,CAAC;AAAA,QACjC,UAAU;AAAA,MAAA;AAAA,IAEd,UAAA;AACE,gBAAU,QAAQ;AAAA,IACpB;AAAA,EACF;AAEA;AAAA,IACE,MAAM,CAAC,kBAAkB,OAAO,eAAe,KAAK;AAAA,IACpD,OAAO,CAAC,OAAO,MAAM;AACnB,YAAM,gBAAgB;AAEtB,UACE,eACA,oBAAoB,eACpB,kBAAkB,qBAClB,kBAAkB,aAClB;AACA,YAAI;AACF,gBAAM,YAAY,aAAa,aAAoB;AACnD,0BAAA;AACA;AAAA,QACF,QAAQ;AACN,8BAAoB;AACpB;AAAA,QACF;AAAA,MACF;AAEA,sBAAA;AAAA,IACF;AAAA,IACA,EAAE,WAAW,KAAA;AAAA,EAAK;AAGpB,QAAM,MAAM,OAAO,YAAY;AAC7B,UAAM,gBAAgB,kBAAkB;AACxC,QACE,eACA,oBAAoB,eACpB,kBAAkB,qBAClB,kBAAkB,aAClB;AACA,UAAI;AACF,cAAM,YAAY,aAAa,aAAoB;AACnD,cAAM,gBAAA;AACN;AAAA,MACF,QAAQ;AACN,4BAAoB;AAAA,MACtB;AAAA,IACF;AAEA,QAAI,aAAa,aAAa;AAG5B,mBAAa,OAAO;AAAA,IACtB,OAAO;AAEL,gBAAU,QAAQ;AAAA,QAChB,mBAAmB,QAAQ;AAAA,QAC3B,OAAO,CAAC,CAAC,EAAE,SAAS,QAAA,CAAS,CAAC;AAAA,QAC9B,UAAU,UAAU,OAAO;AAAA,MAAA;AAAA,IAE/B;AAAA,EACF,CAAC;AAED,cAAY,MAAM;AAChB,eAAW,MAAA;AACX,gBAAY;AACZ,mBAAe;AAAA,EACjB,CAAC;AAED,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEJ;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hejiayue/x-markdown-test",
|
|
3
|
-
"version": "0.0.1-beta.
|
|
3
|
+
"version": "0.0.1-beta.138",
|
|
4
4
|
"description": "A markdown component library for Vue",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/x-markdown.cjs.js",
|
|
@@ -17,10 +17,12 @@
|
|
|
17
17
|
"default": "./dist/x-markdown.cjs.js"
|
|
18
18
|
}
|
|
19
19
|
},
|
|
20
|
-
"./style": "./dist/style.css"
|
|
20
|
+
"./style": "./dist/style.css",
|
|
21
|
+
"./vite-plugin": "./src/vite-plugin.js"
|
|
21
22
|
},
|
|
22
23
|
"files": [
|
|
23
|
-
"dist"
|
|
24
|
+
"dist",
|
|
25
|
+
"src/vite-plugin.js"
|
|
24
26
|
],
|
|
25
27
|
"sideEffects": [
|
|
26
28
|
"*.css",
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { resolve, dirname } from 'node:path'
|
|
2
|
+
import { existsSync } from 'node:fs'
|
|
3
|
+
import { fileURLToPath } from 'node:url'
|
|
4
|
+
|
|
5
|
+
// 在 ES 模块中获取 __dirname
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
7
|
+
const __dirname = dirname(__filename)
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* x-markdown Vite 插件
|
|
11
|
+
*
|
|
12
|
+
* 自动处理可选依赖(shiki、shiki-stream、mermaid)的虚拟模块配置
|
|
13
|
+
* 当这些依赖未安装时,自动映射到虚拟模块避免构建失败
|
|
14
|
+
*
|
|
15
|
+
* @param {Object} options - 插件配置选项
|
|
16
|
+
* @param {string[]} options.optionalDeps - 可选依赖列表(默认:['mermaid', 'shiki', 'shiki-stream'])
|
|
17
|
+
* @param {string} options.virtualModulesDir - 虚拟模块目录(相对于项目根目录)
|
|
18
|
+
* @returns {import('vite').Plugin} Vite 插件
|
|
19
|
+
*/
|
|
20
|
+
export function createXMarkdownVitePlugin(options = {}) {
|
|
21
|
+
const {
|
|
22
|
+
optionalDeps = ['mermaid', 'shiki', 'shiki-stream'],
|
|
23
|
+
virtualModulesDir = './node_modules/@hejiayue/x-markdown-test/virtual-modules',
|
|
24
|
+
} = options
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
name: '@hejiayue/x-markdown-test:vite-plugin',
|
|
28
|
+
enforce: 'pre', // 在其他插件之前执行
|
|
29
|
+
config(config) {
|
|
30
|
+
// 获取项目根目录
|
|
31
|
+
const projectRoot = process.cwd()
|
|
32
|
+
|
|
33
|
+
// 动态生成可选依赖的 alias 配置
|
|
34
|
+
const optionalAliases = []
|
|
35
|
+
|
|
36
|
+
for (const dep of optionalDeps) {
|
|
37
|
+
const depPath = resolve(projectRoot, 'node_modules', dep)
|
|
38
|
+
|
|
39
|
+
if (!existsSync(depPath)) {
|
|
40
|
+
// 依赖未安装,使用虚拟模块
|
|
41
|
+
// 尝试从多个可能的位置查找虚拟模块
|
|
42
|
+
const virtualModulePaths = [
|
|
43
|
+
resolve(projectRoot, virtualModulesDir, `${dep}.js`),
|
|
44
|
+
resolve(projectRoot, 'src/virtual-modules', `${dep}.js`),
|
|
45
|
+
// 最后尝试:从 x-markdown 包内部获取
|
|
46
|
+
resolve(__dirname, 'virtual-modules', `${dep}.js`),
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
let virtualModulePath = null
|
|
50
|
+
for (const path of virtualModulePaths) {
|
|
51
|
+
if (existsSync(path)) {
|
|
52
|
+
virtualModulePath = path
|
|
53
|
+
break
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (virtualModulePath) {
|
|
58
|
+
optionalAliases.push({
|
|
59
|
+
find: dep,
|
|
60
|
+
replacement: virtualModulePath,
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
// 在开发环境显示提示信息
|
|
64
|
+
if (config.mode === 'development') {
|
|
65
|
+
console.log(
|
|
66
|
+
`\x1b[33m[@hejiayue/x-markdown-test]\x1b[0m ${dep} 未安装,使用虚拟模块`
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// 如果有需要添加的 alias,更新配置
|
|
74
|
+
if (optionalAliases.length > 0) {
|
|
75
|
+
// 保留原有的 alias 配置
|
|
76
|
+
const existingAlias = config.resolve?.alias || []
|
|
77
|
+
|
|
78
|
+
// 合并 alias 配置
|
|
79
|
+
config.resolve = {
|
|
80
|
+
...config.resolve,
|
|
81
|
+
alias: [
|
|
82
|
+
...optionalAliases,
|
|
83
|
+
...(Array.isArray(existingAlias) ? existingAlias : [existingAlias]),
|
|
84
|
+
],
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// 确保 optionalDeps 不被预构建
|
|
89
|
+
const optimizeDeps = config.optimizeDeps || {}
|
|
90
|
+
const excludeDeps = optimizeDeps.exclude || []
|
|
91
|
+
const includeDeps = optimizeDeps.include || []
|
|
92
|
+
|
|
93
|
+
// 移除未安装的依赖从 include
|
|
94
|
+
const filteredInclude = includeDeps.filter(dep => {
|
|
95
|
+
const depPath = resolve(projectRoot, 'node_modules', dep)
|
|
96
|
+
return existsSync(depPath)
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
// 添加未安装的依赖到 exclude
|
|
100
|
+
const newExclude = [...optionalDeps.filter(dep => {
|
|
101
|
+
const depPath = resolve(projectRoot, 'node_modules', dep)
|
|
102
|
+
return !existsSync(depPath)
|
|
103
|
+
}), ...excludeDeps]
|
|
104
|
+
|
|
105
|
+
config.optimizeDeps = {
|
|
106
|
+
...optimizeDeps,
|
|
107
|
+
include: filteredInclude,
|
|
108
|
+
exclude: [...new Set(newExclude)],
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// 默认导出,方便使用
|
|
115
|
+
export default createXMarkdownVitePlugin
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* 为了兼容性,也提供一个具名导出
|
|
119
|
+
*/
|
|
120
|
+
export { createXMarkdownVitePlugin as xMarkdownVitePlugin }
|
package/dist/x-markdown.cjs28.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),a=require("lodash-es"),n=require("./x-markdown.cjs9.js"),t={key:0,class:"syntax-mermaid__loading"},r=["innerHTML"],i=e.defineComponent({__name:"SyntaxMermaid",props:{content:{default:""},id:{default:"mermaid-default"},isDark:{type:Boolean,default:!1},config:{default:()=>({})}},emits:["degraded","ready"],setup(i,{expose:o,emit:d}){const l=i,s=d,u=e.ref(null),c=e.computed(()=>l.content),m=e.computed(()=>({id:l.id,theme:l.isDark?"dark":"default",config:l.config,container:u.value})),v=n.useMermaid(c,m),f=e.ref(""),g=e.computed(()=>v.isLoading.value),y=e.computed(()=>v.error.value),p=e.ref(null),k=n.useMermaidZoom({container:p}),x=a.debounce(function(){e.nextTick(()=>{p.value&&k.initialize()})},500);return e.watch(()=>v.data.value,(e,a)=>{console.log("[SyntaxMermaid] mermaidResult.data.value changed:",{oldSvg:a,newSvg:e,isNewSvg:!!e,startsWithSvg:e?.trim().startsWith("<svg"),preview:e?.substring(0,50)}),e&&(f.value=e,x(),e.trim().startsWith("<svg")?(console.log("[SyntaxMermaid] Emitting ready event - Mermaid is available"),s("ready")):(console.log("[SyntaxMermaid] Emitting degraded event - Mermaid not available"),s("degraded")))},{immediate:!0}),e.watch(f,e=>{e&&x()}),e.onMounted(()=>{f.value&&x()}),o({svg:f,isLoading:g,error:y,containerRef:p,zoomIn:function(){k?.zoomIn()},zoomOut:function(){k?.zoomOut()},reset:function(){k?.reset()},fullscreen:function(){k?.fullscreen(),k?.reset()},download:function(){n.downloadSvgAsPng(f.value)},getSvg:function(){return f.value},reinitialize:function(){x()}}),(a,n)=>(e.openBlock(),e.createElementBlock("div",{ref_key:"containerRef",ref:p,class:e.normalizeClass(["syntax-mermaid",{"syntax-mermaid--dark":l.isDark}])},[e.createElementVNode("div",{ref_key:"renderContainerRef",ref:u,class:"syntax-mermaid__render-container","aria-hidden":"true"},null,512),g.value?(e.openBlock(),e.createElementBlock("div",t,[e.renderSlot(a.$slots,"loading",{},()=>[n[0]||(n[0]=e.createElementVNode("span",{class:"syntax-mermaid__loading-text"},"加载中...",-1))])])):(e.openBlock(),e.createElementBlock("div",{key:1,class:"syntax-mermaid__content",innerHTML:f.value},null,8,r))],2))}});exports.default=i;
|
|
2
|
-
//# sourceMappingURL=x-markdown.cjs28.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"x-markdown.cjs28.js","sources":["../src/components/Mermaid/SyntaxMermaid.vue"],"sourcesContent":["<script setup lang=\"ts\">\r\nimport { computed, nextTick, ref, watch, onMounted } from 'vue'\r\nimport { debounce } from 'lodash-es'\r\nimport { useMermaid, useMermaidZoom, downloadSvgAsPng } from '../../hooks'\r\n\r\ninterface SyntaxMermaidProps {\r\n content: string\r\n id?: string\r\n isDark?: boolean\r\n config?: Record<string, any>\r\n}\r\n\r\nconst props = withDefaults(defineProps<SyntaxMermaidProps>(), {\r\n content: '',\r\n id: 'mermaid-default',\r\n isDark: false,\r\n config: () => ({}),\r\n})\r\n\r\nconst emit = defineEmits<{\r\n degraded: []\r\n ready: []\r\n}>()\r\n\r\nconst renderContainerRef = ref<HTMLElement | null>(null)\r\n\r\nconst mermaidContent = computed(() => props.content)\r\nconst mermaidOptions = computed(() => ({\r\n id: props.id,\r\n theme: props.isDark ? 'dark' : 'default',\r\n config: props.config,\r\n container: renderContainerRef.value,\r\n}))\r\nconst mermaidResult = useMermaid(mermaidContent, mermaidOptions)\r\n\r\nconst svg = ref('')\r\nconst isLoading = computed(() => mermaidResult.isLoading.value)\r\nconst error = computed(() => mermaidResult.error.value)\r\n\r\nconst containerRef = ref<HTMLElement | null>(null)\r\n\r\nconst zoomControls = useMermaidZoom({\r\n container: containerRef,\r\n scaleStep: 0.2,\r\n minScale: 0.1,\r\n maxScale: 5,\r\n})\r\n\r\nconst debouncedInitialize = debounce(initializeZoom, 500)\r\n\r\nfunction initializeZoom() {\r\n nextTick(() => {\r\n if (containerRef.value) {\r\n zoomControls.initialize()\r\n }\r\n })\r\n}\r\n\r\nwatch(\r\n () => mermaidResult.data.value,\r\n (newSvg, oldSvg) => {\r\n console.log('[SyntaxMermaid] mermaidResult.data.value changed:', {\r\n oldSvg,\r\n newSvg,\r\n isNewSvg: !!newSvg,\r\n startsWithSvg: newSvg?.trim().startsWith('<svg'),\r\n preview: newSvg?.substring(0, 50)\r\n })\r\n\r\n if (newSvg) {\r\n svg.value = newSvg\r\n debouncedInitialize()\r\n\r\n // 检测是否成功渲染了 SVG(以 <svg 开头)\r\n if (newSvg.trim().startsWith('<svg')) {\r\n console.log('[SyntaxMermaid] Emitting ready event - Mermaid is available')\r\n emit('ready')\r\n } else {\r\n console.log('[SyntaxMermaid] Emitting degraded event - Mermaid not available')\r\n emit('degraded')\r\n }\r\n }\r\n },\r\n { immediate: true },\r\n)\r\n\r\nwatch(svg, (newSvg) => {\r\n if (newSvg) {\r\n debouncedInitialize()\r\n }\r\n})\r\n\r\nfunction zoomIn() {\r\n zoomControls?.zoomIn()\r\n}\r\n\r\nfunction zoomOut() {\r\n zoomControls?.zoomOut()\r\n}\r\n\r\nfunction reset() {\r\n zoomControls?.reset()\r\n}\r\n\r\nfunction fullscreen() {\r\n zoomControls?.fullscreen()\r\n zoomControls?.reset()\r\n}\r\n\r\nfunction download() {\r\n downloadSvgAsPng(svg.value)\r\n}\r\n\r\nfunction getSvg() {\r\n return svg.value\r\n}\r\n\r\nfunction reinitialize() {\r\n debouncedInitialize()\r\n}\r\n\r\nonMounted(() => {\r\n if (svg.value) {\r\n debouncedInitialize()\r\n }\r\n})\r\n\r\ndefineExpose({\r\n svg,\r\n isLoading,\r\n error,\r\n containerRef,\r\n zoomIn,\r\n zoomOut,\r\n reset,\r\n fullscreen,\r\n download,\r\n getSvg,\r\n reinitialize,\r\n})\r\n</script>\r\n\r\n<template>\r\n <div ref=\"containerRef\" class=\"syntax-mermaid\" :class=\"{ 'syntax-mermaid--dark': props.isDark }\">\r\n <div ref=\"renderContainerRef\" class=\"syntax-mermaid__render-container\" aria-hidden=\"true\" />\r\n\r\n <div v-if=\"isLoading\" class=\"syntax-mermaid__loading\">\r\n <slot name=\"loading\">\r\n <span class=\"syntax-mermaid__loading-text\">加载中...</span>\r\n </slot>\r\n </div>\r\n <div v-else class=\"syntax-mermaid__content\" v-html=\"svg\" />\r\n </div>\r\n</template>\r\n\r\n<style>\r\n.syntax-mermaid {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n min-height: 200px;\r\n overflow: hidden;\r\n cursor: grab;\r\n position: relative;\r\n}\r\n\r\n.syntax-mermaid__render-container {\r\n position: absolute;\r\n max-height: 0;\r\n opacity: 0;\r\n overflow: hidden;\r\n pointer-events: none;\r\n}\r\n\r\n.syntax-mermaid:active {\r\n cursor: grabbing;\r\n}\r\n\r\n.syntax-mermaid__content {\r\n width: 100%;\r\n height: 100%;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n\r\n.syntax-mermaid__content svg {\r\n transform-origin: center center;\r\n max-width: 100%;\r\n max-height: 100%;\r\n}\r\n\r\n.syntax-mermaid:fullscreen {\r\n max-height: 100vh;\r\n}\r\n\r\n.syntax-mermaid:fullscreen .syntax-mermaid__content {\r\n justify-content: center;\r\n}\r\n\r\n.syntax-mermaid__loading {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 100%;\r\n height: 100%;\r\n min-height: 200px;\r\n}\r\n\r\n.syntax-mermaid__loading-text {\r\n color: #666;\r\n font-size: 14px;\r\n}\r\n\r\n.syntax-mermaid--dark .syntax-mermaid__loading-text {\r\n color: #999;\r\n}\r\n</style>\r\n"],"names":["props","__props","emit","__emit","renderContainerRef","ref","mermaidContent","computed","content","mermaidOptions","id","theme","isDark","config","container","value","mermaidResult","useMermaid","svg","isLoading","error","containerRef","zoomControls","useMermaidZoom","debouncedInitialize","debounce","nextTick","initialize","watch","data","newSvg","oldSvg","console","log","isNewSvg","startsWithSvg","trim","startsWith","preview","substring","immediate","onMounted","__expose","zoomIn","zoomOut","reset","fullscreen","download","downloadSvgAsPng","getSvg","reinitialize","_createElementBlock","class","_normalizeClass","_createElementVNode","_openBlock","_hoisted_1","_renderSlot","_ctx","_cache","innerHTML"],"mappings":"+cAYA,MAAMA,EAAQC,EAORC,EAAOC,EAKPC,EAAqBC,EAAAA,IAAwB,MAE7CC,EAAiBC,EAAAA,SAAS,IAAMP,EAAMQ,SACtCC,EAAiBF,EAAAA,SAAS,KAAA,CAC9BG,GAAIV,EAAMU,GACVC,MAAOX,EAAMY,OAAS,OAAS,UAC/BC,OAAQb,EAAMa,OACdC,UAAWV,EAAmBW,SAE1BC,EAAgBC,EAAAA,WAAWX,EAAgBG,GAE3CS,EAAMb,EAAAA,IAAI,IACVc,EAAYZ,EAAAA,SAAS,IAAMS,EAAcG,UAAUJ,OACnDK,EAAQb,EAAAA,SAAS,IAAMS,EAAcI,MAAML,OAE3CM,EAAehB,EAAAA,IAAwB,MAEvCiB,EAAeC,EAAAA,eAAe,CAClCT,UAAWO,IAMPG,EAAsBC,EAAAA,SAE5B,WACEC,EAAAA,SAAS,KACHL,EAAaN,OACfO,EAAaK,cAGnB,EARqD,YAUrDC,EAAAA,MACE,IAAMZ,EAAca,KAAKd,MACzB,CAACe,EAAQC,KACPC,QAAQC,IAAI,oDAAqD,CAC/DF,SACAD,SACAI,WAAYJ,EACZK,cAAeL,GAAQM,OAAOC,WAAW,QACzCC,QAASR,GAAQS,UAAU,EAAG,MAG5BT,IACFZ,EAAIH,MAAQe,EACZN,IAGIM,EAAOM,OAAOC,WAAW,SAC3BL,QAAQC,IAAI,+DACZ/B,EAAK,WAEL8B,QAAQC,IAAI,mEACZ/B,EAAK,eAIX,CAAEsC,WAAW,IAGfZ,QAAMV,EAAMY,IACNA,GACFN,MAiCJiB,EAAAA,UAAU,KACJvB,EAAIH,OACNS,MAIJkB,EAAa,CACXxB,MACAC,YACAC,QACAC,eACAsB,OAxCF,WACErB,GAAcqB,QAChB,EAuCEC,QArCF,WACEtB,GAAcsB,SAChB,EAoCEC,MAlCF,WACEvB,GAAcuB,OAChB,EAiCEC,WA/BF,WACExB,GAAcwB,aACdxB,GAAcuB,OAChB,EA6BEE,SA3BF,WACEC,EAAAA,iBAAiB9B,EAAIH,MACvB,EA0BEkC,OAxBF,WACE,OAAO/B,EAAIH,KACb,EAuBEmC,aArBF,WACE1B,GACF,0BAwBE2B,EAAAA,mBASM,MAAA,SATG,eAAJ9C,IAAIgB,EAAe+B,MAAKC,EAAAA,eAAA,CAAC,iBAAgB,CAAA,uBAAmCrD,EAAMY,YACrF0C,EAAAA,mBAA4F,MAAA,SAAnF,qBAAJjD,IAAID,EAAqBgD,MAAM,mCAAmC,cAAY,kBAExEjC,EAAAJ,OAAXwC,EAAAA,YAAAJ,EAAAA,mBAIM,MAJNK,EAIM,CAHJC,EAAAA,WAEOC,sBAFP,IAEO,CADLC,EAAA,KAAAA,EAAA,GAAAL,EAAAA,mBAAwD,OAAA,CAAlDF,MAAM,gCAA+B,UAAM,wBAGrDD,EAAAA,mBAA2D,MAAA,OAA/CC,MAAM,0BAA0BQ,UAAQ1C,EAAAH"}
|
package/dist/x-markdown.cjs33.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"x-markdown.cjs33.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|