From e5d8ed4655b42e975a1d72286bc859257b3d2eb9 Mon Sep 17 00:00:00 2001
From: ULIVZ <472590061@qq.com>
Date: Mon, 4 Mar 2019 23:46:13 +0800
Subject: [PATCH] feat: refine node api (#1395)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- fix($core): markdown slot doesn‘t work. (regression of c85f62d)
- docs: fresh Node.JS API.
- test: official plugins.
---
babel.config.js | 3 +
package.json | 1 +
packages/@vuepress/core/lib/build.js | 197 -
.../@vuepress/core/lib/{app => client}/app.js | 0
.../core/lib/{app => client}/clientEntry.js | 0
.../{app => client}/components/ClientOnly.js | 0
.../lib/{app => client}/components/Content.js | 0
.../components/ContentSlotsDistributor.js | 0
.../components/GlobalLayout.vue | 0
.../{app => client}/components/HeaderList.vue | 0
.../{app => client}/components/NotFound.vue | 0
.../components/OutboundLink.vue | 0
.../lib/{app => client}/components/TOC.vue | 0
.../core/lib/{app => client}/dataMixin.js | 4 +-
.../core/lib/{app => client}/index.dev.html | 0
.../core/lib/{app => client}/index.ssr.html | 0
.../lib/{app => client}/plugins/Store.d.ts | 0
.../core/lib/{app => client}/plugins/Store.js | 0
.../lib/{app => client}/plugins/VuePress.d.ts | 0
.../lib/{app => client}/plugins/VuePress.js | 0
.../core/lib/{app => client}/redirect.js | 0
.../{app => client}/root-mixins/updateMeta.js | 0
.../core/lib/{app => client}/serverEntry.js | 0
.../lib/{app => client}/style/config.styl | 0
.../core/lib/{app => client}/util.js | 0
packages/@vuepress/core/lib/dev.js | 207 -
packages/@vuepress/core/lib/index.js | 25 +-
.../{prepare/AppContext.js => node/App.js} | 167 +-
.../core/lib/{prepare => node}/CacheLoader.js | 6 +-
.../{prepare => node}/ClientComputedMixin.js | 0
.../core/lib/{prepare => node}/Page.js | 2 +-
.../__tests__/plugin-api/AsyncOption.spec.js | 2 +-
.../node}/__tests__/plugin-api/Option.spec.js | 2 +-
.../__tests__/plugin-api/PluginAPI.spec.js | 4 +-
.../__tests__/plugin-api/PluginUtil.spec.js | 16 +-
.../node/__tests__/prepare/App.spec.js} | 12 +-
.../node}/__tests__/prepare/Page.spec.js | 34 +-
.../fixtures/docs-config/.vuepress/config.js | 0
.../prepare/fixtures/docs-config/README.md | 0
.../fixtures/docs-i18n/.vuepress/config.js | 0
.../prepare/fixtures/docs-i18n/README.md | 0
.../prepare/fixtures/docs-i18n/zh/README.md | 0
.../docs-local-theme/.vuepress/config.js | 0
.../.vuepress/theme/Layout.vue | 0
.../fixtures/docs-local-theme/README.md | 0
.../__tests__/prepare/fixtures/docs/README.md | 0
.../__tests__/prepare/fixtures/docs/alpha.md | 0
.../{ => lib/node}/__tests__/prepare/util.js | 14 +-
.../theme-api/fixtures/theme/Layout.vue | 0
.../fixtures/theme/components/Home.vue | 0
.../node}/__tests__/theme-api/index.spec.js | 2 +-
.../@vuepress/core/lib/node/build/index.js | 273 +
.../lib/{prepare => node}/createMarkdown.js | 4 +-
.../@vuepress/core/lib/node/createTemp.js | 42 +
packages/@vuepress/core/lib/node/dev/index.js | 272 +
.../docs.fallback/.vuepress/theme/Layout.vue} | 0
.../core/lib/node/docs.fallback/README.md | 3 +
.../internal-plugins/dataBlock/index.js | 0
.../internal-plugins/dataBlock/loader.js | 0
.../{ => node}/internal-plugins/enhanceApp.js | 0
.../frontmatterBlock/index.js | 0
.../frontmatterBlock/loader.js | 2 +-
.../internal-plugins/layoutComponents.js | 0
.../internal-plugins/pageComponents.js | 0
.../internal-plugins/palette/index.js | 2 +-
.../{ => node}/internal-plugins/rootMixins.js | 3 +-
.../lib/{ => node}/internal-plugins/routes.js | 0
.../{ => node}/internal-plugins/siteData.js | 0
.../internal-plugins/style/client.js | 0
.../internal-plugins/style/index.js | 0
.../internal-plugins/transformModule.js | 2 +-
.../core/lib/{prepare => node}/loadConfig.js | 0
.../core/lib/{prepare => node}/loadTheme.js | 10 +-
.../plugin-api/abstract/AsyncOption.js | 0
.../{ => node}/plugin-api/abstract/Option.js | 0
.../lib/{ => node}/plugin-api/constants.js | 0
.../core/lib/{ => node}/plugin-api/index.js | 44 +
.../plugin-api/override/AliasOption.js | 0
.../override/ClientDynamicModulesOption.js | 0
.../plugin-api/override/DefineOption.js | 0
.../override/EnhanceAppFilesOption.js | 0
.../override/GlobalUIComponentsOption.js | 0
.../plugin-api/override/instantiateOption.js | 0
.../core/lib/{ => node}/plugin-api/util.js | 0
.../lib/node/theme-api/Layout.fallback.vue | 3 +
.../core/lib/{ => node}/theme-api/index.js | 2 +-
.../core/lib/{ => node}/util/index.js | 0
.../lib/{ => node}/webpack/ClientPlugin.js | 0
.../lib/{ => node}/webpack/DevLogPlugin.js | 0
.../core/lib/{ => node}/webpack/HeadPlugin.js | 0
.../{ => node}/webpack/createBaseConfig.js | 48 +-
.../{ => node}/webpack/createClientConfig.js | 6 +-
.../{ => node}/webpack/createServerConfig.js | 4 +-
.../core/lib/{ => node}/webpack/noopModule.js | 0
packages/@vuepress/core/lib/prepare/index.js | 19 -
.../__snapshots__/containers.spec.js.snap | 35 -
.../__snapshots__/highlightLines.spec.js.snap | 17 +-
.../__snapshots__/hoist.spec.js.snap | 1 +
.../__snapshots__/lineNumers.spec.js.snap | 3 +-
.../__tests__/__snapshots__/link.spec.js.snap | 21 +-
.../__snapshots__/snippet.spec.js.snap | 17 +-
.../markdown/__tests__/containers.spec.js | 15 -
.../code-snippet-highlightLines-multiple.md | 2 +-
.../code-snippet-highlightLines-single.md | 2 +-
.../__tests__/fragments/code-snippet.md | 2 +-
.../markdown/__tests__/highlight.spec.js | 7 +-
.../markdown/__tests__/highlightLines.spec.js | 15 +-
.../markdown/__tests__/hoist.spec.js | 11 +-
.../markdown/__tests__/lineNumers.spec.js | 11 +-
.../markdown/__tests__/snippet.spec.js | 17 +-
packages/@vuepress/markdown/__tests__/util.js | 17 -
packages/@vuepress/markdown/package.json | 3 +
.../__snapshots__/index.spec.js.snap | 48 +
.../__tests__/fragments/danger.md} | 0
.../__tests__/fragments/markdown-slots.md | 10 +
.../__tests__/fragments/tip-override.md} | 0
.../__tests__/fragments/tip.md} | 0
.../__tests__/fragments/v-pre.md} | 0
.../__tests__/fragments/warning.md} | 0
.../plugin-container/__tests__/index.spec.js | 36 +
packages/@vuepress/plugin-container/index.js | 4 +-
.../@vuepress/plugin-container/package.json | 3 +
.../shared-utils/src/parseFrontmatter.ts | 6 +-
.../test-utils/client/createLocalVue.js | 20 +
packages/@vuepress/test-utils/client/index.js | 7 +
.../test-utils/{ => client}/mockComponent.js | 2 +-
.../test-utils/{ => client}/siteData.js | 2 +-
.../@vuepress/test-utils/createJestRunner.js | 12 -
.../@vuepress/test-utils/createLocalVue.js | 17 -
.../fixtures/docs/.vuepress/theme/Layout.vue | 3 +
.../test-utils/fixtures/docs/README.md | 1 +
packages/@vuepress/test-utils/getRouter.js | 5 -
packages/@vuepress/test-utils/index.js | 11 +
.../test-utils/{ => lib}/createJestConfig.js | 2 +-
.../test-utils/lib/createJestRunner.js | 45 +
.../@vuepress/test-utils/lib/getFragment.js | 15 +
.../@vuepress/test-utils/lib/getFragments.js | 13 +
.../test-utils/{jest => lib}/jest.config.js | 3 -
packages/@vuepress/test-utils/package.json | 18 +-
.../__tests__/components/DropdownLink.spec.js | 2 +-
.../__tests__/components/NavLink.spec.js | 2 +-
.../__snapshots__/DropdownLink.spec.js.snap | 11 +-
.../__snapshots__/NavLink.spec.js.snap | 3 +-
packages/docs/docs/.vuepress/config.js | 11 +
packages/docs/docs/.vuepress/nav/en.js | 4 +-
packages/docs/docs/.vuepress/nav/zh.js | 4 +-
packages/docs/docs/api/README.md | 7 +
packages/docs/docs/api/cli.md | 45 +
.../docs/{config/README.md => api/config.md} | 9 +-
packages/docs/docs/api/node.md | 57 +
packages/docs/docs/guide/assets.md | 2 +-
packages/docs/docs/guide/basic-config.md | 2 +-
.../docs/docs/guide/directory-structure.md | 4 +-
packages/docs/docs/guide/markdown.md | 6 +-
packages/docs/docs/guide/using-vue.md | 2 +-
.../docs/miscellaneous/migration-guide.md | 4 +-
packages/docs/docs/plugin/context-api.md | 2 +-
.../docs/plugin/official/plugin-nprogress.md | 2 +-
.../docs/docs/theme/default-theme-config.md | 2 +-
packages/docs/docs/theme/writing-a-theme.md | 2 +-
packages/docs/docs/zh/api/README.md | 7 +
packages/docs/docs/zh/api/cli.md | 45 +
.../zh/{config/README.md => api/config.md} | 9 +-
packages/docs/docs/zh/api/node.md | 57 +
packages/docs/docs/zh/guide/assets.md | 2 +-
packages/docs/docs/zh/guide/basic-config.md | 2 +-
.../docs/docs/zh/guide/directory-structure.md | 2 +-
packages/docs/docs/zh/guide/markdown.md | 6 +-
packages/docs/docs/zh/guide/using-vue.md | 2 +-
.../docs/zh/miscellaneous/migration-guide.md | 4 +-
packages/docs/docs/zh/plugin/context-api.md | 2 +-
.../zh/plugin/official/plugin-nprogress.md | 2 +-
.../docs/zh/theme/default-theme-config.md | 2 +-
.../docs/docs/zh/theme/writing-a-theme.md | 2 +-
packages/docs/package.json | 1 +
packages/vuepress/lib/handleUnknownCommand.js | 18 +-
packages/vuepress/lib/registerCoreCommands.js | 6 +-
scripts/jest.config.js | 9 +-
scripts/test.js | 26 +-
yarn.lock | 5325 ++++++++---------
180 files changed, 3886 insertions(+), 3742 deletions(-)
delete mode 100644 packages/@vuepress/core/lib/build.js
rename packages/@vuepress/core/lib/{app => client}/app.js (100%)
rename packages/@vuepress/core/lib/{app => client}/clientEntry.js (100%)
rename packages/@vuepress/core/lib/{app => client}/components/ClientOnly.js (100%)
rename packages/@vuepress/core/lib/{app => client}/components/Content.js (100%)
rename packages/@vuepress/core/lib/{app => client}/components/ContentSlotsDistributor.js (100%)
rename packages/@vuepress/core/lib/{app => client}/components/GlobalLayout.vue (100%)
rename packages/@vuepress/core/lib/{app => client}/components/HeaderList.vue (100%)
rename packages/@vuepress/core/lib/{app => client}/components/NotFound.vue (100%)
rename packages/@vuepress/core/lib/{app => client}/components/OutboundLink.vue (100%)
rename packages/@vuepress/core/lib/{app => client}/components/TOC.vue (100%)
rename packages/@vuepress/core/lib/{app => client}/dataMixin.js (89%)
rename packages/@vuepress/core/lib/{app => client}/index.dev.html (100%)
rename packages/@vuepress/core/lib/{app => client}/index.ssr.html (100%)
rename packages/@vuepress/core/lib/{app => client}/plugins/Store.d.ts (100%)
rename packages/@vuepress/core/lib/{app => client}/plugins/Store.js (100%)
rename packages/@vuepress/core/lib/{app => client}/plugins/VuePress.d.ts (100%)
rename packages/@vuepress/core/lib/{app => client}/plugins/VuePress.js (100%)
rename packages/@vuepress/core/lib/{app => client}/redirect.js (100%)
rename packages/@vuepress/core/lib/{app => client}/root-mixins/updateMeta.js (100%)
rename packages/@vuepress/core/lib/{app => client}/serverEntry.js (100%)
rename packages/@vuepress/core/lib/{app => client}/style/config.styl (100%)
rename packages/@vuepress/core/lib/{app => client}/util.js (100%)
delete mode 100644 packages/@vuepress/core/lib/dev.js
rename packages/@vuepress/core/lib/{prepare/AppContext.js => node/App.js} (73%)
rename packages/@vuepress/core/lib/{prepare => node}/CacheLoader.js (89%)
rename packages/@vuepress/core/lib/{prepare => node}/ClientComputedMixin.js (100%)
rename packages/@vuepress/core/lib/{prepare => node}/Page.js (99%)
rename packages/@vuepress/core/{ => lib/node}/__tests__/plugin-api/AsyncOption.spec.js (90%)
rename packages/@vuepress/core/{ => lib/node}/__tests__/plugin-api/Option.spec.js (97%)
rename packages/@vuepress/core/{ => lib/node}/__tests__/plugin-api/PluginAPI.spec.js (95%)
rename packages/@vuepress/core/{ => lib/node}/__tests__/plugin-api/PluginUtil.spec.js (76%)
rename packages/@vuepress/core/{__tests__/prepare/prepare.spec.js => lib/node/__tests__/prepare/App.spec.js} (70%)
rename packages/@vuepress/core/{ => lib/node}/__tests__/prepare/Page.spec.js (80%)
rename packages/@vuepress/core/{ => lib/node}/__tests__/prepare/fixtures/docs-config/.vuepress/config.js (100%)
rename packages/@vuepress/core/{ => lib/node}/__tests__/prepare/fixtures/docs-config/README.md (100%)
rename packages/@vuepress/core/{ => lib/node}/__tests__/prepare/fixtures/docs-i18n/.vuepress/config.js (100%)
rename packages/@vuepress/core/{ => lib/node}/__tests__/prepare/fixtures/docs-i18n/README.md (100%)
rename packages/@vuepress/core/{ => lib/node}/__tests__/prepare/fixtures/docs-i18n/zh/README.md (100%)
rename packages/@vuepress/core/{ => lib/node}/__tests__/prepare/fixtures/docs-local-theme/.vuepress/config.js (100%)
rename packages/@vuepress/core/{ => lib/node}/__tests__/prepare/fixtures/docs-local-theme/.vuepress/theme/Layout.vue (100%)
rename packages/@vuepress/core/{ => lib/node}/__tests__/prepare/fixtures/docs-local-theme/README.md (100%)
rename packages/@vuepress/core/{ => lib/node}/__tests__/prepare/fixtures/docs/README.md (100%)
rename packages/@vuepress/core/{ => lib/node}/__tests__/prepare/fixtures/docs/alpha.md (100%)
rename packages/@vuepress/core/{ => lib/node}/__tests__/prepare/util.js (55%)
rename packages/@vuepress/core/{ => lib/node}/__tests__/theme-api/fixtures/theme/Layout.vue (100%)
rename packages/@vuepress/core/{ => lib/node}/__tests__/theme-api/fixtures/theme/components/Home.vue (100%)
rename packages/@vuepress/core/{ => lib/node}/__tests__/theme-api/index.spec.js (93%)
create mode 100644 packages/@vuepress/core/lib/node/build/index.js
rename packages/@vuepress/core/lib/{prepare => node}/createMarkdown.js (83%)
create mode 100644 packages/@vuepress/core/lib/node/createTemp.js
create mode 100644 packages/@vuepress/core/lib/node/dev/index.js
rename packages/@vuepress/core/lib/{theme-api/Layout.fallback.vue => node/docs.fallback/.vuepress/theme/Layout.vue} (100%)
create mode 100644 packages/@vuepress/core/lib/node/docs.fallback/README.md
rename packages/@vuepress/core/lib/{ => node}/internal-plugins/dataBlock/index.js (100%)
rename packages/@vuepress/core/lib/{ => node}/internal-plugins/dataBlock/loader.js (100%)
rename packages/@vuepress/core/lib/{ => node}/internal-plugins/enhanceApp.js (100%)
rename packages/@vuepress/core/lib/{ => node}/internal-plugins/frontmatterBlock/index.js (100%)
rename packages/@vuepress/core/lib/{ => node}/internal-plugins/frontmatterBlock/loader.js (94%)
rename packages/@vuepress/core/lib/{ => node}/internal-plugins/layoutComponents.js (100%)
rename packages/@vuepress/core/lib/{ => node}/internal-plugins/pageComponents.js (100%)
rename packages/@vuepress/core/lib/{ => node}/internal-plugins/palette/index.js (95%)
rename packages/@vuepress/core/lib/{ => node}/internal-plugins/rootMixins.js (81%)
rename packages/@vuepress/core/lib/{ => node}/internal-plugins/routes.js (100%)
rename packages/@vuepress/core/lib/{ => node}/internal-plugins/siteData.js (100%)
rename packages/@vuepress/core/lib/{ => node}/internal-plugins/style/client.js (100%)
rename packages/@vuepress/core/lib/{ => node}/internal-plugins/style/index.js (100%)
rename packages/@vuepress/core/lib/{ => node}/internal-plugins/transformModule.js (90%)
rename packages/@vuepress/core/lib/{prepare => node}/loadConfig.js (100%)
rename packages/@vuepress/core/lib/{prepare => node}/loadTheme.js (90%)
rename packages/@vuepress/core/lib/{ => node}/plugin-api/abstract/AsyncOption.js (100%)
rename packages/@vuepress/core/lib/{ => node}/plugin-api/abstract/Option.js (100%)
rename packages/@vuepress/core/lib/{ => node}/plugin-api/constants.js (100%)
rename packages/@vuepress/core/lib/{ => node}/plugin-api/index.js (88%)
rename packages/@vuepress/core/lib/{ => node}/plugin-api/override/AliasOption.js (100%)
rename packages/@vuepress/core/lib/{ => node}/plugin-api/override/ClientDynamicModulesOption.js (100%)
rename packages/@vuepress/core/lib/{ => node}/plugin-api/override/DefineOption.js (100%)
rename packages/@vuepress/core/lib/{ => node}/plugin-api/override/EnhanceAppFilesOption.js (100%)
rename packages/@vuepress/core/lib/{ => node}/plugin-api/override/GlobalUIComponentsOption.js (100%)
rename packages/@vuepress/core/lib/{ => node}/plugin-api/override/instantiateOption.js (100%)
rename packages/@vuepress/core/lib/{ => node}/plugin-api/util.js (100%)
create mode 100644 packages/@vuepress/core/lib/node/theme-api/Layout.fallback.vue
rename packages/@vuepress/core/lib/{ => node}/theme-api/index.js (98%)
rename packages/@vuepress/core/lib/{ => node}/util/index.js (100%)
rename packages/@vuepress/core/lib/{ => node}/webpack/ClientPlugin.js (100%)
rename packages/@vuepress/core/lib/{ => node}/webpack/DevLogPlugin.js (100%)
rename packages/@vuepress/core/lib/{ => node}/webpack/HeadPlugin.js (100%)
rename packages/@vuepress/core/lib/{ => node}/webpack/createBaseConfig.js (90%)
rename packages/@vuepress/core/lib/{ => node}/webpack/createClientConfig.js (90%)
rename packages/@vuepress/core/lib/{ => node}/webpack/createServerConfig.js (90%)
rename packages/@vuepress/core/lib/{ => node}/webpack/noopModule.js (100%)
delete mode 100644 packages/@vuepress/core/lib/prepare/index.js
delete mode 100644 packages/@vuepress/markdown/__tests__/__snapshots__/containers.spec.js.snap
delete mode 100644 packages/@vuepress/markdown/__tests__/containers.spec.js
create mode 100644 packages/@vuepress/plugin-container/__tests__/__snapshots__/index.spec.js.snap
rename packages/@vuepress/{markdown/__tests__/fragments/container-danger.md => plugin-container/__tests__/fragments/danger.md} (100%)
create mode 100644 packages/@vuepress/plugin-container/__tests__/fragments/markdown-slots.md
rename packages/@vuepress/{markdown/__tests__/fragments/container-tip-override.md => plugin-container/__tests__/fragments/tip-override.md} (100%)
rename packages/@vuepress/{markdown/__tests__/fragments/container-tip.md => plugin-container/__tests__/fragments/tip.md} (100%)
rename packages/@vuepress/{markdown/__tests__/fragments/container-v-pre.md => plugin-container/__tests__/fragments/v-pre.md} (100%)
rename packages/@vuepress/{markdown/__tests__/fragments/container-warning.md => plugin-container/__tests__/fragments/warning.md} (100%)
create mode 100644 packages/@vuepress/plugin-container/__tests__/index.spec.js
create mode 100644 packages/@vuepress/test-utils/client/createLocalVue.js
create mode 100644 packages/@vuepress/test-utils/client/index.js
rename packages/@vuepress/test-utils/{ => client}/mockComponent.js (88%)
rename packages/@vuepress/test-utils/{ => client}/siteData.js (98%)
delete mode 100644 packages/@vuepress/test-utils/createJestRunner.js
delete mode 100644 packages/@vuepress/test-utils/createLocalVue.js
create mode 100644 packages/@vuepress/test-utils/fixtures/docs/.vuepress/theme/Layout.vue
create mode 100644 packages/@vuepress/test-utils/fixtures/docs/README.md
delete mode 100644 packages/@vuepress/test-utils/getRouter.js
create mode 100644 packages/@vuepress/test-utils/index.js
rename packages/@vuepress/test-utils/{ => lib}/createJestConfig.js (67%)
create mode 100644 packages/@vuepress/test-utils/lib/createJestRunner.js
create mode 100644 packages/@vuepress/test-utils/lib/getFragment.js
create mode 100644 packages/@vuepress/test-utils/lib/getFragments.js
rename packages/@vuepress/test-utils/{jest => lib}/jest.config.js (81%)
create mode 100644 packages/docs/docs/api/README.md
create mode 100644 packages/docs/docs/api/cli.md
rename packages/docs/docs/{config/README.md => api/config.md} (98%)
create mode 100644 packages/docs/docs/api/node.md
create mode 100644 packages/docs/docs/zh/api/README.md
create mode 100644 packages/docs/docs/zh/api/cli.md
rename packages/docs/docs/zh/{config/README.md => api/config.md} (98%)
create mode 100644 packages/docs/docs/zh/api/node.md
diff --git a/babel.config.js b/babel.config.js
index 87edd47c65..fa59afb6b9 100644
--- a/babel.config.js
+++ b/babel.config.js
@@ -3,6 +3,9 @@ module.exports = {
'test': {
'presets': [
['@babel/preset-env', { 'targets': { 'node': 'current' }}]
+ ],
+ 'plugins': [
+ '@babel/plugin-syntax-dynamic-import'
]
}
}
diff --git a/package.json b/package.json
index b7a5120cd3..ca677c54c0 100644
--- a/package.json
+++ b/package.json
@@ -13,6 +13,7 @@
"remote-version": "node scripts/remote-version.js",
"dev": "yarn tsc && yarn workspace docs dev",
"build": "yarn tsc && yarn workspace docs build",
+ "view-info": "yarn tsc && yarn workspace docs view-info",
"show-help": "yarn workspace docs show-help",
"dev:blog": "yarn tsc && yarn workspace blog dev",
"build:blog": "yarn tsc && yarn workspace blog build",
diff --git a/packages/@vuepress/core/lib/build.js b/packages/@vuepress/core/lib/build.js
deleted file mode 100644
index 23e49bbc96..0000000000
--- a/packages/@vuepress/core/lib/build.js
+++ /dev/null
@@ -1,197 +0,0 @@
-'use strict'
-
-module.exports = async function build (sourceDir, cliOptions = {}) {
- process.env.NODE_ENV = 'production'
-
- const webpack = require('webpack')
- const readline = require('readline')
- const escape = require('escape-html')
-
- const { chalk, fs, path, logger, env, performance } = require('@vuepress/shared-utils')
- const prepare = require('./prepare/index')
- const createClientConfig = require('./webpack/createClientConfig')
- const createServerConfig = require('./webpack/createServerConfig')
- const { createBundleRenderer } = require('vue-server-renderer')
- const { normalizeHeadTag, applyUserWebpackConfig } = require('./util/index')
-
- logger.wait('Extracting site metadata...')
- const ctx = await prepare(sourceDir, cliOptions, true /* isProd */)
-
- const { outDir, cwd } = ctx
- if (cwd === outDir) {
- return console.error(logger.error(chalk.red('Unexpected option: outDir cannot be set to the current working directory.\n'), false))
- }
-
- await fs.emptyDir(outDir)
- logger.debug('Dist directory: ' + chalk.gray(outDir))
-
- let clientConfig = createClientConfig(ctx, cliOptions).toConfig()
- let serverConfig = createServerConfig(ctx, cliOptions).toConfig()
-
- // apply user config...
- const userConfig = ctx.siteConfig.configureWebpack
- if (userConfig) {
- clientConfig = applyUserWebpackConfig(userConfig, clientConfig, false)
- serverConfig = applyUserWebpackConfig(userConfig, serverConfig, true)
- }
-
- // compile!
- const stats = await compile([clientConfig, serverConfig])
-
- const serverBundle = require(path.resolve(outDir, 'manifest/server.json'))
- const clientManifest = require(path.resolve(outDir, 'manifest/client.json'))
-
- // remove manifests after loading them.
- await fs.remove(path.resolve(outDir, 'manifest'))
-
- // find and remove empty style chunk caused by
- // https://github.com/webpack-contrib/mini-css-extract-plugin/issues/85
- // TODO remove when it's fixed
- if (!clientConfig.devtool && (!clientConfig.plugins ||
- !clientConfig.plugins.some(p =>
- p instanceof webpack.SourceMapDevToolPlugin ||
- p instanceof webpack.EvalSourceMapDevToolPlugin
- ))) {
- await workaroundEmptyStyleChunk()
- }
-
- // create server renderer using built manifests
- const renderer = createBundleRenderer(serverBundle, {
- clientManifest,
- runInNewContext: false,
- inject: false,
- shouldPrefetch: ctx.siteConfig.shouldPrefetch || (() => true),
- template: await fs.readFile(ctx.ssrTemplate, 'utf-8')
- })
-
- // pre-render head tags from user config
- const userHeadTags = (ctx.siteConfig.head || [])
- .map(renderHeadTag)
- .join('\n ')
-
- // if the user does not have a custom 404.md, generate the theme's default
- if (!ctx.pages.some(p => p.path === '/404.html')) {
- ctx.addPage({ path: '/404.html' })
- }
-
- // render pages
- logger.wait('Rendering static HTML...')
-
- const pagePaths = []
- for (const page of ctx.pages) {
- pagePaths.push(await renderPage(page))
- }
-
- readline.clearLine(process.stdout, 0)
- readline.cursorTo(process.stdout, 0)
-
- await ctx.pluginAPI.options.generated.apply(pagePaths)
-
- // DONE.
- const relativeDir = path.relative(cwd, outDir)
- logger.success(`Generated static files in ${chalk.cyan(relativeDir)}.`)
- const { duration } = performance.stop()
- logger.developer(`It took a total of ${chalk.cyan(`${duration}ms`)} to run the ${chalk.cyan('vuepress build')}.`)
- console.log()
-
- // --- helpers ---
-
- function compile (config) {
- return new Promise((resolve, reject) => {
- webpack(config, (err, stats) => {
- if (err) {
- return reject(err)
- }
- if (stats.hasErrors()) {
- stats.toJson().errors.forEach(err => {
- console.error(err)
- })
- reject(new Error(`Failed to compile with errors.`))
- return
- }
- if (env.isDebug && stats.hasWarnings()) {
- stats.toJson().warnings.forEach(warning => {
- console.warn(warning)
- })
- }
- resolve(stats.toJson({ modules: false }))
- })
- })
- }
-
- function renderHeadTag (tag) {
- const { tagName, attributes, innerHTML, closeTag } = normalizeHeadTag(tag)
- return `<${tagName}${renderAttrs(attributes)}>${innerHTML}${closeTag ? `${tagName}>` : ``}`
- }
-
- function renderAttrs (attrs = {}) {
- const keys = Object.keys(attrs)
- if (keys.length) {
- return ' ' + keys.map(name => `${name}="${escape(attrs[name])}"`).join(' ')
- } else {
- return ''
- }
- }
-
- async function renderPage (page) {
- const pagePath = page.path
- readline.clearLine(process.stdout, 0)
- readline.cursorTo(process.stdout, 0)
- process.stdout.write(`Rendering page: ${pagePath}`)
-
- // #565 Avoid duplicate description meta at SSR.
- const meta = (page.frontmatter && page.frontmatter.meta || []).filter(item => item.name !== 'description')
- const pageMeta = renderPageMeta(meta)
-
- const context = {
- url: pagePath,
- userHeadTags,
- pageMeta,
- title: 'VuePress',
- lang: 'en',
- description: ''
- }
-
- let html
- try {
- html = await renderer.renderToString(context)
- } catch (e) {
- console.error(logger.error(chalk.red(`Error rendering ${pagePath}:`), false))
- throw e
- }
- const filename = decodeURIComponent(pagePath.replace(/\/$/, '/index.html').replace(/^\//, ''))
- const filePath = path.resolve(outDir, filename)
- await fs.ensureDir(path.dirname(filePath))
- await fs.writeFile(filePath, html)
- return filePath
- }
-
- function renderPageMeta (meta) {
- if (!meta) return ''
- return meta.map(m => {
- let res = ` {
- res += ` ${key}="${escape(m[key])}"`
- })
- return res + `>`
- }).join('')
- }
-
- async function workaroundEmptyStyleChunk () {
- const styleChunk = stats.children[0].assets.find(a => {
- return /styles\.\w{8}\.js$/.test(a.name)
- })
- if (!styleChunk) return
- const styleChunkPath = path.resolve(outDir, styleChunk.name)
- const styleChunkContent = await fs.readFile(styleChunkPath, 'utf-8')
- await fs.remove(styleChunkPath)
- // prepend it to app.js.
- // this is necessary for the webpack runtime to work properly.
- const appChunk = stats.children[0].assets.find(a => {
- return /app\.\w{8}\.js$/.test(a.name)
- })
- const appChunkPath = path.resolve(outDir, appChunk.name)
- const appChunkContent = await fs.readFile(appChunkPath, 'utf-8')
- await fs.writeFile(appChunkPath, styleChunkContent + appChunkContent)
- }
-}
diff --git a/packages/@vuepress/core/lib/app/app.js b/packages/@vuepress/core/lib/client/app.js
similarity index 100%
rename from packages/@vuepress/core/lib/app/app.js
rename to packages/@vuepress/core/lib/client/app.js
diff --git a/packages/@vuepress/core/lib/app/clientEntry.js b/packages/@vuepress/core/lib/client/clientEntry.js
similarity index 100%
rename from packages/@vuepress/core/lib/app/clientEntry.js
rename to packages/@vuepress/core/lib/client/clientEntry.js
diff --git a/packages/@vuepress/core/lib/app/components/ClientOnly.js b/packages/@vuepress/core/lib/client/components/ClientOnly.js
similarity index 100%
rename from packages/@vuepress/core/lib/app/components/ClientOnly.js
rename to packages/@vuepress/core/lib/client/components/ClientOnly.js
diff --git a/packages/@vuepress/core/lib/app/components/Content.js b/packages/@vuepress/core/lib/client/components/Content.js
similarity index 100%
rename from packages/@vuepress/core/lib/app/components/Content.js
rename to packages/@vuepress/core/lib/client/components/Content.js
diff --git a/packages/@vuepress/core/lib/app/components/ContentSlotsDistributor.js b/packages/@vuepress/core/lib/client/components/ContentSlotsDistributor.js
similarity index 100%
rename from packages/@vuepress/core/lib/app/components/ContentSlotsDistributor.js
rename to packages/@vuepress/core/lib/client/components/ContentSlotsDistributor.js
diff --git a/packages/@vuepress/core/lib/app/components/GlobalLayout.vue b/packages/@vuepress/core/lib/client/components/GlobalLayout.vue
similarity index 100%
rename from packages/@vuepress/core/lib/app/components/GlobalLayout.vue
rename to packages/@vuepress/core/lib/client/components/GlobalLayout.vue
diff --git a/packages/@vuepress/core/lib/app/components/HeaderList.vue b/packages/@vuepress/core/lib/client/components/HeaderList.vue
similarity index 100%
rename from packages/@vuepress/core/lib/app/components/HeaderList.vue
rename to packages/@vuepress/core/lib/client/components/HeaderList.vue
diff --git a/packages/@vuepress/core/lib/app/components/NotFound.vue b/packages/@vuepress/core/lib/client/components/NotFound.vue
similarity index 100%
rename from packages/@vuepress/core/lib/app/components/NotFound.vue
rename to packages/@vuepress/core/lib/client/components/NotFound.vue
diff --git a/packages/@vuepress/core/lib/app/components/OutboundLink.vue b/packages/@vuepress/core/lib/client/components/OutboundLink.vue
similarity index 100%
rename from packages/@vuepress/core/lib/app/components/OutboundLink.vue
rename to packages/@vuepress/core/lib/client/components/OutboundLink.vue
diff --git a/packages/@vuepress/core/lib/app/components/TOC.vue b/packages/@vuepress/core/lib/client/components/TOC.vue
similarity index 100%
rename from packages/@vuepress/core/lib/app/components/TOC.vue
rename to packages/@vuepress/core/lib/client/components/TOC.vue
diff --git a/packages/@vuepress/core/lib/app/dataMixin.js b/packages/@vuepress/core/lib/client/dataMixin.js
similarity index 89%
rename from packages/@vuepress/core/lib/app/dataMixin.js
rename to packages/@vuepress/core/lib/client/dataMixin.js
index 7e0acc5a45..8082156ec1 100644
--- a/packages/@vuepress/core/lib/app/dataMixin.js
+++ b/packages/@vuepress/core/lib/client/dataMixin.js
@@ -1,8 +1,8 @@
/* global VUEPRESS_TEMP_PATH */
-import Vue from 'vue'
+import GLobalVue from 'vue'
-export default function dataMixin (I18n, siteData) {
+export default function dataMixin (I18n, siteData, Vue = GLobalVue) {
prepare(siteData)
Vue.$vuepress.$set('siteData', siteData)
diff --git a/packages/@vuepress/core/lib/app/index.dev.html b/packages/@vuepress/core/lib/client/index.dev.html
similarity index 100%
rename from packages/@vuepress/core/lib/app/index.dev.html
rename to packages/@vuepress/core/lib/client/index.dev.html
diff --git a/packages/@vuepress/core/lib/app/index.ssr.html b/packages/@vuepress/core/lib/client/index.ssr.html
similarity index 100%
rename from packages/@vuepress/core/lib/app/index.ssr.html
rename to packages/@vuepress/core/lib/client/index.ssr.html
diff --git a/packages/@vuepress/core/lib/app/plugins/Store.d.ts b/packages/@vuepress/core/lib/client/plugins/Store.d.ts
similarity index 100%
rename from packages/@vuepress/core/lib/app/plugins/Store.d.ts
rename to packages/@vuepress/core/lib/client/plugins/Store.d.ts
diff --git a/packages/@vuepress/core/lib/app/plugins/Store.js b/packages/@vuepress/core/lib/client/plugins/Store.js
similarity index 100%
rename from packages/@vuepress/core/lib/app/plugins/Store.js
rename to packages/@vuepress/core/lib/client/plugins/Store.js
diff --git a/packages/@vuepress/core/lib/app/plugins/VuePress.d.ts b/packages/@vuepress/core/lib/client/plugins/VuePress.d.ts
similarity index 100%
rename from packages/@vuepress/core/lib/app/plugins/VuePress.d.ts
rename to packages/@vuepress/core/lib/client/plugins/VuePress.d.ts
diff --git a/packages/@vuepress/core/lib/app/plugins/VuePress.js b/packages/@vuepress/core/lib/client/plugins/VuePress.js
similarity index 100%
rename from packages/@vuepress/core/lib/app/plugins/VuePress.js
rename to packages/@vuepress/core/lib/client/plugins/VuePress.js
diff --git a/packages/@vuepress/core/lib/app/redirect.js b/packages/@vuepress/core/lib/client/redirect.js
similarity index 100%
rename from packages/@vuepress/core/lib/app/redirect.js
rename to packages/@vuepress/core/lib/client/redirect.js
diff --git a/packages/@vuepress/core/lib/app/root-mixins/updateMeta.js b/packages/@vuepress/core/lib/client/root-mixins/updateMeta.js
similarity index 100%
rename from packages/@vuepress/core/lib/app/root-mixins/updateMeta.js
rename to packages/@vuepress/core/lib/client/root-mixins/updateMeta.js
diff --git a/packages/@vuepress/core/lib/app/serverEntry.js b/packages/@vuepress/core/lib/client/serverEntry.js
similarity index 100%
rename from packages/@vuepress/core/lib/app/serverEntry.js
rename to packages/@vuepress/core/lib/client/serverEntry.js
diff --git a/packages/@vuepress/core/lib/app/style/config.styl b/packages/@vuepress/core/lib/client/style/config.styl
similarity index 100%
rename from packages/@vuepress/core/lib/app/style/config.styl
rename to packages/@vuepress/core/lib/client/style/config.styl
diff --git a/packages/@vuepress/core/lib/app/util.js b/packages/@vuepress/core/lib/client/util.js
similarity index 100%
rename from packages/@vuepress/core/lib/app/util.js
rename to packages/@vuepress/core/lib/client/util.js
diff --git a/packages/@vuepress/core/lib/dev.js b/packages/@vuepress/core/lib/dev.js
deleted file mode 100644
index c0b728c0e9..0000000000
--- a/packages/@vuepress/core/lib/dev.js
+++ /dev/null
@@ -1,207 +0,0 @@
-'use strict'
-
-module.exports = async (sourceDir, cliOptions = {}, ctx) => {
- const { server, host, port } = await prepareServer(sourceDir, cliOptions, ctx)
- server.listen(port, host, err => {
- if (err) {
- console.log(err)
- }
- })
-}
-
-module.exports.prepare = prepareServer
-
-async function prepareServer (sourceDir, cliOptions = {}, context) {
- const WebpackDevServer = require('webpack-dev-server')
- const { path } = require('@vuepress/shared-utils')
- const webpack = require('webpack')
- const chokidar = require('chokidar')
-
- const prepare = require('./prepare/index')
- const { chalk, fs, logger } = require('@vuepress/shared-utils')
- const HeadPlugin = require('./webpack/HeadPlugin')
- const DevLogPlugin = require('./webpack/DevLogPlugin')
- const createClientConfig = require('./webpack/createClientConfig')
- const { applyUserWebpackConfig } = require('./util/index')
- const { frontmatterEmitter } = require('@vuepress/markdown-loader')
-
- const ctx = context || await prepare(sourceDir, cliOptions, false /* isProd */)
-
- // setup watchers to update options and dynamically generated files
- const update = (reason) => {
- console.log(`Reload due to ${reason}`)
- ctx.pluginAPI.options.updated.syncApply()
- prepare(sourceDir, cliOptions, false /* isProd */).catch(err => {
- console.error(logger.error(chalk.red(err.stack), false))
- })
- }
-
- // Curry update handler by update type
- const spawnUpdate = updateType => file => {
- const target = path.join(sourceDir, file)
- // Bust cache.
- delete require.cache[target]
- update(`${chalk.red(updateType)} ${chalk.cyan(file)}`)
- }
-
- // watch add/remove of files
- const pagesWatcher = chokidar.watch([
- '**/*.md',
- '.vuepress/components/**/*.vue'
- ], {
- cwd: sourceDir,
- ignored: ['.vuepress/**/*.md', 'node_modules'],
- ignoreInitial: true
- })
- pagesWatcher.on('add', spawnUpdate('add'))
- pagesWatcher.on('unlink', spawnUpdate('unlink'))
- pagesWatcher.on('addDir', spawnUpdate('addDir'))
- pagesWatcher.on('unlinkDir', spawnUpdate('unlinkDir'))
-
- const watchFiles = [
- '.vuepress/config.js',
- '.vuepress/config.yml',
- '.vuepress/config.toml'
- ].concat(
- (
- ctx.siteConfig.extraWatchFiles || []
- ).map(file => normalizeWatchFilePath(file, ctx.sourceDir))
- )
-
- logger.debug('watchFiles', watchFiles)
-
- // watch config file
- const configWatcher = chokidar.watch(watchFiles, {
- cwd: sourceDir,
- ignoreInitial: true
- })
- configWatcher.on('change', spawnUpdate('change'))
-
- // also listen for frontmatter changes from markdown files
- frontmatterEmitter.on('update', () => update('frontmatter or headers change'))
-
- // resolve webpack config
- let config = createClientConfig(ctx)
-
- config
- .plugin('html')
- // using a fork of html-webpack-plugin to avoid it requiring webpack
- // internals from an incompatible version.
- .use(require('vuepress-html-webpack-plugin'), [{
- template: ctx.devTemplate
- }])
-
- config
- .plugin('site-data')
- .use(HeadPlugin, [{
- tags: ctx.siteConfig.head || []
- }])
-
- const port = await resolvePort(cliOptions.port || ctx.siteConfig.port)
- const { host, displayHost } = await resolveHost(cliOptions.host || ctx.siteConfig.host)
-
- // debug in a running dev process.
- process.stdin
- && process.stdin.on('data', chunk => {
- const parsed = chunk.toString('utf-8').trim()
- if (parsed === '*') {
- console.log(Object.keys(ctx))
- }
- if (ctx[parsed]) {
- console.log(ctx[parsed])
- }
- })
-
- config
- .plugin('vuepress-log')
- .use(DevLogPlugin, [{
- port,
- displayHost,
- publicPath: ctx.base
- }])
-
- config = config.toConfig()
- const userConfig = ctx.siteConfig.configureWebpack
- if (userConfig) {
- config = applyUserWebpackConfig(userConfig, config, false /* isServer */)
- }
-
- const contentBase = path.resolve(sourceDir, '.vuepress/public')
-
- const serverConfig = Object.assign({
- disableHostCheck: true,
- compress: true,
- clientLogLevel: 'error',
- hot: true,
- quiet: true,
- headers: {
- 'access-control-allow-origin': '*'
- },
- open: cliOptions.open,
- publicPath: ctx.base,
- watchOptions: {
- ignored: [
- /node_modules/,
- `!${ctx.tempPath}/**`
- ]
- },
- historyApiFallback: {
- disableDotRule: true,
- rewrites: [
- { from: /./, to: path.posix.join(ctx.base, 'index.html') }
- ]
- },
- overlay: false,
- host,
- contentBase,
- before (app, server) {
- if (fs.existsSync(contentBase)) {
- app.use(ctx.base, require('express').static(contentBase))
- }
-
- ctx.pluginAPI.options.beforeDevServer.syncApply(app, server)
- },
- after (app, server) {
- ctx.pluginAPI.options.afterDevServer.syncApply(app, server)
- }
- }, ctx.siteConfig.devServer || {})
-
- WebpackDevServer.addDevServerEntrypoints(config, serverConfig)
-
- const compiler = webpack(config)
- const server = new WebpackDevServer(compiler, serverConfig)
-
- return {
- server,
- host,
- port,
- ctx
- }
-}
-
-function resolveHost (host) {
- const defaultHost = 'localhost'
- host = host || defaultHost
- const displayHost = host === defaultHost
- ? 'localhost'
- : host
- return {
- displayHost,
- host
- }
-}
-
-async function resolvePort (port) {
- const portfinder = require('portfinder')
- portfinder.basePort = parseInt(port) || 8080
- port = await portfinder.getPortPromise()
- return port
-}
-
-function normalizeWatchFilePath (filepath, baseDir) {
- const { isAbsolute, relative } = require('path')
- if (isAbsolute(filepath)) {
- return relative(baseDir, filepath)
- }
- return filepath
-}
diff --git a/packages/@vuepress/core/lib/index.js b/packages/@vuepress/core/lib/index.js
index 43a6d0124b..9051524575 100644
--- a/packages/@vuepress/core/lib/index.js
+++ b/packages/@vuepress/core/lib/index.js
@@ -1,5 +1,26 @@
'use strict'
-exports.dev = require('./dev')
-exports.build = require('./build')
+const App = require('./node/App')
+const { logger } = require('@vuepress/shared-utils')
+
+function createApp (options) {
+ logger.wait('Extracting site metadata...')
+ return new App(options)
+}
+
+async function dev (options) {
+ const app = createApp(options)
+ await app.process()
+ await app.dev()
+}
+
+async function build (options) {
+ const app = createApp(options)
+ await app.process()
+ await app.build()
+}
+
+exports.createApp = createApp
+exports.dev = dev
+exports.build = build
exports.eject = require('./eject')
diff --git a/packages/@vuepress/core/lib/prepare/AppContext.js b/packages/@vuepress/core/lib/node/App.js
similarity index 73%
rename from packages/@vuepress/core/lib/prepare/AppContext.js
rename to packages/@vuepress/core/lib/node/App.js
index e7d71bb51a..906316f2ef 100755
--- a/packages/@vuepress/core/lib/prepare/AppContext.js
+++ b/packages/@vuepress/core/lib/node/App.js
@@ -16,18 +16,21 @@ const {
const Page = require('./Page')
const ClientComputedMixin = require('./ClientComputedMixin')
-const PluginAPI = require('../plugin-api/index')
+const PluginAPI = require('./plugin-api')
+const DevProcess = require('./dev')
+const BuildProcess = require('./build')
+const createTemp = require('./createTemp')
/**
- * Expose AppContext.
+ * Expose VuePressApp.
*/
-module.exports = class AppContext {
+module.exports = class App {
static getInstance (...args) {
- if (!AppContext._instance) {
- AppContext._instance = new AppContext(...args)
+ if (!App._instance) {
+ App._instance = new App(...args)
}
- return AppContext._instance
+ return App._instance
}
/**
@@ -35,24 +38,23 @@ module.exports = class AppContext {
*
* @param {string} sourceDir
* @param {{
- * isProd: boolean,
* plugins: pluginsConfig,
* theme: themeNameConfig
* temp: string
* }} options
*/
- constructor (sourceDir, cliOptions = {}, isProd) {
- logger.debug('sourceDir', sourceDir)
- this.sourceDir = sourceDir
- this.cliOptions = cliOptions
- this.isProd = isProd
+ constructor (options = {}) {
+ this.options = options
+ this.sourceDir = this.options.sourceDir || path.join(__dirname, 'docs.fallback')
+ logger.debug('sourceDir', this.sourceDir)
- const { tempPath, writeTemp } = createTemp(cliOptions.temp)
+ const { tempPath, writeTemp } = createTemp(options.temp)
this.tempPath = tempPath
this.writeTemp = writeTemp
- this.vuepressDir = path.resolve(sourceDir, '.vuepress')
+ this.vuepressDir = path.resolve(this.sourceDir, '.vuepress')
+ this.libDir = path.join(__dirname, '../')
}
/**
@@ -63,9 +65,14 @@ module.exports = class AppContext {
*/
resolveConfigAndInitialize () {
- this.siteConfig = loadConfig(this.vuepressDir)
- if (isFunction(this.siteConfig)) {
- this.siteConfig = this.siteConfig(this)
+ if (this.options.siteConfig) {
+ this.siteConfig = this.options.siteConfig
+ } else {
+ let siteConfig = loadConfig(this.vuepressDir)
+ if (isFunction(siteConfig)) {
+ siteConfig = siteConfig(this)
+ }
+ this.siteConfig = siteConfig
}
// TODO custom cwd.
@@ -74,7 +81,7 @@ module.exports = class AppContext {
this.base = this.siteConfig.base || '/'
this.themeConfig = this.siteConfig.themeConfig || {}
- const rawOutDir = this.cliOptions.dest || this.siteConfig.dest
+ const rawOutDir = this.options.dest || this.siteConfig.dest
this.outDir = rawOutDir
? require('path').resolve(this.cwd, rawOutDir)
: require('path').resolve(this.sourceDir, '.vuepress/dist')
@@ -92,7 +99,6 @@ module.exports = class AppContext {
async process () {
this.resolveConfigAndInitialize()
- this.resolveCacheLoaderOptions()
this.normalizeHeadTagUrls()
this.themeAPI = loadTheme(this)
this.resolveTemplates()
@@ -105,18 +111,18 @@ module.exports = class AppContext {
this.markdown = createMarkdown(this)
await this.resolvePages()
- await this.pluginAPI.options.additionalPages.apply(this)
+
+ await this.pluginAPI.applyAsyncOption('additionalPages', this)
await Promise.all(
- this.pluginAPI.options.additionalPages.appliedValues.map(async (options) => {
+ this.pluginAPI.getOption('additionalPages').appliedValues.map(async (options) => {
await this.addPage(options)
})
)
-
- await this.pluginAPI.options.ready.apply()
+ await this.pluginAPI.applyAsyncOption('ready')
await Promise.all([
- this.pluginAPI.options.clientDynamicModules.apply(this),
- this.pluginAPI.options.enhanceAppFiles.apply(this),
- this.pluginAPI.options.globalUIComponents.apply(this)
+ this.pluginAPI.applyAsyncOption('clientDynamicModules', this),
+ this.pluginAPI.applyAsyncOption('enhanceAppFiles', this),
+ this.pluginAPI.applyAsyncOption('globalUIComponents', this)
])
}
@@ -138,17 +144,17 @@ module.exports = class AppContext {
this.pluginAPI
// internl core plugins
- .use(require('../internal-plugins/siteData'))
- .use(require('../internal-plugins/routes'))
- .use(require('../internal-plugins/rootMixins'))
- .use(require('../internal-plugins/enhanceApp'))
- .use(require('../internal-plugins/palette'))
- .use(require('../internal-plugins/style'))
- .use(require('../internal-plugins/layoutComponents'))
- .use(require('../internal-plugins/pageComponents'))
- .use(require('../internal-plugins/transformModule'))
- .use(require('../internal-plugins/dataBlock'))
- .use(require('../internal-plugins/frontmatterBlock'))
+ .use(require('./internal-plugins/siteData'))
+ .use(require('./internal-plugins/routes'))
+ .use(require('./internal-plugins/rootMixins'))
+ .use(require('./internal-plugins/enhanceApp'))
+ .use(require('./internal-plugins/palette'))
+ .use(require('./internal-plugins/style'))
+ .use(require('./internal-plugins/layoutComponents'))
+ .use(require('./internal-plugins/pageComponents'))
+ .use(require('./internal-plugins/transformModule'))
+ .use(require('./internal-plugins/dataBlock'))
+ .use(require('./internal-plugins/frontmatterBlock'))
.use('@vuepress/container', {
type: 'slot',
before: info => ``,
@@ -176,7 +182,7 @@ module.exports = class AppContext {
*/
applyUserPlugins () {
- this.pluginAPI.useByPluginsConfig(this.cliOptions.plugins)
+ this.pluginAPI.useByPluginsConfig(this.options.plugins)
if (this.themeAPI.existsParentTheme) {
this.pluginAPI.use(this.themeAPI.parentTheme.entry)
}
@@ -215,7 +221,7 @@ module.exports = class AppContext {
*/
resolveCacheLoaderOptions () {
- Object.assign(this, (getCacheLoaderOptions(this.siteConfig, this.cliOptions, this.cwd, this.isProd)))
+ Object.assign(this, (getCacheLoaderOptions(this.siteConfig, this.options, this.cwd, this.isProd)))
}
/**
@@ -235,7 +241,7 @@ module.exports = class AppContext {
this.devTemplate = this.resolveCommonAgreementFilePath(
'devTemplate',
{
- defaultValue: path.resolve(__dirname, '../app/index.dev.html'),
+ defaultValue: this.getLibFilePath('client/index.dev.html'),
siteAgreement: 'templates/dev.html',
themeAgreement: 'templates/dev.html'
}
@@ -244,7 +250,7 @@ module.exports = class AppContext {
this.ssrTemplate = this.resolveCommonAgreementFilePath(
'ssrTemplate',
{
- defaultValue: path.resolve(__dirname, '../app/index.ssr.html'),
+ defaultValue: this.getLibFilePath('client/index.ssr.html'),
siteAgreement: 'templates/ssr.html',
themeAgreement: 'templates/ssr.html'
}
@@ -265,7 +271,7 @@ module.exports = class AppContext {
this.globalLayout = this.resolveCommonAgreementFilePath(
'globalLayout',
{
- defaultValue: path.resolve(__dirname, `../app/components/GlobalLayout.vue`),
+ defaultValue: this.getLibFilePath('client/components/GlobalLayout.vue'),
siteAgreement: `components/GlobalLayout.vue`,
themeAgreement: `layouts/GlobalLayout.vue`
}
@@ -343,7 +349,7 @@ module.exports = class AppContext {
await page.process({
markdown: this.markdown,
computed: new this.ClientComputedMixinConstructor(),
- enhancers: this.pluginAPI.options.extendPageData.items
+ enhancers: this.pluginAPI.getOption('extendPageData').items
})
this.pages.push(page)
}
@@ -425,45 +431,52 @@ module.exports = class AppContext {
locales
}
}
-}
-/**
- * Create a dynamic temp utility context that allow to lanuch
- * multiple apps with isolated context at the same time.
- * @param tempPath
- * @returns {{
- * writeTemp: (function(file: string, content: string): string),
- * tempPath: string
- * }}
- */
+ /**
+ * Get file path in core lib
+ *
+ * @param relative
+ * @returns {string}
+ * @api public
+ */
-function createTemp (tempPath) {
- if (!tempPath) {
- tempPath = path.resolve(__dirname, '../../.temp')
- } else {
- tempPath = path.resolve(tempPath)
+ getLibFilePath (relative) {
+ return path.join(this.libDir, relative)
}
- if (!fs.existsSync(tempPath)) {
- fs.ensureDirSync(tempPath)
- } else {
- fs.emptyDirSync(tempPath)
- }
+ /**
+ * Start a dev process with correct app context
+ *
+ * @returns {Promise}
+ * @api public
+ */
- logger.debug(`Temp directory: ${chalk.gray(tempPath)}`)
- const tempCache = new Map()
-
- async function writeTemp (file, content) {
- const destPath = path.join(tempPath, file)
- await fs.ensureDir(path.parse(destPath).dir)
- // cache write to avoid hitting the dist if it didn't change
- const cached = tempCache.get(file)
- if (cached !== content) {
- await fs.writeFile(destPath, content)
- tempCache.set(file, content)
- }
- return destPath
+ async dev () {
+ this.isProd = false
+ this.devProcess = new DevProcess(this)
+ await this.devProcess.process()
+
+ this.devProcess
+ .on('fileChanged', ({ type, target }) => {
+ console.log(`Reload due to ${chalk.red(type)} ${chalk.cyan(target)}`)
+ this.process()
+ })
+ .createServer()
+ .listen()
}
- return { writeTemp, tempPath }
+ /**
+ * Start a build process with correct app context
+ *
+ * @returns {Promise}
+ * @api public
+ */
+
+ async build () {
+ this.isProd = true
+ this.buildProcess = new BuildProcess(this)
+ await this.buildProcess.process()
+ await this.buildProcess.render()
+ }
}
+
diff --git a/packages/@vuepress/core/lib/prepare/CacheLoader.js b/packages/@vuepress/core/lib/node/CacheLoader.js
similarity index 89%
rename from packages/@vuepress/core/lib/prepare/CacheLoader.js
rename to packages/@vuepress/core/lib/node/CacheLoader.js
index 7d10291463..77f8d6d723 100644
--- a/packages/@vuepress/core/lib/prepare/CacheLoader.js
+++ b/packages/@vuepress/core/lib/node/CacheLoader.js
@@ -12,12 +12,12 @@ const {
/**
* Get cache directory and cache identifier via config.
* @param {object} siteConfig
- * @param {object} cliOptions
+ * @param {object} options
*/
-exports.getCacheLoaderOptions = function (siteConfig, cliOptions, cwd, isProd) {
+exports.getCacheLoaderOptions = function (siteConfig, options, cwd, isProd) {
const defaultCacheDirectory = path.resolve(__dirname, '../../node_modules/.cache/vuepress')
- let cache = cliOptions.cache || siteConfig.cache || defaultCacheDirectory
+ let cache = options.cache || siteConfig.cache || defaultCacheDirectory
if (isBoolean(cache)) {
if (cache === true) {
diff --git a/packages/@vuepress/core/lib/prepare/ClientComputedMixin.js b/packages/@vuepress/core/lib/node/ClientComputedMixin.js
similarity index 100%
rename from packages/@vuepress/core/lib/prepare/ClientComputedMixin.js
rename to packages/@vuepress/core/lib/node/ClientComputedMixin.js
diff --git a/packages/@vuepress/core/lib/prepare/Page.js b/packages/@vuepress/core/lib/node/Page.js
similarity index 99%
rename from packages/@vuepress/core/lib/prepare/Page.js
rename to packages/@vuepress/core/lib/node/Page.js
index de83e00523..e04bd50f72 100644
--- a/packages/@vuepress/core/lib/prepare/Page.js
+++ b/packages/@vuepress/core/lib/node/Page.js
@@ -4,7 +4,7 @@
* Module dependencies.
*/
-const { inferDate, DATE_RE } = require('../util/index')
+const { inferDate, DATE_RE } = require('./util/index')
const {
fs,
path,
diff --git a/packages/@vuepress/core/__tests__/plugin-api/AsyncOption.spec.js b/packages/@vuepress/core/lib/node/__tests__/plugin-api/AsyncOption.spec.js
similarity index 90%
rename from packages/@vuepress/core/__tests__/plugin-api/AsyncOption.spec.js
rename to packages/@vuepress/core/lib/node/__tests__/plugin-api/AsyncOption.spec.js
index 357f1fb157..807d7967ef 100644
--- a/packages/@vuepress/core/__tests__/plugin-api/AsyncOption.spec.js
+++ b/packages/@vuepress/core/lib/node/__tests__/plugin-api/AsyncOption.spec.js
@@ -1,4 +1,4 @@
-const AsyncOption = require('../../lib/plugin-api/abstract/AsyncOption')
+const AsyncOption = require('../../plugin-api/abstract/AsyncOption')
describe('AsyncOption', () => {
test('parallelApply', async () => {
diff --git a/packages/@vuepress/core/__tests__/plugin-api/Option.spec.js b/packages/@vuepress/core/lib/node/__tests__/plugin-api/Option.spec.js
similarity index 97%
rename from packages/@vuepress/core/__tests__/plugin-api/Option.spec.js
rename to packages/@vuepress/core/lib/node/__tests__/plugin-api/Option.spec.js
index e00a73608c..978a9f742b 100644
--- a/packages/@vuepress/core/__tests__/plugin-api/Option.spec.js
+++ b/packages/@vuepress/core/lib/node/__tests__/plugin-api/Option.spec.js
@@ -1,4 +1,4 @@
-import Option from '../../lib/plugin-api/abstract/Option'
+import Option from '../../plugin-api/abstract/Option'
describe('Option', () => {
test('key', () => {
diff --git a/packages/@vuepress/core/__tests__/plugin-api/PluginAPI.spec.js b/packages/@vuepress/core/lib/node/__tests__/plugin-api/PluginAPI.spec.js
similarity index 95%
rename from packages/@vuepress/core/__tests__/plugin-api/PluginAPI.spec.js
rename to packages/@vuepress/core/lib/node/__tests__/plugin-api/PluginAPI.spec.js
index 7c580aacde..2f21ad454f 100644
--- a/packages/@vuepress/core/__tests__/plugin-api/PluginAPI.spec.js
+++ b/packages/@vuepress/core/lib/node/__tests__/plugin-api/PluginAPI.spec.js
@@ -2,8 +2,8 @@ jest.mock('vuepress-plugin-a')
jest.mock('vuepress-plugin-b')
jest.mock('@org/vuepress-plugin-a')
-import PluginAPI from '../../lib/plugin-api/index'
-import { PLUGIN_OPTION_MAP } from '../../lib/plugin-api/constants'
+import PluginAPI from '../../plugin-api/index'
+import { PLUGIN_OPTION_MAP } from '../../plugin-api/constants'
describe('Plugin', () => {
test('registerOption', () => {
diff --git a/packages/@vuepress/core/__tests__/plugin-api/PluginUtil.spec.js b/packages/@vuepress/core/lib/node/__tests__/plugin-api/PluginUtil.spec.js
similarity index 76%
rename from packages/@vuepress/core/__tests__/plugin-api/PluginUtil.spec.js
rename to packages/@vuepress/core/lib/node/__tests__/plugin-api/PluginUtil.spec.js
index 211c2fbf6c..8d28f27aa0 100644
--- a/packages/@vuepress/core/__tests__/plugin-api/PluginUtil.spec.js
+++ b/packages/@vuepress/core/lib/node/__tests__/plugin-api/PluginUtil.spec.js
@@ -1,31 +1,31 @@
-import { flattenPlugin } from '../../lib/plugin-api/util'
+import { flattenPlugin } from '../../plugin-api/util'
describe('flattenPlugin', () => {
test('should hydrate plugin correctly', () => {
- const plugin = { name: 'a', shortcut: 'a', module: { enhanceAppFiles: 'file' }}
+ const plugin = { name: 'a', shortcut: 'a', entry: { enhanceAppFiles: 'file' }}
const hydratedPlugin = flattenPlugin(plugin, {}, {})
expect(hydratedPlugin.name).toBe('a')
- expect(hydratedPlugin.shortcut).toBe('a')
+ expect(hydratedPlugin.shortcut).toBe(null)
expect(hydratedPlugin.enabled).toBe(true)
expect(hydratedPlugin.enhanceAppFiles).toBe('file')
})
test('should set \'enabled\' to false when \'pluginOptions\' is set to false.', () => {
- const plugin = { name: 'a', shortcut: 'a', module: {}}
+ const plugin = { name: 'a', shortcut: 'a', entry: {}}
const hydratedPlugin = flattenPlugin(plugin, false, {})
expect(hydratedPlugin.name).toBe('a')
- expect(hydratedPlugin.shortcut).toBe('a')
+ expect(hydratedPlugin.shortcut).toBe(null)
expect(hydratedPlugin.enabled).toBe(false)
})
test('should flatten functional plugin correctly.', () => {
const config = jest.fn(() => ({ enhanceAppFiles: 'file' }))
- const plugin = { name: 'a', shortcut: 'a', module: config }
+ const plugin = { name: 'a', shortcut: 'a', entry: config }
const pluginOptions = {}
const pluginContext = {}
const hydratedPlugin = flattenPlugin(plugin, pluginOptions, pluginContext)
expect(hydratedPlugin.name).toBe('a')
- expect(hydratedPlugin.shortcut).toBe('a')
+ expect(hydratedPlugin.shortcut).toBe(null)
expect(hydratedPlugin.enabled).toBe(true)
expect(hydratedPlugin.enhanceAppFiles).toBe('file')
expect(config.mock.calls).toHaveLength(1)
@@ -35,7 +35,7 @@ describe('flattenPlugin', () => {
test('should flatten functional plugin correctly - options defaults to \'{}\'.', () => {
const config = jest.fn(() => ({ enhanceAppFiles: 'file' }))
- const plugin = { name: 'a', shortcut: 'a', module: config }
+ const plugin = { name: 'a', shortcut: 'a', entry: config }
const pluginOptions = undefined
const pluginContext = {}
flattenPlugin(plugin, pluginOptions, pluginContext)
diff --git a/packages/@vuepress/core/__tests__/prepare/prepare.spec.js b/packages/@vuepress/core/lib/node/__tests__/prepare/App.spec.js
similarity index 70%
rename from packages/@vuepress/core/__tests__/prepare/prepare.spec.js
rename to packages/@vuepress/core/lib/node/__tests__/prepare/App.spec.js
index 0e0ef5837b..f33eef167a 100644
--- a/packages/@vuepress/core/__tests__/prepare/prepare.spec.js
+++ b/packages/@vuepress/core/lib/node/__tests__/prepare/App.spec.js
@@ -1,5 +1,5 @@
const { fs, path } = require('@vuepress/shared-utils')
-const prepare = require('../../lib/prepare')
+const App = require('../../App')
const docsBaseDir = path.resolve(__dirname, 'fixtures')
const docsModeNames = fs.readdirSync(docsBaseDir)
@@ -9,12 +9,16 @@ const docsModes = docsModeNames.map(name => {
return { name, docsPath, docsTempPath }
})
-describe('prepare', () => {
+describe('App', () => {
test('should not throw error', async () => {
await Promise.all(docsModes.map(async ({ name, docsPath, docsTempPath }) => {
await fs.ensureDir(docsTempPath)
- const context = await prepare(docsPath, { theme: '@vuepress/default', temp: docsTempPath })
- expect(context.sourceDir).toBe(docsPath)
+ const app = new App({
+ sourceDir: docsPath,
+ theme: '@vuepress/default',
+ emp: docsTempPath
+ })
+ expect(app.sourceDir).toBe(docsPath)
}))
})
})
diff --git a/packages/@vuepress/core/__tests__/prepare/Page.spec.js b/packages/@vuepress/core/lib/node/__tests__/prepare/Page.spec.js
similarity index 80%
rename from packages/@vuepress/core/__tests__/prepare/Page.spec.js
rename to packages/@vuepress/core/lib/node/__tests__/prepare/Page.spec.js
index 294ae9c790..2f3b4b6f30 100644
--- a/packages/@vuepress/core/__tests__/prepare/Page.spec.js
+++ b/packages/@vuepress/core/lib/node/__tests__/prepare/Page.spec.js
@@ -1,19 +1,28 @@
-const Page = require('../../lib/prepare/Page')
+const Page = require('../../Page')
+const App = require('../../App')
+
const {
- getComputed,
getMarkdown,
getDocument,
readFile
} = require('./util')
describe('Page', () => {
+ let app
+ let computed
+
+ beforeAll(async () => {
+ app = new App()
+ await app.process()
+ computed = new app.ClientComputedMixinConstructor()
+ })
+
test('pure route', async () => {
- const page = new Page({ path: '/' })
+ const page = new Page({ path: '/' }, app)
expect(page.path).toBe('/')
expect(page.regularPath).toBe('/')
- const computed = getComputed()
await page.process({ computed })
expect(page.path).toBe('/')
@@ -22,7 +31,7 @@ describe('Page', () => {
test('pure route - encodeURI', async () => {
const path = '/尤/'
- const page = new Page({ path })
+ const page = new Page({ path }, app)
expect(page.path).toBe(encodeURI(path))
expect(page.regularPath).toBe(encodeURI(path))
@@ -33,7 +42,7 @@ describe('Page', () => {
const page = new Page({
path: '/',
frontmatter
- })
+ }, app)
expect(page.frontmatter).toBe(frontmatter)
})
@@ -42,15 +51,16 @@ describe('Page', () => {
const page = new Page({
path: '/',
frontmatter
- })
+ }, app)
expect(page.frontmatter.title).toBe('alpha')
- const computed = getComputed()
const enhancers = [
{
name: 'plugin-a',
- value: page => { page.frontmatter.title = 'beta' }
+ value: page => {
+ page.frontmatter.title = 'beta'
+ }
}
]
await page.process({ computed, enhancers })
@@ -60,14 +70,13 @@ describe('Page', () => {
test('markdown page - pointing to a markdown file', async () => {
const { relative, filePath } = getDocument('README.md')
- const page = new Page({ filePath, relative })
+ const page = new Page({ filePath, relative }, app)
expect(page._filePath).toBe(filePath)
expect(page.regularPath).toBe('/')
expect(page.path).toBe('/')
expect(page.frontmatter).toEqual({})
- const computed = getComputed()
const markdown = getMarkdown()
await page.process({ computed, markdown })
@@ -79,14 +88,13 @@ describe('Page', () => {
test('markdown page - pointing to a markdown file with frontmatter', async () => {
const { relative, filePath } = getDocument('alpha.md')
- const page = new Page({ filePath, relative })
+ const page = new Page({ filePath, relative }, app)
expect(page._filePath).toBe(filePath)
expect(page.regularPath).toBe('/alpha.html')
expect(page.path).toBe('/alpha.html')
expect(page.frontmatter).toEqual({})
- const computed = getComputed()
const markdown = getMarkdown()
await page.process({ computed, markdown })
diff --git a/packages/@vuepress/core/__tests__/prepare/fixtures/docs-config/.vuepress/config.js b/packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs-config/.vuepress/config.js
similarity index 100%
rename from packages/@vuepress/core/__tests__/prepare/fixtures/docs-config/.vuepress/config.js
rename to packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs-config/.vuepress/config.js
diff --git a/packages/@vuepress/core/__tests__/prepare/fixtures/docs-config/README.md b/packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs-config/README.md
similarity index 100%
rename from packages/@vuepress/core/__tests__/prepare/fixtures/docs-config/README.md
rename to packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs-config/README.md
diff --git a/packages/@vuepress/core/__tests__/prepare/fixtures/docs-i18n/.vuepress/config.js b/packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs-i18n/.vuepress/config.js
similarity index 100%
rename from packages/@vuepress/core/__tests__/prepare/fixtures/docs-i18n/.vuepress/config.js
rename to packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs-i18n/.vuepress/config.js
diff --git a/packages/@vuepress/core/__tests__/prepare/fixtures/docs-i18n/README.md b/packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs-i18n/README.md
similarity index 100%
rename from packages/@vuepress/core/__tests__/prepare/fixtures/docs-i18n/README.md
rename to packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs-i18n/README.md
diff --git a/packages/@vuepress/core/__tests__/prepare/fixtures/docs-i18n/zh/README.md b/packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs-i18n/zh/README.md
similarity index 100%
rename from packages/@vuepress/core/__tests__/prepare/fixtures/docs-i18n/zh/README.md
rename to packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs-i18n/zh/README.md
diff --git a/packages/@vuepress/core/__tests__/prepare/fixtures/docs-local-theme/.vuepress/config.js b/packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs-local-theme/.vuepress/config.js
similarity index 100%
rename from packages/@vuepress/core/__tests__/prepare/fixtures/docs-local-theme/.vuepress/config.js
rename to packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs-local-theme/.vuepress/config.js
diff --git a/packages/@vuepress/core/__tests__/prepare/fixtures/docs-local-theme/.vuepress/theme/Layout.vue b/packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs-local-theme/.vuepress/theme/Layout.vue
similarity index 100%
rename from packages/@vuepress/core/__tests__/prepare/fixtures/docs-local-theme/.vuepress/theme/Layout.vue
rename to packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs-local-theme/.vuepress/theme/Layout.vue
diff --git a/packages/@vuepress/core/__tests__/prepare/fixtures/docs-local-theme/README.md b/packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs-local-theme/README.md
similarity index 100%
rename from packages/@vuepress/core/__tests__/prepare/fixtures/docs-local-theme/README.md
rename to packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs-local-theme/README.md
diff --git a/packages/@vuepress/core/__tests__/prepare/fixtures/docs/README.md b/packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs/README.md
similarity index 100%
rename from packages/@vuepress/core/__tests__/prepare/fixtures/docs/README.md
rename to packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs/README.md
diff --git a/packages/@vuepress/core/__tests__/prepare/fixtures/docs/alpha.md b/packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs/alpha.md
similarity index 100%
rename from packages/@vuepress/core/__tests__/prepare/fixtures/docs/alpha.md
rename to packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs/alpha.md
diff --git a/packages/@vuepress/core/__tests__/prepare/util.js b/packages/@vuepress/core/lib/node/__tests__/prepare/util.js
similarity index 55%
rename from packages/@vuepress/core/__tests__/prepare/util.js
rename to packages/@vuepress/core/lib/node/__tests__/prepare/util.js
index ef66db6820..79c42a59ee 100644
--- a/packages/@vuepress/core/__tests__/prepare/util.js
+++ b/packages/@vuepress/core/lib/node/__tests__/prepare/util.js
@@ -1,15 +1,5 @@
const { fs, path } = require('@vuepress/shared-utils')
-const AppContext = require('../../lib/prepare/AppContext')
-const createMarkdown = require('../../../markdown/index')
-
-function getAppContext () {
- return new AppContext('.')
-}
-
-function getComputed () {
- const context = getAppContext()
- return new context.ClientComputedMixinConstructor()
-}
+const createMarkdown = require('../../../../../markdown/index')
const docsBaseDir = path.resolve(__dirname, 'fixtures/docs')
@@ -25,8 +15,6 @@ const getMarkdown = createMarkdown
const readFile = async filePath => await fs.readFile(filePath, 'utf-8')
module.exports = {
- getAppContext,
- getComputed,
getMarkdown,
getDocument,
readFile
diff --git a/packages/@vuepress/core/__tests__/theme-api/fixtures/theme/Layout.vue b/packages/@vuepress/core/lib/node/__tests__/theme-api/fixtures/theme/Layout.vue
similarity index 100%
rename from packages/@vuepress/core/__tests__/theme-api/fixtures/theme/Layout.vue
rename to packages/@vuepress/core/lib/node/__tests__/theme-api/fixtures/theme/Layout.vue
diff --git a/packages/@vuepress/core/__tests__/theme-api/fixtures/theme/components/Home.vue b/packages/@vuepress/core/lib/node/__tests__/theme-api/fixtures/theme/components/Home.vue
similarity index 100%
rename from packages/@vuepress/core/__tests__/theme-api/fixtures/theme/components/Home.vue
rename to packages/@vuepress/core/lib/node/__tests__/theme-api/fixtures/theme/components/Home.vue
diff --git a/packages/@vuepress/core/__tests__/theme-api/index.spec.js b/packages/@vuepress/core/lib/node/__tests__/theme-api/index.spec.js
similarity index 93%
rename from packages/@vuepress/core/__tests__/theme-api/index.spec.js
rename to packages/@vuepress/core/lib/node/__tests__/theme-api/index.spec.js
index a8e6c7bdd4..89dccf9835 100644
--- a/packages/@vuepress/core/__tests__/theme-api/index.spec.js
+++ b/packages/@vuepress/core/lib/node/__tests__/theme-api/index.spec.js
@@ -1,7 +1,7 @@
jest.mock('vuepress-theme-parent')
jest.mock('vuepress-theme-child')
-import ThemeAPI from '../../lib/theme-api'
+import ThemeAPI from '../../theme-api'
import { resolve } from 'path'
const theme = {
diff --git a/packages/@vuepress/core/lib/node/build/index.js b/packages/@vuepress/core/lib/node/build/index.js
new file mode 100644
index 0000000000..666e0f6acc
--- /dev/null
+++ b/packages/@vuepress/core/lib/node/build/index.js
@@ -0,0 +1,273 @@
+'use strict'
+
+const EventEmitter = require('events').EventEmitter
+const webpack = require('webpack')
+const readline = require('readline')
+const escape = require('escape-html')
+
+const { chalk, fs, path, logger, env, performance } = require('@vuepress/shared-utils')
+const createClientConfig = require('../webpack/createClientConfig')
+const createServerConfig = require('../webpack/createServerConfig')
+const { createBundleRenderer } = require('vue-server-renderer')
+const { normalizeHeadTag, applyUserWebpackConfig } = require('../util/index')
+
+/**
+ * Expose Build Process Class.
+ */
+
+module.exports = class Build extends EventEmitter {
+ constructor (context) {
+ super()
+ process.env.NODE_ENV = 'production'
+ this.context = context
+ this.outDir = this.context.outDir
+ }
+
+ /**
+ * Doing somthing before render pages, e.g. validate and empty output directory,
+ * prepare webpack config.
+ *
+ * @returns {Promise}
+ * @api public
+ */
+
+ async process () {
+ if (this.context.cwd === this.outDir) {
+ throw new Error('Unexpected option: "outDir" cannot be set to the current working directory')
+ }
+
+ this.context.resolveCacheLoaderOptions()
+ await fs.emptyDir(this.outDir)
+ logger.debug('Dist directory: ' + chalk.gray(this.outDir))
+ this.prepareWebpackConfig()
+ }
+
+ /**
+ * Compile and render pages.
+ *
+ * @returns {Promise}
+ * @api public
+ */
+
+ async render () {
+ logger.wait('Extracting site metadata...')
+
+ // compile!
+ const stats = await compile([this.clientConfig, this.serverConfig])
+ const serverBundle = require(path.resolve(this.outDir, 'manifest/server.json'))
+ const clientManifest = require(path.resolve(this.outDir, 'manifest/client.json'))
+
+ // remove manifests after loading them.
+ await fs.remove(path.resolve(this.outDir, 'manifest'))
+
+ // ref: https://github.com/vuejs/vuepress/issues/1367
+ if (!this.clientConfig.devtool && (!this.clientConfig.plugins
+ || !this.clientConfig.plugins.some(p =>
+ p instanceof webpack.SourceMapDevToolPlugin
+ || p instanceof webpack.EvalSourceMapDevToolPlugin
+ ))) {
+ await workaroundEmptyStyleChunk(stats, this.outDir)
+ }
+
+ // create server renderer using built manifests
+ this.renderer = createBundleRenderer(serverBundle, {
+ clientManifest,
+ runInNewContext: false,
+ inject: false,
+ shouldPrefetch: this.context.siteConfig.shouldPrefetch || (() => true),
+ template: await fs.readFile(this.context.ssrTemplate, 'utf-8')
+ })
+
+ // pre-render head tags from user config
+ this.userHeadTags = (this.context.siteConfig.head || [])
+ .map(renderHeadTag)
+ .join('\n ')
+
+ // if the user does not have a custom 404.md, generate the theme's default
+ if (!this.context.pages.some(p => p.path === '/404.html')) {
+ this.context.addPage({ path: '/404.html' })
+ }
+
+ // render pages
+ logger.wait('Rendering static HTML...')
+
+ const pagePaths = []
+ for (const page of this.context.pages) {
+ pagePaths.push(await this.renderPage(page))
+ }
+
+ readline.clearLine(process.stdout, 0)
+ readline.cursorTo(process.stdout, 0)
+
+ await this.context.pluginAPI.applyAsyncOption('generated', pagePaths)
+
+ // DONE.
+ const relativeDir = path.relative(this.context.cwd, this.outDir)
+ logger.success(`Generated static files in ${chalk.cyan(relativeDir)}.`)
+ const { duration } = performance.stop()
+ logger.developer(`It took a total of ${chalk.cyan(`${duration}ms`)} to run the ${chalk.cyan('vuepress build')}.`)
+ console.log()
+ }
+
+ /**
+ * Prepare webpack config under build.
+ *
+ * @api private
+ */
+
+ prepareWebpackConfig () {
+ this.clientConfig = createClientConfig(this.context).toConfig()
+ this.serverConfig = createServerConfig(this.context).toConfig()
+
+ const userConfig = this.context.siteConfig.configureWebpack
+ if (userConfig) {
+ this.clientConfig = applyUserWebpackConfig(userConfig, this.clientConfig, false)
+ this.serverConfig = applyUserWebpackConfig(userConfig, this.serverConfig, true)
+ }
+ }
+
+ /**
+ * Render page
+ *
+ * @param {Page} page
+ * @returns {Promise}
+ * @api private
+ */
+
+ async renderPage (page) {
+ const pagePath = page.path
+ readline.clearLine(process.stdout, 0)
+ readline.cursorTo(process.stdout, 0)
+ process.stdout.write(`Rendering page: ${pagePath}`)
+
+ // #565 Avoid duplicate description meta at SSR.
+ const meta = (page.frontmatter && page.frontmatter.meta || []).filter(item => item.name !== 'description')
+ const pageMeta = renderPageMeta(meta)
+
+ const context = {
+ url: pagePath,
+ userHeadTags: this.userHeadTags,
+ pageMeta,
+ title: 'VuePress',
+ lang: 'en',
+ description: ''
+ }
+
+ let html
+ try {
+ html = await this.renderer.renderToString(context)
+ } catch (e) {
+ console.error(logger.error(chalk.red(`Error rendering ${pagePath}:`), false))
+ throw e
+ }
+ const filename = decodeURIComponent(pagePath.replace(/\/$/, '/index.html').replace(/^\//, ''))
+ const filePath = path.resolve(this.outDir, filename)
+ await fs.ensureDir(path.dirname(filePath))
+ await fs.writeFile(filePath, html)
+ return filePath
+ }
+}
+
+/**
+ * Compile a webpack application and return stats json.
+ *
+ * @param {Object} config
+ * @returns {Promise