@sideid/id-profanity-filter 1.11.13 → 1.13.0

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 (38) hide show
  1. package/CONTRIBUTING.md +91 -129
  2. package/README.md +172 -447
  3. package/dist/index.d.ts +11 -6
  4. package/dist/index.esm.js +161 -180
  5. package/dist/index.esm.js.map +1 -1
  6. package/dist/index.js +161 -180
  7. package/dist/index.js.map +1 -1
  8. package/dist/types/core/matcher.d.ts +5 -5
  9. package/dist/types/index.d.ts +5 -0
  10. package/dist/types/types/index.d.ts +1 -1
  11. package/dist/types/utils/ahoCorasick.d.ts +10 -0
  12. package/eslint.config.mjs +1 -0
  13. package/examples/advanced.ts +4 -1
  14. package/examples/custom-list.ts +3 -3
  15. package/package.json +9 -2
  16. package/rollup.config.mjs +5 -1
  17. package/src/constants/categories/sexual.ts +1 -1
  18. package/src/constants/regions/general.ts +3 -3
  19. package/src/constants/wordList.ts +0 -27
  20. package/src/core/filter.ts +58 -178
  21. package/src/core/matcher.ts +69 -43
  22. package/src/index.ts +8 -0
  23. package/src/types/index.ts +1 -11
  24. package/src/utils/ahoCorasick.ts +37 -0
  25. package/src/utils/regexUtils.ts +1 -2
  26. package/src/utils/similarityUtils.ts +0 -4
  27. package/test/matcher.test.ts +18 -0
  28. package/test/profanity-filter.test.ts +15 -0
  29. package/.eslintrc.js +0 -44
  30. package/src/constants/regions/ambon.ts +0 -0
  31. package/src/constants/regions/banjar.ts +0 -0
  32. package/src/constants/regions/bugis.ts +0 -0
  33. package/src/constants/regions/lampung.ts +0 -0
  34. package/src/constants/regions/manado.ts +0 -0
  35. package/src/constants/regions/ntb.ts +0 -0
  36. package/src/constants/regions/ntt.ts +0 -0
  37. package/src/constants/regions/palembang.ts +0 -0
  38. package/src/constants/regions/papua.ts +0 -0
package/README.md CHANGED
@@ -1,548 +1,273 @@
1
- # ID-Profanity-Filter
1
+ <div align="center">
2
+ <img alt="SideID - Profanity Filter" src="https://socialify.git.ci/SideeID/id-profanity-filter/image?custom_description=Library+JavaScript%2FTypeScript+untuk+mendeteksi%2C+menyensor%2C+dan+menganalisis+kata-kata+kotor+dalam+Indonesia+dan+daerah.&description=1&font=Inter&forks=1&language=1&name=1&owner=1&pattern=Circuit+Board&stargazers=1&theme=Auto">
3
+ </div>
2
4
 
3
- ![License](https://img.shields.io/npm/l/@sideid/id-profanity-filter)
4
- ![Version](https://img.shields.io/npm/v/@sideid/id-profanity-filter)
5
- ![Downloads](https://img.shields.io/npm/dt/@sideid/id-profanity-filter)
5
+ ---
6
6
 
7
- Library JavaScript/TypeScript untuk mendeteksi, menyensor, dan menganalisis kata-kata kotor dalam Bahasa Indonesia dan bahasa daerah.
7
+ <div align="center">
8
+ <a href="https://www.npmjs.com/package/@sideid/id-profanity-filter">
9
+ <img src="https://img.shields.io/npm/v/@sideid/id-profanity-filter.svg" alt="NPM Version">
10
+ </a>
11
+ <a href="https://github.com/SideeID/id-profanity-filter">
12
+ <img src="https://img.shields.io/github/license/SideeID/id-profanity-filter" alt="GitHub License">
13
+ </a>
14
+ </div>
8
15
 
9
- ## Fitur Utama
16
+ # id-profanity-filter
10
17
 
11
- - 🔍 **Deteksi Kata Kotor** - Mendeteksi kata-kata kasar/kotor dalam teks Bahasa Indonesia
12
- - ⚠️ **Analisis Konten** - Menganalisis tingkat keparahan dan kategori kata kotor
13
- - 🔒 **Penyensoran** - Menyensor kata-kata kotor dengan berbagai opsi kustomisasi
14
- - 🗺️ **Dukungan Bahasa Daerah** - Mencakup kata-kata dari berbagai daerah di Indonesia (Jawa, Sunda, Batak, dll)
15
- - 🧠 **Deteksi Cerdas** - Mendeteksi variasi ejaan, kata terpisah, dan kesamaan kata
16
- - 🔠 **Deteksi Levenshtein** - Mendeteksi kata kotor yang dimodifikasi dengan typo atau sengaja disamarkan
17
- - 🛡️ **Preset** - Preset filter siap pakai untuk berbagai kebutuhan
18
- - 🔧 **Kustomisasi** - Opsi untuk menambahkan whitelist dan daftar kata kustom
18
+ Library JavaScript dan TypeScript untuk mendeteksi, menyensor, dan menganalisis kata kotor dalam bahasa Indonesia serta berbagai bahasa daerah.
19
+
20
+ ## Fitur
21
+
22
+ - Deteksi kata kotor dan umpatan dalam bahasa Indonesia dan dialek daerah (Jawa, Sunda, Batak, Betawi, Minang, Bali, Madura, Aceh)
23
+ - Sensor fleksibel: ganti karakter (`*`, `#`), grawlix acak (`#@$%&!`), sensor penuh, atau pertahankan huruf pertama dan terakhir
24
+ - Deteksi variasi penulisan: leetspeak (`4nj1ng`), kata terpisah (`a-n-j-i-n-g`), dan typo via Levenshtein distance
25
+ - Analisis teks: skor keparahan (0-1), kategorisasi, analisis per kalimat, pencarian konteks sekitar, dan batch analysis
26
+ - Mendukung whitelist kata dan daftar kata kustom (`wordList`)
27
+ - Preset siap pakai: `strict`, `moderate`, `light`, dan `childSafe`
28
+ - Dukungan penuh TypeScript dengan tipe data lengkap
19
29
 
20
30
  ## Instalasi
21
31
 
22
32
  ```bash
23
33
  npm install @sideid/id-profanity-filter
24
34
  # atau
25
- yarn add @sideid/id-profanity-filter
35
+ bun add @sideid/id-profanity-filter
26
36
  # atau
27
37
  pnpm add @sideid/id-profanity-filter
28
38
  ```
29
39
 
30
- ## Penggunaan Dasar
40
+ ## Penggunaan dasar
31
41
 
32
- ### JavaScript / TypeScript
42
+ ### Menggunakan class IDProfanityFilter
33
43
 
34
44
  ```typescript
35
45
  import IDProfanityFilter from '@sideid/id-profanity-filter';
36
46
 
37
- // Buat instance filter
38
47
  const filter = new IDProfanityFilter();
39
-
40
- // Cek apakah teks mengandung kata kotor
41
48
  const teks = 'Dasar anjing kamu, jangan banyak bacot!';
42
- const hasProfanity = filter.isProfane(teks);
43
-
44
- console.log(hasProfanity); // Output: true
45
-
46
- // Filter kata kotor (sensorisasi)
47
- const hasil = filter.filter(teks);
48
- console.log(hasil.filtered); // Output: "Dasar ***** kamu, jangan banyak *****!"
49
- console.log(hasil.censored); // Output: 2 (jumlah kata yang disensor)
50
-
51
- // Analisis konten
52
- const analisis = filter.analyze(teks);
53
- console.log(analisis.severityScore); // Output: 0.65 (contoh skor keparahan)
54
- console.log(analisis.categories); // Output: ["profanity", "insult"]
55
- ```
56
-
57
- ### Menggunakan Preset
58
-
59
- ```typescript
60
- import IDProfanityFilter from '@sideid/id-profanity-filter';
61
-
62
- // Buat instance filter dengan preset
63
- const filter = new IDProfanityFilter();
64
- filter.usePreset('strict');
65
-
66
- // Atau dengan opsi tambahan
67
- filter.usePreset('childSafe', {
68
- replaceWith: '#',
69
- useRandomGrawlix: true,
70
- });
71
49
 
72
- const teks = 'Dasar anjing kamu, jangan banyak bacot!';
73
- const hasil = filter.filter(teks);
74
- console.log(hasil.filtered); // Output: "Dasar #@$%& kamu, jangan banyak $!@#%!"
50
+ // Cek apakah teks mengandung kata kotor
51
+ if (filter.isProfane(teks)) {
52
+ // Sensor kata kotor
53
+ const hasil = filter.filter(teks);
54
+ console.log(hasil.filtered);
55
+ // Output: "Dasar ****** kamu, jangan banyak *****!"
56
+ console.log(hasil.censored);
57
+ // Output: 2
58
+
59
+ // Analisis detail
60
+ const analisis = filter.analyze(teks);
61
+ console.log(analisis.categories);
62
+ // Output: ["profanity", "insult"]
63
+ console.log(analisis.regions);
64
+ // Output: ["general", "jawa"]
65
+ console.log(analisis.severityScore);
66
+ // Output: 0.36
67
+ }
75
68
  ```
76
69
 
77
- ### Utilitas Langsung
70
+ ### Menggunakan fungsi statis (idFilter)
78
71
 
79
- Anda juga dapat menggunakan fungsi utilitas langsung tanpa membuat instance:
72
+ Jika tidak memerlukan konfigurasi instance khusus, gunakan helper `idFilter`:
80
73
 
81
74
  ```typescript
82
75
  import { idFilter } from '@sideid/id-profanity-filter';
83
76
 
84
77
  const teks = 'Dasar anjing kamu, jangan banyak bacot!';
78
+
79
+ // Filter langsung
85
80
  const hasil = idFilter.filter(teks);
86
- console.log(hasil.filtered); // Output: "Dasar ***** kamu, jangan banyak *****!"
81
+ console.log(hasil.filtered);
87
82
 
88
- // Menggunakan preset dengan API fungsi statis
89
- const presetResult = idFilter.filter(
90
- teks,
91
- idFilter.getPresetOptions('moderate'),
92
- );
83
+ // Cek cepat
84
+ console.log(idFilter.isProfane(teks)); // true
93
85
  ```
94
86
 
95
- ## Dokumentasi API
96
-
97
- ### Kelas `IDProfanityFilter`
98
-
99
- #### Konstruktor
87
+ ### Menggunakan preset
100
88
 
101
89
  ```typescript
102
- constructor(options?: FilterOptions)
103
- ```
104
-
105
- - **options**: Opsi konfigurasi filter (opsional)
106
-
107
- #### Metode
108
-
109
- ##### `filter(text: string): FilterResult`
110
-
111
- Menyensor kata kotor dalam teks.
112
-
113
- - **Hasil**: Objek `FilterResult` dengan properti:
114
- - `filtered`: String teks yang sudah disensor
115
- - `censored`: Jumlah kata yang disensor
116
- - `replacements`: Array berisi detail kata yang disensor
117
-
118
- ##### `isProfane(text: string): boolean`
119
-
120
- Memeriksa apakah teks mengandung kata kotor.
121
-
122
- - **Hasil**: Boolean `true` jika teks mengandung kata kotor, `false` jika tidak
123
-
124
- ##### `analyze(text: string): AnalysisResult`
125
-
126
- Menganalisis teks untuk mendapatkan informasi detail tentang kata kotor yang ditemukan.
127
-
128
- - **Hasil**: Objek `AnalysisResult` dengan properti:
129
- - `hasProfanity`: Apakah teks mengandung kata kotor
130
- - `matches`: Array kata kotor yang ditemukan
131
- - `matchDetails`: Array objek kata kotor dengan metadata
132
- - `categories`: Kategori kata kotor yang ditemukan
133
- - `regions`: Daerah asal kata kotor yang ditemukan
134
- - `severityScore`: Skor keparahan (0-1)
135
- - `similarWords`: Kata-kata yang mirip dengan kata kotor (jika deteksi kesamaan diaktifkan)
136
-
137
- ##### `batchAnalyze(texts: string[])`
138
-
139
- Menganalisis batch teks sekaligus dan memberikan ringkasan.
140
-
141
- - **Hasil**: Objek yang berisi ringkasan analisis
142
-
143
- ##### `analyzeBySentence(text: string)`
144
-
145
- Menganalisis teks per-kalimat.
146
-
147
- - **Hasil**: Array dari hasil analisis per-kalimat
148
-
149
- ##### `analyzeWithContext(text: string, contextWindowSize?: number)`
90
+ import IDProfanityFilter from '@sideid/id-profanity-filter';
150
91
 
151
- Menganalisis teks dengan konteks di sekitar kata kotor.
92
+ const filter = new IDProfanityFilter();
152
93
 
153
- - **Hasil**: Array dari kata kotor dengan konteks di sekitarnya
94
+ // Gunakan preset childSafe dengan grawlix acak
95
+ filter.usePreset('childSafe', { useRandomGrawlix: true });
154
96
 
155
- ##### `usePreset(presetName: string, additionalOptions?: Partial<FilterOptions>)`
97
+ const hasil = filter.filter('Dasar anjing kamu!');
98
+ console.log(hasil.filtered);
99
+ // Output: "Dasar #@$%& kamu!"
100
+ ```
156
101
 
157
- Menggunakan preset filter yang telah ditentukan.
102
+ ## Dokumentasi API
158
103
 
159
- - **presetName**: Nama preset ('strict', 'moderate', 'light', 'childSafe', dll)
160
- - **additionalOptions**: Opsi tambahan untuk override preset (opsional)
104
+ ### Kelas `IDProfanityFilter`
161
105
 
162
- ##### `setOptions(options: Partial<FilterOptions>)`
106
+ #### `constructor(options?: FilterOptions)`
107
+ Membuat instance filter baru dengan opsi default atau kustom.
163
108
 
164
- Mengubah opsi filter.
109
+ #### `filter(text: string): FilterResult`
110
+ Menyensor kata kotor dalam teks. Mengembalikan objek:
111
+ - `filtered`: string hasil sensor
112
+ - `censored`: jumlah kata yang disensor
113
+ - `replacements`: daftar objek penggantian (`original`, `censored`, `metadata`)
165
114
 
166
- ##### `setWordList(wordList: string[])`
115
+ #### `isProfane(text: string): boolean`
116
+ Mengembalikan `true` jika teks mengandung kata kotor.
167
117
 
168
- Menetapkan daftar kata kustom.
118
+ #### `analyze(text: string): AnalysisResult`
119
+ Menganalisis teks secara menyeluruh. Mengembalikan objek:
120
+ - `hasProfanity`: boolean
121
+ - `matches`: string kata kotor yang cocok
122
+ - `matchDetails`: array objek `ProfanityWord` lengkap
123
+ - `categories`: kategori unik yang ditemukan
124
+ - `regions`: daerah asal kata yang ditemukan
125
+ - `severityScore`: skor keparahan kata (0 - 1)
126
+ - `similarWords`: kata yang mirip (jika `detectSimilarity` aktif)
169
127
 
170
- ##### `addToWhitelist(word: string)`
128
+ #### `batchAnalyze(texts: string[])`
129
+ Menganalisis kumpulan teks sekaligus dan mengembalikan statistik agregat (total kata, teks bersih, rata-rata keparahan, kata paling sering muncul).
171
130
 
172
- Menambahkan kata ke whitelist (akan diabaikan dalam filter).
131
+ #### `analyzeBySentence(text: string)`
132
+ Memecah teks per kalimat dan menganalisis masing-masing kalimat secara independen.
173
133
 
174
- ##### `removeFromWhitelist(word: string)`
134
+ #### `analyzeWithContext(text: string, contextWindowSize: number = 5)`
135
+ Mengambil kata kotor beserta konteks kata-kata di sekitarnya.
175
136
 
176
- Menghapus kata dari whitelist.
137
+ #### `setOptions(options: Partial<FilterOptions>)`
138
+ Memperbarui konfigurasi filter yang sedang berjalan.
177
139
 
178
- ##### `enableIndonesianVariations()`
140
+ #### `resetOptions(options: FilterOptions = {})`
141
+ Mengembalikan konfigurasi filter ke opsi default (dapat ditimpa dengan opsi baru).
179
142
 
180
- Mengaktifkan deteksi variasi ejaan Bahasa Indonesia.
143
+ #### `usePreset(presetName: string, additionalOptions?: Partial<FilterOptions>)`
144
+ Menerapkan preset filter (`strict`, `moderate`, `light`, `childSafe`).
181
145
 
182
- ##### `enableSplitWordDetection()`
146
+ #### `setWordList(wordList: string[])`
147
+ Mengatur daftar kata kustom yang akan digunakan oleh filter.
183
148
 
184
- Mengaktifkan deteksi kata yang dipisah.
149
+ #### `addToWhitelist(word: string)` / `removeFromWhitelist(word: string)`
150
+ Menambahkan atau menghapus kata dari whitelist pengecualian.
185
151
 
186
- ##### `enableSimilarityDetection(threshold: number = 0.8, useLevenshtein: boolean = false, maxLevenshteinDistance: number = 2)`
152
+ #### `enableIndonesianVariations()`
153
+ Mengaktifkan deteksi variasi ejaan bahasa Indonesia (misalnya ejaan lama atau substitusi huruf lazim).
187
154
 
188
- Mengaktifkan deteksi berdasarkan kesamaan kata.
155
+ #### `enableSplitWordDetection()`
156
+ Mengaktifkan deteksi kata yang dipisah dengan spasi atau tanda baca (contoh: `a-n-j-i-n-g`).
189
157
 
190
- - **threshold**: Ambang batas kesamaan (0-1, default: 0.8)
191
- - **useLevenshtein**: Gunakan algoritma Levenshtein untuk deteksi (default: false)
192
- - **maxLevenshteinDistance**: Jarak edit maksimum yang diizinkan (default: 2)
158
+ #### `enableSimilarityDetection(threshold = 0.8, useLevenshtein = false, maxDistance = 2)`
159
+ Mengaktifkan deteksi kemiripan kata untuk menangkap typo atau variasi penulisan.
193
160
 
194
- ##### `enableLevenshteinDetection(threshold: number = 0.8, maxDistance: number = 2)`
161
+ ### Opsi Filter (`FilterOptions`)
195
162
 
196
- Mengaktifkan deteksi berbasis jarak Levenshtein.
163
+ | Properti | Tipe | Default | Deskripsi |
164
+ |---|---|---|---|
165
+ | `replaceWith` | `string` | `'*'` | Karakter pengganti kata yang disensor |
166
+ | `fullWordCensor` | `boolean` | `true` | Sensor seluruh karakter kata |
167
+ | `keepFirstAndLast` | `boolean` | `false` | Pertahankan huruf pertama dan terakhir saat sensor (`a****g`) |
168
+ | `useRandomGrawlix` | `boolean` | `false` | Gunakan karakter simbol acak (`#@$%&!`) |
169
+ | `detectLeetSpeak` | `boolean` | `true` | Deteksi variasi angka/simbol (`b4b1`, `4nj1ng`) |
170
+ | `detectSplit` | `boolean` | `false` | Deteksi kata dengan pemisah (`b-a-b-i`) |
171
+ | `indonesianVariation` | `boolean` | `false` | Deteksi variasi ejaan Indonesia |
172
+ | `detectSimilarity` | `boolean` | `false` | Deteksi kata typo atau mirip |
173
+ | `similarityThreshold` | `number` | `0.8` | Batas minimum kemiripan (0 - 1) |
174
+ | `useLevenshtein` | `boolean` | `false` | Gunakan algoritma Levenshtein distance |
175
+ | `maxLevenshteinDistance` | `number` | `2` | Jarak edit maksimum Levenshtein |
176
+ | `checkSubstring` | `boolean` | `false` | Deteksi kata kotor di dalam substring kata lain |
177
+ | `wordList` | `string[]` | `[]` | Daftar kata kustom (menggantikan daftar bawaan) |
178
+ | `whitelist` | `string[]` | `[]` | Daftar kata yang diabaikan dari filter |
179
+ | `categories` | `ProfanityCategory[]` | - | Filter hanya kategori tertentu |
180
+ | `regions` | `Region[]` | - | Filter hanya daerah tertentu |
181
+ | `severityThreshold` | `number` | `0` | Batas keparahan minimum kata (0 - 1) |
197
182
 
198
- - **threshold**: Ambang batas kesamaan (0-1, default: 0.8)
199
- - **maxDistance**: Jarak edit maksimum yang diizinkan (default: 2)
183
+ ## Contoh penggunaan lanjutan
200
184
 
201
- ### Opsi Filter
185
+ ### Daftar kata kustom
202
186
 
203
187
  ```typescript
204
- interface FilterOptions {
205
- // Opsi dasar
206
- wordList?: string[]; // List kata yang ingin difilter
207
- replaceWith?: string; // Karakter pengganti untuk kata yang disensor
208
- fullWordCensor?: boolean; // Apakah menyensor seluruh kata atau sebagian
209
- detectLeetSpeak?: boolean; // Deteksi variasi penulisan (mis: a=4, e=3)
210
- whitelist?: string[]; // Kata-kata yang dikecualikan dari filter
211
- checkSubstring?: boolean; // Memeriksa substring (lebih ketat)
212
- categories?: ProfanityCategory[]; // Kategori kata yang difilter
213
- regions?: Region[]; // Daerah asal kata yang difilter
214
- severityThreshold?: number; // Tingkat keparahan minimum (0-1)
215
-
216
- // Opsi lanjutan
217
- useRandomGrawlix?: boolean; // Gunakan karakter acak untuk sensor (#@$%&!)
218
- keepFirstAndLast?: boolean; // Simpan huruf pertama dan terakhir (a***g)
219
- indonesianVariation?: boolean; // Deteksi variasi ejaan Bahasa Indonesia
220
- detectSimilarity?: boolean; // Deteksi kata berdasarkan kesamaan
221
- similarityThreshold?: number; // Ambang batas kesamaan (0-1)
222
- detectSplit?: boolean; // Deteksi kata yang dipisah (a-n-j-i-n-g)
223
- useLevenshtein?: boolean; // Gunakan algoritma Levenshtein untuk deteksi kesamaan
224
- maxLevenshteinDistance?: number; // Jarak edit maksimum untuk deteksi Levenshtein
225
- }
226
- ```
227
-
228
- ## Preset Filter
229
-
230
- Library ini menyediakan beberapa preset yang dapat digunakan:
231
-
232
- ### Preset Filter
233
-
234
- - **strict**: Filter paling ketat, mendeteksi semua jenis kata kotor
235
- - **moderate**: Filter tingkat menengah, mengabaikan kata-kata dengan tingkat keparahan rendah
236
- - **light**: Filter ringan, hanya untuk kata-kata paling sensitif
237
- - **childSafe**: Filter untuk konten anak-anak, sangat ketat
238
-
239
- ### Preset Kategori
240
-
241
- - **sexual**: Hanya memfilter kata-kata berbau seksual
242
- - **insults**: Hanya memfilter kata-kata penghinaan
243
- - **profanity**: Hanya memfilter umpatan umum
244
-
245
- ### Preset Regional
246
-
247
- - **general**: Hanya memfilter kata-kata umum di Indonesia
248
- - **jawa**: Hanya memfilter kata-kata dari Jawa
249
- - **sunda**: Hanya memfilter kata-kata dari Sunda
250
- - **betawi**: Hanya memfilter kata-kata dari Betawi
251
- - **batak**: Hanya memfilter kata-kata dari Batak
252
-
253
- ## Contoh Penggunaan Lanjutan
254
-
255
- ### Kustomisasi Opsi Filter
188
+ import IDProfanityFilter from '@sideid/id-profanity-filter';
256
189
 
257
- ```typescript
258
190
  const filter = new IDProfanityFilter({
259
- replaceWith: '#', // Menggunakan # sebagai karakter pengganti
260
- fullWordCensor: false, // Hanya menyensor sebagian kata
261
- detectLeetSpeak: true, // Mendeteksi variasi seperti "b4b1" untuk "babi"
262
- categories: ['sexual', 'slur'], // Hanya filter kategori tertentu
263
- regions: ['jawa', 'general'], // Hanya filter dari daerah tertentu
264
- severityThreshold: 0.7, // Hanya filter kata dengan tingkat keparahan ≥ 0.7
265
-
266
- // Opsi lanjutan
267
- useRandomGrawlix: true, // Gunakan #@$%&! sebagai karakter pengganti
268
- keepFirstAndLast: true, // Simpan huruf pertama dan terakhir (a***g)
269
- indonesianVariation: true, // Deteksi variasi ejaan Indonesia
270
- detectSimilarity: true, // Deteksi kata yang mirip
271
- similarityThreshold: 0.8, // Ambang batas kesamaan
272
- detectSplit: true, // Deteksi kata yang dipisah
273
- useLevenshtein: true, // Gunakan algoritma Levenshtein
274
- maxLevenshteinDistance: 2, // Jarak Levenshtein maksimum
191
+ wordList: ['jelek', 'payah', 'curang'],
192
+ replaceWith: '#',
275
193
  });
276
- ```
277
-
278
- ### Menggunakan Whitelist
279
-
280
- ```typescript
281
- const filter = new IDProfanityFilter();
282
-
283
- // Menambahkan kata ke whitelist (akan diabaikan)
284
- filter.addToWhitelist('anjing');
285
194
 
286
- const teks =
287
- 'Anjing itu hewan peliharaan yang setia, tidak seperti bajingan itu';
195
+ const teks = 'Kualitas layanannya sangat jelek dan payah!';
288
196
  const hasil = filter.filter(teks);
289
197
 
290
198
  console.log(hasil.filtered);
291
- // Output: "Anjing itu hewan peliharaan yang setia, tidak seperti ******* itu"
292
- ```
293
-
294
- ### Deteksi Variasi Ejaan dan Kata Terpisah
295
-
296
- ```typescript
297
- // Aktifkan deteksi variasi ejaan dan kata terpisah
298
- const filter = new IDProfanityFilter({
299
- indonesianVariation: true,
300
- detectSplit: true,
301
- detectLeetSpeak: true,
302
- });
303
-
304
- // Uji dengan variasi ejaan
305
- const teks1 = 'Dasar kamu ini sangat bodoh, benar-benar b0d0h dan b-o-d-o-h!';
306
- const hasil1 = filter.filter(teks1);
307
- console.log(hasil1.filtered);
308
- // Output: "Dasar kamu ini sangat *****, benar-benar ***** dan *********!"
309
-
310
- // Uji dengan ejaan Indonesia yang berbeda
311
- const teks2 = 'Dia sangat djail dan djudes dengan temannya';
312
- const hasil2 = filter.filter(teks2);
313
- console.log(hasil2.filtered);
314
- // Output: "Dia sangat ***** dan ****** dengan temannya"
199
+ // Output: "Kualitas layanannya sangat ##### dan #####!"
315
200
  ```
316
201
 
317
- ### Deteksi Berdasarkan Kesamaan (Similarity Detection)
202
+ ### Deteksi typo dan Levenshtein distance
318
203
 
319
204
  ```typescript
320
- // Aktifkan deteksi kesamaan standar
321
- const filter = new IDProfanityFilter();
322
- filter.enableSimilarityDetection(0.75); // Set threshold kesamaan ke 0.75
323
-
324
- const teks = 'Dia benar-benar anjiing dan gooblok!';
325
- const analisis = filter.analyze(teks);
326
-
327
- console.log(analisis.similarWords);
328
- /* Output:
329
- [
330
- { word: "anjiing", original: "anjing", similarity: 0.83 },
331
- { word: "gooblok", original: "goblok", similarity: 0.85 }
332
- ]
333
- */
334
-
335
- const hasil = filter.filter(teks);
336
- console.log(hasil.filtered);
337
- // Output: "Dia benar-benar ****** dan *******!"
338
- ```
339
-
340
- ### Deteksi dengan Algoritma Levenshtein Distance
205
+ import IDProfanityFilter from '@sideid/id-profanity-filter';
341
206
 
342
- ```typescript
343
- // Aktifkan deteksi menggunakan algoritma Levenshtein Distance
344
207
  const filter = new IDProfanityFilter();
345
- filter.enableLevenshteinDetection(0.85, 2);
346
- // Threshold 0.85, maksimal 2 karakter berbeda
208
+ filter.enableLevenshteinDetection(0.8, 2);
347
209
 
348
- const teks = 'Dia benar-benar konntol dan anjiing sekali!';
210
+ const teks = 'Dia benar-benar anjiing sekali!';
349
211
  const hasil = filter.filter(teks);
350
212
 
351
213
  console.log(hasil.filtered);
352
- // Output: "Dia benar-benar ******* dan ****** sekali!"
353
-
354
- // Atau menggunakan opsi langsung:
355
- const filterCustom = new IDProfanityFilter({
356
- detectSimilarity: true,
357
- useLevenshtein: true,
358
- similarityThreshold: 0.85,
359
- maxLevenshteinDistance: 2,
360
- });
361
-
362
- // Mendeteksi typo atau variasi disengaja
363
- const teksVariasi = 'kontool kamu kwontol anjiing';
364
- console.log(filterCustom.filter(teksVariasi).filtered);
365
- // Output: "******* kamu ******* ******"
214
+ // Output: "Dia benar-benar ******* sekali!"
366
215
  ```
367
216
 
368
- ### Variasi Sensor Kata
217
+ ### Whitelist kontekstual
369
218
 
370
219
  ```typescript
371
- // Sensor standar (asterisk)
372
- const filter1 = new IDProfanityFilter();
373
- console.log(filter1.filter('Dasar anjing kamu!').filtered);
374
- // Output: "Dasar ***** kamu!"
375
-
376
- // Sensor dengan grawlix random
377
- const filter2 = new IDProfanityFilter({ useRandomGrawlix: true });
378
- console.log(filter2.filter('Dasar anjing kamu!').filtered);
379
- // Output: "Dasar #@$%& kamu!"
380
-
381
- // Sensor dengan menyimpan huruf pertama dan terakhir
382
- const filter3 = new IDProfanityFilter({
383
- fullWordCensor: false,
384
- keepFirstAndLast: true,
385
- });
386
- console.log(filter3.filter('Dasar anjing kamu!').filtered);
387
- // Output: "Dasar a***g kamu!"
388
- ```
389
-
390
- ### Analisis Konten Mendalam
220
+ import IDProfanityFilter from '@sideid/id-profanity-filter';
391
221
 
392
- ```typescript
393
222
  const filter = new IDProfanityFilter();
394
- const teks = 'Dasar anjing sialan! Kamu ini memang bego dan goblok.';
395
-
396
- // Analisis teks
397
- const analisis = filter.analyze(teks);
398
- console.log(analisis);
399
-
400
- /* Output:
401
- {
402
- hasProfanity: true,
403
- matches: ['anjing', 'sialan', 'bego', 'goblok'],
404
- matchDetails: [
405
- { word: 'anjing', category: 'profanity', region: 'general', severity: 0.7, ... },
406
- { word: 'bego', category: 'insult', region: 'general', severity: 0.5, ... },
407
- ...
408
- ],
409
- categories: ['profanity', 'insult'],
410
- regions: ['general'],
411
- severityScore: 0.64
412
- }
413
- */
414
- ```
415
-
416
- ### Analisis Konteks
223
+ filter.addToWhitelist('anjing');
417
224
 
418
- ```typescript
419
- const filter = new IDProfanityFilter();
420
- const teks =
421
- 'Saya sangat marah dengan sikapnya, dia benar-benar anjing dan bajingan!';
422
-
423
- // Analisis konteks
424
- const konteks = filter.analyzeWithContext(teks, 3);
425
- console.log(konteks);
426
-
427
- /* Output:
428
- [
429
- {
430
- word: "anjing",
431
- context: "benar-benar anjing dan bajingan",
432
- position: { start: 43, end: 62 }
433
- },
434
- {
435
- word: "bajingan",
436
- context: "anjing dan bajingan!",
437
- position: { start: 54, end: 63 }
438
- }
439
- ]
440
- */
225
+ const teks = 'Anjing peliharaan saya setia sekali.';
226
+ console.log(filter.isProfane(teks)); // false
441
227
  ```
442
228
 
443
- ### Analisis Per-Kalimat
229
+ ### Analisis per kalimat
444
230
 
445
231
  ```typescript
446
- const filter = new IDProfanityFilter();
447
- const teks =
448
- 'Filmnya bagus sekali. Tetapi pemainnya seperti anjing, sangat buruk aktingnya.';
449
-
450
- // Analisis per-kalimat
451
- const kalimat = filter.analyzeBySentence(teks);
452
- console.log(
453
- kalimat.map(
454
- (k) =>
455
- k.sentence + (k.hasProfanity ? ' (Mengandung kata kotor)' : ' (Bersih)'),
456
- ),
457
- );
458
-
459
- /* Output:
460
- [
461
- "Filmnya bagus sekali. (Bersih)",
462
- "Tetapi pemainnya seperti anjing, sangat buruk aktingnya. (Mengandung kata kotor)"
463
- ]
464
- */
465
- ```
466
-
467
- ### Analisis Batch
232
+ import IDProfanityFilter from '@sideid/id-profanity-filter';
468
233
 
469
- ```typescript
470
234
  const filter = new IDProfanityFilter();
471
- const komentar = [
472
- 'Film ini sangat bagus, ceritanya menarik sekali!',
473
- 'Dasar goblok, sialan kamu!',
474
- 'Anjing emang filmnya, sampah banget.',
475
- ];
476
-
477
- const hasil = filter.batchAnalyze(komentar);
478
- console.log(hasil);
479
-
480
- /* Output:
481
- {
482
- totalTexts: 3,
483
- profaneTexts: 2,
484
- cleanTexts: 1,
485
- averageSeverity: 0.62,
486
- topCategories: ['profanity', 'insult'],
487
- topRegions: ['general'],
488
- mostFrequentWords: [
489
- { word: 'anjing', count: 1 },
490
- { word: 'goblok', count: 1 },
491
- { word: 'sialan', count: 1 },
492
- { word: 'sampah', count: 1 }
493
- ]
494
- }
495
- */
496
- ```
497
-
498
- ## Dukungan Regional
499
-
500
- Library ini mendukung kata-kata kotor dari berbagai daerah di Indonesia:
501
-
502
- - 🇮🇩 **General** - Kata-kata yang umum di seluruh Indonesia
503
- - 🏝️ **Jawa** - Kata-kata dari bahasa Jawa
504
- - 🏞️ **Sunda** - Kata-kata dari bahasa Sunda
505
- - 🏙️ **Betawi** - Kata-kata dari bahasa Betawi
506
- - 🌋 **Batak** - Kata-kata dari bahasa Batak
507
-
508
- ## Kategori Kata
509
-
510
- Kata-kata dikelompokkan berdasarkan kategori:
235
+ const teks = 'Filmnya bagus sekali. Tapi pemainnya seperti anjing, aktingnya buruk.';
511
236
 
512
- - `sexual`: Kata-kata berbau seksual
513
- - `insult`: Kata-kata penghinaan
514
- - `profanity`: Umpatan umum
515
- - `slur`: Perkataan merendahkan berdasarkan identitas
516
- - `drugs`: Terkait narkoba
517
- - `disgusting`: Kata-kata menjijikkan
518
- - `blasphemy`: Penistaan agama
237
+ const hasilKalimat = filter.analyzeBySentence(teks);
238
+ hasilKalimat.forEach((item) => {
239
+ console.log(`${item.sentence} -> ${item.hasProfanity ? 'Kotor' : 'Bersih'}`);
240
+ });
241
+ // "Filmnya bagus sekali." -> Bersih
242
+ // "Tapi pemainnya seperti anjing, aktingnya buruk." -> Kotor
243
+ ```
519
244
 
520
- ## Berkontribusi
245
+ ## Cakupan daerah dan kategori
521
246
 
522
- Kami sangat menghargai kontribusi Anda! Untuk berkontribusi, silakan lihat [panduan kontribusi](CONTRIBUTING.md).
247
+ ### Bahasa daerah
248
+ - `general`: Bahasa Indonesia umum
249
+ - `jawa`: Bahasa Jawa
250
+ - `sunda`: Bahasa Sunda
251
+ - `betawi`: Dialek Betawi
252
+ - `batak`: Bahasa Batak
253
+ - `minang`: Bahasa Minang
254
+ - `bali`: Bahasa Bali
255
+ - `madura`: Bahasa Madura
256
+ - `aceh`: Bahasa Aceh
523
257
 
524
- ### Menambahkan Kata Baru
258
+ ### Kategori kata
259
+ - `sexual`: Istilah atau aktivitas seksual vulgar
260
+ - `insult`: Penghinaan atau caci maki
261
+ - `profanity`: Umpatan kasar umum
262
+ - `slur`: Kata merendahkan SARA / identitas
263
+ - `drugs`: Istilah obat-obatan terlarang
264
+ - `disgusting`: Kata jorok atau menjijikkan
265
+ - `blasphemy`: Umpatan penistaan agama
525
266
 
526
- Jika Anda ingin menambahkan kata baru ke database, silakan buat pull request dengan mengubah file yang sesuai di `src/constants/categories/` atau `src/constants/regions/`.
267
+ ## Kontribusi
527
268
 
528
- Format untuk menambahkan kata baru:
529
-
530
- ```json
531
- {
532
- "word": "kata_kotor", // Kata yang akan difilter
533
- "category": "insult", // Kategori kata
534
- "region": "general", // Daerah asal kata
535
- "severity": 0.7, // Tingkat keparahan (0-1)
536
- "aliases": ["k4t4_kotor", "kata_k0t0r"], // Alias atau variasi umum
537
- "description": "Deskripsi tentang kata", // Penjelasan tentang kata (opsional)
538
- "context": "Konteks penggunaan kata" // Konteks penggunaan (opsional)
539
- }
540
- ```
269
+ Panduan untuk menambahkan kata baru atau mengembangkan library dapat dilihat di [CONTRIBUTING.md](CONTRIBUTING.md).
541
270
 
542
271
  ## Lisensi
543
272
 
544
- Proyek ini dilisensikan di bawah [MIT License](LICENSE).
545
-
546
- ## Kontak & Dukungan
547
-
548
- Jika Anda memiliki pertanyaan atau saran, silakan buka issue di repositori GitHub kami.
273
+ Proyek ini menggunakan lisensi [MIT](LICENSE).