Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7bca4d3
commit a7b8030
Showing
7 changed files
with
427 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
--- | ||
pageClass: rule-details | ||
sidebarDepth: 0 | ||
title: vue/multi-word-component-names | ||
description: require component names to be always multi-word | ||
--- | ||
# vue/multi-word-component-names | ||
|
||
> require component names to be always multi-word | ||
- :exclamation: <badge text="This rule has not been released yet." vertical="middle" type="error"> ***This rule has not been released yet.*** </badge> | ||
- :gear: This rule is included in all of `"plugin:vue/vue3-essential"`, `"plugin:vue/essential"`, `"plugin:vue/vue3-strongly-recommended"`, `"plugin:vue/strongly-recommended"`, `"plugin:vue/vue3-recommended"` and `"plugin:vue/recommended"`. | ||
|
||
## :book: Rule Details | ||
|
||
This rule .... | ||
|
||
<eslint-code-block :rules="{'vue/multi-word-component-names': ['error']}"> | ||
|
||
```vue | ||
<template> | ||
/* ✓ GOOD */ | ||
Vue.component('todo-item', { | ||
// ... | ||
}) | ||
export default { | ||
name: 'TodoItem', | ||
// ... | ||
} | ||
/* ✗ BAD */ | ||
Vue.component('todo', { | ||
// ... | ||
}) | ||
export default { | ||
name: 'Todo', | ||
// ... | ||
} | ||
</template> | ||
``` | ||
|
||
</eslint-code-block> | ||
|
||
## :wrench: Options | ||
|
||
Nothing. | ||
|
||
## :books: Further Reading | ||
|
||
- [Style guide - Multi-word component names](https://vuejs.org/v2/style-guide/#Multi-word-component-names-essential) | ||
|
||
## :mag: Implementation | ||
|
||
- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/multi-word-component-names.js) | ||
- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/multi-word-component-names.js) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
/** | ||
* @author Marton Csordas | ||
* See LICENSE file in root directory for full license. | ||
*/ | ||
'use strict' | ||
|
||
// ------------------------------------------------------------------------------ | ||
// Requirements | ||
// ------------------------------------------------------------------------------ | ||
const path = require('path') | ||
|
||
const casing = require('../utils/casing') | ||
const utils = require('../utils') | ||
|
||
const RESERVED_NAMES_IN_VUE3 = new Set( | ||
require('../utils/vue3-builtin-components') | ||
) | ||
|
||
// ------------------------------------------------------------------------------ | ||
// Helpers | ||
// ------------------------------------------------------------------------------ | ||
|
||
/** | ||
* Returns true if the given component name is valid, otherwise false. | ||
* @param {string} name | ||
* */ | ||
function isValidComponentName(name) { | ||
if (name.toLowerCase() === 'app' || RESERVED_NAMES_IN_VUE3.has(name)) { | ||
return true | ||
} else { | ||
const elements = casing.kebabCase(name).split('-') | ||
return elements.length > 1 | ||
} | ||
} | ||
|
||
// ------------------------------------------------------------------------------ | ||
// Rule Definition | ||
// ------------------------------------------------------------------------------ | ||
|
||
module.exports = { | ||
meta: { | ||
type: 'problem', | ||
docs: { | ||
description: 'require component names to be always multi-word', | ||
categories: ['vue3-essential', 'essential'], | ||
url: 'https://eslint.vuejs.org/rules/multi-word-component-names.html' | ||
}, | ||
schema: [], | ||
messages: { | ||
unexpected: 'Component name "{{value}}" should always be multi-word.' | ||
} | ||
}, | ||
/** @param {RuleContext} context */ | ||
create(context) { | ||
const fileName = context.getFilename() | ||
let componentName = path.parse(fileName).name | ||
|
||
return utils.compositingVisitors( | ||
{ | ||
/** @param {Program} node */ | ||
Program(node) { | ||
if ( | ||
!node.body.length && | ||
utils.isVueFile(fileName) && | ||
!isValidComponentName(componentName) | ||
) { | ||
context.report({ | ||
messageId: 'unexpected', | ||
data: { | ||
value: componentName | ||
}, | ||
loc: { line: 1, column: 0 } | ||
}) | ||
} | ||
} | ||
}, | ||
|
||
utils.executeOnVue(context, (obj) => { | ||
const node = utils.findProperty(obj, 'name') | ||
|
||
// Check if the component has a name property. | ||
if (node) { | ||
const valueNode = node.value | ||
if (valueNode.type !== 'Literal') return | ||
|
||
componentName = `${valueNode.value}` | ||
} else if ( | ||
obj.parent.type === 'CallExpression' && | ||
obj.parent.arguments.length === 2 | ||
) { | ||
// The component is registered globally with 'Vue.component', where | ||
// the first paremter is the component name. | ||
const argument = obj.parent.arguments[0] | ||
if (argument.type !== 'Literal') return | ||
|
||
componentName = `${argument.value}` | ||
} | ||
|
||
if (!isValidComponentName(componentName)) { | ||
context.report({ | ||
messageId: 'unexpected', | ||
data: { | ||
value: componentName | ||
}, | ||
node: node || obj | ||
}) | ||
} | ||
}) | ||
) | ||
} | ||
} |
Oops, something went wrong.