Skip to content

Commit cf45512

Browse files
gavriguybenmosher
authored andcommitted
Add prefer-default-export rule
1 parent 4d80295 commit cf45512

File tree

6 files changed

+138
-0
lines changed

6 files changed

+138
-0
lines changed

Diff for: CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
44
This change log adheres to standards from [Keep a CHANGELOG](http://keepachangelog.com).
55

66
## [Unreleased]
7+
### Added
8+
- [`prefer-default-export`], new rule. ([#308], thanks [@gavriguy])
9+
710
### Fixed
811
- ignore namespace / ES7 re-exports in [`no-mutable-exports`]. ([#317], fixed by [#322]. thanks [@borisyankov] + [@jfmengels])
912

@@ -204,8 +207,10 @@ for info on changes for earlier releases.
204207
[`named`]: ./docs/rules/named.md
205208
[`newline-after-import`]: ./docs/rules/newline-after-import.md
206209
[`no-mutable-exports`]: ./docs/rules/no-mutable-exports.md
210+
[`prefer-default-export`]: ./docs/rules/prefer-default-export.md
207211

208212
[#322]: https://github.com/benmosher/eslint-plugin-import/pull/322
213+
[#308]: https://github.com/benmosher/eslint-plugin-import/pull/308
209214
[#298]: https://github.com/benmosher/eslint-plugin-import/pull/298
210215
[#297]: https://github.com/benmosher/eslint-plugin-import/pull/297
211216
[#296]: https://github.com/benmosher/eslint-plugin-import/pull/296
@@ -281,3 +286,4 @@ for info on changes for earlier releases.
281286
[@SimenB]: https://github.com/SimenB
282287
[@josh]: https://github.com/josh
283288
[@borisyankov]: https://github.com/borisyankov
289+
[@gavriguy]: https://github.com/gavriguy

Diff for: README.md

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, a
6464
[`extensions`]: ./docs/rules/extensions.md
6565
[`order`]: ./docs/rules/order.md
6666
[`newline-after-import`]: ./docs/rules/newline-after-import.md
67+
[`prefer-default-export`]: ./docs/rules/prefer-default-export.md
6768

6869

6970
## Installation

Diff for: docs/rules/prefer-default-export.md

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# prefer-default-export
2+
3+
When there is only a single export from a module prefer using default export over named export.
4+
5+
## Rule Details
6+
7+
The following patterns are considered warnings:
8+
9+
```javascript
10+
// bad.js
11+
12+
// There is only a single module export and its a named export.
13+
export const foo = 'foo';
14+
15+
```
16+
17+
The following patterns are not warnings:
18+
19+
```javascript
20+
// good1.js
21+
22+
// There is a default export.
23+
export const foo = 'foo';
24+
const bar = 'bar';
25+
export default 'bar';
26+
```
27+
28+
```javascript
29+
// good2.js
30+
31+
// There is more thank one named exports in the module.
32+
export const foo = 'foo';
33+
export const bar = 'bar';
34+
```
35+
36+
```javascript
37+
// good3.js
38+
39+
// There is more thank one named exports in the module
40+
const foo = 'foo';
41+
const bar = 'bar';
42+
export { foo, bar }
43+
```
44+
45+
```javascript
46+
// good4.js
47+
48+
// There is a default export.
49+
const foo = 'foo';
50+
export { foo as default }
51+
```

Diff for: src/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export const rules = {
1919
'no-nodejs-modules': require('./rules/no-nodejs-modules'),
2020
'order': require('./rules/order'),
2121
'newline-after-import': require('./rules/newline-after-import'),
22+
'prefer-default-export': require('./rules/prefer-default-export'),
2223

2324
// metadata-based
2425
'no-deprecated': require('./rules/no-deprecated'),

Diff for: src/rules/prefer-default-export.js

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
'use strict'
2+
3+
module.exports = function(context) {
4+
let namedExportCount = 0
5+
let specifierExportCount = 0
6+
let hasDefaultExport = false
7+
let namedExportNode = null
8+
return {
9+
'ExportSpecifier': function(node) {
10+
if (node.exported.name === 'default') {
11+
hasDefaultExport = true
12+
} else {
13+
specifierExportCount++
14+
namedExportNode = node
15+
}
16+
},
17+
'ExportNamedDeclaration': function(node) {
18+
namedExportCount++
19+
namedExportNode = node
20+
},
21+
'ExportDefaultDeclaration': function() {
22+
hasDefaultExport = true
23+
},
24+
25+
'Program:exit': function() {
26+
if (namedExportCount === 1 && specifierExportCount < 2 && !hasDefaultExport) {
27+
context.report(namedExportNode, 'Prefer default export.')
28+
}
29+
},
30+
}
31+
}

Diff for: tests/src/rules/prefer-default-export.js

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { test } from '../utils'
2+
3+
import { RuleTester } from 'eslint'
4+
5+
const ruleTester = new RuleTester()
6+
, rule = require('rules/prefer-default-export')
7+
8+
ruleTester.run('prefer-default-export', rule, {
9+
valid: [
10+
test({
11+
code: `
12+
export const foo = 'foo';
13+
export const bar = 'bar';`,
14+
}),
15+
test({
16+
code: `
17+
export const foo = 'foo';
18+
export default bar;`,
19+
}),
20+
test({
21+
code: `
22+
export { foo, bar }`,
23+
}),
24+
test({
25+
code: `
26+
export { foo as default }`,
27+
}),
28+
],
29+
invalid: [
30+
test({
31+
code: `
32+
export const foo = 'foo';`,
33+
errors: [{
34+
ruleId: 'ExportNamedDeclaration',
35+
message: 'Prefer default export.',
36+
}],
37+
}),
38+
test({
39+
code: `
40+
const foo = 'foo';
41+
export { foo };`,
42+
errors: [{
43+
ruleId: 'ExportNamedDeclaration',
44+
message: 'Prefer default export.',
45+
}],
46+
}),
47+
],
48+
})

0 commit comments

Comments
 (0)