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 ? `` : ``}` - } - - 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 => `