mirror of
https://github.com/pengzhanbo/vuepress-theme-plume.git
synced 2026-04-23 10:58:13 +08:00
88 lines
2.4 KiB
TypeScript
88 lines
2.4 KiB
TypeScript
import container from 'markdown-it-container'
|
|
import { fs, getDirname, path } from 'vuepress/utils'
|
|
import type markdownIt from 'markdown-it'
|
|
import type Token from 'markdown-it/lib/token.mjs'
|
|
import type { App } from 'vuepress/core'
|
|
import type { ReplEditorData, ReplOptions } from '../../shared/index.js'
|
|
|
|
const RE_INFO = /^(#editable)?(.*)$/
|
|
|
|
function createReplContainer(md: markdownIt, lang: string) {
|
|
const type = `${lang}-repl`
|
|
const validate = (info: string): boolean => info.trim().startsWith(type)
|
|
|
|
const render = (tokens: Token[], index: number): string => {
|
|
const token = tokens[index]
|
|
const info = token.info.trim().slice(type.length).trim() || ''
|
|
// :::lang-repl#editable title
|
|
const [, editable, title] = info.match(RE_INFO) ?? []
|
|
|
|
if (token.nesting === 1)
|
|
return `<CodeRepl ${editable ? 'editable' : ''} title="${title || `${lang} playground`}">`
|
|
|
|
else
|
|
return '</CodeRepl>'
|
|
}
|
|
|
|
md.use(container, type, { validate, render })
|
|
}
|
|
|
|
export async function langReplPlugin(app: App, md: markdownIt, {
|
|
theme,
|
|
go = false,
|
|
kotlin = false,
|
|
rust = false,
|
|
}: ReplOptions) {
|
|
if (kotlin) {
|
|
createReplContainer(md, 'kotlin')
|
|
}
|
|
if (go) {
|
|
createReplContainer(md, 'go')
|
|
}
|
|
if (rust) {
|
|
createReplContainer(md, 'rust')
|
|
}
|
|
theme ??= { light: 'github-light', dark: 'github-dark' }
|
|
|
|
const data: ReplEditorData = { grammars: {} } as ReplEditorData
|
|
|
|
const themesPath = getDirname(import.meta.resolve('tm-themes'))
|
|
const grammarsPath = getDirname(import.meta.resolve('tm-grammars'))
|
|
|
|
const readTheme = (theme: string) => read(path.join(themesPath, 'themes', `${theme}.json`))
|
|
const readGrammar = (grammar: string) => read(path.join(grammarsPath, 'grammars', `${grammar}.json`))
|
|
|
|
if (typeof theme === 'string') {
|
|
data.theme = await readTheme(theme)
|
|
}
|
|
else {
|
|
data.theme = await Promise.all([
|
|
readTheme(theme.light),
|
|
readTheme(theme.dark),
|
|
]).then(([light, dark]) => ({ light, dark }))
|
|
}
|
|
|
|
if (kotlin)
|
|
data.grammars.kotlin = await readGrammar('kotlin')
|
|
|
|
if (go)
|
|
data.grammars.go = await readGrammar('go')
|
|
|
|
if (rust)
|
|
data.grammars.rust = await readGrammar('rust')
|
|
|
|
await app.writeTemp(
|
|
'internal/md-power/replEditorData.js',
|
|
`export default ${JSON.stringify(data, null, 2)}`,
|
|
)
|
|
}
|
|
|
|
async function read(file: string): Promise<any> {
|
|
try {
|
|
const content = await fs.readFile(file, 'utf-8')
|
|
return JSON.parse(content)
|
|
}
|
|
catch {}
|
|
return undefined
|
|
}
|