@cspell/eslint-plugin 8.19.1 → 8.19.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.
Files changed (31) hide show
  1. package/dist/generated/schema.cjs +1 -0
  2. package/dist/plugin/cspell-eslint-plugin.cjs +2 -3
  3. package/dist/{worker/ASTNode.d.mts → spellCheckAST/ASTNode.d.ts} +1 -1
  4. package/dist/spellCheckAST/ASTNode.js +2 -0
  5. package/dist/{worker/ASTPath.d.mts → spellCheckAST/ASTPath.d.ts} +2 -2
  6. package/dist/spellCheckAST/ASTPath.js +2 -0
  7. package/dist/{worker/customScopes.mjs → spellCheckAST/customScopes.cjs} +5 -2
  8. package/dist/{worker/customScopes.d.mts → spellCheckAST/customScopes.d.cts} +1 -1
  9. package/dist/spellCheckAST/index.cjs +6 -0
  10. package/dist/spellCheckAST/index.d.cts +3 -0
  11. package/dist/{worker/scope.mjs → spellCheckAST/scope.cjs} +31 -14
  12. package/dist/{worker/scope.d.mts → spellCheckAST/scope.d.cts} +2 -2
  13. package/dist/spellCheckAST/spellCheck.d.mts +45 -0
  14. package/dist/spellCheckAST/spellCheck.mjs +165 -0
  15. package/dist/{worker/spellCheck.mjs → spellCheckAST/spellCheckAST.cjs} +45 -172
  16. package/dist/spellCheckAST/spellCheckAST.d.cts +5 -0
  17. package/dist/{worker/types.d.mts → spellCheckAST/types.d.ts} +2 -6
  18. package/dist/spellCheckAST/types.js +2 -0
  19. package/dist/{worker/walkTree.mjs → spellCheckAST/walkTree.cjs} +9 -4
  20. package/dist/spellCheckAST/walkTree.d.cts +4 -0
  21. package/dist/spellCheckAST/worker.mjs +9 -0
  22. package/dist/synckit/index.cjs +9 -0
  23. package/dist/synckit/index.d.cts +6 -0
  24. package/package.json +7 -9
  25. package/dist/worker/ASTNode.mjs +0 -2
  26. package/dist/worker/ASTPath.mjs +0 -2
  27. package/dist/worker/spellCheck.d.mts +0 -5
  28. package/dist/worker/types.mjs +0 -2
  29. package/dist/worker/walkTree.d.mts +0 -4
  30. package/dist/worker/worker.mjs +0 -9
  31. /package/dist/{worker → spellCheckAST}/worker.d.mts +0 -0
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.optionsSchema = void 0;
4
+ // NOTICE: This file is autogenerated.
4
5
  exports.optionsSchema = {
5
6
  "$schema": "http://json-schema.org/draft-07/schema#",
6
7
  "additionalProperties": false,
@@ -2,11 +2,10 @@
2
2
  // cspell:ignore TSESTree
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.plugin = exports.configs = exports.meta = exports.rules = void 0;
5
- const synckit_1 = require("synckit");
6
5
  const logger_cjs_1 = require("../common/logger.cjs");
7
6
  const schema_cjs_1 = require("../generated/schema.cjs");
7
+ const index_cjs_1 = require("../spellCheckAST/index.cjs");
8
8
  const defaultCheckOptions_cjs_1 = require("./defaultCheckOptions.cjs");
9
- const spellCheck = (0, synckit_1.createSyncFn)(require.resolve('../worker/worker.mjs'));
10
9
  const messages = {
11
10
  wordUnknown: 'Unknown word: "{{word}}"',
12
11
  wordForbidden: 'Forbidden word: "{{word}}"',
@@ -84,7 +83,7 @@ function create(context) {
84
83
  const sc = context.sourceCode || context.getSourceCode();
85
84
  if (!sc)
86
85
  return;
87
- const { issues, errors } = spellCheck(filename, sc.text, sc.ast, options);
86
+ const { issues, errors } = (0, index_cjs_1.spellCheckAST)(filename, sc.text, sc.ast, options);
88
87
  if (errors && errors.length) {
89
88
  log('errors: %o', errors.map((e) => e.message));
90
89
  errors.forEach((error) => context.report({ message: error.message, loc: { line: 1, column: 1 } }));
@@ -6,4 +6,4 @@ export type ASTNode = Readonly<(Node | Comment | JSXText) & {
6
6
  parent?: Node;
7
7
  }>;
8
8
  export type NodeType = ASTNode['type'];
9
- //# sourceMappingURL=ASTNode.d.mts.map
9
+ //# sourceMappingURL=ASTNode.d.ts.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ASTNode.js.map
@@ -1,4 +1,4 @@
1
- import type { ASTNode } from './ASTNode.mjs';
1
+ import type { ASTNode } from './ASTNode.js';
2
2
  export type Key = string | number | symbol | null | undefined;
3
3
  export interface ASTPathElement {
4
4
  node: ASTNode;
@@ -9,4 +9,4 @@ export interface ASTPathElement {
9
9
  export interface ASTPath extends ASTPathElement {
10
10
  prev: ASTPath | undefined;
11
11
  }
12
- //# sourceMappingURL=ASTPath.d.mts.map
12
+ //# sourceMappingURL=ASTPath.d.ts.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ASTPath.js.map
@@ -1,4 +1,7 @@
1
- export const defaultCheckedScopes = [
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaultCheckedScopes = void 0;
4
+ exports.defaultCheckedScopes = [
2
5
  ['YAMLPair YAMLScalar', true],
3
6
  ['YAMLSequence YAMLScalar', true],
4
7
  ['JSONProperty JSONLiteral', true],
@@ -10,4 +13,4 @@ export const defaultCheckedScopes = [
10
13
  // ['JSONProperty[value] JSONLiteral', true],
11
14
  // ['JSONArrayExpression[elements] JSONLiteral', true],
12
15
  ];
13
- //# sourceMappingURL=customScopes.mjs.map
16
+ //# sourceMappingURL=customScopes.cjs.map
@@ -1,3 +1,3 @@
1
1
  import type { RequiredOptions } from '../common/options.cjs';
2
2
  export declare const defaultCheckedScopes: RequiredOptions['checkScope'];
3
- //# sourceMappingURL=customScopes.d.mts.map
3
+ //# sourceMappingURL=customScopes.d.cts.map
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.spellCheckAST = void 0;
4
+ var spellCheckAST_cjs_1 = require("./spellCheckAST.cjs");
5
+ Object.defineProperty(exports, "spellCheckAST", { enumerable: true, get: function () { return spellCheckAST_cjs_1.spellCheckAST; } });
6
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1,3 @@
1
+ export { spellCheckAST } from './spellCheckAST.cjs';
2
+ export type { Issue } from './types.js' with { 'resolution-mode': 'import' };
3
+ //# sourceMappingURL=index.d.cts.map
@@ -1,5 +1,20 @@
1
- import assert from 'node:assert';
2
- export class AstScopeMatcher {
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.AstPathScope = exports.AstScopeMatcher = void 0;
7
+ exports.scopeItem = scopeItem;
8
+ exports.parseScope = parseScope;
9
+ exports.keyToString = keyToString;
10
+ exports.mapNodeToScope = mapNodeToScope;
11
+ exports.mapNodeToScopeItem = mapNodeToScopeItem;
12
+ exports.mapScopeItemToString = mapScopeItemToString;
13
+ exports.astPathToScope = astPathToScope;
14
+ exports.astScopeToString = astScopeToString;
15
+ exports.astPathToScopeItems = astPathToScopeItems;
16
+ const node_assert_1 = __importDefault(require("node:assert"));
17
+ class AstScopeMatcher {
3
18
  scope;
4
19
  constructor(scope) {
5
20
  this.scope = scope;
@@ -67,36 +82,37 @@ export class AstScopeMatcher {
67
82
  return this.scope[0]?.type || '';
68
83
  }
69
84
  }
70
- export function scopeItem(type, childKey) {
85
+ exports.AstScopeMatcher = AstScopeMatcher;
86
+ function scopeItem(type, childKey) {
71
87
  return { type, childKey };
72
88
  }
73
89
  const regexValidScope = /^([\w.-]+)(?:\[([\w<>.-]*)\])?$/;
74
90
  function parseScopeItem(item) {
75
91
  const match = item.match(regexValidScope);
76
- assert(match, `Invalid scope item: ${item}`);
92
+ (0, node_assert_1.default)(match, `Invalid scope item: ${item}`);
77
93
  const [_, type, key] = match;
78
94
  return { type, childKey: key || undefined };
79
95
  }
80
- export function parseScope(scope) {
96
+ function parseScope(scope) {
81
97
  return scope
82
98
  .split(' ')
83
99
  .filter((s) => s)
84
100
  .map(parseScopeItem);
85
101
  }
86
- export function keyToString(key) {
102
+ function keyToString(key) {
87
103
  return key === undefined || key === null
88
104
  ? undefined
89
105
  : typeof key === 'symbol'
90
106
  ? `<${Symbol.keyFor(key)}>`
91
107
  : `${key}`;
92
108
  }
93
- export function mapNodeToScope(p, key) {
109
+ function mapNodeToScope(p, key) {
94
110
  return mapNodeToScopeItem(p, key);
95
111
  }
96
- export function mapNodeToScopeItem(p, childKey) {
112
+ function mapNodeToScopeItem(p, childKey) {
97
113
  return scopeItem(p.node.type, keyToString(childKey));
98
114
  }
99
- export function mapScopeItemToString(item) {
115
+ function mapScopeItemToString(item) {
100
116
  const { type, childKey: k } = item;
101
117
  return k === undefined ? type : `${type}[${k}]`;
102
118
  }
@@ -105,13 +121,13 @@ export function mapScopeItemToString(item) {
105
121
  * @param path - The path to convert to a scope.
106
122
  * @returns
107
123
  */
108
- export function astPathToScope(path, mapFn = mapNodeToScope) {
124
+ function astPathToScope(path, mapFn = mapNodeToScope) {
109
125
  return astPathToScopeItems(path, mapFn).map(mapScopeItemToString).reverse();
110
126
  }
111
- export function astScopeToString(path, sep = ' ', mapFn) {
127
+ function astScopeToString(path, sep = ' ', mapFn) {
112
128
  return astPathToScope(path, mapFn).join(sep);
113
129
  }
114
- export function astPathToScopeItems(path, mapFn = mapNodeToScope) {
130
+ function astPathToScopeItems(path, mapFn = mapNodeToScope) {
115
131
  const parts = [];
116
132
  let key = undefined;
117
133
  while (path) {
@@ -121,7 +137,7 @@ export function astPathToScopeItems(path, mapFn = mapNodeToScope) {
121
137
  }
122
138
  return parts;
123
139
  }
124
- export class AstPathScope {
140
+ class AstPathScope {
125
141
  path;
126
142
  items;
127
143
  constructor(path) {
@@ -146,4 +162,5 @@ export class AstPathScope {
146
162
  return 0;
147
163
  }
148
164
  }
149
- //# sourceMappingURL=scope.mjs.map
165
+ exports.AstPathScope = AstPathScope;
166
+ //# sourceMappingURL=scope.cjs.map
@@ -1,4 +1,4 @@
1
- import type { ASTPath, Key } from './ASTPath.mjs';
1
+ import type { ASTPath, Key } from './ASTPath.js' with { 'resolution-mode': 'import' };
2
2
  export type ScopeScore = number;
3
3
  export declare class AstScopeMatcher {
4
4
  readonly scope: ScopeItem[];
@@ -55,4 +55,4 @@ export declare class AstPathScope {
55
55
  get scopeString(): string;
56
56
  score(matcher: AstScopeMatcher): ScopeScore;
57
57
  }
58
- //# sourceMappingURL=scope.d.mts.map
58
+ //# sourceMappingURL=scope.d.cts.map
@@ -0,0 +1,45 @@
1
+ import type { Options } from '../common/options.cjs';
2
+ export type SpellCheckOptions = Options & {
3
+ cwd: string;
4
+ };
5
+ interface ExtendedSuggestion {
6
+ /**
7
+ * The suggestion.
8
+ */
9
+ word: string;
10
+ /**
11
+ * The word is preferred above others, except other "preferred" words.
12
+ */
13
+ isPreferred?: boolean;
14
+ /**
15
+ * The suggested word adjusted to match the original case.
16
+ */
17
+ wordAdjustedToMatchCase?: string;
18
+ }
19
+ export type Suggestions = ExtendedSuggestion[] | undefined;
20
+ export interface SpellCheckIssue {
21
+ /** the starting offset of the issue */
22
+ start: number;
23
+ /** the ending offset of the issue */
24
+ end: number;
25
+ /** the word that was flagged */
26
+ word: string;
27
+ /** the severity of the issue. */
28
+ severity: 'Forbidden' | 'Unknown' | 'Hint';
29
+ /** suggestions to be presented. */
30
+ suggestions: Suggestions;
31
+ /** The range of text in which this issue occurred. */
32
+ range: CheckTextRange;
33
+ /** The index of the range in which this issues occurred. */
34
+ rangeIdx: number;
35
+ }
36
+ export interface SpellCheckResults {
37
+ issues: SpellCheckIssue[];
38
+ errors?: Error[];
39
+ }
40
+ export type CheckTextRange = readonly [number, number];
41
+ export type SpellCheckFn = typeof spellCheck;
42
+ export type SpellCheckSyncFn = (...p: Parameters<SpellCheckFn>) => Awaited<ReturnType<SpellCheckFn>>;
43
+ export declare function spellCheck(filename: string, text: string, ranges: CheckTextRange[], options: SpellCheckOptions): Promise<SpellCheckResults>;
44
+ export {};
45
+ //# sourceMappingURL=spellCheck.d.mts.map
@@ -0,0 +1,165 @@
1
+ // cspell:ignore TSESTree
2
+ import assert from 'node:assert';
3
+ import * as path from 'node:path';
4
+ import { toFileDirURL, toFileURL } from '@cspell/url';
5
+ import { createTextDocument, DocumentValidator, extractImportErrors, getDictionary, refreshDictionaryCache, } from 'cspell-lib';
6
+ import { getDefaultLogger } from '../common/logger.cjs';
7
+ const defaultSettings = {
8
+ name: 'eslint-configuration-file',
9
+ patterns: [
10
+ // @todo: be able to use cooked / transformed strings.
11
+ // {
12
+ // // Do not block unicode escape sequences.
13
+ // name: 'js-unicode-escape',
14
+ // pattern: /$^/g,
15
+ // },
16
+ ],
17
+ };
18
+ const isDebugModeExtended = false;
19
+ const forceLogging = false;
20
+ const knownConfigErrors = new Set();
21
+ export async function spellCheck(filename, text, ranges, options) {
22
+ const logger = getDefaultLogger();
23
+ const debugMode = forceLogging || options.debugMode || false;
24
+ logger.enabled = forceLogging || (options.debugMode ?? (logger.enabled || isDebugModeExtended));
25
+ const log = logger.log;
26
+ log('options: %o', options);
27
+ const validator = getDocValidator(filename, text, options);
28
+ await validator.prepare();
29
+ log('Settings: %o', validator.settings);
30
+ const errors = [...validator.errors];
31
+ errors.push(...(await checkSettings()));
32
+ const issues = ranges
33
+ .map((range, idx) => {
34
+ const issues = validator
35
+ .checkText(range, undefined, undefined)
36
+ .map((issue) => normalizeIssue(issue, range, idx));
37
+ return issues.length ? issues : undefined;
38
+ })
39
+ .filter((issues) => !!issues)
40
+ .flat();
41
+ return { issues, errors };
42
+ async function checkSettings() {
43
+ const finalSettings = validator.getFinalizedDocSettings();
44
+ const found = await reportConfigurationErrors(finalSettings, knownConfigErrors);
45
+ found.forEach((err) => (debugMode ? log(err) : log('Error: %s', err.message)));
46
+ return found;
47
+ }
48
+ function normalizeIssue(issue, range, rangeIdx) {
49
+ const word = issue.text;
50
+ const start = issue.offset;
51
+ const end = issue.offset + (issue.length || issue.text.length);
52
+ const suggestions = issue.suggestionsEx;
53
+ const severity = issue.isFlagged ? 'Forbidden' : 'Unknown';
54
+ return { word, start, end, suggestions, severity, range, rangeIdx };
55
+ }
56
+ }
57
+ const cache = { lastDoc: undefined };
58
+ const docValCache = new WeakMap();
59
+ function getDocValidator(filename, text, options) {
60
+ const doc = getTextDocument(filename, text);
61
+ const settings = calcInitialSettings(options);
62
+ const cachedValidator = docValCache.get(doc);
63
+ if (cachedValidator && deepEqual(cachedValidator.settings, settings)) {
64
+ refreshDictionaryCache(0);
65
+ cachedValidator.updateDocumentText(text).catch(() => undefined);
66
+ return cachedValidator;
67
+ }
68
+ const resolveImportsRelativeTo = toFileURL(options.cspellOptionsRoot || import.meta.url, toFileDirURL(options.cwd));
69
+ const validator = new DocumentValidator(doc, { ...options, resolveImportsRelativeTo }, settings);
70
+ docValCache.set(doc, validator);
71
+ return validator;
72
+ }
73
+ function calcInitialSettings(options) {
74
+ const { customWordListFile, cspell, cwd } = options;
75
+ const settings = {
76
+ ...defaultSettings,
77
+ ...cspell,
78
+ words: cspell?.words || [],
79
+ ignoreWords: cspell?.ignoreWords || [],
80
+ flagWords: cspell?.flagWords || [],
81
+ };
82
+ if (options.configFile) {
83
+ const optionCspellImport = options.cspell?.import;
84
+ const importConfig = typeof optionCspellImport === 'string'
85
+ ? [optionCspellImport]
86
+ : Array.isArray(optionCspellImport)
87
+ ? optionCspellImport
88
+ : [];
89
+ importConfig.push(options.configFile);
90
+ settings.import = importConfig;
91
+ }
92
+ if (customWordListFile) {
93
+ const filePath = isCustomWordListFile(customWordListFile) ? customWordListFile.path : customWordListFile;
94
+ const { dictionaries = [], dictionaryDefinitions = [] } = settings;
95
+ dictionaries.push('eslint-plugin-custom-words');
96
+ dictionaryDefinitions.push({ name: 'eslint-plugin-custom-words', path: filePath });
97
+ settings.dictionaries = dictionaries;
98
+ settings.dictionaryDefinitions = dictionaryDefinitions;
99
+ }
100
+ resolveDictionaryPaths(settings.dictionaryDefinitions, cwd);
101
+ return settings;
102
+ }
103
+ const regexIsUrl = /^(https?|file|ftp):/i;
104
+ /** Patches the path of dictionary definitions. */
105
+ function resolveDictionaryPaths(defs, cwd) {
106
+ if (!defs)
107
+ return;
108
+ for (const def of defs) {
109
+ if (!def.path)
110
+ continue;
111
+ if (regexIsUrl.test(def.path))
112
+ continue;
113
+ def.path = path.resolve(cwd, def.path);
114
+ }
115
+ }
116
+ function getTextDocument(filename, content) {
117
+ if (cache.lastDoc?.filename === filename) {
118
+ return cache.lastDoc.doc;
119
+ }
120
+ const doc = createTextDocument({ uri: filename, content });
121
+ cache.lastDoc = { filename, doc };
122
+ return doc;
123
+ }
124
+ function isCustomWordListFile(value) {
125
+ return !!value && typeof value === 'object';
126
+ }
127
+ /**
128
+ * Deep Equal check.
129
+ * Note: There are faster methods, but this is called once per file, so speed is not a concern.
130
+ */
131
+ function deepEqual(a, b) {
132
+ try {
133
+ assert.deepStrictEqual(a, b);
134
+ return true;
135
+ }
136
+ catch {
137
+ return false;
138
+ }
139
+ }
140
+ async function reportConfigurationErrors(config, knownConfigErrors) {
141
+ const errors = [];
142
+ const importErrors = extractImportErrors(config);
143
+ importErrors.forEach((ref) => {
144
+ const key = ref.error.toString();
145
+ if (knownConfigErrors.has(key))
146
+ return;
147
+ knownConfigErrors.add(key);
148
+ errors.push(new Error('Configuration Error: \n ' + ref.error.message));
149
+ });
150
+ const dictCollection = await getDictionary(config);
151
+ dictCollection.dictionaries.forEach((dict) => {
152
+ const dictErrors = dict.getErrors?.() || [];
153
+ const msg = `Dictionary Error with (${dict.name})`;
154
+ dictErrors.forEach((error) => {
155
+ const key = msg + error.toString();
156
+ if (knownConfigErrors.has(key))
157
+ return;
158
+ knownConfigErrors.add(key);
159
+ const errMsg = `${msg}: ${error.message}\n Source: ${dict.source}`;
160
+ errors.push(new Error(errMsg));
161
+ });
162
+ });
163
+ return errors;
164
+ }
165
+ //# sourceMappingURL=spellCheck.mjs.map
@@ -1,47 +1,30 @@
1
- // cspell:ignore TSESTree
2
- import assert from 'node:assert';
3
- import * as path from 'node:path';
4
- import { toFileDirURL, toFileURL } from '@cspell/url';
5
- import { createTextDocument, DocumentValidator, extractImportErrors, getDictionary, refreshDictionaryCache, } from 'cspell-lib';
6
- import { getDefaultLogger } from '../common/logger.cjs';
7
- import { defaultCheckedScopes } from './customScopes.mjs';
8
- import { AstPathScope, AstScopeMatcher, astScopeToString, mapNodeToScope, scopeItem } from './scope.mjs';
9
- import { walkTree } from './walkTree.mjs';
10
- const defaultSettings = {
11
- name: 'eslint-configuration-file',
12
- patterns: [
13
- // @todo: be able to use cooked / transformed strings.
14
- // {
15
- // // Do not block unicode escape sequences.
16
- // name: 'js-unicode-escape',
17
- // pattern: /$^/g,
18
- // },
19
- ],
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
20
4
  };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.spellCheckAST = spellCheckAST;
7
+ // cspell:ignore TSESTree
8
+ const node_assert_1 = __importDefault(require("node:assert"));
9
+ const logger_cjs_1 = require("../common/logger.cjs");
10
+ const index_cjs_1 = require("../synckit/index.cjs");
11
+ const customScopes_cjs_1 = require("./customScopes.cjs");
12
+ const scope_cjs_1 = require("./scope.cjs");
13
+ const walkTree_cjs_1 = require("./walkTree.cjs");
14
+ const spellCheck = (0, index_cjs_1.createSyncFn)(require.resolve('./worker.mjs'));
21
15
  const isDebugModeExtended = false;
22
16
  const forceLogging = false;
23
- const knownConfigErrors = new Set();
24
- export async function spellCheck(filename, text, root, options) {
25
- const logger = getDefaultLogger();
17
+ const skipCheck = process.env.CSPELL_ESLINT_SKIP_CHECK || false;
18
+ function spellCheckAST(filename, text, root, options) {
19
+ const logger = (0, logger_cjs_1.getDefaultLogger)();
26
20
  const debugMode = forceLogging || options.debugMode || false;
27
21
  logger.enabled = forceLogging || (options.debugMode ?? (logger.enabled || isDebugModeExtended));
28
22
  const log = logger.log;
29
- const mapScopes = groupScopes([...defaultCheckedScopes, ...(options.checkScope || [])]);
23
+ const mapScopes = groupScopes([...customScopes_cjs_1.defaultCheckedScopes, ...(options.checkScope || [])]);
30
24
  log('options: %o', options);
31
25
  const toIgnore = new Set();
32
26
  const importedIdentifiers = new Set();
33
- const validator = getDocValidator(filename, text, options);
34
- await validator.prepare();
35
- log('Settings: %o', validator.settings);
36
- const errors = [...validator.errors];
37
- const issues = [];
38
- errors.push(...(await checkSettings()));
39
- async function checkSettings() {
40
- const finalSettings = validator.getFinalizedDocSettings();
41
- const found = await reportConfigurationErrors(finalSettings, knownConfigErrors);
42
- found.forEach((err) => (debugMode ? log(err) : log('Error: %s', err.message)));
43
- return found;
44
- }
27
+ const toBeChecked = [];
45
28
  function checkLiteral(path) {
46
29
  const node = path.node;
47
30
  if (node.type !== 'Literal')
@@ -122,19 +105,13 @@ export async function spellCheck(filename, text, root, options) {
122
105
  debugNode(path, node.value);
123
106
  checkNodeText(path, node.value);
124
107
  }
125
- function checkNodeText(path, text) {
108
+ function checkNodeText(path, _text) {
126
109
  const node = path.node;
127
110
  if (!node.range)
128
111
  return;
129
112
  const adj = node.type === 'Literal' ? 1 : 0;
130
113
  const range = [node.range[0] + adj, node.range[1] - adj];
131
- const scope = calcScope(path);
132
- const result = validator.checkText(range, text, scope);
133
- result.forEach((issue) => reportIssue(issue, node));
134
- }
135
- function calcScope(_path) {
136
- // inheritance(node);
137
- return [];
114
+ toBeChecked.push({ range, node });
138
115
  }
139
116
  function isImportIdentifier(node) {
140
117
  const parent = node.parent;
@@ -197,14 +174,12 @@ export async function spellCheck(filename, text, root, options) {
197
174
  function isObjectProperty(node) {
198
175
  return node.parent?.type === 'MemberExpression';
199
176
  }
200
- function reportIssue(issue, node) {
177
+ function reportIssue(issue) {
178
+ const { word, start, end, severity } = issue;
179
+ const node = toBeChecked[issue.rangeIdx].node;
201
180
  const nodeType = node.type;
202
- const word = issue.text;
203
- const start = issue.offset;
204
- const end = issue.offset + (issue.length || issue.text.length);
205
- const suggestions = normalizeSuggestions(issue.suggestionsEx, nodeType);
206
- const severity = issue.isFlagged ? 'Forbidden' : 'Unknown';
207
- issues.push({ word, start, end, nodeType, node, suggestions, severity });
181
+ const suggestions = normalizeSuggestions(issue.suggestions, nodeType);
182
+ return { word, start, end, nodeType, node, suggestions, severity };
208
183
  }
209
184
  const processors = {
210
185
  Line: checkComment,
@@ -217,10 +192,11 @@ export async function spellCheck(filename, text, root, options) {
217
192
  function needToCheckFields(path) {
218
193
  const possibleScopes = mapScopes.get(path.node.type);
219
194
  if (!possibleScopes) {
220
- _dumpNode(path);
195
+ if (debugMode)
196
+ _dumpNode(path);
221
197
  return undefined;
222
198
  }
223
- const scopePath = new AstPathScope(path);
199
+ const scopePath = new scope_cjs_1.AstPathScope(path);
224
200
  const scores = possibleScopes
225
201
  .map(({ scope, check }) => ({ score: scopePath.score(scope), check, scope }))
226
202
  .filter((s) => s.score > 0);
@@ -301,33 +277,38 @@ export async function spellCheck(filename, text, root, options) {
301
277
  return node.parent?.type === 'ExportNamedDeclaration' && node.parent.source === node;
302
278
  }
303
279
  function debugNode(path, value) {
280
+ if (!debugMode)
281
+ return;
304
282
  log(`${inheritanceSummary(path)}: %o`, value);
305
- if (debugMode)
306
- _dumpNode(path);
283
+ _dumpNode(path);
307
284
  }
308
285
  // console.warn('root: %o', root);
309
- walkTree(root, checkNode);
310
- return { issues, errors };
286
+ (0, walkTree_cjs_1.walkTree)(root, checkNode);
287
+ const result = skipCheck
288
+ ? { issues: [] }
289
+ : spellCheck(filename, text, toBeChecked.map((t) => t.range), options);
290
+ const issues = result.issues.map((issue) => reportIssue(issue));
291
+ return { issues, errors: result.errors || [] };
311
292
  }
312
293
  function mapNode(path, key) {
313
294
  const node = path.node;
314
295
  if (node.type === 'Literal') {
315
- return scopeItem(tagLiteral(node));
296
+ return (0, scope_cjs_1.scopeItem)(tagLiteral(node));
316
297
  }
317
298
  if (node.type === 'Block') {
318
299
  const value = typeof node.value === 'string' ? node.value : '';
319
- return scopeItem(value[0] === '*' ? 'Comment.docBlock' : 'Comment.block');
300
+ return (0, scope_cjs_1.scopeItem)(value[0] === '*' ? 'Comment.docBlock' : 'Comment.block');
320
301
  }
321
302
  if (node.type === 'Line') {
322
- return scopeItem('Comment.line');
303
+ return (0, scope_cjs_1.scopeItem)('Comment.line');
323
304
  }
324
- return mapNodeToScope(path, key);
305
+ return (0, scope_cjs_1.mapNodeToScope)(path, key);
325
306
  }
326
307
  function inheritanceSummary(path) {
327
- return astScopeToString(path, ' ', mapNode);
308
+ return (0, scope_cjs_1.astScopeToString)(path, ' ', mapNode);
328
309
  }
329
310
  function tagLiteral(node) {
330
- assert(node.type === 'Literal');
311
+ (0, node_assert_1.default)(node.type === 'Literal');
331
312
  const kind = typeof node.value;
332
313
  const extra = kind === 'string'
333
314
  ? asStr(node.raw)?.[0] === '"'
@@ -338,76 +319,6 @@ function tagLiteral(node) {
338
319
  : kind;
339
320
  return node.type + '.' + extra;
340
321
  }
341
- const cache = { lastDoc: undefined };
342
- const docValCache = new WeakMap();
343
- function getDocValidator(filename, text, options) {
344
- const doc = getTextDocument(filename, text);
345
- const settings = calcInitialSettings(options);
346
- const cachedValidator = docValCache.get(doc);
347
- if (cachedValidator && deepEqual(cachedValidator.settings, settings)) {
348
- refreshDictionaryCache(0);
349
- cachedValidator.updateDocumentText(text).catch(() => undefined);
350
- return cachedValidator;
351
- }
352
- const resolveImportsRelativeTo = toFileURL(options.cspellOptionsRoot || import.meta.url, toFileDirURL(options.cwd));
353
- const validator = new DocumentValidator(doc, { ...options, resolveImportsRelativeTo }, settings);
354
- docValCache.set(doc, validator);
355
- return validator;
356
- }
357
- function calcInitialSettings(options) {
358
- const { customWordListFile, cspell, cwd } = options;
359
- const settings = {
360
- ...defaultSettings,
361
- ...cspell,
362
- words: cspell?.words || [],
363
- ignoreWords: cspell?.ignoreWords || [],
364
- flagWords: cspell?.flagWords || [],
365
- };
366
- if (options.configFile) {
367
- const optionCspellImport = options.cspell?.import;
368
- const importConfig = typeof optionCspellImport === 'string'
369
- ? [optionCspellImport]
370
- : Array.isArray(optionCspellImport)
371
- ? optionCspellImport
372
- : [];
373
- importConfig.push(options.configFile);
374
- settings.import = importConfig;
375
- }
376
- if (customWordListFile) {
377
- const filePath = isCustomWordListFile(customWordListFile) ? customWordListFile.path : customWordListFile;
378
- const { dictionaries = [], dictionaryDefinitions = [] } = settings;
379
- dictionaries.push('eslint-plugin-custom-words');
380
- dictionaryDefinitions.push({ name: 'eslint-plugin-custom-words', path: filePath });
381
- settings.dictionaries = dictionaries;
382
- settings.dictionaryDefinitions = dictionaryDefinitions;
383
- }
384
- resolveDictionaryPaths(settings.dictionaryDefinitions, cwd);
385
- return settings;
386
- }
387
- const regexIsUrl = /^(https?|file|ftp):/i;
388
- /** Patches the path of dictionary definitions. */
389
- function resolveDictionaryPaths(defs, cwd) {
390
- if (!defs)
391
- return;
392
- for (const def of defs) {
393
- if (!def.path)
394
- continue;
395
- if (regexIsUrl.test(def.path))
396
- continue;
397
- def.path = path.resolve(cwd, def.path);
398
- }
399
- }
400
- function getTextDocument(filename, content) {
401
- if (cache.lastDoc?.filename === filename) {
402
- return cache.lastDoc.doc;
403
- }
404
- const doc = createTextDocument({ uri: filename, content });
405
- cache.lastDoc = { filename, doc };
406
- return doc;
407
- }
408
- function isCustomWordListFile(value) {
409
- return !!value && typeof value === 'object';
410
- }
411
322
  const needToAdjustSpace = {
412
323
  Identifier: true,
413
324
  };
@@ -429,49 +340,11 @@ function normalizeSuggestions(suggestions, nodeType) {
429
340
  return s;
430
341
  });
431
342
  }
432
- /**
433
- * Deep Equal check.
434
- * Note: There are faster methods, but this is called once per file, so speed is not a concern.
435
- */
436
- function deepEqual(a, b) {
437
- try {
438
- assert.deepStrictEqual(a, b);
439
- return true;
440
- }
441
- catch {
442
- return false;
443
- }
444
- }
445
- async function reportConfigurationErrors(config, knownConfigErrors) {
446
- const errors = [];
447
- const importErrors = extractImportErrors(config);
448
- importErrors.forEach((ref) => {
449
- const key = ref.error.toString();
450
- if (knownConfigErrors.has(key))
451
- return;
452
- knownConfigErrors.add(key);
453
- errors.push(new Error('Configuration Error: \n ' + ref.error.message));
454
- });
455
- const dictCollection = await getDictionary(config);
456
- dictCollection.dictionaries.forEach((dict) => {
457
- const dictErrors = dict.getErrors?.() || [];
458
- const msg = `Dictionary Error with (${dict.name})`;
459
- dictErrors.forEach((error) => {
460
- const key = msg + error.toString();
461
- if (knownConfigErrors.has(key))
462
- return;
463
- knownConfigErrors.add(key);
464
- const errMsg = `${msg}: ${error.message}\n Source: ${dict.source}`;
465
- errors.push(new Error(errMsg));
466
- });
467
- });
468
- return errors;
469
- }
470
343
  function groupScopes(scopes) {
471
344
  const objScopes = Object.fromEntries(scopes);
472
345
  const map = new Map();
473
346
  for (const [selector, check] of Object.entries(objScopes)) {
474
- const scope = AstScopeMatcher.fromScopeSelector(selector);
347
+ const scope = scope_cjs_1.AstScopeMatcher.fromScopeSelector(selector);
475
348
  const key = scope.scopeType();
476
349
  const list = map.get(key) || [];
477
350
  list.push({ scope, check });
@@ -482,4 +355,4 @@ function groupScopes(scopes) {
482
355
  function asStr(v) {
483
356
  return typeof v === 'string' ? v : undefined;
484
357
  }
485
- //# sourceMappingURL=spellCheck.mjs.map
358
+ //# sourceMappingURL=spellCheckAST.cjs.map
@@ -0,0 +1,5 @@
1
+ import type { Node } from 'estree';
2
+ import type { WorkerOptions } from '../common/options.cjs';
3
+ import type { SpellCheckResults } from './types.js' with { 'resolution-mode': 'import' };
4
+ export declare function spellCheckAST(filename: string, text: string, root: Node, options: WorkerOptions): SpellCheckResults;
5
+ //# sourceMappingURL=spellCheckAST.d.cts.map
@@ -1,6 +1,4 @@
1
- import type { Node } from 'estree';
2
- import type { WorkerOptions } from '../common/options.cjs';
3
- import type { ASTNode, NodeType } from './ASTNode.mjs';
1
+ import type { ASTNode, NodeType } from './ASTNode.js';
4
2
  interface ExtendedSuggestion {
5
3
  /**
6
4
  * The suggestion.
@@ -29,7 +27,5 @@ export interface SpellCheckResults {
29
27
  issues: Issue[];
30
28
  errors?: Error[];
31
29
  }
32
- export type SpellCheckFn = (filename: string, text: string, root: Node, options: WorkerOptions) => Promise<SpellCheckResults>;
33
- export type SpellCheckSyncFn = (...p: Parameters<SpellCheckFn>) => Awaited<ReturnType<SpellCheckFn>>;
34
30
  export {};
35
- //# sourceMappingURL=types.d.mts.map
31
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -1,6 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.walkTree = walkTree;
1
4
  // const logger = getDefaultLogger();
2
5
  // const log = logger.log;
3
- export function walkTree(node, enter) {
6
+ const debugMode = false;
7
+ function walkTree(node, enter) {
4
8
  const visited = new Set();
5
9
  let pathNode = undefined;
6
10
  function adjustPath(n) {
@@ -26,12 +30,13 @@ export function walkTree(node, enter) {
26
30
  return false;
27
31
  }
28
32
  visited.add(node);
29
- const path = adjustPath({ node, parent: parent, key, index, prev: undefined });
33
+ const path = adjustPath({ node, parent, key, index, prev: undefined });
30
34
  enter(path);
31
35
  return true;
32
36
  });
33
37
  }
34
38
  function walk(root, enter) {
39
+ const useFx = debugMode ? '' : 'walkNodes';
35
40
  function walkNodes(pfx, node, parent, key, index) {
36
41
  const goIn = enter({ node, parent, key, index });
37
42
  // log('walk: %o', { pfx, type: node.type, key, index, goIn });
@@ -40,7 +45,7 @@ function walk(root, enter) {
40
45
  const n = node;
41
46
  for (const key of Object.keys(n)) {
42
47
  const v = n[key];
43
- const fx = pfx + `.${node.type}[${key}]`;
48
+ const fx = useFx || pfx + `.${node.type}[${key}]`;
44
49
  if (Array.isArray(v)) {
45
50
  for (let i = 0; i < v.length; ++i) {
46
51
  const vv = v[i];
@@ -63,4 +68,4 @@ function isNode(node) {
63
68
  const n = node;
64
69
  return (typeof n === 'object' && typeof n['type'] === 'string') || false;
65
70
  }
66
- //# sourceMappingURL=walkTree.mjs.map
71
+ //# sourceMappingURL=walkTree.cjs.map
@@ -0,0 +1,4 @@
1
+ import type { ASTNode } from './ASTNode.js' with { 'resolution-mode': 'import' };
2
+ import type { ASTPath } from './ASTPath.js' with { 'resolution-mode': 'import' };
3
+ export declare function walkTree(node: ASTNode, enter: (path: ASTPath) => void): void;
4
+ //# sourceMappingURL=walkTree.d.cts.map
@@ -0,0 +1,9 @@
1
+ import { runAsWorker } from 'synckit';
2
+ let spellChecker;
3
+ runAsWorker(async (filename, text, ranges, options) => {
4
+ if (!spellChecker) {
5
+ spellChecker = await import('./spellCheck.mjs');
6
+ }
7
+ return spellChecker.spellCheck(filename, text, ranges, options);
8
+ });
9
+ //# sourceMappingURL=worker.mjs.map
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createSyncFn = createSyncFn;
4
+ const synckit_1 = require("synckit");
5
+ function createSyncFn(workerPath, timeoutOrOptions) {
6
+ return (0, synckit_1.createSyncFn)(workerPath, timeoutOrOptions);
7
+ }
8
+ // cspell:ignore Syncify
9
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1,6 @@
1
+ type AnyFn = (...args: any[]) => any;
2
+ type Syncify<T extends AnyFn> = (...args: Parameters<T>) => Awaited<ReturnType<T>>;
3
+ export type CreateSyncFn<T extends AnyFn> = (workerPath: URL | string, timeoutOrOptions?: number) => Syncify<T>;
4
+ export declare function createSyncFn<T extends AnyFn>(workerPath: URL | string, timeoutOrOptions?: number): Syncify<T>;
5
+ export {};
6
+ //# sourceMappingURL=index.d.cts.map
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "access": "public",
5
5
  "provenance": true
6
6
  },
7
- "version": "8.19.1",
7
+ "version": "8.19.2",
8
8
  "description": "CSpell ESLint plugin",
9
9
  "keywords": [
10
10
  "cspell",
@@ -43,7 +43,6 @@
43
43
  "main": "dist/plugin/index.cjs",
44
44
  "types": "dist/plugin/index.d.cts",
45
45
  "files": [
46
- "assets",
47
46
  "dist",
48
47
  "!**/__mocks__",
49
48
  "!**/*.spec.*",
@@ -57,7 +56,6 @@
57
56
  "build": "pnpm build:schema && pnpm build:src",
58
57
  "build:src": "tsc -b ./tsconfig.json -f",
59
58
  "build:schema": "pnpm build-options-schema",
60
- "build:schema:old": "ts-json-schema-generator --no-top-ref --expose none --path src/common/options.cts --type Options -o ./assets/options.schema.json",
61
59
  "watch": "tsc -b ./tsconfig.json --watch -f",
62
60
  "clean": "shx rm -rf dist temp coverage \"*.tsbuildInfo\"",
63
61
  "clean-build": "pnpm run clean && pnpm run build",
@@ -81,13 +79,13 @@
81
79
  },
82
80
  "devDependencies": {
83
81
  "@eslint/eslintrc": "^3.3.1",
84
- "@eslint/js": "^9.24.0",
82
+ "@eslint/js": "^9.25.0",
85
83
  "@internal/cspell-eslint-plugin-scripts": "",
86
84
  "@types/estree": "^1.0.7",
87
85
  "@types/mocha": "^10.0.10",
88
86
  "@typescript-eslint/parser": "^8.30.1",
89
87
  "@typescript-eslint/types": "^8.30.1",
90
- "eslint": "^9.24.0",
88
+ "eslint": "^9.25.0",
91
89
  "eslint-plugin-jsonc": "^2.20.0",
92
90
  "eslint-plugin-mdx": "^3.4.0",
93
91
  "eslint-plugin-n": "^17.17.0",
@@ -103,13 +101,13 @@
103
101
  "yaml-eslint-parser": "^1.3.0"
104
102
  },
105
103
  "dependencies": {
106
- "@cspell/cspell-types": "8.19.1",
107
- "@cspell/url": "8.19.1",
108
- "cspell-lib": "8.19.1",
104
+ "@cspell/cspell-types": "8.19.2",
105
+ "@cspell/url": "8.19.2",
106
+ "cspell-lib": "8.19.2",
109
107
  "synckit": "^0.11.4"
110
108
  },
111
109
  "peerDependencies": {
112
110
  "eslint": "^7 || ^8 || ^9"
113
111
  },
114
- "gitHead": "66fdb8ff1cfb93b5c90c93ad7fbbcc91df39cc2b"
112
+ "gitHead": "f630ececa8cd91420aaaaa81c4ad910039457a06"
115
113
  }
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=ASTNode.mjs.map
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=ASTPath.mjs.map
@@ -1,5 +0,0 @@
1
- import type { Node } from 'estree';
2
- import type { WorkerOptions } from '../common/options.cjs';
3
- import type { SpellCheckResults } from './types.mjs';
4
- export declare function spellCheck(filename: string, text: string, root: Node, options: WorkerOptions): Promise<SpellCheckResults>;
5
- //# sourceMappingURL=spellCheck.d.mts.map
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=types.mjs.map
@@ -1,4 +0,0 @@
1
- import type { ASTNode } from './ASTNode.mjs';
2
- import type { ASTPath } from './ASTPath.mjs';
3
- export declare function walkTree(node: ASTNode, enter: (path: ASTPath) => void): void;
4
- //# sourceMappingURL=walkTree.d.mts.map
@@ -1,9 +0,0 @@
1
- import { runAsWorker } from 'synckit';
2
- let spellChecker;
3
- runAsWorker(async (filename, text, root, options) => {
4
- if (!spellChecker) {
5
- spellChecker = await import('./spellCheck.mjs');
6
- }
7
- return spellChecker.spellCheck(filename, text, root, options);
8
- });
9
- //# sourceMappingURL=worker.mjs.map
File without changes