From e2068bb0241df2b2ecd764ff4d0973ff03109252 Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Sat, 14 Nov 2015 20:58:57 -0500 Subject: [PATCH 01/41] fixed typo in .editorconfig --- .editorconfig | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.editorconfig b/.editorconfig index 90913036d..e2bfac523 100644 --- a/.editorconfig +++ b/.editorconfig @@ -4,8 +4,6 @@ root = true charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true - -[*.js] indent_style = space -indent_width = 2 +indent_size = 2 end_of_line = lf From 24bb1b20852c6e5994056a7e61eb5118cfdbfa74 Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Sat, 14 Nov 2015 20:59:27 -0500 Subject: [PATCH 02/41] building out webpack resolver. step one: aliases --- .npmignore | 1 + resolvers/webpack/.babelrc | 1 + resolvers/webpack/index.js | 26 ++++++++++++++ resolvers/webpack/package.json | 36 +++++++++++++++++++ resolvers/webpack/test/.eslintrc | 5 +++ resolvers/webpack/test/alias.js | 13 +++++++ resolvers/webpack/test/files/package.json | 1 + .../webpack/test/files/webpack.config.js | 9 +++++ 8 files changed, 92 insertions(+) create mode 100644 resolvers/webpack/.babelrc create mode 100644 resolvers/webpack/index.js create mode 100644 resolvers/webpack/package.json create mode 100644 resolvers/webpack/test/.eslintrc create mode 100644 resolvers/webpack/test/alias.js create mode 100644 resolvers/webpack/test/files/package.json create mode 100644 resolvers/webpack/test/files/webpack.config.js diff --git a/.npmignore b/.npmignore index 34c638a58..eeb6ce496 100644 --- a/.npmignore +++ b/.npmignore @@ -1,6 +1,7 @@ # files src/ reports/ +resolvers/ # config .eslintrc diff --git a/resolvers/webpack/.babelrc b/resolvers/webpack/.babelrc new file mode 100644 index 000000000..9d8d51656 --- /dev/null +++ b/resolvers/webpack/.babelrc @@ -0,0 +1 @@ +{ "presets": ["es2015"] } diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js new file mode 100644 index 000000000..f84433572 --- /dev/null +++ b/resolvers/webpack/index.js @@ -0,0 +1,26 @@ +import findRoot from 'find-root' +import path from 'path' + + +/** + * Find the full path to 'source', given 'file' as a full reference path. + * + * resolveImport('./foo', '/Users/ben/bar.js') => '/Users/ben/foo.js' + * @param {string} source - the module to resolve; i.e './some-module' + * @param {string} file - the importing file's full path; i.e. '/usr/local/bin/file.js' + * TODO: take options as a third param, with webpack config file name + * @return {string} the resolved path to source, or undefined if not resolved + */ +export default function resolveImport(source, file) { + const packageDir = findRoot(file) + if (!packageDir) throw new Error('package not found above ' + file) + + const webpackConfig = require(path.join(packageDir, 'webpack.config.js')) + if (!webpackConfig.resolve) throw new Error('no custom webpack resolve config') + + if (webpackConfig.resolve.alias && + source in webpackConfig.resolve.alias) { + // simple alias lookup + return webpackConfig.resolve.alias[source] + } +} diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json new file mode 100644 index 000000000..afb116365 --- /dev/null +++ b/resolvers/webpack/package.json @@ -0,0 +1,36 @@ +{ + "name": "resolve-webpack", + "version": "0.0.0", + "description": "Resolve paths to dependencies, given a webpack.config.js. Plugin for eslint-plugin-import.", + "main": "index.js", + "scripts": { + "test": "mocha --compilers js:babel-core/register" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/benmosher/eslint-plugin-import.git" + }, + "keywords": [ + "eslint-plugin-import", + "eslint", + "jsnext", + "modules", + "webpack" + ], + "author": "Ben Mosher (me@benmosher.com)", + "license": "MIT", + "bugs": { + "url": "https://github.com/benmosher/eslint-plugin-import/issues" + }, + "homepage": "https://github.com/benmosher/eslint-plugin-import#readme", + "dependencies": { + "find-root": "^0.1.1", + "resolve": "^1.1.6" + }, + "devDependencies": { + "babel-core": "^6.1.21", + "babel-preset-es2015": "^6.1.18", + "chai": "^3.4.1", + "mocha": "^2.3.3" + } +} diff --git a/resolvers/webpack/test/.eslintrc b/resolvers/webpack/test/.eslintrc new file mode 100644 index 000000000..2ad1adee9 --- /dev/null +++ b/resolvers/webpack/test/.eslintrc @@ -0,0 +1,5 @@ +--- +env: + mocha: true +rules: + quotes: 0 diff --git a/resolvers/webpack/test/alias.js b/resolvers/webpack/test/alias.js new file mode 100644 index 000000000..9be5143ea --- /dev/null +++ b/resolvers/webpack/test/alias.js @@ -0,0 +1,13 @@ +import { expect } from 'chai' +import resolve from '../index' + +import path from 'path' + +const file = path.join(__dirname, 'files', 'dummy.js') + +describe("resolve.alias", () => { + it("works", () => { + expect(resolve('foo', file)).to.exist + .and.equal(path.join(__dirname, 'files', 'some', 'goofy', 'path', 'foo.js')) + }) +}) diff --git a/resolvers/webpack/test/files/package.json b/resolvers/webpack/test/files/package.json new file mode 100644 index 000000000..d1d80ba6c --- /dev/null +++ b/resolvers/webpack/test/files/package.json @@ -0,0 +1 @@ +{ "just for show": true } diff --git a/resolvers/webpack/test/files/webpack.config.js b/resolvers/webpack/test/files/webpack.config.js new file mode 100644 index 000000000..9616163da --- /dev/null +++ b/resolvers/webpack/test/files/webpack.config.js @@ -0,0 +1,9 @@ +var path = require('path') + +module.exports = { + resolve: { + alias: { + 'foo': path.join(__dirname, 'some', 'goofy', 'path', 'foo.js'), + }, + }, +} From 0c69a10bbaf634e9a3237c881877519fcbd4902a Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Sat, 14 Nov 2015 21:13:07 -0500 Subject: [PATCH 03/41] webpack resolver: externals --- resolvers/webpack/index.js | 31 +++++++++++++++++-- resolvers/webpack/test/externals.js | 15 +++++++++ .../webpack/test/files/webpack.config.js | 5 +++ 3 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 resolvers/webpack/test/externals.js diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js index f84433572..7918287ab 100644 --- a/resolvers/webpack/index.js +++ b/resolvers/webpack/index.js @@ -9,7 +9,8 @@ import path from 'path' * @param {string} source - the module to resolve; i.e './some-module' * @param {string} file - the importing file's full path; i.e. '/usr/local/bin/file.js' * TODO: take options as a third param, with webpack config file name - * @return {string} the resolved path to source, or undefined if not resolved + * @return {string?} the resolved path to source, undefined if not resolved, or null + * if resolved to a non-FS resource (i.e. script tag at page load) */ export default function resolveImport(source, file) { const packageDir = findRoot(file) @@ -18,9 +19,35 @@ export default function resolveImport(source, file) { const webpackConfig = require(path.join(packageDir, 'webpack.config.js')) if (!webpackConfig.resolve) throw new Error('no custom webpack resolve config') + // simple alias lookup if (webpackConfig.resolve.alias && source in webpackConfig.resolve.alias) { - // simple alias lookup return webpackConfig.resolve.alias[source] } + + // externals + if (findExternal(source, webpackConfig.externals)) return null +} + +function findExternal(source, externals) { + if (!externals) return false + + // string match + if (source === externals) return true + + // array: recurse + if (externals instanceof Array) { + return externals.some(e => findExternal(source, e)) + } + + if (externals instanceof RegExp) { + return externals.test(source) + } + + if (typeof externals === 'function') { + throw new Error('unable to handle function externals') + } + + // else, vanilla object + return Object.keys(externals).some(e => source === e) } diff --git a/resolvers/webpack/test/externals.js b/resolvers/webpack/test/externals.js new file mode 100644 index 000000000..cec524a0e --- /dev/null +++ b/resolvers/webpack/test/externals.js @@ -0,0 +1,15 @@ +import { expect } from 'chai' +import resolve from '../index' + +import path from 'path' + +const file = path.join(__dirname, 'files', 'dummy.js') + +describe("externals", () => { + it("works on just a string", () => { + expect(resolve('bootstrap', file)).to.be.null + }) + it("works on object-map", () => { + expect(resolve('jquery', file)).to.be.null + }) +}) diff --git a/resolvers/webpack/test/files/webpack.config.js b/resolvers/webpack/test/files/webpack.config.js index 9616163da..874104661 100644 --- a/resolvers/webpack/test/files/webpack.config.js +++ b/resolvers/webpack/test/files/webpack.config.js @@ -6,4 +6,9 @@ module.exports = { 'foo': path.join(__dirname, 'some', 'goofy', 'path', 'foo.js'), }, }, + + externals: [ + { 'jquery': 'jQuery' }, + 'bootstrap', + ], } From beb23502c3b1520d33d2212842d654d6a6b35b35 Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Sat, 14 Nov 2015 21:20:24 -0500 Subject: [PATCH 04/41] resolving "real" files too --- resolvers/webpack/index.js | 5 ++++- resolvers/webpack/test/modules.js | 12 ++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 resolvers/webpack/test/modules.js diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js index 7918287ab..1780017c0 100644 --- a/resolvers/webpack/index.js +++ b/resolvers/webpack/index.js @@ -1,6 +1,6 @@ import findRoot from 'find-root' import path from 'path' - +import resolve from 'resolve' /** * Find the full path to 'source', given 'file' as a full reference path. @@ -27,6 +27,9 @@ export default function resolveImport(source, file) { // externals if (findExternal(source, webpackConfig.externals)) return null + + // otherwise, resolve "normally" + return resolve.sync(source, { basedir: path.dirname(file) }) } function findExternal(source, externals) { diff --git a/resolvers/webpack/test/modules.js b/resolvers/webpack/test/modules.js new file mode 100644 index 000000000..096478ba7 --- /dev/null +++ b/resolvers/webpack/test/modules.js @@ -0,0 +1,12 @@ +import { expect } from 'chai' +import resolve from '../index' +import path from 'path' + +const file = path.join(__dirname, 'files', 'dummy.js') + +describe("resolve.moduleDirectories", () => { + it("finds a node module", () => { + expect(resolve('some-module', file)).to.exist + .and.equal(path.join(__dirname, 'files', 'node_modules', 'some-module', 'index.js')) + }) +}) From 434e19d9b91a039005d2af6161cac49fd2d0890d Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Sat, 14 Nov 2015 21:45:06 -0500 Subject: [PATCH 05/41] extensions --- resolvers/webpack/index.js | 6 +++++- resolvers/webpack/test/extensions.js | 13 +++++++++++++ resolvers/webpack/test/files/extensions/foo.web.js | 0 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 resolvers/webpack/test/extensions.js create mode 100644 resolvers/webpack/test/files/extensions/foo.web.js diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js index 1780017c0..a869c493d 100644 --- a/resolvers/webpack/index.js +++ b/resolvers/webpack/index.js @@ -29,7 +29,11 @@ export default function resolveImport(source, file) { if (findExternal(source, webpackConfig.externals)) return null // otherwise, resolve "normally" - return resolve.sync(source, { basedir: path.dirname(file) }) + return resolve.sync(source, { + basedir: path.dirname(file), + // defined via http://webpack.github.io/docs/configuration.html#resolve-extensions + extensions: webpackConfig.resolve.extensions || ['', '.webpack.js', '.web.js', '.js'], + }) } function findExternal(source, externals) { diff --git a/resolvers/webpack/test/extensions.js b/resolvers/webpack/test/extensions.js new file mode 100644 index 000000000..0abd49fc7 --- /dev/null +++ b/resolvers/webpack/test/extensions.js @@ -0,0 +1,13 @@ +import { expect } from 'chai' +import resolve from '../index' + +import path from 'path' + +const file = path.join(__dirname, 'files', 'dummy.js') + +describe("extensions", () => { + it("respects the defaults", () => { + expect(resolve('./extensions/foo', file)).to.exist + .and.equal(path.join(__dirname, 'files', 'extensions', 'foo.web.js')) + }) +}) diff --git a/resolvers/webpack/test/files/extensions/foo.web.js b/resolvers/webpack/test/files/extensions/foo.web.js new file mode 100644 index 000000000..e69de29bb From 4d8352291df7a2d6ff89643cf0dc5559b93c6519 Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Sat, 14 Nov 2015 21:47:48 -0500 Subject: [PATCH 06/41] test webpack resolver with travis --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c34ac82f0..52d0016d2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,9 @@ node_js: env: - NODE_PATH=./lib -script: "npm run-script ci-test" +script: + - "npm run-script ci-test" + - "cd resolvers/webpack && npm install && npm test" after_success: - npm run coveralls From 382f8d4b07cd9f8964ae99d2acda0b666763158d Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Mon, 16 Nov 2015 08:29:37 -0500 Subject: [PATCH 07/41] testing custom extensions --- .../bar.coffee} | 0 .../webpack/test/custom-extensions/baz.web.js | 0 .../webpack/test/custom-extensions/foo.js | 0 .../test/custom-extensions/package.json | 1 + .../test/custom-extensions/webpack.config.js | 3 +++ resolvers/webpack/test/extensions.js | 21 +++++++++++++++++-- resolvers/webpack/test/files/foo.web.js | 0 7 files changed, 23 insertions(+), 2 deletions(-) rename resolvers/webpack/test/{files/extensions/foo.web.js => custom-extensions/bar.coffee} (100%) create mode 100644 resolvers/webpack/test/custom-extensions/baz.web.js create mode 100644 resolvers/webpack/test/custom-extensions/foo.js create mode 100644 resolvers/webpack/test/custom-extensions/package.json create mode 100644 resolvers/webpack/test/custom-extensions/webpack.config.js create mode 100644 resolvers/webpack/test/files/foo.web.js diff --git a/resolvers/webpack/test/files/extensions/foo.web.js b/resolvers/webpack/test/custom-extensions/bar.coffee similarity index 100% rename from resolvers/webpack/test/files/extensions/foo.web.js rename to resolvers/webpack/test/custom-extensions/bar.coffee diff --git a/resolvers/webpack/test/custom-extensions/baz.web.js b/resolvers/webpack/test/custom-extensions/baz.web.js new file mode 100644 index 000000000..e69de29bb diff --git a/resolvers/webpack/test/custom-extensions/foo.js b/resolvers/webpack/test/custom-extensions/foo.js new file mode 100644 index 000000000..e69de29bb diff --git a/resolvers/webpack/test/custom-extensions/package.json b/resolvers/webpack/test/custom-extensions/package.json new file mode 100644 index 000000000..2528e5207 --- /dev/null +++ b/resolvers/webpack/test/custom-extensions/package.json @@ -0,0 +1 @@ +{ "dummy": true } diff --git a/resolvers/webpack/test/custom-extensions/webpack.config.js b/resolvers/webpack/test/custom-extensions/webpack.config.js new file mode 100644 index 000000000..ee3444c00 --- /dev/null +++ b/resolvers/webpack/test/custom-extensions/webpack.config.js @@ -0,0 +1,3 @@ +module.exports = { + resolve: { extensions: ['.js', '.coffee'] }, +} diff --git a/resolvers/webpack/test/extensions.js b/resolvers/webpack/test/extensions.js index 0abd49fc7..a1faac202 100644 --- a/resolvers/webpack/test/extensions.js +++ b/resolvers/webpack/test/extensions.js @@ -4,10 +4,27 @@ import resolve from '../index' import path from 'path' const file = path.join(__dirname, 'files', 'dummy.js') + , extensions = path.join(__dirname, 'custom-extensions', 'dummy.js') describe("extensions", () => { it("respects the defaults", () => { - expect(resolve('./extensions/foo', file)).to.exist - .and.equal(path.join(__dirname, 'files', 'extensions', 'foo.web.js')) + expect(resolve('./foo', file)).to.exist + .and.equal(path.join(__dirname, 'files', 'foo.web.js')) + }) + + describe("resolve.extensions set", () => { + it("works", () => { + expect(resolve('./foo', extensions)).to.exist + .and.equal(path.join(__dirname, 'custom-extensions', 'foo.js')) + }) + + it("replaces defaults", () => { + expect(() => resolve('./baz', extensions)).to.throw(Error) + }) + + it("finds .coffee", () => { + expect(resolve('./bar', extensions)).to.exist + .and.equal(path.join(__dirname, 'custom-extensions', 'bar.coffee')) + }) }) }) diff --git a/resolvers/webpack/test/files/foo.web.js b/resolvers/webpack/test/files/foo.web.js new file mode 100644 index 000000000..e69de29bb From 51d7c4662cc98cfa125dc13efecdef3b39aeb4c2 Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Mon, 16 Nov 2015 08:37:10 -0500 Subject: [PATCH 08/41] modulesDirectories --- resolvers/webpack/index.js | 2 ++ resolvers/webpack/test/files/bower_components/typeahead.js | 0 resolvers/webpack/test/files/webpack.config.js | 1 + resolvers/webpack/test/modules.js | 4 ++++ 4 files changed, 7 insertions(+) create mode 100644 resolvers/webpack/test/files/bower_components/typeahead.js diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js index a869c493d..50a9fc833 100644 --- a/resolvers/webpack/index.js +++ b/resolvers/webpack/index.js @@ -33,6 +33,8 @@ export default function resolveImport(source, file) { basedir: path.dirname(file), // defined via http://webpack.github.io/docs/configuration.html#resolve-extensions extensions: webpackConfig.resolve.extensions || ['', '.webpack.js', '.web.js', '.js'], + // http://webpack.github.io/docs/configuration.html#resolve-modulesdirectories + moduleDirectory: webpackConfig.resolve.modulesDirectories || ['web_modules', 'node_modules'] }) } diff --git a/resolvers/webpack/test/files/bower_components/typeahead.js b/resolvers/webpack/test/files/bower_components/typeahead.js new file mode 100644 index 000000000..e69de29bb diff --git a/resolvers/webpack/test/files/webpack.config.js b/resolvers/webpack/test/files/webpack.config.js index 874104661..2b7ee826c 100644 --- a/resolvers/webpack/test/files/webpack.config.js +++ b/resolvers/webpack/test/files/webpack.config.js @@ -5,6 +5,7 @@ module.exports = { alias: { 'foo': path.join(__dirname, 'some', 'goofy', 'path', 'foo.js'), }, + modulesDirectories: ['node_modules', 'bower_components'], }, externals: [ diff --git a/resolvers/webpack/test/modules.js b/resolvers/webpack/test/modules.js index 096478ba7..15033144c 100644 --- a/resolvers/webpack/test/modules.js +++ b/resolvers/webpack/test/modules.js @@ -9,4 +9,8 @@ describe("resolve.moduleDirectories", () => { expect(resolve('some-module', file)).to.exist .and.equal(path.join(__dirname, 'files', 'node_modules', 'some-module', 'index.js')) }) + it("finds a bower module", () => { + expect(resolve('typeahead.js', file)).to.exist + .and.equal(path.join(__dirname, 'files', 'bower_components', 'typeahead.js')) + }) }) From d555785fb275b7e15ab378c483a40ca023b70436 Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Mon, 16 Nov 2015 08:39:24 -0500 Subject: [PATCH 09/41] oops! forgot node_modules from test directory --- resolvers/webpack/test/files/node_modules/some-module/index.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 resolvers/webpack/test/files/node_modules/some-module/index.js diff --git a/resolvers/webpack/test/files/node_modules/some-module/index.js b/resolvers/webpack/test/files/node_modules/some-module/index.js new file mode 100644 index 000000000..e69de29bb From 5bb9c526562e0e153ffe94e845258505669c15ec Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Mon, 16 Nov 2015 08:45:14 -0500 Subject: [PATCH 10/41] splitting npm install for sub-project --- .travis.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 52d0016d2..446232b1d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,9 +7,13 @@ node_js: env: - NODE_PATH=./lib +install: + - npm install + - "cd resolvers/webpack && npm install && cd ../.." + script: - "npm run-script ci-test" - - "cd resolvers/webpack && npm install && npm test" + - "cd resolvers/webpack && npm test" after_success: - npm run coveralls From be524308df423a119ca47ace20ee1b51210bb7f5 Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Mon, 16 Nov 2015 08:56:42 -0500 Subject: [PATCH 11/41] rudimentary resolve.root. need more tests to ensure it matches webpack semantics --- resolvers/webpack/index.js | 12 +++++++++++- resolvers/webpack/test/files/src/main-module.js | 0 resolvers/webpack/test/files/webpack.config.js | 1 + resolvers/webpack/test/root.js | 13 +++++++++++++ 4 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 resolvers/webpack/test/files/src/main-module.js create mode 100644 resolvers/webpack/test/root.js diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js index 50a9fc833..419af5757 100644 --- a/resolvers/webpack/index.js +++ b/resolvers/webpack/index.js @@ -28,13 +28,23 @@ export default function resolveImport(source, file) { // externals if (findExternal(source, webpackConfig.externals)) return null + const paths = [] + // root as first alternate path + if (webpackConfig.resolve.root) { + paths.push(webpackConfig.resolve.root) + } + // otherwise, resolve "normally" return resolve.sync(source, { basedir: path.dirname(file), + // defined via http://webpack.github.io/docs/configuration.html#resolve-extensions extensions: webpackConfig.resolve.extensions || ['', '.webpack.js', '.web.js', '.js'], + // http://webpack.github.io/docs/configuration.html#resolve-modulesdirectories - moduleDirectory: webpackConfig.resolve.modulesDirectories || ['web_modules', 'node_modules'] + moduleDirectory: webpackConfig.resolve.modulesDirectories || ['web_modules', 'node_modules'], + + paths, }) } diff --git a/resolvers/webpack/test/files/src/main-module.js b/resolvers/webpack/test/files/src/main-module.js new file mode 100644 index 000000000..e69de29bb diff --git a/resolvers/webpack/test/files/webpack.config.js b/resolvers/webpack/test/files/webpack.config.js index 2b7ee826c..6cf72257f 100644 --- a/resolvers/webpack/test/files/webpack.config.js +++ b/resolvers/webpack/test/files/webpack.config.js @@ -6,6 +6,7 @@ module.exports = { 'foo': path.join(__dirname, 'some', 'goofy', 'path', 'foo.js'), }, modulesDirectories: ['node_modules', 'bower_components'], + root: path.join(__dirname, 'src'), }, externals: [ diff --git a/resolvers/webpack/test/root.js b/resolvers/webpack/test/root.js new file mode 100644 index 000000000..6e9dae191 --- /dev/null +++ b/resolvers/webpack/test/root.js @@ -0,0 +1,13 @@ +import { expect } from 'chai' +import resolve from '../index' + +import path from 'path' + +const file = path.join(__dirname, 'files', 'src', 'dummy.js') + +describe("root", () => { + it("works", () => { + expect(resolve('main-module', file)).to.exist + .and.equal(path.join(__dirname, 'files', 'src', 'main-module.js')) + }) +}) From f9dd386a18fb8b817225b4e4dd4831fef70370c1 Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Wed, 18 Nov 2015 07:00:50 -0500 Subject: [PATCH 12/41] fixed issue with string externals when unmatched --- resolvers/webpack/index.js | 2 +- resolvers/webpack/test/extensions.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js index 419af5757..81220fbcb 100644 --- a/resolvers/webpack/index.js +++ b/resolvers/webpack/index.js @@ -52,7 +52,7 @@ function findExternal(source, externals) { if (!externals) return false // string match - if (source === externals) return true + if (typeof externals === 'string') return (source === externals) // array: recurse if (externals instanceof Array) { diff --git a/resolvers/webpack/test/extensions.js b/resolvers/webpack/test/extensions.js index a1faac202..b0bb41bab 100644 --- a/resolvers/webpack/test/extensions.js +++ b/resolvers/webpack/test/extensions.js @@ -9,7 +9,7 @@ const file = path.join(__dirname, 'files', 'dummy.js') describe("extensions", () => { it("respects the defaults", () => { expect(resolve('./foo', file)).to.exist - .and.equal(path.join(__dirname, 'files', 'foo.web.js')) + .and.equal(path.join(__dirname, 'files', 'foo.web.js')) }) describe("resolve.extensions set", () => { From f814d885db662884a7793945e25ef4ccf02fecc6 Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Wed, 18 Nov 2015 07:26:04 -0500 Subject: [PATCH 13/41] moved original resolver code to resolvers/node --- resolvers/node/index.js | 16 ++++++++++++++++ resolvers/node/package.json | 29 +++++++++++++++++++++++++++++ resolvers/webpack/package.json | 2 +- 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 resolvers/node/index.js create mode 100644 resolvers/node/package.json diff --git a/resolvers/node/index.js b/resolvers/node/index.js new file mode 100644 index 000000000..ec9f57942 --- /dev/null +++ b/resolvers/node/index.js @@ -0,0 +1,16 @@ +import resolve from 'resolve' + +export default function resolveImport(source, file, settings) { + if (resolve.isCore(source)) return null + + return resolve.sync(source, opts(file, settings)) +} + +function opts(basedir, settings) { + // pulls all items from 'import/resolve' + return Object.assign( {} + , settings && settings['import/resolve'] + , { basedir: basedir } + ) +} + diff --git a/resolvers/node/package.json b/resolvers/node/package.json new file mode 100644 index 000000000..6a1f26886 --- /dev/null +++ b/resolvers/node/package.json @@ -0,0 +1,29 @@ +{ + "name": "eslint-import-resolver-node", + "version": "0.0.0", + "description": "Node default behavior import resolution plugin for eslint-plugin-import.", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/benmosher/eslint-plugin-import" + }, + "keywords": [ + "eslint", + "eslintplugin", + "esnext", + "modules", + "eslint-plugin-import" + ], + "author": "Ben Mosher (me@benmosher.com)", + "license": "MIT", + "bugs": { + "url": "https://github.com/benmosher/eslint-plugin-import/issues" + }, + "homepage": "https://github.com/benmosher/eslint-plugin-import", + "dependencies": { + "resolve": "^1.1.6" + } +} diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json index afb116365..f2ef3f0dd 100644 --- a/resolvers/webpack/package.json +++ b/resolvers/webpack/package.json @@ -1,5 +1,5 @@ { - "name": "resolve-webpack", + "name": "eslint-import-resolver-webpack", "version": "0.0.0", "description": "Resolve paths to dependencies, given a webpack.config.js. Plugin for eslint-plugin-import.", "main": "index.js", From 071f6b8ea3a4ddcc433d8d3a14b2ac4810093c47 Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Fri, 20 Nov 2015 07:29:13 -0500 Subject: [PATCH 14/41] tests passing for "plugin" node resolver --- package.json | 4 +- resolvers/node/index.js | 7 +-- src/core/resolve.js | 90 +++++++++++++++----------------------- src/rules/no-unresolved.js | 2 +- tests/src/core/resolve.js | 10 ++--- 5 files changed, 46 insertions(+), 67 deletions(-) diff --git a/package.json b/package.json index 530c0a86b..78fc1a1a3 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,8 @@ "ci-test": "npm run-script pretest && mocha --recursive --reporter dot tests/lib/", "debug": "mocha debug --recursive --reporter dot tests/lib/", "compile": "rm -rf lib/ && babel -d lib/ src/", - "prepublish": "npm run compile", - "pretest": "eslint ./src && npm run compile && babel -d tests/lib/ tests/src/", + "prepublish": "eslint ./src && npm run compile", + "pretest": "npm run compile && babel -d tests/lib/ tests/src/", "coveralls": "istanbul cover --report lcovonly --dir reports/coverage _mocha tests/lib/ -- --recursive --reporter dot; remap-istanbul -i reports/coverage/coverage.json -o reports/coverage/lcov.info --type lcovonly && cat ./reports/coverage/lcov.info | coveralls" }, "repository": { diff --git a/resolvers/node/index.js b/resolvers/node/index.js index ec9f57942..1b08c3091 100644 --- a/resolvers/node/index.js +++ b/resolvers/node/index.js @@ -1,9 +1,10 @@ -import resolve from 'resolve' +var resolve = require('resolve') + , path = require('path') -export default function resolveImport(source, file, settings) { +exports.resolveImport = function resolveImport(source, file, settings) { if (resolve.isCore(source)) return null - return resolve.sync(source, opts(file, settings)) + return resolve.sync(source, opts(path.dirname(file), settings)) } function opts(basedir, settings) { diff --git a/src/core/resolve.js b/src/core/resolve.js index a466c83a7..e47740ae4 100644 --- a/src/core/resolve.js +++ b/src/core/resolve.js @@ -1,18 +1,16 @@ -var fs = require('fs') - , path = require('path') - , resolve = require('resolve') +import fs from 'fs' +import { dirname, basename, join } from 'path' -const CASE_INSENSITIVE = fs.existsSync(path.join(__dirname, 'reSOLVE.js')) +import * as defaultResolve from '../../resolvers/node' + +const CASE_INSENSITIVE = fs.existsSync(join(__dirname, 'reSOLVE.js')) // http://stackoverflow.com/a/27382838 function fileExistsWithCaseSync(filepath) { - // shortcut exit - if (!fs.existsSync(filepath)) return false - - var dir = path.dirname(filepath) + var dir = dirname(filepath) if (dir === '/' || dir === '.' || /^[A-Z]:\\$/i.test(dir)) return true var filenames = fs.readdirSync(dir) - if (filenames.indexOf(path.basename(filepath)) === -1) { + if (filenames.indexOf(basename(filepath)) === -1) { return false } return fileExistsWithCaseSync(dir) @@ -20,70 +18,52 @@ function fileExistsWithCaseSync(filepath) { function fileExists(filepath) { if (CASE_INSENSITIVE) { - return fileExistsWithCaseSync(filepath) + // short-circuit if path doesn't exist, ignoring case + return !(!fs.existsSync(filepath) || !fileExistsWithCaseSync(filepath)) } else { return fs.existsSync(filepath) } } -function opts(basedir, settings) { - // pulls all items from 'import/resolve' - return Object.assign( { } - , settings && settings['import/resolve'] - , { basedir: basedir } - ) -} +export function relative(modulePath, sourceFile, settings) { -/** - * wrapper around resolve - * @param {string} p - module path - * @param {object} context - ESLint context - * @return {string} - the full module filesystem path - */ -module.exports = function (p, context) { function withResolver(resolver) { // resolve just returns the core module id, which won't appear to exist - if (resolver.isCore(p)) return p - try { - var file = resolver.sync(p, opts( path.dirname(context.getFilename()) - , context.settings)) - if (!fileExists(file)) return null - return file - } catch (err) { + const filePath = resolver.resolveImport(modulePath, sourceFile, settings) + if (filePath === null) return null - // probably want something more general here - if (err.message.indexOf('Cannot find module') === 0) { - return null - } + if (filePath === undefined || !fileExists(filePath)) return undefined - throw err + return filePath + } catch (err) { + return undefined } } - const resolvers = (context.settings['import/resolvers'] || ['resolve']) - .map(require) + // const resolvers = (context.settings['import/resolvers'] || ['resolve']) + // .map(require) + const resolvers = [ defaultResolve ] for (let resolver of resolvers) { - let file = withResolver(resolver) - if (file) return file + let fullPath = withResolver(resolver) + if (fullPath !== undefined) return fullPath } - return null } -module.exports.relative = function (p, r, settings) { - try { - - var file = resolve.sync(p, opts(path.dirname(r), settings)) - if (!fileExists(file)) return null - return file - - } catch (err) { - - if (err.message.indexOf('Cannot find module') === 0) return null - - throw err // else - - } +/** + * Givent + * @param {string} p - module path + * @param {object} context - ESLint context + * @return {string} - the full module filesystem path; + * null if package is core; + * undefined if not found + */ +export default function resolve(p, context) { + return relative( p + , context.getFilename() + , context.settings + ) } +resolve.relative = relative diff --git a/src/rules/no-unresolved.js b/src/rules/no-unresolved.js index a7af2ac07..402790c8c 100644 --- a/src/rules/no-unresolved.js +++ b/src/rules/no-unresolved.js @@ -9,7 +9,7 @@ module.exports = function (context) { function checkSourceValue(source) { if (source == null) return - if (resolve(source.value, context) == null) { + if (resolve(source.value, context) === undefined) { context.report(source, 'Unable to resolve path to module \'' + source.value + '\'.') } diff --git a/tests/src/core/resolve.js b/tests/src/core/resolve.js index 72c95c1d9..3e48a5d71 100644 --- a/tests/src/core/resolve.js +++ b/tests/src/core/resolve.js @@ -1,9 +1,7 @@ -'use strict' +import { expect } from 'chai' +import resolve from 'core/resolve' -var expect = require('chai').expect - , resolve = require('../../../lib/core/resolve') - -var utils = require('../utils') +import * as utils from '../utils' describe('resolve', function () { it('should throw on bad parameters.', function () { @@ -24,6 +22,6 @@ describe('resolve', function () { , utils.testContext({ 'import/resolve': { 'extensions': ['.jsx'] }}) ) - expect(file).to.equal(null) + expect(file, 'path to ./jsx/MyUncoolComponent').to.be.undefined }) }) From c183a39dbd5737bde02f2214616e097c805fa5ea Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Fri, 20 Nov 2015 07:46:47 -0500 Subject: [PATCH 15/41] explicit object-assign polyfill for node < 4 --- resolvers/node/index.js | 9 +++++---- resolvers/node/package.json | 1 + 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/resolvers/node/index.js b/resolvers/node/index.js index 1b08c3091..46943bf4d 100644 --- a/resolvers/node/index.js +++ b/resolvers/node/index.js @@ -1,5 +1,6 @@ var resolve = require('resolve') , path = require('path') + , assign = require('object-assign') exports.resolveImport = function resolveImport(source, file, settings) { if (resolve.isCore(source)) return null @@ -9,9 +10,9 @@ exports.resolveImport = function resolveImport(source, file, settings) { function opts(basedir, settings) { // pulls all items from 'import/resolve' - return Object.assign( {} - , settings && settings['import/resolve'] - , { basedir: basedir } - ) + return assign( {} + , settings && settings['import/resolve'] + , { basedir: basedir } + ) } diff --git a/resolvers/node/package.json b/resolvers/node/package.json index 6a1f26886..edb615a75 100644 --- a/resolvers/node/package.json +++ b/resolvers/node/package.json @@ -24,6 +24,7 @@ }, "homepage": "https://github.com/benmosher/eslint-plugin-import", "dependencies": { + "object-assign": "^4.0.1", "resolve": "^1.1.6" } } From 0b8985e4c47a6600b6a6a580c72b11bc0ab96755 Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Fri, 20 Nov 2015 07:52:57 -0500 Subject: [PATCH 16/41] install all resolvers on travis --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 446232b1d..cf086b102 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,8 @@ env: install: - npm install - - "cd resolvers/webpack && npm install && cd ../.." + # install all resolver deps + - "for resolver in ./resolvers/*; do cd $resolver && npm install && cd ../..; done" script: - "npm run-script ci-test" From f6e94070552508a49e81ea46d3ee2bcea1193629 Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Tue, 24 Nov 2015 07:00:18 -0500 Subject: [PATCH 17/41] ES5'd webpack resolver to simplify publish/install --- resolvers/webpack/index.js | 8 ++++---- resolvers/webpack/test/alias.js | 2 +- resolvers/webpack/test/extensions.js | 2 +- resolvers/webpack/test/externals.js | 2 +- resolvers/webpack/test/modules.js | 2 +- resolvers/webpack/test/root.js | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js index 81220fbcb..1c26bd1b5 100644 --- a/resolvers/webpack/index.js +++ b/resolvers/webpack/index.js @@ -1,6 +1,6 @@ -import findRoot from 'find-root' -import path from 'path' -import resolve from 'resolve' +const findRoot = require('find-root') + , path = require('path') + , resolve = require('resolve') /** * Find the full path to 'source', given 'file' as a full reference path. @@ -12,7 +12,7 @@ import resolve from 'resolve' * @return {string?} the resolved path to source, undefined if not resolved, or null * if resolved to a non-FS resource (i.e. script tag at page load) */ -export default function resolveImport(source, file) { +exports.resolveImport = function resolveImport(source, file) { const packageDir = findRoot(file) if (!packageDir) throw new Error('package not found above ' + file) diff --git a/resolvers/webpack/test/alias.js b/resolvers/webpack/test/alias.js index 9be5143ea..62c03ce1d 100644 --- a/resolvers/webpack/test/alias.js +++ b/resolvers/webpack/test/alias.js @@ -1,5 +1,5 @@ import { expect } from 'chai' -import resolve from '../index' +import { resolveImport as resolve } from '../index' import path from 'path' diff --git a/resolvers/webpack/test/extensions.js b/resolvers/webpack/test/extensions.js index b0bb41bab..ab6fc84f4 100644 --- a/resolvers/webpack/test/extensions.js +++ b/resolvers/webpack/test/extensions.js @@ -1,5 +1,5 @@ import { expect } from 'chai' -import resolve from '../index' +import { resolveImport as resolve } from '../index' import path from 'path' diff --git a/resolvers/webpack/test/externals.js b/resolvers/webpack/test/externals.js index cec524a0e..38e6cba01 100644 --- a/resolvers/webpack/test/externals.js +++ b/resolvers/webpack/test/externals.js @@ -1,5 +1,5 @@ import { expect } from 'chai' -import resolve from '../index' +import { resolveImport as resolve } from '../index' import path from 'path' diff --git a/resolvers/webpack/test/modules.js b/resolvers/webpack/test/modules.js index 15033144c..21f5721fa 100644 --- a/resolvers/webpack/test/modules.js +++ b/resolvers/webpack/test/modules.js @@ -1,5 +1,5 @@ import { expect } from 'chai' -import resolve from '../index' +import { resolveImport as resolve } from '../index' import path from 'path' const file = path.join(__dirname, 'files', 'dummy.js') diff --git a/resolvers/webpack/test/root.js b/resolvers/webpack/test/root.js index 6e9dae191..fc89b8401 100644 --- a/resolvers/webpack/test/root.js +++ b/resolvers/webpack/test/root.js @@ -1,5 +1,5 @@ import { expect } from 'chai' -import resolve from '../index' +import { resolveImport as resolve } from '../index' import path from 'path' From 0387fdba91278c2e8474c150ad16c836fadf7cfb Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Tue, 24 Nov 2015 07:11:15 -0500 Subject: [PATCH 18/41] handle no package found, no webpack config found --- resolvers/webpack/index.js | 34 +++++++++++++++++++++------------- resolvers/webpack/package.json | 1 + 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js index 1c26bd1b5..5c00de6f3 100644 --- a/resolvers/webpack/index.js +++ b/resolvers/webpack/index.js @@ -1,6 +1,7 @@ const findRoot = require('find-root') , path = require('path') , resolve = require('resolve') + , get = require('lodash.get') /** * Find the full path to 'source', given 'file' as a full reference path. @@ -13,36 +14,43 @@ const findRoot = require('find-root') * if resolved to a non-FS resource (i.e. script tag at page load) */ exports.resolveImport = function resolveImport(source, file) { - const packageDir = findRoot(file) - if (!packageDir) throw new Error('package not found above ' + file) - const webpackConfig = require(path.join(packageDir, 'webpack.config.js')) - if (!webpackConfig.resolve) throw new Error('no custom webpack resolve config') + var webpackConfig + try { + var packageDir = findRoot(file) + if (!packageDir) throw new Error('package not found above ' + file) + + webpackConfig = require(path.join(packageDir, 'webpack.config.js')) + } catch (err) { + webpackConfig = {} + } // simple alias lookup - if (webpackConfig.resolve.alias && - source in webpackConfig.resolve.alias) { - return webpackConfig.resolve.alias[source] + var resolveAliases = get(webpackConfig, 'resolve.alias') + if (resolveAliases && source in resolveAliases) { + return resolveAliases[source] } // externals if (findExternal(source, webpackConfig.externals)) return null - const paths = [] + var paths = [] + // root as first alternate path - if (webpackConfig.resolve.root) { - paths.push(webpackConfig.resolve.root) - } + var rootPath = get(webpackConfig, 'resolve.root') + if (rootPath) paths.push(rootPath) // otherwise, resolve "normally" return resolve.sync(source, { basedir: path.dirname(file), // defined via http://webpack.github.io/docs/configuration.html#resolve-extensions - extensions: webpackConfig.resolve.extensions || ['', '.webpack.js', '.web.js', '.js'], + extensions: get(webpackConfig, 'resolve.extensions') + || ['', '.webpack.js', '.web.js', '.js'], // http://webpack.github.io/docs/configuration.html#resolve-modulesdirectories - moduleDirectory: webpackConfig.resolve.modulesDirectories || ['web_modules', 'node_modules'], + moduleDirectory: get(webpackConfig, 'resolve.modulesDirectories') + || ['web_modules', 'node_modules'], paths, }) diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json index f2ef3f0dd..35c2632b1 100644 --- a/resolvers/webpack/package.json +++ b/resolvers/webpack/package.json @@ -25,6 +25,7 @@ "homepage": "https://github.com/benmosher/eslint-plugin-import#readme", "dependencies": { "find-root": "^0.1.1", + "lodash.get": "^3.7.0", "resolve": "^1.1.6" }, "devDependencies": { From ee686fd78e0435534ced0e48a85625ba976644b3 Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Tue, 24 Nov 2015 07:17:29 -0500 Subject: [PATCH 19/41] handle core modules in webpack resolver --- resolvers/webpack/index.js | 2 ++ resolvers/webpack/test/externals.js | 14 ++++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js index 5c00de6f3..68e7e73e1 100644 --- a/resolvers/webpack/index.js +++ b/resolvers/webpack/index.js @@ -15,6 +15,8 @@ const findRoot = require('find-root') */ exports.resolveImport = function resolveImport(source, file) { + if (resolve.isCore(source)) return null + var webpackConfig try { var packageDir = findRoot(file) diff --git a/resolvers/webpack/test/externals.js b/resolvers/webpack/test/externals.js index 38e6cba01..5566acdc5 100644 --- a/resolvers/webpack/test/externals.js +++ b/resolvers/webpack/test/externals.js @@ -6,10 +6,12 @@ import path from 'path' const file = path.join(__dirname, 'files', 'dummy.js') describe("externals", () => { - it("works on just a string", () => { - expect(resolve('bootstrap', file)).to.be.null - }) - it("works on object-map", () => { - expect(resolve('jquery', file)).to.be.null - }) + it("works on just a string", () => + expect(resolve('bootstrap', file)).to.be.null) + + it("works on object-map", () => + expect(resolve('jquery', file)).to.be.null) + + it("returns null for core modules", () => + expect(resolve('fs', file)).to.be.null) }) From 730f5baaea2a402a0ce9cb784b257cca2e61a058 Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Tue, 24 Nov 2015 16:34:27 -0500 Subject: [PATCH 20/41] tests passing, resolvers are now based on settings --- package.json | 4 +++- src/core/resolve.js | 7 ++----- tests/files/package.json | 1 + tests/files/webpack.config.js | 6 ++++++ 4 files changed, 12 insertions(+), 6 deletions(-) create mode 100644 tests/files/package.json create mode 100644 tests/files/webpack.config.js diff --git a/package.json b/package.json index 78fc1a1a3..b8b208968 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,9 @@ "eslint": ">=1.8.0", "istanbul": "^0.4.0", "mocha": "^2.2.1", - "remap-istanbul": "^0.4.0" + "remap-istanbul": "^0.4.0", + "eslint-import-resolver-webpack": "file:./resolvers/webpack", + "eslint-import-resolver-node": "file:./resolvers/node" }, "peerDependencies": { "eslint": ">=1.4.0" diff --git a/src/core/resolve.js b/src/core/resolve.js index e47740ae4..eeaceefbc 100644 --- a/src/core/resolve.js +++ b/src/core/resolve.js @@ -1,8 +1,6 @@ import fs from 'fs' import { dirname, basename, join } from 'path' -import * as defaultResolve from '../../resolvers/node' - const CASE_INSENSITIVE = fs.existsSync(join(__dirname, 'reSOLVE.js')) // http://stackoverflow.com/a/27382838 @@ -41,9 +39,8 @@ export function relative(modulePath, sourceFile, settings) { } } - // const resolvers = (context.settings['import/resolvers'] || ['resolve']) - // .map(require) - const resolvers = [ defaultResolve ] + const resolvers = (settings['import/resolvers'] || ['node']) + .map(suffix => require(`eslint-import-resolver-${suffix}`)) for (let resolver of resolvers) { let fullPath = withResolver(resolver) diff --git a/tests/files/package.json b/tests/files/package.json new file mode 100644 index 000000000..0a5fb6e23 --- /dev/null +++ b/tests/files/package.json @@ -0,0 +1 @@ +{ "dummy": true } \ No newline at end of file diff --git a/tests/files/webpack.config.js b/tests/files/webpack.config.js new file mode 100644 index 000000000..93986f37a --- /dev/null +++ b/tests/files/webpack.config.js @@ -0,0 +1,6 @@ +module.exports = { + resolve: { + extensions: ['.js', '.jsx'], + root: __dirname, + }, +} From a76cb00849d94fd9e9b74296560039945013811d Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Tue, 24 Nov 2015 16:55:02 -0500 Subject: [PATCH 21/41] dynamic tests for both resolvers + concrete tests for each --- tests/src/rules/no-unresolved.js | 342 +++++++++++++++++-------------- 1 file changed, 187 insertions(+), 155 deletions(-) diff --git a/tests/src/rules/no-unresolved.js b/tests/src/rules/no-unresolved.js index c9cc0bd3f..dccd30284 100644 --- a/tests/src/rules/no-unresolved.js +++ b/tests/src/rules/no-unresolved.js @@ -7,13 +7,182 @@ import { RuleTester } from 'eslint' var ruleTester = new RuleTester() , rule = require('../../../lib/rules/no-unresolved') -ruleTester.run('no-unresolved', rule, { +function runResolverTests(resolver) { + // redefine 'test' to set a resolver + // thus 'rest'. needed something 4-chars-long for formatting simplicity + function rest(specs) { + specs.settings = Object.assign({}, + specs.settings, + { 'import/resolvers': [ resolver ] } + ) + + return test(specs) + } + + ruleTester.run(`no-unresolved (${resolver})`, rule, { + valid: [ + rest({ code: 'import foo from "./bar";' }), + rest({ code: "import bar from './bar.js';" }), + rest({ code: "import {someThing} from './module';" }), + rest({ code: "import fs from 'fs';" }), + + rest({ code: 'import * as foo from "a"' }), + + rest({ code: 'export { foo } from "./bar"' }), + rest({ code: 'export * from "./bar"' }), + rest({ code: 'export { foo }' }), + + // stage 1 proposal for export symmetry, + rest({ code: 'export * as bar from "./bar"' + , parser: 'babel-eslint' }), + rest({ code: 'export bar from "./bar"' + , parser: 'babel-eslint' }), + rest({ code: 'import foo from "./jsx/MyUnCoolComponent.jsx"' }), + + // commonjs setting + rest({ code: 'var foo = require("./bar")' + , options: [{ commonjs: true }]}), + rest({ code: 'require("./bar")' + , options: [{ commonjs: true }]}), + rest({ code: 'require("./does-not-exist")' + , options: [{ commonjs: false }]}), + rest({ code: 'require("./does-not-exist")' }), + + // amd setting + rest({ code: 'require(["./bar"], function (bar) {})' + , options: [{ amd: true }]}), + rest({ code: 'define(["./bar"], function (bar) {})' + , options: [{ amd: true }]}), + rest({ code: 'require(["./does-not-exist"], function (bar) {})' + , options: [{ amd: false }]}), + // don't validate without callback param + rest({ code: 'require(["./does-not-exist"])' + , options: [{ amd: true }]}), + rest({ code: 'define(["./does-not-exist"], function (bar) {})' }), + + // stress tests + rest({ code: 'require("./does-not-exist", "another arg")' + , options: [{ commonjs: true, amd: true }]}), + rest({ code: 'proxyquire("./does-not-exist")' + , options: [{ commonjs: true, amd: true }]}), + rest({ code: '(function() {})("./does-not-exist")' + , options: [{ commonjs: true, amd: true }]}), + rest({ code: 'define([0, foo], function (bar) {})' + , options: [{ amd: true }]}), + rest({ code: 'require(0)' + , options: [{ commonjs: true }]}), + rest({ code: 'require(foo)' + , options: [{ commonjs: true }]}), + + ], + + invalid: [ + rest({ + code: 'import reallyfake from "./reallyfake/module"', + settings: { 'import/ignore': ['^\\./fake/'] }, + errors: [{ message: 'Unable to resolve path to module ' + + '\'./reallyfake/module\'.' }], + }), + + + rest({ + code: "import bar from './baz';", + errors: [{ message: "Unable to resolve path to module './baz'." + , type: 'Literal' }], + }), + rest({ code: "import bar from './baz';" + , errors: [{ message: "Unable to resolve path to module './baz'." + , type: 'Literal', + }] }), + rest({ + code: "import bar from './empty-folder';", + errors: [{ message: "Unable to resolve path to module './empty-folder'." + , type: 'Literal', + }]}), + + // sanity check that this module is _not_ found without proper settings + rest({ + code: "import { DEEP } from 'in-alternate-root';", + errors: [{ message: 'Unable to resolve path to ' + + "module 'in-alternate-root'." + , type: 'Literal', + }]}), + + rest({ code: 'export { foo } from "./does-not-exist"' + , errors: 1 }), + rest({ + code: 'export * from "./does-not-exist"', + errors: 1, + }), + + // export symmetry proposal + rest({ code: 'export * as bar from "./does-not-exist"' + , parser: 'babel-eslint' + , errors: 1, + }), + rest({ code: 'export bar from "./does-not-exist"' + , parser: 'babel-eslint' + , errors: 1, + }), + + rest({ code: 'import foo from "./jsx/MyUncoolComponent.jsx"' + , errors: 1 }), + + + // commonjs setting + rest({ + code: 'var bar = require("./baz")', + options: [{ commonjs: true }], + errors: [{ + message: "Unable to resolve path to module './baz'.", + type: 'Literal', + }], + }), + rest({ + code: 'require("./baz")', + options: [{ commonjs: true }], + errors: [{ + message: "Unable to resolve path to module './baz'.", + type: 'Literal', + }], + }), + + // amd + rest({ + code: 'require(["./baz"], function (bar) {})', + options: [{ amd: true }], + errors: [{ + message: "Unable to resolve path to module './baz'.", + type: 'Literal', + }], + }), + rest({ + code: 'define(["./baz"], function (bar) {})', + options: [{ amd: true }], + errors: [{ + message: "Unable to resolve path to module './baz'.", + type: 'Literal', + }], + }), + rest({ + code: 'define(["./baz", "./bar", "./does-not-exist"], function (bar) {})', + options: [{ amd: true }], + errors: [{ + message: "Unable to resolve path to module './baz'.", + type: 'Literal', + },{ + message: "Unable to resolve path to module './does-not-exist'.", + type: 'Literal', + }], + }), + ], + }) +} + +['node', 'webpack'].forEach(runResolverTests) + +ruleTester.run('no-unresolved (node-specific)', rule, { valid: [ - test({ code: 'import foo from "./bar";' }), - test({ code: "import bar from './bar.js';" }), - test({ code: "import {someThing} from './module';" }), - test({ code: "import fs from 'fs';" }), - test({ code: "import { DEEP } from 'in-alternate-root';", settings: { @@ -23,6 +192,7 @@ ruleTester.run('no-unresolved', rule, { }, }, }), + test({ code: "import { DEEP } from 'in-alternate-root'; " + "import { bar } from 'src-bar';", @@ -31,167 +201,29 @@ ruleTester.run('no-unresolved', rule, { path.join('tests', 'files', 'alternate-root'), ]}}}), - test({ code: 'import * as foo from "a"' }), - test({ code: 'import * as foo from "jsx-module/foo"', settings: { 'import/resolve': { 'extensions': ['.jsx'] } }, }), - - test({ code: 'export { foo } from "./bar"' }), - test({ code: 'export * from "./bar"' }), - test({ code: 'export { foo }' }), - - // stage 1 proposal for export symmetry, - test({ code: 'export * as bar from "./bar"' - , parser: 'babel-eslint' }), - test({ code: 'export bar from "./bar"' - , parser: 'babel-eslint' }), - test({ code: 'import foo from "./jsx/MyUnCoolComponent.jsx"' }), - - // commonjs setting - test({ code: 'var foo = require("./bar")' - , options: [{ commonjs: true }]}), - test({ code: 'require("./bar")' - , options: [{ commonjs: true }]}), - test({ code: 'require("./does-not-exist")' - , options: [{ commonjs: false }]}), - test({ code: 'require("./does-not-exist")' }), - - // amd setting - test({ code: 'require(["./bar"], function (bar) {})' - , options: [{ amd: true }]}), - test({ code: 'define(["./bar"], function (bar) {})' - , options: [{ amd: true }]}), - test({ code: 'require(["./does-not-exist"], function (bar) {})' - , options: [{ amd: false }]}), - // don't validate without callback param - test({ code: 'require(["./does-not-exist"])' - , options: [{ amd: true }]}), - test({ code: 'define(["./does-not-exist"], function (bar) {})' }), - - // stress tests - test({ code: 'require("./does-not-exist", "another arg")' - , options: [{ commonjs: true, amd: true }]}), - test({ code: 'proxyquire("./does-not-exist")' - , options: [{ commonjs: true, amd: true }]}), - test({ code: '(function() {})("./does-not-exist")' - , options: [{ commonjs: true, amd: true }]}), - test({ code: 'define([0, foo], function (bar) {})' - , options: [{ amd: true }]}), - test({ code: 'require(0)' - , options: [{ commonjs: true }]}), - test({ code: 'require(foo)' - , options: [{ commonjs: true }]}), - ], invalid: [ - // should fail for jsx by default test({ code: 'import * as foo from "jsx-module/foo"', - errors: [ {message: 'Unable to resolve path to ' + - 'module \'jsx-module/foo\'.'} ], - }), - - - test({ - code: 'import reallyfake from "./reallyfake/module"', - settings: { 'import/ignore': ['^\\./fake/'] }, - errors: [{ message: 'Unable to resolve path to module ' + - '\'./reallyfake/module\'.' }], - }), - - - test({ - code: "import bar from './baz';", - errors: [{ message: "Unable to resolve path to module './baz'." - , type: 'Literal' }], - }), - test({ code: "import bar from './baz';" - , errors: [{ message: "Unable to resolve path to module './baz'." - , type: 'Literal', - }] }), - test({ - code: "import bar from './empty-folder';", - errors: [{ message: "Unable to resolve path to module './empty-folder'." - , type: 'Literal', - }]}), - - // sanity check that this module is _not_ found without proper settings - test({ - code: "import { DEEP } from 'in-alternate-root';", - errors: [{ message: 'Unable to resolve path to ' + - "module 'in-alternate-root'." - , type: 'Literal', - }]}), - - test({ code: 'export { foo } from "./does-not-exist"' - , errors: 1 }), - test({ - code: 'export * from "./does-not-exist"', - errors: 1, - }), - - // export symmetry proposal - test({ code: 'export * as bar from "./does-not-exist"' - , parser: 'babel-eslint' - , errors: 1, - }), - test({ code: 'export bar from "./does-not-exist"' - , parser: 'babel-eslint' - , errors: 1, - }), - - test({ code: 'import foo from "./jsx/MyUncoolComponent.jsx"' - , errors: 1 }), - - - // commonjs setting - test({ - code: 'var bar = require("./baz")', - options: [{ commonjs: true }], - errors: [{ - message: "Unable to resolve path to module './baz'.", - type: 'Literal', - }], - }), - test({ - code: 'require("./baz")', - options: [{ commonjs: true }], - errors: [{ - message: "Unable to resolve path to module './baz'.", - type: 'Literal', - }], + errors: [ "Unable to resolve path to module 'jsx-module/foo'." ], }), + ], +}) - // amd - test({ - code: 'require(["./baz"], function (bar) {})', - options: [{ amd: true }], - errors: [{ - message: "Unable to resolve path to module './baz'.", - type: 'Literal', - }], - }), - test({ - code: 'define(["./baz"], function (bar) {})', - options: [{ amd: true }], - errors: [{ - message: "Unable to resolve path to module './baz'.", - type: 'Literal', - }], - }), +ruleTester.run('no-unresolved (webpack-specific)', rule, { + valid: [ test({ - code: 'define(["./baz", "./bar", "./does-not-exist"], function (bar) {})', - options: [{ amd: true }], - errors: [{ - message: "Unable to resolve path to module './baz'.", - type: 'Literal', - },{ - message: "Unable to resolve path to module './does-not-exist'.", - type: 'Literal', - }], + // default webpack config in files/webpack.config.js knows about jsx + code: 'import * as foo from "jsx-module/foo"', + settings: { 'import/resolvers': [ 'webpack' ] }, }), ], + invalid: [ + // todo: alternate empty config shouldn't find it + ], }) From a2cd08d8acb1c856f6a987c013a1c01b88d33b14 Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Wed, 25 Nov 2015 08:55:43 -0500 Subject: [PATCH 22/41] resolver settings + webpack takes a "config" settings with the config file name. --- .eslintrc | 1 + resolvers/node/index.js | 9 ++++--- resolvers/webpack/index.js | 4 ++-- src/core/resolve.js | 37 ++++++++++++++++++++++++----- tests/files/webpack.empty.config.js | 1 + tests/src/rules/no-unresolved.js | 11 +++++++-- 6 files changed, 48 insertions(+), 15 deletions(-) create mode 100644 tests/files/webpack.empty.config.js diff --git a/.eslintrc b/.eslintrc index 230d90155..f27ff79e4 100644 --- a/.eslintrc +++ b/.eslintrc @@ -12,3 +12,4 @@ rules: curly: [2, "multi-line"] comma-dangle: [2, always-multiline] eqeqeq: [2, "allow-null"] + no-shadow: 1 diff --git a/resolvers/node/index.js b/resolvers/node/index.js index 46943bf4d..6cb03d884 100644 --- a/resolvers/node/index.js +++ b/resolvers/node/index.js @@ -2,16 +2,15 @@ var resolve = require('resolve') , path = require('path') , assign = require('object-assign') -exports.resolveImport = function resolveImport(source, file, settings) { +exports.resolveImport = function resolveImport(source, file, config) { if (resolve.isCore(source)) return null - return resolve.sync(source, opts(path.dirname(file), settings)) + return resolve.sync(source, opts(path.dirname(file), config)) } -function opts(basedir, settings) { - // pulls all items from 'import/resolve' +function opts(basedir, config) { return assign( {} - , settings && settings['import/resolve'] + , config , { basedir: basedir } ) } diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js index 68e7e73e1..4ff1a7112 100644 --- a/resolvers/webpack/index.js +++ b/resolvers/webpack/index.js @@ -13,7 +13,7 @@ const findRoot = require('find-root') * @return {string?} the resolved path to source, undefined if not resolved, or null * if resolved to a non-FS resource (i.e. script tag at page load) */ -exports.resolveImport = function resolveImport(source, file) { +exports.resolveImport = function resolveImport(source, file, settings) { if (resolve.isCore(source)) return null @@ -22,7 +22,7 @@ exports.resolveImport = function resolveImport(source, file) { var packageDir = findRoot(file) if (!packageDir) throw new Error('package not found above ' + file) - webpackConfig = require(path.join(packageDir, 'webpack.config.js')) + webpackConfig = require(path.join(packageDir, get(settings, 'config', 'webpack.config.js'))) } catch (err) { webpackConfig = {} } diff --git a/src/core/resolve.js b/src/core/resolve.js index eeaceefbc..28273d464 100644 --- a/src/core/resolve.js +++ b/src/core/resolve.js @@ -25,10 +25,10 @@ function fileExists(filepath) { export function relative(modulePath, sourceFile, settings) { - function withResolver(resolver) { + function withResolver(resolver, config) { // resolve just returns the core module id, which won't appear to exist try { - const filePath = resolver.resolveImport(modulePath, sourceFile, settings) + const filePath = resolver.resolveImport(modulePath, sourceFile, config) if (filePath === null) return null if (filePath === undefined || !fileExists(filePath)) return undefined @@ -39,16 +39,41 @@ export function relative(modulePath, sourceFile, settings) { } } - const resolvers = (settings['import/resolvers'] || ['node']) - .map(suffix => require(`eslint-import-resolver-${suffix}`)) + const configResolvers = (settings['import/resolvers'] + || { 'node': settings['import/resolve'] }) // backward compatibility - for (let resolver of resolvers) { - let fullPath = withResolver(resolver) + const resolvers = resolverReducer(configResolvers, new Map()) + + for (let [name, config] of resolvers.entries()) { + const resolver = require(`eslint-import-resolver-${name}`) + + let fullPath = withResolver(resolver, config) if (fullPath !== undefined) return fullPath } } +function resolverReducer(resolvers, map) { + if (resolvers instanceof Array) { + resolvers.forEach(r => resolverReducer(r, map)) + return map + } + + if (typeof resolvers === 'string') { + map.set(resolvers, null) + return map + } + + if (typeof resolvers === 'object') { + for (let key in resolvers) { + map.set(key, resolvers[key]) + } + return map + } + + throw new Error('invalid resolver config') +} + /** * Givent * @param {string} p - module path diff --git a/tests/files/webpack.empty.config.js b/tests/files/webpack.empty.config.js new file mode 100644 index 000000000..7c6d6c73d --- /dev/null +++ b/tests/files/webpack.empty.config.js @@ -0,0 +1 @@ +module.exports = {} \ No newline at end of file diff --git a/tests/src/rules/no-unresolved.js b/tests/src/rules/no-unresolved.js index dccd30284..1c0363bd2 100644 --- a/tests/src/rules/no-unresolved.js +++ b/tests/src/rules/no-unresolved.js @@ -181,7 +181,7 @@ function runResolverTests(resolver) { ['node', 'webpack'].forEach(runResolverTests) -ruleTester.run('no-unresolved (node-specific)', rule, { +ruleTester.run('no-unresolved (import/resolve legacy)', rule, { valid: [ test({ code: "import { DEEP } from 'in-alternate-root';", @@ -224,6 +224,13 @@ ruleTester.run('no-unresolved (webpack-specific)', rule, { }), ], invalid: [ - // todo: alternate empty config shouldn't find it + test({ + // default webpack config in files/webpack.config.js knows about jsx + code: 'import * as foo from "jsx-module/foo"', + settings: { + 'import/resolvers': { 'webpack': { 'config': 'webpack.empty.config.js' } }, + }, + errors: [ "Unable to resolve path to module 'jsx-module/foo'." ], + }), ], }) From 1495a9fef6a81943e18dab50d59494e2faa6bf63 Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Thu, 26 Nov 2015 08:49:25 -0500 Subject: [PATCH 23/41] ignore loaders; just uses final path segment --- resolvers/webpack/index.js | 7 +++++++ tests/src/rules/no-unresolved.js | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js index 4ff1a7112..d7f791b34 100644 --- a/resolvers/webpack/index.js +++ b/resolvers/webpack/index.js @@ -15,6 +15,13 @@ const findRoot = require('find-root') */ exports.resolveImport = function resolveImport(source, file, settings) { + // strip loaders + const finalBang = source.lastIndexOf('!') + if (finalBang >= 0) { + source = source.slice(finalBang + 1) + } + + if (resolve.isCore(source)) return null var webpackConfig diff --git a/tests/src/rules/no-unresolved.js b/tests/src/rules/no-unresolved.js index 1c0363bd2..91b69f038 100644 --- a/tests/src/rules/no-unresolved.js +++ b/tests/src/rules/no-unresolved.js @@ -222,6 +222,11 @@ ruleTester.run('no-unresolved (webpack-specific)', rule, { code: 'import * as foo from "jsx-module/foo"', settings: { 'import/resolvers': [ 'webpack' ] }, }), + test({ + // should ignore loaders + code: 'import * as foo from "some-loader?with=args!jsx-module/foo"', + settings: { 'import/resolvers': [ 'webpack' ] }, + }), ], invalid: [ test({ From d3723e12620f8f0896f9c12cb40da77b4198b6a7 Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Thu, 26 Nov 2015 09:03:18 -0500 Subject: [PATCH 24/41] oops! advanced object literal snuck in there. --- resolvers/webpack/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js index d7f791b34..a347d5cc6 100644 --- a/resolvers/webpack/index.js +++ b/resolvers/webpack/index.js @@ -61,7 +61,7 @@ exports.resolveImport = function resolveImport(source, file, settings) { moduleDirectory: get(webpackConfig, 'resolve.modulesDirectories') || ['web_modules', 'node_modules'], - paths, + paths: paths, }) } From a275569a95da319ce3e5840b6a84ff685e689216 Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Thu, 26 Nov 2015 09:29:31 -0500 Subject: [PATCH 25/41] more ES6 rollback for webpack resolver --- resolvers/.eslintrc | 3 +++ resolvers/webpack/index.js | 14 +++++++------- 2 files changed, 10 insertions(+), 7 deletions(-) create mode 100644 resolvers/.eslintrc diff --git a/resolvers/.eslintrc b/resolvers/.eslintrc new file mode 100644 index 000000000..9db33eda4 --- /dev/null +++ b/resolvers/.eslintrc @@ -0,0 +1,3 @@ +--- +env: + es6: false diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js index a347d5cc6..d75e91f4b 100644 --- a/resolvers/webpack/index.js +++ b/resolvers/webpack/index.js @@ -1,7 +1,7 @@ -const findRoot = require('find-root') - , path = require('path') - , resolve = require('resolve') - , get = require('lodash.get') +var findRoot = require('find-root') + , path = require('path') + , resolve = require('resolve') + , get = require('lodash.get') /** * Find the full path to 'source', given 'file' as a full reference path. @@ -16,7 +16,7 @@ const findRoot = require('find-root') exports.resolveImport = function resolveImport(source, file, settings) { // strip loaders - const finalBang = source.lastIndexOf('!') + var finalBang = source.lastIndexOf('!') if (finalBang >= 0) { source = source.slice(finalBang + 1) } @@ -73,7 +73,7 @@ function findExternal(source, externals) { // array: recurse if (externals instanceof Array) { - return externals.some(e => findExternal(source, e)) + return externals.some(function (e) { return findExternal(source, e) }) } if (externals instanceof RegExp) { @@ -85,5 +85,5 @@ function findExternal(source, externals) { } // else, vanilla object - return Object.keys(externals).some(e => source === e) + return Object.keys(externals).some(function (e) { return source === e }) } From 1835c17a1fe588cdbb3a48999da13a331214a981 Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Thu, 26 Nov 2015 09:38:15 -0500 Subject: [PATCH 26/41] prepping to actually implement webpack alias rules --- resolvers/webpack/index.js | 11 +++++------ resolvers/webpack/resolve-alias.js | 7 +++++++ resolvers/webpack/test/alias.js | 15 ++++++++------- .../webpack/test/files/some/goofy/path/foo.js | 0 4 files changed, 20 insertions(+), 13 deletions(-) create mode 100644 resolvers/webpack/resolve-alias.js create mode 100644 resolvers/webpack/test/files/some/goofy/path/foo.js diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js index d75e91f4b..447b585b2 100644 --- a/resolvers/webpack/index.js +++ b/resolvers/webpack/index.js @@ -3,6 +3,8 @@ var findRoot = require('find-root') , resolve = require('resolve') , get = require('lodash.get') +var resolveAlias = require('./resolve-alias') + /** * Find the full path to 'source', given 'file' as a full reference path. * @@ -34,15 +36,12 @@ exports.resolveImport = function resolveImport(source, file, settings) { webpackConfig = {} } - // simple alias lookup - var resolveAliases = get(webpackConfig, 'resolve.alias') - if (resolveAliases && source in resolveAliases) { - return resolveAliases[source] - } - // externals if (findExternal(source, webpackConfig.externals)) return null + // replace alias if needed + source = resolveAlias(source, get(webpackConfig, 'resolve.alias')) + var paths = [] // root as first alternate path diff --git a/resolvers/webpack/resolve-alias.js b/resolvers/webpack/resolve-alias.js new file mode 100644 index 000000000..31c715d41 --- /dev/null +++ b/resolvers/webpack/resolve-alias.js @@ -0,0 +1,7 @@ +module.exports = function resolveAlias(path, aliases) { + if (aliases && path in aliases) { + return aliases[path] + } + + return path +} diff --git a/resolvers/webpack/test/alias.js b/resolvers/webpack/test/alias.js index 62c03ce1d..da4dfbf2f 100644 --- a/resolvers/webpack/test/alias.js +++ b/resolvers/webpack/test/alias.js @@ -1,13 +1,14 @@ -import { expect } from 'chai' -import { resolveImport as resolve } from '../index' +var chai = require('chai') + , expect = chai.expect + , path = require('path') -import path from 'path' +var webpack = require('../index') -const file = path.join(__dirname, 'files', 'dummy.js') +var file = path.join(__dirname, 'files', 'dummy.js') -describe("resolve.alias", () => { - it("works", () => { - expect(resolve('foo', file)).to.exist +describe("resolve.alias", function () { + it("works", function () { + expect(webpack.resolveImport('foo', file)).to.exist .and.equal(path.join(__dirname, 'files', 'some', 'goofy', 'path', 'foo.js')) }) }) diff --git a/resolvers/webpack/test/files/some/goofy/path/foo.js b/resolvers/webpack/test/files/some/goofy/path/foo.js new file mode 100644 index 000000000..e69de29bb From 809109e8da4ca8eea5e89a44c6b6c7c1f0ddfb45 Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Fri, 27 Nov 2015 06:04:52 -0500 Subject: [PATCH 27/41] alias tests from webpack config docs --- resolvers/webpack/index.js | 2 +- resolvers/webpack/resolve-alias.js | 37 ++++++++++++++++-- resolvers/webpack/test/alias.js | 61 ++++++++++++++++++++++++++++++ 3 files changed, 95 insertions(+), 5 deletions(-) diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js index 447b585b2..3c5ad0848 100644 --- a/resolvers/webpack/index.js +++ b/resolvers/webpack/index.js @@ -40,7 +40,7 @@ exports.resolveImport = function resolveImport(source, file, settings) { if (findExternal(source, webpackConfig.externals)) return null // replace alias if needed - source = resolveAlias(source, get(webpackConfig, 'resolve.alias')) + source = resolveAlias(source, get(webpackConfig, 'resolve.alias', {})) var paths = [] diff --git a/resolvers/webpack/resolve-alias.js b/resolvers/webpack/resolve-alias.js index 31c715d41..1ebcd2651 100644 --- a/resolvers/webpack/resolve-alias.js +++ b/resolvers/webpack/resolve-alias.js @@ -1,7 +1,36 @@ -module.exports = function resolveAlias(path, aliases) { - if (aliases && path in aliases) { - return aliases[path] +var path = require('path') + +// implements a rough version of +// http://webpack.github.io/docs/configuration.html#resolve-alias +module.exports = function resolveAlias(source, aliases) { + + for (var alias in aliases) { + var match = matchAlias(source, alias, aliases[alias]) + if (match) return match + } + + // fail out + return source +} + +function matchAlias(source, alias, value) { + var isExact = (alias[alias.length - 1] === '$') + , isFile = (path.extname(value) !== '') + , segments = source.split(path.sep) + + if (isExact) alias = alias.slice(0, -1) + + if (segments[0] === alias) { + // always return exact match + if (segments.length === 1) return value + + // prefix match on exact match for file is an error + if (isFile && (isExact || !/^[./]/.test(value))) { + throw new Error('can\'t match file with exact alias prefix') + } + + // otherwise, prefix match is fine for non-file paths + if (!isExact && !isFile) return [value].concat(segments.slice(1)).join(path.sep) } - return path } diff --git a/resolvers/webpack/test/alias.js b/resolvers/webpack/test/alias.js index da4dfbf2f..8ea0e1b3d 100644 --- a/resolvers/webpack/test/alias.js +++ b/resolvers/webpack/test/alias.js @@ -12,3 +12,64 @@ describe("resolve.alias", function () { .and.equal(path.join(__dirname, 'files', 'some', 'goofy', 'path', 'foo.js')) }) }) + +var resolveAlias = require('../resolve-alias') +describe("webpack alias spec", function () { + // from table: http://webpack.github.io/docs/configuration.html#resolve-alias + function tableLine(alias, xyz, xyzFile) { + describe(JSON.stringify(alias), function () { + it("xyz: " + xyz, function () { + expect(resolveAlias('xyz', alias)).to.equal(xyz) + }) + it("xyz/file: " + (xyzFile.name || xyzFile), function () { + if (xyzFile === Error) { + expect(resolveAlias.bind(null, 'xyz/file', alias)).to.throw(xyzFile) + } else { + expect(resolveAlias('xyz/file', alias)).to.equal(xyzFile) + } + }) + }) + } + + tableLine( {} + , 'xyz', 'xyz/file' ) + + tableLine( { xyz: "/absolute/path/to/file.js" } + , '/absolute/path/to/file.js', 'xyz/file' ) + + tableLine( { xyz$: "/absolute/path/to/file.js" } + , "/absolute/path/to/file.js", Error ) + + tableLine( { xyz: "./dir/file.js" } + , './dir/file.js', 'xyz/file' ) + + tableLine( { xyz$: "./dir/file.js" } + , './dir/file.js', Error ) + + tableLine( { xyz: "/some/dir" } + , '/some/dir', '/some/dir/file' ) + + tableLine( { xyz$: "/some/dir" } + , '/some/dir', 'xyz/file' ) + + tableLine( { xyz: "./dir" } + , './dir', './dir/file' ) + + tableLine( { xyz: "modu" } + , 'modu', 'modu/file' ) + + tableLine( { xyz$: "modu" } + , 'modu', 'xyz/file' ) + + tableLine( { xyz: "modu/some/file.js" } + , 'modu/some/file.js', Error ) + + tableLine( { xyz: "modu/dir" } + , 'modu/dir', 'modu/dir/file' ) + + tableLine( { xyz: "xyz/dir" } + , 'xyz/dir', 'xyz/dir/file' ) + + tableLine( { xyz$: "xyz/dir" } + , 'xyz/dir', 'xyz/file' ) +}) From 71332dc045de8a1c05a0df88976e811d66c5be4a Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Fri, 27 Nov 2015 06:10:06 -0500 Subject: [PATCH 28/41] build updates (npm 2) --- .travis.yml | 3 ++- appveyor.yml | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index cf086b102..e7fb81c21 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,12 +2,13 @@ language: node_js node_js: - 0.10 - 0.12 - - iojs + - 4 - stable env: - NODE_PATH=./lib install: + - npm -g install npm@2 - npm install # install all resolver deps - "for resolver in ./resolvers/*; do cd $resolver && npm install && cd ../..; done" diff --git a/appveyor.yml b/appveyor.yml index 7dcd97210..8c790668b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -18,6 +18,11 @@ environment: install: # Get the latest stable version of Node.js or io.js - ps: Install-Product node $env:nodejs_version + + # update npm + - npm -g install npm@2 + - set PATH=%APPDATA%\npm;%PATH% + # install modules - npm install From 13637b7d0ae7a08d013521df54e39afaeca9233b Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Fri, 27 Nov 2015 06:20:55 -0500 Subject: [PATCH 29/41] oops, need to cd back to root for coveralls (travis) --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index e7fb81c21..b7324c425 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,6 +16,7 @@ install: script: - "npm run-script ci-test" - "cd resolvers/webpack && npm test" + - "cd ../.." # come back out of resolvers folder after_success: - npm run coveralls From 1903dd4ad275ca0fcc2f433eaed8c0e8dc284430 Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Fri, 27 Nov 2015 06:46:44 -0500 Subject: [PATCH 30/41] renamed setting: import/resolvers => import/resolver to better match normal use case (1 resolver) --- src/core/resolve.js | 2 +- tests/src/rules/no-unresolved.js | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/core/resolve.js b/src/core/resolve.js index 28273d464..8c5a76c20 100644 --- a/src/core/resolve.js +++ b/src/core/resolve.js @@ -39,7 +39,7 @@ export function relative(modulePath, sourceFile, settings) { } } - const configResolvers = (settings['import/resolvers'] + const configResolvers = (settings['import/resolver'] || { 'node': settings['import/resolve'] }) // backward compatibility const resolvers = resolverReducer(configResolvers, new Map()) diff --git a/tests/src/rules/no-unresolved.js b/tests/src/rules/no-unresolved.js index 91b69f038..60bb8b700 100644 --- a/tests/src/rules/no-unresolved.js +++ b/tests/src/rules/no-unresolved.js @@ -13,7 +13,7 @@ function runResolverTests(resolver) { function rest(specs) { specs.settings = Object.assign({}, specs.settings, - { 'import/resolvers': [ resolver ] } + { 'import/resolver': resolver } ) return test(specs) @@ -220,12 +220,12 @@ ruleTester.run('no-unresolved (webpack-specific)', rule, { test({ // default webpack config in files/webpack.config.js knows about jsx code: 'import * as foo from "jsx-module/foo"', - settings: { 'import/resolvers': [ 'webpack' ] }, + settings: { 'import/resolver': 'webpack' }, }), test({ // should ignore loaders code: 'import * as foo from "some-loader?with=args!jsx-module/foo"', - settings: { 'import/resolvers': [ 'webpack' ] }, + settings: { 'import/resolver': 'webpack' }, }), ], invalid: [ @@ -233,7 +233,7 @@ ruleTester.run('no-unresolved (webpack-specific)', rule, { // default webpack config in files/webpack.config.js knows about jsx code: 'import * as foo from "jsx-module/foo"', settings: { - 'import/resolvers': { 'webpack': { 'config': 'webpack.empty.config.js' } }, + 'import/resolver': { 'webpack': { 'config': 'webpack.empty.config.js' } }, }, errors: [ "Unable to resolve path to module 'jsx-module/foo'." ], }), From c5a006e5a594b2dbf377c5381759ba6e4200b9f3 Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Fri, 27 Nov 2015 13:13:53 -0500 Subject: [PATCH 31/41] resolver readmes --- resolvers/node/README.md | 26 ++++++++++++++++++++++++++ resolvers/webpack/README.md | 27 +++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 resolvers/node/README.md create mode 100644 resolvers/webpack/README.md diff --git a/resolvers/node/README.md b/resolvers/node/README.md new file mode 100644 index 000000000..11d03d2ca --- /dev/null +++ b/resolvers/node/README.md @@ -0,0 +1,26 @@ +# eslint-import-resolver-node + +[![npm](https://img.shields.io/npm/v/eslint-import-resolver-node.svg)](https://www.npmjs.com/package/eslint-import-resolver-node) + +Default Node-style module resolution plugin for [`eslint-plugin-import`](https://www.npmjs.com/package/eslint-plugin-import). + +Published separately to allow pegging to a specific version in case of breaking +changes. + +Config is passed directly through to [`resolve`](https://www.npmjs.com/package/resolve) as options: + +```yaml +settings: + import/resolver: + node: + moduleDirectory: + - node_modules + - src +``` + +or to use the default options: + +```yaml +settings: + import/resolver: node +``` diff --git a/resolvers/webpack/README.md b/resolvers/webpack/README.md new file mode 100644 index 000000000..8c24a2781 --- /dev/null +++ b/resolvers/webpack/README.md @@ -0,0 +1,27 @@ +# eslint-import-resolver-webpack + +[![npm](https://img.shields.io/npm/v/eslint-import-resolver-webpack.svg)](https://www.npmjs.com/package/eslint-import-resolver-webpack) + +Webpack-literate module resolution plugin for [`eslint-plugin-import`](https://www.npmjs.com/package/eslint-plugin-import). + +Published separately to allow pegging to a specific version in case of breaking +changes. + +Will look for `webpack.config.js` as a sibling of the first ancestral `package.json`, +or a `config` parameter may be provided with another filename/path relative to the +`package.json`. + +```yaml +--- +settings: + import/resolver: webpack # take all defaults +``` + +or with explicit config file name: + +```yaml +--- +settings: + import/resolver: + webpack: { config: 'webpack.dev.config.js' } +``` From 4d3c2ca6f67f709b511133e064d83609593e1170 Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Fri, 27 Nov 2015 13:27:15 -0500 Subject: [PATCH 32/41] cleanup for publish --- resolvers/webpack/.babelrc | 1 - resolvers/webpack/.npmignore | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 resolvers/webpack/.babelrc create mode 100644 resolvers/webpack/.npmignore diff --git a/resolvers/webpack/.babelrc b/resolvers/webpack/.babelrc deleted file mode 100644 index 9d8d51656..000000000 --- a/resolvers/webpack/.babelrc +++ /dev/null @@ -1 +0,0 @@ -{ "presets": ["es2015"] } diff --git a/resolvers/webpack/.npmignore b/resolvers/webpack/.npmignore new file mode 100644 index 000000000..b59f7e3a9 --- /dev/null +++ b/resolvers/webpack/.npmignore @@ -0,0 +1 @@ +test/ \ No newline at end of file From b335133312190f6e728cb0921a4e15072557f765 Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Fri, 27 Nov 2015 13:38:55 -0500 Subject: [PATCH 33/41] removed `resolve` as an explicit top-level dependency (resolvers will use it, if needed) --- package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index b8b208968..64c540a82 100644 --- a/package.json +++ b/package.json @@ -53,8 +53,7 @@ }, "dependencies": { "babel-runtime": "5.x", - "babylon": "^6.1.2", - "resolve": "1.1.6" + "babylon": "^6.1.2" }, "greenkeeper": { "ignore": [ From 670d5b429c55c34755d1a2594c4acf749090f222 Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Fri, 27 Nov 2015 13:55:28 -0500 Subject: [PATCH 34/41] oops. needed the .babelrc --- resolvers/webpack/.babelrc | 1 + resolvers/webpack/.npmignore | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 resolvers/webpack/.babelrc diff --git a/resolvers/webpack/.babelrc b/resolvers/webpack/.babelrc new file mode 100644 index 000000000..7a870ac67 --- /dev/null +++ b/resolvers/webpack/.babelrc @@ -0,0 +1 @@ +{ "presets": ["es2015"] } \ No newline at end of file diff --git a/resolvers/webpack/.npmignore b/resolvers/webpack/.npmignore index b59f7e3a9..e9a16cce0 100644 --- a/resolvers/webpack/.npmignore +++ b/resolvers/webpack/.npmignore @@ -1 +1,2 @@ -test/ \ No newline at end of file +test/ +.babelrc From f35a0b77503ad061615eb59d59135480cad3133d Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Fri, 27 Nov 2015 13:55:44 -0500 Subject: [PATCH 35/41] cleaning up --- resolvers/webpack/index.js | 9 ++++----- resolvers/webpack/test/externals.js | 26 +++++++++++++++----------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/resolvers/webpack/index.js b/resolvers/webpack/index.js index 3c5ad0848..26b0cb607 100644 --- a/resolvers/webpack/index.js +++ b/resolvers/webpack/index.js @@ -23,7 +23,6 @@ exports.resolveImport = function resolveImport(source, file, settings) { source = source.slice(finalBang + 1) } - if (resolve.isCore(source)) return null var webpackConfig @@ -40,12 +39,12 @@ exports.resolveImport = function resolveImport(source, file, settings) { if (findExternal(source, webpackConfig.externals)) return null // replace alias if needed - source = resolveAlias(source, get(webpackConfig, 'resolve.alias', {})) + source = resolveAlias(source, get(webpackConfig, ['resolve', 'alias'], {})) var paths = [] // root as first alternate path - var rootPath = get(webpackConfig, 'resolve.root') + var rootPath = get(webpackConfig, ['resolve', 'root']) if (rootPath) paths.push(rootPath) // otherwise, resolve "normally" @@ -53,11 +52,11 @@ exports.resolveImport = function resolveImport(source, file, settings) { basedir: path.dirname(file), // defined via http://webpack.github.io/docs/configuration.html#resolve-extensions - extensions: get(webpackConfig, 'resolve.extensions') + extensions: get(webpackConfig, ['resolve', 'extensions']) || ['', '.webpack.js', '.web.js', '.js'], // http://webpack.github.io/docs/configuration.html#resolve-modulesdirectories - moduleDirectory: get(webpackConfig, 'resolve.modulesDirectories') + moduleDirectory: get(webpackConfig, ['resolve', 'modulesDirectories']) || ['web_modules', 'node_modules'], paths: paths, diff --git a/resolvers/webpack/test/externals.js b/resolvers/webpack/test/externals.js index 5566acdc5..baea7bdb6 100644 --- a/resolvers/webpack/test/externals.js +++ b/resolvers/webpack/test/externals.js @@ -1,17 +1,21 @@ -import { expect } from 'chai' -import { resolveImport as resolve } from '../index' +var chai = require('chai') + , expect = chai.expect + , path = require('path') -import path from 'path' +var webpack = require('../index') -const file = path.join(__dirname, 'files', 'dummy.js') +var file = path.join(__dirname, 'files', 'dummy.js') -describe("externals", () => { - it("works on just a string", () => - expect(resolve('bootstrap', file)).to.be.null) +describe("externals", function () { + it("works on just a string", function () { + expect(webpack.resolveImport('bootstrap', file)).to.be.null + }) - it("works on object-map", () => - expect(resolve('jquery', file)).to.be.null) + it("works on object-map", function () { + expect(webpack.resolveImport('jquery', file)).to.be.null + }) - it("returns null for core modules", () => - expect(resolve('fs', file)).to.be.null) + it("returns null for core modules", function () { + expect(webpack.resolveImport('fs', file)).to.be.null + }) }) From 488bbb1daa8e3ff526e1e9e1610ed16223033397 Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Fri, 27 Nov 2015 13:57:15 -0500 Subject: [PATCH 36/41] removed `resolve` reference from getExports --- src/core/getExports.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/core/getExports.js b/src/core/getExports.js index 7d14b2659..87c1bad88 100644 --- a/src/core/getExports.js +++ b/src/core/getExports.js @@ -4,7 +4,6 @@ import { createHash } from 'crypto' import parse from './parse' import resolve from './resolve' -import { isCore } from 'resolve' import isIgnored from './ignore' // map from settings sha1 => path => export map objects @@ -24,8 +23,6 @@ export default class ExportMap { get hasNamed() { return this.named.size > (this.hasDefault ? 1 : 0) } static get(source, context) { - // no use trying to parse core modules - if (isCore(source)) return null var path = resolve(source, context) if (path == null || isIgnored(path, context)) return null From c51f7906e39371898e745f5558368698e8b2cd9c Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Fri, 27 Nov 2015 14:37:09 -0500 Subject: [PATCH 37/41] updated core README for new resolver plugins. --- README.md | 115 +++++++++++++++++++++++++++++---------- resolvers/node/README.md | 24 +++++++- 2 files changed, 106 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 918e08125..6348d0c92 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ rules: ``` -## Rule Details +# Rule Details ### `no-unresolved` @@ -79,6 +79,8 @@ This rule can also optionally report on unresolved modules in CommonJS `require( To enable this, send `{ commonjs: true/false, amd: true/false }` as a rule option. Both are disabled by default. +If you are using Webpack, see the section on [resolver plugins](#resolver-plugins). + ### `named` Verifies that all named imports are part of the set of named exports in the referenced module. @@ -254,8 +256,85 @@ import * as _ from 'lodash' // <- reported This rule is disabled by default. +# Resolver plugins + +With the advent of module bundlers and the current state of modules and module +syntax specs, it's not always obvious where `import x from 'module'` should look +to find the file behind `module`. + +Up through v0.10ish, this plugin has directly used substack's [`resolve`] plugin, +which implements Node's import behavior. This works pretty well in most cases. + +However, Webpack allows a number of things in import module source strings that +Node does not, such as loaders (`import 'file!./whatever'`) and a number of +aliasing schemes, such as [`externals`]: mapping a module id to a global name at +runtime (allowing some modules to be included more traditionally via script tags). + +In the interest of supporting both of these, v0.11 introduces resolver plugins. +At the moment, these are modules exporting a single function: + +```js + +exports.resolveImport = function (source, file, config) { + // return source's absolute path given + // - file: absolute path of importing module + // - config: optional config provided for this resolver + + // return `null` if source is a "core" module (i.e. "fs", "crypto") that + // can't be found on the filesystem +} +``` + +The default `node` plugin that uses [`resolve`] is a handful of lines: + +```js +var resolve = require('resolve') + , path = require('path') + , assign = require('object-assign') + +exports.resolveImport = function resolveImport(source, file, config) { + if (resolve.isCore(source)) return null + + return resolve.sync(source, opts(path.dirname(file), config)) +} + +function opts(basedir, config) { + return assign( {} + , config + , { basedir: basedir } + ) +} +``` + +It essentially just uses the current file to get a reference base directory (`basedir`) +and then passes through any explicit config from the `.eslintrc`; things like +non-standard file extensions, module directories, etc. + +Currently [Node] and [Webpack] resolution have been implemented, but the +resolvers are just npm packages, so third party packages are supported (and encouraged!). + +Just install a resolver as `eslint-import-resolver-foo` and reference it as such: + +```yaml +settings: + import/resolver: foo +``` + +or with a config object: + +```yaml +settings: + import/resolver: + foo: { someConfigKey: value } +``` + +[`resolve`]: https://www.npmjs.com/package/resolve +[`externals`]: http://webpack.github.io/docs/library-and-externals.html -## Settings +[Node]: https://www.npmjs.com/package/eslint-import-resolver-node +[Webpack]: https://www.npmjs.com/package/eslint-import-resolver-webpack + +# Settings You may set the following settings in your `.eslintrc`: @@ -265,11 +344,9 @@ A list of regex strings that, if matched by a path, will not parse the matching module. In practice, this means rules other than `no-unresolved` will not report on the `import` in question. -#### `import/resolve` - -A passthrough to [resolve]'s `opts` parameter for `resolve.sync`. +#### `import/resolver` -[resolve]: https://www.npmjs.com/package/resolve#resolve-sync-id-opts +See [resolver plugins](#resolver-plugins). #### `import/parser` @@ -320,31 +397,9 @@ settings: - 'node_modules' # this is the default, but must be included if overwritten - '\\.es5$' - import/resolve: - - extensions: - # if unset, default is just '.js', but it must be re-added explicitly if set - - .js - - .jsx - - .es6 - - .coffee - - paths: - # an array of absolute paths which will also be searched - # think NODE_PATH - - /usr/local/share/global_modules - - # this is technically for identifying `node_modules` alternate names - moduleDirectory: - - - node_modules # defaults to 'node_modules', but... - - bower_components - - - project/src # can add a path segment here that will act like - # a source root, for in-project aliasing (i.e. - # `import MyStore from 'stores/my-store'`) + import/resolver: webpack # will use 'node' if not specified - import/parser: esprima-fb # default is 'babel-core'. change if needed. + import/parser: esprima-fb # default is 'babylon'. change if needed. ``` ## SublimeLinter-eslint diff --git a/resolvers/node/README.md b/resolvers/node/README.md index 11d03d2ca..20fe1e5af 100644 --- a/resolvers/node/README.md +++ b/resolvers/node/README.md @@ -7,15 +7,33 @@ Default Node-style module resolution plugin for [`eslint-plugin-import`](https:/ Published separately to allow pegging to a specific version in case of breaking changes. -Config is passed directly through to [`resolve`](https://www.npmjs.com/package/resolve) as options: +Config is passed directly through to [`resolve`](https://www.npmjs.com/package/resolve#resolve-sync-id-opts) as options: ```yaml settings: import/resolver: node: + extensions: + # if unset, default is just '.js', but it must be re-added explicitly if set + - .js + - .jsx + - .es6 + - .coffee + + paths: + # an array of absolute paths which will also be searched + # think NODE_PATH + - /usr/local/share/global_modules + + # this is technically for identifying `node_modules` alternate names moduleDirectory: - - node_modules - - src + + - node_modules # defaults to 'node_modules', but... + - bower_components + + - project/src # can add a path segment here that will act like + # a source root, for in-project aliasing (i.e. + # `import MyStore from 'stores/my-store'`) ``` or to use the default options: From 1434640b723feb2d181e4947eea350caeee61e68 Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Fri, 27 Nov 2015 20:00:58 -0500 Subject: [PATCH 38/41] extra test while tracking down a typo --- resolvers/webpack/test/files/src/jsx/some-file.js | 0 resolvers/webpack/test/root.js | 14 ++++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 resolvers/webpack/test/files/src/jsx/some-file.js diff --git a/resolvers/webpack/test/files/src/jsx/some-file.js b/resolvers/webpack/test/files/src/jsx/some-file.js new file mode 100644 index 000000000..e69de29bb diff --git a/resolvers/webpack/test/root.js b/resolvers/webpack/test/root.js index fc89b8401..97e8b7e18 100644 --- a/resolvers/webpack/test/root.js +++ b/resolvers/webpack/test/root.js @@ -1,13 +1,19 @@ -import { expect } from 'chai' +var chai = require('chai') + , expect = chai.expect + import { resolveImport as resolve } from '../index' import path from 'path' -const file = path.join(__dirname, 'files', 'src', 'dummy.js') +var file = path.join(__dirname, 'files', 'src', 'dummy.js') -describe("root", () => { - it("works", () => { +describe("root", function () { + it("works", function () { expect(resolve('main-module', file)).to.exist .and.equal(path.join(__dirname, 'files', 'src', 'main-module.js')) }) + it("really works", function () { + expect(resolve('jsx/some-file', file)).to.exist + .and.equal(path.join(__dirname, 'files', 'src', 'jsx', 'some-file.js')) + }) }) From 27fc71fc9debd0ff1ac3f65c77229c4f2a68732b Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Fri, 27 Nov 2015 20:11:37 -0500 Subject: [PATCH 39/41] resolvers/node/v0.1.0 --- resolvers/node/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resolvers/node/package.json b/resolvers/node/package.json index edb615a75..bf8266e37 100644 --- a/resolvers/node/package.json +++ b/resolvers/node/package.json @@ -1,6 +1,6 @@ { "name": "eslint-import-resolver-node", - "version": "0.0.0", + "version": "0.1.0", "description": "Node default behavior import resolution plugin for eslint-plugin-import.", "main": "index.js", "scripts": { From 44f7c8f22bc9f6fdcb4455babf6bb95ba848563a Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Fri, 27 Nov 2015 20:18:28 -0500 Subject: [PATCH 40/41] added npm package dependency on default node resolver --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 64c540a82..9dc827dac 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,8 @@ }, "dependencies": { "babel-runtime": "5.x", - "babylon": "^6.1.2" + "babylon": "^6.1.2", + "eslint-import-resolver-node": "^0.1.0" }, "greenkeeper": { "ignore": [ From a749dafd04d999f9132ac48cc8225c45f89cbdf9 Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Fri, 27 Nov 2015 20:19:44 -0500 Subject: [PATCH 41/41] resolvers/webpack/v0.1.0 --- resolvers/webpack/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resolvers/webpack/package.json b/resolvers/webpack/package.json index 35c2632b1..c6a231bb4 100644 --- a/resolvers/webpack/package.json +++ b/resolvers/webpack/package.json @@ -1,6 +1,6 @@ { "name": "eslint-import-resolver-webpack", - "version": "0.0.0", + "version": "0.1.0", "description": "Resolve paths to dependencies, given a webpack.config.js. Plugin for eslint-plugin-import.", "main": "index.js", "scripts": {