Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add no-named-export + docs/tests #1157

Merged
merged 4 commits into from
Sep 9, 2018
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, a
* Forbid unassigned imports ([`no-unassigned-import`])
* Forbid named default exports ([`no-named-default`])
* Forbid default exports ([`no-default-export`])
* Forbid named exports ([`no-named-export`])
* Forbid anonymous values as default exports ([`no-anonymous-default-export`])
* Prefer named exports to be grouped together in a single export declaration ([`group-exports`])
* Enforce a leading comment with the webpackChunkName for dynamic imports ([`dynamic-import-chunkname`])
Expand All @@ -104,6 +105,7 @@ This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, a
[`no-anonymous-default-export`]: ./docs/rules/no-anonymous-default-export.md
[`group-exports`]: ./docs/rules/group-exports.md
[`no-default-export`]: ./docs/rules/no-default-export.md
[`no-named-export`]: ./docs/rules/no-named-export.md
[`dynamic-import-chunkname`]: ./docs/rules/dynamic-import-chunkname.md

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

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

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

## Rule Details

The following patterns are considered warnings:

```javascript
// bad1.js

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

```javascript
// bad2.js

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

```javascript
// bad3.js

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

```javascript
// bad4.js

// There is more than one named export in the module.
export * from './other-module'
```

```javascript
// bad5.js

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

The following patterns are not warnings:

```javascript
// good1.js

// There is only a single module export and it's a default export.
export default 'bar';
```

```javascript
// good2.js

// There is only a single module export and it's a default export.
const foo = 'foo';
export { foo as default }
```

```javascript
// good3.js

// There is only a single module export and it's a default export.
export default from './other-module';
```

## When Not To Use It

If you don't care if named imports are used, or if you prefer named imports over default imports.
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export const rules = {
'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-named-export': require('./rules/no-named-export'),
'no-dynamic-require': require('./rules/no-dynamic-require'),
'unambiguous': require('./rules/unambiguous'),
'no-unassigned-import': require('./rules/no-unassigned-import'),
Expand Down
33 changes: 33 additions & 0 deletions src/rules/no-named-export.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import docsUrl from '../docsUrl'

module.exports = {
meta: {
docs: { url: docsUrl('no-named-export') },
},

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

const preferDefault = 'Prefer default export.'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This message could be a bit stricter.


return {
ExportAllDeclaration(node) {
context.report({node, message: preferDefault})
},

ExportNamedDeclaration(node) {
if (node.specifiers.length === 0) {
return context.report({node, message: preferDefault})
}

const someNamed = node.specifiers.some(specifier => specifier.exported.name !== 'default')
if (someNamed) {
context.report({node, message: preferDefault})
}
},
}
},
}
179 changes: 179 additions & 0 deletions tests/src/rules/no-named-export.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
import { RuleTester } from 'eslint'
import { test } from '../utils'

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

ruleTester.run('no-named-export', rule, {
valid: [
test({
code: 'export default function bar() {};',
}),
test({
code: 'export { foo as default }',
}),
test({
code: 'export default 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';`,
}),
],
invalid: [
test({
code: `
export const foo = 'foo';
export const bar = 'bar';
`,
errors: [{
ruleId: 'ExportNamedDeclaration',
message: 'Prefer default export.',
}, {
ruleId: 'ExportNamedDeclaration',
message: 'Prefer default export.',
}],
}),
test({
code: `
export const foo = 'foo';
export default bar;`,
errors: [{
ruleId: 'ExportNamedDeclaration',
message: 'Prefer default export.',
}],
}),
test({
code: `
export const foo = 'foo';
export function bar() {};
`,
errors: [{
ruleId: 'ExportNamedDeclaration',
message: 'Prefer default export.',
}, {
ruleId: 'ExportNamedDeclaration',
message: 'Prefer default export.',
}],
}),
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.',
}],
}),
test({
code: `export { foo, bar }`,
errors: [{
ruleId: 'ExportNamedDeclaration',
message: 'Prefer default export.',
}],
}),
test({
code: `export const { foo, bar } = item;`,
errors: [{
ruleId: 'ExportNamedDeclaration',
message: 'Prefer default export.',
}],
}),
test({
code: `export const { foo, bar: baz } = item;`,
errors: [{
ruleId: 'ExportNamedDeclaration',
message: 'Prefer default export.',
}],
}),
test({
code: `export const { foo: { bar, baz } } = item;`,
errors: [{
ruleId: 'ExportNamedDeclaration',
message: 'Prefer default export.',
}],
}),
test({
code: `
export const foo = item;
export { item };
`,
errors: [{
ruleId: 'ExportNamedDeclaration',
message: 'Prefer default export.',
}, {
ruleId: 'ExportNamedDeclaration',
message: 'Prefer default export.',
}],
}),
test({
code: `export * from './foo';`,
errors: [{
ruleId: 'ExportAllDeclaration',
message: 'Prefer default export.',
}],
}),
test({
code: `export const { foo } = { foo: "bar" };`,
errors: [{
ruleId: 'ExportNamedDeclaration',
message: 'Prefer default export.',
}],
}),
test({
code: `export const { foo: { bar } } = { foo: { bar: "baz" } };`,
errors: [{
ruleId: 'ExportNamedDeclaration',
message: 'Prefer default export.',
}],
}),
test({
code: 'export { a, b } from "foo.js"',
parser: 'babel-eslint',
errors: [{
ruleId: 'ExportNamedDeclaration',
message: 'Prefer default export.',
}],
}),
test({
code: `export type UserId = number;`,
parser: 'babel-eslint',
errors: [{
ruleId: 'ExportNamedDeclaration',
message: 'Prefer default export.',
}],
}),
test({
code: 'export foo from "foo.js"',
parser: 'babel-eslint',
errors: [{
ruleId: 'ExportNamedDeclaration',
message: 'Prefer default export.',
}],
}),
test({
code: `export Memory, { MemoryValue } from './Memory'`,
parser: 'babel-eslint',
errors: [{
ruleId: 'ExportNamedDeclaration',
message: 'Prefer default export.',
}],
}),
],
})