Skip to content

Commit 53875b1

Browse files
committedMar 10, 2025·
fix(parser): recreate highlighter when options did change
1 parent 6ec0eb8 commit 53875b1

File tree

1 file changed

+62
-56
lines changed

1 file changed

+62
-56
lines changed
 

‎src/utils/content/index.ts

+62-56
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { dirname } from 'node:path'
22
import { createShikiHighlighter, rehypeHighlight } from '@nuxtjs/mdc/runtime'
33
import { hash } from 'ohash'
4-
import type { Highlighter, MdcConfig, ModuleOptions as MDCModuleOptions } from '@nuxtjs/mdc'
4+
import type { Highlighter, MdcConfig, ModuleOptions as MDCModuleOptions, MdcThemeOptions } from '@nuxtjs/mdc'
55
import type { Nuxt } from '@nuxt/schema'
66
import { resolveAlias } from '@nuxt/kit'
77
import type { LanguageRegistration } from 'shiki'
@@ -35,69 +35,75 @@ let highlightPlugin: {
3535
}
3636
let highlightPluginPromise: Promise<typeof highlightPlugin>
3737
async function getHighlightPluginInstance(options: HighlighterOptions) {
38+
const key = hash(JSON.stringify(options || {}))
39+
40+
// If the key is different, reset the plugin
41+
if (highlightPlugin && highlightPlugin.key !== key) {
42+
highlightPlugin = undefined
43+
highlightPluginPromise = undefined
44+
}
45+
46+
// If the plugin is not initialized, initialize it
3847
if (!highlightPlugin) {
39-
highlightPluginPromise = highlightPluginPromise || _getHighlightPlugin(options)
48+
highlightPluginPromise = highlightPluginPromise || _getHighlightPlugin(key, options)
4049
await highlightPluginPromise
4150
}
4251

4352
return highlightPlugin
4453
}
45-
async function _getHighlightPlugin(options: HighlighterOptions) {
46-
const key = hash(JSON.stringify(options || {}))
47-
if (!highlightPlugin || highlightPlugin.key !== key) {
48-
const langs = Array.from(new Set(['bash', 'html', 'mdc', 'vue', 'yml', 'scss', 'ts', 'typescript', ...(options.langs || [])]))
49-
const themesObject = typeof options.theme === 'string' ? { default: options.theme } : options.theme || { default: 'material-theme-palenight' }
50-
const bundledThemes = await Promise.all(Object.entries(themesObject)
51-
.map(async ([name, theme]) => [
52-
name,
53-
typeof theme === 'string' ? (await import(`shiki/themes/${theme}.mjs`).then(m => m.default || m)) : theme,
54-
]))
55-
const bundledLangs = await Promise.all(langs.map(async lang => [
56-
typeof lang === 'string' ? lang : (lang as unknown as LanguageRegistration).name,
57-
typeof lang === 'string' ? await import(`@shikijs/langs/${lang}`).then(m => m.default || m) : lang,
54+
async function _getHighlightPlugin(key: string, options: HighlighterOptions) {
55+
const langs = Array.from(new Set(['bash', 'html', 'mdc', 'vue', 'yml', 'scss', 'ts', 'typescript', ...(options.langs || [])]))
56+
const themesObject = typeof options.theme === 'string' ? { default: options.theme } : options.theme || { default: 'material-theme-palenight' }
57+
const bundledThemes = await Promise.all(Object.entries(themesObject)
58+
.map(async ([name, theme]) => [
59+
name,
60+
typeof theme === 'string' ? (await import(`shiki/themes/${theme}.mjs`).then(m => m.default || m)) : theme,
5861
]))
59-
60-
const highlighter = createShikiHighlighter({
61-
bundledThemes: Object.fromEntries(bundledThemes),
62-
// Configure the bundled languages
63-
bundledLangs: Object.fromEntries(bundledLangs),
64-
engine: createOnigurumaEngine(import('shiki/wasm')),
65-
getMdcConfigs: () => Promise.resolve(parserOptions.mdcConfigs),
66-
})
67-
68-
highlightPlugin = {
69-
key,
70-
instance: rehypeHighlight,
71-
...options,
72-
options: {
73-
highlighter: async (code, lang, theme, opts) => {
74-
const result = await highlighter(code, lang, theme, opts)
75-
const visitTree = {
76-
type: 'element',
77-
children: result.tree as Array<unknown>,
78-
}
79-
if (options.compress) {
80-
const stylesMap: Record<string, string> = {}
81-
visit(
82-
visitTree,
83-
node => !!(node as HighlightedNode).properties?.style,
84-
(_node) => {
85-
const node = _node as HighlightedNode
86-
const style = node.properties!.style!
87-
stylesMap[style] = stylesMap[style] || 's' + hash(style).substring(0, 4)
88-
node.properties!.class = `${node.properties!.class || ''} ${stylesMap[style]}`.trim()
89-
node.properties!.style = undefined
90-
},
91-
)
92-
93-
result.style = Object.entries(stylesMap).map(([style, cls]) => `html pre.shiki code .${cls}, html code.shiki .${cls}{${style}}`).join('') + result.style
94-
}
95-
96-
return result
97-
},
98-
theme: Object.fromEntries(bundledThemes),
62+
const bundledLangs = await Promise.all(langs.map(async lang => [
63+
typeof lang === 'string' ? lang : (lang as unknown as LanguageRegistration).name,
64+
typeof lang === 'string' ? await import(`@shikijs/langs/${lang}`).then(m => m.default || m) : lang,
65+
]))
66+
67+
const highlighter = createShikiHighlighter({
68+
bundledThemes: Object.fromEntries(bundledThemes),
69+
// Configure the bundled languages
70+
bundledLangs: Object.fromEntries(bundledLangs),
71+
engine: createOnigurumaEngine(import('shiki/wasm')),
72+
getMdcConfigs: () => Promise.resolve(parserOptions.mdcConfigs),
73+
})
74+
75+
highlightPlugin = {
76+
key,
77+
instance: rehypeHighlight,
78+
...options,
79+
options: {
80+
highlighter: async (code, lang, theme, opts) => {
81+
const result = await highlighter(code, lang, theme, opts)
82+
const visitTree = {
83+
type: 'element',
84+
children: result.tree as Array<unknown>,
85+
}
86+
if (options.compress) {
87+
const stylesMap: Record<string, string> = {}
88+
visit(
89+
visitTree,
90+
node => !!(node as HighlightedNode).properties?.style,
91+
(_node) => {
92+
const node = _node as HighlightedNode
93+
const style = node.properties!.style!
94+
stylesMap[style] = stylesMap[style] || 's' + hash(style).substring(0, 4)
95+
node.properties!.class = `${node.properties!.class || ''} ${stylesMap[style]}`.trim()
96+
node.properties!.style = undefined
97+
},
98+
)
99+
100+
result.style = Object.entries(stylesMap).map(([style, cls]) => `html pre.shiki code .${cls}, html code.shiki .${cls}{${style}}`).join('') + result.style
101+
}
102+
103+
return result
99104
},
100-
}
105+
theme: Object.fromEntries(bundledThemes),
106+
},
101107
}
102108
return highlightPlugin
103109
}

0 commit comments

Comments
 (0)
Please sign in to comment.