返回 slidev
shiki.ts
根目录 / packages / slidev / node / syntax / shiki.ts
1 import type { ResolvedSlidevOptions } from '@slidev/types'
2 import type { ShikiTransformer } from 'shiki'
3 import { isTruthy } from '@antfu/utils'
4 import { fromAsyncCodeToHtml } from '@shikijs/markdown-it/async'
5
6 export default async function MarkdownItShiki({ data: { config }, mode, utils: { shiki, shikiOptions } }: ResolvedSlidevOptions) {
7 async function getTwoslashTransformer() {
8 const [, , { transformerTwoslash }] = await Promise.all([
9 // trigger shiki to load the langs
10 shiki.codeToHast('', { lang: 'js', ...shikiOptions }),
11 shiki.codeToHast('', { lang: 'ts', ...shikiOptions }),
12
13 import('@shikijs/vitepress-twoslash'),
14 ])
15 return transformerTwoslash({
16 explicitTrigger: true,
17 twoslashOptions: {
18 compilerOptions: {
19 ignoreDeprecations: '6.0',
20 },
21 handbookOptions: {
22 noErrorValidation: true,
23 },
24 },
25 })
26 }
27
28 const transformers = [
29 ...shikiOptions.transformers || [],
30 (config.twoslash === true || config.twoslash === mode) && await getTwoslashTransformer(),
31 (config.twoslash === true || config.twoslash === mode) && transformerTwoslashConditional(),
32 {
33 pre(pre) {
34 this.addClassToHast(pre, 'slidev-code')
35 delete pre.properties.tabindex
36 },
37 } satisfies ShikiTransformer,
38 ].filter(isTruthy) as ShikiTransformer[]
39
40 return fromAsyncCodeToHtml(shiki.codeToHtml, {
41 ...shikiOptions,
42 transformers,
43 })
44 }
45
46 // Fix #2202
47 function transformerTwoslashConditional(): ShikiTransformer {
48 return {
49 name: 'slidev:twoslash-conditional',
50 code: function applyConditionalFlag(this: any, node) {
51 if (node.tagName === 'v-menu') {
52 if (node.properties[':shown'] === 'true')
53 node.properties[':shown'] = '$nav.currentPage === $page'
54 }
55 else {
56 for (const child of node.children) {
57 if (child.type === 'element')
58 applyConditionalFlag(child)
59 }
60 }
61 },
62 }
63 }
64
64 lines TYPESCRIPT