@nuxtjs/mdc 0.1.6 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/dist/module.d.mts +25 -3
- package/dist/module.d.ts +25 -3
- package/dist/module.json +1 -1
- package/dist/module.mjs +15 -2
- package/dist/runtime/components/MDC.vue +29 -4
- package/dist/runtime/components/MDCRenderer.vue +6 -7
- package/dist/runtime/components/MDCRenderer.vue.d.ts +6 -15
- package/dist/runtime/parser/compiler.mjs +1 -1
- package/dist/runtime/parser/handlers/code.mjs +4 -4
- package/dist/runtime/parser/handlers/inlineCode.mjs +9 -0
- package/dist/runtime/parser/handlers/utils.d.ts +1 -3
- package/dist/runtime/parser/handlers/utils.mjs +1 -1
- package/dist/runtime/parser/index.mjs +13 -2
- package/dist/runtime/parser/options.mjs +3 -6
- package/dist/runtime/shiki/event-handler.d.ts +1 -7
- package/dist/runtime/shiki/event-handler.mjs +18 -13
- package/dist/runtime/shiki/highlighter.d.ts +3 -23
- package/dist/runtime/shiki/highlighter.mjs +43 -249
- package/dist/runtime/{parser/shiki.d.ts → shiki/index.d.ts} +1 -1
- package/dist/runtime/{parser/shiki.mjs → shiki/index.mjs} +16 -8
- package/dist/runtime/shiki/types.d.ts +7 -26
- package/dist/runtime/utils/node.d.ts +2 -2
- package/dist/runtime/utils/node.mjs +10 -5
- package/package.json +20 -20
- package/dist/runtime/shiki/mdc.tmLanguage.d.ts +0 -323
- package/dist/runtime/shiki/mdc.tmLanguage.mjs +0 -582
|
@@ -1,29 +1,13 @@
|
|
|
1
|
-
import { getHighlighter
|
|
2
|
-
import { consola } from "consola";
|
|
3
|
-
import mdcTMLanguage from "./mdc.tmLanguage.mjs";
|
|
4
|
-
const logger = consola.withTag("@nuxtjs/mdc");
|
|
5
|
-
const resolveLang = (lang) => BUNDLED_LANGUAGES.find((l) => l.id === lang || l.aliases?.includes(lang));
|
|
6
|
-
const resolveTheme = (theme) => {
|
|
7
|
-
if (!theme) {
|
|
8
|
-
return;
|
|
9
|
-
}
|
|
10
|
-
if (typeof theme === "string") {
|
|
11
|
-
theme = {
|
|
12
|
-
default: theme
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
return Object.entries(theme).reduce((acc, [key, value]) => {
|
|
16
|
-
acc[key] = BUNDLED_THEMES.find((t) => t === value);
|
|
17
|
-
return acc;
|
|
18
|
-
}, {});
|
|
19
|
-
};
|
|
1
|
+
import { getHighlighter } from "shikiji";
|
|
20
2
|
export const useShikiHighlighter = createSingleton((opts) => {
|
|
21
|
-
const { theme, preload } = opts || {};
|
|
3
|
+
const { theme, preload, wrapperStyle } = opts || {};
|
|
22
4
|
let promise;
|
|
23
5
|
const getShikiHighlighter = () => {
|
|
24
6
|
if (!promise) {
|
|
25
7
|
promise = getHighlighter({
|
|
26
|
-
|
|
8
|
+
themes: [
|
|
9
|
+
theme?.default || theme || "dark-plus"
|
|
10
|
+
],
|
|
27
11
|
langs: [
|
|
28
12
|
...preload || [],
|
|
29
13
|
"diff",
|
|
@@ -36,13 +20,7 @@ export const useShikiHighlighter = createSingleton((opts) => {
|
|
|
36
20
|
"md",
|
|
37
21
|
"yaml",
|
|
38
22
|
"vue",
|
|
39
|
-
|
|
40
|
-
id: "md",
|
|
41
|
-
scopeName: "text.markdown.mdc",
|
|
42
|
-
path: "mdc.tmLanguage.json",
|
|
43
|
-
aliases: ["markdown", "md", "mdc"],
|
|
44
|
-
grammar: mdcTMLanguage
|
|
45
|
-
}
|
|
23
|
+
"mdc"
|
|
46
24
|
]
|
|
47
25
|
}).then((highlighter) => {
|
|
48
26
|
const themes = Object.values(typeof theme === "string" ? { default: theme } : theme || {});
|
|
@@ -54,239 +32,55 @@ export const useShikiHighlighter = createSingleton((opts) => {
|
|
|
54
32
|
}
|
|
55
33
|
return promise;
|
|
56
34
|
};
|
|
57
|
-
const
|
|
58
|
-
const lines = code.split(/\r\n|\r|\n/);
|
|
59
|
-
return [...lines.map((line) => [{ content: line }])];
|
|
60
|
-
};
|
|
61
|
-
const getHighlightedTokens = async (code, lang, theme2) => {
|
|
35
|
+
const getHighlightedAST = async (code, lang, theme2, opts2) => {
|
|
62
36
|
const highlighter = await getShikiHighlighter();
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
await Promise.all(newThemes.map(highlighter.loadTheme));
|
|
37
|
+
const { highlights = [] } = opts2 || {};
|
|
38
|
+
const themesObject = typeof theme2 === "string" ? { default: theme2 } : theme2 || {};
|
|
39
|
+
const themeNames = Object.values(themesObject);
|
|
40
|
+
if (themeNames.length) {
|
|
41
|
+
await Promise.all(themeNames.map((theme3) => highlighter.loadTheme(theme3)));
|
|
69
42
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
lang,
|
|
73
|
-
theme: Object.fromEntries(Object.entries(theme2).map(([n, t]) => [n, highlighter.getTheme(t)])),
|
|
74
|
-
tokens: splitCodeToLines(code)
|
|
75
|
-
};
|
|
76
|
-
if (!lang) {
|
|
77
|
-
return result;
|
|
78
|
-
}
|
|
79
|
-
if (!highlighter.getLoadedLanguages().includes(lang)) {
|
|
80
|
-
const languageRegistration = resolveLang(lang);
|
|
81
|
-
if (languageRegistration) {
|
|
82
|
-
await highlighter.loadLanguage(languageRegistration);
|
|
83
|
-
} else {
|
|
84
|
-
logger.warn(`Language '${lang}' is not supported by shiki. Skipping highlight.`);
|
|
85
|
-
return result;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
const coloredTokens = Object.entries(theme2).map(([key, theme3]) => {
|
|
89
|
-
const tokens = highlighter.codeToThemedTokens(code, lang, theme3, { includeExplanation: false }).map((line) => line.map((token) => ({
|
|
90
|
-
content: token.content,
|
|
91
|
-
style: {
|
|
92
|
-
[key]: { color: token.color, fontStyle: token.fontStyle }
|
|
93
|
-
}
|
|
94
|
-
})));
|
|
95
|
-
return {
|
|
96
|
-
key,
|
|
97
|
-
theme: theme3,
|
|
98
|
-
tokens
|
|
99
|
-
};
|
|
100
|
-
});
|
|
101
|
-
const highlightedCode = [];
|
|
102
|
-
for (const line in coloredTokens[0].tokens) {
|
|
103
|
-
highlightedCode[line] = coloredTokens.reduce((acc, color) => {
|
|
104
|
-
return mergeLines({
|
|
105
|
-
key: coloredTokens[0].key,
|
|
106
|
-
tokens: acc
|
|
107
|
-
}, {
|
|
108
|
-
key: color.key,
|
|
109
|
-
tokens: color.tokens[line]
|
|
110
|
-
});
|
|
111
|
-
}, coloredTokens[0].tokens[line]);
|
|
43
|
+
if (lang && !highlighter.getLoadedLanguages().includes(lang)) {
|
|
44
|
+
await highlighter.loadLanguage(lang);
|
|
112
45
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
color: th.fg
|
|
125
|
-
};
|
|
126
|
-
return acc;
|
|
127
|
-
}, {}),
|
|
128
|
-
className
|
|
129
|
-
};
|
|
130
|
-
const tree = tokens.map((line, lineIndex) => {
|
|
131
|
-
if (lineIndex !== tokens.length - 1) {
|
|
132
|
-
if (line.length === 0) {
|
|
133
|
-
line.push({ content: "" });
|
|
46
|
+
const root = highlighter.codeToHast(code.trimEnd(), {
|
|
47
|
+
lang,
|
|
48
|
+
themes: themesObject,
|
|
49
|
+
defaultColor: "default",
|
|
50
|
+
transforms: {
|
|
51
|
+
line(node, line) {
|
|
52
|
+
node.properties ||= {};
|
|
53
|
+
if (highlights.includes(line)) {
|
|
54
|
+
node.properties.class = (node.properties.class || "") + " highlight";
|
|
55
|
+
}
|
|
56
|
+
node.properties.line = line;
|
|
134
57
|
}
|
|
135
|
-
line[line.length - 1].content += "\n";
|
|
136
58
|
}
|
|
137
|
-
return {
|
|
138
|
-
type: "element",
|
|
139
|
-
tagName: "span",
|
|
140
|
-
properties: {
|
|
141
|
-
class: ["line", highlights.includes(lineIndex + 1) ? "highlight" : ""].join(" ").trim(),
|
|
142
|
-
line: lineIndex + 1
|
|
143
|
-
},
|
|
144
|
-
children: line.map(tokenSpan)
|
|
145
|
-
};
|
|
146
59
|
});
|
|
60
|
+
const preEl = root.children[0];
|
|
61
|
+
const codeEl = preEl.children[0];
|
|
62
|
+
preEl.properties.style = wrapperStyle ? typeof wrapperStyle === "string" ? wrapperStyle : preEl.properties.style : "";
|
|
63
|
+
const style = Object.keys(themesObject).filter((color) => color !== "default").map((color) => [
|
|
64
|
+
wrapperStyle ? `html.${color} .shiki,` : "",
|
|
65
|
+
`html.${color} .shiki span {`,
|
|
66
|
+
`color: var(--shiki-${color}) !important;`,
|
|
67
|
+
`background: var(--shiki-${color}-bg) !important;`,
|
|
68
|
+
`font-style: var(--shiki-${color}-font-style) !important;`,
|
|
69
|
+
`font-weight: var(--shiki-${color}-font-weight) !important;`,
|
|
70
|
+
`text-decoration: var(--shiki-${color}-text-decoration) !important;`,
|
|
71
|
+
"}"
|
|
72
|
+
].join("").trim()).join("\n");
|
|
147
73
|
return {
|
|
148
|
-
tree,
|
|
149
|
-
className
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
if (!token.style) {
|
|
153
|
-
return {};
|
|
154
|
-
}
|
|
155
|
-
const key = Object.values(token.style).map((themeStyle) => Object.values(themeStyle).join("")).join("");
|
|
156
|
-
if (!styleMap[key]) {
|
|
157
|
-
styleMap[key] = {
|
|
158
|
-
style: token.style,
|
|
159
|
-
// Using the hash value of the style as the className,
|
|
160
|
-
// ensure that the className remains stable over multiple compilations,
|
|
161
|
-
// which facilitates content caching.
|
|
162
|
-
className: "ct-" + hash(key)
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
return { class: styleMap[key].className };
|
|
166
|
-
}
|
|
167
|
-
function tokenSpan(token) {
|
|
168
|
-
return {
|
|
169
|
-
type: "element",
|
|
170
|
-
tagName: "span",
|
|
171
|
-
properties: getSpanProps(token),
|
|
172
|
-
children: [{ type: "text", value: token.content }]
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
};
|
|
176
|
-
const getHighlightedCode = async (code, lang, theme2, opts2) => {
|
|
177
|
-
const styleMap = opts2?.styleMap || {};
|
|
178
|
-
const highlights = opts2?.highlights || [];
|
|
179
|
-
const { tree, className } = await getHighlightedAST(code, lang, theme2, { styleMap, highlights });
|
|
180
|
-
function renderNode(node) {
|
|
181
|
-
if (node.type === "text") {
|
|
182
|
-
return node.value.replace(/</g, "<").replace(/>/g, ">");
|
|
183
|
-
}
|
|
184
|
-
const children = node.children.map(renderNode).join("");
|
|
185
|
-
return `<${node.tag} class="${node.props.class}">${children}</${node.tag}>`;
|
|
186
|
-
}
|
|
187
|
-
return {
|
|
188
|
-
code: tree.map(renderNode).join(""),
|
|
189
|
-
className,
|
|
190
|
-
styles: generateStyles(styleMap)
|
|
74
|
+
tree: codeEl.children,
|
|
75
|
+
className: preEl.properties.class,
|
|
76
|
+
inlineStyle: preEl.properties.style,
|
|
77
|
+
style
|
|
191
78
|
};
|
|
192
79
|
};
|
|
193
|
-
const generateStyles = (styleMap) => {
|
|
194
|
-
const styles = [];
|
|
195
|
-
for (const styleToken of Object.values(styleMap)) {
|
|
196
|
-
const defaultStyle = styleToken.style.default;
|
|
197
|
-
const hasColor = !!defaultStyle?.color;
|
|
198
|
-
const hasBold = isBold(defaultStyle);
|
|
199
|
-
const hasItalic = isItalic(defaultStyle);
|
|
200
|
-
const hasUnderline = isUnderline(defaultStyle);
|
|
201
|
-
const themeStyles = Object.entries(styleToken.style).map(([variant, style]) => {
|
|
202
|
-
const styleText = [
|
|
203
|
-
// If the default theme has a style, but the current theme does not have one,
|
|
204
|
-
// we need to override to reset style
|
|
205
|
-
["color", style.color || (hasColor ? "unset" : "")],
|
|
206
|
-
["font-weight", isBold(style) ? "bold" : hasBold ? "unset" : ""],
|
|
207
|
-
["font-style", isItalic(style) ? "italic" : hasItalic ? "unset" : ""],
|
|
208
|
-
["text-decoration", isUnderline(style) ? "bold" : hasUnderline ? "unset" : ""],
|
|
209
|
-
["background", style.background || ""]
|
|
210
|
-
].filter((kv) => kv[1]).map((kv) => kv.join(":") + ";").join("");
|
|
211
|
-
return { variant, styleText };
|
|
212
|
-
});
|
|
213
|
-
const defaultThemeStyle = themeStyles.find((themeStyle) => themeStyle.variant === "default");
|
|
214
|
-
themeStyles.forEach((themeStyle) => {
|
|
215
|
-
if (themeStyle.variant === "default") {
|
|
216
|
-
styles.push(`.${styleToken.className}{${themeStyle.styleText}}`);
|
|
217
|
-
} else if (themeStyle.styleText !== defaultThemeStyle?.styleText) {
|
|
218
|
-
styles.push(`.${themeStyle.variant} .${styleToken.className}{${themeStyle.styleText}}`);
|
|
219
|
-
}
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
return styles.join("\n");
|
|
223
|
-
};
|
|
224
80
|
return {
|
|
225
|
-
|
|
226
|
-
getHighlightedAST,
|
|
227
|
-
getHighlightedCode,
|
|
228
|
-
generateStyles
|
|
81
|
+
getHighlightedAST
|
|
229
82
|
};
|
|
230
83
|
});
|
|
231
|
-
function mergeLines(line1, line2) {
|
|
232
|
-
const mergedTokens = [];
|
|
233
|
-
const right = {
|
|
234
|
-
key: line1.key,
|
|
235
|
-
tokens: line1.tokens.slice()
|
|
236
|
-
};
|
|
237
|
-
const left = {
|
|
238
|
-
key: line2.key,
|
|
239
|
-
tokens: line2.tokens.slice()
|
|
240
|
-
};
|
|
241
|
-
let index = 0;
|
|
242
|
-
while (index < right.tokens.length) {
|
|
243
|
-
const rightToken = right.tokens[index];
|
|
244
|
-
const leftToken = left.tokens[index];
|
|
245
|
-
if (rightToken.content === leftToken.content) {
|
|
246
|
-
mergedTokens.push({
|
|
247
|
-
content: rightToken.content,
|
|
248
|
-
style: {
|
|
249
|
-
...right.tokens[index].style,
|
|
250
|
-
...left.tokens[index].style
|
|
251
|
-
}
|
|
252
|
-
});
|
|
253
|
-
index += 1;
|
|
254
|
-
continue;
|
|
255
|
-
}
|
|
256
|
-
if (rightToken.content.startsWith(leftToken.content)) {
|
|
257
|
-
const nextRightToken = {
|
|
258
|
-
...rightToken,
|
|
259
|
-
content: rightToken.content.slice(leftToken.content.length)
|
|
260
|
-
};
|
|
261
|
-
rightToken.content = leftToken.content;
|
|
262
|
-
right.tokens.splice(index + 1, 0, nextRightToken);
|
|
263
|
-
continue;
|
|
264
|
-
}
|
|
265
|
-
if (leftToken.content.startsWith(rightToken.content)) {
|
|
266
|
-
const nextLeftToken = {
|
|
267
|
-
...leftToken,
|
|
268
|
-
content: leftToken.content.slice(rightToken.content.length)
|
|
269
|
-
};
|
|
270
|
-
leftToken.content = rightToken.content;
|
|
271
|
-
left.tokens.splice(index + 1, 0, nextLeftToken);
|
|
272
|
-
continue;
|
|
273
|
-
}
|
|
274
|
-
throw new Error("Unexpected token");
|
|
275
|
-
}
|
|
276
|
-
return mergedTokens;
|
|
277
|
-
}
|
|
278
|
-
function isBold(style) {
|
|
279
|
-
return style && style.fontStyle === FontStyle.Bold;
|
|
280
|
-
}
|
|
281
|
-
function isItalic(style) {
|
|
282
|
-
return style && style.fontStyle === FontStyle.Italic;
|
|
283
|
-
}
|
|
284
|
-
function isUnderline(style) {
|
|
285
|
-
return style && style.fontStyle === FontStyle.Underline;
|
|
286
|
-
}
|
|
287
|
-
function hash(str) {
|
|
288
|
-
return Array.from(str).reduce((s, c) => Math.imul(31, s) + c.charCodeAt(0) | 0, 0).toString().slice(-6);
|
|
289
|
-
}
|
|
290
84
|
function createSingleton(fn) {
|
|
291
85
|
let instance;
|
|
292
86
|
return (...args) => {
|
|
@@ -3,15 +3,16 @@ import { toString } from "hast-util-to-string";
|
|
|
3
3
|
import { defu } from "defu";
|
|
4
4
|
const defaults = {
|
|
5
5
|
theme: {
|
|
6
|
-
default: "github-
|
|
7
|
-
dark: "github-
|
|
6
|
+
default: "github-light",
|
|
7
|
+
dark: "github-dark"
|
|
8
8
|
},
|
|
9
|
-
highlighter: (code, lang, theme) => {
|
|
9
|
+
highlighter: (code, lang, theme, highlights) => {
|
|
10
10
|
return $fetch("/api/_mdc/highlight", {
|
|
11
11
|
params: {
|
|
12
12
|
code,
|
|
13
13
|
lang,
|
|
14
|
-
theme: JSON.stringify(theme)
|
|
14
|
+
theme: JSON.stringify(theme),
|
|
15
|
+
highlights: JSON.stringify(highlights)
|
|
15
16
|
}
|
|
16
17
|
});
|
|
17
18
|
}
|
|
@@ -23,17 +24,24 @@ export function rehypeShiki(opts = {}) {
|
|
|
23
24
|
const styles = [];
|
|
24
25
|
visit(
|
|
25
26
|
tree,
|
|
26
|
-
(node) => node.tagName
|
|
27
|
+
(node) => ["pre", "code"].includes(node.tagName) && !!node.properties?.language,
|
|
27
28
|
(node) => {
|
|
28
29
|
const _node = node;
|
|
29
|
-
const task = options.highlighter(
|
|
30
|
+
const task = options.highlighter(
|
|
31
|
+
toString(node),
|
|
32
|
+
_node.properties.language,
|
|
33
|
+
options.theme,
|
|
34
|
+
_node.properties.highlights ?? []
|
|
35
|
+
).then(({ tree: tree2, className, style, inlineStyle }) => {
|
|
30
36
|
_node.properties.className = ((_node.properties.className || "") + " " + className).trim();
|
|
37
|
+
_node.properties.style = ((_node.properties.style || "") + " " + inlineStyle).trim();
|
|
31
38
|
if (_node.children[0]?.tagName === "code") {
|
|
32
39
|
_node.children[0].children = tree2;
|
|
33
40
|
} else {
|
|
34
|
-
_node.children = tree2;
|
|
41
|
+
_node.children = tree2[0].children;
|
|
35
42
|
}
|
|
36
|
-
|
|
43
|
+
if (style)
|
|
44
|
+
styles.push(style);
|
|
37
45
|
});
|
|
38
46
|
tasks.push(task);
|
|
39
47
|
}
|
|
@@ -1,32 +1,13 @@
|
|
|
1
1
|
import type { Element } from '../types/hast';
|
|
2
|
-
import type {
|
|
3
|
-
export type Theme =
|
|
4
|
-
export type HighlightThemedTokenStyle = Pick<IThemedToken, 'color' | 'fontStyle'> & {
|
|
5
|
-
background?: string;
|
|
6
|
-
};
|
|
7
|
-
export type TokenStyleMap = Record<string, {
|
|
8
|
-
style: Record<string, HighlightThemedTokenStyle>;
|
|
9
|
-
className: string;
|
|
10
|
-
}>;
|
|
11
|
-
export interface HighlightParams {
|
|
12
|
-
code: string;
|
|
13
|
-
lang: string;
|
|
14
|
-
theme: Theme;
|
|
15
|
-
}
|
|
2
|
+
import type { BuiltinTheme } from 'shikiji';
|
|
3
|
+
export type Theme = BuiltinTheme | Record<string, BuiltinTheme>;
|
|
16
4
|
export interface HighlighterOptions {
|
|
17
|
-
|
|
18
|
-
highlights: Array<number>;
|
|
19
|
-
}
|
|
20
|
-
export interface HighlightThemedToken {
|
|
21
|
-
content: string;
|
|
22
|
-
style?: Record<string, HighlightThemedTokenStyle>;
|
|
5
|
+
highlights: number[];
|
|
23
6
|
}
|
|
24
|
-
export interface
|
|
25
|
-
key: string;
|
|
26
|
-
tokens: HighlightThemedToken[];
|
|
27
|
-
}
|
|
28
|
-
export type Highlighter = (code: string, lang: string, theme: Theme) => Promise<{
|
|
7
|
+
export interface HighlightResult {
|
|
29
8
|
tree: Element[];
|
|
30
9
|
className: string;
|
|
31
10
|
style: string;
|
|
32
|
-
|
|
11
|
+
inlineStyle: string;
|
|
12
|
+
}
|
|
13
|
+
export type Highlighter = (code: string, lang: string, theme: Theme, highlights: number[]) => Promise<HighlightResult>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { VNode } from 'vue';
|
|
2
2
|
import type { MDCElement, MDCNode } from '../types';
|
|
3
3
|
/**
|
|
4
4
|
* List of text nodes
|
|
@@ -34,4 +34,4 @@ export declare function nodeTextContent(node: VNode | MDCNode): string;
|
|
|
34
34
|
* @returns
|
|
35
35
|
*/
|
|
36
36
|
export declare function unwrap(vnode: VNode, tags?: string[]): VNode | VNode[];
|
|
37
|
-
export declare function flatUnwrap(vnodes: VNode | VNode[], tags?: string[]): Array<VNode | string
|
|
37
|
+
export declare function flatUnwrap(vnodes: VNode | VNode[], tags?: string | string[]): Array<VNode | string> | VNode;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { Text } from "vue";
|
|
2
1
|
export const TEXT_TAGS = ["p", "h1", "h2", "h3", "h4", "h5", "h6", "li"];
|
|
3
2
|
export function isTag(vnode, tag) {
|
|
4
3
|
if (vnode.type === tag) {
|
|
@@ -13,7 +12,7 @@ export function isTag(vnode, tag) {
|
|
|
13
12
|
return false;
|
|
14
13
|
}
|
|
15
14
|
export function isText(vnode) {
|
|
16
|
-
return isTag(vnode, "text") || isTag(vnode,
|
|
15
|
+
return isTag(vnode, "text") || isTag(vnode, Symbol.for("v-txt"));
|
|
17
16
|
}
|
|
18
17
|
export function nodeChildren(node) {
|
|
19
18
|
if (Array.isArray(node.children) || typeof node.children === "string") {
|
|
@@ -40,7 +39,7 @@ export function nodeTextContent(node) {
|
|
|
40
39
|
}
|
|
41
40
|
return "";
|
|
42
41
|
}
|
|
43
|
-
export function unwrap(vnode, tags = [
|
|
42
|
+
export function unwrap(vnode, tags = []) {
|
|
44
43
|
if (Array.isArray(vnode)) {
|
|
45
44
|
return vnode.flatMap((node) => unwrap(node, tags));
|
|
46
45
|
}
|
|
@@ -53,14 +52,20 @@ export function unwrap(vnode, tags = ["p"]) {
|
|
|
53
52
|
}
|
|
54
53
|
return result;
|
|
55
54
|
}
|
|
56
|
-
function _flatUnwrap(vnodes, tags = [
|
|
55
|
+
function _flatUnwrap(vnodes, tags = []) {
|
|
57
56
|
vnodes = Array.isArray(vnodes) ? vnodes : [vnodes];
|
|
58
57
|
if (!tags.length) {
|
|
59
58
|
return vnodes;
|
|
60
59
|
}
|
|
61
60
|
return vnodes.flatMap((vnode) => _flatUnwrap(unwrap(vnode, [tags[0]]), tags.slice(1))).filter((vnode) => !(isText(vnode) && nodeTextContent(vnode).trim() === ""));
|
|
62
61
|
}
|
|
63
|
-
export function flatUnwrap(vnodes, tags = [
|
|
62
|
+
export function flatUnwrap(vnodes, tags = []) {
|
|
63
|
+
if (typeof tags === "string") {
|
|
64
|
+
tags = tags.split(",").map((tag) => tag.trim()).filter(Boolean);
|
|
65
|
+
}
|
|
66
|
+
if (!tags.length) {
|
|
67
|
+
return vnodes;
|
|
68
|
+
}
|
|
64
69
|
return _flatUnwrap(vnodes, tags).reduce((acc, item) => {
|
|
65
70
|
if (isText(item)) {
|
|
66
71
|
if (typeof acc[acc.length - 1] === "string") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nuxtjs/mdc",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Nuxt MDC module",
|
|
5
5
|
"repository": "nuxt-modules/mdc",
|
|
6
6
|
"license": "MIT",
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@nuxt/kit": "latest",
|
|
38
|
-
"@types/hast": "^3.0.
|
|
39
|
-
"@types/mdast": "^4.0.
|
|
38
|
+
"@types/hast": "^3.0.1",
|
|
39
|
+
"@types/mdast": "^4.0.1",
|
|
40
40
|
"@vue/compiler-core": "^3.3.4",
|
|
41
41
|
"consola": "^3.2.3",
|
|
42
42
|
"defu": "^6.1.2",
|
|
@@ -47,10 +47,10 @@
|
|
|
47
47
|
"mdast-util-to-hast": "^13.0.2",
|
|
48
48
|
"micromark-util-sanitize-uri": "^2.0.0",
|
|
49
49
|
"ohash": "^1.1.3",
|
|
50
|
-
"property-information": "^6.
|
|
51
|
-
"rehype-external-links": "^
|
|
50
|
+
"property-information": "^6.3.0",
|
|
51
|
+
"rehype-external-links": "^3.0.0",
|
|
52
52
|
"rehype-raw": "^6.1.1",
|
|
53
|
-
"rehype-slug": "^
|
|
53
|
+
"rehype-slug": "^6.0.0",
|
|
54
54
|
"rehype-sort-attribute-values": "^5.0.0",
|
|
55
55
|
"rehype-sort-attributes": "^5.0.0",
|
|
56
56
|
"remark-emoji": "^4.0.0",
|
|
@@ -59,29 +59,29 @@
|
|
|
59
59
|
"remark-parse": "^10.0.2",
|
|
60
60
|
"remark-rehype": "^10.1.0",
|
|
61
61
|
"scule": "^1.0.0",
|
|
62
|
-
"
|
|
63
|
-
"ufo": "^1.3.
|
|
64
|
-
"unified": "^11.0.
|
|
62
|
+
"shikiji": "^0.6.8",
|
|
63
|
+
"ufo": "^1.3.1",
|
|
64
|
+
"unified": "^11.0.3",
|
|
65
65
|
"unist-builder": "^4.0.0",
|
|
66
66
|
"unist-util-visit": "^5.0.0"
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
69
|
"@nuxt/devtools": "latest",
|
|
70
70
|
"@nuxt/eslint-config": "^0.2.0",
|
|
71
|
-
"@nuxt/module-builder": "^0.5.
|
|
72
|
-
"@nuxt/schema": "^3.7.
|
|
73
|
-
"@nuxt/test-utils": "^3.7.
|
|
71
|
+
"@nuxt/module-builder": "^0.5.2",
|
|
72
|
+
"@nuxt/schema": "^3.7.4",
|
|
73
|
+
"@nuxt/test-utils": "^3.7.4",
|
|
74
74
|
"@nuxthq/ui": "^2.7.0",
|
|
75
|
-
"@types/mdurl": "^1.0.
|
|
76
|
-
"@types/node": "^20.
|
|
75
|
+
"@types/mdurl": "^1.0.3",
|
|
76
|
+
"@types/node": "^20.7.1",
|
|
77
77
|
"changelogen": "^0.5.5",
|
|
78
|
-
"eslint": "^8.
|
|
79
|
-
"nuxt": "^3.7.
|
|
80
|
-
"rehype": "^
|
|
81
|
-
"release-it": "^16.1
|
|
82
|
-
"vitest": "^0.34.
|
|
78
|
+
"eslint": "^8.50.0",
|
|
79
|
+
"nuxt": "^3.7.4",
|
|
80
|
+
"rehype": "^13.0.1",
|
|
81
|
+
"release-it": "^16.2.1",
|
|
82
|
+
"vitest": "^0.34.5"
|
|
83
83
|
},
|
|
84
|
-
"packageManager": "pnpm@8.
|
|
84
|
+
"packageManager": "pnpm@8.8.0",
|
|
85
85
|
"release-it": {
|
|
86
86
|
"git": {
|
|
87
87
|
"commitMessage": "chore(release): release v${version}"
|