fixnow 1.0.2 → 2.0.1

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/fr.d.cts ADDED
@@ -0,0 +1,10 @@
1
+ import { CheckOptions, SpellIssue, BoundChecker, IsCorrectOptions } from './index.cjs';
2
+ export { DEFAULT_PROTECTED_PATTERN, Dictionary, LANGUAGES, LanguageInfo, tokenize } from './index.cjs';
3
+
4
+ declare const checker: BoundChecker;
5
+ declare const check: (text: string, options?: Omit<CheckOptions, "language">) => Promise<SpellIssue[]>;
6
+ declare const suggest: (word: string, max?: number) => Promise<string[]>;
7
+ declare const isCorrect: (word: string, options?: IsCorrectOptions) => Promise<boolean>;
8
+ declare const warmup: () => Promise<void>;
9
+
10
+ export { BoundChecker, CheckOptions, IsCorrectOptions, SpellIssue, check, checker, isCorrect, suggest, warmup };
package/dist/fr.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ import { CheckOptions, SpellIssue, BoundChecker, IsCorrectOptions } from './index.js';
2
+ export { DEFAULT_PROTECTED_PATTERN, Dictionary, LANGUAGES, LanguageInfo, tokenize } from './index.js';
3
+
4
+ declare const checker: BoundChecker;
5
+ declare const check: (text: string, options?: Omit<CheckOptions, "language">) => Promise<SpellIssue[]>;
6
+ declare const suggest: (word: string, max?: number) => Promise<string[]>;
7
+ declare const isCorrect: (word: string, options?: IsCorrectOptions) => Promise<boolean>;
8
+ declare const warmup: () => Promise<void>;
9
+
10
+ export { BoundChecker, CheckOptions, IsCorrectOptions, SpellIssue, check, checker, isCorrect, suggest, warmup };
package/dist/fr.js ADDED
@@ -0,0 +1,20 @@
1
+ import {
2
+ DEFAULT_PROTECTED_PATTERN,
3
+ LANGUAGES,
4
+ createChecker,
5
+ tokenize
6
+ } from "./chunk-MSMQKHBH.js";
7
+
8
+ // src/entries/fr.ts
9
+ var checker = createChecker("fr");
10
+ var { check, suggest, isCorrect, warmup } = checker;
11
+ export {
12
+ DEFAULT_PROTECTED_PATTERN,
13
+ LANGUAGES,
14
+ check,
15
+ checker,
16
+ isCorrect,
17
+ suggest,
18
+ tokenize,
19
+ warmup
20
+ };
package/dist/index.cjs CHANGED
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var src_exports = {};
22
22
  __export(src_exports, {
23
+ DEFAULT_PROTECTED_PATTERN: () => DEFAULT_PROTECTED_PATTERN,
23
24
  LANGUAGES: () => LANGUAGES,
24
25
  SUPPORTED_LANGUAGES: () => SUPPORTED_LANGUAGES,
25
26
  checkText: () => checkText,
@@ -4832,11 +4833,11 @@ function consolidate(root) {
4832
4833
  knownMap.set(orig, n);
4833
4834
  return n;
4834
4835
  }
4835
- function process(n) {
4836
+ function process2(n) {
4836
4837
  if (cached.has(n)) return n;
4837
4838
  if (Object.isFrozen(n)) return knownMap.get(n) || deepCopy(n);
4838
4839
  if (n.c) {
4839
- const children = Object.entries(n.c).sort((a, b) => a[0] < b[0] ? -1 : 1).map(([k, n2]) => [k, process(n2)]);
4840
+ const children = Object.entries(n.c).sort((a, b) => a[0] < b[0] ? -1 : 1).map(([k, n2]) => [k, process2(n2)]);
4840
4841
  n.c = Object.fromEntries(children);
4841
4842
  }
4842
4843
  const sig = signature(n);
@@ -4852,7 +4853,7 @@ function consolidate(root) {
4852
4853
  };
4853
4854
  signatures.set(signature(eow), eow);
4854
4855
  cached.set(eow, count2++);
4855
- return trieNodeToRoot(process(root), root);
4856
+ return trieNodeToRoot(process2(root), root);
4856
4857
  }
4857
4858
  function decodeBTrie(data) {
4858
4859
  return TrieBlob.decodeBin(data);
@@ -5902,7 +5903,21 @@ function isSupportedLanguage(code) {
5902
5903
  }
5903
5904
 
5904
5905
  // src/dictionary.ts
5905
- var PACKAGE_ROOT = (0, import_node_path.join)((0, import_node_path.dirname)((0, import_node_url.fileURLToPath)(importMetaUrl)), "..");
5906
+ function resolvePackageRoot() {
5907
+ let url;
5908
+ try {
5909
+ url = importMetaUrl;
5910
+ } catch {
5911
+ url = void 0;
5912
+ }
5913
+ if (url) {
5914
+ return (0, import_node_path.join)((0, import_node_path.dirname)((0, import_node_url.fileURLToPath)(url)), "..");
5915
+ }
5916
+ throw new Error(
5917
+ "fixnow could not locate its dictionaries. Mark 'fixnow' as external in your bundler (esbuild: external: ['fixnow']) so it loads from node_modules."
5918
+ );
5919
+ }
5920
+ var PACKAGE_ROOT = resolvePackageRoot();
5906
5921
  var TrieDictionary = class {
5907
5922
  constructor(trie, compound) {
5908
5923
  this.trie = trie;
@@ -5917,7 +5932,9 @@ var TrieDictionary = class {
5917
5932
  return this.trie.suggest(word, { numSuggestions: max2 });
5918
5933
  }
5919
5934
  };
5920
- var cache = /* @__PURE__ */ new Map();
5935
+ var CACHE_SYMBOL = /* @__PURE__ */ Symbol.for("fixnow.dictionaryCache.v2");
5936
+ var globalRegistry = globalThis;
5937
+ var cache = globalRegistry[CACHE_SYMBOL] ?? (globalRegistry[CACHE_SYMBOL] = /* @__PURE__ */ new Map());
5921
5938
  function loadDictionary(language) {
5922
5939
  if (!isSupportedLanguage(language)) {
5923
5940
  return Promise.reject(
@@ -5939,7 +5956,16 @@ function loadDictionary(language) {
5939
5956
  async function decode(language) {
5940
5957
  const info = LANGUAGES[language];
5941
5958
  const file = (0, import_node_path.join)(PACKAGE_ROOT, "dictionaries", language, info.trie);
5942
- const text = (0, import_node_zlib.gunzipSync)(await (0, import_promises.readFile)(file)).toString("utf8");
5959
+ let buf;
5960
+ try {
5961
+ buf = await (0, import_promises.readFile)(file);
5962
+ } catch (cause) {
5963
+ throw new Error(
5964
+ `fixnow could not read its "${language}" dictionary at ${file}. If you bundle your app, mark 'fixnow' as external (esbuild: external: ['fixnow']) so it loads from node_modules at runtime.`,
5965
+ { cause }
5966
+ );
5967
+ }
5968
+ const text = (0, import_node_zlib.gunzipSync)(buf).toString("utf8");
5943
5969
  return new TrieDictionary(decodeTrie(text), info.compound ?? false);
5944
5970
  }
5945
5971
  function warmup(language) {
@@ -5973,15 +5999,10 @@ var ENCLITICS = [
5973
5999
  ];
5974
6000
  var ACUTE_ACCENT = {
5975
6001
  a: "\xE1",
5976
- // á
5977
6002
  e: "\xE9",
5978
- // é
5979
6003
  i: "\xED",
5980
- // í
5981
6004
  o: "\xF3",
5982
- // ó
5983
6005
  u: "\xFA"
5984
- // ú
5985
6006
  };
5986
6007
  function deaccent(value) {
5987
6008
  return value.normalize("NFD").replace(/[̀-ͯ]/g, "");
@@ -6014,26 +6035,34 @@ function isEncliticVerb(lowerWord, dict) {
6014
6035
  }
6015
6036
  return false;
6016
6037
  }
6017
- function acceptSpanish(word, dict, strict) {
6038
+ function acceptSpanish(word, dict, caseSensitive, acceptAccentOmissions) {
6018
6039
  const lower = word.toLowerCase();
6019
- const inDictionary = strict ? dict.has(word) || dict.has(lower) : dict.has(word) || matchesIgnoringAccents(lower, dict);
6040
+ const inDictionary = caseSensitive ? dict.has(word) || acceptAccentOmissions && word === lower && matchesIgnoringAccents(lower, dict) : acceptAccentOmissions ? dict.has(word) || matchesIgnoringAccents(lower, dict) : dict.has(word) || dict.has(lower);
6020
6041
  return inDictionary || isEncliticVerb(lower, dict);
6021
6042
  }
6022
6043
 
6023
6044
  // src/lang/index.ts
6024
- function isAccepted(word, language, dict, strict) {
6025
- if (language === "es") return acceptSpanish(word, dict, strict);
6026
- return dict.has(word) || dict.has(word.toLowerCase());
6045
+ function isAccepted(word, language, dict, caseSensitive, acceptAccentOmissions) {
6046
+ if (language === "es") return acceptSpanish(word, dict, caseSensitive, acceptAccentOmissions);
6047
+ if (dict.has(word)) return true;
6048
+ if (!caseSensitive && dict.has(word.toLowerCase())) return true;
6049
+ return false;
6027
6050
  }
6028
6051
 
6029
6052
  // src/tokenize.ts
6030
- var PROTECTED_PATTERN = /\[(?:Image|Code|Text) #\d+[^\]\n]*\]|\[Skills? #[^\]\n]+\]|\/skills #\d+|\/skill\b|```[\s\S]*?```|`[^`\n]+`|https?:\/\/[^\s"'`<>]+|[\w.-]+@[\w.-]+\.\w{2,}|(?:\.{1,2}\/|~\/|\/)[^\s"'`<>]+|[A-Za-z]:\\[^\s"'`<>]+|#[0-9a-fA-F]{3,8}\b|\b[A-Z][A-Z0-9_]{1,}\b|(?<!\S)--?[A-Za-z][\w-]*(?:=[^\s"'`<>]+)?|\b(?:@[\w.-]+\/)?[\w.-]+@[\w.-]+\b|\b[\w.-]+\.(?:ts|tsx|js|jsx|mjs|cjs|json|html|css|scss|sass|md|mdx|svg|png|jpg|jpeg|gif|webp|yml|yaml|toml|env|lock)\b|\b[$A-Za-z_][\w$]*(?:[._:$][\w$-]+)+\b/g;
6053
+ var DEFAULT_PROTECTED_PATTERN = /```[\s\S]*?```|`[^`\n]+`|https?:\/\/[^\s"'`<>]+|[\w.-]+@[\w.-]+\.\w{2,}|(?:\.{1,2}\/|~\/|\/)[^\s"'`<>]+|[A-Za-z]:\\[^\s"'`<>]+|#[0-9a-fA-F]{3,8}\b|\b[A-Z][A-Z0-9_]{1,}\b|(?<!\S)--?[A-Za-z][\w-]*(?:=[^\s"'`<>]+)?|\b(?:@[\w.-]+\/)?[\w.-]+@[\w.-]+\b|\b[\w.-]+\.(?:ts|tsx|js|jsx|mjs|cjs|json|html|css|scss|sass|md|mdx|svg|png|jpg|jpeg|gif|webp|yml|yaml|toml|env|lock)\b|\b[$A-Za-z_][\w$]*(?:[._:$][\w$-]+)+\b/g;
6031
6054
  var WORD_PATTERN = /[\p{L}\p{M}]+/gu;
6032
- function* tokenize(text) {
6055
+ function* tokenize(text, protectedSegments) {
6033
6056
  const protectedRanges = [];
6034
- for (const match of text.matchAll(PROTECTED_PATTERN)) {
6035
- const start = match.index ?? 0;
6036
- protectedRanges.push([start, start + match[0].length]);
6057
+ if (protectedSegments !== false) {
6058
+ const patterns = protectedSegments == null ? [DEFAULT_PROTECTED_PATTERN] : Array.isArray(protectedSegments) ? protectedSegments : [protectedSegments];
6059
+ for (const pattern of patterns) {
6060
+ const re = pattern.flags.includes("g") ? pattern : new RegExp(pattern.source, pattern.flags + "g");
6061
+ for (const match of text.matchAll(re)) {
6062
+ const start = match.index ?? 0;
6063
+ protectedRanges.push([start, start + match[0].length]);
6064
+ }
6065
+ }
6037
6066
  }
6038
6067
  const isProtected = (offset) => protectedRanges.some(([start, end]) => offset >= start && offset < end);
6039
6068
  for (const match of text.matchAll(WORD_PATTERN)) {
@@ -6044,16 +6073,15 @@ function* tokenize(text) {
6044
6073
  }
6045
6074
 
6046
6075
  // src/checker.ts
6047
- var DEFAULT_LANGUAGE = "es";
6048
6076
  var DEFAULT_MIN_WORD_LENGTH = 3;
6049
6077
  var DEFAULT_MAX_SUGGESTIONS = 5;
6050
6078
  var MAX_VERDICT_CACHE = 5e3;
6051
6079
  var verdictCache = /* @__PURE__ */ new Map();
6052
- function acceptedVerdict(word, language, strict, dict) {
6053
- const key = `${language}:${strict ? 1 : 0}:${word}`;
6080
+ function acceptedVerdict(word, language, caseSensitive, acceptAccentOmissions, dict) {
6081
+ const key = `${language}:${caseSensitive ? 1 : 0}:${acceptAccentOmissions ? 1 : 0}:${word}`;
6054
6082
  const cached = verdictCache.get(key);
6055
6083
  if (cached !== void 0) return cached;
6056
- const accepted = isAccepted(word, language, dict, strict);
6084
+ const accepted = isAccepted(word, language, dict, caseSensitive, acceptAccentOmissions);
6057
6085
  if (verdictCache.size >= MAX_VERDICT_CACHE) {
6058
6086
  const oldest = verdictCache.keys().next().value;
6059
6087
  if (oldest !== void 0) verdictCache.delete(oldest);
@@ -6061,11 +6089,30 @@ function acceptedVerdict(word, language, strict, dict) {
6061
6089
  verdictCache.set(key, accepted);
6062
6090
  return accepted;
6063
6091
  }
6064
- async function checkText(text, options = {}) {
6092
+ var strictDeprecationWarned = false;
6093
+ function resolveStrictness(options) {
6094
+ let caseSensitive = options.caseSensitive;
6095
+ let acceptAccentOmissions = options.acceptAccentOmissions;
6096
+ if ("strict" in options && options.strict !== void 0) {
6097
+ if (!strictDeprecationWarned && process.env.NODE_ENV !== "production") {
6098
+ console.warn(
6099
+ "[fixnow] `strict` is deprecated; use `caseSensitive` and `acceptAccentOmissions` instead."
6100
+ );
6101
+ strictDeprecationWarned = true;
6102
+ }
6103
+ caseSensitive ??= false;
6104
+ acceptAccentOmissions ??= options.strict === false && options.language === "es";
6105
+ }
6106
+ return {
6107
+ caseSensitive: caseSensitive ?? false,
6108
+ acceptAccentOmissions: acceptAccentOmissions ?? false
6109
+ };
6110
+ }
6111
+ async function checkText(text, options) {
6065
6112
  if (!text || text.trim().length < 2) return [];
6066
- const language = options.language ?? DEFAULT_LANGUAGE;
6113
+ const { language } = options;
6067
6114
  const minWordLength = options.minWordLength ?? DEFAULT_MIN_WORD_LENGTH;
6068
- const strict = options.strict ?? false;
6115
+ const { caseSensitive, acceptAccentOmissions } = resolveStrictness(options);
6069
6116
  const withSuggestions = options.suggestions ?? false;
6070
6117
  const maxSuggestions = options.maxSuggestions ?? DEFAULT_MAX_SUGGESTIONS;
6071
6118
  const ignore = toLowerSet(options.ignoreWords);
@@ -6078,7 +6125,7 @@ async function checkText(text, options = {}) {
6078
6125
  return issue;
6079
6126
  };
6080
6127
  const issues = [];
6081
- for (const { word, offset } of tokenize(text)) {
6128
+ for (const { word, offset } of tokenize(text, options.protectedSegments)) {
6082
6129
  const lower = word.toLowerCase();
6083
6130
  if (ignore?.has(lower)) continue;
6084
6131
  if (isProtectedWord?.(word)) continue;
@@ -6087,14 +6134,15 @@ async function checkText(text, options = {}) {
6087
6134
  continue;
6088
6135
  }
6089
6136
  if (word.length < minWordLength) continue;
6090
- if (acceptedVerdict(word, language, strict, dict)) continue;
6137
+ if (acceptedVerdict(word, language, caseSensitive, acceptAccentOmissions, dict)) continue;
6091
6138
  issues.push(makeIssue(word, offset));
6092
6139
  }
6093
6140
  return issues;
6094
6141
  }
6095
- async function isCorrect(word, language = DEFAULT_LANGUAGE, strict = false) {
6142
+ async function isCorrect(word, language, options = {}) {
6096
6143
  const dict = await loadDictionary(language);
6097
- return acceptedVerdict(word, language, strict, dict);
6144
+ const { caseSensitive, acceptAccentOmissions } = resolveStrictness({ ...options, language });
6145
+ return acceptedVerdict(word, language, caseSensitive, acceptAccentOmissions, dict);
6098
6146
  }
6099
6147
  function toLowerSet(words) {
6100
6148
  if (!words) return void 0;
@@ -6109,16 +6157,17 @@ function createChecker(language) {
6109
6157
  language,
6110
6158
  check: (text, options) => checkText(text, { ...options, language }),
6111
6159
  suggest: async (word, max2 = 5) => (await loadDictionary(language)).suggest(word, max2),
6112
- isCorrect: (word, strict = false) => isCorrect(word, language, strict),
6160
+ isCorrect: (word, options) => isCorrect(word, language, options),
6113
6161
  warmup: () => warmup(language)
6114
6162
  };
6115
6163
  }
6116
- async function suggest(word, options = {}) {
6117
- const dict = await loadDictionary(options.language ?? "es");
6164
+ async function suggest(word, options) {
6165
+ const dict = await loadDictionary(options.language);
6118
6166
  return dict.suggest(word, options.max ?? 5);
6119
6167
  }
6120
6168
  // Annotate the CommonJS export names for ESM import in node:
6121
6169
  0 && (module.exports = {
6170
+ DEFAULT_PROTECTED_PATTERN,
6122
6171
  LANGUAGES,
6123
6172
  SUPPORTED_LANGUAGES,
6124
6173
  checkText,
package/dist/index.d.cts CHANGED
@@ -26,11 +26,19 @@ interface SpellIssue {
26
26
  suggestions?: string[];
27
27
  }
28
28
  interface CheckOptions {
29
- /** Dictionary to check against. Defaults to `'es'`. */
30
- language?: LanguageCode;
29
+ /** Dictionary to check against. Required. */
30
+ language: LanguageCode;
31
+ /** When true, dictionary lookups are case-sensitive. Default: false. */
32
+ caseSensitive?: boolean;
31
33
  /**
32
- * Spanish only: when true, accent omissions (e.g. "codigo" for "código") are
33
- * flagged. When false (default) they are accepted as harmless.
34
+ * Spanish-specific. When true, words missing an acute accent
35
+ * (e.g. "codigo" for "código") are accepted as correct. Default: false.
36
+ * No effect for any other language.
37
+ */
38
+ acceptAccentOmissions?: boolean;
39
+ /**
40
+ * @deprecated Removed in 3.0.0. Use `caseSensitive` and
41
+ * `acceptAccentOmissions` instead.
34
42
  */
35
43
  strict?: boolean;
36
44
  /** Attach correction suggestions to every issue. Defaults to false. */
@@ -49,6 +57,21 @@ interface CheckOptions {
49
57
  flagWords?: Iterable<string>;
50
58
  /** Custom predicate to skip a word before it is checked (e.g. protected terms). */
51
59
  isProtectedWord?: (word: string) => boolean;
60
+ /**
61
+ * Override or disable the protected-segment tokenizer pattern. See
62
+ * `tokenize` for details. Defaults to the bundled default pattern.
63
+ */
64
+ protectedSegments?: RegExp | RegExp[] | false;
65
+ }
66
+ /** Options for `isCorrect` / bound checker `isCorrect`. */
67
+ interface IsCorrectOptions {
68
+ /** When true, dictionary lookups are case-sensitive. Default: false. */
69
+ caseSensitive?: boolean;
70
+ /**
71
+ * Spanish-specific. When true, words missing an acute accent are accepted
72
+ * as correct. Default: false. No effect for any other language.
73
+ */
74
+ acceptAccentOmissions?: boolean;
52
75
  }
53
76
  /** A loaded, decoded dictionary. Membership and suggestion lookups are synchronous. */
54
77
  interface Dictionary {
@@ -59,9 +82,11 @@ interface Dictionary {
59
82
  }
60
83
 
61
84
  /** Finds misspelled words in `text` for the given language. */
62
- declare function checkText(text: string, options?: CheckOptions): Promise<SpellIssue[]>;
85
+ declare function checkText(text: string, options: CheckOptions): Promise<SpellIssue[]>;
63
86
  /** Whether a single word is correctly spelled in the given language. */
64
- declare function isCorrect(word: string, language?: LanguageCode, strict?: boolean): Promise<boolean>;
87
+ declare function isCorrect(word: string, language: LanguageCode, options?: IsCorrectOptions & {
88
+ strict?: boolean;
89
+ }): Promise<boolean>;
65
90
 
66
91
  /** Loads and decodes a language dictionary, caching the result. */
67
92
  declare function loadDictionary(language: LanguageCode): Promise<Dictionary>;
@@ -71,22 +96,32 @@ declare function loadDictionary(language: LanguageCode): Promise<Dictionary>;
71
96
  */
72
97
  declare function warmup(language?: LanguageCode | LanguageCode[]): Promise<void>;
73
98
 
99
+ declare const DEFAULT_PROTECTED_PATTERN: RegExp;
74
100
  interface Token {
75
101
  word: string;
76
102
  offset: number;
77
103
  }
78
104
  /**
79
105
  * Yields candidate words from `text`, skipping anything inside a protected
80
- * segment (code, URLs, paths, acronyms, …).
106
+ * segment.
107
+ *
108
+ * `protectedSegments` controls what is skipped:
109
+ * - `undefined` (default) → the bundled {@link DEFAULT_PROTECTED_PATTERN}.
110
+ * - `RegExp` / `RegExp[]` → use the given patterns instead of the default.
111
+ * Pass `[DEFAULT_PROTECTED_PATTERN, myPattern]` to compose.
112
+ * - `false` → no segment protection at all.
113
+ *
114
+ * Non-global regexes are auto-wrapped with the `g` flag; originals are never
115
+ * mutated.
81
116
  */
82
- declare function tokenize(text: string): Generator<Token>;
117
+ declare function tokenize(text: string, protectedSegments?: RegExp | RegExp[] | false): Generator<Token>;
83
118
 
84
119
  /** A checker bound to a single language, for convenient repeated use. */
85
120
  interface BoundChecker {
86
121
  readonly language: LanguageCode;
87
122
  check(text: string, options?: Omit<CheckOptions, 'language'>): Promise<SpellIssue[]>;
88
123
  suggest(word: string, max?: number): Promise<string[]>;
89
- isCorrect(word: string, strict?: boolean): Promise<boolean>;
124
+ isCorrect(word: string, options?: IsCorrectOptions): Promise<boolean>;
90
125
  warmup(): Promise<void>;
91
126
  }
92
127
  /**
@@ -99,9 +134,9 @@ interface BoundChecker {
99
134
  */
100
135
  declare function createChecker(language: LanguageCode): BoundChecker;
101
136
  /** Correction suggestions for a single word. */
102
- declare function suggest(word: string, options?: {
103
- language?: LanguageCode;
137
+ declare function suggest(word: string, options: {
138
+ language: LanguageCode;
104
139
  max?: number;
105
140
  }): Promise<string[]>;
106
141
 
107
- export { type BoundChecker, type CheckOptions, type Dictionary, LANGUAGES, type LanguageCode, type LanguageInfo, SUPPORTED_LANGUAGES, type SpellIssue, checkText, createChecker, isCorrect, isSupportedLanguage, loadDictionary, suggest, tokenize, warmup };
142
+ export { type BoundChecker, type CheckOptions, DEFAULT_PROTECTED_PATTERN, type Dictionary, type IsCorrectOptions, LANGUAGES, type LanguageCode, type LanguageInfo, SUPPORTED_LANGUAGES, type SpellIssue, checkText, createChecker, isCorrect, isSupportedLanguage, loadDictionary, suggest, tokenize, warmup };
package/dist/index.d.ts CHANGED
@@ -26,11 +26,19 @@ interface SpellIssue {
26
26
  suggestions?: string[];
27
27
  }
28
28
  interface CheckOptions {
29
- /** Dictionary to check against. Defaults to `'es'`. */
30
- language?: LanguageCode;
29
+ /** Dictionary to check against. Required. */
30
+ language: LanguageCode;
31
+ /** When true, dictionary lookups are case-sensitive. Default: false. */
32
+ caseSensitive?: boolean;
31
33
  /**
32
- * Spanish only: when true, accent omissions (e.g. "codigo" for "código") are
33
- * flagged. When false (default) they are accepted as harmless.
34
+ * Spanish-specific. When true, words missing an acute accent
35
+ * (e.g. "codigo" for "código") are accepted as correct. Default: false.
36
+ * No effect for any other language.
37
+ */
38
+ acceptAccentOmissions?: boolean;
39
+ /**
40
+ * @deprecated Removed in 3.0.0. Use `caseSensitive` and
41
+ * `acceptAccentOmissions` instead.
34
42
  */
35
43
  strict?: boolean;
36
44
  /** Attach correction suggestions to every issue. Defaults to false. */
@@ -49,6 +57,21 @@ interface CheckOptions {
49
57
  flagWords?: Iterable<string>;
50
58
  /** Custom predicate to skip a word before it is checked (e.g. protected terms). */
51
59
  isProtectedWord?: (word: string) => boolean;
60
+ /**
61
+ * Override or disable the protected-segment tokenizer pattern. See
62
+ * `tokenize` for details. Defaults to the bundled default pattern.
63
+ */
64
+ protectedSegments?: RegExp | RegExp[] | false;
65
+ }
66
+ /** Options for `isCorrect` / bound checker `isCorrect`. */
67
+ interface IsCorrectOptions {
68
+ /** When true, dictionary lookups are case-sensitive. Default: false. */
69
+ caseSensitive?: boolean;
70
+ /**
71
+ * Spanish-specific. When true, words missing an acute accent are accepted
72
+ * as correct. Default: false. No effect for any other language.
73
+ */
74
+ acceptAccentOmissions?: boolean;
52
75
  }
53
76
  /** A loaded, decoded dictionary. Membership and suggestion lookups are synchronous. */
54
77
  interface Dictionary {
@@ -59,9 +82,11 @@ interface Dictionary {
59
82
  }
60
83
 
61
84
  /** Finds misspelled words in `text` for the given language. */
62
- declare function checkText(text: string, options?: CheckOptions): Promise<SpellIssue[]>;
85
+ declare function checkText(text: string, options: CheckOptions): Promise<SpellIssue[]>;
63
86
  /** Whether a single word is correctly spelled in the given language. */
64
- declare function isCorrect(word: string, language?: LanguageCode, strict?: boolean): Promise<boolean>;
87
+ declare function isCorrect(word: string, language: LanguageCode, options?: IsCorrectOptions & {
88
+ strict?: boolean;
89
+ }): Promise<boolean>;
65
90
 
66
91
  /** Loads and decodes a language dictionary, caching the result. */
67
92
  declare function loadDictionary(language: LanguageCode): Promise<Dictionary>;
@@ -71,22 +96,32 @@ declare function loadDictionary(language: LanguageCode): Promise<Dictionary>;
71
96
  */
72
97
  declare function warmup(language?: LanguageCode | LanguageCode[]): Promise<void>;
73
98
 
99
+ declare const DEFAULT_PROTECTED_PATTERN: RegExp;
74
100
  interface Token {
75
101
  word: string;
76
102
  offset: number;
77
103
  }
78
104
  /**
79
105
  * Yields candidate words from `text`, skipping anything inside a protected
80
- * segment (code, URLs, paths, acronyms, …).
106
+ * segment.
107
+ *
108
+ * `protectedSegments` controls what is skipped:
109
+ * - `undefined` (default) → the bundled {@link DEFAULT_PROTECTED_PATTERN}.
110
+ * - `RegExp` / `RegExp[]` → use the given patterns instead of the default.
111
+ * Pass `[DEFAULT_PROTECTED_PATTERN, myPattern]` to compose.
112
+ * - `false` → no segment protection at all.
113
+ *
114
+ * Non-global regexes are auto-wrapped with the `g` flag; originals are never
115
+ * mutated.
81
116
  */
82
- declare function tokenize(text: string): Generator<Token>;
117
+ declare function tokenize(text: string, protectedSegments?: RegExp | RegExp[] | false): Generator<Token>;
83
118
 
84
119
  /** A checker bound to a single language, for convenient repeated use. */
85
120
  interface BoundChecker {
86
121
  readonly language: LanguageCode;
87
122
  check(text: string, options?: Omit<CheckOptions, 'language'>): Promise<SpellIssue[]>;
88
123
  suggest(word: string, max?: number): Promise<string[]>;
89
- isCorrect(word: string, strict?: boolean): Promise<boolean>;
124
+ isCorrect(word: string, options?: IsCorrectOptions): Promise<boolean>;
90
125
  warmup(): Promise<void>;
91
126
  }
92
127
  /**
@@ -99,9 +134,9 @@ interface BoundChecker {
99
134
  */
100
135
  declare function createChecker(language: LanguageCode): BoundChecker;
101
136
  /** Correction suggestions for a single word. */
102
- declare function suggest(word: string, options?: {
103
- language?: LanguageCode;
137
+ declare function suggest(word: string, options: {
138
+ language: LanguageCode;
104
139
  max?: number;
105
140
  }): Promise<string[]>;
106
141
 
107
- export { type BoundChecker, type CheckOptions, type Dictionary, LANGUAGES, type LanguageCode, type LanguageInfo, SUPPORTED_LANGUAGES, type SpellIssue, checkText, createChecker, isCorrect, isSupportedLanguage, loadDictionary, suggest, tokenize, warmup };
142
+ export { type BoundChecker, type CheckOptions, DEFAULT_PROTECTED_PATTERN, type Dictionary, type IsCorrectOptions, LANGUAGES, type LanguageCode, type LanguageInfo, SUPPORTED_LANGUAGES, type SpellIssue, checkText, createChecker, isCorrect, isSupportedLanguage, loadDictionary, suggest, tokenize, warmup };