@polyv/eslint-config 0.8.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +101 -52
- package/configs/common/README.md +87 -0
- package/configs/common/index.mjs +86 -0
- package/configs/importx/README.md +51 -0
- package/configs/importx/index.mjs +52 -0
- package/configs/js/README.md +34 -0
- package/configs/js/index.mjs +104 -0
- package/configs/miniprogram/README.md +50 -0
- package/configs/miniprogram/index.mjs +46 -0
- package/configs/prettier/README.md +53 -0
- package/configs/prettier/index.mjs +17 -0
- package/configs/sonarjs/README.md +48 -0
- package/configs/sonarjs/index.mjs +92 -0
- package/configs/ts/README.md +43 -0
- package/configs/ts/index.mjs +148 -0
- package/configs/vue2/README.md +87 -0
- package/configs/vue2/index.mjs +96 -0
- package/index.mjs +29 -0
- package/package.json +58 -26
- package/plugin.mjs +17 -0
- package/prettier-config.mjs +15 -0
- package/rules/explicit-module-boundary-types/README.md +126 -0
- package/rules/explicit-module-boundary-types/index.mjs +171 -0
- package/rules/no-relative-directory-index-imports/README.md +87 -0
- package/rules/no-relative-directory-index-imports/index.mjs +142 -0
- package/rules/no-vue-component-variable-name-conflict/README.md +85 -0
- package/rules/no-vue-component-variable-name-conflict/index.mjs +262 -0
- package/utils.mjs +3 -0
- package/.editorconfig +0 -5
- package/.eslintrc.js +0 -3
- package/.gitattributes +0 -12
- package/.nvmrc +0 -1
- package/lib/for-js.js +0 -84
- package/lib/for-ts.js +0 -88
- package/lib/for-vue2-js.js +0 -45
- package/lib/util.js +0 -7
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# no-vue-component-variable-name-conflict
|
|
2
|
+
|
|
3
|
+
`polyv/no-vue-component-variable-name-conflict` 用于禁止 Vue `<script setup>` 中的组件导入名和 lower camel 本地声明产生命名冲突。
|
|
4
|
+
|
|
5
|
+
## 适用场景
|
|
6
|
+
|
|
7
|
+
在 `<script setup>` 中,Vue 组件导入名通常会在模板里自动暴露。例如 `MemberType` 会对应模板里的 `<member-type>`。
|
|
8
|
+
|
|
9
|
+
如果同一个 `<script setup>` 又声明了 `memberType` 变量、函数或类,模板和 ESLint 的变量使用标记容易把 `<member-type>` 关联到 `memberType`,从而导致真正的组件导入 `MemberType` 被判断为未使用。
|
|
10
|
+
|
|
11
|
+
## 使用方式
|
|
12
|
+
|
|
13
|
+
如果已经组合 `polyv.configs.common`,`polyv` plugin 会自动注册:
|
|
14
|
+
|
|
15
|
+
```javascript
|
|
16
|
+
// eslint.config.mjs
|
|
17
|
+
import polyv from '@polyv/eslint-config';
|
|
18
|
+
|
|
19
|
+
export default [
|
|
20
|
+
...polyv.configs.common,
|
|
21
|
+
{
|
|
22
|
+
rules: {
|
|
23
|
+
'polyv/no-vue-component-variable-name-conflict': 'error'
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
];
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Vue2 项目通常直接组合 `polyv.configs.vue2`,该配置会默认启用本规则:
|
|
30
|
+
|
|
31
|
+
```javascript
|
|
32
|
+
// eslint.config.mjs
|
|
33
|
+
import polyv from '@polyv/eslint-config';
|
|
34
|
+
|
|
35
|
+
export default [
|
|
36
|
+
...polyv.configs.common,
|
|
37
|
+
...polyv.configs.ts,
|
|
38
|
+
...polyv.configs.vue2
|
|
39
|
+
];
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## 错误示例
|
|
43
|
+
|
|
44
|
+
```vue
|
|
45
|
+
<!-- bad.vue -->
|
|
46
|
+
<template>
|
|
47
|
+
<member-type v-model="memberType" />
|
|
48
|
+
</template>
|
|
49
|
+
|
|
50
|
+
<script setup lang="ts">
|
|
51
|
+
import { ref } from 'vue';
|
|
52
|
+
import MemberType from './components/member-type.vue';
|
|
53
|
+
|
|
54
|
+
const memberType = ref('online');
|
|
55
|
+
</script>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## 正确示例
|
|
59
|
+
|
|
60
|
+
```vue
|
|
61
|
+
<!-- good.vue -->
|
|
62
|
+
<template>
|
|
63
|
+
<member-type v-model="currentMemberType" />
|
|
64
|
+
</template>
|
|
65
|
+
|
|
66
|
+
<script setup lang="ts">
|
|
67
|
+
import { ref } from 'vue';
|
|
68
|
+
import MemberType from './components/member-type.vue';
|
|
69
|
+
|
|
70
|
+
const currentMemberType = ref('online');
|
|
71
|
+
</script>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## 检查范围
|
|
75
|
+
|
|
76
|
+
该规则只检查 `.vue` 文件中的 `<script setup>`:
|
|
77
|
+
|
|
78
|
+
- 收集模板里的 kebab-case 标签,例如 `<member-type>`。
|
|
79
|
+
- 收集 `<script setup>` 中 PascalCase 组件导入,例如 `MemberType`。
|
|
80
|
+
- 把组件名转换为 kebab-case 标签名和 lower camel 变量名,例如 `MemberType` 对应 `<member-type>` 和 `memberType`。
|
|
81
|
+
- 检查 `<script setup>` 中同名 lower camel 的变量、函数或类声明。
|
|
82
|
+
|
|
83
|
+
## 自动修复
|
|
84
|
+
|
|
85
|
+
该规则不提供自动修复。变量改名会影响业务语义和引用范围,应由开发者按提示手动调整为更明确的名称,例如 `currentMemberType`。
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
function getFilename(context) {
|
|
2
|
+
return context.filename || context.getFilename?.();
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
function isVueFile(context) {
|
|
6
|
+
return getFilename(context)?.endsWith('.vue') === true;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function getSourceCode(context) {
|
|
10
|
+
return context.sourceCode || context.getSourceCode();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function getParserServices(context) {
|
|
14
|
+
return getSourceCode(context).parserServices || context.parserServices;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function getAttributeName(attribute) {
|
|
18
|
+
return attribute?.key?.name ?? null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function isScriptSetupElement(node) {
|
|
22
|
+
return (
|
|
23
|
+
node.type === 'VElement' &&
|
|
24
|
+
node.name === 'script' &&
|
|
25
|
+
node.startTag?.attributes?.some((attribute) => getAttributeName(attribute) === 'setup')
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function getScriptSetupRanges(context) {
|
|
30
|
+
const services = getParserServices(context);
|
|
31
|
+
const fragment = services?.getDocumentFragment?.();
|
|
32
|
+
|
|
33
|
+
if (!fragment?.children) {
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return fragment.children
|
|
38
|
+
.filter(isScriptSetupElement)
|
|
39
|
+
.map((node) => [
|
|
40
|
+
node.startTag.range[1],
|
|
41
|
+
node.endTag?.range?.[0] ?? node.range[1]
|
|
42
|
+
]);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function isInRanges(node, ranges) {
|
|
46
|
+
if (!node?.range) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return ranges.some(([start, end]) => node.range[0] >= start && node.range[1] <= end);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function isKebabCaseTagName(tagName) {
|
|
54
|
+
return /^[a-z][a-z0-9]*(?:-[a-z0-9]+)+$/.test(tagName);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function isComponentLocalName(name) {
|
|
58
|
+
return /^[A-Z]/.test(name);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function toKebabCase(name) {
|
|
62
|
+
return name
|
|
63
|
+
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1-$2')
|
|
64
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
|
|
65
|
+
.replace(/_/g, '-')
|
|
66
|
+
.toLowerCase();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function toLowerCamelCase(name) {
|
|
70
|
+
return name.charAt(0).toLowerCase() + name.slice(1);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function toSuggestName(componentName) {
|
|
74
|
+
return `current${componentName}`;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function getImportLocalNames(node) {
|
|
78
|
+
return node.specifiers
|
|
79
|
+
.map((specifier) => specifier.local?.name)
|
|
80
|
+
.filter((name) => typeof name === 'string' && isComponentLocalName(name));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function addLocalDeclaration(localDeclarations, name, node) {
|
|
84
|
+
if (!name || localDeclarations.has(name)) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
localDeclarations.set(name, node);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function collectPatternIdentifiers(pattern, identifiers) {
|
|
92
|
+
if (!pattern) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (pattern.type === 'Identifier') {
|
|
97
|
+
identifiers.push(pattern);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (pattern.type === 'RestElement') {
|
|
102
|
+
collectPatternIdentifiers(pattern.argument, identifiers);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (pattern.type === 'AssignmentPattern') {
|
|
107
|
+
collectPatternIdentifiers(pattern.left, identifiers);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (pattern.type === 'ArrayPattern') {
|
|
112
|
+
pattern.elements.forEach((element) => collectPatternIdentifiers(element, identifiers));
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (pattern.type === 'ObjectPattern') {
|
|
117
|
+
pattern.properties.forEach((property) => {
|
|
118
|
+
if (property.type === 'Property') {
|
|
119
|
+
collectPatternIdentifiers(property.value, identifiers);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
collectPatternIdentifiers(property.argument, identifiers);
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function getDeclarationIdentifierNodes(node) {
|
|
129
|
+
if (
|
|
130
|
+
(node.type === 'FunctionDeclaration' || node.type === 'ClassDeclaration') &&
|
|
131
|
+
node.id?.type === 'Identifier'
|
|
132
|
+
) {
|
|
133
|
+
return [node.id];
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (node.type !== 'VariableDeclarator') {
|
|
137
|
+
return [];
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const identifiers = [];
|
|
141
|
+
collectPatternIdentifiers(node.id, identifiers);
|
|
142
|
+
return identifiers;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function isRootTemplateElement(node) {
|
|
146
|
+
return (node.rawName || node.name) === 'template' && node.parent?.type === 'VDocumentFragment';
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export default {
|
|
150
|
+
meta: {
|
|
151
|
+
type: 'problem',
|
|
152
|
+
docs: {
|
|
153
|
+
description: '禁止 Vue script setup 中的组件导入名和 lower camel 本地声明产生命名冲突'
|
|
154
|
+
},
|
|
155
|
+
schema: [],
|
|
156
|
+
messages: {
|
|
157
|
+
componentVariableNameConflict:
|
|
158
|
+
'变量 "{{variableName}}" 与组件 "{{componentName}}" 的模板标签 "<{{tagName}}>" 命名冲突,可能导致模板把该标签识别为变量而不是组件。请将变量改成更明确的名称,例如 "{{suggestName}}"。'
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
create(context) {
|
|
162
|
+
if (!isVueFile(context)) {
|
|
163
|
+
return {};
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const services = getParserServices(context);
|
|
167
|
+
if (!services?.defineTemplateBodyVisitor) {
|
|
168
|
+
return {};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const scriptSetupRanges = getScriptSetupRanges(context);
|
|
172
|
+
if (scriptSetupRanges.length === 0) {
|
|
173
|
+
return {};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const templateTags = new Set();
|
|
177
|
+
const componentImports = new Map();
|
|
178
|
+
const localDeclarations = new Map();
|
|
179
|
+
let hasReported = false;
|
|
180
|
+
|
|
181
|
+
function reportConflicts() {
|
|
182
|
+
if (hasReported) {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
hasReported = true;
|
|
187
|
+
|
|
188
|
+
componentImports.forEach((component) => {
|
|
189
|
+
const localDeclaration = localDeclarations.get(component.variableName);
|
|
190
|
+
if (!templateTags.has(component.tagName) || !localDeclaration) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
context.report({
|
|
195
|
+
node: localDeclaration,
|
|
196
|
+
messageId: 'componentVariableNameConflict',
|
|
197
|
+
data: component
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return services.defineTemplateBodyVisitor(
|
|
203
|
+
{
|
|
204
|
+
VElement(node) {
|
|
205
|
+
const tagName = node.rawName || node.name;
|
|
206
|
+
if (typeof tagName === 'string' && isKebabCaseTagName(tagName)) {
|
|
207
|
+
templateTags.add(tagName);
|
|
208
|
+
}
|
|
209
|
+
},
|
|
210
|
+
'VElement:exit'(node) {
|
|
211
|
+
if (isRootTemplateElement(node)) {
|
|
212
|
+
reportConflicts();
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
ImportDeclaration(node) {
|
|
218
|
+
if (!isInRanges(node, scriptSetupRanges)) {
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
getImportLocalNames(node).forEach((componentName) => {
|
|
223
|
+
const tagName = toKebabCase(componentName);
|
|
224
|
+
componentImports.set(componentName, {
|
|
225
|
+
componentName,
|
|
226
|
+
tagName,
|
|
227
|
+
variableName: toLowerCamelCase(componentName),
|
|
228
|
+
suggestName: toSuggestName(componentName)
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
},
|
|
232
|
+
VariableDeclarator(node) {
|
|
233
|
+
if (!isInRanges(node, scriptSetupRanges)) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
getDeclarationIdentifierNodes(node).forEach((identifier) => {
|
|
238
|
+
addLocalDeclaration(localDeclarations, identifier.name, identifier);
|
|
239
|
+
});
|
|
240
|
+
},
|
|
241
|
+
FunctionDeclaration(node) {
|
|
242
|
+
if (!isInRanges(node, scriptSetupRanges)) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
getDeclarationIdentifierNodes(node).forEach((identifier) => {
|
|
247
|
+
addLocalDeclaration(localDeclarations, identifier.name, identifier);
|
|
248
|
+
});
|
|
249
|
+
},
|
|
250
|
+
ClassDeclaration(node) {
|
|
251
|
+
if (!isInRanges(node, scriptSetupRanges)) {
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
getDeclarationIdentifierNodes(node).forEach((identifier) => {
|
|
256
|
+
addLocalDeclaration(localDeclarations, identifier.name, identifier);
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
};
|
package/utils.mjs
ADDED
package/.editorconfig
DELETED
package/.eslintrc.js
DELETED
package/.gitattributes
DELETED
package/.nvmrc
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
20
|
package/lib/for-js.js
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* JavaScript 验证规则(基础规则)。
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
const {
|
|
6
|
-
devWarnProdError,
|
|
7
|
-
strictErrorOtherwiseWarn
|
|
8
|
-
} = require('./util');
|
|
9
|
-
|
|
10
|
-
module.exports = {
|
|
11
|
-
parser: '@babel/eslint-parser',
|
|
12
|
-
parserOptions: {
|
|
13
|
-
ecmaVersion: 2020,
|
|
14
|
-
sourceType: 'module',
|
|
15
|
-
requireConfigFile: false
|
|
16
|
-
},
|
|
17
|
-
env: {
|
|
18
|
-
browser: true,
|
|
19
|
-
es6: true
|
|
20
|
-
},
|
|
21
|
-
plugins: [
|
|
22
|
-
'promise'
|
|
23
|
-
],
|
|
24
|
-
extends: [
|
|
25
|
-
'eslint:recommended',
|
|
26
|
-
'standard',
|
|
27
|
-
'plugin:import/recommended',
|
|
28
|
-
'plugin:sonarjs/recommended'
|
|
29
|
-
],
|
|
30
|
-
rules: {
|
|
31
|
-
semi: ['error', 'always'],
|
|
32
|
-
'space-before-function-paren': ['error', {
|
|
33
|
-
anonymous: 'never',
|
|
34
|
-
named: 'never',
|
|
35
|
-
asyncArrow: 'always'
|
|
36
|
-
}],
|
|
37
|
-
'operator-linebreak': ['error', 'after', {
|
|
38
|
-
overrides: {
|
|
39
|
-
'?': 'before',
|
|
40
|
-
':': 'before'
|
|
41
|
-
}
|
|
42
|
-
}],
|
|
43
|
-
'comma-dangle': ['error', 'only-multiline'],
|
|
44
|
-
'no-trailing-spaces': ['error', { ignoreComments: true }],
|
|
45
|
-
'no-multiple-empty-lines': ['error', { max: 2 }],
|
|
46
|
-
'wrap-iife': ['error', 'inside'],
|
|
47
|
-
'no-confusing-arrow': 'error',
|
|
48
|
-
'padded-blocks': 'off',
|
|
49
|
-
|
|
50
|
-
camelcase: 'error',
|
|
51
|
-
'no-debugger': devWarnProdError,
|
|
52
|
-
'no-unused-vars': [devWarnProdError, {
|
|
53
|
-
vars: 'all',
|
|
54
|
-
args: 'after-used',
|
|
55
|
-
ignoreRestSiblings: true,
|
|
56
|
-
caughtErrors: 'none'
|
|
57
|
-
}],
|
|
58
|
-
'no-use-before-define': ['error', {
|
|
59
|
-
functions: false,
|
|
60
|
-
classes: false,
|
|
61
|
-
variables: true
|
|
62
|
-
}],
|
|
63
|
-
'no-loop-func': 'error',
|
|
64
|
-
'no-script-url': 'error',
|
|
65
|
-
'no-new': 'off',
|
|
66
|
-
'no-constant-condition': devWarnProdError,
|
|
67
|
-
'no-empty': [devWarnProdError, { allowEmptyCatch: true }],
|
|
68
|
-
'no-lonely-if': 'off',
|
|
69
|
-
'no-var': 'error',
|
|
70
|
-
'no-template-curly-in-string': 'off',
|
|
71
|
-
'prefer-promise-reject-errors': 'error',
|
|
72
|
-
|
|
73
|
-
'import/no-unresolved': 'off',
|
|
74
|
-
'import/no-duplicates': 'error',
|
|
75
|
-
|
|
76
|
-
'promise/prefer-await-to-then': 'warn',
|
|
77
|
-
|
|
78
|
-
'sonarjs/cognitive-complexity': ['error', 20],
|
|
79
|
-
'sonarjs/no-duplicate-string': [devWarnProdError, { threshold: 5 }],
|
|
80
|
-
'sonarjs/prefer-single-boolean-return': 'off',
|
|
81
|
-
'sonarjs/no-collection-size-mischeck': 'off',
|
|
82
|
-
'sonarjs/no-nested-template-literals': strictErrorOtherwiseWarn
|
|
83
|
-
}
|
|
84
|
-
};
|
package/lib/for-ts.js
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* TypeScript 工程的附加验证规则。
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
const {
|
|
6
|
-
devWarnProdError,
|
|
7
|
-
strictErrorOtherwiseWarn
|
|
8
|
-
} = require('./util');
|
|
9
|
-
|
|
10
|
-
module.exports = {
|
|
11
|
-
overrides: [{
|
|
12
|
-
files: ['*.ts', '*.tsx'],
|
|
13
|
-
extends: [
|
|
14
|
-
'plugin:@typescript-eslint/recommended',
|
|
15
|
-
'plugin:import/typescript'
|
|
16
|
-
],
|
|
17
|
-
rules: {
|
|
18
|
-
semi: 'off',
|
|
19
|
-
'@typescript-eslint/semi': ['error', 'always'],
|
|
20
|
-
|
|
21
|
-
indent: 'off',
|
|
22
|
-
'@typescript-eslint/indent': ['error', 2, {
|
|
23
|
-
SwitchCase: 1
|
|
24
|
-
}],
|
|
25
|
-
|
|
26
|
-
'comma-spacing': 'off',
|
|
27
|
-
'@typescript-eslint/comma-spacing': ['error'],
|
|
28
|
-
|
|
29
|
-
'comma-dangle': 'off',
|
|
30
|
-
'@typescript-eslint/comma-dangle': ['error', 'only-multiline'],
|
|
31
|
-
|
|
32
|
-
'no-use-before-define': 'off',
|
|
33
|
-
'@typescript-eslint/no-use-before-define': ['error', {
|
|
34
|
-
functions: false,
|
|
35
|
-
classes: false,
|
|
36
|
-
variables: true
|
|
37
|
-
}],
|
|
38
|
-
|
|
39
|
-
'no-unused-vars': 'off',
|
|
40
|
-
'@typescript-eslint/no-unused-vars': [devWarnProdError, {
|
|
41
|
-
vars: 'all',
|
|
42
|
-
args: 'after-used',
|
|
43
|
-
ignoreRestSiblings: true,
|
|
44
|
-
caughtErrors: 'none'
|
|
45
|
-
}],
|
|
46
|
-
|
|
47
|
-
'no-loop-func': 'off',
|
|
48
|
-
'@typescript-eslint/no-loop-func': 'error',
|
|
49
|
-
|
|
50
|
-
'space-before-function-paren': 'off',
|
|
51
|
-
'@typescript-eslint/space-before-function-paren': ['error', {
|
|
52
|
-
anonymous: 'never',
|
|
53
|
-
named: 'never',
|
|
54
|
-
asyncArrow: 'always'
|
|
55
|
-
}],
|
|
56
|
-
|
|
57
|
-
'@typescript-eslint/no-explicit-any': 'warn',
|
|
58
|
-
'@typescript-eslint/no-empty-function': 'off',
|
|
59
|
-
'@typescript-eslint/no-empty-interface': 'off',
|
|
60
|
-
'@typescript-eslint/type-annotation-spacing': ['error', {
|
|
61
|
-
after: true,
|
|
62
|
-
before: false,
|
|
63
|
-
overrides: {
|
|
64
|
-
arrow: {
|
|
65
|
-
before: true,
|
|
66
|
-
after: true
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}],
|
|
70
|
-
'@typescript-eslint/explicit-module-boundary-types': devWarnProdError,
|
|
71
|
-
'@typescript-eslint/naming-convention': [strictErrorOtherwiseWarn, {
|
|
72
|
-
selector: 'enumMember',
|
|
73
|
-
format: ['PascalCase']
|
|
74
|
-
}, {
|
|
75
|
-
selector: 'enum',
|
|
76
|
-
format: ['PascalCase']
|
|
77
|
-
}],
|
|
78
|
-
'@typescript-eslint/no-var-requires': 'off',
|
|
79
|
-
'@typescript-eslint/no-for-in-array': 'error'
|
|
80
|
-
},
|
|
81
|
-
settings: {
|
|
82
|
-
'import/resolver': {
|
|
83
|
-
typescript: true,
|
|
84
|
-
node: true
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}]
|
|
88
|
-
};
|
package/lib/for-vue2-js.js
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Vue.js 工程的验证规则。
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
const { strictErrorOtherwiseWarn } = require('./util');
|
|
6
|
-
const jsConfig = require('./for-js');
|
|
7
|
-
|
|
8
|
-
module.exports = Object.assign({}, jsConfig, {
|
|
9
|
-
parser: 'vue-eslint-parser',
|
|
10
|
-
parserOptions: {
|
|
11
|
-
parser: '@babel/eslint-parser',
|
|
12
|
-
...jsConfig.parserOptions
|
|
13
|
-
},
|
|
14
|
-
extends: [
|
|
15
|
-
...jsConfig.extends,
|
|
16
|
-
'@vue/standard',
|
|
17
|
-
'plugin:vue/essential'
|
|
18
|
-
],
|
|
19
|
-
rules: {
|
|
20
|
-
...jsConfig.rules,
|
|
21
|
-
'vue/html-indent': ['error', 2],
|
|
22
|
-
'vue/html-self-closing': ['error', {
|
|
23
|
-
html: {
|
|
24
|
-
void: 'always',
|
|
25
|
-
normal: 'never',
|
|
26
|
-
component: 'always'
|
|
27
|
-
},
|
|
28
|
-
svg: 'always',
|
|
29
|
-
math: 'always'
|
|
30
|
-
}],
|
|
31
|
-
'vue/no-v-html': 'off',
|
|
32
|
-
'vue/max-attributes-per-line': ['error', {
|
|
33
|
-
singleline: 3,
|
|
34
|
-
multiline: 1
|
|
35
|
-
}],
|
|
36
|
-
'vue/singleline-html-element-content-newline': 'off',
|
|
37
|
-
'vue/custom-event-name-casing': [strictErrorOtherwiseWarn, 'kebab-case'],
|
|
38
|
-
'vue/no-mutating-props': strictErrorOtherwiseWarn,
|
|
39
|
-
'vue/multi-word-component-names': [strictErrorOtherwiseWarn, {
|
|
40
|
-
ignores: ['index', 'Index', 'default', 'Default']
|
|
41
|
-
}],
|
|
42
|
-
'vue/attribute-hyphenation': [strictErrorOtherwiseWarn, 'always'],
|
|
43
|
-
'vue/v-on-event-hyphenation': [strictErrorOtherwiseWarn, 'always']
|
|
44
|
-
}
|
|
45
|
-
});
|