diff --git a/packages/@vue/cli-shared-utils/__tests__/pluginResolution.spec.js b/packages/@vue/cli-shared-utils/__tests__/pluginResolution.spec.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/@vue/cli-shared-utils/lib/pluginResolution.js b/packages/@vue/cli-shared-utils/lib/pluginResolution.js index 0183d0c363..e4b6060e4d 100644 --- a/packages/@vue/cli-shared-utils/lib/pluginResolution.js +++ b/packages/@vue/cli-shared-utils/lib/pluginResolution.js @@ -1,7 +1,28 @@ const pluginRE = /^(@vue\/|vue-|@[\w-]+\/vue-)cli-plugin-/ +const scopeRE = /^@[\w-]+\// exports.isPlugin = id => pluginRE.test(id) -exports.isOfficial = id => /^@vue\//.test(id) +exports.isOfficialPlugin = id => /^@vue\//.test(id) -exports.toShortId = id => id.replace(pluginRE, '') +exports.toShortPluginId = id => id.replace(pluginRE, '') + +exports.resolvePluginId = id => { + // already full id + // e.g. vue-cli-plugin-foo, @vue/cli-plugin-foo, @bar/vue-cli-plugin-foo + if (pluginRE.test(id)) { + return id + } + // scoped short + // e.g. @vue/foo, @bar/foo + if (id.charAt(0) === '@') { + const scopeMatch = id.match(scopeRE) + if (scopeMatch) { + const shortId = id.replace(scopeRE, '') + return `${scopeMatch[0]}vue-cli-plugin-${shortId}` + } + } + // default short + // e.g. foo + return `vue-cli-plugin-${id}` +} diff --git a/packages/@vue/cli/lib/Generator.js b/packages/@vue/cli/lib/Generator.js index c50c31b0f7..825dfd9604 100644 --- a/packages/@vue/cli/lib/Generator.js +++ b/packages/@vue/cli/lib/Generator.js @@ -4,8 +4,8 @@ const debug = require('debug') const GeneratorAPI = require('./GeneratorAPI') const sortObject = require('./util/sortObject') const writeFileTree = require('./util/writeFileTree') -const { toShortId } = require('@vue/cli-shared-utils') const configTransforms = require('./util/configTransforms') +const { toShortPluginId } = require('@vue/cli-shared-utils') const logger = require('@vue/cli-shared-utils/lib/logger') const logTypes = { @@ -151,7 +151,7 @@ module.exports = class Generator { printExitLogs () { if (this.exitLogs.length) { this.exitLogs.forEach(({ id, msg, type }) => { - const shortId = toShortId(id) + const shortId = toShortPluginId(id) const logFn = logTypes[type] if (!logFn) { logger.error(`Invalid api.exitLog type '${type}'.`, shortId) diff --git a/packages/@vue/cli/lib/GeneratorAPI.js b/packages/@vue/cli/lib/GeneratorAPI.js index 847efa6361..ebcfda8607 100644 --- a/packages/@vue/cli/lib/GeneratorAPI.js +++ b/packages/@vue/cli/lib/GeneratorAPI.js @@ -5,7 +5,7 @@ const globby = require('globby') const isBinary = require('isbinaryfile') const yaml = require('yaml-front-matter') const mergeDeps = require('./util/mergeDeps') -const { isOfficial, toShortId } = require('@vue/cli-shared-utils') +const { isOfficialPlugin, toShortPluginId } = require('@vue/cli-shared-utils') const isString = val => typeof val === 'string' const isFunction = val => typeof val === 'function' @@ -40,10 +40,10 @@ class GeneratorAPI { this.pluginsData = generator.plugins .filter(({ id }) => id !== `@vue/cli-service`) .map(({ id }) => { - const name = toShortId(id) + const name = toShortPluginId(id) return { name: name, - link: isOfficial(id) + link: isOfficialPlugin(id) ? `https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-${name}` : getLink(id) } diff --git a/packages/@vue/cli/lib/add.js b/packages/@vue/cli/lib/add.js index 6c159e981b..b846b55a85 100644 --- a/packages/@vue/cli/lib/add.js +++ b/packages/@vue/cli/lib/add.js @@ -1,16 +1,17 @@ const chalk = require('chalk') +const invoke = require('./invoke') const { loadOptions } = require('./options') const { installPackage } = require('./util/installDeps') const { log, error, hasYarn, - stopSpinner + stopSpinner, + resolvePluginId } = require('@vue/cli-shared-utils') -const invoke = require('./invoke') async function add (pluginName, options = {}, context = process.cwd()) { - const packageName = pluginName.includes('vue-cli-plugin-') ? pluginName : `vue-cli-plugin-${pluginName}` + const packageName = resolvePluginId(pluginName) log() log(`📦 Installing ${chalk.cyan(packageName)}...`) diff --git a/packages/@vue/cli/lib/invoke.js b/packages/@vue/cli/lib/invoke.js index 0a7a3886c0..a30bbc34ee 100644 --- a/packages/@vue/cli/lib/invoke.js +++ b/packages/@vue/cli/lib/invoke.js @@ -13,7 +13,8 @@ const { hasYarn, hasGit, logWithSpinner, - stopSpinner + stopSpinner, + resolvePluginId } = require('@vue/cli-shared-utils') function load (request, context) { @@ -40,22 +41,13 @@ async function invoke (pluginName, options = {}, context = process.cwd()) { // attempt to locate the plugin in package.json const findPlugin = deps => { if (!deps) return - - // custom scoped plugin let name - if (pluginName.charAt(0) === '@') { - const scopeRE = /^@[\w-]+\// - const scopeMatch = pluginName.match(scopeRE) - const shortId = pluginName.replace(scopeRE, '') - if (scopeMatch && deps[name = `${scopeMatch[0]}vue-cli-plugin-${shortId}`]) { - return name - } + // official + if (deps[name = `@vue/cli-plugin-${pluginName}`]) { + return name } - - // official, non-scoped & full name - if (deps[name = `@vue/cli-plugin-${pluginName}`] || - deps[name = `vue-cli-plugin-${pluginName}`] || - deps[name = pluginName]) { + // full id, scoped short, or default short + if (deps[name = resolvePluginId(pluginName)]) { return name } } @@ -135,7 +127,7 @@ async function invoke (pluginName, options = {}, context = process.cwd()) { log() } } - log(` You should review and commit the changes.`) + log(` You should review these changes with ${chalk.cyan(`git diff`)} and commit them.`) log() generator.printExitLogs()