From 6380df9c82ffa53d582c52561c20800cce438cc2 Mon Sep 17 00:00:00 2001 From: _Kerman Date: Wed, 29 Jan 2025 11:06:16 +0800 Subject: [PATCH 1/6] perf: use Shiki shorthand --- packages/slidev/node/setups/shiki.ts | 47 ++++- .../slidev/node/syntax/markdown-it/index.ts | 4 +- .../syntax/markdown-it/markdown-it-shiki.ts | 4 +- .../node/syntax/transform/magic-move.ts | 17 +- packages/types/src/options.ts | 4 +- packages/types/src/setups.ts | 5 +- pnpm-lock.yaml | 197 +++++++++--------- pnpm-workspace.yaml | 14 +- 8 files changed, 166 insertions(+), 126 deletions(-) diff --git a/packages/slidev/node/setups/shiki.ts b/packages/slidev/node/setups/shiki.ts index ee1eb2d0ad..ef6afa9d17 100644 --- a/packages/slidev/node/setups/shiki.ts +++ b/packages/slidev/node/setups/shiki.ts @@ -1,13 +1,16 @@ import type { MarkdownItShikiOptions } from '@shikijs/markdown-it' import type { ShikiSetup } from '@slidev/types' -import type { Highlighter } from 'shiki' +import type { LanguageInput, ShorthandsBundle } from 'shiki/core' import fs from 'node:fs/promises' -import { bundledLanguages, createHighlighter } from 'shiki' +import { red } from 'kolorist' +import { bundledLanguages, bundledThemes } from 'shiki/bundle/full' +import { createdBundledHighlighter, createSingletonShorthands } from 'shiki/core' +import { createJavaScriptRegexEngine } from 'shiki/engine/javascript' import { loadSetups } from './load' let cachedRoots: string[] | undefined let cachedShiki: { - shiki: Highlighter + shiki: ShorthandsBundle shikiOptions: MarkdownItShikiOptions } | undefined @@ -15,7 +18,6 @@ export default async function setupShiki(roots: string[]) { // Here we use shallow equality because when server is restarted, the roots will be different object. if (cachedRoots === roots) return cachedShiki! - cachedShiki?.shiki.dispose() const options = await loadSetups( roots, @@ -29,6 +31,34 @@ export default async function setupShiki(roots: string[]) { }], ) const mergedOptions = Object.assign({}, ...options) + const mergedLanguages: Record = bundledLanguages + for (const option of options) { + const langs = option?.langs + if (Array.isArray(langs)) { + for (const lang of langs.flat()) { + if (typeof lang === 'function') { + console.error(red('[slidev] `langs` option in shiki setup cannot be array containing functions. Please use `{ name: loaderFunction }` format instead.')) + } + else if (typeof lang === 'string') { + // Shiki's built-in languages + // In Node environment, they can be loaded on demand + // So all languages are available + // The language names are only used in the browser environment + } + else { + mergedLanguages[lang.name] = lang + for (const alias of lang.aliases || []) + mergedLanguages[alias] = lang + } + } + } + else if (typeof option?.langs === 'object') { + Object.assign(mergedLanguages, option.langs) + } + else { + console.error(red('[slidev] Invalid langs option in shiki setup:'), langs) + } + } if ('theme' in mergedOptions && 'themes' in mergedOptions) delete mergedOptions.theme @@ -50,11 +80,12 @@ export default async function setupShiki(roots: string[]) { if (mergedOptions.themes) mergedOptions.defaultColor = false - const shiki = await createHighlighter({ - ...mergedOptions, - langs: mergedOptions.langs ?? Object.keys(bundledLanguages), - themes: 'themes' in mergedOptions ? Object.values(mergedOptions.themes) : [mergedOptions.theme], + const createHighlighter = createdBundledHighlighter({ + langs: mergedLanguages, + themes: bundledThemes, + engine: createJavaScriptRegexEngine, }) + const shiki = createSingletonShorthands(createHighlighter) cachedRoots = roots return cachedShiki = { diff --git a/packages/slidev/node/syntax/markdown-it/index.ts b/packages/slidev/node/syntax/markdown-it/index.ts index cb33ebfa72..9a55594535 100644 --- a/packages/slidev/node/syntax/markdown-it/index.ts +++ b/packages/slidev/node/syntax/markdown-it/index.ts @@ -1,6 +1,6 @@ import type { ResolvedSlidevOptions } from '@slidev/types' import type MagicString from 'magic-string' -import type MarkdownIt from 'markdown-it' +import type { MarkdownItAsync } from 'markdown-it-async' import { taskLists as MarkdownItTaskList } from '@hedgedoc/markdown-it-plugins' // @ts-expect-error missing types import MarkdownItFootnote from 'markdown-it-footnote' @@ -12,7 +12,7 @@ import MarkdownItLink from './markdown-it-link' import MarkdownItShiki from './markdown-it-shiki' import MarkdownItVDrag from './markdown-it-v-drag' -export async function useMarkdownItPlugins(md: MarkdownIt, options: ResolvedSlidevOptions, markdownTransformMap: Map) { +export async function useMarkdownItPlugins(md: MarkdownItAsync, options: ResolvedSlidevOptions, markdownTransformMap: Map) { const { roots, data: { features, config } } = options if (config.highlighter === 'shiki') { diff --git a/packages/slidev/node/syntax/markdown-it/markdown-it-shiki.ts b/packages/slidev/node/syntax/markdown-it/markdown-it-shiki.ts index 1cf530e870..874546c941 100644 --- a/packages/slidev/node/syntax/markdown-it/markdown-it-shiki.ts +++ b/packages/slidev/node/syntax/markdown-it/markdown-it-shiki.ts @@ -1,7 +1,7 @@ import type { ResolvedSlidevOptions } from '@slidev/types' import type { ShikiTransformer } from 'shiki' import { isTruthy } from '@antfu/utils' -import { fromHighlighter } from '@shikijs/markdown-it/core' +import { fromAsyncCodeToHtml } from '@shikijs/markdown-it/async' import { escapeVueInCode } from '../transform/utils' export default async function MarkdownItShiki({ data: { config }, mode, utils }: ResolvedSlidevOptions) { @@ -27,7 +27,7 @@ export default async function MarkdownItShiki({ data: { config }, mode, utils }: } satisfies ShikiTransformer, ].filter(isTruthy) as ShikiTransformer[] - return fromHighlighter(utils.shiki, { + return fromAsyncCodeToHtml(utils.shiki.codeToHtml, { ...utils.shikiOptions, transformers, }) diff --git a/packages/slidev/node/syntax/transform/magic-move.ts b/packages/slidev/node/syntax/transform/magic-move.ts index 720546aefa..c321c164d9 100644 --- a/packages/slidev/node/syntax/transform/magic-move.ts +++ b/packages/slidev/node/syntax/transform/magic-move.ts @@ -1,6 +1,6 @@ import type { MarkdownTransformContext } from '@slidev/types' import lz from 'lz-string' -import { codeToKeyedTokens } from 'shiki-magic-move/core' +import { toKeyedTokens } from 'shiki-magic-move/core' import { reCodeBlock } from './code-wrapper' import { normalizeRangeStr } from './utils' @@ -14,6 +14,7 @@ function parseLineNumbersOption(options: string) { * Transform magic-move code blocks */ export function transformMagicMove(ctx: MarkdownTransformContext) { + const { codeToTokens } = ctx.options.utils.shiki ctx.s.replace( reMagicMoveBlock, (full, options = '{}', _attrs = '', body: string) => { @@ -25,13 +26,17 @@ export function transformMagicMove(ctx: MarkdownTransformContext) { const defaultLineNumbers = parseLineNumbersOption(options) ?? ctx.options.data.config.lineNumbers const ranges = matches.map(i => normalizeRangeStr(i[2])) - const steps = matches.map((i) => { + const steps = Promise.all(matches.map(async (i) => { + const lang = i[1] const lineNumbers = parseLineNumbersOption(i[3]) ?? defaultLineNumbers - return codeToKeyedTokens(ctx.options.utils.shiki, i[5].trimEnd(), { + const code = i[5].trimEnd() + const options = { ...ctx.options.utils.shikiOptions, - lang: i[1] as any, - }, lineNumbers) - }) + lang, + } + const { tokens } = await codeToTokens(code, options) + return toKeyedTokens(code, tokens, JSON.stringify([lang, 'themes' in options ? options.themes : options.theme]), lineNumbers) + })) const compressed = lz.compressToBase64(JSON.stringify(steps)) return `` }, diff --git a/packages/types/src/options.ts b/packages/types/src/options.ts index ec27d6cc40..66f514953f 100644 --- a/packages/types/src/options.ts +++ b/packages/types/src/options.ts @@ -1,5 +1,5 @@ import type { MarkdownItShikiOptions } from '@shikijs/markdown-it/index.mjs' -import type { HighlighterGeneric } from 'shiki/types.mjs' +import type { ShorthandsBundle } from 'shiki/core' import type { SlidevData } from './types' export interface RootsInfo { @@ -51,7 +51,7 @@ export interface ResolvedSlidevOptions extends RootsInfo, SlidevEntryOptions { } export interface ResolvedSlidevUtils { - shiki: HighlighterGeneric + shiki: ShorthandsBundle shikiOptions: MarkdownItShikiOptions indexHtml: string define: Record diff --git a/packages/types/src/setups.ts b/packages/types/src/setups.ts index 1afc02e5be..4391a63051 100644 --- a/packages/types/src/setups.ts +++ b/packages/types/src/setups.ts @@ -2,7 +2,7 @@ import type { Awaitable } from '@antfu/utils' import type { KatexOptions } from 'katex' import type { MermaidConfig } from 'mermaid' import type * as monaco from 'monaco-editor' -import type { BuiltinLanguage, BuiltinTheme, CodeOptionsMeta, CodeOptionsThemes, CodeToHastOptionsCommon, Highlighter, LanguageInput } from 'shiki' +import type { BuiltinLanguage, BuiltinTheme, CodeOptionsMeta, CodeOptionsThemes, CodeToHastOptionsCommon, LanguageInput, LanguageRegistration, MaybeArray } from 'shiki' import type { VitePluginConfig as UnoCssConfig } from 'unocss/vite' import type { App, ComputedRef, Ref } from 'vue' import type { Router, RouteRecordRaw } from 'vue-router' @@ -57,8 +57,7 @@ export type ShikiSetupReturn = & CodeOptionsThemes & CodeOptionsMeta & { - setup: (highlighter: Highlighter) => Awaitable - langs: (LanguageInput | BuiltinLanguage)[] + langs: (MaybeArray | BuiltinLanguage)[] | Record } > diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f3a9309054..017b6189a9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -40,20 +40,20 @@ catalogs: specifier: ^4.0.0 version: 4.0.0 '@shikijs/engine-javascript': - specifier: ^2.0.0 - version: 2.0.0 + specifier: ^2.1.0 + version: 2.1.0 '@shikijs/markdown-it': - specifier: ^2.0.0 - version: 2.0.0 + specifier: ^2.1.0 + version: 2.1.0 '@shikijs/monaco': - specifier: ^2.0.0 - version: 2.0.0 + specifier: ^2.1.0 + version: 2.1.0 '@shikijs/twoslash': - specifier: ^2.0.0 - version: 2.0.0 + specifier: ^2.1.0 + version: 2.1.0 '@shikijs/vitepress-twoslash': - specifier: ^2.0.0 - version: 2.0.0 + specifier: ^2.1.0 + version: 2.1.0 '@slidev/rough-notation': specifier: ^0.1.0 version: 0.1.0 @@ -319,11 +319,11 @@ catalogs: specifier: ^7.6.3 version: 7.6.3 shiki: - specifier: ^2.0.0 - version: 2.0.0 + specifier: ^2.1.0 + version: 2.1.0 shiki-magic-move: - specifier: ^0.5.2 - version: 0.5.2 + specifier: ^1.0.0 + version: 1.0.0 simple-git-hooks: specifier: ^2.11.1 version: 2.11.1 @@ -439,7 +439,7 @@ importers: version: 8.1.0 '@shikijs/markdown-it': specifier: 'catalog:' - version: 2.0.0 + version: 2.1.0 '@slidev/cli': specifier: workspace:* version: link:packages/slidev @@ -532,7 +532,7 @@ importers: version: 6.0.1 shiki: specifier: 'catalog:' - version: 2.0.0 + version: 2.1.0 simple-git-hooks: specifier: 'catalog:' version: 2.11.1 @@ -662,7 +662,7 @@ importers: version: 2.2.297 '@shikijs/vitepress-twoslash': specifier: 'catalog:' - version: 2.0.0(@nuxt/kit@3.13.0(rollup@4.27.4))(typescript@5.7.3) + version: 2.1.0(@nuxt/kit@3.13.0(rollup@4.27.4))(typescript@5.7.3) '@slidev/client': specifier: workspace:* version: link:../packages/client @@ -695,7 +695,7 @@ importers: version: 14.1.0 shiki: specifier: 'catalog:' - version: 2.0.0 + version: 2.1.0 typescript: specifier: ^5.7.3 version: 5.7.3 @@ -734,13 +734,13 @@ importers: version: 1.2.2 '@shikijs/engine-javascript': specifier: 'catalog:' - version: 2.0.0 + version: 2.1.0 '@shikijs/monaco': specifier: 'catalog:' - version: 2.0.0 + version: 2.1.0 '@shikijs/vitepress-twoslash': specifier: 'catalog:' - version: 2.0.0(@nuxt/kit@3.13.0(rollup@4.27.4))(typescript@5.7.3) + version: 2.1.0(@nuxt/kit@3.13.0(rollup@4.27.4))(typescript@5.7.3) '@slidev/parser': specifier: workspace:* version: link:../parser @@ -806,10 +806,10 @@ importers: version: 5.6.2 shiki: specifier: 'catalog:' - version: 2.0.0 + version: 2.1.0 shiki-magic-move: specifier: 'catalog:' - version: 0.5.2(shiki@2.0.0)(vue@3.5.13(typescript@5.7.3)) + version: 1.0.0(shiki@2.1.0)(vue@3.5.13(typescript@5.7.3)) typescript: specifier: ^5.7.3 version: 5.7.3 @@ -891,13 +891,13 @@ importers: version: 4.0.0 '@shikijs/markdown-it': specifier: 'catalog:' - version: 2.0.0 + version: 2.1.0 '@shikijs/twoslash': specifier: 'catalog:' - version: 2.0.0(typescript@5.7.3) + version: 2.1.0(typescript@5.7.3) '@shikijs/vitepress-twoslash': specifier: 'catalog:' - version: 2.0.0(@nuxt/kit@3.13.0(rollup@4.27.4))(typescript@5.7.3) + version: 2.1.0(@nuxt/kit@3.13.0(rollup@4.27.4))(typescript@5.7.3) '@slidev/client': specifier: workspace:* version: link:../client @@ -1026,10 +1026,10 @@ importers: version: 7.6.3 shiki: specifier: 'catalog:' - version: 2.0.0 + version: 2.1.0 shiki-magic-move: specifier: 'catalog:' - version: 0.5.2(shiki@2.0.0)(vue@3.5.13(typescript@5.7.3)) + version: 1.0.0(shiki@2.1.0)(vue@3.5.13(typescript@5.7.3)) sirv: specifier: 'catalog:' version: 3.0.0 @@ -1102,7 +1102,7 @@ importers: version: 8.1.0 '@shikijs/markdown-it': specifier: 'catalog:' - version: 2.0.0 + version: 2.1.0 '@vitejs/plugin-vue': specifier: 'catalog:' version: 5.2.1(vite@6.0.8(@types/node@22.10.7)(jiti@2.4.2)(tsx@4.19.1)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3)) @@ -1120,7 +1120,7 @@ importers: version: 0.51.0 shiki: specifier: 'catalog:' - version: 2.0.0 + version: 2.1.0 unocss: specifier: 'catalog:' version: 65.4.2(postcss@8.4.49)(rollup@4.27.4)(vite@6.0.8(@types/node@22.10.7)(jiti@2.4.2)(tsx@4.19.1)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3)) @@ -2175,8 +2175,8 @@ packages: '@shikijs/core@1.26.1': resolution: {integrity: sha512-yeo7sG+WZQblKPclUOKRPwkv1PyoHYkJ4gP9DzhFJbTdueKR7wYTI1vfF/bFi1NTgc545yG/DzvVhZgueVOXMA==} - '@shikijs/core@2.0.0': - resolution: {integrity: sha512-BXodyV73f46j8wcwjP5xn7TQ6Ts3puE65lDREfN+DikZWW3/clDduoopGwQi4F7T9agar41G24BLtH3HUT64KQ==} + '@shikijs/core@2.1.0': + resolution: {integrity: sha512-v795KDmvs+4oV0XD05YLzfDMe9ISBgNjtFxP4PAEv5DqyeghO1/TwDqs9ca5/E6fuO95IcAcWqR6cCX9TnqLZA==} '@shikijs/engine-javascript@1.23.1': resolution: {integrity: sha512-i/LdEwT5k3FVu07SiApRFwRcSJs5QM9+tod5vYCPig1Ywi8GR30zcujbxGQFJHwYD7A5BUqagi8o5KS+LEVgBg==} @@ -2184,8 +2184,8 @@ packages: '@shikijs/engine-javascript@1.26.1': resolution: {integrity: sha512-CRhA0b8CaSLxS0E9A4Bzcb3LKBNpykfo9F85ozlNyArxjo2NkijtiwrJZ6eHa+NT5I9Kox2IXVdjUsP4dilsmw==} - '@shikijs/engine-javascript@2.0.0': - resolution: {integrity: sha512-ZpnBGCRLk6cjvtH+G6ljX6ajcErahx65F4IAm+9rGepYRvD3/jj6taSW8jevb7umzFxTUPXZxytf+ZBx/c5rVQ==} + '@shikijs/engine-javascript@2.1.0': + resolution: {integrity: sha512-cgIUdAliOsoaa0rJz/z+jvhrpRd+fVAoixVFEVxUq5FA+tHgBZAIfVJSgJNVRj2hs/wZ1+4hMe82eKAThVh0nQ==} '@shikijs/engine-oniguruma@1.23.1': resolution: {integrity: sha512-KQ+lgeJJ5m2ISbUZudLR1qHeH3MnSs2mjFg7bnencgs5jDVPeJ2NVDJ3N5ZHbcTsOIh0qIueyAJnwg7lg7kwXQ==} @@ -2193,32 +2193,37 @@ packages: '@shikijs/engine-oniguruma@1.26.1': resolution: {integrity: sha512-F5XuxN1HljLuvfXv7d+mlTkV7XukC1cawdtOo+7pKgPD83CAB1Sf8uHqP3PK0u7njFH0ZhoXE1r+0JzEgAQ+kg==} - '@shikijs/engine-oniguruma@2.0.0': - resolution: {integrity: sha512-X6LdTRXoT37uE/9Y6j7oNtWMMFR6cVrlsHAoQG3srhYcdcrmBm33FdfRRfWeCVlZRAeCHVuWaFmYBWeCTWVN+A==} + '@shikijs/engine-oniguruma@2.1.0': + resolution: {integrity: sha512-Ujik33wEDqgqY2WpjRDUBECGcKPv3eGGkoXPujIXvokLaRmGky8NisSk8lHUGeSFxo/Cz5sgFej9sJmA9yeepg==} '@shikijs/langs@1.26.1': resolution: {integrity: sha512-oz/TQiIqZejEIZbGtn68hbJijAOTtYH4TMMSWkWYozwqdpKR3EXgILneQy26WItmJjp3xVspHdiUxUCws4gtuw==} - '@shikijs/langs@2.0.0': - resolution: {integrity: sha512-xelmNcbbIiX3BO446OgsJcugf5tF9u+4N7V6Wws9XjZoe3qCE0dYtfkHXZiVDdciemI/1QnFeTo+AjPw2fD42w==} + '@shikijs/langs@2.1.0': + resolution: {integrity: sha512-Jn0gS4rPgerMDPj1ydjgFzZr5fAIoMYz4k7ZT3LJxWWBWA6lokK0pumUwVtb+MzXtlpjxOaQejLprmLbvMZyww==} - '@shikijs/markdown-it@2.0.0': - resolution: {integrity: sha512-SPSqipr1GSvno7marwOCiW/S2ZQO8qR/9MKi2nYR6lF26LMiRqQzcjxkScN4Nip9y2Siudpu/5ggsYfTfiKKiA==} + '@shikijs/markdown-it@2.1.0': + resolution: {integrity: sha512-Z+OIx0XOfpsETAgNoBjoUlZehSkO+K31GW5RE8l9cc8WxcQdRldXLD+3oavfcA4zoetZJaVUzl60X4kf53bvdA==} + peerDependencies: + markdown-it-async: ^1.1.1 + peerDependenciesMeta: + markdown-it-async: + optional: true - '@shikijs/monaco@2.0.0': - resolution: {integrity: sha512-Sef+kVXaMFk9buVedY5RtEMP9BN2QGBtl8gr/l+6loEWKyB4EukyQaC/Fr17bNv5gF/FvH3gabf9EvVfpfbEJQ==} + '@shikijs/monaco@2.1.0': + resolution: {integrity: sha512-+FEkD0Ey+AlmqMfgA3Vjw6Zf8TsT5KVDzt28qtg02IqoIUdXKslOmyoFjtzSOYpDFLIYmKz02ajEk4vVCNdXww==} '@shikijs/themes@1.26.1': resolution: {integrity: sha512-JDxVn+z+wgLCiUhBGx2OQrLCkKZQGzNH3nAxFir4PjUcYiyD8Jdms9izyxIogYmSwmoPTatFTdzyrRKbKlSfPA==} - '@shikijs/themes@2.0.0': - resolution: {integrity: sha512-2v7PjBlTEcYhj96/WW4t4VhMmIR/0DhuKqZzWcPFG+w2RG3EaIiGfQYf9w+NvFYZ8uF7ianO8vxrjIVpDKnglw==} + '@shikijs/themes@2.1.0': + resolution: {integrity: sha512-oS2mU6+bz+8TKutsjBxBA7Z3vrQk21RCmADLpnu8cy3tZD6Rw0FKqDyXNtwX52BuIDKHxZNmRlTdG3vtcYv3NQ==} '@shikijs/transformers@1.23.1': resolution: {integrity: sha512-yQ2Cn0M9i46p30KwbyIzLvKDk+dQNU+lj88RGO0XEj54Hn4Cof1bZoDb9xBRWxFE4R8nmK63w7oHnJwvOtt0NQ==} - '@shikijs/twoslash@2.0.0': - resolution: {integrity: sha512-yb47A31IqQya1m2m3BA186V/L2cRjcXbwu1AtYJgLaDgdR8vNf0wGGc9rPpdaRk6Zc2kvWB1GTIn6e5DkhJrvg==} + '@shikijs/twoslash@2.1.0': + resolution: {integrity: sha512-tgZEk78/g1ceC/mS3xA50aIc2rArl+oiphZEdAXaoioLVNebDChhV93NzcXu4NAq4pCogfBbD5HV8qO38+fQyQ==} '@shikijs/types@1.23.1': resolution: {integrity: sha512-98A5hGyEhzzAgQh2dAeHKrWW4HfCMeoFER2z16p5eJ+vmPeF6lZ/elEne6/UCU551F/WqkopqRsr1l2Yu6+A0g==} @@ -2226,11 +2231,11 @@ packages: '@shikijs/types@1.26.1': resolution: {integrity: sha512-d4B00TKKAMaHuFYgRf3L0gwtvqpW4hVdVwKcZYbBfAAQXspgkbWqnFfuFl3MDH6gLbsubOcr+prcnsqah3ny7Q==} - '@shikijs/types@2.0.0': - resolution: {integrity: sha512-2gQ9V3NoGE4R1d0pGnsNF0PLStBu7GsJdJdS6H/YbzuTRVjv6cado9slh3sG4KMZBhJPFh7EC8+iIKuyHfNDvA==} + '@shikijs/types@2.1.0': + resolution: {integrity: sha512-OFOdHA6VEVbiQvepJ8yqicC6VmBrKxFFhM2EsHHrZESqLVAXOSeRDiuSYV185lIgp15TVic5vYBYNhTsk1xHLg==} - '@shikijs/vitepress-twoslash@2.0.0': - resolution: {integrity: sha512-riVoDlAqbVID2RSkc6ijab9HbBmltn7ElSndFvOK3T8edEcgH44lF7kammMBL4JOQwFWJ5ezQjfFkU5t5hT9Yg==} + '@shikijs/vitepress-twoslash@2.1.0': + resolution: {integrity: sha512-Z3JdLGMoI/SFmiaFy/eemIMRUnsHAwBKB5f3HhX6yNrVDTFNRfMTpEzVLYkBn3qj9+96mJnJVdbotAswi9QRog==} '@shikijs/vscode-textmate@10.0.1': resolution: {integrity: sha512-fTIQwLF+Qhuws31iw7Ncl1R3HUDtGwIipiJ9iU+UsDUwMhegFcQKQHd51nZjb7CArq0MvON8rbgCGQYWHUKAdg==} @@ -3679,8 +3684,8 @@ packages: devlop@1.1.0: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} - diff-match-patch-es@0.1.1: - resolution: {integrity: sha512-+wE0HYKRuRdfsnpEFh41kTd0GlYFSDQacz2bQ4dwMDvYGtofqtYdJ6Gl4ZOgUPqPi7v8LSqMY0+/OedmIPHBZw==} + diff-match-patch-es@1.0.1: + resolution: {integrity: sha512-KhSofrZDERg/NE6Nd+TK53knp2qz0o2Ix8rhkXd3Chfm7Wlo58Eq/juNmkyS6bS+3xS26L3Pstz3BdY/q+e9UQ==} dns-packet@5.6.1: resolution: {integrity: sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==} @@ -5291,8 +5296,8 @@ packages: oniguruma-to-es@0.4.1: resolution: {integrity: sha512-rNcEohFz095QKGRovP/yqPIKc+nP+Sjs4YTHMv33nMePGKrq/r2eu9Yh4646M5XluGJsUnmwoXuiXE69KDs+fQ==} - oniguruma-to-es@2.2.0: - resolution: {integrity: sha512-EEsso27ri0sf+t4uRFEj5C5gvXQj0d0w1Y2qq06b+hDLBnvzO1rWTwEW4C7ytan6nhg4WPwE26eLoiPhHUbvKg==} + oniguruma-to-es@2.3.0: + resolution: {integrity: sha512-bwALDxriqfKGfUufKGGepCzu9x7nJQuoRoAFp4AnwehhC2crqrDIAP/uN2qdlsAvSMpeRC3+Yzhqc7hLmle5+g==} open@10.1.0: resolution: {integrity: sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==} @@ -5838,11 +5843,11 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - shiki-magic-move@0.5.2: - resolution: {integrity: sha512-Y5EHPD+IPiUUFFMEKu6RE8wELsKp8CYgf420Z+EXVljOvyBakiR9rjt/1Cm0VcSr9rkyQANw6fTE1PqcNOnAGA==} + shiki-magic-move@1.0.0: + resolution: {integrity: sha512-CU1mSLc9H3AV9SuVon3AAhesdi5WZh4GC3SR+Q0I4ilg71q0/OKnOWu0bT8Kgt5w6cJKYkEcQKNEHKCaqSLTIQ==} peerDependencies: react: ^18.2.0 || ^19.0.0 - shiki: ^1.1.6 + shiki: ^2.0.0 solid-js: ^1.9.1 svelte: ^5.0.0-0 vue: ^3.4.0 @@ -5864,8 +5869,8 @@ packages: shiki@1.26.1: resolution: {integrity: sha512-Gqg6DSTk3wYqaZ5OaYtzjcdxcBvX5kCy24yvRJEgjT5U+WHlmqCThLuBUx0juyxQBi+6ug53IGeuQS07DWwpcw==} - shiki@2.0.0: - resolution: {integrity: sha512-cU0KHpb2zOMwVrSeJeYTcKNGzSHM+X/chH5KTtsZLg5QCsFUwclJervFoHQPz1Ap+O+94FOsv7mh/+Bmv3iQPA==} + shiki@2.1.0: + resolution: {integrity: sha512-yvKPdNGLXZv7WC4bl7JBbU3CEcUxnBanvMez8MG3gZXKpClGL4bHqFyLhTx+2zUvbjClUANs/S22HXb7aeOgmA==} side-channel@1.0.6: resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} @@ -7862,11 +7867,11 @@ snapshots: '@types/hast': 3.0.4 hast-util-to-html: 9.0.4 - '@shikijs/core@2.0.0': + '@shikijs/core@2.1.0': dependencies: - '@shikijs/engine-javascript': 2.0.0 - '@shikijs/engine-oniguruma': 2.0.0 - '@shikijs/types': 2.0.0 + '@shikijs/engine-javascript': 2.1.0 + '@shikijs/engine-oniguruma': 2.1.0 + '@shikijs/types': 2.1.0 '@shikijs/vscode-textmate': 10.0.1 '@types/hast': 3.0.4 hast-util-to-html: 9.0.4 @@ -7883,11 +7888,11 @@ snapshots: '@shikijs/vscode-textmate': 10.0.1 oniguruma-to-es: 0.10.0 - '@shikijs/engine-javascript@2.0.0': + '@shikijs/engine-javascript@2.1.0': dependencies: - '@shikijs/types': 2.0.0 + '@shikijs/types': 2.1.0 '@shikijs/vscode-textmate': 10.0.1 - oniguruma-to-es: 2.2.0 + oniguruma-to-es: 2.3.0 '@shikijs/engine-oniguruma@1.23.1': dependencies: @@ -7899,46 +7904,46 @@ snapshots: '@shikijs/types': 1.26.1 '@shikijs/vscode-textmate': 10.0.1 - '@shikijs/engine-oniguruma@2.0.0': + '@shikijs/engine-oniguruma@2.1.0': dependencies: - '@shikijs/types': 2.0.0 + '@shikijs/types': 2.1.0 '@shikijs/vscode-textmate': 10.0.1 '@shikijs/langs@1.26.1': dependencies: '@shikijs/types': 1.26.1 - '@shikijs/langs@2.0.0': + '@shikijs/langs@2.1.0': dependencies: - '@shikijs/types': 2.0.0 + '@shikijs/types': 2.1.0 - '@shikijs/markdown-it@2.0.0': + '@shikijs/markdown-it@2.1.0': dependencies: markdown-it: 14.1.0 - shiki: 2.0.0 + shiki: 2.1.0 - '@shikijs/monaco@2.0.0': + '@shikijs/monaco@2.1.0': dependencies: - '@shikijs/core': 2.0.0 - '@shikijs/types': 2.0.0 + '@shikijs/core': 2.1.0 + '@shikijs/types': 2.1.0 '@shikijs/vscode-textmate': 10.0.1 '@shikijs/themes@1.26.1': dependencies: '@shikijs/types': 1.26.1 - '@shikijs/themes@2.0.0': + '@shikijs/themes@2.1.0': dependencies: - '@shikijs/types': 2.0.0 + '@shikijs/types': 2.1.0 '@shikijs/transformers@1.23.1': dependencies: shiki: 1.23.1 - '@shikijs/twoslash@2.0.0(typescript@5.7.3)': + '@shikijs/twoslash@2.1.0(typescript@5.7.3)': dependencies: - '@shikijs/core': 2.0.0 - '@shikijs/types': 2.0.0 + '@shikijs/core': 2.1.0 + '@shikijs/types': 2.1.0 twoslash: 0.2.12(typescript@5.7.3) transitivePeerDependencies: - supports-color @@ -7954,19 +7959,19 @@ snapshots: '@shikijs/vscode-textmate': 10.0.1 '@types/hast': 3.0.4 - '@shikijs/types@2.0.0': + '@shikijs/types@2.1.0': dependencies: '@shikijs/vscode-textmate': 10.0.1 '@types/hast': 3.0.4 - '@shikijs/vitepress-twoslash@2.0.0(@nuxt/kit@3.13.0(rollup@4.27.4))(typescript@5.7.3)': + '@shikijs/vitepress-twoslash@2.1.0(@nuxt/kit@3.13.0(rollup@4.27.4))(typescript@5.7.3)': dependencies: - '@shikijs/twoslash': 2.0.0(typescript@5.7.3) + '@shikijs/twoslash': 2.1.0(typescript@5.7.3) floating-vue: 5.2.2(@nuxt/kit@3.13.0(rollup@4.27.4))(vue@3.5.13(typescript@5.7.3)) mdast-util-from-markdown: 2.0.2 mdast-util-gfm: 3.0.0 mdast-util-to-hast: 13.2.0 - shiki: 2.0.0 + shiki: 2.1.0 twoslash: 0.2.12(typescript@5.7.3) twoslash-vue: 0.2.12(typescript@5.7.3) vue: 3.5.13(typescript@5.7.3) @@ -9781,7 +9786,7 @@ snapshots: dependencies: dequal: 2.0.3 - diff-match-patch-es@0.1.1: {} + diff-match-patch-es@1.0.1: {} dns-packet@5.6.1: dependencies: @@ -11726,7 +11731,7 @@ snapshots: regex: 5.1.1 regex-recursion: 4.3.0 - oniguruma-to-es@2.2.0: + oniguruma-to-es@2.3.0: dependencies: emoji-regex-xs: 1.0.0 regex: 5.1.1 @@ -12281,12 +12286,12 @@ snapshots: shebang-regex@3.0.0: {} - shiki-magic-move@0.5.2(shiki@2.0.0)(vue@3.5.13(typescript@5.7.3)): + shiki-magic-move@1.0.0(shiki@2.1.0)(vue@3.5.13(typescript@5.7.3)): dependencies: - diff-match-patch-es: 0.1.1 + diff-match-patch-es: 1.0.1 ohash: 1.1.4 optionalDependencies: - shiki: 2.0.0 + shiki: 2.1.0 vue: 3.5.13(typescript@5.7.3) shiki@1.23.1: @@ -12309,14 +12314,14 @@ snapshots: '@shikijs/vscode-textmate': 10.0.1 '@types/hast': 3.0.4 - shiki@2.0.0: + shiki@2.1.0: dependencies: - '@shikijs/core': 2.0.0 - '@shikijs/engine-javascript': 2.0.0 - '@shikijs/engine-oniguruma': 2.0.0 - '@shikijs/langs': 2.0.0 - '@shikijs/themes': 2.0.0 - '@shikijs/types': 2.0.0 + '@shikijs/core': 2.1.0 + '@shikijs/engine-javascript': 2.1.0 + '@shikijs/engine-oniguruma': 2.1.0 + '@shikijs/langs': 2.1.0 + '@shikijs/themes': 2.1.0 + '@shikijs/types': 2.1.0 '@shikijs/vscode-textmate': 10.0.1 '@types/hast': 3.0.4 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 637fac504a..8f5a6188ff 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -15,11 +15,11 @@ catalog: '@iconify-json/svg-spinners': ^1.2.2 '@iconify/json': ^2.2.297 '@lillallol/outline-pdf': ^4.0.0 - '@shikijs/markdown-it': ^2.0.0 - '@shikijs/monaco': ^2.0.0 - '@shikijs/engine-javascript': ^2.0.0 - '@shikijs/twoslash': ^2.0.0 - '@shikijs/vitepress-twoslash': ^2.0.0 + '@shikijs/markdown-it': ^2.1.0 + '@shikijs/monaco': ^2.1.0 + '@shikijs/engine-javascript': ^2.1.0 + '@shikijs/twoslash': ^2.1.0 + '@shikijs/vitepress-twoslash': ^2.1.0 '@slidev/rough-notation': ^0.1.0 '@slidev/theme-default': ^0.25.0 '@slidev/theme-seriph': ^0.25.0 @@ -108,8 +108,8 @@ catalog: resolve-global: ^2.0.0 rimraf: ^6.0.1 semver: ^7.6.3 - shiki: ^2.0.0 - shiki-magic-move: ^0.5.2 + shiki: ^2.1.0 + shiki-magic-move: ^1.0.0 simple-git-hooks: ^2.11.1 sirv: ^3.0.0 source-map-js: ^1.2.1 From 72dc7622b19254dcd4e2457a586bea936b8fe093 Mon Sep 17 00:00:00 2001 From: _Kerman Date: Wed, 29 Jan 2025 11:49:11 +0800 Subject: [PATCH 2/6] fix --- packages/slidev/node/setups/shiki.ts | 30 +++++++++++++++++---------- packages/slidev/node/virtual/shiki.ts | 2 +- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/packages/slidev/node/setups/shiki.ts b/packages/slidev/node/setups/shiki.ts index ef6afa9d17..3583fbce88 100644 --- a/packages/slidev/node/setups/shiki.ts +++ b/packages/slidev/node/setups/shiki.ts @@ -30,8 +30,9 @@ export default async function setupShiki(roots: string[]) { }, }], ) - const mergedOptions = Object.assign({}, ...options) - const mergedLanguages: Record = bundledLanguages + + const browserLanguages: any[] = [] + const nodeLanguages: Record = bundledLanguages for (const option of options) { const langs = option?.langs if (Array.isArray(langs)) { @@ -40,26 +41,33 @@ export default async function setupShiki(roots: string[]) { console.error(red('[slidev] `langs` option in shiki setup cannot be array containing functions. Please use `{ name: loaderFunction }` format instead.')) } else if (typeof lang === 'string') { - // Shiki's built-in languages - // In Node environment, they can be loaded on demand - // So all languages are available - // The language names are only used in the browser environment + // Name of a Shiki built-in language + // In Node environment, they can be loaded on demand without overhead, so all built-in languages are available. + // Only need to include them explicitly in browser environment. + browserLanguages.push(lang) } - else { - mergedLanguages[lang.name] = lang + else if (lang.name) { + // Custom grammar object + browserLanguages.push(lang) + nodeLanguages[lang.name] = lang for (const alias of lang.aliases || []) - mergedLanguages[alias] = lang + nodeLanguages[alias] = lang } } } else if (typeof option?.langs === 'object') { - Object.assign(mergedLanguages, option.langs) + // Map from name to loader or grammar object + Object.assign(nodeLanguages, option.langs) + browserLanguages.push(...Object.values(option.langs).filter(lang => lang?.name)) } else { console.error(red('[slidev] Invalid langs option in shiki setup:'), langs) } } + const mergedOptions = Object.assign({}, ...options) + mergedOptions.langs = browserLanguages + if ('theme' in mergedOptions && 'themes' in mergedOptions) delete mergedOptions.theme @@ -81,7 +89,7 @@ export default async function setupShiki(roots: string[]) { mergedOptions.defaultColor = false const createHighlighter = createdBundledHighlighter({ - langs: mergedLanguages, + langs: nodeLanguages, themes: bundledThemes, engine: createJavaScriptRegexEngine, }) diff --git a/packages/slidev/node/virtual/shiki.ts b/packages/slidev/node/virtual/shiki.ts index 413003f837..3e8fb602fe 100644 --- a/packages/slidev/node/virtual/shiki.ts +++ b/packages/slidev/node/virtual/shiki.ts @@ -7,7 +7,7 @@ export const templateShiki: VirtualModuleTemplate = { id: '/@slidev/shiki', getContent: async ({ utils }) => { const options = utils.shikiOptions - const langs = await resolveLangs(options.langs || ['markdown', 'vue', 'javascript', 'typescript', 'html', 'css']) + const langs = await resolveLangs(options.langs?.length ? options.langs : ['markdown', 'vue', 'javascript', 'typescript', 'html', 'css']) const resolvedThemeOptions = 'themes' in options ? { themes: Object.fromEntries(await Promise.all(Object.entries(options.themes) From 3db064734af8aa45209b741c04ea1a84a4d8d25c Mon Sep 17 00:00:00 2001 From: _Kerman Date: Thu, 30 Jan 2025 12:13:09 +0800 Subject: [PATCH 3/6] fix --- .../node/syntax/transform/magic-move.ts | 58 +++++++++++-------- test/transform-magic-move.test.ts | 4 +- 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/packages/slidev/node/syntax/transform/magic-move.ts b/packages/slidev/node/syntax/transform/magic-move.ts index c321c164d9..d51cb62d0a 100644 --- a/packages/slidev/node/syntax/transform/magic-move.ts +++ b/packages/slidev/node/syntax/transform/magic-move.ts @@ -13,32 +13,44 @@ function parseLineNumbersOption(options: string) { /** * Transform magic-move code blocks */ -export function transformMagicMove(ctx: MarkdownTransformContext) { +export async function transformMagicMove(ctx: MarkdownTransformContext) { const { codeToTokens } = ctx.options.utils.shiki + const replacements: [number, number, Promise][] = [] + ctx.s.replace( reMagicMoveBlock, - (full, options = '{}', _attrs = '', body: string) => { - const matches = Array.from(body.matchAll(reCodeBlock)) - - if (!matches.length) - throw new Error('Magic Move block must contain at least one code block') - - const defaultLineNumbers = parseLineNumbersOption(options) ?? ctx.options.data.config.lineNumbers - - const ranges = matches.map(i => normalizeRangeStr(i[2])) - const steps = Promise.all(matches.map(async (i) => { - const lang = i[1] - const lineNumbers = parseLineNumbersOption(i[3]) ?? defaultLineNumbers - const code = i[5].trimEnd() - const options = { - ...ctx.options.utils.shikiOptions, - lang, - } - const { tokens } = await codeToTokens(code, options) - return toKeyedTokens(code, tokens, JSON.stringify([lang, 'themes' in options ? options.themes : options.theme]), lineNumbers) - })) - const compressed = lz.compressToBase64(JSON.stringify(steps)) - return `` + (full, options = '{}', _attrs = '', body: string, start: number) => { + const end = start + full.length + replacements.push([start, end, worker()]) + return '' + async function worker() { + const matches = Array.from(body.matchAll(reCodeBlock)) + + if (!matches.length) + throw new Error('Magic Move block must contain at least one code block') + + const defaultLineNumbers = parseLineNumbersOption(options) ?? ctx.options.data.config.lineNumbers + + const ranges = matches.map(i => normalizeRangeStr(i[2])) + const steps = await Promise.all(matches.map(async (i) => { + const lang = i[1] + const lineNumbers = parseLineNumbersOption(i[3]) ?? defaultLineNumbers + const code = i[5].trimEnd() + const options = { + ...ctx.options.utils.shikiOptions, + lang, + } + const { tokens } = await codeToTokens(code, options) + return toKeyedTokens(code, tokens, JSON.stringify([lang, 'themes' in options ? options.themes : options.theme]), lineNumbers) + })) + const compressed = lz.compressToBase64(JSON.stringify(steps)) + return `` + } }, ) + + for (const [start, end, content] of replacements) { + // magic-string internally uses `overwrite` instead of `update` in the `replace` method + ctx.s.overwrite(start, end, await content) + } } diff --git a/test/transform-magic-move.test.ts b/test/transform-magic-move.test.ts index d3018b094b..0c199b34db 100644 --- a/test/transform-magic-move.test.ts +++ b/test/transform-magic-move.test.ts @@ -28,7 +28,7 @@ Some text after const ctx = createTransformContext(code, shiki) - transformMagicMove(ctx) + await transformMagicMove(ctx) expect(ctx.s.toString()) .toMatchInlineSnapshot(` @@ -68,7 +68,7 @@ Some text after const ctx = createTransformContext(code, shiki) - transformMagicMove(ctx) + await transformMagicMove(ctx) expect(ctx.s.toString()) .toMatchInlineSnapshot(` From 7189db9c94e8f2e6a2dac3ec7ba2cbb4dad25f2b Mon Sep 17 00:00:00 2001 From: _Kerman Date: Thu, 30 Jan 2025 12:51:44 +0800 Subject: [PATCH 4/6] workaround twoslash --- .../syntax/markdown-it/markdown-it-shiki.ts | 26 +++++++++++++------ packages/types/src/options.ts | 4 +-- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/packages/slidev/node/syntax/markdown-it/markdown-it-shiki.ts b/packages/slidev/node/syntax/markdown-it/markdown-it-shiki.ts index 874546c941..965f01a5e7 100644 --- a/packages/slidev/node/syntax/markdown-it/markdown-it-shiki.ts +++ b/packages/slidev/node/syntax/markdown-it/markdown-it-shiki.ts @@ -4,18 +4,28 @@ import { isTruthy } from '@antfu/utils' import { fromAsyncCodeToHtml } from '@shikijs/markdown-it/async' import { escapeVueInCode } from '../transform/utils' -export default async function MarkdownItShiki({ data: { config }, mode, utils }: ResolvedSlidevOptions) { - const transformers = [ - ...utils.shikiOptions.transformers || [], - (config.twoslash === true || config.twoslash === mode) - && (await import('@shikijs/vitepress-twoslash')).transformerTwoslash({ +export default async function MarkdownItShiki({ data: { config }, mode, utils: { shiki, shikiOptions } }: ResolvedSlidevOptions) { + async function getTwoslashTransformer() { + const [,,{ transformerTwoslash }] = await Promise.all([ + // trigger the shiki to load the langs + shiki.codeToHast('', { lang: 'js', ...shikiOptions }), + shiki.codeToHast('', { lang: 'ts', ...shikiOptions }), + + import('@shikijs/vitepress-twoslash'), + ]) + return transformerTwoslash({ explicitTrigger: true, twoslashOptions: { handbookOptions: { noErrorValidation: true, }, }, - }), + }) + } + + const transformers = [ + ...shikiOptions.transformers || [], + (config.twoslash === true || config.twoslash === mode) && await getTwoslashTransformer(), { pre(pre) { this.addClassToHast(pre, 'slidev-code') @@ -27,8 +37,8 @@ export default async function MarkdownItShiki({ data: { config }, mode, utils }: } satisfies ShikiTransformer, ].filter(isTruthy) as ShikiTransformer[] - return fromAsyncCodeToHtml(utils.shiki.codeToHtml, { - ...utils.shikiOptions, + return fromAsyncCodeToHtml(shiki.codeToHtml, { + ...shikiOptions, transformers, }) } diff --git a/packages/types/src/options.ts b/packages/types/src/options.ts index 02d23407a9..973838863d 100644 --- a/packages/types/src/options.ts +++ b/packages/types/src/options.ts @@ -1,6 +1,6 @@ import type { MarkdownItShikiOptions } from '@shikijs/markdown-it' import type { KatexOptions } from 'katex' -import type { ShorthandsBundle } from 'shiki/core' +import type { CodeOptionsThemes, ShorthandsBundle } from 'shiki/core' import type { SlidevData } from './types' export interface RootsInfo { @@ -58,7 +58,7 @@ export interface ResolvedSlidevOptions extends RootsInfo, SlidevEntryOptions { export interface ResolvedSlidevUtils { shiki: ShorthandsBundle - shikiOptions: MarkdownItShikiOptions + shikiOptions: MarkdownItShikiOptions & CodeOptionsThemes katexOptions: KatexOptions | null indexHtml: string define: Record From 163fa70d8caaed96f613b9664e612729de7197fa Mon Sep 17 00:00:00 2001 From: _Kerman Date: Thu, 30 Jan 2025 12:53:43 +0800 Subject: [PATCH 5/6] Discard changes to pnpm-workspace.yaml --- pnpm-workspace.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 087c344c2c..fd040ae9a9 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -15,9 +15,9 @@ catalog: '@iconify-json/svg-spinners': ^1.2.2 '@iconify/json': ^2.2.300 '@lillallol/outline-pdf': ^4.0.0 + '@shikijs/engine-javascript': ^2.1.0 '@shikijs/markdown-it': ^2.1.0 '@shikijs/monaco': ^2.1.0 - '@shikijs/engine-javascript': ^2.1.0 '@shikijs/twoslash': ^2.1.0 '@shikijs/vitepress-twoslash': ^2.1.0 '@slidev/rough-notation': ^0.1.0 From 00f9ce4eb291e0d6a5e31865b0fcb83bf33391e2 Mon Sep 17 00:00:00 2001 From: _Kerman Date: Thu, 30 Jan 2025 18:01:31 +0800 Subject: [PATCH 6/6] fix --- .../slidev/node/syntax/transform/magic-move.ts | 11 +++++++++-- test/_tutils.ts | 3 ++- test/transform-magic-move.test.ts | 14 ++------------ 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/packages/slidev/node/syntax/transform/magic-move.ts b/packages/slidev/node/syntax/transform/magic-move.ts index d51cb62d0a..ee9ab42c80 100644 --- a/packages/slidev/node/syntax/transform/magic-move.ts +++ b/packages/slidev/node/syntax/transform/magic-move.ts @@ -40,8 +40,15 @@ export async function transformMagicMove(ctx: MarkdownTransformContext) { ...ctx.options.utils.shikiOptions, lang, } - const { tokens } = await codeToTokens(code, options) - return toKeyedTokens(code, tokens, JSON.stringify([lang, 'themes' in options ? options.themes : options.theme]), lineNumbers) + const { tokens, bg, fg, rootStyle, themeName } = await codeToTokens(code, options) + return { + ...toKeyedTokens(code, tokens, JSON.stringify([lang, 'themes' in options ? options.themes : options.theme]), lineNumbers), + bg, + fg, + rootStyle, + themeName, + lang, + } })) const compressed = lz.compressToBase64(JSON.stringify(steps)) return `` diff --git a/test/_tutils.ts b/test/_tutils.ts index 2972466945..c16edc86d4 100644 --- a/test/_tutils.ts +++ b/test/_tutils.ts @@ -1,8 +1,9 @@ import type { MarkdownTransformContext } from '@slidev/types' import path from 'node:path' import MagicString from 'magic-string-stack' +import * as shiki from 'shiki' -export function createTransformContext(code: string, shiki?: any): MarkdownTransformContext { +export function createTransformContext(code: string): MarkdownTransformContext { const s = new MagicString(code) return { s, diff --git a/test/transform-magic-move.test.ts b/test/transform-magic-move.test.ts index 0c199b34db..e0ef9bc20f 100644 --- a/test/transform-magic-move.test.ts +++ b/test/transform-magic-move.test.ts @@ -1,4 +1,3 @@ -import { createHighlighter } from 'shiki' import { expect, it } from 'vitest' import { transformMagicMove } from '../packages/slidev/node/syntax/transform/magic-move' import { createTransformContext } from './_tutils' @@ -21,12 +20,8 @@ let message = 'Hello, Slidev!' Some text after ` - const shiki = await createHighlighter({ - themes: ['nord'], - langs: ['typescript'], - }) - const ctx = createTransformContext(code, shiki) + const ctx = createTransformContext(code) await transformMagicMove(ctx) @@ -61,12 +56,7 @@ console.log('Hello, Angular #2!') Some text after ` - const shiki = await createHighlighter({ - themes: ['nord'], - langs: ['angular-ts'], - }) - - const ctx = createTransformContext(code, shiki) + const ctx = createTransformContext(code) await transformMagicMove(ctx)