From 1827947df2a362d5ad3ebe81c8a747c014cf1b1a Mon Sep 17 00:00:00 2001 From: Abdelrahman Bayoumi Date: Mon, 26 Oct 2026 18:53:04 +0300 Subject: [PATCH] fix: recognize exact banned words before stripping affixes --- CHANGELOG.md | 1 + src/scripts/tashfeer.ts | 2 +- tests/scripts.test.ts | 8 ++++++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d0ec6f..0d33f1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ - Release publishing now validates the tag/version and runs formatting, lint, and tests before publishing the verified build. ### Fixed +- Recognize exact banned-word matches before stripping affixes, so listed words such as `فلسطين` are obfuscated while retaining existing affix-based similarity matching. - Calculate `similarityScore` lengths and edit distance after lowercasing so Unicode case expansion cannot produce negative scores or incorrect similarity ratios. - Prevent invalid levels from hanging `tashfeer`, `tashfeerBannedWords`, and `toOldArabicAndTashfeerBannedWords`: non-number values throw `TypeError`; negative, fractional, and non-finite numbers throw `RangeError`. Random-index generation handles empty input and caps the requested count at the word length ([#35](https://github.com/Seen-Arabic/Arabic-Services-JavaScript/issues/35), [PR #36](https://github.com/Seen-Arabic/Arabic-Services-JavaScript/pull/36)). - Attempt browser bundle uploads after a successful build even if npm publishing fails ([commit 598035a](https://github.com/Seen-Arabic/Arabic-Services-JavaScript/commit/598035a)). diff --git a/src/scripts/tashfeer.ts b/src/scripts/tashfeer.ts index 5745590..6decf34 100644 --- a/src/scripts/tashfeer.ts +++ b/src/scripts/tashfeer.ts @@ -192,7 +192,7 @@ function bannedSimilarityRatio(string: string): number { */ function checkIfBannedWord(string: string): boolean { const std_ratio = 70; - return bannedSimilarityRatio(removeArabicAffixes(string)) >= std_ratio; + return BANNED_WORDS.includes(string) || bannedSimilarityRatio(removeArabicAffixes(string)) >= std_ratio; } /** diff --git a/tests/scripts.test.ts b/tests/scripts.test.ts index bf696f6..fdb012a 100644 --- a/tests/scripts.test.ts +++ b/tests/scripts.test.ts @@ -335,6 +335,14 @@ describe('#similarityScore', () => { }); describe('#tashfeerBannedWords', () => { + it.each(['فلسطين', 'غزة', 'حرية'])('should obfuscate %s while preserving surrounding non-banned words', (word) => { + const sentence = `هذه ${word} جميلة`; + const obfuscated = ArabicServices.tashfeerBannedWords(sentence); + expect(obfuscated).not.toContain(word); + expect(obfuscated.startsWith('هذه ')).toBe(true); + expect(obfuscated.endsWith(' جميلة')).toBe(true); + }); + it('should perform tashfeer obfuscation on banned words only', () => { const sentence = 'جيش العدو يقتل الأطفال'; const result = ArabicServices.tashfeerBannedWords(sentence);