Permalink
Browse files

Breaking: support @scope shorthand in plugins (fixes #9903) (#9905)

  • Loading branch information...
mysticatea authored and not-an-aardvark committed Mar 30, 2018
1 parent 462b058 commit d440e8496925aa1dfef903a2c54cd7505e8f436f
View
@@ -11,12 +11,6 @@
const debug = require("debug")("eslint:plugins");
const naming = require("../util/naming");
//------------------------------------------------------------------------------
// Private
//------------------------------------------------------------------------------
const PLUGIN_NAME_PREFIX = "eslint-plugin-";
//------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------
@@ -44,10 +38,8 @@ class Plugins {
* @returns {void}
*/
define(pluginName, plugin) {
const pluginNamespace = naming.getNamespaceFromTerm(pluginName),
pluginNameWithoutNamespace = naming.removeNamespaceFromTerm(pluginName),
pluginNameWithoutPrefix = naming.removePrefixFromTerm(PLUGIN_NAME_PREFIX, pluginNameWithoutNamespace),
shortName = pluginNamespace + pluginNameWithoutPrefix;
const longName = naming.normalizePackageName(pluginName, "eslint-plugin");
const shortName = naming.getShorthandName(longName, "eslint-plugin");
// load up environments and rules
this._plugins[shortName] = plugin;
@@ -79,11 +71,8 @@ class Plugins {
* @throws {Error} If the plugin cannot be loaded.
*/
load(pluginName) {
const pluginNamespace = naming.getNamespaceFromTerm(pluginName),
pluginNameWithoutNamespace = naming.removeNamespaceFromTerm(pluginName),
pluginNameWithoutPrefix = naming.removePrefixFromTerm(PLUGIN_NAME_PREFIX, pluginNameWithoutNamespace),
shortName = pluginNamespace + pluginNameWithoutPrefix,
longName = pluginNamespace + PLUGIN_NAME_PREFIX + pluginNameWithoutPrefix;
const longName = naming.normalizePackageName(pluginName, "eslint-plugin");
const shortName = naming.getShorthandName(longName, "eslint-plugin");
let plugin = null;
if (pluginName.match(/\s+/)) {
View
@@ -61,23 +61,28 @@ function normalizePackageName(name, prefix) {
}
/**
* Removes the prefix from a term.
* Removes the prefix from a fullname.
* @param {string} fullname The term which may have the prefix.
* @param {string} prefix The prefix to remove.
* @param {string} term The term which may have the prefix.
* @returns {string} The term without prefix.
*/
function removePrefixFromTerm(prefix, term) {
return term.startsWith(prefix) ? term.slice(prefix.length) : term;
}
function getShorthandName(fullname, prefix) {
if (fullname[0] === "@") {
let matchResult = new RegExp(`^(@[^/]+)/${prefix}$`).exec(fullname);
/**
* Adds a prefix to a term.
* @param {string} prefix The prefix to add.
* @param {string} term The term which may not have the prefix.
* @returns {string} The term with prefix.
*/
function addPrefixToTerm(prefix, term) {
return term.startsWith(prefix) ? term : `${prefix}${term}`;
if (matchResult) {
return matchResult[1];
}
matchResult = new RegExp(`^(@[^/]+)/${prefix}-(.+)$`).exec(fullname);
if (matchResult) {
return `${matchResult[1]}/${matchResult[2]}`;
}
} else if (fullname.startsWith(`${prefix}-`)) {
return fullname.slice(prefix.length + 1);
}
return fullname;
}
/**
@@ -91,23 +96,12 @@ function getNamespaceFromTerm(term) {
return match ? match[0] : "";
}
/**
* Removes the namespace from a term.
* @param {string} term The term which may have the namespace.
* @returns {string} The name of the plugin without the namespace.
*/
function removeNamespaceFromTerm(term) {
return term.replace(NAMESPACE_REGEX, "");
}
//------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------
module.exports = {
normalizePackageName,
removePrefixFromTerm,
addPrefixToTerm,
getNamespaceFromTerm,
removeNamespaceFromTerm
getShorthandName,
getNamespaceFromTerm
};
@@ -0,0 +1,7 @@
{
"root": true,
"plugins": ["@scope"],
"rules": {
"@scope/rule": "error"
}
}

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.
@@ -0,0 +1,4 @@
{
"root": true,
"extends": ["plugin:@scope/recommended"]
}

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.
View
@@ -557,6 +557,44 @@ describe("CLIEngine", () => {
assert.strictEqual(report.results[0].messages[0].message, expectedMsg);
});
// @scope for @scope/eslint-plugin
describe("(plugin shorthand)", () => {
const Module = require("module");
let originalFindPath = null;
/* eslint-disable no-underscore-dangle */
before(() => {
originalFindPath = Module._findPath;
Module._findPath = function(id) {
if (id === "@scope/eslint-plugin") {
return path.resolve(__dirname, "../fixtures/plugin-shorthand/basic/node_modules/@scope/eslint-plugin/index.js");
}
return originalFindPath.apply(this, arguments);
};
});
after(() => {
Module._findPath = originalFindPath;
});
/* eslint-enable no-underscore-dangle */
it("should resolve 'plugins:[\"@scope\"]' to 'node_modules/@scope/eslint-plugin'.", () => {
engine = new CLIEngine({ cwd: getFixturePath("plugin-shorthand/basic") });
const report = engine.executeOnText("var x = 0", "index.js").results[0];
assert.strictEqual(report.filePath, getFixturePath("plugin-shorthand/basic/index.js"));
assert.strictEqual(report.messages[0].ruleId, "@scope/rule");
assert.strictEqual(report.messages[0].message, "OK");
});
it("should resolve 'extends:[\"plugin:@scope/recommended\"]' to 'node_modules/@scope/eslint-plugin'.", () => {
engine = new CLIEngine({ cwd: getFixturePath("plugin-shorthand/extends") });
const report = engine.executeOnText("var x = 0", "index.js").results[0];
assert.strictEqual(report.filePath, getFixturePath("plugin-shorthand/extends/index.js"));
assert.strictEqual(report.messages[0].ruleId, "@scope/rule");
assert.strictEqual(report.messages[0].message, "OK");
});
});
});
describe("executeOnFiles()", () => {
View
@@ -36,32 +36,23 @@ describe("naming", () => {
});
describe("removePrefixFromTerm()", () => {
it("should remove prefix when passed a term with a prefix", () => {
const pluginName = naming.removePrefixFromTerm("eslint-plugin-", "eslint-plugin-test");
describe("getShorthandName()", () => {
assert.strictEqual(pluginName, "test");
});
it("should not modify term when passed a term without a prefix", () => {
const pluginName = naming.removePrefixFromTerm("eslint-plugin-", "test");
assert.strictEqual(pluginName, "test");
});
});
describe("addPrefixToTerm()", () => {
it("should add prefix when passed a term without a prefix", () => {
const pluginName = naming.addPrefixToTerm("eslint-plugin-", "test");
leche.withData([
["foo", "foo"],
["eslint-config-foo", "foo"],
["@z", "@z"],
["@z/eslint-config", "@z"],
["@z/foo", "@z/foo"],
["@z/eslint-config-foo", "@z/foo"]
], (input, expected) => {
it(`should return ${expected} when passed ${input}`, () => {
const result = naming.getShorthandName(input, "eslint-config");
assert.strictEqual(pluginName, "eslint-plugin-test");
assert.strictEqual(result, expected);
});
});
it("should not modify term when passed a term with a prefix", () => {
const pluginName = naming.addPrefixToTerm("eslint-plugin-", "eslint-plugin-test");
assert.strictEqual(pluginName, "eslint-plugin-test");
});
});
describe("getNamespaceFromTerm()", () => {
@@ -71,12 +62,4 @@ describe("naming", () => {
assert.strictEqual(namespace, "@namepace/");
});
});
describe("removeNamespaceFromTerm()", () => {
it("should remove namepace when passed with namepace", () => {
const namespace = naming.removeNamespaceFromTerm("@namepace/eslint-plugin-test");
assert.strictEqual(namespace, "eslint-plugin-test");
});
});
});

0 comments on commit d440e84

Please sign in to comment.