File size: 21,628 Bytes
cca0cf3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
/**

 * @fileoverview 

 * @module utils/linguistic-engine

 * @description 

 */

(global => {
    'use strict';

    const HOMOGLYPHS_DB = Object.freeze({
        'ا': Object.freeze(['\u0627', '\u0430', '\u05D0', '\u1D00']),
        'أ': Object.freeze(['\u0623', '\u0627', '\u0430']),
        'إ': Object.freeze(['\u0625', '\u0627', '\u05D0']),
        'آ': Object.freeze(['\u0622', '\u0627']),
        'ب': Object.freeze(['\u0628', '\u0432']),
        'ت': Object.freeze(['\u062A']),
        'ث': Object.freeze(['\u062B']),
        'ج': Object.freeze(['\u062C']),
        'ح': Object.freeze(['\u062D', '\u043D']),
        'خ': Object.freeze(['\u062E', '\u0445', '\u03C7']),
        'د': Object.freeze(['\u062F', '\u05D3', '\u0434']),
        'ذ': Object.freeze(['\u0630']),
        'ر': Object.freeze(['\u0631', '\u0440', '\u03C1']),
        'ز': Object.freeze(['\u0632']),
        'س': Object.freeze(['\u0633', '\u0441']),
        'ش': Object.freeze(['\u0634']),
        'ص': Object.freeze(['\u0635']),
        'ض': Object.freeze(['\u0636']),
        'ط': Object.freeze(['\u0637']),
        'ظ': Object.freeze(['\u0638']),
        'ع': Object.freeze(['\u0639']),
        'غ': Object.freeze(['\u063A']),
        'ف': Object.freeze(['\u0641', '\u03C6']),
        'ق': Object.freeze(['\u0642']),
        'ك': Object.freeze(['\u0643', '\u03BA', '\u043A']),
        'ل': Object.freeze(['\u0644']),
        'م': Object.freeze(['\u0645', '\u03BC', '\u043C']),
        'ن': Object.freeze(['\u0646']),
        'ه': Object.freeze(['\u0647', '\u0435', '\u03BF', '\u05E5']),
        'ة': Object.freeze(['\u0629']),
        'و': Object.freeze(['\u0648', '\u03BF', '\u043E']),
        'ؤ': Object.freeze(['\u0624']),
        'ي': Object.freeze(['\u064A', '\u0456', '\u03B9']),
        'ى': Object.freeze(['\u0649']),
        'ئ': Object.freeze(['\u0626']),
        'a': Object.freeze(['a', '\u0430', '\u03B1', '\uFF41']),
        'b': Object.freeze(['b', '\uFF42', '\u1D47']),
        'c': Object.freeze(['c', '\u0441', '\u03F2', '\uFF43']),
        'd': Object.freeze(['d', '\uFF44', '\u2146']),
        'e': Object.freeze(['e', '\u0435', '\u03B5', '\uFF45']),
        'f': Object.freeze(['f', '\uFF46', '\u1DA0']),
        'g': Object.freeze(['g', '\uFF47', '\u0261']),
        'h': Object.freeze(['h', '\u04BB', '\uFF48']),
        'i': Object.freeze(['i', '\u0456', '\u03B9', '\uFF49', '\u0131']),
        'j': Object.freeze(['j', '\u0452', '\u03F2', '\uFF4A']),
        'k': Object.freeze(['k', '\u043A', '\u03BA', '\uFF4B']),
        'l': Object.freeze(['l', '\u04CF', '\uFF4C', '\u2113']),
        'm': Object.freeze(['m', '\u043C', '\u03BC', '\uFF4D']),
        'n': Object.freeze(['n', '\uFF4E', '\u0272']),
        'o': Object.freeze(['o', '\u043E', '\u03BF', '\uFF4F', '\u0585']),
        'p': Object.freeze(['p', '\u0440', '\u03C1', '\uFF50']),
        'q': Object.freeze(['q', '\uFF51', '\u024A']),
        'r': Object.freeze(['r', '\u027E', '\uFF52']),
        's': Object.freeze(['s', '\u0455', '\uFF53', '\u015F']),
        't': Object.freeze(['t', '\uFF54', '\u0163']),
        'u': Object.freeze(['u', '\u03C5', '\u0443', '\uFF55']),
        'v': Object.freeze(['v', '\u03BD', '\uFF56', '\u1D1B']),
        'w': Object.freeze(['w', '\uFF57', '\u027F']),
        'x': Object.freeze(['x', '\u0445', '\u03C7', '\uFF58']),
        'y': Object.freeze(['y', '\u0443', '\u03C5', '\uFF59']),
        'z': Object.freeze(['z', '\uFF5A', '\u0225']),
        'A': Object.freeze(['A', '\u0391', '\u0410', '\uFF21']),
        'B': Object.freeze(['B', '\u0392', '\u0412', '\uFF22']),
        'C': Object.freeze(['C', '\u03F9', '\u0421', '\uFF23']),
        'D': Object.freeze(['D', '\uFF24', '\u0501']),
        'E': Object.freeze(['E', '\u0395', '\u0415', '\uFF22']),
        'F': Object.freeze(['F', '\uFF26', '\u1E1E']),
        'G': Object.freeze(['G', '\uFF27', '\u0192']),
        'H': Object.freeze(['H', '\u0397', '\u041D', '\uFF28']),
        'I': Object.freeze(['I', '\u0399', '\u0406', '\uFF29']),
        'J': Object.freeze(['J', '\u0408', '\uFF2A']),
        'K': Object.freeze(['K', '\u039A', '\u041A', '\uFF2B']),
        'L': Object.freeze(['L', '\uFF2C', '\u2112']),
        'M': Object.freeze(['M', '\u039C', '\u041C', '\uFF2D']),
        'N': Object.freeze(['N', '\u039D', '\uFF2E', '\u019D']),
        'O': Object.freeze(['O', '\u039F', '\u041E', '\uFF2F']),
        'P': Object.freeze(['P', '\u03A1', '\u0420', '\uFF30']),
        'Q': Object.freeze(['Q', '\uFF31', '\u024A']),
        'R': Object.freeze(['R', '\uFF32', '\u1154']),
        'S': Object.freeze(['S', '\uFF33', '\u1E60']),
        'T': Object.freeze(['T', '\u03A4', '\u0422', '\uFF34']),
        'U': Object.freeze(['U', '\u03A5', '\u04AE', '\uFF35']),
        'V': Object.freeze(['V', '\u039B', '\uFF36']),
        'W': Object.freeze(['W', '\uFF37', '\u019C']),
        'X': Object.freeze(['X', '\u03A7', '\u0425', '\uFF38']),
        'Y': Object.freeze(['Y', '\u03A5', '\u04AE', '\uFF39']),
        'Z': Object.freeze(['Z', '\uFF3A', '\u0124'])
    });

    const ARABIC_SYNONYMS_THESAURUS = Object.freeze({
        "بيع": Object.freeze(["تسويق", "تمليك", "عرض خاص للبيع", "إتاحة للتمليك", "التصرف بالبيع"]),
        "للبيع": Object.freeze(["للتمليك", "متاح للاقتناء", "فرصة نادرة للشراء", "معروض للتمليك", "جاهز للاستلام فورا"]),
        "شراء": Object.freeze(["اقتناء", "امتلاك", "الحصول على", "الاستحواذ على", "حجز"]),
        "اشتر": Object.freeze(["اقتني", "احجز الآن", "احصل على", "سارع بامتلاك", "تملّك فورا"]),
        "بيع سريع": Object.freeze(["بيع فوري عاجل", "تصفية عاجلة", "فرصة استثمارية سريعة", "تصفية نهائية"]),
        "سعر": Object.freeze(["ثمن البيع", "قيمة استثمارية", "تكلفة مالية", "مبلغ محدد", "قيمة إجمالية"]),
        "الأسعار": Object.freeze(["القيم المالية", "التكاليف الإجمالية", "الأسعار المطروحة حالياً"]),
        "رخيص": Object.freeze(["اقتصادي وموفر", "بسعر لقطة لا يتكرر", "تكلفة تنافسية مخفضة", "قيمة مغرية جداً"]),
        "غالي": Object.freeze(["فاخر وراقي", "عالي القيمة الاستثمارية", "متميز ونادر"]),
        "خصم": Object.freeze(["تخفيض فوري", "وفر مالي حصري", "عرض تخفيض خاص", "تنزيل مؤقت بالسعر"]),
        "خصومات": Object.freeze(["تخفيضات هائلة", "عروض خصم كبرى", "تنزيلات ترويجية حصرية", "أسعار مخفضة جداً"]),
        "تخفيض": Object.freeze(["خصم مالي", "تنزيل إضافي", "تقليل مباشر للتكلفة"]),
        "عرض": Object.freeze(["فرصة استثمارية صفقة", "صفقة ممتازة", "إعلان ترويجي مميز", "عرض حصري مؤقت"]),
        "عروض": Object.freeze(["فرص ذهبية", "صفقات لا تعوض", "مهرجان تخفيضات حصري", "عروض ممتازة جديدة"]),
        "شقة": Object.freeze(["وحدة سكنية راقية", "منزل سكني", "مسكن مستقل", "عقار سكني متميز"]),
        "شقق": Object.freeze(["وحدات سكنية متنوعة", "عقارات سكنية متميزة", "منازل ممتازة"]),
        "فيلا": Object.freeze(["قصر مستقل", "فيلّا فاخرة", "منزل مستقل فاخر", "وحدة سكنية مستقلة"]),
        "فلل": Object.freeze(["قصور متميزة", "فيلات مستقلة فاخرة", "وحدات سكنية فاخرة مستقلة"]),
        "دوبلكس": Object.freeze(["وحدة دوبلكس مستقلة", "شقة طابقين فاخرة"]),
        "بنتهاوس": Object.freeze(["شقة علوية بنتهاوس", "وحدة سكنية بحديقة علوية فاخرة"]),
        "استوديو": Object.freeze(["استوديو مجهز بالكامل", "شقة استوديو أنيقة"]),
        "عقار": Object.freeze(["وحدة استثمارية", "ملكية عقارية ممتازة", "ممتلكات فاخرة"]),
        "عقارات": Object.freeze(["مشاريع عقارية كبرى", "وحدات وممتلكات متميزة", "محفظة عقارية فاخرة"]),
        "أرض": Object.freeze(["قطعة أرض متميزة", "مساحة أرض صالحة للبناء فورا"]),
        "محل": Object.freeze(["وحدة تجارية متميزة", "متجر تجاري جاهز للتشغيل"]),
        "مكتب": Object.freeze(["مقر إداري مجهز", "وحدة إدارية ممتازة للشركات"]),
        "إيجار": Object.freeze(["استئجار مؤقت", "تأجير دوري", "إيجار شهري"]),
        "للإيجار": Object.freeze(["للايجار الفوري", "متاح للاستئجار", "جاهز للتأجير الفوري", "للاستثمار الإيجاري"]),
        "مؤجر": Object.freeze(["مستأجر حالي", "تم تأجيره بالكامل"]),
        "ممتاز": Object.freeze(["استثنائي رائع", "فاخر للغاية", "راقي ومميز جداً", "عالي الجودة والكفاءة"]),
        "رائع": Object.freeze(["مذهل وجذاب", "استثنائي غير مسبوق", "خيالي وساحر", "من الدرجة الأولى"]),
        "جيد": Object.freeze(["مناسب تماماً", "بحالة جيدة جداً", "مقبول ومطابق للمواصفات"]),
        "فاخر": Object.freeze(["سوبر لوكس راقي", "الترا لوكس فاخر", "متميز ونخبوي"]),
        "جديد": Object.freeze(["حديث كلياً", "أول استخدام لم يستعمل", "جديد تماماً بأوراق المصنع"]),
        "قديم": Object.freeze(["مستعمل بحالة ممتازة", "كلاسيكي كسر زيرو"]),
        "تواصل": Object.freeze(["راسلنا الآن مباشرة", "استفسر من فريق العمل", "كلمنا فورا", "تحدث مع المبيعات"]),
        "اتصل": Object.freeze(["تواصل معنا", "راسلنا بالاتصال المباشر", "تحدث معنا هاتفياً فورا"]),
        "واتساب": Object.freeze(["الواتساب المباشر", "عبر شات واتساب", "WhatsApp Chat فوري"]),
        "رقم": Object.freeze(["رقم الهاتف الموثق", "وسيلة الاتصال المباشرة", "الخط الساخن للخدمة"]),
        "فرصة": Object.freeze(["عرض لقطة استثنائي", "صفقة العمر الممتازة", "فرصة ذهبية نادرة", "مناسبة ممتازة"]),
        "فرصة ذهبية": Object.freeze(["صفقة استثمارية لا تتكرر", "عرض العمر الحصري"]),
        "حصري": Object.freeze(["حصرياً وبشكل خاص", "لفترة محدودة جداً للرواد", "إعلان مميز مخصص"]),
        "لفترة محدودة": Object.freeze(["لفترة وجيزة جداً", "عرض مؤقت ينتهي قريباً", "فرصة عاجلة تسري لأيام"]),
        "كاش": Object.freeze(["نقداً فوري", "دفع كاش نقدي كامل"]),
        "تقسيط": Object.freeze(["أقساط مرنة مريحة", "دفعات شهرية ميسرة", "أنظمة سداد وتقسيط"]),
        "بدون مقدم": Object.freeze(["بصفر مقدم تعاقد", "بدون دفعة أولى مقدمة", "تسهيلات بدون دفعة حجز"]),
        "تمويل": Object.freeze(["تسهيلات تمويلية وسداد", "تسهيلات دفع طويلة المدى"]),
        "مدينة": Object.freeze(["منطقة سكنية متكاملة", "حي راقي وهادئ", "مجمع سكني مغلق متميز"]),
        "موقع": Object.freeze(["لوكيشن مميز جداً", "عنوان جغرافي استراتيجي", "مقر حيوي للغاية"]),
        "قريب": Object.freeze(["على بعد خطوات بسيطة", "بالقرب الشديد من الخدمات", "بجوار المعالم الرئيسية"]),
        "أمام": Object.freeze(["مقابل ومواجه مباشرة لـ", "بإطلالة أمامية على"]),
        "داخل": Object.freeze(["في قلب منطقة", "ضمن نطاق أرقى مجمعات"]),
        "مساحة": Object.freeze(["مساحة إجمالية ممتازة", "مقاس هندسي متسع"]),
        "غرفة": Object.freeze(["حجرة مجهزة", "غرفة نوم واسعة"]),
        "غرف": Object.freeze(["حجرات متسعة", "غرف نوم مستقلة"]),
        "حمام": Object.freeze(["دورة مياه مجهزة بالكامل", "حمام راقي"]),
        "مطبخ": Object.freeze(["مطبخ أمريكي متكامل", "مطبخ عصري حديث"]),
        "بلكونة": Object.freeze(["شرفة بإطلالة مفتوحة", "بلكونة واسعة ذات رؤية متميزة"]),
        "حديقة": Object.freeze(["مساحة لاندسكيب خضراء", "حديقة خاصة مستقلة"]),
        "روف": Object.freeze(["روف علوي واسع ومستقل", "شقة روف علوية متميزة"]),
        "تشطيب": Object.freeze(["مستوى تشطيبات راقي", "إنهاءات هندسية فائقة الدقة"]),
        "فيو": Object.freeze(["منظر بانورامي مفتوح", "إطلالة ساحرة مباشرة"]),
        "تشطيب سوبر لوكس": Object.freeze(["تشطيب الترا سوبر لوكس فاخر", "مستوى تشطيبات راقي ونخبوية", "جاهز للسكن الفوري الفاخر"])
    });

    /**

     * @param {string} text 

     * @param {number} density 

     * @returns {string}

     */
    function injectZeroWidthSpaces(text, density = 0.25) {
        if (!text) return text;
        const words = text.split(/(\s+)/);

        const processedWords = words.map(word => {
            if (/^\s+$/.test(word) || word.length <= 3) return word;

            if (Math.random() < density) {
                const chars = [];
                for (let i = 0; i < word.length; i++) {
                    chars.push(word[i]);
                    if (i < word.length - 1 && Math.random() < 0.35) {
                        chars.push(Math.random() > 0.5 ? '\u200C' : '\u200B');
                    }
                }
                return chars.join('');
            }
            return word;
        });

        return processedWords.join('');
    }

    /**

     * @param {string} text 

     * @param {number} rate 

     * @returns {string}

     */
    function applyUnicodeHomoglyphs(text, rate = 0.20) {
        if (!text) return text;
        let result = "";

        for (let i = 0; i < text.length; i++) {
            const char = text[i];
            if (HOMOGLYPHS_DB[char] && Math.random() < rate) {
                const options = HOMOGLYPHS_DB[char];
                const randomIndex = Math.floor(Math.random() * options.length);
                result += options[randomIndex];
            } else {
                result += char;
            }
        }

        return result;
    }

    /**

     * إعادة الصياغة التلقائية للكلمات باستخدام معجم المترادفات

     * @param {string} text 

     * @param {number} substitutionStrength - شدة الاستبدال

     * @returns {string}

     */
    function autoParaphraseArabicText(text, substitutionStrength = 0.40) {
        if (!text) return text;
        let processedText = text;

        const keys = Object.keys(ARABIC_SYNONYMS_THESAURUS).sort((a, b) => b.length - a.length);

        keys.forEach(key => {
            if (Math.random() < substitutionStrength) {
                const regex = new RegExp(`(?<=^|\\s|\\p{P})${key}(?=$|\\s|\\p{P})`, 'gu');
                if (regex.test(processedText)) {
                    const synonyms = ARABIC_SYNONYMS_THESAURUS[key];
                    const randomSynonym = synonyms[Math.floor(Math.random() * synonyms.length)];
                    processedText = processedText.replace(regex, randomSynonym);
                }
            }
        });

        return processedText;
    }

    /**

     * @param {Blob} imageBlob 

     * @returns {Promise<Blob>}

     */
    async function stripExifAndObfuscateMedia(imageBlob) {
        if (!(imageBlob instanceof Blob)) return imageBlob;

        try {
            const arrayBuffer = await imageBlob.arrayBuffer();
            const view = new DataView(arrayBuffer);

            if (view.getUint16(0) !== 0xFFD8) {
                return imageBlob;
            }

            const cleanSegments = [];
            let offset = 2;
            cleanSegments.push(arrayBuffer.slice(0, 2));
            const length = arrayBuffer.byteLength;

            while (offset < length) {
                if (offset + 2 > length) break;
                const marker = view.getUint16(offset);

                if (marker >= 0xFFE1 && marker <= 0xFFEF) {
                    const segmentLength = view.getUint16(offset + 2);
                    offset += segmentLength + 2;
                    continue;
                }

                if (marker === 0xFFDA) { 
                    cleanSegments.push(arrayBuffer.slice(offset));
                    break;
                }

                const segmentLength = view.getUint16(offset + 2);
                cleanSegments.push(arrayBuffer.slice(offset, offset + segmentLength + 2));
                offset += segmentLength + 2;
            }

            const cleanedBlob = new Blob(cleanSegments, { type: imageBlob.type || 'image/jpeg' });
            return await injectInvisibleImageNoise(cleanedBlob);
        } catch (err) {
            console.error("[Fritree Shield Obfuscator] EXIF stripping failed:", err);
            return imageBlob;
        }
    }

    /**

     * @param {Blob} imageBlob 

     * @returns {Promise<Blob>}

     */
    function injectInvisibleImageNoise(imageBlob) {
        return new Promise((resolve) => {
            const reader = new FileReader();
            reader.readAsDataURL(imageBlob);

            reader.onload = (event) => {
                const img = new Image();
                img.src = event.target.result;

                img.onload = () => {
                    const canvas = document.createElement('canvas');
                    canvas.width = img.width;
                    canvas.height = img.height;
                    const ctx = canvas.getContext('2d');

                    if (ctx) {
                        ctx.drawImage(img, 0, 0);
                        const pixel = ctx.getImageData(img.width - 1, img.height - 1, 1, 1);
                        pixel.data[0] = (pixel.data[0] + (Math.random() > 0.5 ? 1 : -1) + 256) % 256;
                        pixel.data[1] = (pixel.data[1] + (Math.random() > 0.5 ? 1 : -1) + 256) % 256;
                        pixel.data[2] = (pixel.data[2] + (Math.random() > 0.5 ? 1 : -1) + 256) % 256;
                        ctx.putImageData(pixel, img.width - 1, img.height - 1);

                        canvas.toBlob((obfuscatedBlob) => {
                            resolve(obfuscatedBlob || imageBlob);
                        }, 'image/jpeg', 0.85);
                    } else {
                        resolve(imageBlob);
                    }
                };

                img.onerror = () => resolve(imageBlob);
            };

            reader.onerror = () => resolve(imageBlob);
        });
    }

    /**

     * @param {string} rawText 

     * @param {Object} config 

     * @returns {Promise<string>}

     */
    async function processTextStealthMasking(rawText, config = {}) {
        if (!rawText) return rawText;

        let maskedText = rawText;
        const paraphraseStrength = config.synonymStrength !== undefined ? config.synonymStrength : 0.40;
        const homoglyphStrength = config.homoglyphStrength !== undefined ? config.homoglyphStrength : 0.20;
        const zwspDensity = config.zwspDensity !== undefined ? config.zwspDensity : 0.25;

        if (paraphraseStrength > 0) {
            maskedText = autoParaphraseArabicText(maskedText, paraphraseStrength);
        }
        if (homoglyphStrength > 0) {
            maskedText = applyUnicodeHomoglyphs(maskedText, homoglyphStrength);
        }
        if (zwspDensity > 0) {
            maskedText = injectZeroWidthSpaces(maskedText, zwspDensity);
        }

        return maskedText;
    }

    global.FritreeStealthLinguisticEngine = Object.freeze({
        injectZWSP: injectZeroWidthSpaces,
        applyHomoglyphs: applyUnicodeHomoglyphs,
        paraphrase: autoParaphraseArabicText,
        processTextMasking: processTextStealthMasking,
        cleanImageExif: stripExifAndObfuscateMedia,
        thesaurus: ARABIC_SYNONYMS_THESAURUS
    });

})(typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : this);