Skip to content

Commit

Permalink
Add prefer-default-export rule
Browse files Browse the repository at this point in the history
  • Loading branch information
gavriguy committed May 8, 2016
1 parent 51161b8 commit 1e0992d
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
- [`import/extensions` setting]: a whitelist of file extensions to parse as modules
and search for `export`s. If unspecified, all extensions are considered valid (for now).
In v2, this will likely default to `['.js', MODULE_EXT]`,. ([#297], to fix [#267])
- [`prefer-default-export`], new rule. ([#308], thanks [@gavriguy])

### Fixed
- [`extensions`]: fallback to source path for extension enforcement if imported
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, a
[`extensions`]: ./docs/rules/extensions.md
[`order`]: ./docs/rules/order.md
[`newline-after-import`]: ./docs/rules/newline-after-import.md
[`prefer-default-export`]: ./docs/rules/prefer-default-export.md


## Installation
Expand Down
51 changes: 51 additions & 0 deletions docs/rules/prefer-default-export.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# prefer-default-export

When there is only a single export from a module prefer using default export over named export.

## Rule Details

The following patterns are considered warnings:

```javascript
// bad.js

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

```

The following patterns are not warnings:

```javascript
// good1.js

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

```javascript
// good2.js

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

```javascript
// good3.js

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

```javascript
// good4.js

// There is a default export.
const foo = 'foo';
export { foo as default }
```
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const rules = {
'no-nodejs-modules': require('./rules/no-nodejs-modules'),
'order': require('./rules/order'),
'newline-after-import': require('./rules/newline-after-import'),
'prefer-default-export': require('./rules/prefer-default-export'),

// metadata-based
'no-deprecated': require('./rules/no-deprecated'),
Expand Down
31 changes: 31 additions & 0 deletions src/rules/prefer-default-export.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
'use strict'

module.exports = function(context) {
let namedExportCount = 0
let specifierExportCount = 0
let hasDefaultExport = false
let namedExportNode = null
return {
'ExportSpecifier': function(node) {
if (node.exported.name === 'default') {
hasDefaultExport = true
} else {
specifierExportCount++
namedExportNode = node
}
},
'ExportNamedDeclaration': function(node) {
namedExportCount++
namedExportNode = node
},
'ExportDefaultDeclaration': function() {
hasDefaultExport = true
},

'Program:exit': function() {
if (namedExportCount === 1 && specifierExportCount < 2 && !hasDefaultExport) {
context.report(namedExportNode, 'Prefer default export.')
}
},
}
}
48 changes: 48 additions & 0 deletions tests/src/rules/prefer-default-export.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { test } from '../utils'

import { RuleTester } from 'eslint'

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

ruleTester.run('prefer-default-export', rule, {
valid: [
test({
code: `
export const foo = 'foo';
export const bar = 'bar';`,
}),
test({
code: `
export const foo = 'foo';
export default bar;`,
}),
test({
code: `
export { foo, bar }`,
}),
test({
code: `
export { foo as default }`,
}),
],
invalid: [
test({
code: `
export const foo = 'foo';`,
errors: [{
ruleId: 'ExportNamedDeclaration',
message: 'Prefer default export.',
}],
}),
test({
code: `
const foo = 'foo';
export { foo };`,
errors: [{
ruleId: 'ExportNamedDeclaration',
message: 'Prefer default export.',
}],
}),
],
})

0 comments on commit 1e0992d

Please sign in to comment.