cspell-lib
Version:
A library of useful functions used across various cspell tools.
106 lines • 4.33 kB
JavaScript
import { getSources } from '../Settings/index.js';
import { createCollection, getInlineConfigDictionaries, mapSpecialDictionaryNamesToSettings, } from '../SpellingDictionary/index.js';
import { toFileUrl } from '../util/url.js';
import { uniqueFn } from '../util/util.js';
import { split } from '../util/wordSplitter.js';
export function traceWord(word, dictCollection, config) {
const opts = {
ignoreCase: config.ignoreCase ?? true,
useCompounds: config.allowCompoundWords || false,
};
const splits = split({ text: word, offset: 0 }, 0, checkWord);
const wfSplits = splits.words.map((s) => ({ word: s.text, found: s.isFound }));
const unique = uniqueFn((w) => w.word + '|' + w.found);
const wsFound = { word, found: dictCollection.has(word, opts) };
const wordSplits = wfSplits.some((s) => s.word === word) ? wfSplits : [wsFound, ...wfSplits];
const traces = wordSplits
.filter(unique)
.map((s) => s.word)
.flatMap((word) => dictCollection.dictionaries.map((dict) => ({ dict, word })))
.map(({ dict, word }) => ({ dict, findResult: dict.find(word, opts), word }))
.flatMap((r) => unpackDictionaryFindResult(r, config));
const r = new CTraceResult(...traces);
r.splits = wordSplits;
return r;
function checkWord(wo) {
return dictCollection.has(wo.text, opts);
}
}
/**
* Map FindInDictResult to DictionaryTraceResult
* If the word was found in a dictionary based upon a config field setting, then find the source config.
* @param found - a word found in a dictionary
* @param config - the trace config
* @returns DictionaryTraceResult[]
*/
function unpackDictionaryFindResult(found, config) {
const { word, dict, findResult } = found;
const dictPreferred = getPreferred(dict, word);
const baseResult = {
word,
found: !!findResult?.found,
foundWord: findResult?.found || undefined,
forbidden: findResult?.forbidden || false,
noSuggest: findResult?.noSuggest || false,
dictName: dict.name,
dictSource: dict.source,
configSource: undefined,
preferredSuggestions: dictPreferred,
errors: normalizeErrors(dict.getErrors?.()),
};
const configFieldName = mapSpecialDictionaryNamesToSettings.get(dict.name);
if (!findResult?.found || !configFieldName || !config.source) {
return [baseResult];
}
const opts = {
ignoreCase: true,
useCompounds: config.allowCompoundWords || false,
};
const sources = getSources(config);
const results = [];
for (const src of sources) {
if (!src[configFieldName] ||
!Array.isArray(src[configFieldName]) ||
!src[configFieldName]?.length ||
!src.source?.filename) {
continue;
}
// We found a possible config, build a dictionary result for it.
const configSource = toFileUrl(src.source.filename).href;
const cfg = { [configFieldName]: src[configFieldName] };
const cfgDict = createCollection(getInlineConfigDictionaries(cfg), dict.name, configSource);
const findResult = cfgDict.find(word, opts);
const preferredSuggestions = getPreferred(cfgDict, word);
if (!findResult?.found && !preferredSuggestions)
continue;
const result = {
word,
found: !!findResult?.found,
foundWord: findResult?.found || undefined,
forbidden: findResult?.forbidden || false,
noSuggest: findResult?.noSuggest || false,
dictName: dict.name,
dictSource: configSource,
configSource,
preferredSuggestions,
errors: normalizeErrors(dict.getErrors?.()),
};
results.push(result);
}
return results.length ? results : [baseResult];
}
function normalizeErrors(errors) {
return errors?.length ? errors : undefined;
}
function getPreferred(dict, word) {
const sugs = dict.getPreferredSuggestions?.(word);
const preferred = sugs?.length ? sugs.filter((s) => s.isPreferred).map((s) => s.word) : undefined;
return preferred;
}
class CTraceResult extends Array {
splits = [];
constructor(...items) {
super(...items);
}
}
//# sourceMappingURL=traceWord.js.map