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