eslint-plugin-svelte 3.8.0 → 3.8.2
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/lib/main.d.ts +1 -1
- package/lib/meta.d.ts +1 -1
- package/lib/meta.js +1 -1
- package/lib/rules/consistent-selector-style.js +13 -6
- package/lib/rules/no-top-level-browser-globals.js +20 -1
- package/lib/utils/element-occurences.d.ts +7 -0
- package/lib/utils/element-occurences.js +43 -0
- package/package.json +1 -1
package/lib/main.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ export declare const configs: {
|
|
|
14
14
|
export declare const rules: Record<string, Rule.RuleModule>;
|
|
15
15
|
export declare const meta: {
|
|
16
16
|
name: "eslint-plugin-svelte";
|
|
17
|
-
version: "3.8.
|
|
17
|
+
version: "3.8.2";
|
|
18
18
|
};
|
|
19
19
|
export declare const processors: {
|
|
20
20
|
'.svelte': typeof processor;
|
package/lib/meta.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export declare const name: "eslint-plugin-svelte";
|
|
2
|
-
export declare const version: "3.8.
|
|
2
|
+
export declare const version: "3.8.2";
|
package/lib/meta.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { findClassesInAttribute } from '../utils/ast-utils.js';
|
|
2
2
|
import { extractExpressionPrefixLiteral, extractExpressionSuffixLiteral } from '../utils/expression-affixes.js';
|
|
3
3
|
import { createRule } from '../utils/index.js';
|
|
4
|
+
import { ElementOccurenceCount, elementOccurrenceCount } from '../utils/element-occurences.js';
|
|
4
5
|
export default createRule('consistent-selector-style', {
|
|
5
6
|
meta: {
|
|
6
7
|
docs: {
|
|
@@ -108,7 +109,7 @@ export default createRule('consistent-selector-style', {
|
|
|
108
109
|
if (styleValue === 'class') {
|
|
109
110
|
return;
|
|
110
111
|
}
|
|
111
|
-
if (styleValue === 'id' && canUseIdSelector(selection)) {
|
|
112
|
+
if (styleValue === 'id' && canUseIdSelector(selection.map(([elem]) => elem))) {
|
|
112
113
|
context.report({
|
|
113
114
|
messageId: 'classShouldBeId',
|
|
114
115
|
loc: styleSelectorNodeLoc(node)
|
|
@@ -243,10 +244,10 @@ function addToArrayMap(map, key, value) {
|
|
|
243
244
|
* Finds all nodes in selections that could be matched by key
|
|
244
245
|
*/
|
|
245
246
|
function matchSelection(selections, key) {
|
|
246
|
-
const selection = selections.exact.get(key) ?? [];
|
|
247
|
+
const selection = (selections.exact.get(key) ?? []).map((elem) => [elem, true]);
|
|
247
248
|
selections.affixes.forEach((nodes, [prefix, suffix]) => {
|
|
248
249
|
if ((prefix === null || key.startsWith(prefix)) && (suffix === null || key.endsWith(suffix))) {
|
|
249
|
-
selection.push(...nodes);
|
|
250
|
+
selection.push(...nodes.map((elem) => [elem, false]));
|
|
250
251
|
}
|
|
251
252
|
});
|
|
252
253
|
return selection;
|
|
@@ -255,22 +256,28 @@ function matchSelection(selections, key) {
|
|
|
255
256
|
* Checks whether a given selection could be obtained using an ID selector
|
|
256
257
|
*/
|
|
257
258
|
function canUseIdSelector(selection) {
|
|
258
|
-
return selection.length
|
|
259
|
+
return (selection.length === 0 ||
|
|
260
|
+
(selection.length === 1 &&
|
|
261
|
+
elementOccurrenceCount(selection[0]) !== ElementOccurenceCount.ZeroToInf));
|
|
259
262
|
}
|
|
260
263
|
/**
|
|
261
264
|
* Checks whether a given selection could be obtained using a type selector
|
|
262
265
|
*/
|
|
263
266
|
function canUseTypeSelector(selection, typeSelections) {
|
|
264
|
-
const types = new Set(selection.map((node) => node.name.name));
|
|
267
|
+
const types = new Set(selection.map(([node]) => node.name.name));
|
|
265
268
|
if (types.size > 1) {
|
|
266
269
|
return false;
|
|
267
270
|
}
|
|
268
271
|
if (types.size < 1) {
|
|
269
272
|
return true;
|
|
270
273
|
}
|
|
274
|
+
if (selection.some(([elem, exact]) => !exact && elementOccurrenceCount(elem) === ElementOccurenceCount.ZeroToInf)) {
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
271
277
|
const type = [...types][0];
|
|
272
278
|
const typeSelection = typeSelections.get(type);
|
|
273
|
-
return typeSelection !== undefined &&
|
|
279
|
+
return (typeSelection !== undefined &&
|
|
280
|
+
arrayEquals(typeSelection, selection.map(([elem]) => elem)));
|
|
274
281
|
}
|
|
275
282
|
/**
|
|
276
283
|
* Compares two arrays for item equality
|
|
@@ -25,11 +25,17 @@ export default createRule('no-top-level-browser-globals', {
|
|
|
25
25
|
});
|
|
26
26
|
const maybeGuards = [];
|
|
27
27
|
const functions = [];
|
|
28
|
+
const typeAnnotations = [];
|
|
28
29
|
function enterFunction(node) {
|
|
29
30
|
if (isTopLevelLocation(node)) {
|
|
30
31
|
functions.push(node);
|
|
31
32
|
}
|
|
32
33
|
}
|
|
34
|
+
function enterTypeAnnotation(node) {
|
|
35
|
+
if (!isInTypeAnnotation(node)) {
|
|
36
|
+
typeAnnotations.push(node);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
33
39
|
function enterMetaProperty(node) {
|
|
34
40
|
if (node.meta.name !== 'import' || node.property.name !== 'meta')
|
|
35
41
|
return;
|
|
@@ -69,7 +75,7 @@ export default createRule('no-top-level-browser-globals', {
|
|
|
69
75
|
const reportCandidates = [];
|
|
70
76
|
// Collects references to global variables.
|
|
71
77
|
for (const ref of iterateBrowserGlobalReferences()) {
|
|
72
|
-
if (!isTopLevelLocation(ref.node))
|
|
78
|
+
if (!isTopLevelLocation(ref.node) || isInTypeAnnotation(ref.node))
|
|
73
79
|
continue;
|
|
74
80
|
const guardChecker = getGuardCheckerFromReference(ref.node);
|
|
75
81
|
if (guardChecker) {
|
|
@@ -98,6 +104,7 @@ export default createRule('no-top-level-browser-globals', {
|
|
|
98
104
|
}
|
|
99
105
|
return {
|
|
100
106
|
':function': enterFunction,
|
|
107
|
+
'*.typeAnnotation': enterTypeAnnotation,
|
|
101
108
|
MetaProperty: enterMetaProperty,
|
|
102
109
|
'Program:exit': verifyGlobalReferences
|
|
103
110
|
};
|
|
@@ -127,6 +134,18 @@ export default createRule('no-top-level-browser-globals', {
|
|
|
127
134
|
}
|
|
128
135
|
return true;
|
|
129
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* Checks whether the node is in type annotation.
|
|
139
|
+
* @returns `true` if the node is in type annotation.
|
|
140
|
+
*/
|
|
141
|
+
function isInTypeAnnotation(node) {
|
|
142
|
+
for (const typeAnnotation of typeAnnotations) {
|
|
143
|
+
if (typeAnnotation.range[0] <= node.range[0] && node.range[1] <= typeAnnotation.range[1]) {
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
130
149
|
/**
|
|
131
150
|
* Iterate over the references of modules that can check the browser environment.
|
|
132
151
|
*/
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export var ElementOccurenceCount;
|
|
2
|
+
(function (ElementOccurenceCount) {
|
|
3
|
+
ElementOccurenceCount[ElementOccurenceCount["ZeroOrOne"] = 0] = "ZeroOrOne";
|
|
4
|
+
ElementOccurenceCount[ElementOccurenceCount["One"] = 1] = "One";
|
|
5
|
+
ElementOccurenceCount[ElementOccurenceCount["ZeroToInf"] = 2] = "ZeroToInf";
|
|
6
|
+
})(ElementOccurenceCount || (ElementOccurenceCount = {}));
|
|
7
|
+
function multiplyCounts(left, right) {
|
|
8
|
+
if (left === ElementOccurenceCount.One) {
|
|
9
|
+
return right;
|
|
10
|
+
}
|
|
11
|
+
if (right === ElementOccurenceCount.One) {
|
|
12
|
+
return left;
|
|
13
|
+
}
|
|
14
|
+
if (left === right) {
|
|
15
|
+
return left;
|
|
16
|
+
}
|
|
17
|
+
return ElementOccurenceCount.ZeroToInf;
|
|
18
|
+
}
|
|
19
|
+
function childElementOccurenceCount(parent) {
|
|
20
|
+
if (parent === null) {
|
|
21
|
+
return ElementOccurenceCount.One;
|
|
22
|
+
}
|
|
23
|
+
if ([
|
|
24
|
+
'SvelteIfBlock',
|
|
25
|
+
'SvelteElseBlock',
|
|
26
|
+
'SvelteAwaitBlock',
|
|
27
|
+
'SvelteAwaitPendingBlock',
|
|
28
|
+
'SvelteAwaitThenBlock',
|
|
29
|
+
'SvelteAwaitCatchBlock'
|
|
30
|
+
].includes(parent.type)) {
|
|
31
|
+
return ElementOccurenceCount.ZeroOrOne;
|
|
32
|
+
}
|
|
33
|
+
if (['SvelteEachBlock', 'SvelteSnippetBlock'].includes(parent.type) ||
|
|
34
|
+
(parent.type === 'SvelteElement' && parent.kind === 'component')) {
|
|
35
|
+
return ElementOccurenceCount.ZeroToInf;
|
|
36
|
+
}
|
|
37
|
+
return ElementOccurenceCount.One;
|
|
38
|
+
}
|
|
39
|
+
export function elementOccurrenceCount(element) {
|
|
40
|
+
const parentCount = element.parent !== null ? elementOccurrenceCount(element.parent) : ElementOccurenceCount.One;
|
|
41
|
+
const parentChildCount = childElementOccurenceCount(element.parent);
|
|
42
|
+
return multiplyCounts(parentCount, parentChildCount);
|
|
43
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-svelte",
|
|
3
|
-
"version": "3.8.
|
|
3
|
+
"version": "3.8.2",
|
|
4
4
|
"description": "ESLint plugin for Svelte using AST",
|
|
5
5
|
"repository": "git+https://github.com/sveltejs/eslint-plugin-svelte.git",
|
|
6
6
|
"homepage": "https://sveltejs.github.io/eslint-plugin-svelte",
|