Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
1 change: 1 addition & 0 deletions docs/rules/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ For example:
| Rule ID | Description | |
|:--------|:------------|:---|
| [vue/component-name-in-template-casing](./component-name-in-template-casing.md) | enforce specific casing for the component naming style in template | :wrench: |
| [vue/require-direct-export](./require-direct-export.md) | require the component to be directly exported | |
| [vue/script-indent](./script-indent.md) | enforce consistent indentation in `<script>` | :wrench: |

## Deprecated
Expand Down
45 changes: 45 additions & 0 deletions docs/rules/require-direct-export.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
pageClass: rule-details
sidebarDepth: 0
title: vue/require-direct-export
description: require the component to be directly exported
---
# vue/require-direct-export
> require the component to be directly exported

## Rule Details

This rule aims to require that the component object be directly exported.

:-1: Examples of **incorrect** code:

```js
const ComponentA = {
name: 'ComponentA',
data() {
return {
state: 1
}
}
}

export default ComponentA
```

:+1: Examples of **correct** code:

```js
export default {
name: 'ComponentA',
data() {
return {
state: 1
}
}
}
```

## :mag: Implementation

- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/require-direct-export.js)
- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/require-direct-export.js)
1 change: 1 addition & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ module.exports = {
'prop-name-casing': require('./rules/prop-name-casing'),
'require-component-is': require('./rules/require-component-is'),
'require-default-prop': require('./rules/require-default-prop'),
'require-direct-export': require('./rules/require-direct-export'),
'require-prop-type-constructor': require('./rules/require-prop-type-constructor'),
'require-prop-types': require('./rules/require-prop-types'),
'require-render-return': require('./rules/require-render-return'),
Expand Down
46 changes: 46 additions & 0 deletions lib/rules/require-direct-export.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
* @fileoverview require the component to be directly exported
* @author Hiroki Osame <[email protected]>
*/
'use strict'

const utils = require('../utils')

// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------

module.exports = {
meta: {
type: 'suggestion',
docs: {
description: 'require the component to be directly exported',
category: undefined,
url: 'https://eslint.vuejs.org/rules/require-direct-export.html'
},
fixable: null, // or "code" or "whitespace"
schema: []
},

create (context) {
const filePath = context.getFilename()

return {
'ExportDefaultDeclaration:exit' (node) {
if (!utils.isVueFile(filePath)) return

const isObjectExpression = (
node.type === 'ExportDefaultDeclaration' &&
node.declaration.type === 'ObjectExpression'
)

if (!isObjectExpression) {
context.report({
node,
message: `Expected the component literal to be directly exported.`
})
}
}
}
}
}
7 changes: 5 additions & 2 deletions lib/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,10 @@ module.exports = {
})
},

isVueFile (path) {
return path.endsWith('.vue') || path.endsWith('.jsx')
},

/**
* Check whether the given node is a Vue component based
* on the filename and default export type
Expand All @@ -481,8 +485,7 @@ module.exports = {
* @returns {boolean}
*/
isVueComponentFile (node, path) {
const isVueFile = path.endsWith('.vue') || path.endsWith('.jsx')
return isVueFile &&
return this.isVueFile(path) &&
node.type === 'ExportDefaultDeclaration' &&
node.declaration.type === 'ObjectExpression'
},
Expand Down
56 changes: 56 additions & 0 deletions tests/lib/rules/require-direct-export.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/**
* @fileoverview require the component to be directly exported
* @author Hiroki Osame <[email protected]>
*/
'use strict'

// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------

const rule = require('../../../lib/rules/require-direct-export')
const RuleTester = require('eslint').RuleTester

const parserOptions = {
ecmaVersion: 2018,
sourceType: 'module',
ecmaFeatures: { jsx: true }
}

// ------------------------------------------------------------------------------
// Tests
// ------------------------------------------------------------------------------

const ruleTester = new RuleTester()
ruleTester.run('require-direct-export', rule, {

valid: [
{
filename: 'test.vue',
code: ''
},
{
filename: 'test.vue',
code: `
export default {}
`,
parserOptions
}
],

invalid: [

{
filename: 'test.vue',
code: `
const A = {};
export default A`,
parserOptions,
errors: [{
message: 'Expected the component literal to be directly exported.',
type: 'ExportDefaultDeclaration',
line: 3
}]
}
]
})