terlik.js 2.2.0 → 2.2.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/README.md +12 -0
- package/dist/index.js +3 -3
- package/dist/index.mjs +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -451,6 +451,18 @@ See [CONTRIBUTING.md](./CONTRIBUTING.md) for contribution guidelines.
|
|
|
451
451
|
|
|
452
452
|
## Changelog
|
|
453
453
|
|
|
454
|
+
### 2026-02-28 (v2.2.1) — CI Fix: Timeout Race Condition + İ Platform Compatibility
|
|
455
|
+
|
|
456
|
+
**Fixes detection failures on slow runners and cross-platform İ (U+0130) handling.**
|
|
457
|
+
|
|
458
|
+
- **Timeout race condition fix** — `REGEX_TIMEOUT_MS` check moved from _before_ match processing to _after_. Previously, V8 JIT compilation on first `exec()` call (triggered by lazy compilation) could exceed 250ms, causing the timeout to discard a valid match before it was recorded. Now the current match is always processed; the timeout only prevents scanning for additional matches.
|
|
459
|
+
- **İ (U+0130) cross-platform fix** — First regex pass now runs on `text.toLocaleLowerCase(locale)` instead of raw text. Turkish İ→i mapping is performed explicitly before regex matching, avoiding inconsistent V8/ICU case-folding behavior across platforms (Ubuntu vs macOS). The `mapNormalizedToOriginal()` mapper recovers original-cased words for result output.
|
|
460
|
+
|
|
461
|
+
| Change | File |
|
|
462
|
+
|---|---|
|
|
463
|
+
| Timeout check moved after match processing | `src/detector.ts` (`runPatterns`) |
|
|
464
|
+
| Locale-lower first pass for İ safety | `src/detector.ts` (`detectPattern`) |
|
|
465
|
+
|
|
454
466
|
### 2026-02-28 (v2.2) — Lazy Compilation + Linguistic Patch
|
|
455
467
|
|
|
456
468
|
**Zero-cost construction. Background warmup. Turkish agglutination hardening.**
|
package/dist/index.js
CHANGED
|
@@ -383,9 +383,9 @@ var Detector = class {
|
|
|
383
383
|
}
|
|
384
384
|
}
|
|
385
385
|
detectPattern(text, whitelist, results) {
|
|
386
|
-
this.runPatterns(text, text, whitelist, results, false);
|
|
387
|
-
const normalizedText = this.normalizeFn(text);
|
|
388
386
|
const lowerText = text.toLocaleLowerCase(this.locale);
|
|
387
|
+
this.runPatterns(lowerText, text, whitelist, results, lowerText !== text);
|
|
388
|
+
const normalizedText = this.normalizeFn(text);
|
|
389
389
|
if (normalizedText !== lowerText && normalizedText.length > 0) {
|
|
390
390
|
this.runPatterns(normalizedText, text, whitelist, results, true);
|
|
391
391
|
}
|
|
@@ -398,7 +398,6 @@ var Detector = class {
|
|
|
398
398
|
pattern.regex.lastIndex = 0;
|
|
399
399
|
let match;
|
|
400
400
|
while ((match = pattern.regex.exec(searchText)) !== null) {
|
|
401
|
-
if (Date.now() - patternStart > REGEX_TIMEOUT_MS) break;
|
|
402
401
|
const matchedText = match[0];
|
|
403
402
|
const matchIndex = match.index;
|
|
404
403
|
const normalizedMatch = this.normalizeFn(matchedText);
|
|
@@ -433,6 +432,7 @@ var Detector = class {
|
|
|
433
432
|
if (matchedText.length === 0) {
|
|
434
433
|
pattern.regex.lastIndex++;
|
|
435
434
|
}
|
|
435
|
+
if (Date.now() - patternStart > REGEX_TIMEOUT_MS) break;
|
|
436
436
|
}
|
|
437
437
|
}
|
|
438
438
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -350,9 +350,9 @@ var Detector = class {
|
|
|
350
350
|
}
|
|
351
351
|
}
|
|
352
352
|
detectPattern(text, whitelist, results) {
|
|
353
|
-
this.runPatterns(text, text, whitelist, results, false);
|
|
354
|
-
const normalizedText = this.normalizeFn(text);
|
|
355
353
|
const lowerText = text.toLocaleLowerCase(this.locale);
|
|
354
|
+
this.runPatterns(lowerText, text, whitelist, results, lowerText !== text);
|
|
355
|
+
const normalizedText = this.normalizeFn(text);
|
|
356
356
|
if (normalizedText !== lowerText && normalizedText.length > 0) {
|
|
357
357
|
this.runPatterns(normalizedText, text, whitelist, results, true);
|
|
358
358
|
}
|
|
@@ -365,7 +365,6 @@ var Detector = class {
|
|
|
365
365
|
pattern.regex.lastIndex = 0;
|
|
366
366
|
let match;
|
|
367
367
|
while ((match = pattern.regex.exec(searchText)) !== null) {
|
|
368
|
-
if (Date.now() - patternStart > REGEX_TIMEOUT_MS) break;
|
|
369
368
|
const matchedText = match[0];
|
|
370
369
|
const matchIndex = match.index;
|
|
371
370
|
const normalizedMatch = this.normalizeFn(matchedText);
|
|
@@ -400,6 +399,7 @@ var Detector = class {
|
|
|
400
399
|
if (matchedText.length === 0) {
|
|
401
400
|
pattern.regex.lastIndex++;
|
|
402
401
|
}
|
|
402
|
+
if (Date.now() - patternStart > REGEX_TIMEOUT_MS) break;
|
|
403
403
|
}
|
|
404
404
|
}
|
|
405
405
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "terlik.js",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.1",
|
|
4
4
|
"description": "Ultra-fast, zero-dependency multi-language profanity detection engine for Turkish, English, Spanish, and German with lazy compilation, deep agglutination support, and ReDoS-safe regex patterns",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|