From 7775f344b90aa44c446d596e4e137d6a725bf5e8 Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Mon, 2 May 2016 06:52:06 -0400 Subject: [PATCH] import/extensions setting: parser whitelist. fixes #267 --- CHANGELOG.md | 5 +++++ README.md | 13 +++++++++++++ config/react.js | 8 ++++++++ src/core/ignore.js | 21 ++++++++++++++++++++- src/index.js | 3 +++ tests/files/data.json | 1 + tests/src/rules/named.js | 4 +++- tests/src/rules/namespace.js | 3 ++- tests/src/rules/no-named-as-default.js | 4 +++- tests/src/utils.js | 3 +++ 10 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 config/react.js create mode 100644 tests/files/data.json diff --git a/CHANGELOG.md b/CHANGELOG.md index cfe937a9e..f81b59503 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel - [`extensions`]: fallback to source path for extension enforcement if imported module is not resolved. Also, never report for builtins (i.e. `path`). ([#296]) +### Breaking +- [`import/extensions` setting]: a whitelist of file extensions to parse as modules + and search for `export`s. Defaults to `['.js']`. + ## resolvers/webpack/0.2.4 - 2016-04-29 ### Changed - automatically find webpack config with `interpret`-able extensions ([#287], thanks [@taion]) @@ -180,6 +184,7 @@ for info on changes for earlier releases. [`import/cache` setting]: ./README.md#importcache [`import/ignore` setting]: ./README.md#importignore +[`import/extensions` setting]: ./README.md#importextensions [`no-unresolved`]: ./docs/rules/no-unresolved.md [`no-deprecated`]: ./docs/rules/no-deprecated.md diff --git a/README.md b/README.md index 348d87d29..24e018e0b 100644 --- a/README.md +++ b/README.md @@ -147,6 +147,19 @@ If you are interesting in writing a resolver, see the [spec](./resolvers/README. You may set the following settings in your `.eslintrc`: +#### `import/extensions` + +A whitelist of file extensions that will be parsed as modules and inspected for +`export`s. This defaults to `['.js']`, unless you are using the `react` shared config, +in which case it is specified as `['.js', '.jsx']`. + +Note that this is different from (and likely a subset of) any `import/resolver` +extensions settings, which may include `.json`, `.coffee`, etc. which will still +factor into the `no-unresolved` rule. + +Also, `import/ignore` patterns will overrule this whitelist, so `node_modules` that +end in `.js` will still be ignored by default. + #### `import/ignore` A list of regex strings that, if matched by a path, will diff --git a/config/react.js b/config/react.js new file mode 100644 index 000000000..c8bd7ade9 --- /dev/null +++ b/config/react.js @@ -0,0 +1,8 @@ +/** + * - adds `.jsx` as an extension + */ +module.exports = { + settings: { + 'import/extensions': ['.js', '.jsx'], + }, +} diff --git a/src/core/ignore.js b/src/core/ignore.js index ec992ca10..d70a51992 100644 --- a/src/core/ignore.js +++ b/src/core/ignore.js @@ -1,9 +1,28 @@ +import { extname } from 'path' +import Set from 'es6-set' + +// one-shot memoized +let cachedSet, lastSettings +function validExtensions({ settings }) { + if (cachedSet && settings === lastSettings) { + return cachedSet + } + + // todo: add 'mjs'? + lastSettings = settings + cachedSet = new Set(settings['import/extensions'] || [ '.js' ]) + return cachedSet +} + export default function ignore(path, context) { // ignore node_modules by default - var ignoreStrings = context.settings['import/ignore'] + const ignoreStrings = context.settings['import/ignore'] ? [].concat(context.settings['import/ignore']) : ['node_modules'] + // check extension whitelist first (cheap) + if (!validExtensions(context).has(extname(path))) return true + if (ignoreStrings.length === 0) return false for (var i = 0; i < ignoreStrings.length; i++) { diff --git a/src/index.js b/src/index.js index c9c01b111..0d1eb15cf 100644 --- a/src/index.js +++ b/src/index.js @@ -28,6 +28,9 @@ export const configs = { 'errors': require('../config/errors'), 'warnings': require('../config/warnings'), + // useful stuff for folks using React + 'react': require('../config/react'), + // shhhh... work in progress "secret" rules 'stage-0': require('../config/stage-0'), } diff --git a/tests/files/data.json b/tests/files/data.json new file mode 100644 index 000000000..ca747236d --- /dev/null +++ b/tests/files/data.json @@ -0,0 +1 @@ +{ "foo": "bar" } \ No newline at end of file diff --git a/tests/src/rules/named.js b/tests/src/rules/named.js index 4ad6a6cbc..590a62e8e 100644 --- a/tests/src/rules/named.js +++ b/tests/src/rules/named.js @@ -1,4 +1,4 @@ -import { test } from '../utils' +import { test, SYNTAX_CASES } from '../utils' import { RuleTester } from 'eslint' var ruleTester = new RuleTester() @@ -96,6 +96,7 @@ ruleTester.run('named', rule, { settings: { 'import/ignore': ['common'] }, }), + ...SYNTAX_CASES, ], invalid: [ @@ -166,6 +167,7 @@ ruleTester.run('named', rule, { // parse errors test({ code: "import { a } from './test.coffee';", + settings: { 'import/extensions': ['.js', '.coffee'] }, errors: [{ message: "Parse errors in imported module './test.coffee': Unexpected token > (1:20)", type: 'Literal', diff --git a/tests/src/rules/namespace.js b/tests/src/rules/namespace.js index 0e49bd8b2..1651a6949 100644 --- a/tests/src/rules/namespace.js +++ b/tests/src/rules/namespace.js @@ -1,4 +1,4 @@ -var test = require('../utils').test +import { test, SYNTAX_CASES } from '../utils' import { RuleTester } from 'eslint' var ruleTester = new RuleTester({ env: { es6: true }}) @@ -86,6 +86,7 @@ const valid = [ parser: 'babel-eslint', }), + ...SYNTAX_CASES, ] const invalid = [ diff --git a/tests/src/rules/no-named-as-default.js b/tests/src/rules/no-named-as-default.js index 4b12c56be..e3a843378 100644 --- a/tests/src/rules/no-named-as-default.js +++ b/tests/src/rules/no-named-as-default.js @@ -1,4 +1,4 @@ -import { test } from '../utils' +import { test, SYNTAX_CASES } from '../utils' import { RuleTester } from 'eslint' const ruleTester = new RuleTester() @@ -16,6 +16,8 @@ ruleTester.run('no-named-as-default', rule, { , parser: 'babel-eslint' }), test({ code: 'export bar from "./bar";' , parser: 'babel-eslint' }), + + ...SYNTAX_CASES, ], invalid: [ diff --git a/tests/src/utils.js b/tests/src/utils.js index 301b9ac1d..bddd9745c 100644 --- a/tests/src/utils.js +++ b/tests/src/utils.js @@ -57,4 +57,7 @@ export const SYNTAX_CASES = [ test({ code: 'export default x' }), test({ code: 'export default class x {}' }), + // issue #267: parser whitelist + test({ code: 'import json from "./data.json"' }), + ]