Skip to content
This repository was archived by the owner on Nov 17, 2019. It is now read-only.

Commit 6d13800

Browse files
committed
Initial commit
0 parents  commit 6d13800

File tree

9 files changed

+1047
-0
lines changed

9 files changed

+1047
-0
lines changed

.eslintignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
**/node_modules/**
2+
!.eslintrc.js

.eslintrc.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/* eslint comma-dangle: [error, always-multiline] */
2+
module.exports = {
3+
extends: [
4+
'xo-space',
5+
],
6+
rules: {
7+
'object-curly-spacing': [
8+
'error',
9+
'always',
10+
],
11+
},
12+
};

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules/
2+
*.log

LICENCE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2019 sharkykh
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# eslint-plugin-vue-extra
2+
3+
[![NPM version](https://img.shields.io/npm/v/@sharkykh/eslint-plugin-vue-extra.svg)](https://npmjs.org/package/@sharkykh/eslint-plugin-vue-extra)
4+
[![License](https://img.shields.io/github/license/sharkykh/eslint-plugin-vue-extra.svg?style=flat)](https://github.com/sharkykh/eslint-plugin-vue-extra/blob/master/LICENSE)
5+
6+
> ESLint plugin, extension for [`eslint-plugin-vue`](https://eslint.vuejs.org).
7+
8+
## Rules
9+
10+
- [component-not-registered](src/component-not-registered.js) - Warn if a component is used in a [SFC file](https://vuejs.org/v2/guide/single-file-components.html) without being registered (a.k.a. a globally registered component). **Does not support dynamically assigned components.**
11+
12+
## :lock: License
13+
14+
See the [LICENSE](LICENSE) file for license rights and limitations (MIT).

package.json

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"version": "0.1.0",
3+
"name": "@sharkykh/eslint-plugin-vue-extra",
4+
"description": "ESLint plugin, extension for eslint-plugin-vue",
5+
"author": "sharkykh",
6+
"license": "MIT",
7+
"keywords": [
8+
"eslint",
9+
"eslint-plugin",
10+
"eslint-config",
11+
"vue",
12+
"vuejs",
13+
"rules"
14+
],
15+
"repository": {
16+
"type": "git",
17+
"url": "git+https://github.com/sharkykh/eslint-plugin-vue.git"
18+
},
19+
"bugs": {
20+
"url": "https://github.com/sharkykh/eslint-plugin-vue/issues"
21+
},
22+
"main": "src/index.js",
23+
"scripts": {
24+
"lint": "eslint *.js"
25+
},
26+
"peerDependencies": {
27+
"eslint": "^5.0.0 || ^6.0.0",
28+
"eslint-plugin-vue": "^5.2.3"
29+
},
30+
"devDependencies": {
31+
"eslint": "^6.0.1",
32+
"eslint-config-xo-space": "^0.21.0",
33+
"eslint-plugin-vue": "^5.2.3"
34+
}
35+
}

src/component-not-registered.js

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/**
2+
* @author sharkykh
3+
* Based on https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/component-name-in-template-casing.js
4+
*/
5+
'use strict';
6+
7+
// ------------------------------------------------------------------------------
8+
// Requirements
9+
// ------------------------------------------------------------------------------
10+
11+
const utils = require('eslint-plugin-vue/lib/utils');
12+
const casing = require('eslint-plugin-vue/lib/utils/casing');
13+
14+
//------------------------------------------------------------------------------
15+
// Helpers
16+
//------------------------------------------------------------------------------
17+
18+
const VueBuiltInComponents = [
19+
'component',
20+
'keep-alive',
21+
'slot',
22+
'transition',
23+
'transition-group'
24+
];
25+
26+
//------------------------------------------------------------------------------
27+
// Rule Definition
28+
//------------------------------------------------------------------------------
29+
30+
module.exports = {
31+
meta: {
32+
type: 'problem',
33+
schema: [
34+
{
35+
type: 'array',
36+
items: {
37+
type: 'string'
38+
},
39+
uniqueItems: true,
40+
additionalItems: false
41+
}
42+
]
43+
},
44+
45+
create(context) {
46+
const allowedComponents = VueBuiltInComponents.concat(context.options[0] || []);
47+
const registeredComponents = [];
48+
49+
const tokens = context.parserServices.getTemplateBodyTokenStore && context.parserServices.getTemplateBodyTokenStore();
50+
51+
let hasInvalidEOF = false;
52+
53+
/**
54+
* Checks whether the given node is the verification target node.
55+
* @param {VElement} node element node
56+
* @returns {boolean} `true` if the given node is the verification target node.
57+
*/
58+
function isVerifyTarget(node) {
59+
// If the component is allowed, ignore it
60+
try {
61+
if (allowedComponents.some(name => name === node.rawName)) {
62+
return false;
63+
}
64+
} catch (_) {}
65+
66+
// Ignore non-Vue-components (vanilla HTML elements and SVG)
67+
if ((!utils.isHtmlElementNode(node) && !utils.isSvgElementNode(node)) ||
68+
utils.isHtmlWellKnownElementName(node.rawName) ||
69+
utils.isSvgWellKnownElementName(node.rawName)
70+
) {
71+
return false;
72+
}
73+
74+
return true;
75+
}
76+
77+
return utils.defineTemplateBodyVisitor(
78+
context,
79+
{
80+
VElement(node) {
81+
if (hasInvalidEOF) {
82+
return;
83+
}
84+
85+
if (!isVerifyTarget(node)) {
86+
return;
87+
}
88+
89+
const name = node.rawName;
90+
const casingName = casing.getConverter('PascalCase')(name);
91+
if (!registeredComponents.some(componentName => casingName === componentName)) {
92+
const { startTag } = node;
93+
const open = tokens.getFirstToken(startTag);
94+
95+
context.report({
96+
node: open,
97+
loc: open.loc,
98+
message: 'Component "{{name}}" is used but not registered.',
99+
data: {
100+
name
101+
}
102+
});
103+
}
104+
}
105+
},
106+
Object.assign(
107+
{
108+
Program(node) {
109+
hasInvalidEOF = utils.hasInvalidEOF(node);
110+
}
111+
},
112+
utils.executeOnVue(context, obj => {
113+
registeredComponents.push(...utils.getRegisteredComponents(obj).map(n => n.name));
114+
})
115+
)
116+
);
117+
}
118+
};

src/index.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
'use strict';
2+
3+
module.exports = {
4+
rules: {
5+
'component-not-registered': require('./component-not-registered.js')
6+
}
7+
};

0 commit comments

Comments
 (0)