@dcoffey/espells
Version:
Pure JS/TS spellchecker, using Hunspell dictionaries. Based on Spylls.
147 lines • 5.62 kB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import { iterate } from "iterare";
import { CapType, CONSTANTS as C } from "../constants.js";
import { any, includes } from "../util.js";
import { affixForms as affixes } from "./affixes.js";
import { compoundForms as compounds } from "./compounds.js";
import { breakWord } from "./decompose.js";
import { LKWord } from "./lk-word.js";
/** Class that facilitaties lookups for a spellchecker. */
export class Lookup {
/**
* @param aff - The affix data to use.
* @param dic - The dictionary data to use.
*/
constructor(aff, dic) {
this.aff = aff;
this.dic = dic;
}
/**
* Checks if a word is spelled correctly.
*
* @param word - The word to check.
* @param caps - If true, checking will be case sensitive. Defaults to true.
* @param allowNoSuggest - If false, words which are in the dictionary,
* but are flagged with the `NOSUGGEST` flag (if provided), will not be
* considered correct. Defaults to true.
*/
check(word, caps = true, allowNoSuggest = true) {
let forbidden = this.isForbidden(word);
let warn = this.isWarn(word);
if (forbidden)
return { correct: false, forbidden, warn };
if (this.aff.ICONV)
word = this.aff.ICONV.match(word);
word = this.aff.ignore(word);
if (C.NUMBER_REGEX.test(word))
return { correct: true, forbidden, warn };
for (const words of breakWord(this.aff, word)) {
if (words.every(word => this.correct(word, { caps, allowNoSuggest }))) {
return { correct: true, forbidden, warn };
}
}
return { correct: false, forbidden, warn };
}
/**
* Yields *correct* combinations of stems and affixes for a word,
* specifically instances of {@link AffixForm} or {@link CompoundForm}. If
* this function does actually yield a form, that means that it can be
* considered as spelled correctly.
*
* @param word - The word to yield the forms of.
* @see {@link LKC}
*/
*forms(word, { caps = true, allowNoSuggest = true, affixForms = true, compoundForms = true } = {}) {
let captype, variants;
if (caps) {
;
[captype, ...variants] = this.aff.casing.variants(word);
}
else {
captype = this.aff.casing.guess(word);
variants = [word];
}
const lkword = new LKWord(this.aff, this.dic, word, captype);
for (const variant of variants) {
const word = lkword.to(variant);
if (affixForms) {
for (const form of affixes(word, allowNoSuggest)) {
if (form.inDictionary &&
captype === CapType.ALL &&
includes(this.aff.KEEPCASE, form.flags) &&
this.aff.isSharps(form.inDictionary.stem) &&
this.aff.isSharps(lkword.word)) {
continue;
}
yield form;
}
}
if (compoundForms)
yield* compounds(word, allowNoSuggest);
}
}
// -- UTILITY
/**
* Checks if a word is spelled correctly. Performs no processing on the
* word, such as handling `aff.IGNORE` characters.
*
* @param word - The word to check.
* @see {@link LKC}
*/
correct(word, { caps, allowNoSuggest, affixForms, compoundForms } = {}) {
return any(this.forms(word, { caps, allowNoSuggest, affixForms, compoundForms }));
}
/**
* Yields the stems of a word. If no stems are returned, the word was incorrect.
*
* @param word - The word to yield the stems of.
* @see {@link LKC}
*/
*stems(word, { caps, allowNoSuggest, affixForms, compoundForms } = {}) {
if (this.aff.ICONV)
word = this.aff.ICONV.match(word);
word = this.aff.ignore(word);
const iter = this.forms(word, { caps, allowNoSuggest, affixForms, compoundForms });
for (const form of iter) {
if (Array.isArray(form))
yield* iterate(form).map(form => form.stem);
else
yield form.stem;
}
}
/**
* Yields a list of a data maps associated with the homonyms of the given stem.
*
* @param stem - The stem to get the data of.
* @param caps - If true, checking will be case sensitive. Defaults to true.
*/
*data(stem, caps = true) {
for (const homonym of this.dic.homonyms(stem, !caps)) {
if (!homonym.data)
continue;
yield homonym.data;
}
}
/**
* Determines if a stem is marked with the `WARN` flag.
*
* @param stem - The stem to check.
*/
isWarn(stem) {
return this.dic.hasFlag(stem, this.aff.WARN, true);
}
/**
* Determines if a stem is marked as forbidden, either through the
* `FORBIDDENWORD` flag *or* the the combination of the stem having the
* `WARN` flag and the `FORBIDWARN` directive being true.
*
* @param stem - The word to check.
*/
isForbidden(stem) {
return (this.dic.hasFlag(stem, this.aff.FORBIDDENWORD, true) ||
(this.aff.FORBIDWARN && this.dic.hasFlag(stem, this.aff.WARN, true)));
}
}
//# sourceMappingURL=index.js.map