Skip to content

Commit

Permalink
Add no-default-export + docs/tests
Browse files Browse the repository at this point in the history
  • Loading branch information
dead-claudia authored and ljharb committed Oct 1, 2017
1 parent 2aef76e commit acf9633
Show file tree
Hide file tree
Showing 5 changed files with 224 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel

## [2.8.0] - 2017-10-18
### Added
- [`no-default-export`] rule ([#889], thanks [@isiahmeadows])
- [`exports-last`] rule ([#620] + [#632], thanks [@k15a])

### Changed
Expand Down Expand Up @@ -435,11 +436,13 @@ for info on changes for earlier releases.
[`exports-last`]: ./docs/rules/exports-last.md
[`group-exports`]: ./docs/rules/group-exports.md
[`no-self-import`]: ./docs/rules/no-self-import.md
[`no-default-export`]: ./docs/rules/no-default-export.md

[`memo-parser`]: ./memo-parser/README.md

[#944]: https://github.com/benmosher/eslint-plugin-import/pull/944
[#891]: https://github.com/benmosher/eslint-plugin-import/pull/891
[#889]: https://github.com/benmosher/eslint-plugin-import/pull/889
[#858]: https://github.com/benmosher/eslint-plugin-import/pull/858
[#843]: https://github.com/benmosher/eslint-plugin-import/pull/843
[#871]: https://github.com/benmosher/eslint-plugin-import/pull/871
Expand Down Expand Up @@ -670,3 +673,4 @@ for info on changes for earlier releases.
[@rosswarren]: https://github.com/rosswarren
[@alexgorbatchev]: https://github.com/alexgorbatchev
[@robertrossmann]: https://github.com/robertrossmann
[@isiahmeadows]: https://github.com/isiahmeadows
63 changes: 63 additions & 0 deletions docs/rules/no-default-export.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# no-default-export

Prohibit default exports. Mostly an inverse of [`prefer-default-export`].

[`prefer-default-export`]: ./prefer-default-export.md

## Rule Details

The following patterns are considered warnings:

```javascript
// bad1.js

// There is a default export.
export const foo = 'foo';
const bar = 'bar';
export default 'bar';
```

```javascript
// bad2.js

// There is a default export.
const foo = 'foo';
export { foo as default }
```

The following patterns are not warnings:

```javascript
// good1.js

// There is only a single module export and it's a named export.
export const foo = 'foo';
```

```javascript
// good2.js

// There is more than one named export in the module.
export const foo = 'foo';
export const bar = 'bar';
```

```javascript
// good3.js

// There is more than one named export in the module
const foo = 'foo';
const bar = 'bar';
export { foo, bar }
```

```javascript
// export-star.js

// Any batch export will disable this rule. The remote module is not inspected.
export * from './other-module'
```

## When Not To Use It

If you don't care if default imports are used, or if you prefer default imports over named imports.
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const rules = {
'order': require('./rules/order'),
'newline-after-import': require('./rules/newline-after-import'),
'prefer-default-export': require('./rules/prefer-default-export'),
'no-default-export': require('./rules/no-default-export'),
'no-dynamic-require': require('./rules/no-dynamic-require'),
'unambiguous': require('./rules/unambiguous'),
'no-unassigned-import': require('./rules/no-unassigned-import'),
Expand Down
35 changes: 35 additions & 0 deletions src/rules/no-default-export.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
module.exports = {
meta: {
docs: {},
},

create(context) {
// ignore non-modules
if (context.parserOptions.sourceType !== 'module') {
return {}
}

const preferNamed = 'Prefer named exports.'
const noAliasDefault = ({local}) =>
`Do not alias \`${local.name}\` as \`default\`. Just export ` +
`\`${local.name}\` itself instead.`

return {
ExportDefaultDeclaration(node) {
context.report({node, message: preferNamed})
},

ExportNamedDeclaration(node) {
node.specifiers.forEach(specifier => {
if (specifier.type === 'ExportDefaultSpecifier' &&
specifier.exported.name === 'default') {
context.report({node, message: preferNamed})
} else if (specifier.type === 'ExportSpecifier' &&
specifier.exported.name === 'default') {
context.report({node, message: noAliasDefault(specifier)})
}
})
},
}
},
}
121 changes: 121 additions & 0 deletions tests/src/rules/no-default-export.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import { test } from '../utils'

import { RuleTester } from 'eslint'

const ruleTester = new RuleTester()
, rule = require('rules/no-default-export')

ruleTester.run('no-default-export', rule, {
valid: [
test({
code: `
export const foo = 'foo';
export const bar = 'bar';
`,
}),
test({
code: `
export const foo = 'foo';
export function bar() {};
`,
}),
test({
code: `export const foo = 'foo';`,
}),
test({
code: `
const foo = 'foo';
export { foo };
`,
}),
test({
code: `export { foo, bar }`,
}),
test({
code: `export const { foo, bar } = item;`,
}),
test({
code: `export const { foo, bar: baz } = item;`,
}),
test({
code: `export const { foo: { bar, baz } } = item;`,
}),
test({
code: `
export const foo = item;
export { item };
`,
}),
test({
code: `export * from './foo';`,
}),
test({
code: `export const { foo } = { foo: "bar" };`,
}),
test({
code: `export const { foo: { bar } } = { foo: { bar: "baz" } };`,
}),
test({
code: 'export { a, b } from "foo.js"',
parser: 'babel-eslint',
}),

// no exports at all
test({
code: `import * as foo from './foo';`,
}),
test({
code: `import foo from './foo';`,
}),
test({
code: `import {default as foo} from './foo';`,
}),

test({
code: `export type UserId = number;`,
parser: 'babel-eslint',
}),
test({
code: 'export foo from "foo.js"',
parser: 'babel-eslint',
}),
test({
code: `export Memory, { MemoryValue } from './Memory'`,
parser: 'babel-eslint',
}),
],
invalid: [
test({
code: 'export default function bar() {};',
errors: [{
ruleId: 'ExportDefaultDeclaration',
message: 'Prefer named exports.',
}],
}),
test({
code: `
export const foo = 'foo';
export default bar;`,
errors: [{
ruleId: 'ExportDefaultDeclaration',
message: 'Prefer named exports.',
}],
}),
test({
code: 'export { foo as default }',
errors: [{
ruleId: 'ExportNamedDeclaration',
message: 'Do not alias `foo` as `default`. Just export `foo` itself ' +
'instead.',
}],
}),
test({
code: 'export default from "foo.js"',
parser: 'babel-eslint',
errors: [{
ruleId: 'ExportNamedDeclaration',
message: 'Prefer named exports.',
}],
}),
],
})

0 comments on commit acf9633

Please sign in to comment.