feat(plugin-shikiji): auto scan code blocks language (#243)

This commit is contained in:
pengzhanbo 2024-10-02 01:29:28 +08:00 committed by GitHub
parent 5115791aa7
commit 5d112d0e37
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 53 additions and 1 deletions

View File

@ -1 +1,2 @@
export * from './highlight.js'
export * from './scanLanguages.js'

View File

@ -0,0 +1,34 @@
import type { App } from 'vuepress'
import fs from 'node:fs/promises'
import path from 'node:path'
import fg from 'fast-glob'
import { bundledLanguages } from 'shiki'
const languages = Object.keys(bundledLanguages)
const RE_FENCE = /`{3,}[^`]*?(\s|$)/g
export async function scanLanguages(app: App): Promise<string[]> {
const source = app.dir.source()
const pattern = ['**/*.md', '!.vuepress', '!node_modules']
const files = await fg(pattern, {
cwd: source,
})
const langs = new Set<string>()
for (const file of files) {
const filepath = path.join(source, file)
const content = await fs.readFile(filepath, 'utf-8')
const matched = content.match(RE_FENCE)
if (matched) {
for (const match of matched) {
let lang = match.replace(/`{3,}/, '').trim()
if (lang.includes(':'))
lang = lang.split(':')[0]
if (lang)
langs.add(lang)
}
}
}
return Array.from(langs).filter(lang => languages.includes(lang))
}

View File

@ -7,7 +7,7 @@ import type {
} from './types.js'
import { isPlainObject } from 'vuepress/shared'
import { copyCodeButtonPlugin } from './copy-code-button/index.js'
import { highlight } from './highlight/index.js'
import { highlight, scanLanguages } from './highlight/index.js'
import {
collapsedLinesPlugin,
highlightLinesPlugin,
@ -15,6 +15,7 @@ import {
preWrapperPlugin,
} from './markdown/index.js'
import { prepareClientConfigFile } from './prepareClientConfigFile.js'
import { logger } from './utils/index.js'
export interface ShikiPluginOptions
extends HighlighterOptions, LineNumberOptions, PreWrapperOptions {
@ -49,9 +50,21 @@ export function shikiPlugin({
}),
extendsMarkdown: async (md, app) => {
const start = performance.now()
const theme = options.theme ?? { light: 'github-light', dark: 'github-dark' }
if (!options.languages || !options.languages.length) {
options.languages = await scanLanguages(app)
if (app.env.isDebug) {
logger.info(`scan languages: ${JSON.stringify(options.languages)}`)
logger.info(`scan languages in: ${(performance.now() - start).toFixed(2)}ms`)
}
}
md.options.highlight = await highlight(theme, options)
if (app.env.isDebug) {
logger.info(`highlight Loaded in: ${(performance.now() - start).toFixed(2)}ms`)
}
md.use(highlightLinesPlugin)
md.use(preWrapperPlugin, { preWrapper })

View File

@ -1,3 +1,7 @@
import { Logger } from '@vuepress/helper'
export const logger = new Logger('@vuepress-plume/plugin-shikiji')
export * from './attrsToLines.js'
export * from './collapsedLines.js'
export * from './lru.js'