prepare.js 3.1 KB
Newer Older
E
Evan You 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
const fs = require('fs')
const path = require('path')
const globby = require('globby')
const yaml = require('yaml-front-matter')
const tempPath = path.resolve(__dirname, 'app/.temp')

module.exports = async function prepare (sourceDir) {
  // 1. load options
  const options = await resolveOptions(sourceDir)

  // 2. generate dynamic component registration file
  await genComponentRegistrationFile(options)

  // 3. generate routes
  await genRoutesFile(options)

  return options
}

async function resolveOptions (sourceDir) {
  const configPath = path.resolve(sourceDir, 'vuepress.config.js')
  const siteConfig = fs.existsSync(configPath) ? require(configPath) : {}

  const options = {
    siteConfig,
    sourceDir,
    publicPath: siteConfig.baseUrl || '/',
    themePath: path.resolve(__dirname, 'default-theme/App.vue'),
    pages: await globby(['**/*.md'], { cwd: sourceDir })
  }

E
wip  
Evan You 已提交
32 33 34 35
  // resolve theme
  const themePath = path.resolve(sourceDir, '_theme/App.vue')
  if (fs.existsSync(themePath)) {
    options.themePath = themePath
E
Evan You 已提交
36 37 38 39
  }

  const pagesData = {}
  options.pages.forEach(file => {
E
Evan You 已提交
40 41
    const name = file.replace(/\.md$/, '').replace(/\\/g, '/')
    const urlPath = '/' + (name === 'index' ? '' : (name + '.html'))
E
Evan You 已提交
42
    const content = fs.readFileSync(path.resolve(sourceDir, file), 'utf-8')
E
Evan You 已提交
43 44 45
    const data = pagesData[urlPath] = {
      path: urlPath
    }
E
Evan You 已提交
46 47
    const frontmatter = yaml.loadFront(content)
    delete frontmatter.__content
E
Evan You 已提交
48 49
    if (Object.keys(frontmatter).length) {
      data.frontmatter = frontmatter
E
Evan You 已提交
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
    }
  })

  options.siteData = Object.assign({}, siteConfig.data, {
    pages: pagesData
  })

  return options
}

async function genComponentRegistrationFile ({ sourceDir, pages }) {
  function genImport (file) {
    const name = toComponentName(file)
    const baseDir = /\.md$/.test(file)
      ? sourceDir
      : path.resolve(sourceDir, '_components')
    const absolutePath = path.resolve(baseDir, file)
    const code = `Vue.component(${JSON.stringify(name)}, () => import(${JSON.stringify(absolutePath)}))`
    return code
  }

  const components = (await resolveComponents(sourceDir)) || []
  const all = [...pages, ...components]
  const file = `import Vue from 'vue'\n` + all.map(genImport).join('\n')
  fs.writeFileSync(path.join(tempPath, 'register-components.js'), file)
}

E
Evan You 已提交
77 78 79 80 81 82 83 84 85 86
function toComponentName (file) {
  const isPage = /\.md$/.test(file)
  return (
    (isPage ? `page-` : ``) +
    file
      .replace(/\.(vue|md)$/, '')
      .replace(/\/|\\/g, '-')
  )
}

E
Evan You 已提交
87 88 89 90 91 92 93 94
async function resolveComponents (sourceDir) {
  const componentDir = path.resolve(sourceDir, '_components')
  if (!fs.existsSync(componentDir)) {
    return
  }
  return await globby(['*.vue'], { cwd: componentDir })
}

E
Evan You 已提交
95 96
async function genRoutesFile ({ sourceDir, siteData: { pages }}) {
  function genRoute (path) {
E
Evan You 已提交
97 98
    const code = `
    {
E
Evan You 已提交
99
      path: ${JSON.stringify(path)},
E
Evan You 已提交
100 101 102 103 104 105 106
      component: Theme
    }`
    return code
  }

  const file =
    `import Theme from '~theme'\n` +
E
Evan You 已提交
107
    `export default [${Object.keys(pages).map(genRoute).join(',')}\n]`
E
Evan You 已提交
108 109
  fs.writeFileSync(path.join(tempPath, 'routes.js'), file)
}