@cspell/eslint-plugin 8.8.4 → 8.9.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 +48 -0
- package/assets/options.schema.json +19 -0
- package/dist/common/options.d.cts +34 -0
- package/dist/plugin/cspell-eslint-plugin.cjs +3 -2
- package/dist/plugin/defaultCheckOptions.cjs +1 -0
- package/dist/worker/ASTNode.d.cts +2 -2
- package/dist/worker/ASTPath.d.mts +12 -0
- package/dist/worker/ASTPath.mjs +2 -0
- package/dist/worker/customScopes.d.mts +3 -0
- package/dist/worker/customScopes.mjs +13 -0
- package/dist/worker/scope.d.mts +58 -0
- package/dist/worker/scope.mjs +149 -0
- package/dist/worker/spellCheck.mjs +125 -93
- package/dist/worker/walkTree.d.mts +2 -3
- package/dist/worker/walkTree.mjs +59 -10
- package/package.json +21 -15
package/README.md
CHANGED
|
@@ -192,6 +192,7 @@ interface Options {
|
|
|
192
192
|
/** Define dictionaries. */
|
|
193
193
|
dictionaryDefinitions?: DictionaryDefinition[];
|
|
194
194
|
};
|
|
195
|
+
|
|
195
196
|
/**
|
|
196
197
|
* Specify a path to a custom word list file.
|
|
197
198
|
*
|
|
@@ -201,6 +202,35 @@ interface Options {
|
|
|
201
202
|
* ```
|
|
202
203
|
*/
|
|
203
204
|
customWordListFile?: string | { path: string };
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Scope selectors to spell check.
|
|
208
|
+
* This is a list of scope selectors to spell check.
|
|
209
|
+
*
|
|
210
|
+
* Example:
|
|
211
|
+
* ```js
|
|
212
|
+
* checkScope: [
|
|
213
|
+
* ['YAMLPair[key] YAMLScalar', true],
|
|
214
|
+
* ['YAMLPair[value] YAMLScalar', true],
|
|
215
|
+
* ['YAMLSequence[entries] YAMLScalar', true],
|
|
216
|
+
* ['JSONProperty[key] JSONLiteral', true],
|
|
217
|
+
* ['JSONProperty[value] JSONLiteral', true],
|
|
218
|
+
* ['JSONArrayExpression JSONLiteral', true],
|
|
219
|
+
* ],
|
|
220
|
+
* ```
|
|
221
|
+
*
|
|
222
|
+
* To turn off checking JSON keys, use the following:
|
|
223
|
+
*
|
|
224
|
+
* ```js
|
|
225
|
+
* checkScope: [
|
|
226
|
+
* ['JSONProperty[key] JSONLiteral', false],
|
|
227
|
+
* ],
|
|
228
|
+
* ```
|
|
229
|
+
*
|
|
230
|
+
* @since 8.9.0
|
|
231
|
+
*/
|
|
232
|
+
checkScope?: ScopeSelectorList;
|
|
233
|
+
|
|
204
234
|
/**
|
|
205
235
|
* Output debug logs
|
|
206
236
|
* @default false
|
|
@@ -294,6 +324,24 @@ When spell checking, if `colour` is not in one of the dictionaries, then `color`
|
|
|
294
324
|
|
|
295
325
|
CSpell will match case, but not word stems. `blacklist` and `Blacklist` will get replaced, but not `blacklists`.
|
|
296
326
|
|
|
327
|
+
## Checking Custom AST Nodes
|
|
328
|
+
|
|
329
|
+
The `checkScope` setting is used to enable / disable checking AST Nodes. ESLint uses parsers to generate the AST (Abstract Syntax Tree) to evaluate a document. Each PlugIn gets access to the AST. `checkScope` can be used to handle new AST nodes when a custom parser is added. Some knowledge of the AST output by the parser is necessary.
|
|
330
|
+
|
|
331
|
+
```js
|
|
332
|
+
rules: {
|
|
333
|
+
'@cspell/spellchecker': ['warn', { checkScope: [
|
|
334
|
+
['JSONLiteral': true], // will match AST Nodes of type `JSONLiteral` and spell check the value.
|
|
335
|
+
['JSONProperty[key] JSONLiteral', false] // will turn off checking the JSON Property keys.
|
|
336
|
+
['JSONProperty JSONLiteral', false] // will turn off checking the JSON Property keys and values.
|
|
337
|
+
['JSONProperty[value] JSONLiteral', true] // will turn on checking the JSON Property values.
|
|
338
|
+
['YAMLPair[key] YAMLScalar', true],
|
|
339
|
+
['YAMLPair[value] YAMLScalar', true],
|
|
340
|
+
['YAMLSequence YAMLScalar', true],
|
|
341
|
+
] }],
|
|
342
|
+
},
|
|
343
|
+
```
|
|
344
|
+
|
|
297
345
|
## In Combination with CSpell
|
|
298
346
|
|
|
299
347
|
Due to the nature of how files are parsed, the `cspell` command line tool and this ESLint plugin will give different results.
|
|
@@ -23,6 +23,25 @@
|
|
|
23
23
|
"description": "Spell check JSX Text",
|
|
24
24
|
"type": "boolean"
|
|
25
25
|
},
|
|
26
|
+
"checkScope": {
|
|
27
|
+
"description": "Scope selectors to spell check. This is a list of scope selectors to spell check.\n\nExample: ```js checkScope: [ ['YAMLPair[key] YAMLScalar', true], ['YAMLPair[value] YAMLScalar', true], ['YAMLSequence[entries] YAMLScalar', true], ['JSONProperty[key] JSONLiteral', true], ['JSONProperty[value] JSONLiteral', true], ['JSONArrayExpression JSONLiteral', true], ], ```",
|
|
28
|
+
"items": {
|
|
29
|
+
"description": "A scope selector entry is a tuple that defines a scope selector and whether to spell check it.",
|
|
30
|
+
"items": [
|
|
31
|
+
{
|
|
32
|
+
"description": "The scope selector is a string that defines the context in which a rule applies. Examples:\n- `YAMLPair[value] YAMLScalar` - check the value of a YAML pair.\n- `YAMLPair[key] YAMLScalar` - check the key of a YAML pair.",
|
|
33
|
+
"type": "string"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"type": "boolean"
|
|
37
|
+
}
|
|
38
|
+
],
|
|
39
|
+
"maxItems": 2,
|
|
40
|
+
"minItems": 2,
|
|
41
|
+
"type": "array"
|
|
42
|
+
},
|
|
43
|
+
"type": "array"
|
|
44
|
+
},
|
|
26
45
|
"checkStringTemplates": {
|
|
27
46
|
"default": true,
|
|
28
47
|
"description": "Spell check template strings",
|
|
@@ -90,6 +90,25 @@ export interface Check {
|
|
|
90
90
|
* ```
|
|
91
91
|
*/
|
|
92
92
|
customWordListFile?: CustomWordListFilePath | CustomWordListFile | undefined;
|
|
93
|
+
/**
|
|
94
|
+
* Scope selectors to spell check.
|
|
95
|
+
* This is a list of scope selectors to spell check.
|
|
96
|
+
*
|
|
97
|
+
* Example:
|
|
98
|
+
* ```js
|
|
99
|
+
* checkScope: [
|
|
100
|
+
* ['YAMLPair[key] YAMLScalar', true],
|
|
101
|
+
* ['YAMLPair[value] YAMLScalar', true],
|
|
102
|
+
* ['YAMLSequence[entries] YAMLScalar', true],
|
|
103
|
+
* ['JSONProperty[key] JSONLiteral', true],
|
|
104
|
+
* ['JSONProperty[value] JSONLiteral', true],
|
|
105
|
+
* ['JSONArrayExpression JSONLiteral', true],
|
|
106
|
+
* ],
|
|
107
|
+
* ```
|
|
108
|
+
*
|
|
109
|
+
* @since 8.9.0
|
|
110
|
+
*/
|
|
111
|
+
checkScope?: ScopeSelectorList;
|
|
93
112
|
}
|
|
94
113
|
/**
|
|
95
114
|
* Specify a path to a custom word list file
|
|
@@ -106,5 +125,20 @@ export type WorkerOptions = RequiredOptions & {
|
|
|
106
125
|
cwd: string;
|
|
107
126
|
};
|
|
108
127
|
export declare const defaultOptions: Options;
|
|
128
|
+
/**
|
|
129
|
+
* The scope selector is a string that defines the context in which a rule applies.
|
|
130
|
+
* Examples:
|
|
131
|
+
* - `YAMLPair[value] YAMLScalar` - check the value of a YAML pair.
|
|
132
|
+
* - `YAMLPair[key] YAMLScalar` - check the key of a YAML pair.
|
|
133
|
+
*/
|
|
134
|
+
export type ScopeSelector = string;
|
|
135
|
+
/**
|
|
136
|
+
* A scope selector entry is a tuple that defines a scope selector and whether to spell check it.
|
|
137
|
+
*/
|
|
138
|
+
export type ScopeSelectorEntry = [ScopeSelector, boolean];
|
|
139
|
+
/**
|
|
140
|
+
* A list of scope selectors.
|
|
141
|
+
*/
|
|
142
|
+
export type ScopeSelectorList = ScopeSelectorEntry[];
|
|
109
143
|
export {};
|
|
110
144
|
//# sourceMappingURL=options.d.cts.map
|
|
@@ -83,11 +83,12 @@ function create(context) {
|
|
|
83
83
|
};
|
|
84
84
|
context.report(des);
|
|
85
85
|
}
|
|
86
|
-
function checkProgram() {
|
|
86
|
+
function checkProgram(_node) {
|
|
87
|
+
const filename = context.filename || context.getFilename();
|
|
87
88
|
const sc = context.sourceCode || context.getSourceCode();
|
|
88
89
|
if (!sc)
|
|
89
90
|
return;
|
|
90
|
-
const { issues, errors } = spellCheck(
|
|
91
|
+
const { issues, errors } = spellCheck(filename, sc.text, sc.ast, options);
|
|
91
92
|
if (errors && errors.length) {
|
|
92
93
|
log('errors: %o', errors.map((e) => e.message));
|
|
93
94
|
errors.forEach((error) => console.error('%s', error.message));
|
|
@@ -2,8 +2,8 @@ import type { Comment, Literal, Node } from 'estree';
|
|
|
2
2
|
export interface JSXText extends Omit<Literal, 'type'> {
|
|
3
3
|
type: 'JSXText';
|
|
4
4
|
}
|
|
5
|
-
export type ASTNode = (Node | Comment | JSXText) & {
|
|
5
|
+
export type ASTNode = Readonly<(Node | Comment | JSXText) & {
|
|
6
6
|
parent?: Node;
|
|
7
|
-
}
|
|
7
|
+
}>;
|
|
8
8
|
export type NodeType = ASTNode['type'];
|
|
9
9
|
//# sourceMappingURL=ASTNode.d.cts.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ASTNode } from './ASTNode.cjs';
|
|
2
|
+
export type Key = string | number | symbol | null | undefined;
|
|
3
|
+
export interface ASTPathElement {
|
|
4
|
+
node: ASTNode;
|
|
5
|
+
parent: ASTNode | undefined;
|
|
6
|
+
key: Key;
|
|
7
|
+
index?: number | undefined;
|
|
8
|
+
}
|
|
9
|
+
export interface ASTPath extends ASTPathElement {
|
|
10
|
+
prev: ASTPath | undefined;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=ASTPath.d.mts.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const defaultCheckedScopes = [
|
|
2
|
+
['YAMLPair YAMLScalar', true],
|
|
3
|
+
['YAMLSequence YAMLScalar', true],
|
|
4
|
+
['JSONProperty JSONLiteral', true],
|
|
5
|
+
['JSONArrayExpression JSONLiteral', true],
|
|
6
|
+
// ['YAMLPair[key] YAMLScalar', true],
|
|
7
|
+
// ['YAMLPair[value] YAMLScalar', true],
|
|
8
|
+
// ['YAMLSequence[entries] YAMLScalar', true],
|
|
9
|
+
// ['JSONProperty[key] JSONLiteral', true],
|
|
10
|
+
// ['JSONProperty[value] JSONLiteral', true],
|
|
11
|
+
// ['JSONArrayExpression[elements] JSONLiteral', true],
|
|
12
|
+
];
|
|
13
|
+
//# sourceMappingURL=customScopes.mjs.map
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { ASTPath, Key } from './ASTPath.mjs';
|
|
2
|
+
export type ScopeScore = number;
|
|
3
|
+
export declare class AstScopeMatcher {
|
|
4
|
+
readonly scope: ScopeItem[];
|
|
5
|
+
constructor(scope: ScopeItem[]);
|
|
6
|
+
static fromScopeSelector(scopeSelector: string): AstScopeMatcher;
|
|
7
|
+
/**
|
|
8
|
+
* Score the astScope based on the given scope.
|
|
9
|
+
* @param astScope The scope to score.
|
|
10
|
+
* @returns The score of the scope. 0 = no match, higher the score the better the match.
|
|
11
|
+
*/
|
|
12
|
+
score(astScope: string[]): ScopeScore;
|
|
13
|
+
/**
|
|
14
|
+
* Score the astScope based on the given scope.
|
|
15
|
+
* @param astScope The scope to score.
|
|
16
|
+
* @returns The score of the scope. 0 = no match, higher the score the better the match.
|
|
17
|
+
*/
|
|
18
|
+
scoreItems(scopeItems: ScopeItem[]): ScopeScore;
|
|
19
|
+
matchPath(path: ASTPath): ScopeScore;
|
|
20
|
+
scopeField(): string;
|
|
21
|
+
scopeType(): string;
|
|
22
|
+
}
|
|
23
|
+
export interface ScopeItem {
|
|
24
|
+
type: string;
|
|
25
|
+
childKey: string | undefined;
|
|
26
|
+
}
|
|
27
|
+
export declare function scopeItem(type: string, childKey?: string): ScopeItem;
|
|
28
|
+
export declare function parseScope(scope: string): ScopeItem[];
|
|
29
|
+
export interface ASTPathNodeToScope {
|
|
30
|
+
/**
|
|
31
|
+
* Convert a path node into a scope.
|
|
32
|
+
* @param node - The node to convert
|
|
33
|
+
* @param childKey - The key to the child node.
|
|
34
|
+
*/
|
|
35
|
+
(node: ASTPath, childKey: Key | undefined): ScopeItem;
|
|
36
|
+
}
|
|
37
|
+
export declare function keyToString(key: Key): string | undefined;
|
|
38
|
+
export declare function mapNodeToScope(p: ASTPath, key: Key | undefined): ScopeItem;
|
|
39
|
+
export declare function mapNodeToScopeItem(p: ASTPath, childKey: Key | undefined): ScopeItem;
|
|
40
|
+
export declare function mapScopeItemToString(item: ScopeItem): string;
|
|
41
|
+
/**
|
|
42
|
+
* Convert an ASTPath to a scope.
|
|
43
|
+
* @param path - The path to convert to a scope.
|
|
44
|
+
* @returns
|
|
45
|
+
*/
|
|
46
|
+
export declare function astPathToScope(path: ASTPath | undefined, mapFn?: ASTPathNodeToScope): string[];
|
|
47
|
+
export declare function astScopeToString(path: ASTPath | undefined, sep?: string, mapFn?: ASTPathNodeToScope): string;
|
|
48
|
+
export declare function astPathToScopeItems(path: ASTPath | undefined, mapFn?: ASTPathNodeToScope): ScopeItem[];
|
|
49
|
+
export declare class AstPathScope {
|
|
50
|
+
readonly path: ASTPath;
|
|
51
|
+
private items;
|
|
52
|
+
constructor(path: ASTPath);
|
|
53
|
+
get scope(): string[];
|
|
54
|
+
get scopeItems(): ScopeItem[];
|
|
55
|
+
get scopeString(): string;
|
|
56
|
+
score(matcher: AstScopeMatcher): ScopeScore;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=scope.d.mts.map
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import assert from 'node:assert';
|
|
2
|
+
export class AstScopeMatcher {
|
|
3
|
+
scope;
|
|
4
|
+
constructor(scope) {
|
|
5
|
+
this.scope = scope;
|
|
6
|
+
}
|
|
7
|
+
static fromScopeSelector(scopeSelector) {
|
|
8
|
+
return new AstScopeMatcher(parseScope(scopeSelector).reverse());
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Score the astScope based on the given scope.
|
|
12
|
+
* @param astScope The scope to score.
|
|
13
|
+
* @returns The score of the scope. 0 = no match, higher the score the better the match.
|
|
14
|
+
*/
|
|
15
|
+
score(astScope) {
|
|
16
|
+
try {
|
|
17
|
+
const scopeItems = astScope.map(parseScopeItem).reverse();
|
|
18
|
+
return this.scoreItems(scopeItems);
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
console.error('Failed to parse scope: %o', astScope);
|
|
22
|
+
return 0;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Score the astScope based on the given scope.
|
|
27
|
+
* @param astScope The scope to score.
|
|
28
|
+
* @returns The score of the scope. 0 = no match, higher the score the better the match.
|
|
29
|
+
*/
|
|
30
|
+
scoreItems(scopeItems) {
|
|
31
|
+
const scope = this.scope;
|
|
32
|
+
let score = 0;
|
|
33
|
+
let scale = 1;
|
|
34
|
+
let matchKey = false;
|
|
35
|
+
for (let i = 0; i < scope.length; i++) {
|
|
36
|
+
const item = scopeItems[i];
|
|
37
|
+
if (!item)
|
|
38
|
+
return 0;
|
|
39
|
+
const curr = scope[i];
|
|
40
|
+
if (curr.type !== item.type)
|
|
41
|
+
return 0;
|
|
42
|
+
if (curr.childKey && item.childKey && curr.childKey !== item.childKey)
|
|
43
|
+
return 0;
|
|
44
|
+
if (curr.childKey && !item.childKey && matchKey)
|
|
45
|
+
return 0;
|
|
46
|
+
if (curr.childKey && (curr.childKey == item.childKey || !matchKey)) {
|
|
47
|
+
score += scale;
|
|
48
|
+
}
|
|
49
|
+
score += scale * 2;
|
|
50
|
+
matchKey = true;
|
|
51
|
+
scale *= 4;
|
|
52
|
+
}
|
|
53
|
+
return score;
|
|
54
|
+
}
|
|
55
|
+
matchPath(path) {
|
|
56
|
+
const s = this.scope[0];
|
|
57
|
+
// Early out
|
|
58
|
+
if (s?.type !== path.node.type)
|
|
59
|
+
return 0;
|
|
60
|
+
const items = astPathToScopeItems(path);
|
|
61
|
+
return this.scoreItems(items);
|
|
62
|
+
}
|
|
63
|
+
scopeField() {
|
|
64
|
+
return this.scope[0]?.childKey || 'value';
|
|
65
|
+
}
|
|
66
|
+
scopeType() {
|
|
67
|
+
return this.scope[0]?.type || '';
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export function scopeItem(type, childKey) {
|
|
71
|
+
return { type, childKey };
|
|
72
|
+
}
|
|
73
|
+
const regexValidScope = /^([\w.-]+)(?:\[([\w<>.-]*)\])?$/;
|
|
74
|
+
function parseScopeItem(item) {
|
|
75
|
+
const match = item.match(regexValidScope);
|
|
76
|
+
assert(match, `Invalid scope item: ${item}`);
|
|
77
|
+
const [_, type, key] = match;
|
|
78
|
+
return { type, childKey: key || undefined };
|
|
79
|
+
}
|
|
80
|
+
export function parseScope(scope) {
|
|
81
|
+
return scope
|
|
82
|
+
.split(' ')
|
|
83
|
+
.filter((s) => s)
|
|
84
|
+
.map(parseScopeItem);
|
|
85
|
+
}
|
|
86
|
+
export function keyToString(key) {
|
|
87
|
+
return key === undefined || key === null
|
|
88
|
+
? undefined
|
|
89
|
+
: typeof key === 'symbol'
|
|
90
|
+
? `<${Symbol.keyFor(key)}>`
|
|
91
|
+
: `${key}`;
|
|
92
|
+
}
|
|
93
|
+
export function mapNodeToScope(p, key) {
|
|
94
|
+
return mapNodeToScopeItem(p, key);
|
|
95
|
+
}
|
|
96
|
+
export function mapNodeToScopeItem(p, childKey) {
|
|
97
|
+
return scopeItem(p.node.type, keyToString(childKey));
|
|
98
|
+
}
|
|
99
|
+
export function mapScopeItemToString(item) {
|
|
100
|
+
const { type, childKey: k } = item;
|
|
101
|
+
return k === undefined ? type : `${type}[${k}]`;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Convert an ASTPath to a scope.
|
|
105
|
+
* @param path - The path to convert to a scope.
|
|
106
|
+
* @returns
|
|
107
|
+
*/
|
|
108
|
+
export function astPathToScope(path, mapFn = mapNodeToScope) {
|
|
109
|
+
return astPathToScopeItems(path, mapFn).map(mapScopeItemToString).reverse();
|
|
110
|
+
}
|
|
111
|
+
export function astScopeToString(path, sep = ' ', mapFn) {
|
|
112
|
+
return astPathToScope(path, mapFn).join(sep);
|
|
113
|
+
}
|
|
114
|
+
export function astPathToScopeItems(path, mapFn = mapNodeToScope) {
|
|
115
|
+
const parts = [];
|
|
116
|
+
let key = undefined;
|
|
117
|
+
while (path) {
|
|
118
|
+
parts.push(mapFn(path, key));
|
|
119
|
+
key = path?.key;
|
|
120
|
+
path = path.prev;
|
|
121
|
+
}
|
|
122
|
+
return parts;
|
|
123
|
+
}
|
|
124
|
+
export class AstPathScope {
|
|
125
|
+
path;
|
|
126
|
+
items;
|
|
127
|
+
constructor(path) {
|
|
128
|
+
this.path = path;
|
|
129
|
+
this.items = astPathToScopeItems(path);
|
|
130
|
+
}
|
|
131
|
+
get scope() {
|
|
132
|
+
return this.items.map(mapScopeItemToString).reverse();
|
|
133
|
+
}
|
|
134
|
+
get scopeItems() {
|
|
135
|
+
return this.items;
|
|
136
|
+
}
|
|
137
|
+
get scopeString() {
|
|
138
|
+
return this.scope.join(' ');
|
|
139
|
+
}
|
|
140
|
+
score(matcher) {
|
|
141
|
+
const field = matcher.scopeField();
|
|
142
|
+
const node = this.path.node;
|
|
143
|
+
if (field in node && typeof node[field] === 'string') {
|
|
144
|
+
return matcher.scoreItems(this.items);
|
|
145
|
+
}
|
|
146
|
+
return 0;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=scope.mjs.map
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
// cspell:ignore TSESTree
|
|
2
2
|
import assert from 'node:assert';
|
|
3
3
|
import * as path from 'node:path';
|
|
4
|
-
import { format } from 'node:util';
|
|
5
4
|
import { createTextDocument, DocumentValidator, extractImportErrors, getDictionary, refreshDictionaryCache, } from 'cspell-lib';
|
|
6
5
|
import { getDefaultLogger } from '../common/logger.cjs';
|
|
6
|
+
import { defaultCheckedScopes } from './customScopes.mjs';
|
|
7
|
+
import { AstPathScope, AstScopeMatcher, astScopeToString, mapNodeToScope, scopeItem } from './scope.mjs';
|
|
7
8
|
import { walkTree } from './walkTree.mjs';
|
|
8
9
|
const defaultSettings = {
|
|
9
10
|
patterns: [
|
|
@@ -16,12 +17,14 @@ const defaultSettings = {
|
|
|
16
17
|
],
|
|
17
18
|
};
|
|
18
19
|
const isDebugModeExtended = false;
|
|
20
|
+
const forceLogging = false;
|
|
19
21
|
const knownConfigErrors = new Set();
|
|
20
22
|
export async function spellCheck(filename, text, root, options) {
|
|
21
23
|
const logger = getDefaultLogger();
|
|
22
|
-
const debugMode = options.debugMode || false;
|
|
23
|
-
logger.enabled = options.debugMode ?? (logger.enabled || isDebugModeExtended);
|
|
24
|
+
const debugMode = forceLogging || options.debugMode || false;
|
|
25
|
+
logger.enabled = forceLogging || (options.debugMode ?? (logger.enabled || isDebugModeExtended));
|
|
24
26
|
const log = logger.log;
|
|
27
|
+
const mapScopes = groupScopes([...defaultCheckedScopes, ...(options.checkScope || [])]);
|
|
25
28
|
log('options: %o', options);
|
|
26
29
|
const toIgnore = new Set();
|
|
27
30
|
const importedIdentifiers = new Set();
|
|
@@ -37,42 +40,46 @@ export async function spellCheck(filename, text, root, options) {
|
|
|
37
40
|
found.forEach((err) => (debugMode ? log(err) : log('Error: %s', err.message)));
|
|
38
41
|
return found;
|
|
39
42
|
}
|
|
40
|
-
function checkLiteral(
|
|
43
|
+
function checkLiteral(path) {
|
|
44
|
+
const node = path.node;
|
|
41
45
|
if (node.type !== 'Literal')
|
|
42
46
|
return;
|
|
43
47
|
if (!options.checkStrings)
|
|
44
48
|
return;
|
|
45
49
|
if (typeof node.value === 'string') {
|
|
46
|
-
debugNode(
|
|
50
|
+
debugNode(path, node.value);
|
|
47
51
|
if (options.ignoreImports && isImportOrRequired(node))
|
|
48
52
|
return;
|
|
49
53
|
if (options.ignoreImportProperties && isImportedProperty(node))
|
|
50
54
|
return;
|
|
51
|
-
checkNodeText(
|
|
55
|
+
checkNodeText(path, node.value);
|
|
52
56
|
}
|
|
53
57
|
}
|
|
54
|
-
function checkJSXText(
|
|
58
|
+
function checkJSXText(path) {
|
|
59
|
+
const node = path.node;
|
|
55
60
|
if (node.type !== 'JSXText')
|
|
56
61
|
return;
|
|
57
62
|
if (!options.checkJSXText)
|
|
58
63
|
return;
|
|
59
64
|
if (typeof node.value === 'string') {
|
|
60
|
-
debugNode(
|
|
61
|
-
checkNodeText(
|
|
65
|
+
debugNode(path, node.value);
|
|
66
|
+
checkNodeText(path, node.value);
|
|
62
67
|
}
|
|
63
68
|
}
|
|
64
|
-
function checkTemplateElement(
|
|
69
|
+
function checkTemplateElement(path) {
|
|
70
|
+
const node = path.node;
|
|
65
71
|
if (node.type !== 'TemplateElement')
|
|
66
72
|
return;
|
|
67
73
|
if (!options.checkStringTemplates)
|
|
68
74
|
return;
|
|
69
|
-
debugNode(
|
|
70
|
-
checkNodeText(
|
|
75
|
+
debugNode(path, node.value);
|
|
76
|
+
checkNodeText(path, node.value.cooked || node.value.raw);
|
|
71
77
|
}
|
|
72
|
-
function checkIdentifier(
|
|
78
|
+
function checkIdentifier(path) {
|
|
79
|
+
const node = path.node;
|
|
73
80
|
if (node.type !== 'Identifier')
|
|
74
81
|
return;
|
|
75
|
-
debugNode(
|
|
82
|
+
debugNode(path, node.name);
|
|
76
83
|
if (options.ignoreImports) {
|
|
77
84
|
if (isRawImportIdentifier(node)) {
|
|
78
85
|
toIgnore.add(node.name);
|
|
@@ -81,7 +88,7 @@ export async function spellCheck(filename, text, root, options) {
|
|
|
81
88
|
if (isImportIdentifier(node)) {
|
|
82
89
|
importedIdentifiers.add(node.name);
|
|
83
90
|
if (isLocalImportIdentifierUnique(node)) {
|
|
84
|
-
checkNodeText(
|
|
91
|
+
checkNodeText(path, node.name);
|
|
85
92
|
}
|
|
86
93
|
return;
|
|
87
94
|
}
|
|
@@ -95,26 +102,28 @@ export async function spellCheck(filename, text, root, options) {
|
|
|
95
102
|
return;
|
|
96
103
|
if (skipCheckForRawImportIdentifiers(node))
|
|
97
104
|
return;
|
|
98
|
-
checkNodeText(
|
|
105
|
+
checkNodeText(path, node.name);
|
|
99
106
|
}
|
|
100
|
-
function checkComment(
|
|
107
|
+
function checkComment(path) {
|
|
108
|
+
const node = path.node;
|
|
101
109
|
if (node.type !== 'Line' && node.type !== 'Block')
|
|
102
110
|
return;
|
|
103
111
|
if (!options.checkComments)
|
|
104
112
|
return;
|
|
105
|
-
debugNode(
|
|
106
|
-
checkNodeText(
|
|
113
|
+
debugNode(path, node.value);
|
|
114
|
+
checkNodeText(path, node.value);
|
|
107
115
|
}
|
|
108
|
-
function checkNodeText(
|
|
116
|
+
function checkNodeText(path, text) {
|
|
117
|
+
const node = path.node;
|
|
109
118
|
if (!node.range)
|
|
110
119
|
return;
|
|
111
120
|
const adj = node.type === 'Literal' ? 1 : 0;
|
|
112
121
|
const range = [node.range[0] + adj, node.range[1] - adj];
|
|
113
|
-
const scope = calcScope(
|
|
122
|
+
const scope = calcScope(path);
|
|
114
123
|
const result = validator.checkText(range, text, scope);
|
|
115
124
|
result.forEach((issue) => reportIssue(issue, node.type));
|
|
116
125
|
}
|
|
117
|
-
function calcScope(
|
|
126
|
+
function calcScope(_path) {
|
|
118
127
|
// inheritance(node);
|
|
119
128
|
return [];
|
|
120
129
|
}
|
|
@@ -176,74 +185,64 @@ export async function spellCheck(filename, text, root, options) {
|
|
|
176
185
|
Identifier: checkIdentifier,
|
|
177
186
|
JSXText: checkJSXText,
|
|
178
187
|
};
|
|
179
|
-
function
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
if (node.type === 'ImportSpecifier') {
|
|
185
|
-
const extra = node.imported === child ? '.imported' : node.local === child ? '.local' : '';
|
|
186
|
-
return node.type + extra;
|
|
187
|
-
}
|
|
188
|
-
if (node.type === 'ImportDeclaration') {
|
|
189
|
-
const extra = node.source === child ? '.source' : '';
|
|
190
|
-
return node.type + extra;
|
|
191
|
-
}
|
|
192
|
-
if (node.type === 'ExportSpecifier') {
|
|
193
|
-
const extra = node.exported === child ? '.exported' : node.local === child ? '.local' : '';
|
|
194
|
-
return node.type + extra;
|
|
195
|
-
}
|
|
196
|
-
if (node.type === 'ExportNamedDeclaration') {
|
|
197
|
-
const extra = node.source === child ? '.source' : '';
|
|
198
|
-
return node.type + extra;
|
|
199
|
-
}
|
|
200
|
-
if (node.type === 'Property') {
|
|
201
|
-
const extra = node.key === child ? 'key' : node.value === child ? 'value' : '';
|
|
202
|
-
return [node.type, node.kind, extra].join('.');
|
|
203
|
-
}
|
|
204
|
-
if (node.type === 'MemberExpression') {
|
|
205
|
-
const extra = node.property === child ? 'property' : node.object === child ? 'object' : '';
|
|
206
|
-
return node.type + '.' + extra;
|
|
207
|
-
}
|
|
208
|
-
if (node.type === 'ArrowFunctionExpression') {
|
|
209
|
-
const extra = node.body === child ? 'body' : 'param';
|
|
210
|
-
return node.type + '.' + extra;
|
|
211
|
-
}
|
|
212
|
-
if (node.type === 'FunctionDeclaration') {
|
|
213
|
-
const extra = node.id === child ? 'id' : node.body === child ? 'body' : 'params';
|
|
214
|
-
return node.type + '.' + extra;
|
|
215
|
-
}
|
|
216
|
-
if (node.type === 'ClassDeclaration' || node.type === 'ClassExpression') {
|
|
217
|
-
const extra = node.id === child ? 'id' : node.body === child ? 'body' : 'superClass';
|
|
218
|
-
return node.type + '.' + extra;
|
|
219
|
-
}
|
|
220
|
-
if (node.type === 'CallExpression') {
|
|
221
|
-
const extra = node.callee === child ? 'callee' : 'arguments';
|
|
222
|
-
return node.type + '.' + extra;
|
|
223
|
-
}
|
|
224
|
-
if (node.type === 'Literal') {
|
|
225
|
-
return tagLiteral(node);
|
|
226
|
-
}
|
|
227
|
-
if (node.type === 'Block') {
|
|
228
|
-
return node.value[0] === '*' ? 'Comment.docBlock' : 'Comment.block';
|
|
229
|
-
}
|
|
230
|
-
if (node.type === 'Line') {
|
|
231
|
-
return 'Comment.line';
|
|
188
|
+
function needToCheckFields(path) {
|
|
189
|
+
const possibleScopes = mapScopes.get(path.node.type);
|
|
190
|
+
if (!possibleScopes) {
|
|
191
|
+
_dumpNode(path);
|
|
192
|
+
return undefined;
|
|
232
193
|
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
194
|
+
const scopePath = new AstPathScope(path);
|
|
195
|
+
const scores = possibleScopes
|
|
196
|
+
.map(({ scope, check }) => ({ score: scopePath.score(scope), check, scope }))
|
|
197
|
+
.filter((s) => s.score > 0);
|
|
198
|
+
const maxScore = Math.max(0, ...scores.map((s) => s.score));
|
|
199
|
+
const topScopes = scores.filter((s) => s.score === maxScore);
|
|
200
|
+
if (!topScopes.length)
|
|
201
|
+
return undefined;
|
|
202
|
+
return Object.fromEntries(topScopes.map((s) => [s.scope.scopeField(), s.check]));
|
|
238
203
|
}
|
|
239
|
-
function
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
204
|
+
function defaultHandler(path) {
|
|
205
|
+
const fields = needToCheckFields(path);
|
|
206
|
+
if (!fields)
|
|
207
|
+
return;
|
|
208
|
+
for (const [field, check] of Object.entries(fields)) {
|
|
209
|
+
if (!check)
|
|
210
|
+
continue;
|
|
211
|
+
const node = path.node;
|
|
212
|
+
const value = node[field];
|
|
213
|
+
if (typeof value !== 'string')
|
|
214
|
+
continue;
|
|
215
|
+
debugNode(path, value);
|
|
216
|
+
checkNodeText(path, value);
|
|
243
217
|
}
|
|
244
218
|
}
|
|
245
|
-
function
|
|
246
|
-
|
|
219
|
+
function checkNode(path) {
|
|
220
|
+
// _dumpNode(path);
|
|
221
|
+
const handler = processors[path.node.type] ?? defaultHandler;
|
|
222
|
+
handler(path);
|
|
223
|
+
}
|
|
224
|
+
function _dumpNode(path) {
|
|
225
|
+
function value(v) {
|
|
226
|
+
if (['string', 'number', 'boolean'].includes(typeof v))
|
|
227
|
+
return v;
|
|
228
|
+
if (v && typeof v === 'object' && 'type' in v)
|
|
229
|
+
return `{ type: ${v.type} }`;
|
|
230
|
+
return `<${v}>`;
|
|
231
|
+
}
|
|
232
|
+
function dotValue(v) {
|
|
233
|
+
if (typeof v === 'object' && v) {
|
|
234
|
+
return Object.fromEntries(Object.entries(v).map(([k, v]) => [k, value(v)]));
|
|
235
|
+
}
|
|
236
|
+
return `<${typeof v}>`;
|
|
237
|
+
}
|
|
238
|
+
const { parent: _, ...n } = path.node;
|
|
239
|
+
const warn = log;
|
|
240
|
+
warn('Node: %o', {
|
|
241
|
+
key: path.key,
|
|
242
|
+
type: n.type,
|
|
243
|
+
path: inheritanceSummary(path),
|
|
244
|
+
node: dotValue(n),
|
|
245
|
+
});
|
|
247
246
|
}
|
|
248
247
|
/**
|
|
249
248
|
* find the origin of a member expression
|
|
@@ -259,7 +258,9 @@ export async function spellCheck(filename, text, root, options) {
|
|
|
259
258
|
return obj;
|
|
260
259
|
}
|
|
261
260
|
function isFunctionCall(node, name) {
|
|
262
|
-
|
|
261
|
+
if (!node)
|
|
262
|
+
return false;
|
|
263
|
+
return node.type === 'CallExpression' && node.callee.type === 'Identifier' && node.callee.name === name;
|
|
263
264
|
}
|
|
264
265
|
function isRequireCall(node) {
|
|
265
266
|
return isFunctionCall(node, 'require');
|
|
@@ -267,20 +268,36 @@ export async function spellCheck(filename, text, root, options) {
|
|
|
267
268
|
function isImportOrRequired(node) {
|
|
268
269
|
return isRequireCall(node.parent) || (node.parent?.type === 'ImportDeclaration' && node.parent.source === node);
|
|
269
270
|
}
|
|
270
|
-
function debugNode(
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
const val = format('%o', value);
|
|
274
|
-
log(`${inheritanceSummary(node)}: ${val}`);
|
|
271
|
+
function debugNode(path, value) {
|
|
272
|
+
log(`${inheritanceSummary(path)}: %o`, value);
|
|
273
|
+
debugMode && _dumpNode(path);
|
|
275
274
|
}
|
|
275
|
+
// console.warn('root: %o', root);
|
|
276
276
|
walkTree(root, checkNode);
|
|
277
277
|
return { issues, errors };
|
|
278
278
|
}
|
|
279
|
+
function mapNode(path, key) {
|
|
280
|
+
const node = path.node;
|
|
281
|
+
if (node.type === 'Literal') {
|
|
282
|
+
return scopeItem(tagLiteral(node));
|
|
283
|
+
}
|
|
284
|
+
if (node.type === 'Block') {
|
|
285
|
+
const value = typeof node.value === 'string' ? node.value : '';
|
|
286
|
+
return scopeItem(value[0] === '*' ? 'Comment.docBlock' : 'Comment.block');
|
|
287
|
+
}
|
|
288
|
+
if (node.type === 'Line') {
|
|
289
|
+
return scopeItem('Comment.line');
|
|
290
|
+
}
|
|
291
|
+
return mapNodeToScope(path, key);
|
|
292
|
+
}
|
|
293
|
+
function inheritanceSummary(path) {
|
|
294
|
+
return astScopeToString(path, ' ', mapNode);
|
|
295
|
+
}
|
|
279
296
|
function tagLiteral(node) {
|
|
280
297
|
assert(node.type === 'Literal');
|
|
281
298
|
const kind = typeof node.value;
|
|
282
299
|
const extra = kind === 'string'
|
|
283
|
-
? node.raw?.[0] === '"'
|
|
300
|
+
? asStr(node.raw)?.[0] === '"'
|
|
284
301
|
? 'string.double'
|
|
285
302
|
: 'string.single'
|
|
286
303
|
: node.value === null
|
|
@@ -416,4 +433,19 @@ async function reportConfigurationErrors(config, knownConfigErrors) {
|
|
|
416
433
|
});
|
|
417
434
|
return errors;
|
|
418
435
|
}
|
|
436
|
+
function groupScopes(scopes) {
|
|
437
|
+
const objScopes = Object.fromEntries(scopes);
|
|
438
|
+
const map = new Map();
|
|
439
|
+
for (const [selector, check] of Object.entries(objScopes)) {
|
|
440
|
+
const scope = AstScopeMatcher.fromScopeSelector(selector);
|
|
441
|
+
const key = scope.scopeType();
|
|
442
|
+
const list = map.get(key) || [];
|
|
443
|
+
list.push({ scope, check });
|
|
444
|
+
map.set(key, list);
|
|
445
|
+
}
|
|
446
|
+
return map;
|
|
447
|
+
}
|
|
448
|
+
function asStr(v) {
|
|
449
|
+
return typeof v === 'string' ? v : undefined;
|
|
450
|
+
}
|
|
419
451
|
//# sourceMappingURL=spellCheck.mjs.map
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { ASTNode } from './ASTNode.cjs';
|
|
2
|
-
type
|
|
3
|
-
export declare function walkTree(node: ASTNode, enter: (
|
|
4
|
-
export {};
|
|
2
|
+
import type { ASTPath } from './ASTPath.mjs';
|
|
3
|
+
export declare function walkTree(node: ASTNode, enter: (path: ASTPath) => void): void;
|
|
5
4
|
//# sourceMappingURL=walkTree.d.mts.map
|
package/dist/worker/walkTree.mjs
CHANGED
|
@@ -1,15 +1,64 @@
|
|
|
1
|
-
|
|
1
|
+
// const logger = getDefaultLogger();
|
|
2
|
+
// const log = logger.log;
|
|
2
3
|
export function walkTree(node, enter) {
|
|
3
4
|
const visited = new Set();
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
let pathNode = undefined;
|
|
6
|
+
function adjustPath(n) {
|
|
7
|
+
if (!n.parent || !pathNode) {
|
|
8
|
+
pathNode = n;
|
|
9
|
+
n.prev = undefined;
|
|
10
|
+
return n;
|
|
11
|
+
}
|
|
12
|
+
if (pathNode.node === n.parent) {
|
|
13
|
+
n.prev = pathNode;
|
|
14
|
+
pathNode = n;
|
|
15
|
+
return n;
|
|
16
|
+
}
|
|
17
|
+
while (pathNode && pathNode.node !== n.parent) {
|
|
18
|
+
pathNode = pathNode.prev;
|
|
19
|
+
}
|
|
20
|
+
n.prev = pathNode;
|
|
21
|
+
pathNode = n;
|
|
22
|
+
return n;
|
|
23
|
+
}
|
|
24
|
+
walk(node, ({ node, parent, key, index }) => {
|
|
25
|
+
if (key === 'tokens' || key === 'parent' || visited.has(node)) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
visited.add(node);
|
|
29
|
+
const path = adjustPath({ node, parent: parent, key, index, prev: undefined });
|
|
30
|
+
enter(path);
|
|
31
|
+
return true;
|
|
13
32
|
});
|
|
14
33
|
}
|
|
34
|
+
function walk(root, enter) {
|
|
35
|
+
function walkNodes(pfx, node, parent, key, index) {
|
|
36
|
+
const goIn = enter({ node, parent, key, index });
|
|
37
|
+
// log('walk: %o', { pfx, type: node.type, key, index, goIn });
|
|
38
|
+
if (!goIn)
|
|
39
|
+
return;
|
|
40
|
+
const n = node;
|
|
41
|
+
for (const key of Object.keys(n)) {
|
|
42
|
+
const v = n[key];
|
|
43
|
+
const fx = pfx + `.${node.type}[${key}]`;
|
|
44
|
+
if (Array.isArray(v)) {
|
|
45
|
+
for (let i = 0; i < v.length; ++i) {
|
|
46
|
+
const vv = v[i];
|
|
47
|
+
isNode(vv) && walkNodes(fx, vv, node, key, i);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
else if (isNode(v)) {
|
|
51
|
+
walkNodes(fx, v, node, key, undefined);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
walkNodes('root', root, undefined, undefined, undefined);
|
|
57
|
+
}
|
|
58
|
+
function isNode(node) {
|
|
59
|
+
if (!node)
|
|
60
|
+
return false;
|
|
61
|
+
const n = node;
|
|
62
|
+
return (typeof n === 'object' && typeof n['type'] === 'string') || false;
|
|
63
|
+
}
|
|
15
64
|
//# sourceMappingURL=walkTree.mjs.map
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "8.
|
|
6
|
+
"version": "8.9.0",
|
|
7
7
|
"description": "CSpell ESLint plugin",
|
|
8
8
|
"keywords": [
|
|
9
9
|
"cspell",
|
|
@@ -45,9 +45,10 @@
|
|
|
45
45
|
"assets",
|
|
46
46
|
"dist",
|
|
47
47
|
"!**/__mocks__",
|
|
48
|
-
"!**/*.tsbuildInfo",
|
|
49
|
-
"!**/*.test.*",
|
|
50
48
|
"!**/*.spec.*",
|
|
49
|
+
"!**/*.test.*",
|
|
50
|
+
"!**/test*/**",
|
|
51
|
+
"!**/*.tsbuildInfo",
|
|
51
52
|
"!**/*.map"
|
|
52
53
|
],
|
|
53
54
|
"scripts": {
|
|
@@ -60,6 +61,7 @@
|
|
|
60
61
|
"clean-build": "pnpm run clean && pnpm run build",
|
|
61
62
|
"coverage": "echo coverage",
|
|
62
63
|
"test-watch": "pnpm run test -- --watch",
|
|
64
|
+
"test-yaml": "npx mocha --timeout 10000 \"dist/**/yaml.test.mjs\"",
|
|
63
65
|
"test": "npx mocha --timeout 10000 \"dist/**/*.test.mjs\""
|
|
64
66
|
},
|
|
65
67
|
"repository": {
|
|
@@ -75,29 +77,33 @@
|
|
|
75
77
|
},
|
|
76
78
|
"devDependencies": {
|
|
77
79
|
"@eslint/eslintrc": "^3.1.0",
|
|
78
|
-
"@eslint/js": "^9.
|
|
80
|
+
"@eslint/js": "^9.5.0",
|
|
79
81
|
"@types/estree": "^1.0.5",
|
|
80
82
|
"@types/mocha": "^10.0.6",
|
|
81
|
-
"@typescript-eslint/parser": "^7.
|
|
82
|
-
"@typescript-eslint/types": "^7.
|
|
83
|
-
"eslint": "^9.
|
|
84
|
-
"eslint-plugin-
|
|
83
|
+
"@typescript-eslint/parser": "^7.13.1",
|
|
84
|
+
"@typescript-eslint/types": "^7.13.1",
|
|
85
|
+
"eslint": "^9.5.0",
|
|
86
|
+
"eslint-plugin-jsonc": "^2.16.0",
|
|
87
|
+
"eslint-plugin-mdx": "^3.1.5",
|
|
88
|
+
"eslint-plugin-n": "^17.9.0",
|
|
85
89
|
"eslint-plugin-react": "^7.34.2",
|
|
86
90
|
"eslint-plugin-simple-import-sort": "^12.1.0",
|
|
87
|
-
"
|
|
91
|
+
"eslint-plugin-yml": "^1.14.0",
|
|
92
|
+
"globals": "^15.6.0",
|
|
93
|
+
"jsonc-eslint-parser": "^2.4.0",
|
|
88
94
|
"mocha": "^10.4.0",
|
|
89
|
-
"ts-json-schema-generator": "^2.
|
|
95
|
+
"ts-json-schema-generator": "^2.3.0",
|
|
90
96
|
"typescript": "^5.4.5",
|
|
91
|
-
"typescript-eslint": "^7.
|
|
97
|
+
"typescript-eslint": "^7.13.1",
|
|
98
|
+
"yaml-eslint-parser": "^1.2.3"
|
|
92
99
|
},
|
|
93
100
|
"dependencies": {
|
|
94
|
-
"@cspell/cspell-types": "8.
|
|
95
|
-
"cspell-lib": "8.
|
|
96
|
-
"estree-walker": "^3.0.3",
|
|
101
|
+
"@cspell/cspell-types": "8.9.0",
|
|
102
|
+
"cspell-lib": "8.9.0",
|
|
97
103
|
"synckit": "^0.9.0"
|
|
98
104
|
},
|
|
99
105
|
"peerDependencies": {
|
|
100
106
|
"eslint": "^7 || ^8 || ^9"
|
|
101
107
|
},
|
|
102
|
-
"gitHead": "
|
|
108
|
+
"gitHead": "33c513cf848a61fb1ebcea1b9c67505a31447411"
|
|
103
109
|
}
|