@nextcloud/eslint-config 8.3.0-beta.0 → 8.3.0-beta.1
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/CHANGELOG.md +13 -0
- package/README.md +14 -0
- package/index.js +15 -151
- package/package.json +11 -10
- package/parts/base.js +96 -0
- package/parts/typescript.js +36 -0
- package/parts/vue.js +42 -0
- package/typescript.js +25 -0
- package/tests/eslint-config.test.ts +0 -31
- package/tests/eslint.d.ts +0 -11
- package/tests/fixtures/example-fail.js +0 -3
- package/tests/fixtures/some.tsx +0 -7
- package/tests/setup-jest.ts +0 -128
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
## [v8.3.0-beta.1](https://github.com/nextcloud/eslint-config/tree/v8.3.0-beta.1) (2023-06-27)
|
|
6
|
+
|
|
7
|
+
[Full Changelog](https://github.com/nextcloud/eslint-config/compare/v8.3.0-beta.0...v8.3.0-beta.1)
|
|
8
|
+
|
|
9
|
+
**Features:**
|
|
10
|
+
- Provide config for vue files written in Typescript, use `extends: "@nextcloud/eslint-config/typescript"`.
|
|
11
|
+
- Fully support vue files using the Composition API `<script setup>`.
|
|
12
|
+
|
|
13
|
+
**Fixed:**
|
|
14
|
+
- fix: Add Typescript overrides for all valid Typescript file extensions by @susnux in https://github.com/nextcloud/eslint-config/pull/567
|
|
15
|
+
|
|
3
16
|
## [v8.3.0-beta.0](https://github.com/nextcloud/eslint-config/tree/v8.3.0-beta.0) (2023-05-12)
|
|
4
17
|
|
|
5
18
|
[Full Changelog](https://github.com/nextcloud/eslint-config/compare/v8.2.1...v8.3.0-beta.0)
|
package/README.md
CHANGED
|
@@ -28,6 +28,20 @@ module.exports = {
|
|
|
28
28
|
}
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
+
### Usage with Typescript projects
|
|
32
|
+
|
|
33
|
+
If your projects uses Typescript for vue files, like `<script lang="ts">` then use the Typescript config instead:
|
|
34
|
+
|
|
35
|
+
Add a file `.eslintrc.js` in the root directory of your app repository with the following content:
|
|
36
|
+
|
|
37
|
+
```js
|
|
38
|
+
module.exports = {
|
|
39
|
+
extends: [
|
|
40
|
+
'@nextcloud/eslint-config/typescript',
|
|
41
|
+
],
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
31
45
|
## Release new version
|
|
32
46
|
|
|
33
47
|
1. Update CHANGELOG.md file with the latest changes
|
package/index.js
CHANGED
|
@@ -1,157 +1,21 @@
|
|
|
1
|
+
const base = require('./parts/base.js')
|
|
2
|
+
const typescriptOverrides = require('./parts/typescript.js')
|
|
3
|
+
const vueOverrides = require('./parts/vue.js')
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Config for Vue + Javascript projects (optionally with parts, except vue files, written in Typescript)
|
|
7
|
+
*/
|
|
1
8
|
module.exports = {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
commonjs: true,
|
|
6
|
-
es6: true,
|
|
7
|
-
node: true,
|
|
8
|
-
// Allow jest syntax in the src folder
|
|
9
|
-
jest: true,
|
|
10
|
-
},
|
|
11
|
-
parserOptions: {
|
|
12
|
-
parser: '@babel/eslint-parser',
|
|
13
|
-
ecmaVersion: 6,
|
|
14
|
-
requireConfigFile: false,
|
|
15
|
-
},
|
|
16
|
-
extends: [
|
|
17
|
-
'eslint:recommended',
|
|
18
|
-
'plugin:import/errors',
|
|
19
|
-
'plugin:import/warnings',
|
|
20
|
-
'plugin:n/recommended',
|
|
21
|
-
'plugin:vue/recommended',
|
|
22
|
-
'plugin:@nextcloud/recommended',
|
|
23
|
-
'plugin:jsdoc/recommended',
|
|
24
|
-
'standard',
|
|
25
|
-
],
|
|
26
|
-
settings: {
|
|
27
|
-
'import/resolver': {
|
|
28
|
-
node: {
|
|
29
|
-
paths: ['src'],
|
|
30
|
-
extensions: ['.js', '.vue'],
|
|
31
|
-
},
|
|
32
|
-
exports: {
|
|
33
|
-
conditions: ['import'],
|
|
34
|
-
},
|
|
35
|
-
},
|
|
36
|
-
jsdoc: {
|
|
37
|
-
tagNamePreference: {
|
|
38
|
-
returns: 'return',
|
|
39
|
-
},
|
|
40
|
-
mode: 'typescript',
|
|
41
|
-
},
|
|
42
|
-
},
|
|
43
|
-
plugins: ['vue', 'n', 'jsdoc'],
|
|
44
|
-
rules: {
|
|
45
|
-
// space before function ()
|
|
46
|
-
'space-before-function-paren': ['error', {
|
|
47
|
-
anonymous: 'never',
|
|
48
|
-
named: 'never',
|
|
49
|
-
asyncArrow: 'always',
|
|
50
|
-
}],
|
|
51
|
-
// stay consistent with array brackets
|
|
52
|
-
'array-bracket-newline': ['error', 'consistent'],
|
|
53
|
-
// tabs only for indentation
|
|
54
|
-
indent: ['error', 'tab'],
|
|
55
|
-
'no-tabs': ['error', { allowIndentationTabs: true }],
|
|
56
|
-
'vue/html-indent': ['error', 'tab'],
|
|
57
|
-
// allow spaces after tabs for alignment
|
|
58
|
-
'no-mixed-spaces-and-tabs': ['error', 'smart-tabs'],
|
|
59
|
-
// only debug console
|
|
60
|
-
'no-console': ['error', { allow: ['error', 'warn', 'info', 'debug'] }],
|
|
61
|
-
// classes blocks
|
|
62
|
-
'padded-blocks': ['error', { classes: 'always' }],
|
|
63
|
-
// always have the operator in front
|
|
64
|
-
'operator-linebreak': ['error', 'before'],
|
|
65
|
-
// ternary on multiline
|
|
66
|
-
'multiline-ternary': ['error', 'always-multiline'],
|
|
67
|
-
// force proper JSDocs
|
|
68
|
-
'jsdoc/require-returns': 0,
|
|
69
|
-
'jsdoc/require-returns-description': 0,
|
|
70
|
-
'jsdoc/tag-lines': ['off'],
|
|
71
|
-
// disallow use of "var"
|
|
72
|
-
'no-var': 'error',
|
|
73
|
-
// suggest using const
|
|
74
|
-
'prefer-const': 'error',
|
|
75
|
-
// es6 import/export and require
|
|
76
|
-
'n/no-unpublished-require': ['off'],
|
|
77
|
-
'n/no-unsupported-features/es-syntax': ['off'],
|
|
78
|
-
// PascalCase components names for vuejs
|
|
79
|
-
// https://vuejs.org/v2/style-guide/#Single-file-component-filename-casing-strongly-recommended
|
|
80
|
-
'vue/component-name-in-template-casing': ['error', 'PascalCase'],
|
|
81
|
-
// force name
|
|
82
|
-
'vue/match-component-file-name': ['error', {
|
|
83
|
-
extensions: ['jsx', 'vue', 'js'],
|
|
84
|
-
shouldMatchCase: true,
|
|
85
|
-
}],
|
|
86
|
-
// space before self-closing elements
|
|
87
|
-
'vue/html-closing-bracket-spacing': 'error',
|
|
88
|
-
// no ending html tag on a new line
|
|
89
|
-
'vue/html-closing-bracket-newline': ['error', { multiline: 'never' }],
|
|
90
|
-
// check vue files too
|
|
91
|
-
'n/no-missing-import': ['error', {}],
|
|
92
|
-
// code spacing with attributes
|
|
93
|
-
'vue/max-attributes-per-line': ['error', {
|
|
94
|
-
singleline: 3,
|
|
95
|
-
multiline: 1,
|
|
96
|
-
}],
|
|
97
|
-
'vue/first-attribute-linebreak': ['error', {
|
|
98
|
-
singleline: 'beside',
|
|
99
|
-
multiline: 'beside',
|
|
100
|
-
}],
|
|
101
|
-
// Allow single-word components names
|
|
102
|
-
'vue/multi-word-component-names': ['off'],
|
|
103
|
-
// custom event naming convention
|
|
104
|
-
'vue/custom-event-name-casing': ['error', 'kebab-case', {
|
|
105
|
-
// allows custom xxxx:xxx events formats
|
|
106
|
-
ignores: ['/^[a-z]+(?:-[a-z]+)*:[a-z]+(?:-[a-z]+)*$/u'],
|
|
107
|
-
}],
|
|
108
|
-
// always add a trailing comma (for diff readability)
|
|
109
|
-
'comma-dangle': ['warn', 'always-multiline'],
|
|
110
|
-
// Allow shallow import of @vue/test-utils and @testing-library/vue in order to be able to use it in
|
|
111
|
-
// the src folder
|
|
112
|
-
'n/no-unpublished-import': ['error', {
|
|
113
|
-
allowModules: ['@vue/test-utils', '@testing-library/vue'],
|
|
114
|
-
}],
|
|
115
|
-
// require object literal shorthand syntax
|
|
116
|
-
'object-shorthand': ['error', 'always'],
|
|
117
|
-
// Warn when file extensions are not used on import paths
|
|
118
|
-
'import/extensions': ['warn', 'always', {
|
|
119
|
-
ignorePackages: true,
|
|
120
|
-
}],
|
|
121
|
-
},
|
|
9
|
+
// Base rules
|
|
10
|
+
...base,
|
|
11
|
+
// basic Typescript rules
|
|
122
12
|
overrides: [
|
|
123
13
|
{
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
parserOptions: {
|
|
130
|
-
parser: '@typescript-eslint/parser',
|
|
131
|
-
},
|
|
132
|
-
rules: {
|
|
133
|
-
'n/no-missing-import': 'off',
|
|
134
|
-
'import/extensions': 'off',
|
|
135
|
-
'jsdoc/check-tag-names': [
|
|
136
|
-
'warn', {
|
|
137
|
-
// for projects using typedoc
|
|
138
|
-
definedTags: [
|
|
139
|
-
'notExported',
|
|
140
|
-
'packageDocumentation',
|
|
141
|
-
],
|
|
142
|
-
},
|
|
143
|
-
],
|
|
144
|
-
// Does not make sense with TypeScript
|
|
145
|
-
'jsdoc/require-param-type': 'off',
|
|
146
|
-
},
|
|
147
|
-
settings: {
|
|
148
|
-
'import/resolver': {
|
|
149
|
-
node: {
|
|
150
|
-
paths: ['src'],
|
|
151
|
-
extensions: ['.(m|c)?js', '.ts', '.tsx', '.vue'],
|
|
152
|
-
},
|
|
153
|
-
},
|
|
154
|
-
},
|
|
14
|
+
...typescriptOverrides,
|
|
15
|
+
},
|
|
16
|
+
// Setup different vue parser to support `<script setup>` correctly
|
|
17
|
+
{
|
|
18
|
+
...vueOverrides,
|
|
155
19
|
},
|
|
156
20
|
],
|
|
157
21
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextcloud/eslint-config",
|
|
3
|
-
"version": "8.3.0-beta.
|
|
3
|
+
"version": "8.3.0-beta.1",
|
|
4
4
|
"description": "Eslint shared config for nextcloud vue.js apps",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|
|
@@ -20,13 +20,13 @@
|
|
|
20
20
|
"eslint": "^8.27.0",
|
|
21
21
|
"eslint-config-standard": "^17.0.0",
|
|
22
22
|
"eslint-import-resolver-exports": "^1.0.0-beta.4",
|
|
23
|
+
"eslint-import-resolver-typescript": "^3.5.5",
|
|
23
24
|
"eslint-plugin-import": "^2.26.0",
|
|
24
|
-
"eslint-plugin-jsdoc": "^
|
|
25
|
-
"eslint-plugin-n": "^
|
|
25
|
+
"eslint-plugin-jsdoc": "^46.2.6",
|
|
26
|
+
"eslint-plugin-n": "^16.0.0",
|
|
26
27
|
"eslint-plugin-promise": "^6.1.1",
|
|
27
28
|
"eslint-plugin-vue": "^9.7.0",
|
|
28
|
-
"typescript": "^5.0.2"
|
|
29
|
-
"webpack": "^5.4.0"
|
|
29
|
+
"typescript": "^5.0.2"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@babel/core": "^7.13.10",
|
|
@@ -37,15 +37,16 @@
|
|
|
37
37
|
"eslint": "^8.27.0",
|
|
38
38
|
"eslint-config-standard": "^17.0.0",
|
|
39
39
|
"eslint-import-resolver-exports": "^1.0.0-beta.4",
|
|
40
|
+
"eslint-import-resolver-typescript": "^3.5.5",
|
|
40
41
|
"eslint-plugin-import": "^2.26.0",
|
|
41
|
-
"eslint-plugin-jsdoc": "^
|
|
42
|
-
"eslint-plugin-n": "^
|
|
42
|
+
"eslint-plugin-jsdoc": "^46.2.6",
|
|
43
|
+
"eslint-plugin-n": "^16.0.0",
|
|
43
44
|
"eslint-plugin-promise": "^6.1.1",
|
|
44
45
|
"eslint-plugin-vue": "^9.7.0",
|
|
45
46
|
"jest": "^29.4.1",
|
|
46
47
|
"ts-jest": "^29.0.5",
|
|
47
48
|
"typescript": "^5.0.2",
|
|
48
|
-
"
|
|
49
|
+
"vue-eslint-parser": "^9.3.1"
|
|
49
50
|
},
|
|
50
51
|
"keywords": [
|
|
51
52
|
"eslint",
|
|
@@ -61,8 +62,8 @@
|
|
|
61
62
|
},
|
|
62
63
|
"homepage": "https://github.com/nextcloud/eslint-config#readme",
|
|
63
64
|
"engines": {
|
|
64
|
-
"node": "^
|
|
65
|
-
"npm": "^
|
|
65
|
+
"node": "^20.0.0",
|
|
66
|
+
"npm": "^9.0.0"
|
|
66
67
|
},
|
|
67
68
|
"jest": {
|
|
68
69
|
"preset": "ts-jest",
|
package/parts/base.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/** Base rules */
|
|
2
|
+
module.exports = {
|
|
3
|
+
root: true,
|
|
4
|
+
env: {
|
|
5
|
+
browser: true,
|
|
6
|
+
commonjs: true,
|
|
7
|
+
es6: true,
|
|
8
|
+
node: true,
|
|
9
|
+
// Allow jest syntax in the src folder
|
|
10
|
+
jest: true,
|
|
11
|
+
},
|
|
12
|
+
parser: '@babel/eslint-parser',
|
|
13
|
+
parserOptions: {
|
|
14
|
+
requireConfigFile: false,
|
|
15
|
+
},
|
|
16
|
+
extends: [
|
|
17
|
+
'eslint:recommended',
|
|
18
|
+
'plugin:import/errors',
|
|
19
|
+
'plugin:import/warnings',
|
|
20
|
+
'plugin:n/recommended',
|
|
21
|
+
'plugin:@nextcloud/recommended',
|
|
22
|
+
'plugin:jsdoc/recommended',
|
|
23
|
+
'standard',
|
|
24
|
+
],
|
|
25
|
+
settings: {
|
|
26
|
+
'import/resolver': {
|
|
27
|
+
node: {
|
|
28
|
+
paths: ['src'],
|
|
29
|
+
extensions: ['.js', '.vue'],
|
|
30
|
+
},
|
|
31
|
+
exports: {
|
|
32
|
+
conditions: ['import'],
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
jsdoc: {
|
|
36
|
+
tagNamePreference: {
|
|
37
|
+
returns: 'return',
|
|
38
|
+
},
|
|
39
|
+
mode: 'typescript',
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
plugins: ['vue', 'n', 'jsdoc'],
|
|
43
|
+
rules: {
|
|
44
|
+
// space before function ()
|
|
45
|
+
'space-before-function-paren': ['error', {
|
|
46
|
+
anonymous: 'never',
|
|
47
|
+
named: 'never',
|
|
48
|
+
asyncArrow: 'always',
|
|
49
|
+
}],
|
|
50
|
+
// stay consistent with array brackets
|
|
51
|
+
'array-bracket-newline': ['error', 'consistent'],
|
|
52
|
+
// tabs only for indentation
|
|
53
|
+
indent: ['error', 'tab'],
|
|
54
|
+
'no-tabs': ['error', { allowIndentationTabs: true }],
|
|
55
|
+
// allow spaces after tabs for alignment
|
|
56
|
+
'no-mixed-spaces-and-tabs': ['error', 'smart-tabs'],
|
|
57
|
+
// only debug console
|
|
58
|
+
'no-console': ['error', { allow: ['error', 'warn', 'info', 'debug'] }],
|
|
59
|
+
// classes blocks
|
|
60
|
+
'padded-blocks': ['error', { classes: 'always' }],
|
|
61
|
+
// always have the operator in front
|
|
62
|
+
'operator-linebreak': ['error', 'before'],
|
|
63
|
+
// ternary on multiline
|
|
64
|
+
'multiline-ternary': ['error', 'always-multiline'],
|
|
65
|
+
// force proper JSDocs
|
|
66
|
+
'jsdoc/require-returns': 0,
|
|
67
|
+
'jsdoc/require-returns-description': 0,
|
|
68
|
+
'jsdoc/tag-lines': ['off'],
|
|
69
|
+
// disallow use of "var"
|
|
70
|
+
'no-var': 'error',
|
|
71
|
+
// suggest using const
|
|
72
|
+
'prefer-const': 'error',
|
|
73
|
+
// es6 import/export and require
|
|
74
|
+
'n/no-unpublished-require': ['off'],
|
|
75
|
+
'n/no-unsupported-features/es-syntax': ['off'],
|
|
76
|
+
// always add a trailing comma (for diff readability)
|
|
77
|
+
'comma-dangle': ['warn', 'always-multiline'],
|
|
78
|
+
// Allow shallow import of @vue/test-utils and @testing-library/vue in order to be able to use it in
|
|
79
|
+
// the src folder
|
|
80
|
+
'n/no-unpublished-import': ['error', {
|
|
81
|
+
allowModules: ['@vue/test-utils', '@testing-library/vue'],
|
|
82
|
+
}],
|
|
83
|
+
// require object literal shorthand syntax
|
|
84
|
+
'object-shorthand': ['error', 'always'],
|
|
85
|
+
// Warn when file extensions are not used on import paths
|
|
86
|
+
'import/extensions': ['warn', 'always', {
|
|
87
|
+
ignorePackages: true,
|
|
88
|
+
}],
|
|
89
|
+
// ignore camelcase for __webpack variables
|
|
90
|
+
camelcase: ['error', {
|
|
91
|
+
allow: ['^UNSAFE_', '^__webpack_'],
|
|
92
|
+
properties: 'never',
|
|
93
|
+
ignoreGlobals: true,
|
|
94
|
+
}],
|
|
95
|
+
},
|
|
96
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/** Rules for typescript */
|
|
2
|
+
module.exports = {
|
|
3
|
+
files: ['**/*.ts', '**/*.cts', '**/*.mts', '**/*.tsx'],
|
|
4
|
+
extends: [
|
|
5
|
+
'@vue/eslint-config-typescript/recommended',
|
|
6
|
+
'plugin:import/typescript',
|
|
7
|
+
],
|
|
8
|
+
parser: '@typescript-eslint/parser',
|
|
9
|
+
parserOptions: {},
|
|
10
|
+
rules: {
|
|
11
|
+
'n/no-missing-import': 'off',
|
|
12
|
+
'import/extensions': 'off',
|
|
13
|
+
'jsdoc/check-tag-names': [
|
|
14
|
+
'warn', {
|
|
15
|
+
// for projects using typedoc
|
|
16
|
+
definedTags: [
|
|
17
|
+
'notExported',
|
|
18
|
+
'packageDocumentation',
|
|
19
|
+
],
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
// Does not make sense with TypeScript
|
|
23
|
+
'jsdoc/require-param-type': 'off',
|
|
24
|
+
},
|
|
25
|
+
settings: {
|
|
26
|
+
'import/resolver': {
|
|
27
|
+
typescript: {
|
|
28
|
+
alwaysTryTypes: true,
|
|
29
|
+
},
|
|
30
|
+
node: {
|
|
31
|
+
paths: ['src'],
|
|
32
|
+
extensions: ['.(m|c)?js', '.ts', '.tsx', '.vue'],
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
}
|
package/parts/vue.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
|
|
2
|
+
module.exports = {
|
|
3
|
+
files: ['**/*.vue'],
|
|
4
|
+
parser: 'vue-eslint-parser',
|
|
5
|
+
parserOptions: {
|
|
6
|
+
parser: '@babel/eslint-parser',
|
|
7
|
+
},
|
|
8
|
+
extends: ['plugin:vue/recommended'],
|
|
9
|
+
rules: {
|
|
10
|
+
'vue/html-indent': ['error', 'tab'],
|
|
11
|
+
// PascalCase components names for vuejs
|
|
12
|
+
// https://vuejs.org/v2/style-guide/#Single-file-component-filename-casing-strongly-recommended
|
|
13
|
+
'vue/component-name-in-template-casing': ['error', 'PascalCase'],
|
|
14
|
+
// force name
|
|
15
|
+
'vue/match-component-file-name': ['error', {
|
|
16
|
+
extensions: ['jsx', 'vue', 'js'],
|
|
17
|
+
shouldMatchCase: true,
|
|
18
|
+
}],
|
|
19
|
+
// space before self-closing elements
|
|
20
|
+
'vue/html-closing-bracket-spacing': 'error',
|
|
21
|
+
// no ending html tag on a new line
|
|
22
|
+
'vue/html-closing-bracket-newline': ['error', { multiline: 'never' }],
|
|
23
|
+
// check vue files too
|
|
24
|
+
'n/no-missing-import': ['error', {}],
|
|
25
|
+
// code spacing with attributes
|
|
26
|
+
'vue/max-attributes-per-line': ['error', {
|
|
27
|
+
singleline: 3,
|
|
28
|
+
multiline: 1,
|
|
29
|
+
}],
|
|
30
|
+
'vue/first-attribute-linebreak': ['error', {
|
|
31
|
+
singleline: 'beside',
|
|
32
|
+
multiline: 'beside',
|
|
33
|
+
}],
|
|
34
|
+
// Allow single-word components names
|
|
35
|
+
'vue/multi-word-component-names': ['off'],
|
|
36
|
+
// custom event naming convention
|
|
37
|
+
'vue/custom-event-name-casing': ['error', 'kebab-case', {
|
|
38
|
+
// allows custom xxxx:xxx events formats
|
|
39
|
+
ignores: ['/^[a-z]+(?:-[a-z]+)*:[a-z]+(?:-[a-z]+)*$/u'],
|
|
40
|
+
}],
|
|
41
|
+
},
|
|
42
|
+
}
|
package/typescript.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const base = require('./parts/base.js')
|
|
2
|
+
const typescriptOverrides = require('./parts/typescript.js')
|
|
3
|
+
const vueOverrides = require('./parts/vue.js')
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Config for projects written in Typescript + vue including vue files written in Typescript (`<script lang='ts'>`)
|
|
7
|
+
*/
|
|
8
|
+
module.exports = {
|
|
9
|
+
...base,
|
|
10
|
+
overrides: [
|
|
11
|
+
// Add Typescript rules also for vue files
|
|
12
|
+
{
|
|
13
|
+
...typescriptOverrides,
|
|
14
|
+
files: ['**/*.ts', '**/*.tsx', '**/*.vue'],
|
|
15
|
+
},
|
|
16
|
+
// Use different parser for vue files script section
|
|
17
|
+
{
|
|
18
|
+
...vueOverrides,
|
|
19
|
+
parserOptions: {
|
|
20
|
+
parser: '@typescript-eslint/parser',
|
|
21
|
+
sourceType: 'module',
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { ESLint } from "eslint"
|
|
2
|
-
import type { Linter } from "eslint"
|
|
3
|
-
import * as path from 'path'
|
|
4
|
-
import * as eslintConfig from '../index.js'
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const eslint = new ESLint({
|
|
8
|
-
baseConfig: eslintConfig as unknown as Linter.Config<Linter.RulesRecord>
|
|
9
|
-
})
|
|
10
|
-
|
|
11
|
-
const lintFile = async (file) => {
|
|
12
|
-
const real = path.resolve(path.join(__dirname, file))
|
|
13
|
-
return await eslint.lintFiles(real)
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
test('some basic issues should fail', async () => {
|
|
17
|
-
const results = await lintFile('fixtures/example-fail.js')
|
|
18
|
-
expect(results).toHaveIssueCount(3)
|
|
19
|
-
expect(results).toHaveIssue('spaced-comment')
|
|
20
|
-
expect(results).toHaveIssue({ ruleId: 'no-console', line: 3 })
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
test('TSX is linted', async () => {
|
|
24
|
-
const ignored = await eslint.isPathIgnored('./fixtures/some.tsx')
|
|
25
|
-
expect(ignored).toBe(false)
|
|
26
|
-
|
|
27
|
-
const results = await lintFile('fixtures/some.tsx')
|
|
28
|
-
expect(results).toHaveIssue({ruleId: 'jsdoc/check-tag-names', line: 5})
|
|
29
|
-
expect(results).toHaveIssue({ruleId: '@typescript-eslint/no-unused-vars', line: 7})
|
|
30
|
-
expect(results).toHaveIssueCount(2)
|
|
31
|
-
})
|
package/tests/eslint.d.ts
DELETED
package/tests/fixtures/some.tsx
DELETED
package/tests/setup-jest.ts
DELETED
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import { ESLint, Linter } from "eslint"
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Add some custom matchers for ESLint to jest
|
|
5
|
-
*/
|
|
6
|
-
expect.extend({
|
|
7
|
-
toPass: assertLintingPassed,
|
|
8
|
-
toHaveIssueCount: assertHavingNIssues,
|
|
9
|
-
toHaveIssue: assertHavingIssue
|
|
10
|
-
})
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Check if linting a file did not throw any errors or warnings
|
|
14
|
-
*
|
|
15
|
-
* @param received Lint result
|
|
16
|
-
*/
|
|
17
|
-
function hasNoIssues(received: ESLint.LintResult) {
|
|
18
|
-
// dirty type check
|
|
19
|
-
if (received?.errorCount === undefined) throw new Error('Expected ESLintResult')
|
|
20
|
-
|
|
21
|
-
return received.errorCount === 0 && received.warningCount === 0
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Check if linting of multiple fils
|
|
26
|
-
*
|
|
27
|
-
* @param received
|
|
28
|
-
* @returns {}
|
|
29
|
-
*/
|
|
30
|
-
function assertLintingPassed(received: ESLint.LintResult | ESLint.LintResult[]) {
|
|
31
|
-
// allow single ESLintResult
|
|
32
|
-
if (!Array.isArray(received)) {
|
|
33
|
-
received = [received]
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const errors = [] as {file: string, errors: Linter.LintMessage[]}[]
|
|
37
|
-
const pass = received.every((result) => {
|
|
38
|
-
// save issues
|
|
39
|
-
errors.push({file: result.filePath, errors: result.messages})
|
|
40
|
-
return hasNoIssues(result)
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
return {
|
|
44
|
-
pass,
|
|
45
|
-
message: () => {
|
|
46
|
-
if (pass) {
|
|
47
|
-
return 'Expected file to not pass eslint, but got no issues'
|
|
48
|
-
} else {
|
|
49
|
-
const errorMessages = errors.map((m) =>
|
|
50
|
-
`file: ${m.file}\n` + m.errors.map((e) => 'line: ' + e.line + ': ' + (e.ruleId || e.message))
|
|
51
|
-
)
|
|
52
|
-
return 'Expected file to pass eslint, got issues:\n' + errorMessages.join('\n')
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Count the total amount of issues
|
|
60
|
-
*
|
|
61
|
-
* @param received lint result
|
|
62
|
-
* @returns total amount of issues
|
|
63
|
-
*/
|
|
64
|
-
function countIssues(received: ESLint.LintResult) {
|
|
65
|
-
return received.errorCount + received.warningCount
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Check if exactly the same number of issues is reported
|
|
70
|
-
*
|
|
71
|
-
* @param received the lint result
|
|
72
|
-
* @param expected number of expected issues
|
|
73
|
-
* @returns jest matcher result
|
|
74
|
-
*/
|
|
75
|
-
function assertHavingNIssues(received: ESLint.LintResult | ESLint.LintResult[], expected: number) {
|
|
76
|
-
if (!(typeof expected === 'number')) throw new Error('Expected a number as expected value')
|
|
77
|
-
|
|
78
|
-
if (!Array.isArray(received)) {
|
|
79
|
-
received = [received]
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const issues = received.map(countIssues).reduce((p, c) => p + c)
|
|
83
|
-
const pass = issues === expected
|
|
84
|
-
|
|
85
|
-
return {
|
|
86
|
-
pass,
|
|
87
|
-
message: () => pass ? `Expected not to find exactly ${expected} issues.` : `Expected ${expected} issues, found ${issues}`
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Check if result contains the expected issue
|
|
93
|
-
*
|
|
94
|
-
* @param received the lint result
|
|
95
|
-
* @param issue the expected issue
|
|
96
|
-
* @returns jest matcher result
|
|
97
|
-
*/
|
|
98
|
-
function assertHavingIssue(received: ESLint.LintResult | ESLint.LintResult[], issue: string | {ruleId: string, line?: number}) {
|
|
99
|
-
if (!Array.isArray(received)) {
|
|
100
|
-
received = [received]
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Should not pass
|
|
104
|
-
if (assertLintingPassed(received).pass) {
|
|
105
|
-
return {
|
|
106
|
-
pass: false,
|
|
107
|
-
message: () => 'Expected issue, but no linting issues found.'
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
const name = typeof issue === 'string' ? issue : issue.ruleId
|
|
112
|
-
const result = received.some((result) => {
|
|
113
|
-
return result.messages.some((message) => {
|
|
114
|
-
// ensure name matches
|
|
115
|
-
if (message.ruleId !== name) return false
|
|
116
|
-
// if line is requested ignore not matching ones
|
|
117
|
-
if (typeof issue === 'object' && issue.line !== undefined && issue.line !== message.line) return false
|
|
118
|
-
// otherwise matched
|
|
119
|
-
return true
|
|
120
|
-
})
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
const onLine = typeof issue === 'string' ? '' : ` on line ${issue.line}`
|
|
124
|
-
return {
|
|
125
|
-
pass: result,
|
|
126
|
-
message: () => result ? `Unexpected error '${name}'${onLine} found.` : `Expected error '${name}'${onLine} not found.`
|
|
127
|
-
}
|
|
128
|
-
}
|