cspell-lib 8.14.1 → 8.14.3
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/dist/lib/Models/CSpellSettingsInternalDef.js +6 -9
- package/dist/lib/Settings/CSpellSettingsServer.d.ts +1 -1
- package/dist/lib/Settings/CSpellSettingsServer.js +10 -10
- package/dist/lib/Settings/InDocSettings.d.ts +22 -7
- package/dist/lib/Settings/InDocSettings.js +96 -63
- package/dist/lib/Settings/InDocSettings.perf.d.ts +2 -0
- package/dist/lib/Settings/InDocSettings.perf.js +73 -0
- package/dist/lib/Settings/RegExpPatterns.d.ts +6 -2
- package/dist/lib/Settings/RegExpPatterns.js +7 -3
- package/dist/lib/Settings/TextDocumentSettings.js +2 -1
- package/dist/lib/Settings/resolveCwd.d.ts +7 -0
- package/dist/lib/Settings/resolveCwd.js +28 -0
- package/dist/lib/textValidation/determineTextDocumentSettings.js +2 -2
- package/package.json +21 -20
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
import { clean } from '../util/util.js';
|
|
2
2
|
export const SymbolCSpellSettingsInternal = Symbol('CSpellSettingsInternal');
|
|
3
|
-
export function cleanCSpellSettingsInternal(parts
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
export function cleanCSpellSettingsInternal(parts) {
|
|
4
|
+
return parts
|
|
5
|
+
? Object.assign(clean(parts), { [SymbolCSpellSettingsInternal]: true })
|
|
6
|
+
: { [SymbolCSpellSettingsInternal]: true };
|
|
7
7
|
}
|
|
8
|
-
export function createCSpellSettingsInternal(parts
|
|
9
|
-
return
|
|
10
|
-
...parts,
|
|
11
|
-
[SymbolCSpellSettingsInternal]: true,
|
|
12
|
-
});
|
|
8
|
+
export function createCSpellSettingsInternal(parts) {
|
|
9
|
+
return cleanCSpellSettingsInternal({ ...parts });
|
|
13
10
|
}
|
|
14
11
|
export function isCSpellSettingsInternal(cs) {
|
|
15
12
|
return !!cs[SymbolCSpellSettingsInternal];
|
|
@@ -10,7 +10,7 @@ declare function mergeObjects<T>(left: T, right: undefined): T;
|
|
|
10
10
|
declare function mergeObjects<T>(left: T, right: T): T;
|
|
11
11
|
declare function mergeObjects<T>(left: undefined, right: T): T;
|
|
12
12
|
export declare function mergeSettings(left: CSpellSettingsWSTO | CSpellSettingsI, ...settings: (CSpellSettingsWSTO | CSpellSettingsI | undefined)[]): CSpellSettingsI;
|
|
13
|
-
export declare function mergeInDocSettings(left: CSpellSettingsWSTO,
|
|
13
|
+
export declare function mergeInDocSettings(left: CSpellSettingsWSTO, ...rest: CSpellSettingsWSTO[]): CSpellSettingsWST;
|
|
14
14
|
/**
|
|
15
15
|
*
|
|
16
16
|
* @param settings - settings to finalize
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import assert from 'node:assert';
|
|
2
|
-
import { pathToFileURL } from 'node:url';
|
|
3
2
|
import { onClearCache } from '../events/index.js';
|
|
4
3
|
import { cleanCSpellSettingsInternal as csi, isCSpellSettingsInternal } from '../Models/CSpellSettingsInternalDef.js';
|
|
5
4
|
import { autoResolveWeak, AutoResolveWeakCache } from '../util/AutoResolve.js';
|
|
@@ -9,6 +8,7 @@ import { configSettingsFileVersion0_1, ENV_CSPELL_GLOB_ROOT } from './constants.
|
|
|
9
8
|
import { calcDictionaryDefsToLoad, mapDictDefsToInternal } from './DictionarySettings.js';
|
|
10
9
|
import { mergeList, mergeListUnique } from './mergeList.js';
|
|
11
10
|
import { resolvePatterns } from './patterns.js';
|
|
11
|
+
import { CwdUrlResolver } from './resolveCwd.js';
|
|
12
12
|
export { stats as getMergeStats } from './mergeList.js';
|
|
13
13
|
const emptyWords = [];
|
|
14
14
|
Object.freeze(emptyWords);
|
|
@@ -17,12 +17,16 @@ const mergeCache = new AutoResolveWeakCache();
|
|
|
17
17
|
const cacheInternalSettings = new AutoResolveWeakCache();
|
|
18
18
|
const parserCache = new AutoResolveWeakCache();
|
|
19
19
|
const emptyParserMap = new Map();
|
|
20
|
+
const cwdResolver = new CwdUrlResolver();
|
|
21
|
+
let envCSpellGlobRoot = process.env[ENV_CSPELL_GLOB_ROOT];
|
|
20
22
|
onClearCache(() => {
|
|
21
23
|
parserCache.clear();
|
|
22
24
|
emptyParserMap.clear();
|
|
23
25
|
cachedMerges.clear();
|
|
24
26
|
mergeCache.clear();
|
|
25
27
|
cacheInternalSettings.clear();
|
|
28
|
+
cwdResolver.reset();
|
|
29
|
+
envCSpellGlobRoot = process.env[ENV_CSPELL_GLOB_ROOT];
|
|
26
30
|
});
|
|
27
31
|
function _mergeWordsCached(left, right) {
|
|
28
32
|
const map = autoResolveWeak(cachedMerges, left, () => new WeakMap());
|
|
@@ -154,11 +158,8 @@ function hasAncestor(s, ancestor, side) {
|
|
|
154
158
|
const src = sources[i];
|
|
155
159
|
return src === ancestor || (src && hasAncestor(src, ancestor, side)) || false;
|
|
156
160
|
}
|
|
157
|
-
export function mergeInDocSettings(left,
|
|
158
|
-
const merged =
|
|
159
|
-
...mergeSettings(left, right),
|
|
160
|
-
includeRegExpList: mergeListUnique(left.includeRegExpList, right.includeRegExpList),
|
|
161
|
-
};
|
|
161
|
+
export function mergeInDocSettings(left, ...rest) {
|
|
162
|
+
const merged = mergeSettings(left, ...rest);
|
|
162
163
|
return util.clean(merged);
|
|
163
164
|
}
|
|
164
165
|
function takeRightOtherwiseLeft(left, right) {
|
|
@@ -197,7 +198,8 @@ export function toInternalSettings(settings) {
|
|
|
197
198
|
}
|
|
198
199
|
function _toInternalSettings(settings) {
|
|
199
200
|
const { dictionaryDefinitions: defs, ...rest } = settings;
|
|
200
|
-
const dictionaryDefinitions =
|
|
201
|
+
const dictionaryDefinitions = defs &&
|
|
202
|
+
mapDictDefsToInternal(defs, (settings.source?.filename && toFileUrl(settings.source?.filename)) || resolveCwd());
|
|
201
203
|
const setting = dictionaryDefinitions ? { ...rest, dictionaryDefinitions } : rest;
|
|
202
204
|
return csi(setting);
|
|
203
205
|
}
|
|
@@ -260,9 +262,7 @@ export function extractDependencies(settings) {
|
|
|
260
262
|
};
|
|
261
263
|
}
|
|
262
264
|
function resolveCwd() {
|
|
263
|
-
|
|
264
|
-
const cwd = envGlobRoot || process.cwd();
|
|
265
|
-
return pathToFileURL(cwd);
|
|
265
|
+
return cwdResolver.resolveUrl(envCSpellGlobRoot);
|
|
266
266
|
}
|
|
267
267
|
function resolveParser(settings) {
|
|
268
268
|
if (!settings.parser)
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { CSpellUserSettings, DictionaryDefinitionInline } from '@cspell/cspell-types';
|
|
2
|
-
import type { Sequence } from 'gensequence';
|
|
3
2
|
import type { ExtendedSuggestion } from '../Models/Suggestion.js';
|
|
4
3
|
export type CSpellUserSettingsKeys = keyof CSpellUserSettings;
|
|
5
4
|
export interface DirectiveIssue {
|
|
@@ -15,16 +14,31 @@ export interface DirectiveIssue {
|
|
|
15
14
|
suggestions: string[];
|
|
16
15
|
suggestionsEx: ExtendedSuggestion[];
|
|
17
16
|
}
|
|
17
|
+
declare function collectInDocumentDirectives(text: string): DirectiveMatchWithParser[];
|
|
18
18
|
export declare function getInDocumentSettings(text: string): CSpellUserSettings;
|
|
19
19
|
export declare function validateInDocumentSettings(docText: string, _settings: CSpellUserSettings): Iterable<DirectiveIssue>;
|
|
20
|
+
interface PossibleMatch {
|
|
21
|
+
/** The full directive text till the end of the line */
|
|
22
|
+
fullDirective: string;
|
|
23
|
+
/** Offset of the directive */
|
|
24
|
+
offset: number;
|
|
25
|
+
/** the partial directive, missing the CSpell prefix. */
|
|
26
|
+
match: string;
|
|
27
|
+
}
|
|
28
|
+
type Directive = 'CompoundWords' | 'CaseSensitive' | 'Enable' | 'Disable' | 'Words' | 'Ignore' | 'Flag' | 'IgnoreRegExp' | 'IncludeRegExp' | 'Locale' | 'Dictionaries';
|
|
29
|
+
type ReducerFn = (acc: CSpellUserSettings, match: string) => CSpellUserSettings;
|
|
30
|
+
interface DirectiveMatchWithParser extends PossibleMatch {
|
|
31
|
+
directive: Directive;
|
|
32
|
+
fn: ReducerFn;
|
|
33
|
+
}
|
|
20
34
|
export declare const regExSpellingGuardBlock: RegExp;
|
|
21
35
|
export declare const regExSpellingGuardNext: RegExp;
|
|
22
36
|
export declare const regExSpellingGuardLine: RegExp;
|
|
23
|
-
declare function parseCompoundWords(match: string): CSpellUserSettings;
|
|
24
|
-
declare function parseWords(match: string): CSpellUserSettings;
|
|
25
|
-
declare function parseIgnoreWords(match: string): CSpellUserSettings;
|
|
26
|
-
declare function parseIgnoreRegExp(match: string): CSpellUserSettings;
|
|
27
|
-
declare function getPossibleInDocSettings(text: string):
|
|
37
|
+
declare function parseCompoundWords(acc: CSpellUserSettings, match: string): CSpellUserSettings;
|
|
38
|
+
declare function parseWords(acc: CSpellUserSettings, match: string): CSpellUserSettings;
|
|
39
|
+
declare function parseIgnoreWords(acc: CSpellUserSettings, match: string): CSpellUserSettings;
|
|
40
|
+
declare function parseIgnoreRegExp(acc: CSpellUserSettings, match: string): CSpellUserSettings;
|
|
41
|
+
declare function getPossibleInDocSettings(text: string): Iterable<PossibleMatch>;
|
|
28
42
|
declare function getWordsFromDocument(text: string): string[];
|
|
29
43
|
export declare function extractInDocDictionary(settings: CSpellUserSettings): DictionaryDefinitionInline | undefined;
|
|
30
44
|
export declare function getIgnoreWordsFromDocument(text: string): string[];
|
|
@@ -32,7 +46,8 @@ export declare function getIgnoreRegExpFromDocument(text: string): (string | Reg
|
|
|
32
46
|
/**
|
|
33
47
|
* These internal functions are used exposed for unit testing.
|
|
34
48
|
*/
|
|
35
|
-
export declare const
|
|
49
|
+
export declare const __internal: {
|
|
50
|
+
collectInDocumentSettings: typeof collectInDocumentDirectives;
|
|
36
51
|
getPossibleInDocSettings: typeof getPossibleInDocSettings;
|
|
37
52
|
getWordsFromDocument: typeof getWordsFromDocument;
|
|
38
53
|
parseWords: typeof parseWords;
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import { opAppend, opFilter, opMap, pipeSync } from '@cspell/cspell-pipe/sync';
|
|
2
|
-
import { genSequence } from 'gensequence';
|
|
1
|
+
import { opAppend, opFilter, opFlatten, opMap, pipeSync } from '@cspell/cspell-pipe/sync';
|
|
3
2
|
import { createSpellingDictionary } from '../SpellingDictionary/index.js';
|
|
4
3
|
import * as Text from '../util/text.js';
|
|
5
4
|
import { clean, isDefined } from '../util/util.js';
|
|
6
|
-
import { mergeInDocSettings } from './CSpellSettingsServer.js';
|
|
7
5
|
// cspell:ignore gimuy
|
|
8
6
|
const regExMatchRegEx = /\/.*\/[gimuy]*/;
|
|
9
7
|
const regExCSpellInDocDirective = /\b(?:spell-?checker|c?spell)::?(.*)/gi;
|
|
@@ -67,12 +65,17 @@ const dictInDocSettings = createSpellingDictionary(allDirectives, 'Directives',
|
|
|
67
65
|
const EmptyWords = [];
|
|
68
66
|
Object.freeze(EmptyWords);
|
|
69
67
|
const staticInDocumentDictionaryName = `[in-document-dict]`;
|
|
68
|
+
function collectInDocumentDirectives(text) {
|
|
69
|
+
const dirs = [...getPossibleInDocSettings(text)].flatMap((a) => associateDirectivesWithParsers(a));
|
|
70
|
+
return dirs;
|
|
71
|
+
}
|
|
72
|
+
const baseInDocSettings = { id: 'in-doc-settings' };
|
|
73
|
+
Object.freeze(baseInDocSettings);
|
|
70
74
|
export function getInDocumentSettings(text) {
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}, { id: 'in-doc-settings' });
|
|
75
|
+
const found = collectInDocumentDirectives(text);
|
|
76
|
+
if (!found.length)
|
|
77
|
+
return { ...baseInDocSettings };
|
|
78
|
+
const collectedSettings = reducePossibleMatchesToSettings(found, { ...baseInDocSettings });
|
|
76
79
|
const { words, flagWords, ignoreWords, suggestWords, dictionaries = [], dictionaryDefinitions = [], ...rest } = collectedSettings;
|
|
77
80
|
const dict = (words || flagWords || ignoreWords || suggestWords) &&
|
|
78
81
|
clean({
|
|
@@ -95,44 +98,42 @@ export function getInDocumentSettings(text) {
|
|
|
95
98
|
...rest,
|
|
96
99
|
...dictSettings,
|
|
97
100
|
};
|
|
98
|
-
// console.log('InDocSettings: %o', settings);
|
|
99
101
|
return settings;
|
|
100
102
|
}
|
|
101
103
|
export function validateInDocumentSettings(docText, _settings) {
|
|
102
104
|
return pipeSync(getPossibleInDocSettings(docText), opMap(parseSettingMatchValidation), opFilter(isDefined));
|
|
103
105
|
}
|
|
104
106
|
const settingParsers = [
|
|
105
|
-
[/^(?:enable|disable)(?:allow)?CompoundWords\b(?!-)/i, parseCompoundWords],
|
|
106
|
-
[/^(?:enable|disable)CaseSensitive\b(?!-)/i, parseCaseSensitive],
|
|
107
|
-
[/^enable\b(?!-)/i, parseEnable],
|
|
108
|
-
[/^disable(-line|-next(-line)?)?\b(?!-)/i, parseDisable],
|
|
109
|
-
[/^words?\b(?!-)/i, parseWords],
|
|
110
|
-
[/^ignore(?:-?words?)?\b(?!-)/i, parseIgnoreWords],
|
|
111
|
-
[/^(?:flag|forbid)(?:-?words?)?\b(?!-)/i, parseFlagWords],
|
|
112
|
-
[/^ignore_?Reg_?Exp\s+.+$/i, parseIgnoreRegExp],
|
|
113
|
-
[/^include_?Reg_?Exp\s+.+$/i, parseIncludeRegExp],
|
|
114
|
-
[/^locale?\b(?!-)/i, parseLocale],
|
|
115
|
-
[/^language\s\b(?!-)/i, parseLocale],
|
|
116
|
-
[/^dictionar(?:y|ies)\b(?!-)/i, parseDictionaries], // cspell:disable-line
|
|
117
|
-
[/^LocalWords:/, (
|
|
107
|
+
[/^(?:enable|disable)(?:allow)?CompoundWords\b(?!-)/i, parseCompoundWords, 'CompoundWords'],
|
|
108
|
+
[/^(?:enable|disable)CaseSensitive\b(?!-)/i, parseCaseSensitive, 'CaseSensitive'],
|
|
109
|
+
[/^enable\b(?!-)/i, parseEnable, 'Enable'],
|
|
110
|
+
[/^disable(-line|-next(-line)?)?\b(?!-)/i, parseDisable, 'Disable'],
|
|
111
|
+
[/^words?\b(?!-)/i, parseWords, 'Words'],
|
|
112
|
+
[/^ignore(?:-?words?)?\b(?!-)/i, parseIgnoreWords, 'Ignore'],
|
|
113
|
+
[/^(?:flag|forbid)(?:-?words?)?\b(?!-)/i, parseFlagWords, 'Flag'],
|
|
114
|
+
[/^ignore_?Reg_?Exp\s+.+$/i, parseIgnoreRegExp, 'IgnoreRegExp'],
|
|
115
|
+
[/^include_?Reg_?Exp\s+.+$/i, parseIncludeRegExp, 'IncludeRegExp'],
|
|
116
|
+
[/^locale?\b(?!-)/i, parseLocale, 'Locale'],
|
|
117
|
+
[/^language\s\b(?!-)/i, parseLocale, 'Locale'],
|
|
118
|
+
[/^dictionar(?:y|ies)\b(?!-)/i, parseDictionaries, 'Dictionaries'], // cspell:disable-line
|
|
119
|
+
[/^LocalWords:/, (acc, m) => reduceWordList(acc, m.replaceAll(/^LocalWords:?/gi, ' '), 'words'), 'Words'],
|
|
118
120
|
];
|
|
119
121
|
export const regExSpellingGuardBlock = /(\bc?spell(?:-?checker)?::?)\s*disable(?!-line|-next)\b[\s\S]*?((?:\1\s*enable\b)|$)/gi;
|
|
120
122
|
export const regExSpellingGuardNext = /\bc?spell(?:-?checker)?::?\s*disable-next\b.*\s\s?.*/gi;
|
|
121
123
|
export const regExSpellingGuardLine = /^.*\bc?spell(?:-?checker)?::?\s*disable-line\b.*/gim;
|
|
122
|
-
const emptySettings = Object.freeze({});
|
|
123
124
|
const issueMessages = {
|
|
124
125
|
unknownDirective: 'Unknown CSpell directive',
|
|
125
126
|
};
|
|
126
|
-
function parseSettingMatchValidation(
|
|
127
|
-
const
|
|
128
|
-
const directiveMatch =
|
|
127
|
+
function parseSettingMatchValidation(possibleMatch) {
|
|
128
|
+
const { fullDirective, offset } = possibleMatch;
|
|
129
|
+
const directiveMatch = fullDirective.match(regExCSpellDirectiveKey);
|
|
129
130
|
if (!directiveMatch)
|
|
130
131
|
return undefined;
|
|
131
132
|
const match = directiveMatch[1];
|
|
132
133
|
const possibleSetting = match.trim();
|
|
133
134
|
if (!possibleSetting)
|
|
134
135
|
return undefined;
|
|
135
|
-
const start =
|
|
136
|
+
const start = offset + (directiveMatch.index || 0) + (match.length - match.trimStart().length);
|
|
136
137
|
const text = possibleSetting.replace(/^([-\w]+)?.*/, '$1');
|
|
137
138
|
const end = start + text.length;
|
|
138
139
|
if (!text)
|
|
@@ -167,44 +168,66 @@ function* filterUniqueSuggestions(sugs) {
|
|
|
167
168
|
yield sug;
|
|
168
169
|
}
|
|
169
170
|
}
|
|
170
|
-
function
|
|
171
|
-
const
|
|
171
|
+
function associateDirectivesWithParsers(possibleMatch) {
|
|
172
|
+
const { match } = possibleMatch;
|
|
172
173
|
const possibleSetting = match.trim();
|
|
173
174
|
return settingParsers
|
|
174
175
|
.filter(([regex]) => regex.test(possibleSetting))
|
|
175
|
-
.map(([, fn]) => fn)
|
|
176
|
-
|
|
176
|
+
.map(([, fn, directive]) => ({ ...possibleMatch, directive, fn }));
|
|
177
|
+
}
|
|
178
|
+
function mergeDirectiveIntoSettings(settings, directive) {
|
|
179
|
+
return directive.fn(settings, directive.match);
|
|
177
180
|
}
|
|
178
|
-
function
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
+
function reducePossibleMatchesToSettings(directives, settings) {
|
|
182
|
+
for (const directive of directives) {
|
|
183
|
+
settings = mergeDirectiveIntoSettings(settings, directive);
|
|
184
|
+
}
|
|
185
|
+
return settings;
|
|
181
186
|
}
|
|
182
|
-
function
|
|
183
|
-
|
|
184
|
-
return
|
|
187
|
+
function parseCompoundWords(acc, match) {
|
|
188
|
+
acc.allowCompoundWords = /enable/i.test(match);
|
|
189
|
+
return acc;
|
|
185
190
|
}
|
|
186
|
-
function
|
|
187
|
-
|
|
188
|
-
|
|
191
|
+
function parseCaseSensitive(acc, match) {
|
|
192
|
+
acc.caseSensitive = /enable/i.test(match);
|
|
193
|
+
return acc;
|
|
194
|
+
}
|
|
195
|
+
function splitWords(match) {
|
|
196
|
+
return match
|
|
189
197
|
.split(/[,\s;]+/g)
|
|
190
198
|
.slice(1)
|
|
191
199
|
.filter((a) => !!a);
|
|
192
|
-
return { words };
|
|
193
200
|
}
|
|
194
|
-
function
|
|
201
|
+
function mergeList(a, b) {
|
|
202
|
+
if (!a)
|
|
203
|
+
return b;
|
|
204
|
+
if (!b)
|
|
205
|
+
return a;
|
|
206
|
+
return [...a, ...b];
|
|
207
|
+
}
|
|
208
|
+
function reduceWordList(acc, match, key) {
|
|
209
|
+
const words = splitWords(match);
|
|
210
|
+
if (words.length) {
|
|
211
|
+
acc[key] = mergeList(acc[key], words);
|
|
212
|
+
}
|
|
213
|
+
return acc;
|
|
214
|
+
}
|
|
215
|
+
function parseWords(acc, match) {
|
|
216
|
+
return reduceWordList(acc, match, 'words');
|
|
217
|
+
}
|
|
218
|
+
function parseLocale(acc, match) {
|
|
195
219
|
const parts = match.trim().split(/[\s,]+/);
|
|
196
220
|
const language = parts.slice(1).join(',');
|
|
197
|
-
|
|
221
|
+
if (language) {
|
|
222
|
+
acc.language = language;
|
|
223
|
+
}
|
|
224
|
+
return acc;
|
|
198
225
|
}
|
|
199
|
-
function parseIgnoreWords(match) {
|
|
200
|
-
|
|
201
|
-
const ignoreWords = wordsSetting.words;
|
|
202
|
-
return ignoreWords && ignoreWords.length ? { ignoreWords } : emptySettings;
|
|
226
|
+
function parseIgnoreWords(acc, match) {
|
|
227
|
+
return reduceWordList(acc, match, 'ignoreWords');
|
|
203
228
|
}
|
|
204
|
-
function parseFlagWords(match) {
|
|
205
|
-
|
|
206
|
-
const flagWords = wordsSetting.words;
|
|
207
|
-
return flagWords && flagWords.length ? { flagWords } : emptySettings;
|
|
229
|
+
function parseFlagWords(acc, match) {
|
|
230
|
+
return reduceWordList(acc, match, 'flagWords');
|
|
208
231
|
}
|
|
209
232
|
function parseRegEx(match) {
|
|
210
233
|
const patterns = [match.replace(/^[^\s]+\s+/, '')].map((a) => {
|
|
@@ -216,32 +239,41 @@ function parseRegEx(match) {
|
|
|
216
239
|
});
|
|
217
240
|
return patterns;
|
|
218
241
|
}
|
|
219
|
-
function parseIgnoreRegExp(match) {
|
|
242
|
+
function parseIgnoreRegExp(acc, match) {
|
|
220
243
|
const ignoreRegExpList = parseRegEx(match);
|
|
221
|
-
|
|
244
|
+
if (ignoreRegExpList.length) {
|
|
245
|
+
acc.ignoreRegExpList = mergeList(acc.ignoreRegExpList, ignoreRegExpList);
|
|
246
|
+
}
|
|
247
|
+
return acc;
|
|
222
248
|
}
|
|
223
|
-
function parseIncludeRegExp(match) {
|
|
249
|
+
function parseIncludeRegExp(acc, match) {
|
|
224
250
|
const includeRegExpList = parseRegEx(match);
|
|
225
|
-
|
|
251
|
+
if (includeRegExpList.length) {
|
|
252
|
+
acc.includeRegExpList = mergeList(acc.includeRegExpList, includeRegExpList);
|
|
253
|
+
}
|
|
254
|
+
return acc;
|
|
226
255
|
}
|
|
227
|
-
function parseDictionaries(match) {
|
|
256
|
+
function parseDictionaries(acc, match) {
|
|
228
257
|
const dictionaries = match.split(/[,\s]+/g).slice(1);
|
|
229
|
-
|
|
258
|
+
if (dictionaries.length) {
|
|
259
|
+
acc.dictionaries = mergeList(acc.dictionaries, dictionaries);
|
|
260
|
+
}
|
|
261
|
+
return acc;
|
|
230
262
|
}
|
|
231
263
|
function getPossibleInDocSettings(text) {
|
|
232
|
-
return
|
|
264
|
+
return pipeSync(regExInFileSettings, opMap((regexp) => Text.match(regexp, text)), opFlatten(), opMap((match) => ({ fullDirective: match[0], offset: match.index, match: match[1].trim() })));
|
|
233
265
|
}
|
|
234
266
|
function getWordsFromDocument(text) {
|
|
235
267
|
const dict = extractInDocDictionary(getInDocumentSettings(text));
|
|
236
268
|
return dict?.words || EmptyWords;
|
|
237
269
|
}
|
|
238
|
-
function parseEnable(_match) {
|
|
270
|
+
function parseEnable(acc, _match) {
|
|
239
271
|
// Do nothing. Enable / Disable is handled in a different way.
|
|
240
|
-
return
|
|
272
|
+
return acc;
|
|
241
273
|
}
|
|
242
|
-
function parseDisable(_match) {
|
|
274
|
+
function parseDisable(acc, _match) {
|
|
243
275
|
// Do nothing. Enable / Disable is handled in a different way.
|
|
244
|
-
return
|
|
276
|
+
return acc;
|
|
245
277
|
}
|
|
246
278
|
export function extractInDocDictionary(settings) {
|
|
247
279
|
const inDocDicts = settings.dictionaryDefinitions?.filter((def) => def.name === staticInDocumentDictionaryName);
|
|
@@ -259,7 +291,8 @@ export function getIgnoreRegExpFromDocument(text) {
|
|
|
259
291
|
/**
|
|
260
292
|
* These internal functions are used exposed for unit testing.
|
|
261
293
|
*/
|
|
262
|
-
export const
|
|
294
|
+
export const __internal = {
|
|
295
|
+
collectInDocumentSettings: collectInDocumentDirectives,
|
|
263
296
|
getPossibleInDocSettings,
|
|
264
297
|
getWordsFromDocument,
|
|
265
298
|
parseWords,
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { suite } from 'perf-insight';
|
|
2
|
+
import { __internal, getInDocumentSettings } from './InDocSettings.js';
|
|
3
|
+
suite('Get InDocSettings', async (test) => {
|
|
4
|
+
const doc = sampleDoc();
|
|
5
|
+
const iterations = 10;
|
|
6
|
+
test('getInDocumentSettings', () => {
|
|
7
|
+
let settings = undefined;
|
|
8
|
+
for (let i = iterations; i > 0; --i) {
|
|
9
|
+
settings = getInDocumentSettings(doc);
|
|
10
|
+
}
|
|
11
|
+
return settings;
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
suite('Collect InDocSettings', async (test) => {
|
|
15
|
+
const doc = sampleDoc();
|
|
16
|
+
const iterations = 10;
|
|
17
|
+
test('collectInDocumentSettings', () => {
|
|
18
|
+
let settings = undefined;
|
|
19
|
+
for (let i = iterations; i > 0; --i) {
|
|
20
|
+
settings = __internal.collectInDocumentSettings(doc);
|
|
21
|
+
}
|
|
22
|
+
return settings;
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
function sampleDoc() {
|
|
26
|
+
return `
|
|
27
|
+
// cSpell\u003AenableCompoundWords
|
|
28
|
+
// cSpell\u003AdisableCompoundWords
|
|
29
|
+
// cSpell\u003A enableCOMPOUNDWords
|
|
30
|
+
// cSpell:words whiteberry, redberry, lightbrown
|
|
31
|
+
// cSpell\u003A ignoreRegExp /\\/\\/\\/.*/
|
|
32
|
+
// cSpell\u003AignoreRegexp w\\w+berry
|
|
33
|
+
// cSpell\u003A:ignoreRegExp /
|
|
34
|
+
/* cSpell\u003AignoreRegExp \\w+s{4}\\w+ */
|
|
35
|
+
/* cSpell\u003AignoreRegExp /faullts[/]?/ */
|
|
36
|
+
const berries = ['whiteberry', 'redberry', 'blueberry'];
|
|
37
|
+
|
|
38
|
+
/* cSpell\u003Aignore tripe, comment */
|
|
39
|
+
// cSpell\u003A: ignoreWords tooo faullts
|
|
40
|
+
/// ignore triple comment, with misssspellings and faullts
|
|
41
|
+
/// mooree prooobleems onn thisss line tooo with wordberry
|
|
42
|
+
// misssspellings faullts
|
|
43
|
+
|
|
44
|
+
// weirdberry can be straange.
|
|
45
|
+
// cSpell\u003Alanguage en-US
|
|
46
|
+
// cspell\u003Alocal
|
|
47
|
+
// cspell\u003Alocale es-ES
|
|
48
|
+
// cspell\u003Alocal en, nl
|
|
49
|
+
|
|
50
|
+
// cspell\u003Adictionaries lorem-ipsum
|
|
51
|
+
// LocalWords: one two three
|
|
52
|
+
// LocalWords:four five six
|
|
53
|
+
// localwords: seven eight nine
|
|
54
|
+
|
|
55
|
+
// cspell:ignore againxx
|
|
56
|
+
# cSpell\u003AdisableCompoundWords
|
|
57
|
+
# cSpell\u003AenableCOMPOUNDWords
|
|
58
|
+
# happydays arehere againxx
|
|
59
|
+
|
|
60
|
+
// cspell:ignore popoutlist
|
|
61
|
+
|
|
62
|
+
// spell\u003Adictionaries php
|
|
63
|
+
// spell\u003Awords const
|
|
64
|
+
// cspell\u003A
|
|
65
|
+
// cspell\u003Aignore popoutlist
|
|
66
|
+
const x = imp.popoutlist;
|
|
67
|
+
// cspell\u003Aignore again
|
|
68
|
+
|
|
69
|
+
// cspell:ignore happydays arehere againxx localwords weirdberry straange misssspellings
|
|
70
|
+
// cspell:ignore faullts mooree prooobleems onn thisss line tooo wordberry
|
|
71
|
+
`;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=InDocSettings.perf.js.map
|
|
@@ -21,10 +21,14 @@ export declare const regExBase64: RegExp;
|
|
|
21
21
|
*
|
|
22
22
|
* It must be:
|
|
23
23
|
* - at least 40 characters
|
|
24
|
-
* -
|
|
25
|
-
* -
|
|
24
|
+
* - preceded by a non-Base64
|
|
25
|
+
* - contain at least 1 of [0-9+/]
|
|
26
|
+
* - contain at least 1 of [A-Z][a-z][A-Z]
|
|
27
|
+
* - contain at least 1 of [A-Z][0-9][A-Z] | [a-z][0-9][a-z] | [A-Z][0-9][a-z] | [0-9][A-Za-z][0-9]
|
|
28
|
+
* - contain at least 1 of [a-z]{3} | [A-Z]{3}
|
|
26
29
|
*/
|
|
27
30
|
export declare const regExBase64SingleLine: RegExp;
|
|
31
|
+
export declare const regExBase64SingleLineLegacy: RegExp;
|
|
28
32
|
export declare const regExBase64MultiLine: RegExp;
|
|
29
33
|
export declare const regExPhpHereDoc: RegExp;
|
|
30
34
|
export declare const regExString: RegExp;
|
|
@@ -23,10 +23,14 @@ export const regExBase64 = /(?<![A-Za-z0-9/+])(?:[A-Za-z0-9/+]{40,})(?:\s^\s*[A-
|
|
|
23
23
|
*
|
|
24
24
|
* It must be:
|
|
25
25
|
* - at least 40 characters
|
|
26
|
-
* -
|
|
27
|
-
* -
|
|
26
|
+
* - preceded by a non-Base64
|
|
27
|
+
* - contain at least 1 of [0-9+/]
|
|
28
|
+
* - contain at least 1 of [A-Z][a-z][A-Z]
|
|
29
|
+
* - contain at least 1 of [A-Z][0-9][A-Z] | [a-z][0-9][a-z] | [A-Z][0-9][a-z] | [0-9][A-Za-z][0-9]
|
|
30
|
+
* - contain at least 1 of [a-z]{3} | [A-Z]{3}
|
|
28
31
|
*/
|
|
29
|
-
export const regExBase64SingleLine = /(
|
|
32
|
+
export const regExBase64SingleLine = /(?<=[^A-Za-z0-9/+_]|^)(?=[A-Za-z]{0,80}[0-9+/])(?=[A-Za-z0-9/+]{0,80}?[A-Z][a-z][A-Z])(?=[A-Za-z0-9/+]{0,80}?(?:[A-Z][0-9][A-Z]|[a-z][0-9][a-z]|[A-Z][0-9][a-z]|[a-z][0-9][A-Z]|[0-9][A-Za-z][0-9]))(?=[A-Za-z0-9/+]{0,80}?(?:[a-z]{3}|[A-Z]{3}))(?:[A-Za-z0-9/+]{40,})=*/gm;
|
|
33
|
+
export const regExBase64SingleLineLegacy = /((?<![A-Za-z0-9/+]))(?=[A-Za-z]{0,80}[0-9])(?:[A-Za-z0-9/+]{4}){10,}(?:[A-Za-z0-9/+]{3}={1}|[A-Za-z0-9/+]{2}={2}|[A-Za-z0-9/+]{1}={3})?(?![A-Za-z0-9/+=])(?=\1)/gm;
|
|
30
34
|
export const regExBase64MultiLine = /(?<![A-Za-z0-9/+])["']?(?:[A-Za-z0-9/+]{40,})["']?(?:\s^\s*["']?[A-Za-z0-9/+]{40,}["']?)+(?:\s^\s*["']?[A-Za-z0-9/+]+={0,3}["']?)?(?![A-Za-z0-9/+=])/gm;
|
|
31
35
|
// cspell:ignore aeiou
|
|
32
36
|
// The following is an attempt at detecting random strings.
|
|
@@ -9,7 +9,8 @@ export function combineTextAndLanguageSettings(settings, text, languageId) {
|
|
|
9
9
|
const settingsForText = mergeSettings(settings, docSettings);
|
|
10
10
|
const langSettings = calcSettingsForLanguageId(settingsForText, languageId);
|
|
11
11
|
// Merge again, to force In-Doc settings.
|
|
12
|
-
|
|
12
|
+
const final = mergeSettings(langSettings, docSettings);
|
|
13
|
+
return final;
|
|
13
14
|
}
|
|
14
15
|
export function extractSettingsFromText(text) {
|
|
15
16
|
return getInDocumentSettings(text);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { pathToFileURL } from 'node:url';
|
|
2
|
+
export class CwdUrlResolver {
|
|
3
|
+
#lastPath;
|
|
4
|
+
#lastUrl;
|
|
5
|
+
#cwd;
|
|
6
|
+
#cwdUrl;
|
|
7
|
+
constructor() {
|
|
8
|
+
this.#cwd = process.cwd();
|
|
9
|
+
this.#cwdUrl = pathToFileURL(this.#cwd);
|
|
10
|
+
this.#lastPath = this.#cwd;
|
|
11
|
+
this.#lastUrl = this.#cwdUrl;
|
|
12
|
+
}
|
|
13
|
+
resolveUrl(path) {
|
|
14
|
+
path = path || this.#cwd;
|
|
15
|
+
if (path === this.#lastPath)
|
|
16
|
+
return this.#lastUrl;
|
|
17
|
+
if (path === this.#cwd)
|
|
18
|
+
return this.#cwdUrl;
|
|
19
|
+
this.#lastPath = path;
|
|
20
|
+
this.#lastUrl = pathToFileURL(path);
|
|
21
|
+
return this.#lastUrl;
|
|
22
|
+
}
|
|
23
|
+
reset(cwd = process.cwd()) {
|
|
24
|
+
this.#cwd = cwd;
|
|
25
|
+
this.#cwdUrl = pathToFileURL(this.#cwd);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=resolveCwd.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as path from 'node:path';
|
|
2
2
|
import { getLanguagesForBasename } from '../fileTypes.js';
|
|
3
|
-
import { calcOverrideSettings, getDefaultSettings,
|
|
3
|
+
import { calcOverrideSettings, getDefaultSettings, getGlobalSettingsAsync, mergeSettings } from '../Settings/index.js';
|
|
4
4
|
import { combineTextAndLanguageSettings } from '../Settings/TextDocumentSettings.js';
|
|
5
5
|
import { uriToFilePath } from '../util/Uri.js';
|
|
6
6
|
/**
|
|
@@ -17,7 +17,7 @@ import { uriToFilePath } from '../util/Uri.js';
|
|
|
17
17
|
*/
|
|
18
18
|
export async function determineTextDocumentSettings(doc, settings) {
|
|
19
19
|
const filename = uriToFilePath(doc.uri);
|
|
20
|
-
const settingsWithDefaults = mergeSettings(await getDefaultSettings(settings.loadDefaultConfiguration ?? true),
|
|
20
|
+
const settingsWithDefaults = mergeSettings(await getDefaultSettings(settings.loadDefaultConfiguration ?? true), await getGlobalSettingsAsync(), settings);
|
|
21
21
|
const fileSettings = calcOverrideSettings(settingsWithDefaults, filename);
|
|
22
22
|
const languageIds = fileSettings?.languageId?.length
|
|
23
23
|
? fileSettings.languageId
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cspell-lib",
|
|
3
|
-
"version": "8.14.
|
|
3
|
+
"version": "8.14.3",
|
|
4
4
|
"description": "A library of useful functions used across various cspell tools.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -33,7 +33,8 @@
|
|
|
33
33
|
"#test": "vitest run --reporter=hanging-process --reporter=default",
|
|
34
34
|
"test": "vitest run --pool=forks",
|
|
35
35
|
"test:update-snapshot": "vitest run -u",
|
|
36
|
-
"test:perf": "NODE_ENV=production insight --
|
|
36
|
+
"test:perf": "NODE_ENV=production insight --file \"**/*.perf.{mts,ts}\" --register ts-node/esm",
|
|
37
|
+
"test:perf:prof": "NODE_ENV=production node --cpu-prof ../../node_modules/perf-insight/bin.mjs --file \"dist/**/*.perf.{mjs,js}\" -t 1000"
|
|
37
38
|
},
|
|
38
39
|
"repository": {
|
|
39
40
|
"type": "git",
|
|
@@ -56,24 +57,24 @@
|
|
|
56
57
|
"bugs": {
|
|
57
58
|
"url": "https://github.com/streetsidesoftware/cspell/labels/cspell-lib"
|
|
58
59
|
},
|
|
59
|
-
"homepage": "https://github.com/streetsidesoftware/cspell#readme",
|
|
60
|
+
"homepage": "https://github.com/streetsidesoftware/cspell/tree/main/packages/cspell-lib#readme",
|
|
60
61
|
"dependencies": {
|
|
61
|
-
"@cspell/cspell-bundled-dicts": "8.14.
|
|
62
|
-
"@cspell/cspell-pipe": "8.14.
|
|
63
|
-
"@cspell/cspell-resolver": "8.14.
|
|
64
|
-
"@cspell/cspell-types": "8.14.
|
|
65
|
-
"@cspell/dynamic-import": "8.14.
|
|
66
|
-
"@cspell/filetypes": "8.14.
|
|
67
|
-
"@cspell/strong-weak-map": "8.14.
|
|
68
|
-
"@cspell/url": "8.14.
|
|
62
|
+
"@cspell/cspell-bundled-dicts": "8.14.3",
|
|
63
|
+
"@cspell/cspell-pipe": "8.14.3",
|
|
64
|
+
"@cspell/cspell-resolver": "8.14.3",
|
|
65
|
+
"@cspell/cspell-types": "8.14.3",
|
|
66
|
+
"@cspell/dynamic-import": "8.14.3",
|
|
67
|
+
"@cspell/filetypes": "8.14.3",
|
|
68
|
+
"@cspell/strong-weak-map": "8.14.3",
|
|
69
|
+
"@cspell/url": "8.14.3",
|
|
69
70
|
"clear-module": "^4.1.2",
|
|
70
71
|
"comment-json": "^4.2.5",
|
|
71
|
-
"cspell-config-lib": "8.14.
|
|
72
|
-
"cspell-dictionary": "8.14.
|
|
73
|
-
"cspell-glob": "8.14.
|
|
74
|
-
"cspell-grammar": "8.14.
|
|
75
|
-
"cspell-io": "8.14.
|
|
76
|
-
"cspell-trie-lib": "8.14.
|
|
72
|
+
"cspell-config-lib": "8.14.3",
|
|
73
|
+
"cspell-dictionary": "8.14.3",
|
|
74
|
+
"cspell-glob": "8.14.3",
|
|
75
|
+
"cspell-grammar": "8.14.3",
|
|
76
|
+
"cspell-io": "8.14.3",
|
|
77
|
+
"cspell-trie-lib": "8.14.3",
|
|
77
78
|
"env-paths": "^3.0.0",
|
|
78
79
|
"fast-equals": "^5.0.1",
|
|
79
80
|
"gensequence": "^7.0.0",
|
|
@@ -87,14 +88,14 @@
|
|
|
87
88
|
"node": ">=18"
|
|
88
89
|
},
|
|
89
90
|
"devDependencies": {
|
|
90
|
-
"@cspell/dict-cpp": "^5.1.
|
|
91
|
+
"@cspell/dict-cpp": "^5.1.16",
|
|
91
92
|
"@cspell/dict-csharp": "^4.0.2",
|
|
92
93
|
"@cspell/dict-css": "^4.0.13",
|
|
93
94
|
"@cspell/dict-fa-ir": "^4.0.0",
|
|
94
95
|
"@cspell/dict-fr-fr": "^2.2.2",
|
|
95
96
|
"@cspell/dict-html": "^4.0.5",
|
|
96
97
|
"@cspell/dict-nl-nl": "^2.3.0",
|
|
97
|
-
"@cspell/dict-python": "^4.2.
|
|
98
|
+
"@cspell/dict-python": "^4.2.6",
|
|
98
99
|
"@types/configstore": "^6.0.2",
|
|
99
100
|
"configstore": "^7.0.0",
|
|
100
101
|
"cspell-dict-nl-nl": "^1.1.2",
|
|
@@ -102,5 +103,5 @@
|
|
|
102
103
|
"lorem-ipsum": "^2.0.8",
|
|
103
104
|
"perf-insight": "^1.2.0"
|
|
104
105
|
},
|
|
105
|
-
"gitHead": "
|
|
106
|
+
"gitHead": "ce996377857f5d7c3e70f27fc512afbe605562f8"
|
|
106
107
|
}
|