@searpent/react-image-annotate 2.0.80 → 2.0.82-cand-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.
Files changed (57) hide show
  1. package/Annotator/examplePhotos.js +28 -28
  2. package/Annotator/index.js +15 -21
  3. package/Annotator/reducers/combine-reducers.js +18 -3
  4. package/Annotator/reducers/convert-expanding-line-to-polygon.js +15 -16
  5. package/Annotator/reducers/get-implied-video-regions.js +18 -30
  6. package/ClassSelectionMenu/index.js +8 -8
  7. package/Crosshairs/index.js +2 -2
  8. package/DebugSidebarBox/index.js +4 -4
  9. package/DemoSite/Editor.js +15 -15
  10. package/DemoSite/ErrorBoundaryDialog.js +3 -5
  11. package/DemoSite/index.js +3 -3
  12. package/Editor/annotation-plugin/annotation.js +1 -3
  13. package/Editor/index.js +12 -31
  14. package/Editor/readOnly.js +395 -47
  15. package/Errorer/index.js +2 -2
  16. package/FullImageSegmentationAnnotator/index.js +1 -1
  17. package/GroupSelectorSidebarBox/index.js +7 -7
  18. package/GroupsEditorSidebarBox/index.js +11 -11
  19. package/HelpSidebarBox/index.js +4 -4
  20. package/HighlightBox/index.js +3 -3
  21. package/HistorySidebarBox/index.js +8 -8
  22. package/ImageCanvas/index.js +16 -16
  23. package/ImageMask/index.js +1 -1
  24. package/ImageSelectorSidebarBox/index.js +7 -7
  25. package/KeyframeTimeline/index.js +30 -14
  26. package/KeyframesSelectorSidebarBox/index.js +8 -8
  27. package/LandingPage/index.js +12 -12
  28. package/Locker/index.js +2 -2
  29. package/MainLayout/RightSidebarItemsWrapper.js +1 -1
  30. package/MainLayout/icon-dictionary.js +11 -11
  31. package/MainLayout/index.js +25 -23
  32. package/MetadataEditorSidebarBox/index.js +18 -18
  33. package/PageSelector/index.js +21 -21
  34. package/PointDistances/index.js +4 -4
  35. package/PreventScrollToParents/index.js +3 -3
  36. package/RegionLabel/index.js +24 -24
  37. package/RegionSelectAndTransformBoxes/index.js +8 -8
  38. package/RegionSelectorSidebarBox/index.js +33 -33
  39. package/RegionShapes/index.js +22 -22
  40. package/RegionTags/index.js +6 -6
  41. package/SettingsDialog/index.js +4 -4
  42. package/SettingsProvider/index.js +1 -1
  43. package/Shortcuts/ShortcutField.js +3 -3
  44. package/Shortcuts/index.js +2 -2
  45. package/ShortcutsManager/index.js +9 -9
  46. package/Sidebar/index.js +7 -7
  47. package/SidebarBoxContainer/index.js +3 -3
  48. package/SmallToolButton/index.js +2 -2
  49. package/TagsSidebarBox/index.js +6 -6
  50. package/TaskDescriptionSidebarBox/index.js +4 -4
  51. package/Theme/index.js +2 -2
  52. package/VideoOrImageCanvasBackground/index.js +5 -5
  53. package/mj_smaz_hist.log +20015 -0
  54. package/package.json +4 -3
  55. package/utils/blocks-to-article.js +3 -3
  56. package/utils/get-landmarks-with-transform.js +13 -15
  57. package/utils/spellcheck-nspell.js +635 -0
@@ -0,0 +1,635 @@
1
+ import _regeneratorRuntime from "@babel/runtime/regenerator";
2
+ import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
3
+ import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
4
+
5
+ function _createForOfIteratorHelper(o) { if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (o = _unsupportedIterableToArray(o))) { var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var it, normalCompletion = true, didErr = false, err; return { s: function s() { it = o[Symbol.iterator](); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
6
+
7
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(n); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
8
+
9
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
10
+
11
+ /**
12
+ * Multi-language spellcheck system with priority-based language detection
13
+ *
14
+ * Language Detection Priority:
15
+ * 1. Explicit spellcheck language setting (setSpellcheckLanguage())
16
+ * 2. Text content analysis (character frequency)
17
+ * 3. Browser language preferences
18
+ * 4. Default fallback (en-US)
19
+ *
20
+ * Usage:
21
+ * - setSpellcheckEnabled(true) // Enable spellchecking (disabled by default for performance)
22
+ * - setSpellcheckLanguage('cs-CZ') // Set explicit language
23
+ * - setSpellcheckLanguage(null) // Clear setting (use auto-detection)
24
+ * - highlightMisspellingsInHtml(html, 'auto') // Auto-detect with priority
25
+ *
26
+ * Configuration:
27
+ * - Set REACT_APP_SPELLCHECK_ENABLED=true in .env file to enable spellchecking (default: disabled)
28
+ * - Or call setSpellcheckEnabled(true) programmatically at app startup to enable
29
+ */
30
+ // Simple nspell loader usable in the browser. It lazy-loads the aff/dic
31
+ // and exposes a singleton spell instance plus a helper to check words.
32
+ // Cache for different language spellcheckers
33
+ var spellInstances = new Map();
34
+ var loadPromises = new Map();
35
+ export function getSpell() {
36
+ return _getSpell.apply(this, arguments);
37
+ } // Available dictionaries mapping
38
+
39
+ function _getSpell() {
40
+ _getSpell = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
41
+ var lang,
42
+ result,
43
+ promise,
44
+ _args2 = arguments;
45
+ return _regeneratorRuntime.wrap(function _callee2$(_context2) {
46
+ while (1) {
47
+ switch (_context2.prev = _context2.next) {
48
+ case 0:
49
+ lang = _args2.length > 0 && _args2[0] !== undefined ? _args2[0] : 'en-US';
50
+
51
+ if (AVAILABLE_DICTIONARIES[lang]) {
52
+ _context2.next = 4;
53
+ break;
54
+ }
55
+
56
+ console.warn("Dictionary not available for language: ".concat(lang));
57
+ return _context2.abrupt("return", null);
58
+
59
+ case 4:
60
+ if (!spellInstances.has(lang)) {
61
+ _context2.next = 6;
62
+ break;
63
+ }
64
+
65
+ return _context2.abrupt("return", spellInstances.get(lang));
66
+
67
+ case 6:
68
+ if (!loadPromises.has(lang)) {
69
+ _context2.next = 11;
70
+ break;
71
+ }
72
+
73
+ _context2.next = 9;
74
+ return loadPromises.get(lang);
75
+
76
+ case 9:
77
+ result = _context2.sent;
78
+ return _context2.abrupt("return", result);
79
+
80
+ case 11:
81
+ promise = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
82
+ var _yield$import, nspell, dictName, affUrl, dicUrl, _yield$Promise$all, _yield$Promise$all2, affRes, dicRes, errorMsg, _yield$Promise$all3, _yield$Promise$all4, affBuf, dicBuf, utf8Decoder, affUtf8, enc, setMatch, raw, map, mapped, decoder, aff, dic, spellInstance;
83
+
84
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
85
+ while (1) {
86
+ switch (_context.prev = _context.next) {
87
+ case 0:
88
+ _context.prev = 0;
89
+ _context.next = 3;
90
+ return import('nspell');
91
+
92
+ case 3:
93
+ _yield$import = _context.sent;
94
+ nspell = _yield$import.default;
95
+ // Use the mapped dictionary name
96
+ dictName = AVAILABLE_DICTIONARIES[lang];
97
+ affUrl = "/dicts/".concat(dictName, ".aff");
98
+ dicUrl = "/dicts/".concat(dictName, ".dic");
99
+ console.log('Loading dictionary files:', affUrl, dicUrl);
100
+ _context.next = 11;
101
+ return Promise.all([fetch(affUrl, {
102
+ mode: 'cors'
103
+ }), fetch(dicUrl, {
104
+ mode: 'cors'
105
+ })]);
106
+
107
+ case 11:
108
+ _yield$Promise$all = _context.sent;
109
+ _yield$Promise$all2 = _slicedToArray(_yield$Promise$all, 2);
110
+ affRes = _yield$Promise$all2[0];
111
+ dicRes = _yield$Promise$all2[1];
112
+ console.log('Fetch responses:', affRes.status, dicRes.status);
113
+
114
+ if (!(!affRes.ok || !dicRes.ok)) {
115
+ _context.next = 22;
116
+ break;
117
+ }
118
+
119
+ errorMsg = "Failed to load dictionary files: ".concat(affUrl, " (").concat(affRes.status, "), ").concat(dicUrl, " (").concat(dicRes.status, ")");
120
+ console.error("[Spellcheck Error] ".concat(errorMsg));
121
+ console.error("[Spellcheck Error] Make sure dictionary files are served from /dicts/ path");
122
+ console.error("[Spellcheck Error] Check that public/dicts/ files are copied during build");
123
+ return _context.abrupt("return", null);
124
+
125
+ case 22:
126
+ _context.next = 24;
127
+ return Promise.all([affRes.arrayBuffer(), dicRes.arrayBuffer()]);
128
+
129
+ case 24:
130
+ _yield$Promise$all3 = _context.sent;
131
+ _yield$Promise$all4 = _slicedToArray(_yield$Promise$all3, 2);
132
+ affBuf = _yield$Promise$all4[0];
133
+ dicBuf = _yield$Promise$all4[1];
134
+ // Decode .aff as UTF-8 first to read SET <encoding>
135
+ utf8Decoder = new TextDecoder('utf-8');
136
+ affUtf8 = utf8Decoder.decode(affBuf);
137
+ enc = 'utf-8';
138
+ setMatch = /\n\s*SET\s+([^\r\n]+)/i.exec("\n" + affUtf8);
139
+
140
+ if (setMatch) {
141
+ raw = setMatch[1].trim(); // Map common Hunspell enc names to TextDecoder labels
142
+
143
+ map = {
144
+ 'UTF-8': 'utf-8',
145
+ 'UTF8': 'utf-8',
146
+ 'ISO8859-1': 'iso-8859-1',
147
+ 'ISO-8859-1': 'iso-8859-1',
148
+ 'ISO8859-2': 'iso-8859-2',
149
+ 'ISO-8859-2': 'iso-8859-2',
150
+ 'ISO8859-5': 'iso-8859-5',
151
+ 'ISO-8859-5': 'iso-8859-5',
152
+ 'KOI8-R': 'koi8-r',
153
+ 'KOI8-U': 'koi8-u',
154
+ 'WINDOWS-1250': 'windows-1250',
155
+ 'CP1250': 'windows-1250',
156
+ 'WINDOWS-1251': 'windows-1251',
157
+ 'CP1251': 'windows-1251',
158
+ 'WINDOWS-1252': 'windows-1252',
159
+ 'CP1252': 'windows-1252',
160
+ 'MICROSOFT-CP1251': 'windows-1251',
161
+ 'microsoft-cp1251': 'windows-1251'
162
+ };
163
+ mapped = map[raw.toUpperCase()] || raw;
164
+
165
+ try {
166
+ // Probe if browser supports it
167
+ new TextDecoder(mapped);
168
+ enc = mapped;
169
+ } catch (_) {
170
+ console.warn("Unsupported dictionary encoding '".concat(raw, "' resolved to '").concat(mapped, "'. Falling back to UTF-8."));
171
+ }
172
+ }
173
+
174
+ decoder = new TextDecoder(enc);
175
+ aff = enc === 'utf-8' ? affUtf8 : decoder.decode(affBuf);
176
+ dic = decoder.decode(dicBuf);
177
+ spellInstance = nspell(aff, dic);
178
+ spellInstances.set(lang, spellInstance);
179
+ console.log("Dictionary loaded successfully for ".concat(lang));
180
+ return _context.abrupt("return", spellInstance);
181
+
182
+ case 42:
183
+ _context.prev = 42;
184
+ _context.t0 = _context["catch"](0);
185
+ console.error("[Spellcheck Error] Failed to load dictionary for ".concat(lang, ":"), _context.t0);
186
+ return _context.abrupt("return", null);
187
+
188
+ case 46:
189
+ case "end":
190
+ return _context.stop();
191
+ }
192
+ }
193
+ }, _callee, null, [[0, 42]]);
194
+ }))();
195
+ loadPromises.set(lang, promise);
196
+ return _context2.abrupt("return", promise);
197
+
198
+ case 14:
199
+ case "end":
200
+ return _context2.stop();
201
+ }
202
+ }
203
+ }, _callee2);
204
+ }));
205
+ return _getSpell.apply(this, arguments);
206
+ }
207
+
208
+ var AVAILABLE_DICTIONARIES = {
209
+ 'en-US': 'en_US',
210
+ 'en': 'en_US',
211
+ 'cs-CZ': 'cs_CZ',
212
+ 'cs': 'cs_CZ',
213
+ 'sk-SK': 'sk_SK',
214
+ 'sk': 'sk_SK',
215
+ 'pt-BR': 'pt_BR',
216
+ 'pt_BR': 'pt_BR',
217
+ 'pt': 'pt_BR',
218
+ 'mk-MK': 'mk_MK',
219
+ 'mk': 'mk_MK'
220
+ }; // Spellcheck language setting (can be set by user)
221
+
222
+ var spellcheckLanguageSetting = null; // Spellcheck enabled/disabled flag
223
+ // Defaults to false (disabled) for performance. Enable via REACT_APP_SPELLCHECK_ENABLED=true or setSpellcheckEnabled()
224
+
225
+ var spellcheckEnabled = function () {
226
+ try {
227
+ // Check for environment variable (works in Create React App, Storybook, etc.)
228
+ if (typeof process !== 'undefined' && process.env && process.env.REACT_APP_SPELLCHECK_ENABLED !== undefined) {
229
+ var envValue = process.env.REACT_APP_SPELLCHECK_ENABLED;
230
+ console.log('[Spellcheck] REACT_APP_SPELLCHECK_ENABLED from env:', envValue);
231
+ var enabledFromEnv = envValue === 'true' || envValue === '1';
232
+ console.log('[Spellcheck] Initial spellcheckEnabled from env:', enabledFromEnv);
233
+ return enabledFromEnv;
234
+ }
235
+ } catch (e) {
236
+ // Ignore errors accessing process.env
237
+ console.warn('[Spellcheck] Failed to read REACT_APP_SPELLCHECK_ENABLED from process.env:', e);
238
+ }
239
+
240
+ console.log('[Spellcheck] REACT_APP_SPELLCHECK_ENABLED not set, defaulting spellcheckEnabled=false');
241
+ return false; // Default to disabled for performance
242
+ }(); // Function to enable/disable spellchecking
243
+ // Call this from your application to control spellchecking at runtime
244
+
245
+
246
+ export function setSpellcheckEnabled(enabled) {
247
+ spellcheckEnabled = Boolean(enabled);
248
+ console.log("Spellcheck ".concat(spellcheckEnabled ? 'enabled' : 'disabled'));
249
+ } // Function to check if spellchecking is enabled
250
+
251
+ export function isSpellcheckEnabled() {
252
+ return spellcheckEnabled;
253
+ } // Function to set spellcheck language preference
254
+
255
+ export function setSpellcheckLanguage(lang) {
256
+ if (lang && AVAILABLE_DICTIONARIES[lang]) {
257
+ spellcheckLanguageSetting = lang;
258
+ console.log("Spellcheck language set to: ".concat(lang));
259
+ } else if (lang === null) {
260
+ spellcheckLanguageSetting = null;
261
+ console.log('Spellcheck language setting cleared');
262
+ } else {
263
+ console.warn("Invalid spellcheck language: ".concat(lang, ". Available: ").concat(Object.keys(AVAILABLE_DICTIONARIES).join(', ')));
264
+ }
265
+ } // Function to get current spellcheck language setting
266
+
267
+ export function getSpellcheckLanguage() {
268
+ return spellcheckLanguageSetting;
269
+ } // Get browser language preferences for spellcheck
270
+
271
+ function getBrowserSpellcheckLanguage() {
272
+ if (typeof navigator === 'undefined') return 'en-US'; // Get browser language preferences
273
+
274
+ var languages = navigator.languages || [navigator.language || navigator.userLanguage || 'en-US']; // Find first available language
275
+
276
+ var _iterator = _createForOfIteratorHelper(languages),
277
+ _step;
278
+
279
+ try {
280
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
281
+ var lang = _step.value;
282
+ var normalized = lang.toLowerCase(); // Direct match
283
+
284
+ if (AVAILABLE_DICTIONARIES[lang]) return lang; // Match by prefix (e.g., 'en-US' matches 'en')
285
+
286
+ var prefix = normalized.split('-')[0];
287
+ if (AVAILABLE_DICTIONARIES[prefix]) return prefix; // Match by full language code
288
+
289
+ if (AVAILABLE_DICTIONARIES[normalized]) return normalized;
290
+ }
291
+ } catch (err) {
292
+ _iterator.e(err);
293
+ } finally {
294
+ _iterator.f();
295
+ }
296
+
297
+ return 'en-US'; // fallback
298
+ } // Enhanced language detection with priority: spellcheck setting → text analysis → browser settings
299
+
300
+
301
+ function detectLanguage(text) {
302
+ var browserLang = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
303
+ var spellcheckLang = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
304
+
305
+ // console.log(`Language detection inputs - browserLang: ${browserLang}, spellcheckLang: ${spellcheckLang}, text length: ${text ? text.length : 0}`)
306
+ // Priority 1: Use explicit spellcheck language setting if available
307
+ if (spellcheckLang && AVAILABLE_DICTIONARIES[spellcheckLang]) {
308
+ console.log("Using explicit spellcheck language: ".concat(spellcheckLang));
309
+ return spellcheckLang;
310
+ } // Priority 2: Detect from text content if available
311
+
312
+
313
+ if (text) {
314
+ // Check for Czech-specific characters first (highest priority for distinctive characters)
315
+ var czechChars = text.match(/[áčďéěíňóřšťúůýžÁČĎÉĚÍŇÓŘŠŤÚŮÝŽ]/g) || [];
316
+ var czechScore = czechChars.length; // Check for Slovak-specific characters
317
+
318
+ var slovakChars = text.match(/[áäčďéíĺľňóôŕšťúýžÁÄČĎÉÍĹĽŇÓÔŔŠŤÚÝŽ]/g) || [];
319
+ var slovakScore = slovakChars.length; // Check for Portuguese-specific characters (including Brazilian Portuguese)
320
+
321
+ var portugueseChars = text.match(/[áàâãäéêëíîïóôõöúûüçÁÀÂÃÄÉÊËÍÎÏÓÔÕÖÚÛÜÇ]/g) || [];
322
+ var portugueseScore = portugueseChars.length; // Check for Macedonian-specific Cyrillic characters
323
+ // Macedonian uses letters like ѓ (U+0453), ќ (U+045C), ѕ (U+0455), џ (U+045F), ј (U+0458)
324
+ // and their uppercase counterparts Ѓ (U+0403), Ќ (U+040C), Ѕ (U+0405), Џ (U+040F), Ј (U+0408)
325
+ // We also include the broader Cyrillic range to capture words.
326
+
327
+ var macedonianChars = text.match(/[ЃЌЅЏЈѓќѕџјА-Яа-яЀ-Џѐ-џ]/g) || [];
328
+ var macedonianScore = macedonianChars.length; // console.log(`Language detection scores - Czech: ${czechScore}, Slovak: ${slovakScore}, Portuguese: ${portugueseScore}`)
329
+ // Find the language with the highest score
330
+
331
+ var languageScores = [{
332
+ lang: 'cs-CZ',
333
+ score: czechScore,
334
+ name: 'Czech'
335
+ }, {
336
+ lang: 'sk-SK',
337
+ score: slovakScore,
338
+ name: 'Slovak'
339
+ }, {
340
+ lang: 'pt-BR',
341
+ score: portugueseScore,
342
+ name: 'Portuguese'
343
+ }, {
344
+ lang: 'mk-MK',
345
+ score: macedonianScore,
346
+ name: 'Macedonian'
347
+ }]; // Filter out languages with no score and check if dictionary is available
348
+
349
+ var validLanguages = languageScores.filter(function (lang) {
350
+ return lang.score > 0 && AVAILABLE_DICTIONARIES[lang.lang];
351
+ });
352
+
353
+ if (validLanguages.length > 0) {
354
+ // Sort by score (highest first) and return the top language
355
+ var bestMatch = validLanguages.sort(function (a, b) {
356
+ return b.score - a.score;
357
+ })[0]; // console.log(`Detected language from text: ${bestMatch.lang} (${bestMatch.name} diacritics: ${bestMatch.score})`)
358
+
359
+ return bestMatch.lang;
360
+ } // If we have text but no distinctive diacritics, it's likely English
361
+
362
+
363
+ if (text.trim().length > 0) {
364
+ // console.log(`Detected language from text: en-US (no distinctive diacritics found)`)
365
+ return 'en-US';
366
+ }
367
+ } // Priority 3: Fall back to browser language if available
368
+
369
+
370
+ if (browserLang && AVAILABLE_DICTIONARIES[browserLang]) {
371
+ console.log("Using browser language: ".concat(browserLang));
372
+ return browserLang;
373
+ } // Final fallback
374
+
375
+
376
+ console.log('Using default language: en-US');
377
+ return 'en-US';
378
+ }
379
+
380
+ export function findMisspellings(_x) {
381
+ return _findMisspellings.apply(this, arguments);
382
+ }
383
+
384
+ function _findMisspellings() {
385
+ _findMisspellings = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3(text) {
386
+ var lang,
387
+ browserLang,
388
+ spellcheckLang,
389
+ detectedLang,
390
+ spell,
391
+ wordRegex,
392
+ words,
393
+ miss,
394
+ _iterator2,
395
+ _step2,
396
+ w,
397
+ word,
398
+ _args3 = arguments;
399
+
400
+ return _regeneratorRuntime.wrap(function _callee3$(_context3) {
401
+ while (1) {
402
+ switch (_context3.prev = _context3.next) {
403
+ case 0:
404
+ lang = _args3.length > 1 && _args3[1] !== undefined ? _args3[1] : 'auto';
405
+
406
+ if (spellcheckEnabled) {
407
+ _context3.next = 3;
408
+ break;
409
+ }
410
+
411
+ return _context3.abrupt("return", []);
412
+
413
+ case 3:
414
+ _context3.prev = 3;
415
+ // Get browser language preferences
416
+ browserLang = getBrowserSpellcheckLanguage(); // Get spellcheck language setting
417
+
418
+ spellcheckLang = getSpellcheckLanguage(); // Auto-detect language if not specified
419
+
420
+ detectedLang = lang === 'auto' ? detectLanguage(text, browserLang, spellcheckLang) : lang; // Check if dictionary is available
421
+
422
+ if (AVAILABLE_DICTIONARIES[detectedLang]) {
423
+ _context3.next = 10;
424
+ break;
425
+ }
426
+
427
+ console.warn("Dictionary not available for ".concat(detectedLang, ", skipping spellcheck"));
428
+ return _context3.abrupt("return", []);
429
+
430
+ case 10:
431
+ _context3.next = 12;
432
+ return getSpell(detectedLang);
433
+
434
+ case 12:
435
+ spell = _context3.sent;
436
+
437
+ if (spell) {
438
+ _context3.next = 16;
439
+ break;
440
+ }
441
+
442
+ console.warn("[Spellcheck] Dictionary not available for ".concat(detectedLang, ", skipping spellcheck"));
443
+ return _context3.abrupt("return", []);
444
+
445
+ case 16:
446
+ // Unicode-aware word extraction across scripts (Latin, Cyrillic, etc.)
447
+ // Matches sequences of letters, allowing internal apostrophes/dashes.
448
+ wordRegex = /(?:[A-Za-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08C7\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D04-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1878\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u31A0-\u31BF\u31F0-\u31FF\u3400-\u4DBF\u4E00-\u9FFC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA7BF\uA7C2-\uA7CA\uA7F5-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB69\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF40\uDF42-\uDF49\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF]|\uD801[\uDC00-\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2\uDD00-\uDD23\uDE80-\uDEA9\uDEB0\uDEB1\uDF00-\uDF1C\uDF27\uDF30-\uDF45\uDFB0-\uDFC4\uDFE0-\uDFF6]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD44\uDD47\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC5F-\uDC61\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDEB8\uDF00-\uDF1A]|\uD806[\uDC00-\uDC2B\uDCA0-\uDCDF\uDCFF-\uDD06\uDD09\uDD0C-\uDD13\uDD15\uDD16\uDD18-\uDD2F\uDD3F\uDD41\uDDA0-\uDDA7\uDDAA-\uDDD0\uDDE1\uDDE3\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE89\uDE9D\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD89\uDD98\uDEE0-\uDEF2\uDFB0]|\uD808[\uDC00-\uDF99]|\uD809[\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD822\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879\uD880-\uD883][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDE40-\uDE7F\uDF00-\uDF4A\uDF50\uDF93-\uDF9F\uDFE0\uDFE1\uDFE3]|\uD821[\uDC00-\uDFF7]|\uD823[\uDC00-\uDCD5\uDD00-\uDD08]|\uD82C[\uDC00-\uDD1E\uDD50-\uDD52\uDD64-\uDD67\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD838[\uDD00-\uDD2C\uDD37-\uDD3D\uDD4E\uDEC0-\uDEEB]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43\uDD4B]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDEDD\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uD884[\uDC00-\uDF4A])(?:['\x2DA-Za-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08C7\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D04-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1878\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2019\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u31A0-\u31BF\u31F0-\u31FF\u3400-\u4DBF\u4E00-\u9FFC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA7BF\uA7C2-\uA7CA\uA7F5-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB69\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF40\uDF42-\uDF49\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF]|\uD801[\uDC00-\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2\uDD00-\uDD23\uDE80-\uDEA9\uDEB0\uDEB1\uDF00-\uDF1C\uDF27\uDF30-\uDF45\uDFB0-\uDFC4\uDFE0-\uDFF6]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD44\uDD47\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC5F-\uDC61\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDEB8\uDF00-\uDF1A]|\uD806[\uDC00-\uDC2B\uDCA0-\uDCDF\uDCFF-\uDD06\uDD09\uDD0C-\uDD13\uDD15\uDD16\uDD18-\uDD2F\uDD3F\uDD41\uDDA0-\uDDA7\uDDAA-\uDDD0\uDDE1\uDDE3\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE89\uDE9D\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD89\uDD98\uDEE0-\uDEF2\uDFB0]|\uD808[\uDC00-\uDF99]|\uD809[\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD822\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879\uD880-\uD883][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDE40-\uDE7F\uDF00-\uDF4A\uDF50\uDF93-\uDF9F\uDFE0\uDFE1\uDFE3]|\uD821[\uDC00-\uDFF7]|\uD823[\uDC00-\uDCD5\uDD00-\uDD08]|\uD82C[\uDC00-\uDD1E\uDD50-\uDD52\uDD64-\uDD67\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD838[\uDD00-\uDD2C\uDD37-\uDD3D\uDD4E\uDEC0-\uDEEB]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43\uDD4B]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDEDD\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uD884[\uDC00-\uDF4A])*/g;
449
+ words = text.match(wordRegex) || [];
450
+ miss = new Set();
451
+ _iterator2 = _createForOfIteratorHelper(words);
452
+ _context3.prev = 20;
453
+
454
+ _iterator2.s();
455
+
456
+ case 22:
457
+ if ((_step2 = _iterator2.n()).done) {
458
+ _context3.next = 30;
459
+ break;
460
+ }
461
+
462
+ w = _step2.value;
463
+ word = w.replace(/^'+|'+$/g, '');
464
+
465
+ if (word) {
466
+ _context3.next = 27;
467
+ break;
468
+ }
469
+
470
+ return _context3.abrupt("continue", 28);
471
+
472
+ case 27:
473
+ if (!spell.correct(word)) miss.add(word);
474
+
475
+ case 28:
476
+ _context3.next = 22;
477
+ break;
478
+
479
+ case 30:
480
+ _context3.next = 35;
481
+ break;
482
+
483
+ case 32:
484
+ _context3.prev = 32;
485
+ _context3.t0 = _context3["catch"](20);
486
+
487
+ _iterator2.e(_context3.t0);
488
+
489
+ case 35:
490
+ _context3.prev = 35;
491
+
492
+ _iterator2.f();
493
+
494
+ return _context3.finish(35);
495
+
496
+ case 38:
497
+ return _context3.abrupt("return", Array.from(miss));
498
+
499
+ case 41:
500
+ _context3.prev = 41;
501
+ _context3.t1 = _context3["catch"](3);
502
+ console.error("[Spellcheck Error] Spellcheck failed for language ".concat(lang, ":"), _context3.t1);
503
+ console.error("[Spellcheck Error] Stack:", _context3.t1.stack);
504
+ return _context3.abrupt("return", []);
505
+
506
+ case 46:
507
+ case "end":
508
+ return _context3.stop();
509
+ }
510
+ }
511
+ }, _callee3, null, [[3, 41], [20, 32, 35, 38]]);
512
+ }));
513
+ return _findMisspellings.apply(this, arguments);
514
+ }
515
+
516
+ export function highlightMisspellingsInHtml(_x2) {
517
+ return _highlightMisspellingsInHtml.apply(this, arguments);
518
+ }
519
+
520
+ function _highlightMisspellingsInHtml() {
521
+ _highlightMisspellingsInHtml = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4(html) {
522
+ var lang,
523
+ textForSpellcheck,
524
+ browserLang,
525
+ spellcheckLang,
526
+ detectedLang,
527
+ miss,
528
+ segments,
529
+ wrapped,
530
+ _args4 = arguments;
531
+ return _regeneratorRuntime.wrap(function _callee4$(_context4) {
532
+ while (1) {
533
+ switch (_context4.prev = _context4.next) {
534
+ case 0:
535
+ lang = _args4.length > 1 && _args4[1] !== undefined ? _args4[1] : 'auto';
536
+
537
+ if (html) {
538
+ _context4.next = 3;
539
+ break;
540
+ }
541
+
542
+ return _context4.abrupt("return", html);
543
+
544
+ case 3:
545
+ if (spellcheckEnabled) {
546
+ _context4.next = 5;
547
+ break;
548
+ }
549
+
550
+ return _context4.abrupt("return", html);
551
+
552
+ case 5:
553
+ _context4.prev = 5;
554
+ // Decode HTML entities for spellchecking, but preserve original HTML
555
+ textForSpellcheck = html.replace(/<[^>]+>/g, ' ') // strip tags
556
+ .replace(/&nbsp;/g, ' ') // convert non-breaking spaces to regular spaces
557
+ .replace(/&[a-zA-Z0-9#]+;/g, ' ') // remove other HTML entities
558
+ .replace(/\s+/g, ' ') // normalize whitespace
559
+ .trim();
560
+ browserLang = getBrowserSpellcheckLanguage();
561
+ spellcheckLang = getSpellcheckLanguage();
562
+ detectedLang = lang === 'auto' ? detectLanguage(textForSpellcheck, browserLang, spellcheckLang) : lang; // Check if dictionary is available
563
+
564
+ if (AVAILABLE_DICTIONARIES[detectedLang]) {
565
+ _context4.next = 13;
566
+ break;
567
+ }
568
+
569
+ console.warn("Dictionary not available for ".concat(detectedLang, ", skipping spellcheck"));
570
+ return _context4.abrupt("return", html);
571
+
572
+ case 13:
573
+ _context4.next = 15;
574
+ return findMisspellings(textForSpellcheck, detectedLang);
575
+
576
+ case 15:
577
+ miss = _context4.sent;
578
+
579
+ if (!(miss.length === 0)) {
580
+ _context4.next = 18;
581
+ break;
582
+ }
583
+
584
+ return _context4.abrupt("return", html);
585
+
586
+ case 18:
587
+ // Replace whole-word occurrences with span wrapper. Do not touch inside tags or HTML entities
588
+ // We split on tags and HTML entities, only operate on text segments.
589
+ segments = html.split(/(<[^>]+>|&[a-zA-Z0-9#]+;)/g);
590
+ wrapped = segments.map(function (seg) {
591
+ if (/^<[^>]+>$/.test(seg) || /^&[a-zA-Z0-9#]+;$/.test(seg)) {
592
+ return seg; // tag or HTML entity segment - leave unchanged
593
+ }
594
+
595
+ var out = seg;
596
+
597
+ var _iterator3 = _createForOfIteratorHelper(miss),
598
+ _step3;
599
+
600
+ try {
601
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
602
+ var m = _step3.value;
603
+ // Use Unicode-aware boundaries: ensure preceding/following chars are not letters
604
+ var re = new RegExp("(?<!\\p{L})".concat(escapeRegExp(m), "(?!\\p{L})"), 'gu');
605
+ out = out.replace(re, "<span class=\"spell-error\">$&</span>");
606
+ }
607
+ } catch (err) {
608
+ _iterator3.e(err);
609
+ } finally {
610
+ _iterator3.f();
611
+ }
612
+
613
+ return out;
614
+ });
615
+ return _context4.abrupt("return", wrapped.join(''));
616
+
617
+ case 23:
618
+ _context4.prev = 23;
619
+ _context4.t0 = _context4["catch"](5);
620
+ console.warn('Spellcheck failed, returning original HTML:', _context4.t0);
621
+ return _context4.abrupt("return", html);
622
+
623
+ case 27:
624
+ case "end":
625
+ return _context4.stop();
626
+ }
627
+ }
628
+ }, _callee4, null, [[5, 23]]);
629
+ }));
630
+ return _highlightMisspellingsInHtml.apply(this, arguments);
631
+ }
632
+
633
+ function escapeRegExp(s) {
634
+ return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
635
+ }