hunk.code_window:     default: () => ({}) as any as RouteRecordRaw,
     },
     scale: {
       type: Number,
     },
     is: {
       type: Object,
     },
   })
  
hunk.labels: keep keep keep keep add keep keep keep keep keep
hunk.after_edit:   no: {
       type: Number,
     },
  
hunk.file_path: packages/client/internals/SlideContainer.vue
hunk.type: add
file: import path from 'path'
  import http from 'http'
  import os from 'os'
  import fs from 'fs-extra'
  import yargs, { Argv } from 'yargs'
  import prompts from 'prompts'
  import { blue, bold, cyan, dim, green, yellow } from 'kolorist'
  import { LogLevel, ViteDevServer } from 'vite'
  import * as parser from '@slidev/parser/fs'
  import { version } from '../package.json'
  import { createServer } from './server'
  import { ResolvedSlidevOptions, resolveOptions } from './options'
  import { resolveThemeName } from './themes'
  
  const cli = yargs
    .scriptName('slidev')
    .usage('$0 [args]')
    .version(version)
    .strict()
    .showHelpOnFail(false)
    .alias('h', 'help')
    .alias('v', 'version')
  
  cli.command(
    '* [entry]',
    'Start a local server for Slidev',
    args => commonOptions(args)
      .option('port', {
        alias: 'p',
        type: 'number',
        describe: 'port',
      })
      .option('open', {
        alias: 'o',
        default: true,
        type: 'boolean',
        describe: 'open in browser',
      })
      .option('log', {
        default: 'warn',
        type: 'string',
        choices: ['error', 'warn', 'info', 'silent'],
        describe: 'log level',
      })
      .strict()
      .help(),
    async({ entry, theme, port, open, log }) => {
      if (!fs.existsSync(entry) && !entry.endsWith('.md'))
        entry = `${entry}.md`
  
      if (!fs.existsSync(entry)) {
        const { create } = await prompts({
          name: 'create',
          type: 'confirm',
          initial: 'Y',
          message: `Entry file ${yellow(`"${entry}"`)} does not exist, do you want to create it?`,
        })
        if (create)
          await fs.copyFile(path.resolve(__dirname, '../template.md'), entry)
        else
          process.exit(0)
      }
  
      let server: ViteDevServer | undefined
  
      async function initServer() {
        if (server)
          await server.close()
        const options = await resolveOptions({ entry, theme }, 'dev')
        port = port || await findFreePort(3030)
        server = (await createServer(
          options,
          {
            onDataReload(newData, data) {
              if (!theme && resolveThemeName(newData.config.theme) !== resolveThemeName(data.config.theme)) {
                console.log(yellow('\n  restarting on theme change\n'))
                initServer()
              }
              else if (newData.config.monaco !== data.config.monaco || newData.config.highlighter !== data.config.highlighter) {
                console.log(yellow('\n  restarting on config change\n'))
                initServer()
              }
            },
          },
          {
            server: {
              port,
              open,
            },
            logLevel: log as LogLevel,
          },
        ))
        await server.listen()
        printInfo(options, port)
      }
  
      initServer()
    },
  )
  
  cli.command(
    'build [entry]',
    'Build hostable SPA',
    args => commonOptions(args)
      .option('watch', {
        alias: 'w',
        default: false,
        describe: 'build watch',
      })
      .option('out', {
        alias: 'o',
        type: 'string',
        default: 'dist',
        describe: 'output dir',
      })
      .option('base', {
        type: 'string',
        describe: 'output base',
      })
      .option('download', {
        alias: 'd',
        type: 'boolean',
        describe: 'allow download as PDF',
      })
      .strict()
      .help(),
    async({ entry, theme, watch, base, download, out }) => {
      const { build } = await import('./build')
  
      const options = await resolveOptions({ entry, theme }, 'build')
      if (download && !options.data.config.download)
        options.data.config.download = download
  
      printInfo(options)
      await build(options, {}, {
        base,
        build: {
          watch: watch ? {} : undefined,
          outDir: out,
        },
      })
    },
  )
  
  cli.command(
    'format [entry]',
    'Format the markdown file',
    args => commonOptions(args)
      .strict()
      .help(),
    async({ entry }) => {
      const data = await parser.load(entry)
      parser.prettify(data)
      await parser.save(data)
    },
  )
  
  cli.command(
    'export [entry]',
    'Export slides to PDF',
    args => commonOptions(args)
      .option('output', {
        type: 'string',
        describe: 'path to the the port output',
      })
      .option('format', {
        default: 'pdf',
        type: 'string',
        choices: ['pdf', 'png'],
        describe: 'output format',
      })
      .option('timeout', {
        default: 100,
        type: 'number',
        describe: 'timeout for rendering each page',
      })
      .option('range', {
        type: 'string',
        describe: 'page ranges to export, for example "1,4-5,6"',
      })
      .strict()
      .help(),
    async({
      entry,
      theme,
      output,
      format,
      timeout,
      range,
    }) => {
      output = output || `${path.basename(entry, '.md')}-export`
      process.env.NODE_ENV = 'production'
      const { exportSlides } = await import('./export')
      const port = await findFreePort(12445)
      const options = await resolveOptions({ entry, theme }, 'build')
      const server = await createServer(
        options,
        {},
        {
          server: { port },
          logLevel: 'error',
          clearScreen: false,
        },
      )
      await server.listen(port)
      printInfo(options)
      parser.filterDisabled(options.data)
      output = await exportSlides({
        port,
        total: options.data.slides.length,
        range,
        format: format as any,
        output,
        timeout,
      })
      console.log(`${green('  ✓ ')}${dim('exported to ')}./${output}\n`)
      server.close()
      process.exit(0)
    },
  )
  
  cli
    .help()
    .parse()
  
  function commonOptions(args: Argv<{}>) {
    return args
      .positional('entry', {
        default: 'slides.md',
        type: 'string',
        describe: 'path to the slides markdown entry',
      })
      .option('theme', {
        alias: 't',
        type: 'string',
        describe: 'overide theme',
      })
  }
  
  function printInfo(options: ResolvedSlidevOptions, port?: number) {
    console.log()
    console.log()
    console.log(`  ${cyan('●') + blue('■') + yellow('▲')}`)
    console.log(`${bold('  Slidev')}  ${blue(`v${version}`)}`)
    console.log()
    console.log(dim('  theme   ') + green(options.theme))
    console.log(dim('  entry   ') + dim(path.dirname(options.entry) + path.sep) + path.basename(options.entry))
    if (port) {
      console.log()
      console.log(`${dim('  slide show     ')} > ${cyan(`http://localhost:${bold(port)}/`)}`)
      console.log(`${dim('  presenter mode ')} > ${blue(`http://localhost:${bold(port)}/presenter`)}`)
  
      Object.values(os.networkInterfaces())
        .forEach(v => (v || [])
          .filter(details => details.family === 'IPv4' && !details.address.includes('127.0.0.1'))
          .forEach(({ address }) => {
            console.log(`${dim('  remote control ')} > ${blue(`http://${address}:${port}/presenter`)}`)
          }),
        )
    }
    console.log()
    console.log()
  }
  
  function isPortFree(port: number) {
    return new Promise((resolve) => {
      const server = http.createServer()
        .listen(port, () => {
          server.close()
          resolve(true)
        })
        .on('error', () => {
          resolve(false)
        })
    })
  }
  
  async function findFreePort(start: number): Promise<number> {
    if (await isPortFree(start))
      return start
    return findFreePort(start + 1)
  }
  