hunk.code_window: /**
    * Transform Monaco code block to component
    */
   export function transformHighlighter(md: string) {
     return md.replace(/^```(\w+?)\s*{([\d\w*,\|-]+)}[\s\n]*([\s\S]+?)^```/mg, (full, lang = '', rangeStr: string, code: string) => {
       const ranges = rangeStr.split(/\|/g).map(i => i.trim())
  
hunk.labels: keep keep keep keep replace keep
hunk.after_edit:   return md.replace(/^```(\w+?)\s*{([\d\w*,\|-]+)}\s*({.*?})[\s\n]*([\s\S]+?)^```/mg, (full, lang = '', rangeStr: string, options = '', code: string) => {
  
hunk.file_path: packages/slidev/node/plugins/markdown.ts
hunk.type: replace
file: import Markdown from 'vite-plugin-md'
  import { Plugin } from 'vite'
  import type { ShikiOptions } from '@slidev/types'
  import type MarkdownIt from 'markdown-it'
  import base64 from 'js-base64'
  import { slash } from '@antfu/utils'
  // @ts-expect-error
  import mila from 'markdown-it-link-attributes'
  // @ts-expect-error
  import Katex from 'markdown-it-katex'
  import { ResolvedSlidevOptions, SlidevPluginOptions } from '../options'
  import { loadSetups } from './setupNode'
  import Prism from './markdown-it-prism'
  import Shiki, { resolveShikiOptions } from './markdown-it-shiki'
  
  const DEFAULT_SHIKI_OPTIONS: ShikiOptions = {
    theme: {
      dark: 'min-dark',
      light: 'min-light',
    },
  }
  
  export async function createMarkdownPlugin(
    { data: { config }, roots, mode, entry }: ResolvedSlidevOptions,
    { markdown: mdOptions }: SlidevPluginOptions,
  ): Promise<Plugin> {
    const setups: ((md: MarkdownIt) => void)[] = []
    const entryPath = slash(entry)
  
    if (config.highlighter === 'shiki') {
      const { getHighlighter } = await import('shiki')
      const shikiOptions: ShikiOptions = await loadSetups(roots, 'shiki.ts', {}, DEFAULT_SHIKI_OPTIONS, false)
      const { langs, themes } = resolveShikiOptions(shikiOptions)
      shikiOptions.highlighter = await getHighlighter({ themes, langs })
      setups.push(md => md.use(Shiki, shikiOptions))
    }
    else {
      setups.push(md => md.use(Prism))
    }
  
    return Markdown({
      wrapperClasses: '',
      headEnabled: false,
      frontmatter: false,
      markdownItOptions: {
        quotes: '""\'\'',
        html: true,
        xhtmlOut: true,
        linkify: true,
      },
      markdownItSetup(md) {
        md.use(mila, {
          attrs: {
            target: '_blank',
            rel: 'noopener',
          },
        })
  
        md.use(Katex)
  
        setups.forEach(i => i(md))
      },
      transforms: {
        before(code, id) {
          if (id === entryPath)
            return ''
  
          const monaco = (config.monaco === true || config.monaco === mode)
            ? transformMarkdownMonaco
            : truncateMancoMark
  
          code = transformMermaid(code)
          code = monaco(code)
          code = transformHighlighter(code)
          code = transformPageCSS(code, id)
  
          return code
        },
      },
      ...mdOptions,
    })
  }
  
  export function transformMarkdownMonaco(md: string) {
    // transform monaco
    md = md.replace(/^```(\w+?)\s*{monaco([\w:,-]*)}[\s\n]*([\s\S]+?)^```/mg, (full, lang = 'ts', options: string, code: string) => {
      options = options || ''
      lang = lang.trim()
      const encoded = base64.encode(code, true)
      return `<Monaco :code="'${encoded}'" lang="${lang}" :readonly="${options.includes('readonly')}" />`
    })
  
    return md
  }
  
  export function truncateMancoMark(code: string) {
    return code.replace(/{monaco.*?}/g, '')
  }
  
  /**
   * Transform Monaco code block to component
   */
  export function transformHighlighter(md: string) {
    return md.replace(/^```(\w+?)\s*{([\d\w*,\|-]+)}[\s\n]*([\s\S]+?)^```/mg, (full, lang = '', rangeStr: string, code: string) => {
      const ranges = rangeStr.split(/\|/g).map(i => i.trim())
      return `\n<CodeHighlightController :ranges='${JSON.stringify(ranges)}'>\n\n\`\`\`${lang}\n${code}\n\`\`\`\n\n</CodeHighlightController>`
    })
  }
  
  /**
   * Transform <style> in markdown to scoped style with page selector
   */
  export function transformPageCSS(md: string, id: string) {
    const page = id.match(/(\d+)\.md$/)?.[1]
    if (!page)
      return md
  
    const codeblocks = Array.from(md.matchAll(/^```[\s\S]*?^```/mg))
      .map(m => ([m.index!, m.index! + m[0].length]))
  
    const result = md.replace(
      /(\n<style[^>]*?>)([\s\S]+?)(<\/style>)/g,
      (full, start, css, end) => {
        const index = md.indexOf(full)
        // don't replace `<style>` inside code blocks, #101
        if (index < 0 || codeblocks.some(([s, e]) => s <= index && index <= e))
          return full
        if (!start.includes('scoped'))
          start = start.replace('<style', '<style scoped')
        return `${start}\n.slidev-page-${page}{${css}}${end}`
      },
    )
  
    return result
  }
  
  /**
   * Transform Mermaid code blocks (render done on client side)
   */
  export function transformMermaid(md: string): string {
    return md
      .replace(/^```mermaid\s*?({.*?})?\n([\s\S]+?)\n```/mg, (full, options = '', code = '') => {
        code = code.trim()
        options = options.trim() || '{}'
        const encoded = base64.encode(code, true)
        return `<Mermaid :code="'${encoded}'" v-bind="${options}" />`
      })
  }
  
  /**
   * Escape `{{}}` in code block to prevent Vue interpret it, #99
   */
  export function escapeVueInCode(md: string) {
    return md.replace(/{{(.*)}}/g, '&lbrace;&lbrace;$1&rbrace;&rbrace;')
  }
  