115 lines
3.2 KiB
TypeScript
115 lines
3.2 KiB
TypeScript
import type { TransformerTwoslashOptions } from '@shikijs/twoslash/core'
|
|
import type { ShikiTransformer } from 'shiki'
|
|
import type { VueSpecificOptions } from 'twoslash-vue'
|
|
import type { WhitespacePosition } from '../utils/index.js'
|
|
import process from 'node:process'
|
|
import {
|
|
transformerCompactLineOptions,
|
|
transformerNotationDiff,
|
|
transformerNotationErrorLevel,
|
|
transformerNotationFocus,
|
|
transformerNotationHighlight,
|
|
transformerNotationWordHighlight,
|
|
transformerRemoveNotationEscape,
|
|
transformerRenderWhitespace,
|
|
} from '@shikijs/transformers'
|
|
import { defaultTwoslashOptions } from '@shikijs/twoslash/core'
|
|
import { addClassToHast } from 'shiki'
|
|
import { isPlainObject } from 'vuepress/shared'
|
|
import { defaultHoverInfoProcessor, transformerTwoslash } from '../twoslash/rendererTransformer.js'
|
|
import { attrsToLines, resolveWhitespacePosition } from '../utils/index.js'
|
|
|
|
const decorationsRE = /^\/\/ @decorations:(.*)\n/
|
|
|
|
export const baseTransformers: ShikiTransformer[] = [
|
|
transformerNotationDiff({
|
|
matchAlgorithm: 'v3',
|
|
}),
|
|
transformerNotationFocus({
|
|
matchAlgorithm: 'v3',
|
|
classActiveLine: 'has-focus',
|
|
classActivePre: 'has-focused-lines',
|
|
}),
|
|
transformerNotationHighlight({
|
|
matchAlgorithm: 'v3',
|
|
}),
|
|
transformerNotationErrorLevel({
|
|
matchAlgorithm: 'v3',
|
|
}),
|
|
transformerNotationWordHighlight({
|
|
matchAlgorithm: 'v3',
|
|
}),
|
|
{
|
|
name: 'vuepress:add-class',
|
|
pre(node) {
|
|
addClassToHast(node, 'vp-code')
|
|
},
|
|
},
|
|
{
|
|
name: 'vuepress:clean-up',
|
|
pre(node) {
|
|
delete node.properties.tabindex
|
|
delete node.properties.style
|
|
},
|
|
},
|
|
{
|
|
name: 'shiki:inline-decorations',
|
|
preprocess(code, options) {
|
|
code = code.replace(decorationsRE, (match, decorations) => {
|
|
options.decorations ||= []
|
|
options.decorations.push(...JSON.parse(decorations))
|
|
return ''
|
|
})
|
|
return code
|
|
},
|
|
},
|
|
transformerRemoveNotationEscape(),
|
|
]
|
|
|
|
const vueRE = /-vue$/
|
|
export function getInlineTransformers({ attrs, lang, enabledTwoslash, whitespace, twoslash }: {
|
|
attrs: string
|
|
lang: string
|
|
enabledTwoslash: boolean
|
|
whitespace: boolean | WhitespacePosition
|
|
twoslash?: boolean | TransformerTwoslashOptions['twoslashOptions'] & VueSpecificOptions
|
|
}): ShikiTransformer[] {
|
|
const vPre = vueRE.test(lang) ? '' : 'v-pre'
|
|
const inlineTransformers: ShikiTransformer[] = [
|
|
transformerCompactLineOptions(attrsToLines(attrs)),
|
|
]
|
|
|
|
if (enabledTwoslash) {
|
|
const { compilerOptions, ...twoslashOptions } = isPlainObject(twoslash) ? twoslash : {}
|
|
const defaultOptions = defaultTwoslashOptions()
|
|
inlineTransformers.push(transformerTwoslash({
|
|
processHoverInfo(info) {
|
|
return defaultHoverInfoProcessor(info)
|
|
},
|
|
twoslashOptions: {
|
|
...defaultOptions,
|
|
...twoslashOptions,
|
|
compilerOptions: {
|
|
baseUrl: process.cwd(),
|
|
...compilerOptions,
|
|
},
|
|
},
|
|
}))
|
|
}
|
|
else {
|
|
inlineTransformers.push({
|
|
name: 'vuepress:v-pre',
|
|
pre(node) {
|
|
if (vPre)
|
|
node.properties['v-pre'] = ''
|
|
},
|
|
})
|
|
}
|
|
|
|
const position = resolveWhitespacePosition(attrs, whitespace)
|
|
if (position)
|
|
inlineTransformers.push(transformerRenderWhitespace({ position }))
|
|
|
|
return inlineTransformers
|
|
}
|