diff --git a/README.md b/README.md index b435dc8a..658c4a60 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,16 @@ idea to have a look at the [Get Started With ESLint](http://devnull.guru/get-sta blog post by [IanVS](https://github.com/IanVS) and [the ESLint documentation](http://eslint.org/docs/user-guide/configuring), including the [list of rules](http://eslint.org/docs/rules/). +## A Note About Settings + +If Use Global is on, Atom will use the global ESLint. The path to it is figured out by running `npm get prefix`. If this fails for any reason, you can set the global path manually in Global Node Installation Path. + +If Use Global is off, Atom will try to find a local installation in the project folder, look if there's ESLint in `${PROJECT_ROOT}/node_modules` and use it if found. + +The path to the local node_modules folder can be a path relative to the project or an absolute path and should end in /node_modules/. This path is used if the other methods of discovery have failed. + +If there is no local installation Atom will use the built-in ESLint in the linter-eslint package itself. + ## Contributing See the [contributing guidelines](./CONTRIBUTING.md) to get started diff --git a/lib/helpers.js b/lib/helpers.js index 931fe8de..6cb50a6d 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -49,7 +49,7 @@ function spawnWorker() { } function showError(givenMessage) { - var givenDetail = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1]; + var givenDetail = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; var detail = void 0; var message = void 0; @@ -67,7 +67,7 @@ function showError(givenMessage) { } function idsToIgnoredRules() { - var ruleIds = arguments.length <= 0 || arguments[0] === undefined ? [] : arguments[0]; + var ruleIds = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; return ruleIds.reduce(function (ids, id) { ids[id] = RULE_OFF_SEVERITY; diff --git a/lib/main.js b/lib/main.js index 67de0911..4d047634 100644 --- a/lib/main.js +++ b/lib/main.js @@ -52,10 +52,14 @@ module.exports = { this.subscriptions.add(atom.workspace.observeTextEditors(function (editor) { editor.onDidSave(function () { if (scopes.indexOf(editor.getGrammar().scopeName) !== -1 && atom.config.get('linter-eslint.fixOnSave')) { + var filePath = editor.getPath(); + var projectPath = atom.project.relativizePath(filePath)[0]; + _this.worker.request('job', { type: 'fix', config: atom.config.get('linter-eslint'), - filePath: editor.getPath() + filePath: filePath, + projectPath: projectPath }).catch(function (response) { return atom.notifications.addWarning(response); }); @@ -67,6 +71,7 @@ module.exports = { 'linter-eslint:fix-file': function linterEslintFixFile() { var textEditor = atom.workspace.getActiveTextEditor(); var filePath = textEditor.getPath(); + var projectPath = atom.project.relativizePath(filePath)[0]; if (!textEditor || textEditor.isModified()) { // Abort for invalid or unsaved text editors @@ -77,7 +82,8 @@ module.exports = { _this.worker.request('job', { type: 'fix', config: atom.config.get('linter-eslint'), - filePath: filePath + filePath: filePath, + projectPath: projectPath }).then(function (response) { return atom.notifications.addSuccess(response); }).catch(function (response) { @@ -138,11 +144,12 @@ module.exports = { } return _this2.worker.request('job', { - contents: text, type: 'lint', + contents: text, config: atom.config.get('linter-eslint'), rules: rules, - filePath: filePath + filePath: filePath, + projectPath: atom.project.relativizePath(filePath)[0] || '' }).then(function (response) { if (textEditor.getText() !== text) { /* diff --git a/lib/worker-helpers.js b/lib/worker-helpers.js index 7e8ddec2..f073258d 100644 --- a/lib/worker-helpers.js +++ b/lib/worker-helpers.js @@ -52,7 +52,7 @@ function getNodePrefixPath() { return Cache.NODE_PREFIX_PATH; } -function getESLintFromDirectory(modulesDir, config) { +function getESLintFromDirectory(modulesDir, config, projectPath) { var ESLintDirectory = null; if (config.useGlobalEslint) { @@ -62,8 +62,12 @@ function getESLintFromDirectory(modulesDir, config) { } else { ESLintDirectory = _path2.default.join(prefixPath, 'lib', 'node_modules', 'eslint'); } - } else { + } else if (!config.advancedLocalNodeModules) { ESLintDirectory = _path2.default.join(modulesDir || '', 'eslint'); + } else if (_path2.default.isAbsolute(config.advancedLocalNodeModules)) { + ESLintDirectory = _path2.default.join(config.advancedLocalNodeModules || '', 'eslint'); + } else { + ESLintDirectory = _path2.default.join(projectPath, config.advancedLocalNodeModules, 'eslint'); } try { // eslint-disable-next-line import/no-dynamic-require @@ -85,10 +89,10 @@ function refreshModulesPath(modulesDir) { } } -function getESLintInstance(fileDir, config) { +function getESLintInstance(fileDir, config, projectPath) { var modulesDir = _path2.default.dirname((0, _atomLinter.findCached)(fileDir, 'node_modules/eslint') || ''); refreshModulesPath(modulesDir); - return getESLintFromDirectory(modulesDir, config); + return getESLintFromDirectory(modulesDir, config, projectPath || ''); } function getConfigPath(fileDir) { diff --git a/lib/worker.js b/lib/worker.js index fe6de819..76dba0a8 100644 --- a/lib/worker.js +++ b/lib/worker.js @@ -55,6 +55,7 @@ function fixJob(argv, eslint) { var type = _ref.type; var config = _ref.config; var filePath = _ref.filePath; + var projectPath = _ref.projectPath; var rules = _ref.rules; global.__LINTER_ESLINT_RESPONSE = []; @@ -64,7 +65,7 @@ function fixJob(argv, eslint) { } var fileDir = _path2.default.dirname(filePath); - var eslint = Helpers.getESLintInstance(fileDir, config); + var eslint = Helpers.getESLintInstance(fileDir, config, projectPath); var configPath = Helpers.getConfigPath(fileDir); var relativeFilePath = Helpers.getRelativePath(fileDir, filePath, config); diff --git a/package.json b/package.json index f5db30c2..09bea2ea 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,12 @@ "type": "string", "default": "" }, + "advancedLocalNodeModules": { + "title": "Path to the local node_modules folder", + "description": "Optionally specify the path to the local node_modules folder", + "type": "string", + "default": "" + }, "eslintRulesDir": { "title": "ESLint Rules Dir", "description": "Specify a directory for ESLint to load rules from", diff --git a/spec/fixtures/indirect-local-eslint/testing/eslint/.gitignore b/spec/fixtures/indirect-local-eslint/testing/eslint/.gitignore new file mode 100644 index 00000000..e5f6df12 --- /dev/null +++ b/spec/fixtures/indirect-local-eslint/testing/eslint/.gitignore @@ -0,0 +1,2 @@ +# Keep node_modules test fixtures +!node_modules diff --git a/spec/fixtures/indirect-local-eslint/testing/eslint/lib/foo.js b/spec/fixtures/indirect-local-eslint/testing/eslint/lib/foo.js new file mode 100644 index 00000000..be92fda5 --- /dev/null +++ b/spec/fixtures/indirect-local-eslint/testing/eslint/lib/foo.js @@ -0,0 +1 @@ +var foo = 42; diff --git a/spec/fixtures/indirect-local-eslint/testing/eslint/lib/node_modules/.gitkeep b/spec/fixtures/indirect-local-eslint/testing/eslint/lib/node_modules/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/spec/fixtures/indirect-local-eslint/testing/eslint/lib/package.json b/spec/fixtures/indirect-local-eslint/testing/eslint/lib/package.json new file mode 100644 index 00000000..e69de29b diff --git a/spec/fixtures/indirect-local-eslint/testing/eslint/node_modules/eslint/bin/eslint.js b/spec/fixtures/indirect-local-eslint/testing/eslint/node_modules/eslint/bin/eslint.js new file mode 100755 index 00000000..e69de29b diff --git a/spec/fixtures/indirect-local-eslint/testing/eslint/node_modules/eslint/lib/cli.js b/spec/fixtures/indirect-local-eslint/testing/eslint/node_modules/eslint/lib/cli.js new file mode 100644 index 00000000..620463e4 --- /dev/null +++ b/spec/fixtures/indirect-local-eslint/testing/eslint/node_modules/eslint/lib/cli.js @@ -0,0 +1 @@ +module.exports = "located" diff --git a/spec/fixtures/indirect-local-eslint/testing/eslint/package.json b/spec/fixtures/indirect-local-eslint/testing/eslint/package.json new file mode 100644 index 00000000..e69de29b diff --git a/spec/worker-helpers-spec.js b/spec/worker-helpers-spec.js index d02c38ea..9ce0dbe8 100644 --- a/spec/worker-helpers-spec.js +++ b/spec/worker-helpers-spec.js @@ -6,6 +6,27 @@ import { getFixturesPath } from './common' describe('Worker Helpers', () => { describe('getESLintInstance && getESLintFromDirectory', () => { + it('tries to find an indirect local eslint using an absolute path', () => { + const path = Path.join( + getFixturesPath('indirect-local-eslint'), 'testing', 'eslint', 'node_modules') + const eslint = Helpers.getESLintInstance('', { + useGlobalEslint: false, + advancedLocalNodeModules: path + }) + expect(eslint).toBe('located') + }) + it('tries to find an indirect local eslint using a relative path', () => { + const path = Path.join( + getFixturesPath('indirect-local-eslint'), 'testing', 'eslint', 'node_modules') + const [projectPath, relativePath] = atom.project.relativizePath(path) + + const eslint = Helpers.getESLintInstance('', { + useGlobalEslint: false, + advancedLocalNodeModules: relativePath + }, projectPath) + + expect(eslint).toBe('located') + }) it('tries to find a local eslint', () => { const eslint = Helpers.getESLintInstance(getFixturesPath('local-eslint'), {}) expect(eslint).toBe('located') diff --git a/src/main.js b/src/main.js index d6a56619..bdee035d 100644 --- a/src/main.js +++ b/src/main.js @@ -45,10 +45,14 @@ module.exports = { editor.onDidSave(() => { if (scopes.indexOf(editor.getGrammar().scopeName) !== -1 && atom.config.get('linter-eslint.fixOnSave')) { + const filePath = editor.getPath() + const projectPath = atom.project.relativizePath(filePath)[0] + this.worker.request('job', { type: 'fix', config: atom.config.get('linter-eslint'), - filePath: editor.getPath() + filePath, + projectPath }).catch(response => atom.notifications.addWarning(response) ) @@ -60,6 +64,7 @@ module.exports = { 'linter-eslint:fix-file': () => { const textEditor = atom.workspace.getActiveTextEditor() const filePath = textEditor.getPath() + const projectPath = atom.project.relativizePath(filePath)[0] if (!textEditor || textEditor.isModified()) { // Abort for invalid or unsaved text editors @@ -70,7 +75,8 @@ module.exports = { this.worker.request('job', { type: 'fix', config: atom.config.get('linter-eslint'), - filePath + filePath, + projectPath }).then(response => atom.notifications.addSuccess(response) ).catch(response => @@ -128,11 +134,12 @@ module.exports = { } return this.worker.request('job', { - contents: text, type: 'lint', + contents: text, config: atom.config.get('linter-eslint'), rules, - filePath + filePath, + projectPath: atom.project.relativizePath(filePath)[0] || '' }).then((response) => { if (textEditor.getText() !== text) { /* diff --git a/src/worker-helpers.js b/src/worker-helpers.js index 22b3eb5e..d9fac393 100644 --- a/src/worker-helpers.js +++ b/src/worker-helpers.js @@ -29,7 +29,7 @@ export function getNodePrefixPath() { return Cache.NODE_PREFIX_PATH } -export function getESLintFromDirectory(modulesDir, config) { +export function getESLintFromDirectory(modulesDir, config, projectPath) { let ESLintDirectory = null if (config.useGlobalEslint) { @@ -39,8 +39,12 @@ export function getESLintFromDirectory(modulesDir, config) { } else { ESLintDirectory = Path.join(prefixPath, 'lib', 'node_modules', 'eslint') } - } else { + } else if (!config.advancedLocalNodeModules) { ESLintDirectory = Path.join(modulesDir || '', 'eslint') + } else if (Path.isAbsolute(config.advancedLocalNodeModules)) { + ESLintDirectory = Path.join(config.advancedLocalNodeModules || '', 'eslint') + } else { + ESLintDirectory = Path.join(projectPath, config.advancedLocalNodeModules, 'eslint') } try { // eslint-disable-next-line import/no-dynamic-require @@ -64,10 +68,10 @@ export function refreshModulesPath(modulesDir) { } } -export function getESLintInstance(fileDir, config) { +export function getESLintInstance(fileDir, config, projectPath) { const modulesDir = Path.dirname(findCached(fileDir, 'node_modules/eslint') || '') refreshModulesPath(modulesDir) - return getESLintFromDirectory(modulesDir, config) + return getESLintFromDirectory(modulesDir, config, projectPath || '') } export function getConfigPath(fileDir) { diff --git a/src/worker.js b/src/worker.js index e4e26566..1a4b1dd6 100644 --- a/src/worker.js +++ b/src/worker.js @@ -41,7 +41,7 @@ function fixJob(argv, eslint) { } } -create().onRequest('job', ({ contents, type, config, filePath, rules }, job) => { +create().onRequest('job', ({ contents, type, config, filePath, projectPath, rules }, job) => { global.__LINTER_ESLINT_RESPONSE = [] if (config.disableFSCache) { @@ -49,7 +49,7 @@ create().onRequest('job', ({ contents, type, config, filePath, rules }, job) => } const fileDir = Path.dirname(filePath) - const eslint = Helpers.getESLintInstance(fileDir, config) + const eslint = Helpers.getESLintInstance(fileDir, config, projectPath) const configPath = Helpers.getConfigPath(fileDir) const relativeFilePath = Helpers.getRelativePath(fileDir, filePath, config)