cspell-lib 8.3.0 → 8.3.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.
@@ -1,6 +1,17 @@
1
+ import type { CSpellSettings } from '@cspell/cspell-types';
1
2
  import type { SpellingDictionary, SpellingDictionaryCollection } from 'cspell-dictionary';
2
3
  import type { CSpellSettingsInternal, DictionaryDefinitionInternal } from '../Models/CSpellSettingsInternalDef.js';
3
4
  export declare function loadDictionaryDefs(defsToLoad: DictionaryDefinitionInternal[]): Promise<SpellingDictionary>[];
4
5
  export declare function refreshDictionaryCache(maxAge?: number): Promise<void>;
5
6
  export declare function getDictionaryInternal(settings: CSpellSettingsInternal): Promise<SpellingDictionaryCollection>;
7
+ export declare const specialDictionaryNames: {
8
+ readonly words: "[words]";
9
+ readonly userWords: "[userWords]";
10
+ readonly flagWords: "[flagWords]";
11
+ readonly ignoreWords: "[ignoreWords]";
12
+ readonly suggestWords: "[suggestWords]";
13
+ };
14
+ export type DictionaryNameFields = keyof typeof specialDictionaryNames;
15
+ export declare const mapSpecialDictionaryNamesToSettings: Map<string, DictionaryNameFields>;
16
+ export declare function getInlineConfigDictionaries(settings: CSpellSettings): SpellingDictionary[];
6
17
  //# sourceMappingURL=Dictionaries.d.ts.map
@@ -13,29 +13,40 @@ export async function getDictionaryInternal(settings) {
13
13
  const spellDictionaries = await Promise.all(loadDictionaryDefs(calcDictionaryDefsToLoad(settings)));
14
14
  return _getDictionaryInternal(settings, spellDictionaries);
15
15
  }
16
- function _getDictionaryInternal(settings, spellDictionaries) {
16
+ export const specialDictionaryNames = {
17
+ words: '[words]',
18
+ userWords: '[userWords]',
19
+ flagWords: '[flagWords]',
20
+ ignoreWords: '[ignoreWords]',
21
+ suggestWords: '[suggestWords]',
22
+ };
23
+ export const mapSpecialDictionaryNamesToSettings = new Map(Object.entries(specialDictionaryNames).map(([k, v]) => [v, k]));
24
+ export function getInlineConfigDictionaries(settings) {
17
25
  const { words = emptyWords, userWords = emptyWords, flagWords = emptyWords, ignoreWords = emptyWords, suggestWords = emptyWords, } = settings;
18
- const settingsWordsDictionary = createSpellingDictionary(words, '[words]', 'From Settings `words`', {
26
+ const settingsWordsDictionary = createSpellingDictionary(words, specialDictionaryNames.words, 'From Settings `words`', {
19
27
  caseSensitive: true,
20
28
  weightMap: undefined,
21
29
  });
22
30
  const settingsUserWordsDictionary = userWords.length
23
- ? createSpellingDictionary(userWords, '[userWords]', 'From Settings `userWords`', {
31
+ ? createSpellingDictionary(userWords, specialDictionaryNames.userWords, 'From Settings `userWords`', {
24
32
  caseSensitive: true,
25
33
  weightMap: undefined,
26
34
  })
27
35
  : undefined;
28
- const ignoreWordsDictionary = createIgnoreWordsDictionary(ignoreWords, '[ignoreWords]', 'From Settings `ignoreWords`');
29
- const flagWordsDictionary = createForbiddenWordsDictionary(flagWords, '[flagWords]', 'From Settings `flagWords`');
36
+ const ignoreWordsDictionary = createIgnoreWordsDictionary(ignoreWords, specialDictionaryNames.ignoreWords, 'From Settings `ignoreWords`');
37
+ const flagWordsDictionary = createForbiddenWordsDictionary(flagWords, specialDictionaryNames.flagWords, 'From Settings `flagWords`');
30
38
  const suggestWordsDictionary = createSuggestDictionary(suggestWords, '[suggestWords]', 'From Settings `suggestWords`');
31
39
  const dictionaries = [
32
- ...spellDictionaries,
33
40
  settingsWordsDictionary,
34
41
  settingsUserWordsDictionary,
35
42
  ignoreWordsDictionary,
36
43
  flagWordsDictionary,
37
44
  suggestWordsDictionary,
38
45
  ].filter(isDefined);
46
+ return dictionaries;
47
+ }
48
+ function _getDictionaryInternal(settings, spellDictionaries) {
49
+ const dictionaries = [...spellDictionaries, ...getInlineConfigDictionaries(settings)];
39
50
  return createCollection(dictionaries, 'dictionary collection');
40
51
  }
41
52
  //# sourceMappingURL=Dictionaries.js.map
@@ -16,7 +16,7 @@ export { CompoundWordsMethod, createSpellingDictionary, createCollection as crea
16
16
  export type { SuggestedWord, SuggestionOptions, SuggestionsForWordResult } from './suggestions.js';
17
17
  export { SuggestionError, suggestionsForWord, suggestionsForWords } from './suggestions.js';
18
18
  export { DocumentValidator, DocumentValidatorOptions, shouldCheckDocument } from './textValidation/index.js';
19
- export type { TraceOptions, TraceResult } from './trace.js';
19
+ export type { TraceOptions, TraceResult, TraceWordResult } from './trace.js';
20
20
  export { traceWords, traceWordsAsync } from './trace.js';
21
21
  export { getLogger, Logger, setLogger } from './util/logger.js';
22
22
  export { resolveFile } from './util/resolveFile.js';
@@ -1,6 +1,7 @@
1
1
  import type { MappedText, TextOffset as TextOffsetRW } from '@cspell/cspell-types';
2
2
  import type { ExtendedSuggestion } from '../Models/Suggestion.js';
3
3
  import type { ValidationIssue } from '../Models/ValidationIssue.js';
4
+ export type { TextOffset as TextOffsetRW } from '@cspell/cspell-types';
4
5
  export type TextOffsetRO = Readonly<TextOffsetRW>;
5
6
  export interface ValidationOptions extends IncludeExcludeOptions {
6
7
  maxNumberOfProblems?: number;
@@ -77,16 +77,7 @@ export declare class DocumentValidator {
77
77
  * @returns MatchRanges of text to include.
78
78
  */
79
79
  getCheckedTextRanges(): MatchRange[];
80
- traceWord(word: string): {
81
- word: string;
82
- found: boolean;
83
- foundWord: string | undefined;
84
- forbidden: boolean;
85
- noSuggest: boolean;
86
- dictName: string;
87
- dictSource: string;
88
- errors: Error[] | undefined;
89
- }[];
80
+ traceWord(word: string): import("./traceWord.js").TraceResult;
90
81
  private defaultParser;
91
82
  private _checkParsedText;
92
83
  private addPossibleError;
@@ -11,13 +11,13 @@ import { calcSuggestionAdjustedToToMatchCase } from '../suggestions.js';
11
11
  import { catchPromiseError, toError } from '../util/errors.js';
12
12
  import { AutoCache } from '../util/simpleCache.js';
13
13
  import { uriToFilePath } from '../util/Uri.js';
14
- import { toFilePathOrHref } from '../util/url.js';
15
14
  import { defaultMaxDuplicateProblems, defaultMaxNumberOfProblems } from './defaultConstants.js';
16
15
  import { determineTextDocumentSettings } from './determineTextDocumentSettings.js';
17
16
  import { textValidatorFactory } from './lineValidatorFactory.js';
18
17
  import { createMappedTextSegmenter } from './parsedText.js';
19
18
  import { settingsToValidateOptions } from './settingsToValidateOptions.js';
20
19
  import { calcTextInclusionRanges } from './textValidator.js';
20
+ import { traceWord } from './traceWord.js';
21
21
  const ERROR_NOT_PREPARED = 'Validator Must be prepared before calling this function.';
22
22
  export class DocumentValidator {
23
23
  settings;
@@ -248,25 +248,7 @@ export class DocumentValidator {
248
248
  }
249
249
  traceWord(word) {
250
250
  assert(this._preparations, ERROR_NOT_PREPARED);
251
- const dictCollection = this._preparations.dictionary;
252
- const config = this._preparations.config;
253
- const opts = {
254
- ignoreCase: true,
255
- allowCompoundWords: config.allowCompoundWords || false,
256
- };
257
- const trace = dictCollection.dictionaries
258
- .map((dict) => ({ dict, findResult: dict.find(word, opts) }))
259
- .map(({ dict, findResult }) => ({
260
- word,
261
- found: !!findResult?.found,
262
- foundWord: findResult?.found || undefined,
263
- forbidden: findResult?.forbidden || false,
264
- noSuggest: findResult?.noSuggest || false,
265
- dictName: dict.name,
266
- dictSource: toFilePathOrHref(dict.source),
267
- errors: normalizeErrors(dict.getErrors?.()),
268
- }));
269
- return trace;
251
+ return traceWord(word, this._preparations.dictionary, this._preparations.config);
270
252
  }
271
253
  defaultParser() {
272
254
  return pipeSync(this.document.getLines(), opMap((line) => {
@@ -409,7 +391,4 @@ function recordPerfTime(timings, name) {
409
391
  function timePromise(timings, name, p) {
410
392
  return p.finally(recordPerfTime(timings, name));
411
393
  }
412
- function normalizeErrors(errors) {
413
- return errors?.length ? errors : undefined;
414
- }
415
394
  //# sourceMappingURL=docValidator.js.map
@@ -88,7 +88,7 @@ export function lineValidatorFactory(sDict, options) {
88
88
  };
89
89
  return [vr];
90
90
  }
91
- const mismatches = toArray(pipe(Text.extractWordsFromTextOffset(possibleWord), opFilter(filterAlreadyChecked), opMap((wo) => ({ ...wo, line: lineSegment.line })), opMap(annotateIsFlagged), opFilter(rememberFilter((wo) => wo.text.length >= minWordLength || !!wo.isFlagged)), opConcatMap(checkFullWord)));
91
+ const mismatches = toArray(pipe(Text.extractWordsFromTextOffset(possibleWord), opFilter((wo) => filterAlreadyChecked(wo)), opMap((wo) => ((wo.line = lineSegment.line), wo)), opMap(annotateIsFlagged), opFilter(rememberFilter((wo) => wo.text.length >= minWordLength || !!wo.isFlagged)), opConcatMap(checkFullWord)));
92
92
  if (mismatches.length) {
93
93
  // Try the more expensive word splitter
94
94
  const splitResult = split(lineSegment.segment, possibleWord.offset, splitterIsValid);
@@ -0,0 +1,27 @@
1
+ import type { CSpellSettingsWithSourceTrace } from '@cspell/cspell-types';
2
+ import type { SpellingDictionaryCollection } from '../SpellingDictionary/index.js';
3
+ type Href = string;
4
+ export interface DictionaryTraceResult {
5
+ word: string;
6
+ found: boolean;
7
+ foundWord: string | undefined;
8
+ forbidden: boolean;
9
+ noSuggest: boolean;
10
+ dictName: string;
11
+ dictSource: string;
12
+ configSource: Href | undefined;
13
+ errors: Error[] | undefined;
14
+ }
15
+ export interface WordSplits {
16
+ word: string;
17
+ found: boolean;
18
+ }
19
+ export interface TraceResult extends Array<DictionaryTraceResult> {
20
+ splits?: readonly WordSplits[];
21
+ }
22
+ export interface TraceOptions extends Pick<CSpellSettingsWithSourceTrace, 'source' | 'allowCompoundWords'> {
23
+ ignoreCase?: boolean;
24
+ }
25
+ export declare function traceWord(word: string, dictCollection: SpellingDictionaryCollection, config: TraceOptions): TraceResult;
26
+ export {};
27
+ //# sourceMappingURL=traceWord.d.ts.map
@@ -0,0 +1,106 @@
1
+ import { getSources } from '../Settings/index.js';
2
+ import { createCollection, getInlineConfigDictionaries, mapSpecialDictionaryNamesToSettings, } from '../SpellingDictionary/index.js';
3
+ import { toFileUrl } from '../util/url.js';
4
+ import { uniqueFn } from '../util/util.js';
5
+ import { split } from '../util/wordSplitter.js';
6
+ export function traceWord(word, dictCollection, config) {
7
+ const opts = {
8
+ ignoreCase: true,
9
+ useCompounds: config.allowCompoundWords || false,
10
+ };
11
+ const splits = split({ text: word, offset: 0 }, 0, checkWord);
12
+ const wfSplits = splits.words.map((s) => ({ word: s.text, found: s.isFound }));
13
+ const unique = uniqueFn((w) => w.word + '|' + w.found);
14
+ const wsFound = { word, found: dictCollection.has(word, opts) };
15
+ const wordSplits = wfSplits.find((s) => s.word === word) ? wfSplits : [wsFound, ...wfSplits];
16
+ const traces = wordSplits
17
+ .filter(unique)
18
+ .map((s) => s.word)
19
+ .flatMap((word) => dictCollection.dictionaries.map((dict) => ({ dict, word })))
20
+ .map(({ dict, word }) => ({ dict, findResult: dict.find(word, opts), word }))
21
+ .flatMap((r) => unpackDictionaryFindResult(r, config));
22
+ const r = new CTraceResult(...traces);
23
+ r.splits = wordSplits;
24
+ return r;
25
+ function checkWord(wo) {
26
+ return dictCollection.has(wo.text, opts);
27
+ }
28
+ }
29
+ /**
30
+ * Map FindInDictResult to DictionaryTraceResult
31
+ * If the word was found in a dictionary based upon a config field setting, then find the source config.
32
+ * @param found - a word found in a dictionary
33
+ * @param config - the trace config
34
+ * @returns DictionaryTraceResult[]
35
+ */
36
+ function unpackDictionaryFindResult(found, config) {
37
+ const { word, dict, findResult } = found;
38
+ const baseResult = {
39
+ word,
40
+ found: !!findResult?.found,
41
+ foundWord: findResult?.found || undefined,
42
+ forbidden: findResult?.forbidden || false,
43
+ noSuggest: findResult?.noSuggest || false,
44
+ dictName: dict.name,
45
+ dictSource: dict.source,
46
+ configSource: undefined,
47
+ errors: normalizeErrors(dict.getErrors?.()),
48
+ };
49
+ const configFieldName = mapSpecialDictionaryNamesToSettings.get(dict.name);
50
+ if (!findResult?.found || !configFieldName || !config.source) {
51
+ return [baseResult];
52
+ }
53
+ const opts = {
54
+ ignoreCase: true,
55
+ useCompounds: config.allowCompoundWords || false,
56
+ };
57
+ const sources = getSources(config);
58
+ const results = [];
59
+ for (const src of sources) {
60
+ if (!src[configFieldName] ||
61
+ !Array.isArray(src[configFieldName]) ||
62
+ !src[configFieldName]?.length ||
63
+ !src.source?.filename) {
64
+ continue;
65
+ }
66
+ // We found a possible config, build a dictionary result for it.
67
+ const configSource = toFileUrl(src.source.filename).href;
68
+ const cfg = { [configFieldName]: src[configFieldName] };
69
+ const cfgDict = createCollection(getInlineConfigDictionaries(cfg), dict.name, configSource);
70
+ const findResult = cfgDict.find(word, opts);
71
+ if (!findResult?.found)
72
+ continue;
73
+ const result = {
74
+ word,
75
+ found: !!findResult?.found,
76
+ foundWord: findResult?.found || undefined,
77
+ forbidden: findResult?.forbidden || false,
78
+ noSuggest: findResult?.noSuggest || false,
79
+ dictName: dict.name,
80
+ dictSource: configSource,
81
+ configSource,
82
+ errors: normalizeErrors(dict.getErrors?.()),
83
+ };
84
+ results.push(result);
85
+ // console.log('unpackDictFindResult %o', {
86
+ // id: src.id,
87
+ // name: src.name,
88
+ // filename: src.source?.filename,
89
+ // configFieldName,
90
+ // findResult,
91
+ // cfg,
92
+ // result,
93
+ // });
94
+ }
95
+ return results.length ? results : [baseResult];
96
+ }
97
+ function normalizeErrors(errors) {
98
+ return errors?.length ? errors : undefined;
99
+ }
100
+ class CTraceResult extends Array {
101
+ splits = [];
102
+ constructor(...items) {
103
+ super(...items);
104
+ }
105
+ }
106
+ //# sourceMappingURL=traceWord.js.map
@@ -1,5 +1,6 @@
1
1
  import type { CSpellSettings, LocaleId } from '@cspell/cspell-types';
2
2
  import type { LanguageId } from './LanguageIds.js';
3
+ import type { WordSplits } from './textValidation/traceWord.js';
3
4
  export interface TraceResult {
4
5
  word: string;
5
6
  found: boolean;
@@ -18,6 +19,9 @@ export interface TraceOptions {
18
19
  ignoreCase?: boolean;
19
20
  allowCompoundWords?: boolean;
20
21
  }
22
+ export interface TraceWordResult extends Array<TraceResult> {
23
+ splits: readonly WordSplits[];
24
+ }
21
25
  export declare function traceWords(words: string[], settings: CSpellSettings, options: TraceOptions | undefined): Promise<TraceResult[]>;
22
- export declare function traceWordsAsync(words: Iterable<string> | AsyncIterable<string>, settings: CSpellSettings, options: TraceOptions | undefined): AsyncIterableIterator<TraceResult[]>;
26
+ export declare function traceWordsAsync(words: Iterable<string> | AsyncIterable<string>, settings: CSpellSettings, options: TraceOptions | undefined): AsyncIterableIterator<TraceWordResult>;
23
27
  //# sourceMappingURL=trace.d.ts.map
package/dist/esm/trace.js CHANGED
@@ -3,6 +3,7 @@ import { toInternalSettings } from './Settings/CSpellSettingsServer.js';
3
3
  import { finalizeSettings, mergeSettings } from './Settings/index.js';
4
4
  import { calcSettingsForLanguageId } from './Settings/LanguageSettings.js';
5
5
  import { getDictionaryInternal, refreshDictionaryCache } from './SpellingDictionary/index.js';
6
+ import { traceWord } from './textValidation/traceWord.js';
6
7
  import { toFilePathOrHref } from './util/url.js';
7
8
  import * as util from './util/util.js';
8
9
  export async function traceWords(words, settings, options) {
@@ -37,33 +38,27 @@ export async function* traceWordsAsync(words, settings, options) {
37
38
  await refreshDictionaryCache();
38
39
  const { config, dicts, activeDictionaries } = await finalize(settings);
39
40
  const setOfActiveDicts = new Set(activeDictionaries);
40
- const opts = util.clean({ ignoreCase, useCompounds: config.allowCompoundWords });
41
- function normalizeErrors(errors) {
42
- if (!errors?.length)
43
- return undefined;
44
- return errors;
45
- }
46
41
  function processWord(word) {
47
- return dicts.dictionaries
48
- .map((dict) => ({ dict, findResult: dict.find(word, opts) }))
49
- .map(({ dict, findResult }) => ({
50
- word,
51
- found: !!findResult?.found,
52
- foundWord: findResult?.found || undefined,
53
- forbidden: findResult?.forbidden || false,
54
- noSuggest: findResult?.noSuggest || false,
55
- dictName: dict.name,
56
- dictSource: dictSourceToFilename(dict.source),
57
- dictActive: setOfActiveDicts.has(dict.name),
58
- configSource: config.name || '',
59
- errors: normalizeErrors(dict.getErrors?.()),
42
+ const results = traceWord(word, dicts, { ...config, ignoreCase });
43
+ const r = results.map((r) => ({
44
+ ...r,
45
+ dictActive: setOfActiveDicts.has(r.dictName),
46
+ dictSource: toFilePathOrHref(r.dictSource),
47
+ configSource: r.configSource || config.name || '',
48
+ splits: results.splits,
60
49
  }));
50
+ const tr = new CTraceResult(...r);
51
+ results.splits && tr.splits.push(...results.splits);
52
+ return tr;
61
53
  }
62
54
  for await (const word of words) {
63
55
  yield processWord(word);
64
56
  }
65
57
  }
66
- function dictSourceToFilename(source) {
67
- return toFilePathOrHref(source);
58
+ class CTraceResult extends Array {
59
+ splits = [];
60
+ constructor(...items) {
61
+ super(...items);
62
+ }
68
63
  }
69
64
  //# sourceMappingURL=trace.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cspell-lib",
3
- "version": "8.3.0",
3
+ "version": "8.3.2",
4
4
  "description": "A library of useful functions used across various cspell tools.",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -57,21 +57,21 @@
57
57
  },
58
58
  "homepage": "https://github.com/streetsidesoftware/cspell#readme",
59
59
  "dependencies": {
60
- "@cspell/cspell-bundled-dicts": "8.3.0",
61
- "@cspell/cspell-pipe": "8.3.0",
62
- "@cspell/cspell-resolver": "8.3.0",
63
- "@cspell/cspell-types": "8.3.0",
64
- "@cspell/dynamic-import": "8.3.0",
65
- "@cspell/strong-weak-map": "8.3.0",
60
+ "@cspell/cspell-bundled-dicts": "8.3.2",
61
+ "@cspell/cspell-pipe": "8.3.2",
62
+ "@cspell/cspell-resolver": "8.3.2",
63
+ "@cspell/cspell-types": "8.3.2",
64
+ "@cspell/dynamic-import": "8.3.2",
65
+ "@cspell/strong-weak-map": "8.3.2",
66
66
  "clear-module": "^4.1.2",
67
67
  "comment-json": "^4.2.3",
68
68
  "configstore": "^6.0.0",
69
- "cspell-config-lib": "8.3.0",
70
- "cspell-dictionary": "8.3.0",
71
- "cspell-glob": "8.3.0",
72
- "cspell-grammar": "8.3.0",
73
- "cspell-io": "8.3.0",
74
- "cspell-trie-lib": "8.3.0",
69
+ "cspell-config-lib": "8.3.2",
70
+ "cspell-dictionary": "8.3.2",
71
+ "cspell-glob": "8.3.2",
72
+ "cspell-grammar": "8.3.2",
73
+ "cspell-io": "8.3.2",
74
+ "cspell-trie-lib": "8.3.2",
75
75
  "fast-equals": "^5.0.1",
76
76
  "gensequence": "^6.0.0",
77
77
  "import-fresh": "^3.3.0",
@@ -95,5 +95,5 @@
95
95
  "cspell-dict-nl-nl": "^1.1.2",
96
96
  "lorem-ipsum": "^2.0.8"
97
97
  },
98
- "gitHead": "019c7ccd326b7fc9e106069ddf6008d5079bbd12"
98
+ "gitHead": "98f622b2b12529f2d1ccf0f3a57991e4c08b3e3a"
99
99
  }