Skip to content

Commit

Permalink
Update: Resolve npm installed formatters (eslint#5900)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tom Erik Støwer committed Oct 22, 2017
1 parent 47e5f6f commit cd9d6a2
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 8 deletions.
11 changes: 11 additions & 0 deletions docs/user-guide/command-line-interface.md
Expand Up @@ -333,6 +333,17 @@ Example:

eslint -f ./customformat.js file.js

An npm-installed formatter is resolved with or without `eslint-formatter-` prefix.

Example:

npm install eslint-formatter-pretty

eslint -f pretty file.js

// equivalent:
eslint -f eslint-formatter-pretty file.js

When specified, the given format is output to the console. If you'd like to save that output into a file, you can do so on the command line like so:

eslint -f compact file.js > results.txt
Expand Down
23 changes: 20 additions & 3 deletions lib/cli-engine.js
Expand Up @@ -26,10 +26,14 @@ const fs = require("fs"),
validator = require("./config/config-validator"),
stringify = require("json-stable-stringify"),
hash = require("./util/hash"),
ModuleResolver = require("./util/module-resolver"),
naming = require("./util/naming"),
pkg = require("../package.json");

const debug = require("debug")("eslint:cli-engine");

const resolver = new ModuleResolver();

//------------------------------------------------------------------------------
// Typedefs
//------------------------------------------------------------------------------
Expand Down Expand Up @@ -670,15 +674,28 @@ class CLIEngine {
// replace \ with / for Windows compatibility
format = format.replace(/\\/g, "/");

let cwd = this.options ? this.options.cwd : process.cwd();

const namespace = naming.getNamespaceFromTerm(format);

if (namespace) {
cwd = `${cwd}/${namespace}`;
format = naming.removeNamespaceFromTerm(format);
}

let formatterPath;

// if there's a slash, then it's a file
if (format.indexOf("/") > -1) {
const cwd = this.options ? this.options.cwd : process.cwd();

formatterPath = path.resolve(cwd, format);
} else {
formatterPath = `./formatters/${format}`;
const npmFormat = naming.addPrefixToTerm("eslint-formatter-", format);

try {
formatterPath = resolver.resolve(npmFormat, cwd);
} catch (_) {
formatterPath = `./formatters/${format}`;
}
}

try {
Expand Down
10 changes: 5 additions & 5 deletions lib/config/plugins.js
Expand Up @@ -9,13 +9,13 @@
//------------------------------------------------------------------------------

const debug = require("debug")("eslint:plugins");
const naming = require("../util/naming");

//------------------------------------------------------------------------------
// Private
//------------------------------------------------------------------------------

const PLUGIN_NAME_PREFIX = "eslint-plugin-",
NAMESPACE_REGEX = /^@.*\//i;
const PLUGIN_NAME_PREFIX = "eslint-plugin-";

//------------------------------------------------------------------------------
// Public Interface
Expand Down Expand Up @@ -43,7 +43,7 @@ class Plugins {
* @returns {string} The name of the plugin without prefix.
*/
static removePrefix(pluginName) {
return pluginName.startsWith(PLUGIN_NAME_PREFIX) ? pluginName.slice(PLUGIN_NAME_PREFIX.length) : pluginName;
return naming.removePrefixFromTerm(PLUGIN_NAME_PREFIX, pluginName);
}

/**
Expand All @@ -52,7 +52,7 @@ class Plugins {
* @returns {string} The name of the plugins namepace if it has one.
*/
static getNamespace(pluginName) {
return pluginName.match(NAMESPACE_REGEX) ? pluginName.match(NAMESPACE_REGEX)[0] : "";
return naming.getNamespaceFromTerm(pluginName);
}

/**
Expand All @@ -61,7 +61,7 @@ class Plugins {
* @returns {string} The name of the plugin without the namespace.
*/
static removeNamespace(pluginName) {
return pluginName.replace(NAMESPACE_REGEX, "");
return naming.removeNamespaceFromTerm(pluginName);
}

/**
Expand Down
@@ -0,0 +1 @@
module.exports = function() {};
1 change: 1 addition & 0 deletions tests/fixtures/cli-engine/eslint-formatter-bar/index.js
@@ -0,0 +1 @@
module.exports = function() {};
36 changes: 36 additions & 0 deletions tests/lib/cli-engine.js
Expand Up @@ -2685,6 +2685,42 @@ describe("CLIEngine", () => {
assert.isFunction(formatter);
});

it("should return a function when a formatter prefixed with eslint-formatter is requested", () => {
const engine = new CLIEngine({
cwd: getFixturePath("cli-engine")
}),
formatter = engine.getFormatter("bar");

assert.isFunction(formatter);
});

it("should return a function when a formatter is requested, also when the eslint-formatter prefix is included in the format argument", () => {
const engine = new CLIEngine({
cwd: getFixturePath("cli-engine")
}),
formatter = engine.getFormatter("eslint-formatter-bar");

assert.isFunction(formatter);
});

it("should return a function when a formatter is requested within a scoped npm package", () => {
const engine = new CLIEngine({
cwd: getFixturePath("cli-engine")
}),
formatter = engine.getFormatter("@somenamespace/foo");

assert.isFunction(formatter);
});

it("should return a function when a formatter is requested within a scoped npm package, also when the eslint-formatter prefix is included in the format argument", () => {
const engine = new CLIEngine({
cwd: getFixturePath("cli-engine")
}),
formatter = engine.getFormatter("@somenamespace/eslint-formatter-foo");

assert.isFunction(formatter);
});

it("should return null when a customer formatter doesn't exist", () => {
const engine = new CLIEngine(),
formatterPath = getFixturePath("formatters", "doesntexist.js");
Expand Down

0 comments on commit cd9d6a2

Please sign in to comment.