Skip to content

Commit

Permalink
Add new rule no-webpack-loader-syntax (#586)
Browse files Browse the repository at this point in the history
* Add new rule `no-webpack-loader-syntax`

Webpack allows specifying loaders and their configuration inline in imports
using a non-standard import syntax. This rule allows disabling this non-standard
syntax in imports.

* Fix up no-webpack-loader-syntax docs

* Add no-webpack-loader-syntax to README
  • Loading branch information
fson authored and benmosher committed Sep 26, 2016
1 parent e3c41ca commit 1d5b14f
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
- `recommended` shared config. Roughly `errors` and `warnings` mixed together,
with some `parserOptions` in the mix. ([#402])
- `react` shared config: added `jsx: true` to `parserOptions.ecmaFeatures`.
- Added [`no-webpack-loader-syntax`] rule: forbid custom Webpack loader syntax in imports. ([#586], thanks [@fson]!)

### Breaking
- [`import/extensions` setting] defaults to `['.js']`. ([#306])
Expand Down Expand Up @@ -331,7 +332,9 @@ for info on changes for earlier releases.
[`max-dependencies`]: ./docs/rules/max-dependencies.md
[`no-internal-modules`]: ./docs/rules/no-internal-modules.md
[`no-dynamic-require`]: ./docs/rules/no-dynamic-require.md
[`no-webpack-loader-syntax`]: ./docs/rules/no-webpack-loader-syntax.md

[#586]: https://github.com/benmosher/eslint-plugin-import/pull/586
[#568]: https://github.com/benmosher/eslint-plugin-import/pull/568
[#555]: https://github.com/benmosher/eslint-plugin-import/pull/555
[#538]: https://github.com/benmosher/eslint-plugin-import/pull/538
Expand Down Expand Up @@ -488,3 +491,4 @@ for info on changes for earlier releases.
[@spalger]: https://github.com/spalger
[@preco21]: https://github.com/preco21
[@skyrpex]: https://github.com/skyrpex
[@fson]: https://github.com/fson
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, a
* Forbid import of modules using absolute paths ([`no-absolute-path`])
* Forbid `require()` calls with expressions ([`no-dynamic-require`])
* Prevent importing the submodules of other modules ([`no-internal-modules`])
* Forbid Webpack loader syntax in imports ([`no-webpack-loader-syntax`])

[`no-unresolved`]: ./docs/rules/no-unresolved.md
[`named`]: ./docs/rules/named.md
Expand All @@ -31,6 +32,7 @@ This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, a
[`no-absolute-path`]: ./docs/rules/no-absolute-path.md
[`no-dynamic-require`]: ./docs/rules/no-dynamic-require.md
[`no-internal-modules`]: ./docs/rules/no-internal-modules.md
[`no-webpack-loader-syntax`]: ./docs/rules/no-webpack-loader-syntax.md

**Helpful warnings:**

Expand Down
36 changes: 36 additions & 0 deletions docs/rules/no-webpack-loader-syntax.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# no-webpack-loader-syntax

Forbid Webpack loader syntax in imports.

[Webpack](http://webpack.github.io) allows specifying the [loaders](http://webpack.github.io/docs/loaders.html) to use in the import source string using a special syntax like this:
```js
var moduleWithOneLoader = require("my-loader!./my-awesome-module");
```

This syntax is non-standard, so it couples the code to Webpack. The recommended way to specify Webpack loader configuration is in a [Webpack configuration file](http://webpack.github.io/docs/loaders.html#loaders-by-config).

## Rule Details

### Fail

```js
import myModule from 'my-loader!my-module';
import theme from 'style!css!./theme.css';

var myModule = require('my-loader!./my-module');
var theme = require('style!css!./theme.css');
```

### Pass

```js
import myModule from 'my-module';
import theme from './theme.css';

var myModule = require('my-module');
var theme = require('./theme.css');
```

## When Not To Use It

If you have a project that doesn't use Webpack you can safely disable this rule.
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const rules = {
'no-extraneous-dependencies': require('./rules/no-extraneous-dependencies'),
'no-absolute-path': require('./rules/no-absolute-path'),
'no-nodejs-modules': require('./rules/no-nodejs-modules'),
'no-webpack-loader-syntax': require('./rules/no-webpack-loader-syntax'),
'order': require('./rules/order'),
'newline-after-import': require('./rules/newline-after-import'),
'prefer-default-export': require('./rules/prefer-default-export'),
Expand Down
28 changes: 28 additions & 0 deletions src/rules/no-webpack-loader-syntax.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import isStaticRequire from '../core/staticRequire'

function reportIfNonStandard(context, node, name) {
if (name.indexOf('!') !== -1) {
context.report(node, `Unexpected '!' in '${name}'. ` +
'Do not use import syntax to configure webpack loaders.'
)
}
}

module.exports = {
meta: {
docs: {},
},

create: function (context) {
return {
ImportDeclaration: function handleImports(node) {
reportIfNonStandard(context, node, node.source.value)
},
CallExpression: function handleRequires(node) {
if (isStaticRequire(node)) {
reportIfNonStandard(context, node, node.arguments[0].value)
}
},
}
},
}
74 changes: 74 additions & 0 deletions tests/src/rules/no-webpack-loader-syntax.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { test } from '../utils'

import { RuleTester } from 'eslint'

const ruleTester = new RuleTester()
, rule = require('rules/no-webpack-loader-syntax')

const message = 'Do not use import syntax to configure webpack loaders.'

ruleTester.run('no-webpack-loader-syntax', rule, {
valid: [
test({ code: 'import _ from "lodash"'}),
test({ code: 'import find from "lodash.find"'}),
test({ code: 'import foo from "./foo.css"'}),
test({ code: 'import data from "@scope/my-package/data.json"'}),
test({ code: 'var _ = require("lodash")'}),
test({ code: 'var find = require("lodash.find")'}),
test({ code: 'var foo = require("./foo")'}),
test({ code: 'var foo = require("../foo")'}),
test({ code: 'var foo = require("foo")'}),
test({ code: 'var foo = require("./")'}),
test({ code: 'var foo = require("@scope/foo")'}),
],
invalid: [
test({
code: 'import _ from "babel!lodash"',
errors: [
{ message: `Unexpected '!' in 'babel!lodash'. ${message}` },
],
}),
test({
code: 'import find from "-babel-loader!lodash.find"',
errors: [
{ message: `Unexpected '!' in '-babel-loader!lodash.find'. ${message}` },
],
}),
test({
code: 'import foo from "style!css!./foo.css"',
errors: [
{ message: `Unexpected '!' in 'style!css!./foo.css'. ${message}` },
],
}),
test({
code: 'import data from "json!@scope/my-package/data.json"',
errors: [
{ message: `Unexpected '!' in 'json!@scope/my-package/data.json'. ${message}` },
],
}),
test({
code: 'var _ = require("babel!lodash")',
errors: [
{ message: `Unexpected '!' in 'babel!lodash'. ${message}` },
],
}),
test({
code: 'var find = require("-babel-loader!lodash.find")',
errors: [
{ message: `Unexpected '!' in '-babel-loader!lodash.find'. ${message}` },
],
}),
test({
code: 'var foo = require("style!css!./foo.css")',
errors: [
{ message: `Unexpected '!' in 'style!css!./foo.css'. ${message}` },
],
}),
test({
code: 'var data = require("json!@scope/my-package/data.json")',
errors: [
{ message: `Unexpected '!' in 'json!@scope/my-package/data.json'. ${message}` },
],
}),
],
})

0 comments on commit 1d5b14f

Please sign in to comment.