@sideid/id-profanity-filter
Version:
Library filter kata kotor dalam Bahasa Indonesia
568 lines (427 loc) • 17.6 kB
Markdown
<div align="center">
<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">
</div>
---
<div align="center">
<a href="https://www.npmjs.com/package/@sideid/id-profanity-filter">
<img src="https://img.shields.io/npm/v/@sideid/id-profanity-filter.svg" alt="NPM Version">
</a>
<a href="https://www.npmjs.com/package/@sideid/id-profanity-filter">
<img src="https://img.shields.io/npm/dt/@sideid/id-profanity-filter?label=npm&color=%23CB3837" alt="NPM Downloads">
</a>
<a href="https://github.com/SideeID/id-profanity-filter">
<img src="https://img.shields.io/github/languages/code-size/SideeID/id-profanity-filter" alt="GitHub Code Size">
</a>
<a href="https://github.com/SideeID/id-profanity-filter">
<img src="https://img.shields.io/github/license/SideeID/id-profanity-filter" alt="GitHub License">
</a>
<a href="https://github.com/SideeID/id-profanity-filter">
<img src="https://img.shields.io/github/stars/SideeID/id-profanity-filter" alt="GitHub Stars">
</a>
<a href="https://github.com/SideeID/id-profanity-filter">
<img src="https://img.shields.io/github/forks/SideeID/id-profanity-filter" alt="GitHub Forks">
</a>
</div>
## Fitur Utama
- 🔍 **Deteksi Kata Kotor** - Mendeteksi kata-kata kasar/kotor dalam teks Bahasa Indonesia
- ⚠️ **Analisis Konten** - Menganalisis tingkat keparahan dan kategori kata kotor
- 🔒 **Penyensoran** - Menyensor kata-kata kotor dengan berbagai opsi kustomisasi
- 🗺️ **Dukungan Bahasa Daerah** - Mencakup kata-kata dari berbagai daerah di Indonesia (Jawa, Sunda, Batak, dll)
- 🧠 **Deteksi Cerdas** - Mendeteksi variasi ejaan, kata terpisah, dan kesamaan kata
- 🔠 **Deteksi Levenshtein** - Mendeteksi kata kotor yang dimodifikasi dengan typo atau sengaja disamarkan
- 🛡️ **Preset** - Preset filter siap pakai untuk berbagai kebutuhan
- 🔧 **Kustomisasi** - Opsi untuk menambahkan whitelist dan daftar kata kustom
## Instalasi
```bash
npm install @sideid/id-profanity-filter
# atau
yarn add @sideid/id-profanity-filter
# atau
pnpm add @sideid/id-profanity-filter
```
## Penggunaan Dasar
### JavaScript / TypeScript
```typescript
import IDProfanityFilter from '@sideid/id-profanity-filter';
// Buat instance filter
const filter = new IDProfanityFilter();
// Cek apakah teks mengandung kata kotor
const teks = 'Dasar anjing kamu, jangan banyak bacot!';
const hasProfanity = filter.isProfane(teks);
console.log(hasProfanity); // Output: true
// Filter kata kotor (sensorisasi)
const hasil = filter.filter(teks);
console.log(hasil.filtered); // Output: "Dasar ***** kamu, jangan banyak *****!"
console.log(hasil.censored); // Output: 2 (jumlah kata yang disensor)
// Analisis konten
const analisis = filter.analyze(teks);
console.log(analisis.severityScore); // Output: 0.65 (contoh skor keparahan)
console.log(analisis.categories); // Output: ["profanity", "insult"]
```
### Menggunakan Preset
```typescript
import IDProfanityFilter from '@sideid/id-profanity-filter';
// Buat instance filter dengan preset
const filter = new IDProfanityFilter();
filter.usePreset('strict');
// Atau dengan opsi tambahan
filter.usePreset('childSafe', {
replaceWith: '#',
useRandomGrawlix: true,
});
const teks = 'Dasar anjing kamu, jangan banyak bacot!';
const hasil = filter.filter(teks);
console.log(hasil.filtered); // Output: "Dasar #@$%& kamu, jangan banyak $!@#%!"
```
### Utilitas Langsung
Anda juga dapat menggunakan fungsi utilitas langsung tanpa membuat instance:
```typescript
import { idFilter } from '@sideid/id-profanity-filter';
const teks = 'Dasar anjing kamu, jangan banyak bacot!';
const hasil = idFilter.filter(teks);
console.log(hasil.filtered); // Output: "Dasar ***** kamu, jangan banyak *****!"
// Menggunakan preset dengan API fungsi statis
const presetResult = idFilter.filter(
teks,
idFilter.getPresetOptions('moderate'),
);
```
## Dokumentasi API
### Kelas `IDProfanityFilter`
#### Konstruktor
```typescript
constructor(options?: FilterOptions)
```
- **options**: Opsi konfigurasi filter (opsional)
#### Metode
##### `filter(text: string): FilterResult`
Menyensor kata kotor dalam teks.
- **Hasil**: Objek `FilterResult` dengan properti:
- `filtered`: String teks yang sudah disensor
- `censored`: Jumlah kata yang disensor
- `replacements`: Array berisi detail kata yang disensor
##### `isProfane(text: string): boolean`
Memeriksa apakah teks mengandung kata kotor.
- **Hasil**: Boolean `true` jika teks mengandung kata kotor, `false` jika tidak
##### `analyze(text: string): AnalysisResult`
Menganalisis teks untuk mendapatkan informasi detail tentang kata kotor yang ditemukan.
- **Hasil**: Objek `AnalysisResult` dengan properti:
- `hasProfanity`: Apakah teks mengandung kata kotor
- `matches`: Array kata kotor yang ditemukan
- `matchDetails`: Array objek kata kotor dengan metadata
- `categories`: Kategori kata kotor yang ditemukan
- `regions`: Daerah asal kata kotor yang ditemukan
- `severityScore`: Skor keparahan (0-1)
- `similarWords`: Kata-kata yang mirip dengan kata kotor (jika deteksi kesamaan diaktifkan)
##### `batchAnalyze(texts: string[])`
Menganalisis batch teks sekaligus dan memberikan ringkasan.
- **Hasil**: Objek yang berisi ringkasan analisis
##### `analyzeBySentence(text: string)`
Menganalisis teks per-kalimat.
- **Hasil**: Array dari hasil analisis per-kalimat
##### `analyzeWithContext(text: string, contextWindowSize?: number)`
Menganalisis teks dengan konteks di sekitar kata kotor.
- **Hasil**: Array dari kata kotor dengan konteks di sekitarnya
##### `usePreset(presetName: string, additionalOptions?: Partial<FilterOptions>)`
Menggunakan preset filter yang telah ditentukan.
- **presetName**: Nama preset ('strict', 'moderate', 'light', 'childSafe', dll)
- **additionalOptions**: Opsi tambahan untuk override preset (opsional)
##### `setOptions(options: Partial<FilterOptions>)`
Mengubah opsi filter.
##### `setWordList(wordList: string[])`
Menetapkan daftar kata kustom.
##### `addToWhitelist(word: string)`
Menambahkan kata ke whitelist (akan diabaikan dalam filter).
##### `removeFromWhitelist(word: string)`
Menghapus kata dari whitelist.
##### `enableIndonesianVariations()`
Mengaktifkan deteksi variasi ejaan Bahasa Indonesia.
##### `enableSplitWordDetection()`
Mengaktifkan deteksi kata yang dipisah.
##### `enableSimilarityDetection(threshold: number = 0.8, useLevenshtein: boolean = false, maxLevenshteinDistance: number = 2)`
Mengaktifkan deteksi berdasarkan kesamaan kata.
- **threshold**: Ambang batas kesamaan (0-1, default: 0.8)
- **useLevenshtein**: Gunakan algoritma Levenshtein untuk deteksi (default: false)
- **maxLevenshteinDistance**: Jarak edit maksimum yang diizinkan (default: 2)
##### `enableLevenshteinDetection(threshold: number = 0.8, maxDistance: number = 2)`
Mengaktifkan deteksi berbasis jarak Levenshtein.
- **threshold**: Ambang batas kesamaan (0-1, default: 0.8)
- **maxDistance**: Jarak edit maksimum yang diizinkan (default: 2)
### Opsi Filter
```typescript
interface FilterOptions {
// Opsi dasar
wordList?: string[]; // List kata yang ingin difilter
replaceWith?: string; // Karakter pengganti untuk kata yang disensor
fullWordCensor?: boolean; // Apakah menyensor seluruh kata atau sebagian
detectLeetSpeak?: boolean; // Deteksi variasi penulisan (mis: a=4, e=3)
whitelist?: string[]; // Kata-kata yang dikecualikan dari filter
checkSubstring?: boolean; // Memeriksa substring (lebih ketat)
categories?: ProfanityCategory[]; // Kategori kata yang difilter
regions?: Region[]; // Daerah asal kata yang difilter
severityThreshold?: number; // Tingkat keparahan minimum (0-1)
// Opsi lanjutan
useRandomGrawlix?: boolean; // Gunakan karakter acak untuk sensor (#@$%&!)
keepFirstAndLast?: boolean; // Simpan huruf pertama dan terakhir (a***g)
indonesianVariation?: boolean; // Deteksi variasi ejaan Bahasa Indonesia
detectSimilarity?: boolean; // Deteksi kata berdasarkan kesamaan
similarityThreshold?: number; // Ambang batas kesamaan (0-1)
detectSplit?: boolean; // Deteksi kata yang dipisah (a-n-j-i-n-g)
useLevenshtein?: boolean; // Gunakan algoritma Levenshtein untuk deteksi kesamaan
maxLevenshteinDistance?: number; // Jarak edit maksimum untuk deteksi Levenshtein
}
```
## Preset Filter
Library ini menyediakan beberapa preset yang dapat digunakan:
### Preset Filter
- **strict**: Filter paling ketat, mendeteksi semua jenis kata kotor
- **moderate**: Filter tingkat menengah, mengabaikan kata-kata dengan tingkat keparahan rendah
- **light**: Filter ringan, hanya untuk kata-kata paling sensitif
- **childSafe**: Filter untuk konten anak-anak, sangat ketat
### Preset Kategori
- **sexual**: Hanya memfilter kata-kata berbau seksual
- **insults**: Hanya memfilter kata-kata penghinaan
- **profanity**: Hanya memfilter umpatan umum
### Preset Regional
- **general**: Hanya memfilter kata-kata umum di Indonesia
- **jawa**: Hanya memfilter kata-kata dari Jawa
- **sunda**: Hanya memfilter kata-kata dari Sunda
- **betawi**: Hanya memfilter kata-kata dari Betawi
- **batak**: Hanya memfilter kata-kata dari Batak
## Contoh Penggunaan Lanjutan
### Kustomisasi Opsi Filter
```typescript
const filter = new IDProfanityFilter({
replaceWith: '#', // Menggunakan # sebagai karakter pengganti
fullWordCensor: false, // Hanya menyensor sebagian kata
detectLeetSpeak: true, // Mendeteksi variasi seperti "b4b1" untuk "babi"
categories: ['sexual', 'slur'], // Hanya filter kategori tertentu
regions: ['jawa', 'general'], // Hanya filter dari daerah tertentu
severityThreshold: 0.7, // Hanya filter kata dengan tingkat keparahan ≥ 0.7
// Opsi lanjutan
useRandomGrawlix: true, // Gunakan #@$%&! sebagai karakter pengganti
keepFirstAndLast: true, // Simpan huruf pertama dan terakhir (a***g)
indonesianVariation: true, // Deteksi variasi ejaan Indonesia
detectSimilarity: true, // Deteksi kata yang mirip
similarityThreshold: 0.8, // Ambang batas kesamaan
detectSplit: true, // Deteksi kata yang dipisah
useLevenshtein: true, // Gunakan algoritma Levenshtein
maxLevenshteinDistance: 2, // Jarak Levenshtein maksimum
});
```
### Menggunakan Whitelist
```typescript
const filter = new IDProfanityFilter();
// Menambahkan kata ke whitelist (akan diabaikan)
filter.addToWhitelist('anjing');
const teks =
'Anjing itu hewan peliharaan yang setia, tidak seperti bajingan itu';
const hasil = filter.filter(teks);
console.log(hasil.filtered);
// Output: "Anjing itu hewan peliharaan yang setia, tidak seperti ******* itu"
```
### Deteksi Variasi Ejaan dan Kata Terpisah
```typescript
// Aktifkan deteksi variasi ejaan dan kata terpisah
const filter = new IDProfanityFilter({
indonesianVariation: true,
detectSplit: true,
detectLeetSpeak: true,
});
// Uji dengan variasi ejaan
const teks1 = 'Dasar kamu ini sangat bodoh, benar-benar b0d0h dan b-o-d-o-h!';
const hasil1 = filter.filter(teks1);
console.log(hasil1.filtered);
// Output: "Dasar kamu ini sangat *****, benar-benar ***** dan *********!"
// Uji dengan ejaan Indonesia yang berbeda
const teks2 = 'Dia sangat djail dan djudes dengan temannya';
const hasil2 = filter.filter(teks2);
console.log(hasil2.filtered);
// Output: "Dia sangat ***** dan ****** dengan temannya"
```
### Deteksi Berdasarkan Kesamaan (Similarity Detection)
```typescript
// Aktifkan deteksi kesamaan standar
const filter = new IDProfanityFilter();
filter.enableSimilarityDetection(0.75); // Set threshold kesamaan ke 0.75
const teks = 'Dia benar-benar anjiing dan gooblok!';
const analisis = filter.analyze(teks);
console.log(analisis.similarWords);
/* Output:
[
{ word: "anjiing", original: "anjing", similarity: 0.83 },
{ word: "gooblok", original: "goblok", similarity: 0.85 }
]
*/
const hasil = filter.filter(teks);
console.log(hasil.filtered);
// Output: "Dia benar-benar ****** dan *******!"
```
### Deteksi dengan Algoritma Levenshtein Distance
```typescript
// Aktifkan deteksi menggunakan algoritma Levenshtein Distance
const filter = new IDProfanityFilter();
filter.enableLevenshteinDetection(0.85, 2);
// Threshold 0.85, maksimal 2 karakter berbeda
const teks = 'Dia benar-benar konntol dan anjiing sekali!';
const hasil = filter.filter(teks);
console.log(hasil.filtered);
// Output: "Dia benar-benar ******* dan ****** sekali!"
// Atau menggunakan opsi langsung:
const filterCustom = new IDProfanityFilter({
detectSimilarity: true,
useLevenshtein: true,
similarityThreshold: 0.85,
maxLevenshteinDistance: 2,
});
// Mendeteksi typo atau variasi disengaja
const teksVariasi = 'kontool kamu kwontol anjiing';
console.log(filterCustom.filter(teksVariasi).filtered);
// Output: "******* kamu ******* ******"
```
### Variasi Sensor Kata
```typescript
// Sensor standar (asterisk)
const filter1 = new IDProfanityFilter();
console.log(filter1.filter('Dasar anjing kamu!').filtered);
// Output: "Dasar ***** kamu!"
// Sensor dengan grawlix random
const filter2 = new IDProfanityFilter({ useRandomGrawlix: true });
console.log(filter2.filter('Dasar anjing kamu!').filtered);
// Output: "Dasar #@$%& kamu!"
// Sensor dengan menyimpan huruf pertama dan terakhir
const filter3 = new IDProfanityFilter({
fullWordCensor: false,
keepFirstAndLast: true,
});
console.log(filter3.filter('Dasar anjing kamu!').filtered);
// Output: "Dasar a***g kamu!"
```
### Analisis Konten Mendalam
```typescript
const filter = new IDProfanityFilter();
const teks = 'Dasar anjing sialan! Kamu ini memang bego dan goblok.';
// Analisis teks
const analisis = filter.analyze(teks);
console.log(analisis);
/* Output:
{
hasProfanity: true,
matches: ['anjing', 'sialan', 'bego', 'goblok'],
matchDetails: [
{ word: 'anjing', category: 'profanity', region: 'general', severity: 0.7, ... },
{ word: 'bego', category: 'insult', region: 'general', severity: 0.5, ... },
...
],
categories: ['profanity', 'insult'],
regions: ['general'],
severityScore: 0.64
}
*/
```
### Analisis Konteks
```typescript
const filter = new IDProfanityFilter();
const teks =
'Saya sangat marah dengan sikapnya, dia benar-benar anjing dan bajingan!';
// Analisis konteks
const konteks = filter.analyzeWithContext(teks, 3);
console.log(konteks);
/* Output:
[
{
word: "anjing",
context: "benar-benar anjing dan bajingan",
position: { start: 43, end: 62 }
},
{
word: "bajingan",
context: "anjing dan bajingan!",
position: { start: 54, end: 63 }
}
]
*/
```
### Analisis Per-Kalimat
```typescript
const filter = new IDProfanityFilter();
const teks =
'Filmnya bagus sekali. Tetapi pemainnya seperti anjing, sangat buruk aktingnya.';
// Analisis per-kalimat
const kalimat = filter.analyzeBySentence(teks);
console.log(
kalimat.map(
(k) =>
k.sentence + (k.hasProfanity ? ' (Mengandung kata kotor)' : ' (Bersih)'),
),
);
/* Output:
[
"Filmnya bagus sekali. (Bersih)",
"Tetapi pemainnya seperti anjing, sangat buruk aktingnya. (Mengandung kata kotor)"
]
*/
```
### Analisis Batch
```typescript
const filter = new IDProfanityFilter();
const komentar = [
'Film ini sangat bagus, ceritanya menarik sekali!',
'Dasar goblok, sialan kamu!',
'Anjing emang filmnya, sampah banget.',
];
const hasil = filter.batchAnalyze(komentar);
console.log(hasil);
/* Output:
{
totalTexts: 3,
profaneTexts: 2,
cleanTexts: 1,
averageSeverity: 0.62,
topCategories: ['profanity', 'insult'],
topRegions: ['general'],
mostFrequentWords: [
{ word: 'anjing', count: 1 },
{ word: 'goblok', count: 1 },
{ word: 'sialan', count: 1 },
{ word: 'sampah', count: 1 }
]
}
*/
```
## Dukungan Regional
Library ini mendukung kata-kata kotor dari berbagai daerah di Indonesia:
- 🇮🇩 **General** - Kata-kata yang umum di seluruh Indonesia
- 🏝️ **Jawa** - Kata-kata dari bahasa Jawa
- 🏞️ **Sunda** - Kata-kata dari bahasa Sunda
- 🏙️ **Betawi** - Kata-kata dari bahasa Betawi
- 🌋 **Batak** - Kata-kata dari bahasa Batak
## Kategori Kata
Kata-kata dikelompokkan berdasarkan kategori:
- `sexual`: Kata-kata berbau seksual
- `insult`: Kata-kata penghinaan
- `profanity`: Umpatan umum
- `slur`: Perkataan merendahkan berdasarkan identitas
- `drugs`: Terkait narkoba
- `disgusting`: Kata-kata menjijikkan
- `blasphemy`: Penistaan agama
## Berkontribusi
Kami sangat menghargai kontribusi Anda! Untuk berkontribusi, silakan lihat [panduan kontribusi](CONTRIBUTING.md).
### Menambahkan Kata Baru
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/`.
Format untuk menambahkan kata baru:
```json
{
"word": "kata_kotor", // Kata yang akan difilter
"category": "insult", // Kategori kata
"region": "general", // Daerah asal kata
"severity": 0.7, // Tingkat keparahan (0-1)
"aliases": ["k4t4_kotor", "kata_k0t0r"], // Alias atau variasi umum
"description": "Deskripsi tentang kata", // Penjelasan tentang kata (opsional)
"context": "Konteks penggunaan kata" // Konteks penggunaan (opsional)
}
```
## Lisensi
Proyek ini dilisensikan di bawah [MIT License](LICENSE).
## Kontak & Dukungan
Jika Anda memiliki pertanyaan atau saran, silakan buka issue di repositori GitHub kami.