From f39b6932b1dfba653519103944277d3e6d72b07d Mon Sep 17 00:00:00 2001 From: ULIVZ <472590061@qq.com> Date: Tue, 4 Dec 2018 23:54:41 +0800 Subject: [PATCH 01/10] chore: show-help script --- package.json | 1 + packages/docs/package.json | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index d204b21bbc..3c8473c60d 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "boot": "node scripts/bootstrap.js", "dev": "yarn workspace docs dev", "build": "yarn workspace docs build", + "show-help": "yarn workspace docs show-help", "dev:blog": "yarn workspace blog dev", "build:blog": "yarn workspace blog build", "register-vuepress": "lerna exec --scope vuepress -- yarn link", diff --git a/packages/docs/package.json b/packages/docs/package.json index 771ad7a83f..175e3ef5f5 100644 --- a/packages/docs/package.json +++ b/packages/docs/package.json @@ -5,7 +5,8 @@ "description": "docs of VuePress", "scripts": { "dev": "vuepress dev docs --temp .temp", - "build": "vuepress build docs --temp .temp" + "build": "vuepress build docs --temp .temp", + "show-help": "vuepress --help" }, "repository": { "type": "git", From bc57ec96edaa1ae26703a2ce8b7f4ee017d3ec3f Mon Sep 17 00:00:00 2001 From: ULIVZ <472590061@qq.com> Date: Wed, 5 Dec 2018 01:58:40 +0800 Subject: [PATCH 02/10] feat: new plugin option API - 'registerCommand' Internal changes: 1. Removing '@vuepress/cli' package --- .gitignore | 1 - packages/@vuepress/cli/.npmignore | 3 - packages/@vuepress/cli/README.md | 18 --- packages/@vuepress/cli/index.js | 129 ----------------- packages/@vuepress/cli/package.json | 39 ----- packages/@vuepress/core/lib/index.js | 1 + .../core/lib/plugin-api/constants.js | 3 +- .../@vuepress/core/lib/plugin-api/index.js | 4 +- .../@vuepress/core/lib/prepare/AppContext.js | 1 + packages/@vuepress/core/lib/unknownCommand.js | 11 ++ packages/vuepress/lib/checkEnv.js | 26 ++++ packages/vuepress/lib/handleUnknownCommand.js | 133 ++++++++++++++++++ packages/vuepress/lib/registerCoreCommands.js | 67 +++++++++ packages/vuepress/lib/util.js | 56 ++++++++ packages/vuepress/vuepress.js | 27 +++- 15 files changed, 326 insertions(+), 193 deletions(-) delete mode 100644 packages/@vuepress/cli/.npmignore delete mode 100644 packages/@vuepress/cli/README.md delete mode 100644 packages/@vuepress/cli/index.js delete mode 100644 packages/@vuepress/cli/package.json create mode 100644 packages/@vuepress/core/lib/unknownCommand.js create mode 100644 packages/vuepress/lib/checkEnv.js create mode 100644 packages/vuepress/lib/handleUnknownCommand.js create mode 100644 packages/vuepress/lib/registerCoreCommands.js create mode 100644 packages/vuepress/lib/util.js diff --git a/.gitignore b/.gitignore index 9a60952a32..9496595310 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,3 @@ node_modules *.log .temp TODOs.md -vuepress diff --git a/packages/@vuepress/cli/.npmignore b/packages/@vuepress/cli/.npmignore deleted file mode 100644 index 13c38ea313..0000000000 --- a/packages/@vuepress/cli/.npmignore +++ /dev/null @@ -1,3 +0,0 @@ -__tests__ -__mocks__ -.temp diff --git a/packages/@vuepress/cli/README.md b/packages/@vuepress/cli/README.md deleted file mode 100644 index e2524b698b..0000000000 --- a/packages/@vuepress/cli/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# @vuepress/cli - -> cli for vuepress - -## APIs - -### program - -Current instance of [commander.js](https://github.com/tj/commander.js) - -### bootstrap(options) - -Launch the cli. - -#### options.plugins - -#### options.theme - \ No newline at end of file diff --git a/packages/@vuepress/cli/index.js b/packages/@vuepress/cli/index.js deleted file mode 100644 index c132a7b310..0000000000 --- a/packages/@vuepress/cli/index.js +++ /dev/null @@ -1,129 +0,0 @@ -const { chalk } = require('@vuepress/shared-utils') -const semver = require('semver') - -try { - require.resolve('@vuepress/core') -} catch (err) { - console.log(chalk.red( - `\n[vuepress] @vuepress/cli ` + - `requires @vuepress/core to be installed.\n` - )) - process.exit(1) -} - -const pkg = require('@vuepress/core/package.json') -const requiredVersion = pkg.engines.node - -if (!semver.satisfies(process.version, requiredVersion)) { - console.log(chalk.red( - `\n[vuepress] minimum Node version not met:` + - `\nYou are using Node ${process.version}, but VuePress ` + - `requires Node ${requiredVersion}.\nPlease upgrade your Node version.\n` - )) - process.exit(1) -} - -const cli = require('cac')() - -exports.cli = cli -exports.bootstrap = function ({ - plugins, - theme -} = {}) { - const { path, logger, env } = require('@vuepress/shared-utils') - const { dev, build, eject } = require('@vuepress/core') - - cli - .version(pkg.version) - .help() - - cli - .command('dev [targetDir]', 'start development server') - .option('-p, --port ', 'use specified port (default: 8080)') - .option('-t, --temp ', 'set the directory of the temporary file') - .option('-c, --cache [cache]', 'set the directory of cache') - .option('--host ', 'use specified host (default: 0.0.0.0)') - .option('--no-cache', 'clean the cache before build') - .option('--debug', 'start development server in debug mode') - .option('--silent', 'start development server in silent mode') - .action((sourceDir = '.', options) => { - const { - host, - port, - debug, - temp, - cache, - silent - } = options - logger.setOptions({ logLevel: silent ? 1 : debug ? 4 : 3 }) - logger.debug('cli_options', options) - env.setOptions({ isDebug: debug, isTest: process.env.NODE_ENV === 'test' }) - - wrapCommand(dev)(path.resolve(sourceDir), { - host, - port, - temp, - cache, - plugins, - theme - }) - }) - - cli - .command('build [targetDir]', 'build dir as static site') - .option('-d, --dest ', 'specify build output dir (default: .vuepress/dist)') - .option('-t, --temp ', 'set the directory of the temporary file') - .option('-c, --cache [cache]', 'set the directory of cache') - .option('--no-cache', 'clean the cache before build') - .option('--debug', 'build in development mode for debugging') - .option('--silent', 'build static site in silent mode') - .action((sourceDir = '.', options) => { - const { - debug, - dest, - temp, - cache, - silent - } = options - logger.setOptions({ logLevel: silent ? 1 : debug ? 4 : 3 }) - logger.debug('cli_options', options) - env.setOptions({ isDebug: debug, isTest: process.env.NODE_ENV === 'test' }) - - wrapCommand(build)(path.resolve(sourceDir), { - debug, - dest, - plugins, - theme, - temp, - cache, - silent - }) - }) - - cli - .command('eject [targetDir]', 'copy the default theme into .vuepress/theme for customization.') - .option('--debug', 'eject in debug mode') - .action((dir = '.') => { - wrapCommand(eject)(path.resolve(dir)) - }) - - // output help information on unknown commands - cli.on('command:*', () => { - console.error('Unknown command: %s', cli.args.join(' ')) - console.log() - }) - - function wrapCommand (fn) { - return (...args) => { - return fn(...args).catch(err => { - console.error(chalk.red(err.stack)) - process.exitCode = 1 - }) - } - } - - cli.parse(process.argv) - if (!process.argv.slice(2).length) { - cli.outputHelp() - } -} diff --git a/packages/@vuepress/cli/package.json b/packages/@vuepress/cli/package.json deleted file mode 100644 index 72a5b3b27f..0000000000 --- a/packages/@vuepress/cli/package.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "name": "@vuepress/cli", - "version": "1.0.0-alpha.24", - "description": "cli for vuepress", - "main": "index.js", - "publishConfig": { - "access": "public" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/vuejs/vue-cli.git" - }, - "keywords": [ - "documentation", - "vue", - "vuepress", - "generator" - ], - "author": "Evan You", - "maintainers": [ - { - "name": "ULIVZ", - "email": "chl814@foxmail.com" - } - ], - "license": "MIT", - "bugs": { - "url": "https://github.com/vuejs/vuepress/issues" - }, - "dependencies": { - "chalk": "^2.3.2", - "semver": "^5.5.0", - "cac": "^6.3.3" - }, - "peerDependencies": { - "@vuepress/core": "^1.0.0-alpha.1" - }, - "homepage": "https://github.com/vuejs/vuepress/packages/@vuepress/cli#readme" -} diff --git a/packages/@vuepress/core/lib/index.js b/packages/@vuepress/core/lib/index.js index 43a6d0124b..522ff40069 100644 --- a/packages/@vuepress/core/lib/index.js +++ b/packages/@vuepress/core/lib/index.js @@ -3,3 +3,4 @@ exports.dev = require('./dev') exports.build = require('./build') exports.eject = require('./eject') +exports.unknownCommand = require('./unknownCommand') diff --git a/packages/@vuepress/core/lib/plugin-api/constants.js b/packages/@vuepress/core/lib/plugin-api/constants.js index e9bcb63591..55d92c8d5a 100644 --- a/packages/@vuepress/core/lib/plugin-api/constants.js +++ b/packages/@vuepress/core/lib/plugin-api/constants.js @@ -19,7 +19,8 @@ const PLUGIN_OPTION_META_MAP = { ADDITIONAL_PAGES: { name: 'additionalPages', types: [Function, Array] }, GLOBAL_UI_COMPONENTS: { name: 'globalUIComponents', types: [String, Array] }, DEFINE: { name: 'define', types: [Function, Object] }, - ALIAS: { name: 'alias', types: [Function, Object] } + ALIAS: { name: 'alias', types: [Function, Object] }, + REGISTER_COMMAND: { name: 'registerCommand', types: [Function] } } const PLUGIN_OPTION_MAP = {} diff --git a/packages/@vuepress/core/lib/plugin-api/index.js b/packages/@vuepress/core/lib/plugin-api/index.js index 7158e8e87b..c7f0f8c815 100644 --- a/packages/@vuepress/core/lib/plugin-api/index.js +++ b/packages/@vuepress/core/lib/plugin-api/index.js @@ -207,7 +207,8 @@ module.exports = class PluginAPI { additionalPages, globalUIComponents, define, - alias + alias, + registerCommand }) { const isInternalPlugin = pluginName.startsWith('@vuepress/internal-') if (!isInternalPlugin || debug) { @@ -236,5 +237,6 @@ module.exports = class PluginAPI { .registerOption(PLUGIN_OPTION_MAP.GLOBAL_UI_COMPONENTS.key, globalUIComponents, pluginName) .registerOption(PLUGIN_OPTION_MAP.DEFINE.key, define, pluginName) .registerOption(PLUGIN_OPTION_MAP.ALIAS.key, alias, pluginName) + .registerOption(PLUGIN_OPTION_MAP.REGISTER_COMMAND.key, registerCommand, pluginName) } } diff --git a/packages/@vuepress/core/lib/prepare/AppContext.js b/packages/@vuepress/core/lib/prepare/AppContext.js index fe04d23fdc..cd790098ff 100644 --- a/packages/@vuepress/core/lib/prepare/AppContext.js +++ b/packages/@vuepress/core/lib/prepare/AppContext.js @@ -36,6 +36,7 @@ module.exports = class AppContext { */ constructor (sourceDir, cliOptions = {}, isProd) { + logger.debug('sourceDir', sourceDir) this.sourceDir = sourceDir this.cliOptions = cliOptions this.isProd = isProd diff --git a/packages/@vuepress/core/lib/unknownCommand.js b/packages/@vuepress/core/lib/unknownCommand.js new file mode 100644 index 0000000000..89c8cba18c --- /dev/null +++ b/packages/@vuepress/core/lib/unknownCommand.js @@ -0,0 +1,11 @@ +'use strict' + +module.exports = async function (commandName, sourceDir, cliOptions = {}) { + const prepare = require('./prepare/index') + const ctx = await prepare(sourceDir, cliOptions, false /* isProd */) + const cli = require('cac')() + cli.help() + ctx.pluginAPI.options.registerCommand.apply(cli) + cli.parse() + return cli +} diff --git a/packages/vuepress/lib/checkEnv.js b/packages/vuepress/lib/checkEnv.js new file mode 100644 index 0000000000..3fe1feb6fc --- /dev/null +++ b/packages/vuepress/lib/checkEnv.js @@ -0,0 +1,26 @@ +module.exports = function checkEnv () { + const { chalk } = require('@vuepress/shared-utils') + const semver = require('semver') + + try { + require.resolve('@vuepress/core') + } catch (err) { + console.log(chalk.red( + `\n[vuepress] @vuepress/cli ` + + `requires @vuepress/core to be installed.\n` + )) + process.exit(1) + } + + const pkg = require('@vuepress/core/package.json') + const requiredVersion = pkg.engines.node + + if (!semver.satisfies(process.version, requiredVersion)) { + console.log(chalk.red( + `\n[vuepress] minimum Node version not met:` + + `\nYou are using Node ${process.version}, but VuePress ` + + `requires Node ${requiredVersion}.\nPlease upgrade your Node version.\n` + )) + process.exit(1) + } +} diff --git a/packages/vuepress/lib/handleUnknownCommand.js b/packages/vuepress/lib/handleUnknownCommand.js new file mode 100644 index 0000000000..0394e9bf4a --- /dev/null +++ b/packages/vuepress/lib/handleUnknownCommand.js @@ -0,0 +1,133 @@ +'use strict' + +/** + * Module dependencies. + */ + +const prepare = require('@vuepress/core/lib/prepare') +const { path, logger, globby, chalk } = require('@vuepress/shared-utils') +const { isKnownCommand, CLI } = require('./util') +const pwd = process.cwd() + +/** + * Expose handleUnknownCommand function. + */ + +module.exports = async function (cli, options) { + registerUnknownCommands(cli, options) + + const argv = process.argv.slice(2) + const inferredUserDocsDirectory = await inferUserDocsDirectory(pwd) + logger.developer('inferredUserDocsDirectory', inferredUserDocsDirectory) + + const needPrepareBeforeLaunchCLI = inferredUserDocsDirectory && + (isHelpFlag(argv[0]) || isUnknownCommandHelp(argv)) + + logger.developer('needPrepareBeforeLaunchCLI', needPrepareBeforeLaunchCLI) + + if (needPrepareBeforeLaunchCLI) { + let context + let [, sourceDir] = argv + + if (!sourceDir || sourceDir.startsWith('-')) { + sourceDir = inferredUserDocsDirectory + } else { + sourceDir = pwd + } + + logger.setOptions({ logLevel: 1 }) + + if (sourceDir) { + context = await prepare(sourceDir, options) + context.pluginAPI.options.registerCommand.apply(cli) + } + + logger.setOptions({ logLevel: 3 }) + } +} + +// When user type `vuepress [customCommand] --help`, +// VuePress will try to detect where user to place docs. + +async function inferUserDocsDirectory (cwd) { + const paths = await globby([ + '**/.vuepress/config.js', + '!node_modules' + ], { + cwd, + dot: true + }) + const siteConfigPath = paths && paths[0] + if (siteConfigPath) { + return path.resolve( + cwd, + siteConfigPath.replace('.vuepress/config.js', '') + ) + } + return null +} + +/** + * Register a command to match all unmatched commands + * @param {CAC} cli + */ + +function registerUnknownCommands (cli, options) { + cli.on('command:*', async () => { + const { args, options: commandoptions } = cli + + logger.debug('global_options', options) + logger.debug('cli_options', commandoptions) + logger.debug('cli_args', args) + + const [commandName] = args + const sourceDir = args[1] ? path.resolve(args[1]) : pwd + const inferredUserDocsDirectory = await inferUserDocsDirectory(pwd) + logger.developer('inferredUserDocsDirectory', inferredUserDocsDirectory) + logger.developer('sourceDir', sourceDir) + + if (inferredUserDocsDirectory && sourceDir !== inferredUserDocsDirectory) { + logUnknownCommand(cli) + console.log() + logger.tip(`Did you miss to specify the target docs dir? e.g. ${chalk.cyan(`vuepress ${commandName} [targetDir]`)}.`) + logger.tip(`A custom command registered by a plugin requires VuePress to locate your site configuration like ${chalk.cyan('vuepress dev')} or ${chalk.cyan('vuepress build')}.`) + console.log() + process.exit(1) + } + + if (!inferredUserDocsDirectory) { + logUnknownCommand(cli) + process.exit(1) + } + + logger.debug('Custom command', chalk.cyan(commandName)) + CLI({ + async beforeParse (subCli) { + const context = await prepare(sourceDir, { + ...options, + ...commandoptions + }, false /* isProd */) + await context.pluginAPI.options.registerCommand.apply(subCli) + }, + async afterParse (subCli) { + if (!subCli.matchedCommand) { + logUnknownCommand(subCli) + console.log() + } + } + }) + }) +} + +function isHelpFlag (v) { + return v === '--help' || v === '-h' +} + +function isUnknownCommandHelp (argv) { + return !isKnownCommand(argv) && isHelpFlag(argv[1]) +} + +function logUnknownCommand (cli) { + console.error('Unknown command: %s', cli.args.join(' ')) +} + diff --git a/packages/vuepress/lib/registerCoreCommands.js b/packages/vuepress/lib/registerCoreCommands.js new file mode 100644 index 0000000000..3301fae914 --- /dev/null +++ b/packages/vuepress/lib/registerCoreCommands.js @@ -0,0 +1,67 @@ +'use strict' + +/** + * Module dependencies. + */ + +const { dev, build, eject } = require('@vuepress/core') +const { path, logger, env } = require('@vuepress/shared-utils') +const { wrapCommand } = require('./util') + +/** + * Expose registerCoreCommands function. + */ + +module.exports = function (cli, options) { + cli + .command(`dev [targetDir]`, 'start development server') + .option('-p, --port ', 'use specified port (default: 8080)') + .option('-t, --temp ', 'set the directory of the temporary file') + .option('-c, --cache [cache]', 'set the directory of cache') + .option('--host ', 'use specified host (default: 0.0.0.0)') + .option('--no-cache', 'clean the cache before build') + .option('--debug', 'start development server in debug mode') + .option('--silent', 'start development server in silent mode') + .action((sourceDir = '.', commandOptions) => { + const { debug, silent } = commandOptions + + logger.setOptions({ logLevel: silent ? 1 : debug ? 4 : 3 }) + logger.debug('global_options', options) + logger.debug('dev_options', commandOptions) + env.setOptions({ isDebug: debug, isTest: process.env.NODE_ENV === 'test' }) + + wrapCommand(dev)(path.resolve(sourceDir), { + ...options, + ...commandOptions + }) + }) + + cli + .command('build [targetDir]', 'build dir as static site') + .option('-d, --dest ', 'specify build output dir (default: .vuepress/dist)') + .option('-t, --temp ', 'set the directory of the temporary file') + .option('-c, --cache [cache]', 'set the directory of cache') + .option('--no-cache', 'clean the cache before build') + .option('--debug', 'build in development mode for debugging') + .option('--silent', 'build static site in silent mode') + .action((sourceDir = '.', commandOptions) => { + const { debug, silent } = commandOptions + + logger.setOptions({ logLevel: silent ? 1 : debug ? 4 : 3 }) + logger.debug('global_options', options) + logger.debug('build_options', commandOptions) + env.setOptions({ isDebug: debug, isTest: process.env.NODE_ENV === 'test' }) + + wrapCommand(build)(path.resolve(sourceDir), { + ...options, + ...commandOptions + }) + }) + + cli + .command('eject [targetDir]', 'copy the default theme into .vuepress/theme for customization.') + .option('--debug', 'eject in debug mode') + .action((dir = '.') => { + wrapCommand(eject)(path.resolve(dir)) + }) +} diff --git a/packages/vuepress/lib/util.js b/packages/vuepress/lib/util.js new file mode 100644 index 0000000000..6c14e277ea --- /dev/null +++ b/packages/vuepress/lib/util.js @@ -0,0 +1,56 @@ +'use strict' + +/** + * Module dependencies. + */ + +const { chalk } = require('@vuepress/shared-utils') +const CAC = require('cac') + +/** + * Bootstrap a CAC cli + * @param {function} beforeParse + * @param {function} adterParse + * @returns {Promise} + */ + +async function CLI ({ + beforeParse, + afterParse +}) { + const cli = CAC() + beforeParse && await beforeParse(cli) + cli.parse(process.argv) + afterParse && await afterParse(cli) +} + +/** + * Wrap a function to catch error. + * @param {function} fn + * @returns {function(...[*]): (*|Promise|Promise)} + */ + +function wrapCommand (fn) { + return (...args) => { + return fn(...args).catch(err => { + console.error(chalk.red(err.stack)) + process.exitCode = 1 + }) + } +} + +/** + * Check if a command is built-in + * @param {array} argv + * @returns {boolean} + */ + +function isKnownCommand (argv) { + return ['dev', 'build', 'eject'].includes(argv[0]) +} + +module.exports = { + CLI, + isKnownCommand, + wrapCommand +} diff --git a/packages/vuepress/vuepress.js b/packages/vuepress/vuepress.js index c885579271..78c9528808 100755 --- a/packages/vuepress/vuepress.js +++ b/packages/vuepress/vuepress.js @@ -1,3 +1,28 @@ #!/usr/bin/env node -require('@vuepress/cli').bootstrap({ theme: '@vuepress/default' }) +const checkEnv = require('./lib/checkEnv') +const { CLI } = require('./lib/util') +const registerCoreCommands = require('./lib/registerCoreCommands') +const handleUnknownCommand = require('./lib/handleUnknownCommand') + +const OPTIONS = { + theme: '@vuepress/default' +} + +CLI({ + async beforeParse (cli) { + checkEnv() + registerCoreCommands(cli, OPTIONS) + await handleUnknownCommand(cli, OPTIONS) + + const pkg = require('@vuepress/core/package.json') + cli.version(pkg.version).help() + }, + + async afterParse (cli) { + if (!process.argv.slice(2).length) { + cli.outputHelp() + } + } +}) + From 239547f91dbb2449336a35274576ff40da9e8570 Mon Sep 17 00:00:00 2001 From: ULIVZ <472590061@qq.com> Date: Wed, 5 Dec 2018 02:09:10 +0800 Subject: [PATCH 03/10] chore: gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 9496595310..9a60952a32 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ node_modules *.log .temp TODOs.md +vuepress From 9d0d879d3bb8383134547713079ad11364983fea Mon Sep 17 00:00:00 2001 From: ULIVZ <472590061@qq.com> Date: Wed, 5 Dec 2018 02:13:00 +0800 Subject: [PATCH 04/10] chore: remove unnecessary check and outdated code --- packages/vuepress/lib/checkEnv.js | 25 ++++++++++++------------- packages/vuepress/package.json | 1 - packages/vuepress/vuepress.js | 5 ++--- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/packages/vuepress/lib/checkEnv.js b/packages/vuepress/lib/checkEnv.js index 3fe1feb6fc..8b0de2959c 100644 --- a/packages/vuepress/lib/checkEnv.js +++ b/packages/vuepress/lib/checkEnv.js @@ -1,18 +1,17 @@ -module.exports = function checkEnv () { - const { chalk } = require('@vuepress/shared-utils') - const semver = require('semver') +'use strict' - try { - require.resolve('@vuepress/core') - } catch (err) { - console.log(chalk.red( - `\n[vuepress] @vuepress/cli ` + - `requires @vuepress/core to be installed.\n` - )) - process.exit(1) - } +/** + * Module dependencies. + */ + +const { chalk } = require('@vuepress/shared-utils') +const semver = require('semver') + +/** + * Expose handleUnknownCommand function. + */ - const pkg = require('@vuepress/core/package.json') +module.exports = function checkEnv (pkg) { const requiredVersion = pkg.engines.node if (!semver.satisfies(process.version, requiredVersion)) { diff --git a/packages/vuepress/package.json b/packages/vuepress/package.json index 76eed6341d..b3981e52db 100644 --- a/packages/vuepress/package.json +++ b/packages/vuepress/package.json @@ -28,7 +28,6 @@ }, "homepage": "https://github.com/vuejs/vuepress#readme", "dependencies": { - "@vuepress/cli": "^1.0.0-alpha.24", "@vuepress/core": "^1.0.0-alpha.24", "@vuepress/theme-default": "^1.0.0-alpha.24" }, diff --git a/packages/vuepress/vuepress.js b/packages/vuepress/vuepress.js index 78c9528808..35050b4f62 100755 --- a/packages/vuepress/vuepress.js +++ b/packages/vuepress/vuepress.js @@ -11,11 +11,10 @@ const OPTIONS = { CLI({ async beforeParse (cli) { - checkEnv() + const pkg = require('@vuepress/core/package.json') + checkEnv(pkg) registerCoreCommands(cli, OPTIONS) await handleUnknownCommand(cli, OPTIONS) - - const pkg = require('@vuepress/core/package.json') cli.version(pkg.version).help() }, From 9cd9c738113132561f5c045f1c0bca2fb654d7c0 Mon Sep 17 00:00:00 2001 From: ULIVZ <472590061@qq.com> Date: Wed, 5 Dec 2018 02:28:45 +0800 Subject: [PATCH 05/10] docs: update --- .../docs/miscellaneous/design-concepts.md | 3 +-- packages/docs/docs/plugin/option-api.md | 26 ++++++++++++++++++ .../docs/zh/miscellaneous/design-concepts.md | 3 +-- packages/docs/docs/zh/plugin/option-api.md | 27 +++++++++++++++++++ 4 files changed, 55 insertions(+), 4 deletions(-) diff --git a/packages/docs/docs/miscellaneous/design-concepts.md b/packages/docs/docs/miscellaneous/design-concepts.md index 665c4c2891..1dc40d857a 100644 --- a/packages/docs/docs/miscellaneous/design-concepts.md +++ b/packages/docs/docs/miscellaneous/design-concepts.md @@ -187,9 +187,8 @@ Then the final route of i18n UI is `/i18n/`. ## Others -With the goal of decoupling, we were able to separate VuePress into the following libraries by introducing monorepo: +With the goal of decoupling, we were able to separate VuePress into the following two libraries by introducing monorepo: -- [@vuepress/cli](https://github.com/vuejs/vuepress/tree/master/packages/@vuepress/cli): Management of command line; - [@vuepress/core](https://github.com/vuejs/vuepress/tree/master/packages/@vuepress/core):Including the core implementation of `dev`, `build` and `Plugin API`; - [@vuepress/theme-default](https://github.com/vuejs/vuepress/tree/master/packages/@vuepress/theme-default):The default theme you see now. diff --git a/packages/docs/docs/plugin/option-api.md b/packages/docs/docs/plugin/option-api.md index 6be11d8cb9..a9764fd457 100644 --- a/packages/docs/docs/plugin/option-api.md +++ b/packages/docs/docs/plugin/option-api.md @@ -434,3 +434,29 @@ Then, VuePress will automatically inject these components behind the layout comp ``` + +## registerCommand + +- Type: `function` +- Default: `undefined` + +Register a extra command to enhance the CLI of vuepress. The function will be called with a [CAC](https://github.com/cacjs/cac)'s instance as the first argument. + +```js +module.exports = { + registerCommand (cli) { + cli + .command('info [targetDir]', '') + .option('--debug', 'display info in debug mode') + .action((dir = '.') => { + console.log('Display info of your website') + }) + } +} +``` + +Now you can use `vuepress info [targetDir]` a in your project! + +::: tip +Note that a custom command registered by a plugin requires VuePress to locate your site configuration like `vuepress dev` and `vuepress build`, so when developing a command, be sure to lead the user to pass `targetDir` as an CLI argument. +::: diff --git a/packages/docs/docs/zh/miscellaneous/design-concepts.md b/packages/docs/docs/zh/miscellaneous/design-concepts.md index ea64376650..6adb30cb10 100644 --- a/packages/docs/docs/zh/miscellaneous/design-concepts.md +++ b/packages/docs/docs/zh/miscellaneous/design-concepts.md @@ -187,9 +187,8 @@ i18n UI 最终的路由将是 `/i18n/`. ## 其他 -本着解耦的目标,引入 monorepo 后,我们也得以将 VuePress 分离成以下几个库: +本着解耦的目标,引入 monorepo 后,我们也得以将 VuePress 分离成以下两个库: -- [@vuepress/cli](https://github.com/vuejs/vuepress/tree/master/packages/@vuepress/cli): 命令行指令的管理; - [@vuepress/core](https://github.com/vuejs/vuepress/tree/master/packages/@vuepress/core):包含 dev、build 的核心实现和 Plugin API; - [@vuepress/theme-default](https://github.com/vuejs/vuepress/tree/master/packages/@vuepress/theme-default):你现在所看到的默认主题。 diff --git a/packages/docs/docs/zh/plugin/option-api.md b/packages/docs/docs/zh/plugin/option-api.md index 188ddaf363..1ed3a75dd6 100644 --- a/packages/docs/docs/zh/plugin/option-api.md +++ b/packages/docs/docs/zh/plugin/option-api.md @@ -436,3 +436,30 @@ VuePress 将会自动将这些组件注入到布局组件的隔壁: ``` + +## registerCommand + +- 类型: `function` +- 默认值: `undefined` + +注册一个额外的 command 来增强 vuepress 的 CLI。这个函数将会以一个 [CAC](https://github.com/cacjs/cac) 的实例作为第一个参数被调用。 + +```js +module.exports = { + registerCommand (cli) { + cli + .command('info [targetDir]', '') + .option('--debug', 'display info in debug mode') + .action((dir = '.') => { + console.log('Display info of your website') + }) + } +} +``` + +现在你可以在你项目中使用 `vuepress info [targetDir]` 了! + +::: tip +值得注意的是,一个自定义的 command 需要 VuePress 像 `vuepress dev` 或 `vuepress build` 去定位到你的站点配置,所以在开发一个 command 时,请确保引导用户去传入 `targetDir` 作为 CLI 参数的一部分。 +::: + From 9d7e8d02605c8cf469c3b06b16c815197d2551cc Mon Sep 17 00:00:00 2001 From: ULIVZ <472590061@qq.com> Date: Wed, 5 Dec 2018 02:30:01 +0800 Subject: [PATCH 06/10] chore: tweaks --- packages/@vuepress/core/lib/index.js | 1 - packages/@vuepress/core/lib/unknownCommand.js | 11 ----------- 2 files changed, 12 deletions(-) delete mode 100644 packages/@vuepress/core/lib/unknownCommand.js diff --git a/packages/@vuepress/core/lib/index.js b/packages/@vuepress/core/lib/index.js index 522ff40069..43a6d0124b 100644 --- a/packages/@vuepress/core/lib/index.js +++ b/packages/@vuepress/core/lib/index.js @@ -3,4 +3,3 @@ exports.dev = require('./dev') exports.build = require('./build') exports.eject = require('./eject') -exports.unknownCommand = require('./unknownCommand') diff --git a/packages/@vuepress/core/lib/unknownCommand.js b/packages/@vuepress/core/lib/unknownCommand.js deleted file mode 100644 index 89c8cba18c..0000000000 --- a/packages/@vuepress/core/lib/unknownCommand.js +++ /dev/null @@ -1,11 +0,0 @@ -'use strict' - -module.exports = async function (commandName, sourceDir, cliOptions = {}) { - const prepare = require('./prepare/index') - const ctx = await prepare(sourceDir, cliOptions, false /* isProd */) - const cli = require('cac')() - cli.help() - ctx.pluginAPI.options.registerCommand.apply(cli) - cli.parse() - return cli -} From 7d3620c15bdd7b164e3f265d9d8f5f7db160c924 Mon Sep 17 00:00:00 2001 From: ULIVZ <472590061@qq.com> Date: Wed, 5 Dec 2018 02:32:53 +0800 Subject: [PATCH 07/10] chore: modify the compatible node version to 8.6 or higher. Since we have started to using `object spread properties` syntax Ref: https://node.green/#ES2018-features-object-rest-spread-properties-object-spread-properties --- packages/@vuepress/core/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@vuepress/core/package.json b/packages/@vuepress/core/package.json index 7c6c510ce0..eada85823b 100644 --- a/packages/@vuepress/core/package.json +++ b/packages/@vuepress/core/package.json @@ -72,7 +72,7 @@ "webpackbar": "^2.6.1" }, "engines": { - "node": ">=8" + "node": ">=8.6" }, "browserslist": [ ">1%" From 2ccec71be98717feaaacae905dcc3501613056ba Mon Sep 17 00:00:00 2001 From: ULIVZ <472590061@qq.com> Date: Wed, 5 Dec 2018 02:35:19 +0800 Subject: [PATCH 08/10] chore: add missing deps --- packages/@vuepress/core/package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/@vuepress/core/package.json b/packages/@vuepress/core/package.json index eada85823b..1b0fa4cacc 100644 --- a/packages/@vuepress/core/package.json +++ b/packages/@vuepress/core/package.json @@ -69,7 +69,9 @@ "webpack-chain": "^4.6.0", "webpack-merge": "^4.1.2", "webpack-serve": "^1.0.2", - "webpackbar": "^2.6.1" + "webpackbar": "^2.6.1", + "semver": "^5.5.0", + "cac": "^6.3.3" }, "engines": { "node": ">=8.6" From 30b697fdee6ef4520145405cae628a0c6ebc3248 Mon Sep 17 00:00:00 2001 From: ULIVZ <472590061@qq.com> Date: Thu, 6 Dec 2018 09:13:02 +0800 Subject: [PATCH 09/10] chore: bump version of CAC --- packages/@vuepress/core/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@vuepress/core/package.json b/packages/@vuepress/core/package.json index db56acf5e5..63400739d0 100644 --- a/packages/@vuepress/core/package.json +++ b/packages/@vuepress/core/package.json @@ -71,7 +71,7 @@ "webpack-serve": "^1.0.2", "webpackbar": "^2.6.1", "semver": "^5.5.0", - "cac": "^6.3.3" + "cac": "^6.3.9" }, "engines": { "node": ">=8.6" From 1f7bf85bdd7e96e4f759d3785c96b60e32e5fa83 Mon Sep 17 00:00:00 2001 From: ULIVZ <472590061@qq.com> Date: Sat, 8 Dec 2018 22:10:55 +0800 Subject: [PATCH 10/10] chore: rename 'registerCommand' to 'extendCli' --- packages/@vuepress/core/lib/plugin-api/constants.js | 2 +- packages/@vuepress/core/lib/plugin-api/index.js | 4 ++-- packages/vuepress/lib/handleUnknownCommand.js | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/@vuepress/core/lib/plugin-api/constants.js b/packages/@vuepress/core/lib/plugin-api/constants.js index e5193b99a7..883447930d 100644 --- a/packages/@vuepress/core/lib/plugin-api/constants.js +++ b/packages/@vuepress/core/lib/plugin-api/constants.js @@ -20,7 +20,7 @@ const PLUGIN_OPTION_META_MAP = { GLOBAL_UI_COMPONENTS: { name: 'globalUIComponents', types: [String, Array] }, DEFINE: { name: 'define', types: [Function, Object] }, ALIAS: { name: 'alias', types: [Function, Object] }, - REGISTER_COMMAND: { name: 'registerCommand', types: [Function] } + EXTEND_CLI: { name: 'extendCli', types: [Function] } } const PLUGIN_OPTION_MAP = {} diff --git a/packages/@vuepress/core/lib/plugin-api/index.js b/packages/@vuepress/core/lib/plugin-api/index.js index c41e5fc153..c4aa89e4f9 100644 --- a/packages/@vuepress/core/lib/plugin-api/index.js +++ b/packages/@vuepress/core/lib/plugin-api/index.js @@ -207,7 +207,7 @@ module.exports = class PluginAPI { globalUIComponents, define, alias, - registerCommand + extendCli }) { const isInternalPlugin = pluginName.startsWith('@vuepress/internal-') logger[isInternalPlugin ? 'debug' : 'tip'](pluginLog(pluginName, shortcut)) @@ -230,7 +230,7 @@ module.exports = class PluginAPI { .registerOption(PLUGIN_OPTION_MAP.GLOBAL_UI_COMPONENTS.key, globalUIComponents, pluginName) .registerOption(PLUGIN_OPTION_MAP.DEFINE.key, define, pluginName) .registerOption(PLUGIN_OPTION_MAP.ALIAS.key, alias, pluginName) - .registerOption(PLUGIN_OPTION_MAP.REGISTER_COMMAND.key, registerCommand, pluginName) + .registerOption(PLUGIN_OPTION_MAP.EXTEND_CLI.key, extendCli, pluginName) } } diff --git a/packages/vuepress/lib/handleUnknownCommand.js b/packages/vuepress/lib/handleUnknownCommand.js index 0394e9bf4a..cc20a2aed7 100644 --- a/packages/vuepress/lib/handleUnknownCommand.js +++ b/packages/vuepress/lib/handleUnknownCommand.js @@ -39,7 +39,7 @@ module.exports = async function (cli, options) { if (sourceDir) { context = await prepare(sourceDir, options) - context.pluginAPI.options.registerCommand.apply(cli) + context.pluginAPI.options.extendCli.apply(cli) } logger.setOptions({ logLevel: 3 }) @@ -107,7 +107,7 @@ function registerUnknownCommands (cli, options) { ...options, ...commandoptions }, false /* isProd */) - await context.pluginAPI.options.registerCommand.apply(subCli) + await context.pluginAPI.options.extendCli.apply(subCli) }, async afterParse (subCli) { if (!subCli.matchedCommand) {