lint-rules-alvin 1.1.3 → 1.2.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/eslint/configs/custom.js +7 -4
- package/eslint/configs/index.d.ts +1 -0
- package/eslint/configs/index.js +1 -0
- package/eslint/configs/sveltekit.js +209 -0
- package/eslint/custom_rules/jsx-multiline-prop-newline.js +162 -71
- package/eslint/presets/index.d.ts +4 -7
- package/eslint/presets/index.js +2 -2
- package/eslint/presets/sveltekitTs.js +25 -0
- package/package.json +15 -1
- package/eslint/custom_rules/jsx-no-single-object-curly-newline.js +0 -120
- package/eslint/presets/astroReact.js +0 -34
package/eslint/configs/custom.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { newlineBetweenImportsRule } from '../custom_rules/newline-between-imports.js';
|
|
2
2
|
import { unnamedImportsLastRule } from '../custom_rules/unnamed-imports-last.js';
|
|
3
3
|
import { jsxMultilinePropNewlineRule } from '../custom_rules/jsx-multiline-prop-newline.js';
|
|
4
|
-
import { jsxNoSingleObjectCurlyNewlineRule } from '../custom_rules/jsx-no-single-object-curly-newline.js';
|
|
5
4
|
import { maxChainPerLineRule } from '../custom_rules/max-chain-per-line.js';
|
|
6
5
|
import { multilineParenNewlineRule } from '../custom_rules/multiline-paren-newline.js';
|
|
7
6
|
import { multilineArrayAccessorNewlineRule } from '../custom_rules/multiline-array-accessor-newline.js';
|
|
@@ -19,7 +18,6 @@ export const custom = {
|
|
|
19
18
|
'newline-between-imports': newlineBetweenImportsRule,
|
|
20
19
|
'unnamed-imports-last': unnamedImportsLastRule,
|
|
21
20
|
'jsx-multiline-prop-newline': jsxMultilinePropNewlineRule,
|
|
22
|
-
'jsx-no-single-object-curly-newline': jsxNoSingleObjectCurlyNewlineRule,
|
|
23
21
|
'max-chain-per-line': maxChainPerLineRule,
|
|
24
22
|
'multiline-paren-newline': multilineParenNewlineRule,
|
|
25
23
|
'multiline-array-accessor-newline': multilineArrayAccessorNewlineRule,
|
|
@@ -33,8 +31,13 @@ export const custom = {
|
|
|
33
31
|
{ minItems: 2 }
|
|
34
32
|
],
|
|
35
33
|
'custom/unnamed-imports-last': 'error',
|
|
36
|
-
'custom/jsx-multiline-prop-newline':
|
|
37
|
-
|
|
34
|
+
'custom/jsx-multiline-prop-newline': [
|
|
35
|
+
'error',
|
|
36
|
+
{
|
|
37
|
+
enforceSingleLine: true,
|
|
38
|
+
allowSingleExpression: true
|
|
39
|
+
}
|
|
40
|
+
],
|
|
38
41
|
'custom/max-chain-per-line': [
|
|
39
42
|
'error',
|
|
40
43
|
{
|
|
@@ -9,4 +9,5 @@ export declare const json: Linter.Config[];
|
|
|
9
9
|
export declare const markdown: Linter.Config;
|
|
10
10
|
export declare const reactHooks: Linter.Config;
|
|
11
11
|
export declare const stylistic: Linter.Config;
|
|
12
|
+
export declare const sveltekit: Linter.Config[];
|
|
12
13
|
export declare const typescript: Linter.Config;
|
package/eslint/configs/index.js
CHANGED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import eslintPluginSvelte from 'eslint-plugin-svelte';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The ESLint `stylistic` config. Extends `configs.recommended` and overrides all rules.
|
|
5
|
+
*
|
|
6
|
+
* @type {import('eslint').Linter.Config[]}
|
|
7
|
+
*/
|
|
8
|
+
export const sveltekit = [
|
|
9
|
+
...eslintPluginSvelte.configs['flat/base'],
|
|
10
|
+
{
|
|
11
|
+
files: [
|
|
12
|
+
'**/*.svelte',
|
|
13
|
+
'**/*.svelte.ts',
|
|
14
|
+
'**/*.svelte.js'
|
|
15
|
+
],
|
|
16
|
+
rules: {
|
|
17
|
+
|
|
18
|
+
// Svelte-specific
|
|
19
|
+
'svelte/infinite-reactive-loop': 'warn',
|
|
20
|
+
'svelte/no-dom-manupulating': 'warn',
|
|
21
|
+
'svelte/no-dupe-else-if-blocks': 'error',
|
|
22
|
+
'svelte/no-dupe-else-on-directives': 'error',
|
|
23
|
+
'svelte/no-dupe-style-properties': 'error',
|
|
24
|
+
'svelte/no-dupe-use-directives': 'error',
|
|
25
|
+
'svelte/no-not-function-handler': 'error',
|
|
26
|
+
'svelte/no-object-in-text-mustaches': 'error',
|
|
27
|
+
'svelte/no-raw-special-elements': 'error',
|
|
28
|
+
'svelte/no-reactive-reassign': 'error',
|
|
29
|
+
'svelte/no-shorthand-style-property-overrides': 'warn',
|
|
30
|
+
'svelte/no-store-async': 'error',
|
|
31
|
+
'svelte/no-top-level-browser-globals': 'error',
|
|
32
|
+
'svelte/no-unknown-style-directive-property': 'error',
|
|
33
|
+
'svelte/prefer-svelte-reactivity': 'error',
|
|
34
|
+
'svelte/require-store-callbacks-use-set-param': 'error',
|
|
35
|
+
'svelte/require-store-reactive-access': 'error',
|
|
36
|
+
'svelte/valid-compile': 'off',
|
|
37
|
+
'svelte/valid-style-parse': 'error',
|
|
38
|
+
|
|
39
|
+
// Security
|
|
40
|
+
'svelte/no-at-html-tags': 'warn',
|
|
41
|
+
'svelte/no-target-blank': 'error',
|
|
42
|
+
|
|
43
|
+
// Best practices
|
|
44
|
+
'svelte/block-lang': [
|
|
45
|
+
'error',
|
|
46
|
+
{
|
|
47
|
+
enforceScriptPresent: false,
|
|
48
|
+
enforceStylePresent: false,
|
|
49
|
+
script: [
|
|
50
|
+
'ts',
|
|
51
|
+
'js'
|
|
52
|
+
]
|
|
53
|
+
}
|
|
54
|
+
],
|
|
55
|
+
'svelte/button-has-type': 'off',
|
|
56
|
+
'svelte/no-add-event-listener': 'error',
|
|
57
|
+
'svelte/no-at-debug-tags': 'warn',
|
|
58
|
+
'svelte/no-ignored-unsubscribe': 'warn',
|
|
59
|
+
'svelte/no-immutable-reactive-statements': 'error',
|
|
60
|
+
'svelte/no-inline-styles': 'error',
|
|
61
|
+
'svelte/no-inspect': 'warn',
|
|
62
|
+
'svelte/no-reactive-functions': 'error',
|
|
63
|
+
'svelte/no-reactive-literals': 'error',
|
|
64
|
+
'svelte/no-svelte-internal': 'error',
|
|
65
|
+
'svelte/no-unnecessary-state-wrap': 'error',
|
|
66
|
+
'svelte/no-unused-class-name': 'error',
|
|
67
|
+
'svelte/no-unused-props': 'error',
|
|
68
|
+
'svelte/no-unused-svelte-ignore': 'error',
|
|
69
|
+
'svelte/no-useless-children-snippet': 'error',
|
|
70
|
+
'svelte/no-useless-mustaches': 'error',
|
|
71
|
+
'prefer-const': 'off',
|
|
72
|
+
'svelte/prefer-const': 'error',
|
|
73
|
+
'svelte/prefer-destructed-store-props': 'error',
|
|
74
|
+
'svelte/prefer-writable-derived': 'error',
|
|
75
|
+
'svelte/require-each-key': 'error',
|
|
76
|
+
'svelte/require-event-dispatcher-types': 'error',
|
|
77
|
+
'svelte/require-optimized-style-attribute': 'error',
|
|
78
|
+
'svelte/require-store-init': 'error',
|
|
79
|
+
'svelte/valid-each-key': 'error',
|
|
80
|
+
|
|
81
|
+
// Stylistic
|
|
82
|
+
'svelte/consistent-selector-style': 'off',
|
|
83
|
+
'svelte/derived-has-same-inputs-outputs': 'error',
|
|
84
|
+
'svelte/first-attribute-linebreak': [
|
|
85
|
+
'error',
|
|
86
|
+
{
|
|
87
|
+
singleline: 'beside',
|
|
88
|
+
multiline: 'below'
|
|
89
|
+
}
|
|
90
|
+
],
|
|
91
|
+
'svelte/html-closing-bracket-new-line': [
|
|
92
|
+
'error',
|
|
93
|
+
{
|
|
94
|
+
singleline: 'never',
|
|
95
|
+
multiline: 'always',
|
|
96
|
+
selfClosingTag: {
|
|
97
|
+
singleline: 'never',
|
|
98
|
+
multiline: 'always'
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
],
|
|
102
|
+
'svelte/html-closing-bracket-spacing': [
|
|
103
|
+
'error',
|
|
104
|
+
{
|
|
105
|
+
startTag: 'never',
|
|
106
|
+
endTag: 'never',
|
|
107
|
+
selfClosingTag: 'always'
|
|
108
|
+
}
|
|
109
|
+
],
|
|
110
|
+
'svelte/html-quotes': [
|
|
111
|
+
'error',
|
|
112
|
+
{
|
|
113
|
+
prefer: 'double',
|
|
114
|
+
dynamic: {
|
|
115
|
+
quoted: false,
|
|
116
|
+
avoidInvalidUnquotedInHTML: false
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
],
|
|
120
|
+
'svelte/html-self-closing': [
|
|
121
|
+
'error',
|
|
122
|
+
'default'
|
|
123
|
+
],
|
|
124
|
+
'indent': 'off', // eslint-disable-line @stylistic/quote-props
|
|
125
|
+
'@stylistic/indent': 'off',
|
|
126
|
+
'svelte/indent': [
|
|
127
|
+
'error',
|
|
128
|
+
{
|
|
129
|
+
indent: 'tab',
|
|
130
|
+
switchCase: 1,
|
|
131
|
+
alignAttributesVertically: false
|
|
132
|
+
}
|
|
133
|
+
],
|
|
134
|
+
'svelte/max-attributes-per-line': [
|
|
135
|
+
'error',
|
|
136
|
+
{
|
|
137
|
+
singleline: 1,
|
|
138
|
+
multiline: 1
|
|
139
|
+
}
|
|
140
|
+
],
|
|
141
|
+
'svelte/mustache-spacing': [
|
|
142
|
+
'error',
|
|
143
|
+
{
|
|
144
|
+
textExpressions: 'never',
|
|
145
|
+
attributesAndProps: 'never',
|
|
146
|
+
directiveExpressions: 'never',
|
|
147
|
+
tags: {
|
|
148
|
+
openingBrace: 'never',
|
|
149
|
+
closingBrace: 'never'
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
],
|
|
153
|
+
'svelte/no-extra-reactive-curlies': 'error',
|
|
154
|
+
'svelte/no-restricted-html-elements': 'off', // Allow the user to override
|
|
155
|
+
'svelte/no-spaces-around-equal-signs-in-attribute': 'error',
|
|
156
|
+
'svelte/prefer-class-directive': 'error',
|
|
157
|
+
'svelte/prefer-style-directive': 'error',
|
|
158
|
+
'svelte/require-event-prefix': 'off',
|
|
159
|
+
'svelte/shorthand-attribute': [
|
|
160
|
+
'error',
|
|
161
|
+
{ prefer: 'always' }
|
|
162
|
+
],
|
|
163
|
+
'svelte/shorthand-directive': [
|
|
164
|
+
'off',
|
|
165
|
+
{ prefer: 'never' }
|
|
166
|
+
],
|
|
167
|
+
'svelte/sort-attributes': 'error',
|
|
168
|
+
'svelte/spaced-html-comment': [
|
|
169
|
+
'error',
|
|
170
|
+
'always'
|
|
171
|
+
],
|
|
172
|
+
|
|
173
|
+
// Extensions
|
|
174
|
+
'svelte/no-inner-declarations': [
|
|
175
|
+
'error',
|
|
176
|
+
'functions',
|
|
177
|
+
{ blockScopedFunctions: 'allow' }
|
|
178
|
+
],
|
|
179
|
+
'no-trailing-spaces': 'off',
|
|
180
|
+
'svelte/no-trailing-spaces': [
|
|
181
|
+
'error',
|
|
182
|
+
{
|
|
183
|
+
skipBlankLines: false,
|
|
184
|
+
ignoreComments: false
|
|
185
|
+
}
|
|
186
|
+
],
|
|
187
|
+
|
|
188
|
+
// SvelteKit
|
|
189
|
+
'svelte/no-export-load-in-svelte-module-in-kit-pages': 'error',
|
|
190
|
+
'svelte/no-navigation-without-resolve': [
|
|
191
|
+
'error',
|
|
192
|
+
{
|
|
193
|
+
ignoreGoto: false,
|
|
194
|
+
ignoreLinks: false,
|
|
195
|
+
ignorePushState: false,
|
|
196
|
+
ignoreReplaceState: false
|
|
197
|
+
}
|
|
198
|
+
],
|
|
199
|
+
'svelte/valid-prop-names-in-kit-pages': 'error',
|
|
200
|
+
|
|
201
|
+
// System
|
|
202
|
+
'svelte/comment-directive': [
|
|
203
|
+
'error',
|
|
204
|
+
{ reportUnusedDisableDirectives: true }
|
|
205
|
+
],
|
|
206
|
+
'svelte/system': 'error' // Keep this on!
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
];
|
|
@@ -5,108 +5,199 @@ export const jsxMultilinePropNewlineRule = {
|
|
|
5
5
|
meta: {
|
|
6
6
|
type: 'layout',
|
|
7
7
|
docs: {
|
|
8
|
-
description: 'Enforces
|
|
8
|
+
description: 'Enforces newline consistency for JSX properties.',
|
|
9
9
|
category: 'Stylistic Issues',
|
|
10
10
|
recommended: false
|
|
11
11
|
},
|
|
12
12
|
fixable: 'code',
|
|
13
|
-
schema: [
|
|
14
|
-
|
|
13
|
+
schema: [
|
|
14
|
+
{
|
|
15
|
+
type: 'object',
|
|
16
|
+
properties: {
|
|
17
|
+
enforceSingleLine: {
|
|
18
|
+
type: 'boolean',
|
|
19
|
+
default: false
|
|
20
|
+
},
|
|
21
|
+
allowSingleExpression: {
|
|
22
|
+
type: 'boolean',
|
|
23
|
+
default: true
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
additionalProperties: false
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
messages: {
|
|
30
|
+
collapse: 'This expression should not be surrounded by newlines.',
|
|
31
|
+
expand: 'This multiline expression should be surrounded by newlines.'
|
|
32
|
+
}
|
|
15
33
|
},
|
|
16
|
-
|
|
17
34
|
create(context) {
|
|
18
35
|
|
|
36
|
+
const {
|
|
37
|
+
allowSingleExpression = true,
|
|
38
|
+
enforceSingleLine = false
|
|
39
|
+
} = context.options[0] || {};
|
|
19
40
|
const sourceCode = context.sourceCode;
|
|
20
41
|
|
|
21
|
-
function isMultiline(node) {
|
|
22
|
-
|
|
23
|
-
return node && node.loc && node
|
|
24
|
-
.loc
|
|
25
|
-
.start
|
|
26
|
-
.line < node
|
|
27
|
-
.loc
|
|
28
|
-
.end
|
|
29
|
-
.line;
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
|
|
33
42
|
return {
|
|
34
|
-
|
|
43
|
+
JSXExpressionContainer(node) {
|
|
35
44
|
|
|
36
|
-
if (node.
|
|
45
|
+
if (node.parent.type !== 'JSXAttribute' || node.expression.type === 'JSXEmptyExpression') {
|
|
37
46
|
|
|
38
47
|
return;
|
|
39
48
|
|
|
40
49
|
}
|
|
41
50
|
|
|
42
|
-
const
|
|
43
|
-
|
|
51
|
+
const openingBrace = sourceCode.getFirstToken(node);
|
|
52
|
+
const closingBrace = sourceCode.getLastToken(node);
|
|
53
|
+
const expression = node.expression;
|
|
54
|
+
|
|
55
|
+
const expressionIsMultiline = expression
|
|
56
|
+
.loc
|
|
57
|
+
.start
|
|
58
|
+
.line !== expression
|
|
59
|
+
.loc
|
|
60
|
+
.end
|
|
61
|
+
.line;
|
|
62
|
+
|
|
63
|
+
const hasNewlineAfter = openingBrace
|
|
64
|
+
.loc
|
|
65
|
+
.end
|
|
66
|
+
.line !== expression
|
|
67
|
+
.loc
|
|
68
|
+
.start
|
|
69
|
+
.line;
|
|
70
|
+
const hasNewlineBefore = expression
|
|
71
|
+
.loc
|
|
72
|
+
.end
|
|
73
|
+
.line !== closingBrace
|
|
74
|
+
.loc
|
|
75
|
+
.start
|
|
76
|
+
.line;
|
|
77
|
+
|
|
78
|
+
if (expressionIsMultiline) {
|
|
79
|
+
|
|
80
|
+
const isSingleObjectOrArray = expression.type === 'ObjectExpression' || expression.type === 'ArrayExpression';
|
|
81
|
+
|
|
82
|
+
if (allowSingleExpression && isSingleObjectOrArray) {
|
|
83
|
+
|
|
84
|
+
// Collapse newlines for single multiline Object/Array
|
|
85
|
+
if (hasNewlineAfter || hasNewlineBefore) {
|
|
86
|
+
|
|
87
|
+
context.report({
|
|
88
|
+
node,
|
|
89
|
+
messageId: 'collapse',
|
|
90
|
+
fix(fixer) {
|
|
91
|
+
|
|
92
|
+
const fixes = [];
|
|
93
|
+
if (hasNewlineAfter) {
|
|
94
|
+
|
|
95
|
+
fixes.push(
|
|
96
|
+
fixer.removeRange([
|
|
97
|
+
openingBrace.range[1],
|
|
98
|
+
expression.range[0]
|
|
99
|
+
])
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
}
|
|
103
|
+
if (hasNewlineBefore) {
|
|
104
|
+
|
|
105
|
+
fixes.push(
|
|
106
|
+
fixer.removeRange([
|
|
107
|
+
expression.range[1],
|
|
108
|
+
closingBrace.range[0]
|
|
109
|
+
])
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
}
|
|
113
|
+
return fixes;
|
|
114
|
+
|
|
115
|
+
}
|
|
116
|
+
});
|
|
44
117
|
|
|
45
|
-
|
|
46
|
-
if (attr.type === 'JSXAttribute') {
|
|
118
|
+
}
|
|
47
119
|
|
|
48
|
-
|
|
120
|
+
} else {
|
|
49
121
|
|
|
50
|
-
|
|
122
|
+
// Enforce newlines for other multiline expressions
|
|
123
|
+
if (!hasNewlineAfter || !hasNewlineBefore) {
|
|
124
|
+
|
|
125
|
+
context.report({
|
|
126
|
+
node,
|
|
127
|
+
messageId: 'expand',
|
|
128
|
+
fix(fixer) {
|
|
129
|
+
|
|
130
|
+
const fixes = [];
|
|
131
|
+
if (!hasNewlineAfter) {
|
|
132
|
+
|
|
133
|
+
fixes.push(
|
|
134
|
+
fixer.insertTextAfter(
|
|
135
|
+
openingBrace,
|
|
136
|
+
'\n'
|
|
137
|
+
)
|
|
138
|
+
);
|
|
51
139
|
|
|
52
|
-
|
|
53
|
-
|
|
140
|
+
}
|
|
141
|
+
if (!hasNewlineBefore) {
|
|
54
142
|
|
|
55
|
-
|
|
143
|
+
fixes.push(
|
|
144
|
+
fixer.insertTextBefore(
|
|
145
|
+
closingBrace,
|
|
146
|
+
'\n'
|
|
147
|
+
)
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
}
|
|
151
|
+
return fixes;
|
|
152
|
+
|
|
153
|
+
}
|
|
154
|
+
});
|
|
56
155
|
|
|
57
156
|
}
|
|
58
|
-
return false;
|
|
59
157
|
|
|
60
158
|
}
|
|
61
|
-
);
|
|
62
159
|
|
|
63
|
-
|
|
160
|
+
} else { // Single-line expression
|
|
64
161
|
|
|
65
|
-
|
|
162
|
+
if (enforceSingleLine) {
|
|
66
163
|
|
|
67
|
-
|
|
164
|
+
// Collapse newlines
|
|
165
|
+
if (hasNewlineAfter || hasNewlineBefore) {
|
|
166
|
+
|
|
167
|
+
context.report({
|
|
168
|
+
node,
|
|
169
|
+
messageId: 'collapse',
|
|
170
|
+
fix(fixer) {
|
|
171
|
+
|
|
172
|
+
const fixes = [];
|
|
173
|
+
if (hasNewlineAfter) {
|
|
68
174
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
.loc
|
|
92
|
-
.start
|
|
93
|
-
.line - 1
|
|
94
|
-
];
|
|
95
|
-
const baseIndentMatch = line.match(/^\s*/);
|
|
96
|
-
const baseIndent = baseIndentMatch
|
|
97
|
-
? baseIndentMatch[0]
|
|
98
|
-
: '';
|
|
99
|
-
|
|
100
|
-
// Assume an indent of 2 spaces, a common practice.
|
|
101
|
-
const indent = baseIndent + ' ';
|
|
102
|
-
|
|
103
|
-
return fixer.insertTextBefore(
|
|
104
|
-
firstProp,
|
|
105
|
-
`\n${indent}`
|
|
106
|
-
);
|
|
175
|
+
fixes.push(
|
|
176
|
+
fixer.removeRange([
|
|
177
|
+
openingBrace.range[1],
|
|
178
|
+
expression.range[0]
|
|
179
|
+
])
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
}
|
|
183
|
+
if (hasNewlineBefore) {
|
|
184
|
+
|
|
185
|
+
fixes.push(
|
|
186
|
+
fixer.removeRange([
|
|
187
|
+
expression.range[1],
|
|
188
|
+
closingBrace.range[0]
|
|
189
|
+
])
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
}
|
|
193
|
+
return fixes;
|
|
194
|
+
|
|
195
|
+
}
|
|
196
|
+
});
|
|
107
197
|
|
|
108
198
|
}
|
|
109
|
-
|
|
199
|
+
|
|
200
|
+
}
|
|
110
201
|
|
|
111
202
|
}
|
|
112
203
|
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
import type { Linter } from 'eslint';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* ESLint preset for Astro/React with
|
|
5
|
-
*
|
|
6
|
-
* This package uses ESLint's flat config format, so the preset is an array
|
|
7
|
-
* of flat-config items.
|
|
4
|
+
* ESLint preset for Astro/React with TypeScript.
|
|
8
5
|
*/
|
|
9
|
-
export declare const
|
|
6
|
+
export declare const astroReactTs: readonly Linter.Config[];
|
|
10
7
|
|
|
11
8
|
/**
|
|
12
|
-
* ESLint preset for
|
|
9
|
+
* ESLint preset for SvelteKit with TypeScript.
|
|
13
10
|
*/
|
|
14
|
-
export declare const
|
|
11
|
+
export declare const sveltekitTs: readonly Linter.Config[];
|
package/eslint/presets/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export {
|
|
1
|
+
export { astroReactTs } from './astroReactTs.js';
|
|
2
|
+
export { sveltekitTs } from './sveltekitTs.js';
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { defineConfig } from 'eslint/config';
|
|
2
|
+
import { importX as eslintPluginImportX } from 'eslint-plugin-import-x';
|
|
3
|
+
import {
|
|
4
|
+
base,
|
|
5
|
+
importX,
|
|
6
|
+
sveltekit,
|
|
7
|
+
stylistic,
|
|
8
|
+
custom,
|
|
9
|
+
typescript
|
|
10
|
+
} from '../configs/index.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The `ESLint` PocketBase/SvelteKit config with typescript.
|
|
14
|
+
*/
|
|
15
|
+
export const sveltekitTs = defineConfig(
|
|
16
|
+
base,
|
|
17
|
+
sveltekit,
|
|
18
|
+
typescript,
|
|
19
|
+
{
|
|
20
|
+
...eslintPluginImportX.configs['flat/typescript'],
|
|
21
|
+
...importX
|
|
22
|
+
},
|
|
23
|
+
stylistic,
|
|
24
|
+
custom
|
|
25
|
+
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lint-rules-alvin",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "My own personal linting ruleset for a bunch of different plugins. Includes a few custom rules. Used in a few of my repos.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"eslint"
|
|
@@ -43,7 +43,9 @@
|
|
|
43
43
|
"eslint-plugin-jsonc": "^2.21.0",
|
|
44
44
|
"eslint-plugin-markdown": "^5.1.0",
|
|
45
45
|
"eslint-plugin-react-hooks": "^7.0.0",
|
|
46
|
+
"eslint-plugin-svelte": "^3.12.4",
|
|
46
47
|
"globals": "^16.4.0",
|
|
48
|
+
"svelte": "^5.40.2",
|
|
47
49
|
"typescript": "^5.9.3",
|
|
48
50
|
"typescript-eslint": "^8.46.1"
|
|
49
51
|
},
|
|
@@ -59,6 +61,9 @@
|
|
|
59
61
|
"eslint-plugin-jsonc": "^2.21.0",
|
|
60
62
|
"eslint-plugin-markdown": "^5.1.0",
|
|
61
63
|
"eslint-plugin-react-hooks": "^7.0.0",
|
|
64
|
+
"eslint-plugin-svelte": "^3.12.4",
|
|
65
|
+
"globals": "^16.4.0",
|
|
66
|
+
"svelte": "^5.40.2",
|
|
62
67
|
"typescript": "^5.9.3",
|
|
63
68
|
"typescript-eslint": "^8.46.0"
|
|
64
69
|
},
|
|
@@ -96,6 +101,15 @@
|
|
|
96
101
|
"eslint-plugin-react-hooks": {
|
|
97
102
|
"optional": true
|
|
98
103
|
},
|
|
104
|
+
"eslint-plugin-svelte": {
|
|
105
|
+
"optional": true
|
|
106
|
+
},
|
|
107
|
+
"globals": {
|
|
108
|
+
"optional": true
|
|
109
|
+
},
|
|
110
|
+
"svelte": {
|
|
111
|
+
"optional": true
|
|
112
|
+
},
|
|
99
113
|
"typescript": {
|
|
100
114
|
"optional": true
|
|
101
115
|
},
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @type {import('eslint').Rule.RuleModule}
|
|
3
|
-
*/
|
|
4
|
-
export const jsxNoSingleObjectCurlyNewlineRule = {
|
|
5
|
-
meta: {
|
|
6
|
-
type: 'layout',
|
|
7
|
-
docs: {
|
|
8
|
-
description: 'Disallows newlines inside curly braces for single object or array expressions in JSX.',
|
|
9
|
-
category: 'Stylistic Issues',
|
|
10
|
-
recommended: false
|
|
11
|
-
},
|
|
12
|
-
fixable: 'code',
|
|
13
|
-
schema: [],
|
|
14
|
-
messages: { error: 'Newlines around single object or array expressions in JSX curly braces are not allowed.' }
|
|
15
|
-
},
|
|
16
|
-
|
|
17
|
-
create(context) {
|
|
18
|
-
|
|
19
|
-
const sourceCode = context.sourceCode;
|
|
20
|
-
|
|
21
|
-
return {
|
|
22
|
-
JSXExpressionContainer(node) {
|
|
23
|
-
|
|
24
|
-
const expression = node.expression;
|
|
25
|
-
|
|
26
|
-
// This rule applies only to single ArrayExpressions or ObjectExpressions.
|
|
27
|
-
if (expression.type !== 'ArrayExpression' && expression.type !== 'ObjectExpression') {
|
|
28
|
-
|
|
29
|
-
return;
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// If the expression itself isn't multiline, there are no newlines to collapse.
|
|
34
|
-
if (
|
|
35
|
-
expression
|
|
36
|
-
.loc
|
|
37
|
-
.start
|
|
38
|
-
.line === expression
|
|
39
|
-
.loc
|
|
40
|
-
.end
|
|
41
|
-
.line
|
|
42
|
-
) {
|
|
43
|
-
|
|
44
|
-
return;
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const openingBrace = sourceCode.getFirstToken(node); // `{`
|
|
49
|
-
const closingBrace = sourceCode.getLastToken(node); // `}`
|
|
50
|
-
const firstTokenInExpression = sourceCode.getFirstToken(expression);
|
|
51
|
-
const lastTokenInExpression = sourceCode.getLastToken(expression);
|
|
52
|
-
|
|
53
|
-
const hasNewlineBefore = openingBrace
|
|
54
|
-
.loc
|
|
55
|
-
.end
|
|
56
|
-
.line < firstTokenInExpression
|
|
57
|
-
.loc
|
|
58
|
-
.start
|
|
59
|
-
.line;
|
|
60
|
-
const hasNewlineAfter = lastTokenInExpression
|
|
61
|
-
.loc
|
|
62
|
-
.end
|
|
63
|
-
.line < closingBrace
|
|
64
|
-
.loc
|
|
65
|
-
.start
|
|
66
|
-
.line;
|
|
67
|
-
|
|
68
|
-
if (hasNewlineBefore || hasNewlineAfter) {
|
|
69
|
-
|
|
70
|
-
context.report({
|
|
71
|
-
node,
|
|
72
|
-
messageId: 'error',
|
|
73
|
-
fix(fixer) {
|
|
74
|
-
|
|
75
|
-
const fixes = [];
|
|
76
|
-
|
|
77
|
-
if (hasNewlineBefore) {
|
|
78
|
-
|
|
79
|
-
// Range from the end of `{` to the start of the expression's first token.
|
|
80
|
-
const range = [
|
|
81
|
-
openingBrace.range[1],
|
|
82
|
-
firstTokenInExpression.range[0]
|
|
83
|
-
];
|
|
84
|
-
fixes.push(
|
|
85
|
-
fixer.replaceTextRange(
|
|
86
|
-
range,
|
|
87
|
-
''
|
|
88
|
-
)
|
|
89
|
-
);
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
if (hasNewlineAfter) {
|
|
94
|
-
|
|
95
|
-
// Range from the end of the expression's last token to the start of `}`.
|
|
96
|
-
const range = [
|
|
97
|
-
lastTokenInExpression.range[1],
|
|
98
|
-
closingBrace.range[0]
|
|
99
|
-
];
|
|
100
|
-
fixes.push(
|
|
101
|
-
fixer.replaceTextRange(
|
|
102
|
-
range,
|
|
103
|
-
''
|
|
104
|
-
)
|
|
105
|
-
);
|
|
106
|
-
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
return fixes;
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
}
|
|
120
|
-
};
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from 'eslint/config';
|
|
2
|
-
import { importX as eslintPluginImportX } from 'eslint-plugin-import-x';
|
|
3
|
-
import {
|
|
4
|
-
base,
|
|
5
|
-
astro,
|
|
6
|
-
importX,
|
|
7
|
-
reactHooks,
|
|
8
|
-
stylistic,
|
|
9
|
-
custom
|
|
10
|
-
} from '../configs/index.js';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* The `ESLint` Astro/React config with typescript.
|
|
14
|
-
*/
|
|
15
|
-
export const astroReact = defineConfig(
|
|
16
|
-
base,
|
|
17
|
-
astro,
|
|
18
|
-
{
|
|
19
|
-
...eslintPluginImportX.configs['flat/react'],
|
|
20
|
-
...importX
|
|
21
|
-
},
|
|
22
|
-
reactHooks,
|
|
23
|
-
stylistic,
|
|
24
|
-
custom,
|
|
25
|
-
{
|
|
26
|
-
name: 'eslint-plugin-astro-stylistic-override',
|
|
27
|
-
files: [ '**/*.astro' ],
|
|
28
|
-
rules: {
|
|
29
|
-
'@stylistic/jsx-one-expression-per-line': 'off',
|
|
30
|
-
'@stylistic/jsx-curly-brace-presence': 'off',
|
|
31
|
-
'import-x/unambiguous': 'off'
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
);
|