Skip to content

Commit 8acd640

Browse files
authored
refactor(plugin-shiki): code and test refactor (#302)
1 parent 356e1a2 commit 8acd640

File tree

10 files changed

+160
-130
lines changed

10 files changed

+160
-130
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export const createMarkdownFilePathGetter = (
1111
const rawRender = md.render.bind(md)
1212

1313
// we need to store file path before each render
14-
md.render = (src, env: MarkdownEnv) => {
14+
md.render = (src, env: MarkdownEnv = {}) => {
1515
store.path = env.filePathRelative
1616

1717
return rawRender(src, env)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import type { BundledLanguage, BundledTheme, HighlighterGeneric } from 'shiki'
2+
import { createHighlighter } from 'shiki'
3+
import { bundledLanguageNames } from '../../shiki.js'
4+
import type { ShikiHighlightOptions } from '../../types.js'
5+
6+
export const createShikiHighlighter = async ({
7+
langs = bundledLanguageNames,
8+
langAlias = {},
9+
defaultLang,
10+
shikiSetup,
11+
...options
12+
}: ShikiHighlightOptions = {}): Promise<
13+
HighlighterGeneric<BundledLanguage, BundledTheme>
14+
> => {
15+
const shikiHighlighter = await createHighlighter({
16+
langs,
17+
langAlias,
18+
themes:
19+
'themes' in options
20+
? Object.values(options.themes)
21+
: [options.theme ?? 'nord'],
22+
})
23+
24+
await shikiSetup?.(shikiHighlighter)
25+
26+
return shikiHighlighter
27+
}

plugins/markdown/plugin-shiki/src/node/markdown/applyHighlighter/index.ts renamed to plugins/markdown/plugin-shiki/src/node/markdown/highlighter/getHighLightFunction.ts

Lines changed: 16 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,37 @@
11
import { transformerCompactLineOptions } from '@shikijs/transformers'
2-
import type MarkdownIt from 'markdown-it'
3-
import { createHighlighter } from 'shiki'
4-
import type { App } from 'vuepress'
5-
import { bundledLanguageNames } from '../../shiki.js'
2+
import type { BundledLanguage, BundledTheme, HighlighterGeneric } from 'shiki'
63
import {
74
getTransformers,
85
whitespaceTransformer,
96
} from '../../transformers/getTransformers.js'
107
import type { ShikiHighlightOptions } from '../../types.js'
118
import { attrsToLines } from '../../utils.js'
12-
import { createMarkdownFilePathGetter } from './createMarkdownFilePathGetter.js'
9+
import type { MarkdownFilePathGetter } from './createMarkdownFilePathGetter.js'
1310
import { getLanguage } from './getLanguage.js'
1411
import { handleMustache } from './handleMustache.js'
1512

16-
export const applyHighlighter = async (
17-
md: MarkdownIt,
18-
app: App,
19-
{
20-
langs = bundledLanguageNames,
21-
langAlias = {},
22-
defaultLang,
23-
transformers: userTransformers = [],
24-
...options
25-
}: ShikiHighlightOptions = {},
26-
): Promise<void> => {
27-
const logLevel = options.logLevel ?? (app.env.isDebug ? 'debug' : 'warn')
28-
const getMarkdownFilePath =
29-
logLevel === 'debug' ? createMarkdownFilePathGetter(md) : null
30-
31-
const highlighter = await createHighlighter({
32-
langs,
33-
langAlias,
34-
themes:
35-
'themes' in options
36-
? Object.values(options.themes)
37-
: [options.theme ?? 'nord'],
38-
})
39-
40-
await options.shikiSetup?.(highlighter)
13+
type MarkdownItHighlight = (
14+
content: string,
15+
language: string,
16+
attrs: string,
17+
) => string
4118

19+
export const getHighLightFunction = (
20+
highlighter: HighlighterGeneric<BundledLanguage, BundledTheme>,
21+
options: ShikiHighlightOptions,
22+
markdownFilePathGetter: MarkdownFilePathGetter,
23+
): MarkdownItHighlight => {
4224
const transformers = getTransformers(options)
4325
const loadedLanguages = highlighter.getLoadedLanguages()
4426

45-
md.options.highlight = (content, language, attrs) =>
27+
return (content, language, attrs) =>
4628
handleMustache(content, (str) =>
4729
highlighter.codeToHtml(str, {
4830
lang: getLanguage(
4931
language,
5032
loadedLanguages,
51-
defaultLang,
52-
logLevel,
53-
getMarkdownFilePath!,
33+
options,
34+
markdownFilePathGetter,
5435
),
5536
meta: {
5637
/**
@@ -65,7 +46,7 @@ export const applyHighlighter = async (
6546
? [transformerCompactLineOptions(attrsToLines(attrs))]
6647
: []),
6748
...whitespaceTransformer(attrs, options.whitespace),
68-
...userTransformers,
49+
...(options.transformers ?? []),
6950
],
7051
...('themes' in options
7152
? {

plugins/markdown/plugin-shiki/src/node/markdown/applyHighlighter/getLanguage.ts renamed to plugins/markdown/plugin-shiki/src/node/markdown/highlighter/getLanguage.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { isSpecialLang } from 'shiki'
22
import { colors } from 'vuepress/utils'
3+
import type { ShikiHighlightOptions } from '../../types.js'
34
import { logger, resolveLanguage } from '../../utils.js'
45
import type { MarkdownFilePathGetter } from './createMarkdownFilePathGetter.js'
56

@@ -8,9 +9,8 @@ const WARNED_LANGS = new Set<string>()
89
export const getLanguage = (
910
lang: string,
1011
loadedLanguages: string[],
11-
defaultLang: string | undefined,
12-
logLevel: string,
13-
getMarkdownFilePath: MarkdownFilePathGetter,
12+
{ defaultLang, logLevel }: ShikiHighlightOptions,
13+
markdownFilePathGetter: MarkdownFilePathGetter,
1414
): string => {
1515
let result = resolveLanguage(lang)
1616

@@ -26,7 +26,7 @@ export const getLanguage = (
2626
// log file path if unknown language is found
2727
if (logLevel === 'debug') {
2828
logger.info(
29-
`Unknown language ${colors.cyan(result)} found in ${colors.cyan(getMarkdownFilePath())}`,
29+
`Unknown language ${colors.cyan(result)} found in ${colors.cyan(markdownFilePathGetter())}`,
3030
)
3131
}
3232

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export * from './createMarkdownFilePathGetter.js'
2+
export * from './createShikiHighlighter.js'
3+
export * from './getHighLightFunction.js'
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
export * from './applyHighlighter/index.js'
1+
export * from './highlighter/index.js'
22
export * from './highlightLinesPlugin.js'
33
export * from './preWrapperPlugin.js'

plugins/markdown/plugin-shiki/src/node/shikiPlugin.ts

Lines changed: 46 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -8,50 +8,60 @@ import {
88
} from '@vuepress/highlighter-helper'
99
import type { Plugin } from 'vuepress/core'
1010
import { isPlainObject } from 'vuepress/shared'
11+
import { createMarkdownFilePathGetter } from './markdown/highlighter/createMarkdownFilePathGetter.js'
1112
import type { MarkdownItPreWrapperOptions } from './markdown/index.js'
1213
import {
13-
applyHighlighter,
14+
createShikiHighlighter,
15+
getHighLightFunction,
1416
highlightLinesPlugin,
1517
preWrapperPlugin,
1618
} from './markdown/index.js'
1719
import type { ShikiPluginOptions } from './options.js'
1820
import { prepareClientConfigFile } from './prepareClientConfigFile.js'
1921

20-
export const shikiPlugin = (options: ShikiPluginOptions = {}): Plugin => {
21-
const opt: ShikiPluginOptions = {
22-
preWrapper: true,
23-
lineNumbers: true,
24-
collapsedLines: 'disable',
25-
...options,
26-
}
22+
export const shikiPlugin = (_options: ShikiPluginOptions = {}): Plugin => {
23+
return (app) => {
24+
// FIXME: Remove in stable version
25+
// eslint-disable-next-line @typescript-eslint/no-deprecated
26+
const { code } = app.options.markdown
27+
const options = {
28+
...(isPlainObject(code) ? code : {}),
29+
..._options,
30+
}
31+
32+
options.logLevel ??= app.env.isDebug ? 'debug' : 'warn'
33+
options.preWrapper ??= true
34+
options.lineNumbers ??= true
35+
options.collapsedLines ??= 'disable'
36+
37+
return {
38+
name: '@vuepress/plugin-shiki',
39+
40+
extendsMarkdown: async (md) => {
41+
const { preWrapper, lineNumbers, collapsedLines } = options
42+
43+
const markdownFilePathGetter = createMarkdownFilePathGetter(md)
44+
const shikiHighlighter = await createShikiHighlighter(options)
45+
46+
md.options.highlight = getHighLightFunction(
47+
shikiHighlighter,
48+
options,
49+
markdownFilePathGetter,
50+
)
51+
52+
md.use(highlightLinesPlugin)
53+
md.use<MarkdownItPreWrapperOptions>(preWrapperPlugin, { preWrapper })
54+
if (preWrapper) {
55+
md.use<MarkdownItLineNumbersOptions>(lineNumbersPlugin, {
56+
lineNumbers,
57+
})
58+
md.use<MarkdownItCollapsedLinesOptions>(collapsedLinesPlugin, {
59+
collapsedLines,
60+
})
61+
}
62+
},
2763

28-
return {
29-
name: '@vuepress/plugin-shiki',
30-
31-
extendsMarkdown: async (md, app) => {
32-
// FIXME: Remove in stable version
33-
// eslint-disable-next-line @typescript-eslint/no-deprecated
34-
const { code } = app.options.markdown
35-
36-
await applyHighlighter(md, app, {
37-
...(isPlainObject(code) ? code : {}),
38-
...options,
39-
})
40-
41-
const { preWrapper, lineNumbers, collapsedLines } = opt
42-
43-
md.use(highlightLinesPlugin)
44-
md.use<MarkdownItPreWrapperOptions>(preWrapperPlugin, { preWrapper })
45-
if (preWrapper) {
46-
md.use<MarkdownItLineNumbersOptions>(lineNumbersPlugin, {
47-
lineNumbers,
48-
})
49-
md.use<MarkdownItCollapsedLinesOptions>(collapsedLinesPlugin, {
50-
collapsedLines,
51-
})
52-
}
53-
},
54-
55-
clientConfigFile: (app) => prepareClientConfigFile(app, opt),
64+
clientConfigFile: () => prepareClientConfigFile(app, options),
65+
}
5666
}
5767
}

0 commit comments

Comments
 (0)