@sideid/id-profanity-filter 1.11.7 → 1.11.8

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 (53) hide show
  1. package/dist/index.d.ts +2 -2
  2. package/dist/index.esm.js +1004 -438
  3. package/dist/index.esm.js.map +1 -1
  4. package/dist/index.js +1004 -438
  5. package/dist/index.js.map +1 -1
  6. package/dist/types/config/options.d.ts +1 -1
  7. package/dist/types/constants/categories/blasphemy.d.ts +1 -1
  8. package/dist/types/constants/categories/disgusting.d.ts +1 -1
  9. package/dist/types/constants/categories/drugs.d.ts +1 -1
  10. package/dist/types/constants/categories/insult.d.ts +1 -1
  11. package/dist/types/constants/categories/profanity.d.ts +1 -1
  12. package/dist/types/constants/categories/sexual.d.ts +1 -1
  13. package/dist/types/constants/categories/slur.d.ts +1 -1
  14. package/dist/types/constants/regions/bali.d.ts +1 -1
  15. package/dist/types/constants/regions/batak.d.ts +1 -1
  16. package/dist/types/constants/regions/betawi.d.ts +1 -1
  17. package/dist/types/constants/regions/general.d.ts +1 -1
  18. package/dist/types/constants/regions/minang.d.ts +4 -0
  19. package/dist/types/constants/wordList.d.ts +10 -1
  20. package/dist/types/core/analyzer.d.ts +1 -1
  21. package/dist/types/core/filter.d.ts +1 -1
  22. package/dist/types/core/matcher.d.ts +1 -1
  23. package/dist/types/types/index.d.ts +2 -2
  24. package/dist/types/utils/regexUtils.d.ts +1 -1
  25. package/package.json +1 -1
  26. package/src/config/options.ts +25 -30
  27. package/src/constants/categories/blasphemy.ts +26 -15
  28. package/src/constants/categories/disgusting.ts +62 -54
  29. package/src/constants/categories/drugs.ts +56 -47
  30. package/src/constants/categories/insult.ts +80 -76
  31. package/src/constants/categories/profanity.ts +98 -92
  32. package/src/constants/categories/sexual.ts +74 -65
  33. package/src/constants/categories/slur.ts +73 -66
  34. package/src/constants/regions/aceh.ts +5 -9
  35. package/src/constants/regions/bali.ts +4 -7
  36. package/src/constants/regions/batak.ts +5 -9
  37. package/src/constants/regions/betawi.ts +19 -22
  38. package/src/constants/regions/general.ts +140 -144
  39. package/src/constants/regions/jawa.ts +11 -29
  40. package/src/constants/regions/madura.ts +2 -4
  41. package/src/constants/regions/minang.ts +53 -0
  42. package/src/constants/regions/sunda.ts +2 -4
  43. package/src/constants/wordList.ts +31 -34
  44. package/src/core/analyzer.ts +15 -26
  45. package/src/core/filter.ts +23 -39
  46. package/src/core/matcher.ts +25 -49
  47. package/src/index.ts +5 -16
  48. package/src/types/index.ts +26 -25
  49. package/src/utils/ahoCorasick.ts +1 -1
  50. package/src/utils/regexUtils.ts +37 -43
  51. package/src/utils/similarityUtils.ts +13 -28
  52. package/src/utils/stringUtils.ts +30 -38
  53. /package/{prettierrc → .prettierrc} +0 -0
package/dist/index.js CHANGED
@@ -4,212 +4,212 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  const general = [
6
6
  {
7
- word: "anjing",
8
- category: "profanity",
9
- region: "general",
7
+ word: 'anjing',
8
+ category: 'profanity',
9
+ region: 'general',
10
10
  severity: 0.7,
11
- aliases: ["anjay", "anjir", "anying", "njing", "anj", "anjg", "ajg"],
12
- description: "Mengacu pada hewan anjing, digunakan sebagai umpatan",
13
- context: "Umpatan umum untuk menunjukkan kemarahan atau ketidaksetujuan",
11
+ aliases: ['anjay', 'anjir', 'anying', 'njing', 'anj', 'anjg', 'ajg'],
12
+ description: 'Mengacu pada hewan anjing, digunakan sebagai umpatan',
13
+ context: 'Umpatan umum untuk menunjukkan kemarahan atau ketidaksetujuan',
14
14
  },
15
15
  {
16
- word: "babi",
17
- category: "profanity",
18
- region: "general",
16
+ word: 'babi',
17
+ category: 'profanity',
18
+ region: 'general',
19
19
  severity: 0.6,
20
- aliases: ["bab1", "b4b1", "b4bi", "8481", "8ab1", "ba81"],
21
- description: "Mengacu pada hewan babi, digunakan sebagai umpatan",
22
- context: "Umpatan umum untuk menunjukkan kemarahan atau ketidaksetujuan",
20
+ aliases: ['bab1', 'b4b1', 'b4bi', '8481', '8ab1', 'ba81'],
21
+ description: 'Mengacu pada hewan babi, digunakan sebagai umpatan',
22
+ context: 'Umpatan umum untuk menunjukkan kemarahan atau ketidaksetujuan',
23
23
  },
24
24
  {
25
- word: "bangsat",
26
- category: "insult",
27
- region: "general",
25
+ word: 'bangsat',
26
+ category: 'insult',
27
+ region: 'general',
28
28
  severity: 0.8,
29
- aliases: ["bangst", "bngst", "bgst"],
30
- description: "Secara harfiah berarti kutu busuk, digunakan sebagai umpatan untuk menyebut seseorang yang tidak bermoral",
31
- context: "Umpatan kasar untuk menyebut orang yang dianggap jahat atau merugikan",
29
+ aliases: ['bangst', 'bngst', 'bgst'],
30
+ description: 'Secara harfiah berarti kutu busuk, digunakan sebagai umpatan untuk menyebut seseorang yang tidak bermoral',
31
+ context: 'Umpatan kasar untuk menyebut orang yang dianggap jahat atau merugikan',
32
32
  },
33
33
  {
34
- word: "kontol",
35
- category: "sexual",
36
- region: "general",
34
+ word: 'kontol',
35
+ category: 'sexual',
36
+ region: 'general',
37
37
  severity: 0.9,
38
- aliases: ["kntl", "k0ntol", "k0nt0l"],
39
- description: "Kata vulgar yang mengacu pada alat kelamin laki-laki",
40
- context: "Umpatan kasar atau istilah vulgar untuk alat kelamin",
38
+ aliases: ['kntl', 'k0ntol', 'k0nt0l'],
39
+ description: 'Kata vulgar yang mengacu pada alat kelamin laki-laki',
40
+ context: 'Umpatan kasar atau istilah vulgar untuk alat kelamin',
41
41
  },
42
42
  {
43
- word: "memek",
44
- category: "sexual",
45
- region: "general",
43
+ word: 'memek',
44
+ category: 'sexual',
45
+ region: 'general',
46
46
  severity: 0.9,
47
- aliases: ["mmk", "memk"],
48
- description: "Kata vulgar yang mengacu pada alat kelamin perempuan",
49
- context: "Umpatan kasar atau istilah vulgar untuk alat kelamin",
47
+ aliases: ['mmk', 'memk'],
48
+ description: 'Kata vulgar yang mengacu pada alat kelamin perempuan',
49
+ context: 'Umpatan kasar atau istilah vulgar untuk alat kelamin',
50
50
  },
51
51
  {
52
- word: "bego",
53
- category: "insult",
54
- region: "general",
52
+ word: 'bego',
53
+ category: 'insult',
54
+ region: 'general',
55
55
  severity: 0.5,
56
- aliases: ["bgo", "begok"],
57
- description: "Kata yang mengacu pada kebodohan seseorang",
58
- context: "Hinaan untuk menyebut orang yang dianggap tidak pintar",
56
+ aliases: ['bgo', 'begok'],
57
+ description: 'Kata yang mengacu pada kebodohan seseorang',
58
+ context: 'Hinaan untuk menyebut orang yang dianggap tidak pintar',
59
59
  },
60
60
  {
61
- word: "tolol",
62
- category: "insult",
63
- region: "general",
61
+ word: 'tolol',
62
+ category: 'insult',
63
+ region: 'general',
64
64
  severity: 0.6,
65
- aliases: ["tll", "tlol"],
66
- description: "Kata yang mengacu pada kebodohan seseorang",
67
- context: "Hinaan untuk menyebut orang yang dianggap tidak pintar",
65
+ aliases: ['tll', 'tlol'],
66
+ description: 'Kata yang mengacu pada kebodohan seseorang',
67
+ context: 'Hinaan untuk menyebut orang yang dianggap tidak pintar',
68
68
  },
69
69
  {
70
- word: "bajingan",
71
- category: "insult",
72
- region: "general",
70
+ word: 'bajingan',
71
+ category: 'insult',
72
+ region: 'general',
73
73
  severity: 0.7,
74
- aliases: ["bajingn", "bjgn"],
75
- description: "Kata yang mengacu pada orang jahat atau tidak bermoral",
76
- context: "Hinaan untuk menyebut orang yang dianggap jahat atau tidak bermoral",
74
+ aliases: ['bajingn', 'bjgn'],
75
+ description: 'Kata yang mengacu pada orang jahat atau tidak bermoral',
76
+ context: 'Hinaan untuk menyebut orang yang dianggap jahat atau tidak bermoral',
77
77
  },
78
78
  {
79
- word: "goblok",
80
- category: "insult",
81
- region: "general",
79
+ word: 'goblok',
80
+ category: 'insult',
81
+ region: 'general',
82
82
  severity: 0.6,
83
- aliases: ["gblk", "goblk"],
84
- description: "Kata yang mengacu pada kebodohan seseorang",
85
- context: "Hinaan untuk menyebut orang yang dianggap tidak pintar",
83
+ aliases: ['gblk', 'goblk'],
84
+ description: 'Kata yang mengacu pada kebodohan seseorang',
85
+ context: 'Hinaan untuk menyebut orang yang dianggap tidak pintar',
86
86
  },
87
87
  {
88
- word: "keparat",
89
- category: "insult",
90
- region: "general",
88
+ word: 'keparat',
89
+ category: 'insult',
90
+ region: 'general',
91
91
  severity: 0.7,
92
- aliases: ["kprt", "keprat"],
93
- description: "Kata yang mengacu pada orang jahat atau tidak bermoral",
94
- context: "Hinaan untuk menyebut orang yang dianggap jahat atau tidak bermoral",
92
+ aliases: ['kprt', 'keprat'],
93
+ description: 'Kata yang mengacu pada orang jahat atau tidak bermoral',
94
+ context: 'Hinaan untuk menyebut orang yang dianggap jahat atau tidak bermoral',
95
95
  },
96
96
  {
97
- word: "bacot",
98
- category: "insult",
99
- region: "general",
97
+ word: 'bacot',
98
+ category: 'insult',
99
+ region: 'general',
100
100
  severity: 0.5,
101
- aliases: ["bcot", "bacot2"],
102
- description: "Kata yang mengacu pada orang yang banyak bicara",
103
- context: "Hinaan untuk menyebut orang yang banyak bicara atau cerewet",
101
+ aliases: ['bcot', 'bacot2'],
102
+ description: 'Kata yang mengacu pada orang yang banyak bicara',
103
+ context: 'Hinaan untuk menyebut orang yang banyak bicara atau cerewet',
104
104
  },
105
105
  {
106
- word: "ngentot",
107
- category: "sexual",
108
- region: "general",
106
+ word: 'ngentot',
107
+ category: 'sexual',
108
+ region: 'general',
109
109
  severity: 0.9,
110
- aliases: ["ngentod", "ntot", "tod"],
111
- description: "Istilah kasar untuk aktivitas seksual",
112
- context: "Kata vulgar yang merujuk pada aktivitas seksual",
110
+ aliases: ['ngentod', 'ntot', 'tod'],
111
+ description: 'Istilah kasar untuk aktivitas seksual',
112
+ context: 'Kata vulgar yang merujuk pada aktivitas seksual',
113
113
  },
114
114
  {
115
- word: "sialan",
116
- category: "insult",
117
- region: "general",
115
+ word: 'sialan',
116
+ category: 'insult',
117
+ region: 'general',
118
118
  severity: 0.5,
119
- aliases: ["sialn", "sl"],
120
- description: "Kata yang mengacu pada orang yang membawa sial",
121
- context: "Hinaan untuk menyebut orang yang dianggap membawa sial",
119
+ aliases: ['sialn', 'sl'],
120
+ description: 'Kata yang mengacu pada orang yang membawa sial',
121
+ context: 'Hinaan untuk menyebut orang yang dianggap membawa sial',
122
122
  },
123
123
  {
124
- word: "pler",
125
- category: "sexual",
126
- region: "general",
124
+ word: 'pler',
125
+ category: 'sexual',
126
+ region: 'general',
127
127
  severity: 0.9,
128
- aliases: ["peler", "plr", "biji"],
129
- description: "Istilah kasar untuk alat kelamin laki-laki",
130
- context: "Kata vulgar yang merujuk pada alat kelamin laki-laki",
128
+ aliases: ['peler', 'plr', 'biji'],
129
+ description: 'Istilah kasar untuk alat kelamin laki-laki',
130
+ context: 'Kata vulgar yang merujuk pada alat kelamin laki-laki',
131
131
  },
132
132
  {
133
- word: "bokep",
134
- category: "sexual",
135
- region: "general",
133
+ word: 'bokep',
134
+ category: 'sexual',
135
+ region: 'general',
136
136
  severity: 0.7,
137
- aliases: ["bkp", "bokap"],
138
- description: "Istilah untuk video atau konten pornografi",
139
- context: "Kata yang mengacu pada materi pornografi",
137
+ aliases: ['bkp', 'bokap'],
138
+ description: 'Istilah untuk video atau konten pornografi',
139
+ context: 'Kata yang mengacu pada materi pornografi',
140
140
  },
141
141
  {
142
- word: "coli",
143
- category: "sexual",
144
- region: "general",
142
+ word: 'coli',
143
+ category: 'sexual',
144
+ region: 'general',
145
145
  severity: 0.8,
146
- aliases: ["col", "coly"],
147
- description: "Istilah untuk masturbasi laki-laki",
148
- context: "Kata vulgar yang merujuk pada aktivitas seksual pribadi",
146
+ aliases: ['col', 'coly'],
147
+ description: 'Istilah untuk masturbasi laki-laki',
148
+ context: 'Kata vulgar yang merujuk pada aktivitas seksual pribadi',
149
149
  },
150
150
  {
151
- word: "desah",
152
- category: "sexual",
153
- region: "general",
151
+ word: 'desah',
152
+ category: 'sexual',
153
+ region: 'general',
154
154
  severity: 0.6,
155
- aliases: ["ds4h", "dsh"],
156
- description: "Istilah untuk suara yang dibuat selama aktivitas seksual",
157
- context: "Dapat menjadi vulgar tergantung konteks penggunaan",
155
+ aliases: ['ds4h', 'dsh'],
156
+ description: 'Istilah untuk suara yang dibuat selama aktivitas seksual',
157
+ context: 'Dapat menjadi vulgar tergantung konteks penggunaan',
158
158
  },
159
159
  {
160
- word: "seks",
161
- category: "sexual",
162
- region: "general",
160
+ word: 'seks',
161
+ category: 'sexual',
162
+ region: 'general',
163
163
  severity: 0.5,
164
- aliases: ["sex", "ML"],
165
- description: "Istilah untuk aktivitas seksual",
166
- context: "Dapat menjadi vulgar tergantung konteks penggunaan",
164
+ aliases: ['sex', 'ML'],
165
+ description: 'Istilah untuk aktivitas seksual',
166
+ context: 'Dapat menjadi vulgar tergantung konteks penggunaan',
167
167
  },
168
168
  {
169
- word: "kondom",
170
- category: "sexual",
171
- region: "general",
169
+ word: 'kondom',
170
+ category: 'sexual',
171
+ region: 'general',
172
172
  severity: 0.5,
173
- aliases: ["kndm", "kondom", "cd"],
174
- description: "Alat kontrasepsi",
175
- context: "Dapat menjadi vulgar tergantung konteks penggunaan",
173
+ aliases: ['kndm', 'kondom', 'cd'],
174
+ description: 'Alat kontrasepsi',
175
+ context: 'Dapat menjadi vulgar tergantung konteks penggunaan',
176
176
  },
177
177
  {
178
- word: "ngewe",
179
- category: "sexual",
180
- region: "general",
178
+ word: 'ngewe',
179
+ category: 'sexual',
180
+ region: 'general',
181
181
  severity: 0.9,
182
- aliases: ["ngew", "we"],
183
- description: "Istilah kasar untuk aktivitas seksual",
184
- context: "Kata vulgar yang merujuk pada aktivitas seksual",
182
+ aliases: ['ngew', 'we'],
183
+ description: 'Istilah kasar untuk aktivitas seksual',
184
+ context: 'Kata vulgar yang merujuk pada aktivitas seksual',
185
185
  },
186
186
  {
187
- word: "puki",
188
- category: "sexual",
189
- region: "general",
187
+ word: 'puki',
188
+ category: 'sexual',
189
+ region: 'general',
190
190
  severity: 0.9,
191
- aliases: ["puk", "pukih"],
192
- description: "Kata vulgar yang mengacu pada alat kelamin perempuan",
193
- context: "Kata vulgar yang merujuk pada anatomi seksual",
191
+ aliases: ['puk', 'pukih'],
192
+ description: 'Kata vulgar yang mengacu pada alat kelamin perempuan',
193
+ context: 'Kata vulgar yang merujuk pada anatomi seksual',
194
194
  },
195
195
  {
196
- word: "xxx",
197
- category: "sexual",
198
- region: "general",
196
+ word: 'xxx',
197
+ category: 'sexual',
198
+ region: 'general',
199
199
  severity: 0.6,
200
- aliases: ["xXx", "triplex"],
201
- description: "Simbol yang sering digunakan untuk menandai konten pornografi",
202
- context: "Digunakan untuk menandai konten seksual eksplisit",
200
+ aliases: ['xXx', 'triplex'],
201
+ description: 'Simbol yang sering digunakan untuk menandai konten pornografi',
202
+ context: 'Digunakan untuk menandai konten seksual eksplisit',
203
203
  },
204
204
  {
205
- word: "xnxx",
206
- category: "sexual",
207
- region: "general",
205
+ word: 'xnxx',
206
+ category: 'sexual',
207
+ region: 'general',
208
208
  severity: 0.6,
209
- aliases: ["xnxx", "xnx"],
210
- description: "simbol yang sering digunakan untuk menandai konten pornografi",
211
- context: "Digunakan untuk menandai konten seksual eksplisit",
212
- }
209
+ aliases: ['xnxx', 'xnx'],
210
+ description: 'simbol yang sering digunakan untuk menandai konten pornografi',
211
+ context: 'Digunakan untuk menandai konten seksual eksplisit',
212
+ },
213
213
  ];
214
214
  general.map((item) => item.word);
215
215
 
@@ -363,15 +363,7 @@ const jawa = [
363
363
  category: 'insult',
364
364
  region: 'jawa',
365
365
  severity: 0.7,
366
- aliases: [
367
- 'bajilak',
368
- 'bajhingan',
369
- 'bajingak',
370
- 'bajingseng',
371
- 'bajindul',
372
- 'bajigur',
373
- 'jingan',
374
- ],
366
+ aliases: ['bajilak', 'bajhingan', 'bajingak', 'bajingseng', 'bajindul', 'bajigur', 'jingan'],
375
367
  description: 'Sebutan untuk orang yang dianggap jahat atau tidak bermoral',
376
368
  context: 'Umpatan untuk mengekspresikan kemarahan atau kekesalan',
377
369
  },
@@ -1050,221 +1042,221 @@ sunda.map((item) => item.word);
1050
1042
 
1051
1043
  const betawi = [
1052
1044
  {
1053
- word: "jablay",
1054
- category: "sexual",
1055
- region: "betawi",
1045
+ word: 'jablay',
1046
+ category: 'sexual',
1047
+ region: 'betawi',
1056
1048
  severity: 0.7,
1057
- aliases: ["jabl4y", "jalay"],
1049
+ aliases: ['jabl4y', 'jalay'],
1058
1050
  description: 'Singkatan dari "jarang dibelai", istilah untuk perempuan yang mudah didekati',
1059
- context: "Hinaan yang merendahkan untuk wanita",
1051
+ context: 'Hinaan yang merendahkan untuk wanita',
1060
1052
  },
1061
1053
  {
1062
- word: "udik",
1063
- category: "insult",
1064
- region: "betawi",
1054
+ word: 'udik',
1055
+ category: 'insult',
1056
+ region: 'betawi',
1065
1057
  severity: 0.5,
1066
- aliases: ["kampungan", "ndeso"],
1067
- description: "Kata yang mengacu pada seseorang yang dianggap ketinggalan zaman atau tidak modern",
1068
- context: "Hinaan untuk menyebut orang yang dianggap tidak modern atau kampungan",
1058
+ aliases: ['kampungan', 'ndeso'],
1059
+ description: 'Kata yang mengacu pada seseorang yang dianggap ketinggalan zaman atau tidak modern',
1060
+ context: 'Hinaan untuk menyebut orang yang dianggap tidak modern atau kampungan',
1069
1061
  },
1070
1062
  {
1071
- word: "perek",
1072
- category: "sexual",
1073
- region: "betawi",
1063
+ word: 'perek',
1064
+ category: 'sexual',
1065
+ region: 'betawi',
1074
1066
  severity: 0.7,
1075
- aliases: ["perempuan eksperimen", "prk"],
1076
- description: "Istilah untuk perempuan yang dianggap memiliki moral yang rendah",
1077
- context: "Hinaan yang merendahkan untuk wanita",
1067
+ aliases: ['perempuan eksperimen', 'prk'],
1068
+ description: 'Istilah untuk perempuan yang dianggap memiliki moral yang rendah',
1069
+ context: 'Hinaan yang merendahkan untuk wanita',
1078
1070
  },
1079
1071
  ];
1080
1072
  betawi.map((item) => item.word);
1081
1073
 
1082
- const sexual = [
1083
- ...general.filter((word) => word.category === "sexual"),
1084
- ...jawa.filter((word) => word.category === "sexual"),
1085
- ...sunda.filter((word) => word.category === "sexual"),
1086
- ...betawi.filter((word) => word.category === "sexual"),
1087
- {
1088
- word: "bokep",
1089
- category: "sexual",
1090
- region: "general",
1091
- severity: 0.7,
1092
- aliases: ["bkp", "bokap"],
1093
- description: "Istilah untuk video atau konten pornografi",
1094
- context: "Kata yang mengacu pada materi pornografi",
1074
+ const minang = [
1075
+ {
1076
+ word: 'pantek',
1077
+ category: 'insult',
1078
+ region: 'minang',
1079
+ severity: 1,
1080
+ aliases: ['pantak', 'kalera'],
1081
+ description: 'Secara harfiah berarti "kelamin pria',
1082
+ context: 'Digunakan ketika kesal dan mengumpat ke sesorang',
1095
1083
  },
1096
1084
  {
1097
- word: "coli",
1098
- category: "sexual",
1099
- region: "general",
1100
- severity: 0.8,
1101
- aliases: ["col", "coly"],
1102
- description: "Istilah untuk masturbasi laki-laki",
1103
- context: "Kata vulgar yang merujuk pada aktivitas seksual pribadi",
1085
+ word: 'kondiak',
1086
+ category: 'insult',
1087
+ region: 'minang',
1088
+ severity: 0.5,
1089
+ aliases: ['kondik', 'kandiak'],
1090
+ description: 'Secara harfiah berarti "babi"',
1091
+ context: 'Digunakan ketika bercanda dengan teman sebaya',
1104
1092
  },
1105
1093
  {
1106
- word: "desah",
1107
- category: "sexual",
1108
- region: "general",
1109
- severity: 0.6,
1110
- aliases: ["ds4h", "dsh"],
1111
- description: "Istilah untuk suara yang dibuat selama aktivitas seksual",
1112
- context: "Dapat menjadi vulgar tergantung konteks penggunaan",
1094
+ word: 'binga',
1095
+ category: 'insult',
1096
+ region: 'minang',
1097
+ severity: 0.4,
1098
+ aliases: ['tele', 'binguang'],
1099
+ description: 'Secara harfiah berarti "tolol"',
1100
+ context: 'Digunakan untuk menyebut orang yang dianggap bodoh dalam melakukan sesuatu',
1113
1101
  },
1114
1102
  {
1115
- word: "seks",
1116
- category: "sexual",
1117
- region: "general",
1118
- severity: 0.5,
1119
- aliases: ["sex", "ML"],
1120
- description: "Istilah untuk aktivitas seksual",
1121
- context: "Dapat menjadi vulgar tergantung konteks penggunaan",
1103
+ word: 'incek',
1104
+ category: 'sexual',
1105
+ region: 'minang',
1106
+ severity: 0.8,
1107
+ aliases: ['ncek'],
1108
+ description: 'Secara harfiah berarti "kelamin wanita"',
1109
+ context: 'Digunakan ketika menyerang pribadi sesorang',
1122
1110
  },
1123
1111
  {
1124
- word: "itil",
1125
- category: "sexual",
1126
- region: "general",
1127
- severity: 0.9,
1128
- aliases: ["itl", "itul"],
1129
- description: "Kata vulgar yang mengacu pada bagian dari alat kelamin perempuan",
1130
- context: "Kata vulgar yang merujuk pada anatomi seksual",
1112
+ word: 'kanciang',
1113
+ category: 'sexual',
1114
+ region: 'minang',
1115
+ severity: 0.3,
1116
+ aliases: ['kanciang'],
1117
+ description: 'Secara harfiah berarti "pipis"',
1118
+ context: 'Digunakan ketika orang tersebut melakukan kesalahan',
1131
1119
  },
1120
+ ];
1121
+ minang.map((item) => item.word);
1122
+
1123
+ const madura = [
1132
1124
  {
1133
- word: "kondom",
1134
- category: "sexual",
1135
- region: "general",
1136
- severity: 0.5,
1137
- aliases: ["kndm", "kondom", "cd"],
1138
- description: "Alat kontrasepsi",
1139
- context: "Dapat menjadi vulgar tergantung konteks penggunaan",
1125
+ word: 'Pate',
1126
+ category: 'insult',
1127
+ region: 'madura',
1128
+ severity: 0.7,
1129
+ aliases: ['Pate', 'Pate jih', 'pate ben'],
1130
+ description: 'Secara harfiah berarti "anjing"',
1131
+ context: 'Digunakan untuk menyebut orang yang dianggap hina atau tidak berguna',
1140
1132
  },
1141
1133
  {
1142
- word: "ngewe",
1143
- category: "sexual",
1144
- region: "general",
1145
- severity: 0.9,
1146
- aliases: ["ngew", "we"],
1147
- description: "Istilah kasar untuk aktivitas seksual",
1148
- context: "Kata vulgar yang merujuk pada aktivitas seksual",
1134
+ word: 'Matanah',
1135
+ category: 'insult',
1136
+ region: 'madura',
1137
+ severity: 0.4,
1138
+ aliases: ['Matanah', 'Matanah jereyah'],
1139
+ description: 'Kata kasar yang merujuk pada "mata" (bentuk kasar dari mata, sementara bentuk halusnya adalah "ma\'repat")',
1140
+ context: 'Digunakan sebagai umpatan atau dalam ungkapan seperti "ngabes matanah rah!" (Lihat-lihat matanya, dong!) untuk menegur seseorang yang tersandung',
1149
1141
  },
1150
1142
  {
1151
- word: "puki",
1152
- category: "sexual",
1153
- region: "general",
1154
- severity: 0.9,
1155
- aliases: ["puk", "pukih"],
1156
- description: "Kata vulgar yang mengacu pada alat kelamin perempuan",
1157
- context: "Kata vulgar yang merujuk pada anatomi seksual",
1143
+ word: 'Taeh',
1144
+ category: 'insult',
1145
+ region: 'madura',
1146
+ severity: 0.8,
1147
+ aliases: ['Taeh'],
1148
+ description: 'Secara harfiah berarti "tinja" atau "kotoran"',
1149
+ context: 'Digunakan untuk mengungkapkan kekesalan yang ditujukan terhadap seseorang, mengumpamakan mereka dengan hal yang menjijikkan',
1158
1150
  },
1159
1151
  {
1160
- word: "xxx",
1161
- category: "sexual",
1162
- region: "general",
1152
+ word: 'Korang ajher',
1153
+ category: 'insult',
1154
+ region: 'madura',
1163
1155
  severity: 0.6,
1164
- aliases: ["xXx", "triplex"],
1165
- description: "Simbol yang sering digunakan untuk menandai konten pornografi",
1166
- context: "Digunakan untuk menandai konten seksual eksplisit",
1156
+ aliases: ['Korang ajher'],
1157
+ description: 'Berarti "kurang ajar" dalam bahasa Indonesia',
1158
+ context: 'Digunakan saat kesal terhadap seseorang atau menghadapi tingkah laku orang lain yang dirasa kurang sopan',
1159
+ },
1160
+ {
1161
+ word: 'Gendheng',
1162
+ category: 'insult',
1163
+ region: 'madura',
1164
+ severity: 0.5,
1165
+ aliases: ['Gendheng', 'Bhungghen'],
1166
+ description: 'Berarti "bodoh" atau "goblok" dalam bahasa Indonesia',
1167
+ context: 'Digunakan untuk menghina kecerdasan seseorang yang dianggap tidak pintar',
1167
1168
  },
1168
1169
  ];
1169
- sexual.map((item) => item.word);
1170
+ madura.map((item) => item.word);
1170
1171
 
1171
- const insult = [
1172
- ...general.filter((word) => word.category === "insult"),
1173
- ...jawa.filter((word) => word.category === "insult"),
1174
- ...sunda.filter((word) => word.category === "insult"),
1175
- ...betawi.filter((word) => word.category === "insult"),
1176
- {
1177
- word: "idiot",
1178
- category: "insult",
1179
- region: "general",
1180
- severity: 0.6,
1181
- aliases: ["idi0t", "idot"],
1182
- description: "Kata yang mengacu pada kebodohan seseorang",
1183
- context: "Hinaan untuk menyebut orang yang dianggap sangat tidak pintar",
1184
- },
1172
+ const aceh = [
1185
1173
  {
1186
- word: "dungu",
1187
- category: "insult",
1188
- region: "general",
1189
- severity: 0.5,
1190
- aliases: ["dngu", "dongu"],
1191
- description: "Kata yang mengacu pada kebodohan seseorang",
1192
- context: "Hinaan untuk menyebut orang yang dianggap tidak pintar",
1174
+ word: 'pukoe ma',
1175
+ category: 'sexual',
1176
+ region: 'aceh',
1177
+ severity: 0.9,
1178
+ aliases: ['pukoima', 'pukima'],
1179
+ description: 'Secara harfiah berarti kemaluan ibu',
1180
+ context: 'Umpatan sangat kasar yang menyerang ibu seseorang',
1193
1181
  },
1194
1182
  {
1195
- word: "sinting",
1196
- category: "insult",
1197
- region: "general",
1183
+ word: 'bui',
1184
+ category: 'insult',
1185
+ region: 'aceh',
1198
1186
  severity: 0.6,
1199
- aliases: ["sintng", "senteng"],
1200
- description: "Kata yang mengacu pada kegilaan atau ketidakwarasan seseorang",
1201
- context: "Hinaan untuk menyebut orang yang dianggap gila atau tidak waras",
1187
+ aliases: [],
1188
+ description: 'Secara harfiah berarti babi',
1189
+ context: 'Umpatan untuk menyebut orang yang dianggap kotor, rakus, atau tidak berakhlak',
1202
1190
  },
1203
1191
  {
1204
- word: "sarap",
1205
- category: "insult",
1206
- region: "general",
1192
+ word: 'asèe',
1193
+ category: 'insult',
1194
+ region: 'aceh',
1207
1195
  severity: 0.6,
1208
- aliases: ["saraf", "srap"],
1209
- description: "Kata yang mengacu pada kegilaan atau ketidakwarasan seseorang",
1210
- context: "Hinaan untuk menyebut orang yang dianggap gila atau tidak waras",
1196
+ aliases: ['asee'],
1197
+ description: 'Secara harfiah berarti anjing',
1198
+ context: 'Umpatan untuk menyebut orang yang dianggap hina atau tidak berguna',
1211
1199
  },
1212
1200
  {
1213
- word: "geblek",
1214
- category: "insult",
1215
- region: "general",
1216
- severity: 0.5,
1217
- aliases: ["gblk", "geblk"],
1218
- description: "Kata yang mengacu pada kebodohan seseorang",
1219
- context: "Hinaan untuk menyebut orang yang dianggap tidak pintar",
1201
+ word: 'haramjadah',
1202
+ category: 'insult',
1203
+ region: 'aceh',
1204
+ severity: 0.8,
1205
+ aliases: [],
1206
+ description: 'Berarti kurang ajar atau anak haram (lebih halus dari aneuk bajeung)',
1207
+ context: 'Umpatan kasar untuk menyebut anak yang tidak sopan atau tidak beradab',
1220
1208
  },
1221
1209
  {
1222
- word: "kampungan",
1223
- category: "insult",
1224
- region: "general",
1225
- severity: 0.5,
1226
- aliases: ["kmpngn", "kamphungan"],
1227
- description: "Kata yang mengacu pada ketidaksopanan atau kenaifan seseorang",
1228
- context: "Hinaan untuk menyebut orang yang dianggap tidak modern atau primitif",
1210
+ word: "pa'ak",
1211
+ category: 'insult',
1212
+ region: 'aceh',
1213
+ severity: 0.6,
1214
+ aliases: [],
1215
+ description: 'Berarti bodoh',
1216
+ context: 'Umpatan untuk menyebut seseorang yang tidak pintar',
1229
1217
  },
1230
1218
  {
1231
- word: "udik",
1232
- category: "insult",
1233
- region: "general",
1234
- severity: 0.5,
1235
- aliases: ["udhik", "udek"],
1236
- description: "Kata yang mengacu pada ketidaksopanan atau kenaifan seseorang",
1237
- context: "Hinaan untuk menyebut orang yang dianggap tidak modern atau primitif",
1219
+ word: 'sangak',
1220
+ category: 'insult',
1221
+ region: 'aceh',
1222
+ severity: 0.6,
1223
+ aliases: [],
1224
+ description: "Berarti bodoh (lebih kasar dari pa'ak)",
1225
+ context: 'Umpatan kasar untuk menyebut seseorang yang sangat bodoh',
1238
1226
  },
1227
+ ];
1228
+ aceh.map((item) => item.word);
1229
+
1230
+ const bali = [
1239
1231
  {
1240
- word: "dongo",
1241
- category: "insult",
1242
- region: "general",
1243
- severity: 0.5,
1244
- aliases: ["donggo", "dungu"],
1245
- description: "Kata yang mengacu pada kebodohan seseorang",
1246
- context: "Hinaan untuk menyebut orang yang dianggap tidak pintar",
1232
+ word: 'cicing',
1233
+ category: 'insult',
1234
+ region: 'bali',
1235
+ severity: 0.7,
1236
+ aliases: [],
1237
+ description: 'Secara harfiah berarti anjing',
1238
+ context: 'Umpatan umum di Bali untuk menyebut orang yang dianggap hina atau tidak berguna',
1247
1239
  },
1248
1240
  {
1249
- word: "tolol",
1250
- category: "insult",
1251
- region: "general",
1252
- severity: 0.6,
1253
- aliases: ["tol0l", "tollo", "tlol"],
1254
- description: "Kata yang mengacu pada kebodohan seseorang",
1255
- context: "Hinaan untuk menyebut orang yang dianggap tidak pintar",
1241
+ word: 'bengkung',
1242
+ category: 'insult',
1243
+ region: 'bali',
1244
+ severity: 0.5,
1245
+ aliases: [],
1246
+ description: 'Berarti bengkok atau tidak lurus (juga bisa berarti tidak jujur)',
1247
+ context: 'Umpatan ringan untuk menyebut orang yang tidak jujur atau berkelakuan buruk',
1256
1248
  },
1257
1249
  {
1258
- word: "brengsek",
1259
- category: "insult",
1260
- region: "general",
1261
- severity: 0.7,
1262
- aliases: ["brengskek", "brengsik", "brengzek"],
1263
- description: "Kata yang mengacu pada kelakuan buruk atau tidak bermoral",
1264
- context: "Hinaan untuk menyebut orang yang dianggap memiliki kelakuan buruk",
1250
+ word: 'belog',
1251
+ category: 'insult',
1252
+ region: 'bali',
1253
+ severity: 0.6,
1254
+ aliases: [],
1255
+ description: 'Berarti bodoh',
1256
+ context: 'Umpatan umum untuk menyebut seseorang yang tidak pintar',
1265
1257
  },
1266
1258
  ];
1267
- insult.map((item) => item.word);
1259
+ bali.map((item) => item.word);
1268
1260
 
1269
1261
  const batak = [
1270
1262
  {
@@ -1405,17 +1397,610 @@ const batak = [
1405
1397
  ];
1406
1398
  batak.map((item) => item.word);
1407
1399
 
1400
+ const sexual = [
1401
+ ...general.filter((word) => word.category === 'sexual'),
1402
+ ...jawa.filter((word) => word.category === 'sexual'),
1403
+ ...sunda.filter((word) => word.category === 'sexual'),
1404
+ ...betawi.filter((word) => word.category === 'sexual'),
1405
+ ...minang.filter((word) => word.category === 'sexual'),
1406
+ ...madura.filter((word) => word.category === 'sexual'),
1407
+ ...sunda.filter((word) => word.category === 'sexual'),
1408
+ ...aceh.filter((word) => word.category === 'sexual'),
1409
+ ...bali.filter((word) => word.category === 'sexual'),
1410
+ ...batak.filter((word) => word.category === 'sexual'),
1411
+ {
1412
+ word: 'bokep',
1413
+ category: 'sexual',
1414
+ region: 'general',
1415
+ severity: 0.7,
1416
+ aliases: ['bkp', 'bokap'],
1417
+ description: 'Istilah untuk video atau konten pornografi',
1418
+ context: 'Kata yang mengacu pada materi pornografi',
1419
+ },
1420
+ {
1421
+ word: 'coli',
1422
+ category: 'sexual',
1423
+ region: 'general',
1424
+ severity: 0.8,
1425
+ aliases: ['col', 'coly'],
1426
+ description: 'Istilah untuk masturbasi laki-laki',
1427
+ context: 'Kata vulgar yang merujuk pada aktivitas seksual pribadi',
1428
+ },
1429
+ {
1430
+ word: 'desah',
1431
+ category: 'sexual',
1432
+ region: 'general',
1433
+ severity: 0.6,
1434
+ aliases: ['ds4h', 'dsh'],
1435
+ description: 'Istilah untuk suara yang dibuat selama aktivitas seksual',
1436
+ context: 'Dapat menjadi vulgar tergantung konteks penggunaan',
1437
+ },
1438
+ {
1439
+ word: 'seks',
1440
+ category: 'sexual',
1441
+ region: 'general',
1442
+ severity: 0.5,
1443
+ aliases: ['sex', 'ML'],
1444
+ description: 'Istilah untuk aktivitas seksual',
1445
+ context: 'Dapat menjadi vulgar tergantung konteks penggunaan',
1446
+ },
1447
+ {
1448
+ word: 'itil',
1449
+ category: 'sexual',
1450
+ region: 'general',
1451
+ severity: 0.9,
1452
+ aliases: ['itl', 'itul'],
1453
+ description: 'Kata vulgar yang mengacu pada bagian dari alat kelamin perempuan',
1454
+ context: 'Kata vulgar yang merujuk pada anatomi seksual',
1455
+ },
1456
+ {
1457
+ word: 'kondom',
1458
+ category: 'sexual',
1459
+ region: 'general',
1460
+ severity: 0.5,
1461
+ aliases: ['kndm', 'kondom', 'cd'],
1462
+ description: 'Alat kontrasepsi',
1463
+ context: 'Dapat menjadi vulgar tergantung konteks penggunaan',
1464
+ },
1465
+ {
1466
+ word: 'ngewe',
1467
+ category: 'sexual',
1468
+ region: 'general',
1469
+ severity: 0.9,
1470
+ aliases: ['ngew', 'we'],
1471
+ description: 'Istilah kasar untuk aktivitas seksual',
1472
+ context: 'Kata vulgar yang merujuk pada aktivitas seksual',
1473
+ },
1474
+ {
1475
+ word: 'puki',
1476
+ category: 'sexual',
1477
+ region: 'general',
1478
+ severity: 0.9,
1479
+ aliases: ['puk', 'pukih'],
1480
+ description: 'Kata vulgar yang mengacu pada alat kelamin perempuan',
1481
+ context: 'Kata vulgar yang merujuk pada anatomi seksual',
1482
+ },
1483
+ {
1484
+ word: 'xxx',
1485
+ category: 'sexual',
1486
+ region: 'general',
1487
+ severity: 0.6,
1488
+ aliases: ['xXx', 'triplex'],
1489
+ description: 'Simbol yang sering digunakan untuk menandai konten pornografi',
1490
+ context: 'Digunakan untuk menandai konten seksual eksplisit',
1491
+ },
1492
+ ];
1493
+ sexual.map((item) => item.word);
1494
+
1495
+ const insult = [
1496
+ ...general.filter((word) => word.category === 'insult'),
1497
+ ...jawa.filter((word) => word.category === 'insult'),
1498
+ ...sunda.filter((word) => word.category === 'insult'),
1499
+ ...betawi.filter((word) => word.category === 'insult'),
1500
+ ...minang.filter((word) => word.category === 'insult'),
1501
+ ...madura.filter((word) => word.category === 'insult'),
1502
+ ...sunda.filter((word) => word.category === 'insult'),
1503
+ ...aceh.filter((word) => word.category === 'insult'),
1504
+ ...bali.filter((word) => word.category === 'insult'),
1505
+ ...batak.filter((word) => word.category === 'insult'),
1506
+ {
1507
+ word: 'idiot',
1508
+ category: 'insult',
1509
+ region: 'general',
1510
+ severity: 0.6,
1511
+ aliases: ['idi0t', 'idot'],
1512
+ description: 'Kata yang mengacu pada kebodohan seseorang',
1513
+ context: 'Hinaan untuk menyebut orang yang dianggap sangat tidak pintar',
1514
+ },
1515
+ {
1516
+ word: 'dungu',
1517
+ category: 'insult',
1518
+ region: 'general',
1519
+ severity: 0.5,
1520
+ aliases: ['dngu', 'dongu'],
1521
+ description: 'Kata yang mengacu pada kebodohan seseorang',
1522
+ context: 'Hinaan untuk menyebut orang yang dianggap tidak pintar',
1523
+ },
1524
+ {
1525
+ word: 'sinting',
1526
+ category: 'insult',
1527
+ region: 'general',
1528
+ severity: 0.6,
1529
+ aliases: ['sintng', 'senteng'],
1530
+ description: 'Kata yang mengacu pada kegilaan atau ketidakwarasan seseorang',
1531
+ context: 'Hinaan untuk menyebut orang yang dianggap gila atau tidak waras',
1532
+ },
1533
+ {
1534
+ word: 'sarap',
1535
+ category: 'insult',
1536
+ region: 'general',
1537
+ severity: 0.6,
1538
+ aliases: ['saraf', 'srap'],
1539
+ description: 'Kata yang mengacu pada kegilaan atau ketidakwarasan seseorang',
1540
+ context: 'Hinaan untuk menyebut orang yang dianggap gila atau tidak waras',
1541
+ },
1542
+ {
1543
+ word: 'geblek',
1544
+ category: 'insult',
1545
+ region: 'general',
1546
+ severity: 0.5,
1547
+ aliases: ['gblk', 'geblk'],
1548
+ description: 'Kata yang mengacu pada kebodohan seseorang',
1549
+ context: 'Hinaan untuk menyebut orang yang dianggap tidak pintar',
1550
+ },
1551
+ {
1552
+ word: 'kampungan',
1553
+ category: 'insult',
1554
+ region: 'general',
1555
+ severity: 0.5,
1556
+ aliases: ['kmpngn', 'kamphungan'],
1557
+ description: 'Kata yang mengacu pada ketidaksopanan atau kenaifan seseorang',
1558
+ context: 'Hinaan untuk menyebut orang yang dianggap tidak modern atau primitif',
1559
+ },
1560
+ {
1561
+ word: 'udik',
1562
+ category: 'insult',
1563
+ region: 'general',
1564
+ severity: 0.5,
1565
+ aliases: ['udhik', 'udek'],
1566
+ description: 'Kata yang mengacu pada ketidaksopanan atau kenaifan seseorang',
1567
+ context: 'Hinaan untuk menyebut orang yang dianggap tidak modern atau primitif',
1568
+ },
1569
+ {
1570
+ word: 'dongo',
1571
+ category: 'insult',
1572
+ region: 'general',
1573
+ severity: 0.5,
1574
+ aliases: ['donggo', 'dungu'],
1575
+ description: 'Kata yang mengacu pada kebodohan seseorang',
1576
+ context: 'Hinaan untuk menyebut orang yang dianggap tidak pintar',
1577
+ },
1578
+ {
1579
+ word: 'tolol',
1580
+ category: 'insult',
1581
+ region: 'general',
1582
+ severity: 0.6,
1583
+ aliases: ['tol0l', 'tollo', 'tlol'],
1584
+ description: 'Kata yang mengacu pada kebodohan seseorang',
1585
+ context: 'Hinaan untuk menyebut orang yang dianggap tidak pintar',
1586
+ },
1587
+ {
1588
+ word: 'brengsek',
1589
+ category: 'insult',
1590
+ region: 'general',
1591
+ severity: 0.7,
1592
+ aliases: ['brengskek', 'brengsik', 'brengzek'],
1593
+ description: 'Kata yang mengacu pada kelakuan buruk atau tidak bermoral',
1594
+ context: 'Hinaan untuk menyebut orang yang dianggap memiliki kelakuan buruk',
1595
+ },
1596
+ ];
1597
+ insult.map((item) => item.word);
1598
+
1599
+ const profanity = [
1600
+ ...general.filter((word) => word.category === 'profanity'),
1601
+ ...jawa.filter((word) => word.category === 'profanity'),
1602
+ ...sunda.filter((word) => word.category === 'profanity'),
1603
+ ...betawi.filter((word) => word.category === 'profanity'),
1604
+ ...minang.filter((word) => word.category === 'profanity'),
1605
+ ...madura.filter((word) => word.category === 'profanity'),
1606
+ ...sunda.filter((word) => word.category === 'profanity'),
1607
+ ...aceh.filter((word) => word.category === 'profanity'),
1608
+ ...bali.filter((word) => word.category === 'profanity'),
1609
+ ...batak.filter((word) => word.category === 'profanity'),
1610
+ {
1611
+ word: 'anjing',
1612
+ category: 'profanity',
1613
+ region: 'general',
1614
+ severity: 0.9,
1615
+ aliases: ['anjir', 'anying', 'njing', 'njir'],
1616
+ description: 'Kata umpatan yang mengacu pada hewan anjing',
1617
+ context: 'Digunakan sebagai ekspresi kemarahan atau frustasi',
1618
+ },
1619
+ {
1620
+ word: 'babi',
1621
+ category: 'profanity',
1622
+ region: 'general',
1623
+ severity: 0.8,
1624
+ aliases: ['babik', 'khinzir'],
1625
+ description: 'Kata umpatan yang mengacu pada hewan babi',
1626
+ context: 'Digunakan untuk mengekspresikan kemarahan atau menghina seseorang',
1627
+ },
1628
+ {
1629
+ word: 'bangsat',
1630
+ category: 'profanity',
1631
+ region: 'general',
1632
+ severity: 0.8,
1633
+ aliases: ['bgst', 'bangst'],
1634
+ description: 'Kata umpatan kasar yang berarti kutu atau parasit',
1635
+ context: 'Digunakan untuk menunjukkan kemarahan atau menghina seseorang',
1636
+ },
1637
+ {
1638
+ word: 'kampret',
1639
+ category: 'profanity',
1640
+ region: 'general',
1641
+ severity: 0.7,
1642
+ aliases: ['kampret lu', 'kampretot'],
1643
+ description: 'Kata umpatan yang mengacu pada jenis kelelawar kecil',
1644
+ context: 'Digunakan untuk mengungkapkan kekesalan atau menghina seseorang',
1645
+ },
1646
+ {
1647
+ word: 'sialan',
1648
+ category: 'profanity',
1649
+ region: 'general',
1650
+ severity: 0.6,
1651
+ aliases: ['sial', 'siaal'],
1652
+ description: 'Kata umpatan yang menunjukkan nasib buruk',
1653
+ context: 'Digunakan untuk mengekspresikan kekesalan atau kemarahan',
1654
+ },
1655
+ {
1656
+ word: 'monyet',
1657
+ category: 'profanity',
1658
+ region: 'general',
1659
+ severity: 0.7,
1660
+ aliases: ['monyong', 'munyuk'],
1661
+ description: 'Kata umpatan yang mengacu pada hewan primata',
1662
+ context: 'Digunakan untuk menghina atau mengekspresikan kemarahan',
1663
+ },
1664
+ {
1665
+ word: 'bajingan',
1666
+ category: 'profanity',
1667
+ region: 'general',
1668
+ severity: 0.8,
1669
+ aliases: ['bajinga', 'bjngn'],
1670
+ description: 'Kata umpatan yang berarti penjahat atau orang jahat',
1671
+ context: 'Digunakan untuk mengumpat seseorang yang dianggap buruk perilakunya',
1672
+ },
1673
+ {
1674
+ word: 'jancok',
1675
+ category: 'profanity',
1676
+ region: 'jawa',
1677
+ severity: 0.9,
1678
+ aliases: ['jancuk', 'jancik', 'dancok'],
1679
+ description: 'Kata umpatan kasar dalam bahasa Jawa',
1680
+ context: 'Umpatan sangat kasar dalam budaya Jawa, menunjukkan kemarahan yang tinggi',
1681
+ },
1682
+ {
1683
+ word: 'cuk',
1684
+ category: 'profanity',
1685
+ region: 'jawa',
1686
+ severity: 0.8,
1687
+ aliases: ['cok', 'cug'],
1688
+ description: 'Bentuk singkat dari jancok',
1689
+ context: 'Versi pendek dari umpatan jancok, digunakan dalam percakapan sehari-hari',
1690
+ },
1691
+ {
1692
+ word: 'asu',
1693
+ category: 'profanity',
1694
+ region: 'jawa',
1695
+ severity: 0.8,
1696
+ aliases: ['asyu', 'su'],
1697
+ description: 'Kata Jawa untuk anjing, digunakan sebagai umpatan',
1698
+ context: 'Ekspresi umpatan yang umum di masyarakat Jawa',
1699
+ },
1700
+ {
1701
+ word: 'sia',
1702
+ category: 'profanity',
1703
+ region: 'sunda',
1704
+ severity: 0.6,
1705
+ aliases: ['siah', 'siaa'],
1706
+ description: 'Kata ganti orang kedua dalam bahasa Sunda yang kasar',
1707
+ context: 'Menunjukkan ketidakhormatan pada lawan bicara dalam konteks Sunda',
1708
+ },
1709
+ {
1710
+ word: 'lu',
1711
+ category: 'profanity',
1712
+ region: 'betawi',
1713
+ severity: 0.4,
1714
+ aliases: ['elu', 'lo'],
1715
+ description: 'Kata ganti orang kedua dalam dialek Betawi',
1716
+ context: 'Dapat dianggap kasar dalam konteks formal atau saat berbicara dengan orang yang lebih tua',
1717
+ },
1718
+ {
1719
+ word: 'goblok',
1720
+ category: 'profanity',
1721
+ region: 'general',
1722
+ severity: 0.7,
1723
+ aliases: ['goblog', 'goblokk', 'bego', 'bodoh'],
1724
+ description: 'Kata umpatan yang menunjukkan kebodohan',
1725
+ context: 'Digunakan untuk menghina kecerdasan seseorang',
1726
+ },
1727
+ ];
1728
+ profanity.map((item) => item.word);
1729
+
1730
+ const slur = [
1731
+ ...general.filter((word) => word.category === 'slur'),
1732
+ ...jawa.filter((word) => word.category === 'slur'),
1733
+ ...sunda.filter((word) => word.category === 'slur'),
1734
+ ...betawi.filter((word) => word.category === 'slur'),
1735
+ ...minang.filter((word) => word.category === 'slur'),
1736
+ ...madura.filter((word) => word.category === 'slur'),
1737
+ ...sunda.filter((word) => word.category === 'slur'),
1738
+ ...aceh.filter((word) => word.category === 'slur'),
1739
+ ...bali.filter((word) => word.category === 'slur'),
1740
+ ...batak.filter((word) => word.category === 'slur'),
1741
+ {
1742
+ word: 'cina',
1743
+ category: 'slur',
1744
+ region: 'general',
1745
+ severity: 0.7,
1746
+ aliases: ['cino', 'china'],
1747
+ description: 'Sebutan yang dianggap merendahkan untuk orang keturunan Tionghoa',
1748
+ context: 'Dianggap tidak sopan dan sebaiknya diganti dengan "Tionghoa"',
1749
+ },
1750
+ {
1751
+ word: 'banci',
1752
+ category: 'slur',
1753
+ region: 'general',
1754
+ severity: 0.7,
1755
+ aliases: ['bencong', 'waria', 'bences'],
1756
+ description: 'Istilah merendahkan untuk transgender atau pria yang dianggap feminin',
1757
+ context: 'Digunakan sebagai hinaan terhadap identitas gender atau ekspresi gender seseorang',
1758
+ },
1759
+ {
1760
+ word: 'autis',
1761
+ category: 'slur',
1762
+ region: 'general',
1763
+ severity: 0.6,
1764
+ aliases: ['autis lu', 'autisan'],
1765
+ description: 'Penyalahgunaan kondisi medis sebagai hinaan',
1766
+ context: 'Menggunakan kondisi spektrum autisme sebagai hinaan untuk seseorang yang dianggap aneh',
1767
+ },
1768
+ {
1769
+ word: 'londo',
1770
+ category: 'slur',
1771
+ region: 'jawa',
1772
+ severity: 0.5,
1773
+ aliases: ['landa', 'landi'],
1774
+ description: 'Sebutan untuk orang Belanda atau orang berkulit putih',
1775
+ context: 'Dapat bersifat merendahkan tergantung konteks dan nada bicara',
1776
+ },
1777
+ {
1778
+ word: 'keling',
1779
+ category: 'slur',
1780
+ region: 'general',
1781
+ severity: 0.8,
1782
+ aliases: ['kaling', 'hitam legam'],
1783
+ description: 'Istilah merendahkan untuk orang India atau berkulit gelap',
1784
+ context: 'Dianggap sangat tidak sopan dan bernada rasis',
1785
+ },
1786
+ {
1787
+ word: 'cacat',
1788
+ category: 'slur',
1789
+ region: 'general',
1790
+ severity: 0.7,
1791
+ aliases: ['cacad', 'difabel'],
1792
+ description: 'Istilah merendahkan untuk penyandang disabilitas',
1793
+ context: 'Digunakan sebagai hinaan untuk menunjukkan ketidaksempurnaan',
1794
+ },
1795
+ {
1796
+ word: 'gembel',
1797
+ category: 'slur',
1798
+ region: 'general',
1799
+ severity: 0.6,
1800
+ aliases: ['gembul', 'gelandangan'],
1801
+ description: 'Istilah merendahkan untuk orang tidak mampu atau tunawisma',
1802
+ context: 'Mengandung stigma terhadap kemiskinan dan kelas sosial',
1803
+ },
1804
+ {
1805
+ word: 'kampungan',
1806
+ category: 'slur',
1807
+ region: 'general',
1808
+ severity: 0.5,
1809
+ aliases: ['ndeso', 'katrok', 'udik'],
1810
+ description: 'Istilah merendahkan untuk orang dari daerah pedesaan',
1811
+ context: 'Menyiratkan seseorang tidak beradab, tidak berpendidikan, atau ketinggalan zaman',
1812
+ },
1813
+ {
1814
+ word: 'tolol',
1815
+ category: 'slur',
1816
+ region: 'general',
1817
+ severity: 0.6,
1818
+ aliases: ['tololnya', 'tolo'],
1819
+ description: 'Hinaan terhadap kecerdasan seseorang',
1820
+ context: 'Digunakan untuk menghina kapasitas mental seseorang',
1821
+ },
1822
+ ];
1823
+ slur.map((item) => item.word);
1824
+
1825
+ const drugs = [
1826
+ ...general.filter((word) => word.category === 'drugs'),
1827
+ ...jawa.filter((word) => word.category === 'drugs'),
1828
+ ...sunda.filter((word) => word.category === 'drugs'),
1829
+ ...betawi.filter((word) => word.category === 'drugs'),
1830
+ ...minang.filter((word) => word.category === 'drugs'),
1831
+ ...madura.filter((word) => word.category === 'drugs'),
1832
+ ...sunda.filter((word) => word.category === 'drugs'),
1833
+ ...aceh.filter((word) => word.category === 'drugs'),
1834
+ ...bali.filter((word) => word.category === 'drugs'),
1835
+ ...batak.filter((word) => word.category === 'drugs'),
1836
+ {
1837
+ word: 'ganja',
1838
+ category: 'drugs',
1839
+ region: 'general',
1840
+ severity: 0.6,
1841
+ aliases: ['cimeng', 'kanabis', 'marijuana'],
1842
+ description: 'Tanaman yang mengandung zat psikoaktif',
1843
+ context: 'Digunakan untuk merujuk pada narkotika jenis cannabis',
1844
+ },
1845
+ {
1846
+ word: 'sabu',
1847
+ category: 'drugs',
1848
+ region: 'general',
1849
+ severity: 0.8,
1850
+ aliases: ['crystal', 'meth', 'ss'],
1851
+ description: 'Narkotika jenis metamfetamin',
1852
+ context: 'Istilah untuk metamfetamin yang merupakan narkotika berbahaya',
1853
+ },
1854
+ {
1855
+ word: 'inex',
1856
+ category: 'drugs',
1857
+ region: 'general',
1858
+ severity: 0.7,
1859
+ aliases: ['ekstasi', 'pil'],
1860
+ description: 'Obat terlarang yang mengandung MDMA',
1861
+ context: 'Nama slang untuk obat terlarang ecstasy',
1862
+ },
1863
+ {
1864
+ word: 'sakaw',
1865
+ category: 'drugs',
1866
+ region: 'general',
1867
+ severity: 0.5,
1868
+ aliases: ['ketagihan', 'menarik'],
1869
+ description: 'Gejala putus obat pada pecandu',
1870
+ context: 'Menggambarkan kondisi pecandu yang sedang mengalami gejala putus obat',
1871
+ },
1872
+ {
1873
+ word: 'ngepil',
1874
+ category: 'drugs',
1875
+ region: 'jawa',
1876
+ severity: 0.3,
1877
+ aliases: ['minum pil', 'telan pil'],
1878
+ description: 'Mengkonsumsi obat-obatan terlarang dalam bentuk pil',
1879
+ context: 'Istilah dalam bahasa gaul untuk mengkonsumsi obat terlarang jenis tablet',
1880
+ },
1881
+ {
1882
+ word: 'nyimeng',
1883
+ category: 'drugs',
1884
+ region: 'sunda',
1885
+ severity: 0.6,
1886
+ aliases: ['nyimang', 'isap ganja'],
1887
+ description: 'Mengisap ganja atau marijuana',
1888
+ context: 'Istilah sunda untuk aktivitas mengkonsumsi ganja',
1889
+ },
1890
+ ];
1891
+ drugs.map((item) => item.word);
1892
+
1893
+ const disgusting = [
1894
+ ...general.filter((word) => word.category === 'disgusting'),
1895
+ ...jawa.filter((word) => word.category === 'disgusting'),
1896
+ ...sunda.filter((word) => word.category === 'disgusting'),
1897
+ ...betawi.filter((word) => word.category === 'disgusting'),
1898
+ ...minang.filter((word) => word.category === 'disgusting'),
1899
+ ...madura.filter((word) => word.category === 'disgusting'),
1900
+ ...sunda.filter((word) => word.category === 'disgusting'),
1901
+ ...aceh.filter((word) => word.category === 'disgusting'),
1902
+ ...bali.filter((word) => word.category === 'disgusting'),
1903
+ ...batak.filter((word) => word.category === 'disgusting'),
1904
+ {
1905
+ word: 'muntah',
1906
+ category: 'disgusting',
1907
+ region: 'general',
1908
+ severity: 0.4,
1909
+ aliases: ['muntaber', 'memuntahkan'],
1910
+ description: 'Muntahan atau tindakan muntah',
1911
+ context: 'Digunakan untuk mengekspresikan rasa jijik atau menggambarkan tindakan tersebut',
1912
+ },
1913
+ {
1914
+ word: 'ingus',
1915
+ category: 'disgusting',
1916
+ region: 'general',
1917
+ severity: 0.4,
1918
+ aliases: ['ingusan', 'beringus'],
1919
+ description: 'Lendir hidung',
1920
+ context: 'Digunakan untuk menggambarkan lendir hidung atau sebagai hinaan',
1921
+ },
1922
+ {
1923
+ word: 'tai',
1924
+ category: 'disgusting',
1925
+ region: 'general',
1926
+ severity: 0.8,
1927
+ aliases: ['tahi', 'kotoran'],
1928
+ description: 'Kotoran manusia',
1929
+ context: 'Istilah vulgar untuk kotoran, sering digunakan sebagai hinaan',
1930
+ },
1931
+ {
1932
+ word: 'jembut',
1933
+ category: 'disgusting',
1934
+ region: 'general',
1935
+ severity: 1.0,
1936
+ aliases: ['jembud', 'rambut kemaluan'],
1937
+ description: 'Rambut kemaluan',
1938
+ context: 'Istilah vulgar untuk rambut kemaluan, dianggap sangat tidak pantas',
1939
+ },
1940
+ {
1941
+ word: 'pecret',
1942
+ category: 'disgusting',
1943
+ region: 'sunda',
1944
+ severity: 0.8,
1945
+ aliases: ['mencret', 'diare'],
1946
+ description: 'Diare dalam bahasa Sunda',
1947
+ context: 'Dianggap vulgar ketika disebutkan di depan umum',
1948
+ },
1949
+ {
1950
+ word: 'bacot',
1951
+ category: 'disgusting',
1952
+ region: 'betawi',
1953
+ severity: 0.8,
1954
+ aliases: ['cicing', 'berisik'],
1955
+ description: 'Mulut atau omongan berisik dalam konteks vulgar',
1956
+ context: 'Istilah kasar yang digunakan untuk menyuruh seseorang diam',
1957
+ },
1958
+ {
1959
+ word: 'lendir',
1960
+ category: 'disgusting',
1961
+ region: 'general',
1962
+ severity: 0.3,
1963
+ aliases: ['berlendir', 'cairan lengket'],
1964
+ description: 'Lendir atau cairan lengket',
1965
+ context: 'Dapat digunakan dalam konteks vulgar untuk menggambarkan cairan tubuh',
1966
+ },
1967
+ ];
1968
+ disgusting.map((item) => item.word);
1969
+
1970
+ const blasphemy = [
1971
+ ...general.filter((word) => word.category === 'blasphemy'),
1972
+ ...jawa.filter((word) => word.category === 'blasphemy'),
1973
+ ...sunda.filter((word) => word.category === 'blasphemy'),
1974
+ ...betawi.filter((word) => word.category === 'blasphemy'),
1975
+ ...minang.filter((word) => word.category === 'blasphemy'),
1976
+ ...madura.filter((word) => word.category === 'blasphemy'),
1977
+ ...sunda.filter((word) => word.category === 'blasphemy'),
1978
+ ...aceh.filter((word) => word.category === 'blasphemy'),
1979
+ ...bali.filter((word) => word.category === 'blasphemy'),
1980
+ ...batak.filter((word) => word.category === 'blasphemy'),
1981
+ {
1982
+ word: 'kafir',
1983
+ category: 'blasphemy',
1984
+ region: 'general',
1985
+ severity: 0.6,
1986
+ aliases: ['kapir', 'kafur'],
1987
+ description: 'Istilah untuk orang yang tidak percaya pada Islam',
1988
+ context: 'Dapat bersifat merendahkan ketika digunakan terhadap non-Muslim',
1989
+ },
1990
+ ];
1991
+ blasphemy.map((item) => item.word);
1992
+
1408
1993
  const wordObjects = [
1409
1994
  ...general,
1410
1995
  ...jawa,
1411
1996
  ...sunda,
1412
1997
  ...betawi,
1413
1998
  ...batak,
1414
- // ...minang,
1415
- // ...bali,
1416
- // ...madura,
1999
+ ...minang,
2000
+ ...bali,
2001
+ ...madura,
1417
2002
  // ...bugis,
1418
- // ...aceh,
2003
+ ...aceh,
1419
2004
  // ...ambon,
1420
2005
  // ...papua,
1421
2006
  // ...manado,
@@ -1441,7 +2026,7 @@ wordObjects
1441
2026
  * @param keepFirstAndLast Apakah harus menyimpan huruf pertama dan terakhir
1442
2027
  * @returns Kata yang telah disensor
1443
2028
  */
1444
- function censorWord(word, replaceChar = "*", keepFirstAndLast = false) {
2029
+ function censorWord(word, replaceChar = '*', keepFirstAndLast = false) {
1445
2030
  if (word.length <= 2) {
1446
2031
  return replaceChar.repeat(word.length);
1447
2032
  }
@@ -1459,9 +2044,9 @@ function censorWord(word, replaceChar = "*", keepFirstAndLast = false) {
1459
2044
  function normalizeText(text) {
1460
2045
  return text
1461
2046
  .toLowerCase()
1462
- .normalize("NFD") // Normalisasi Unicode
1463
- .replace(/[\u0300-\u036f]/g, "") // Hapus diacritic marks
1464
- .replace(/[^\w\s]/g, "") // Hapus karakter non-alphanumeric
2047
+ .normalize('NFD') // Normalisasi Unicode
2048
+ .replace(/[\u0300-\u036f]/g, '') // Hapus diacritic marks
2049
+ .replace(/[^\w\s]/g, '') // Hapus karakter non-alphanumeric
1465
2050
  .trim(); // Hapus whitespace di awal dan akhir
1466
2051
  }
1467
2052
  /**
@@ -1478,7 +2063,7 @@ function containsAnyWord(text, wordList, checkSubstring = false) {
1478
2063
  const normalizedWord = normalizeText(word);
1479
2064
  return checkSubstring
1480
2065
  ? normalizedText.includes(normalizedWord)
1481
- : new RegExp(`\\b${escapeRegExp(normalizedWord)}\\b`, "i").test(normalizedText);
2066
+ : new RegExp(`\\b${escapeRegExp(normalizedWord)}\\b`, 'i').test(normalizedText);
1482
2067
  });
1483
2068
  }
1484
2069
  /**
@@ -1495,7 +2080,7 @@ function containsEuphemism(text, wordList) {
1495
2080
  return false;
1496
2081
  const firstChar = word[0];
1497
2082
  const lastChar = word[word.length - 1];
1498
- const pattern = new RegExp(`\\b${escapeRegExp(firstChar)}[*@#\\-_.!?\\s]{${word.length - 2}}${escapeRegExp(lastChar)}\\b`, "i");
2083
+ const pattern = new RegExp(`\\b${escapeRegExp(firstChar)}[*@#\\-_.!?\\s]{${word.length - 2}}${escapeRegExp(lastChar)}\\b`, 'i');
1499
2084
  return pattern.test(text);
1500
2085
  });
1501
2086
  }
@@ -1508,11 +2093,11 @@ function containsEuphemism(text, wordList) {
1508
2093
  * @returns Boolean apakah teks mengandung upaya menghindari filter
1509
2094
  */
1510
2095
  function detectSplitWords(text, wordList) {
1511
- const compressedText = text.replace(/[\s\-_.!?*]/g, "").toLowerCase();
2096
+ const compressedText = text.replace(/[\s\-_.!?*]/g, '').toLowerCase();
1512
2097
  return wordList.some((word) => compressedText.includes(normalizeText(word)));
1513
2098
  }
1514
2099
  function escapeRegExp(string) {
1515
- return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2100
+ return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
1516
2101
  }
1517
2102
  /**
1518
2103
  * Mengganti sebagian kata dengan masking
@@ -1524,9 +2109,9 @@ function escapeRegExp(string) {
1524
2109
  * @param maskChar Karakter masking
1525
2110
  * @returns Teks yang telah dimasking
1526
2111
  */
1527
- function maskText(text, visibleStart = 1, visibleEnd = 1, maskChar = "*") {
2112
+ function maskText(text, visibleStart = 1, visibleEnd = 1, maskChar = '*') {
1528
2113
  if (!text)
1529
- return "";
2114
+ return '';
1530
2115
  if (text.length <= visibleStart + visibleEnd)
1531
2116
  return text;
1532
2117
  const start = text.substring(0, visibleStart);
@@ -1543,25 +2128,25 @@ function maskText(text, visibleStart = 1, visibleEnd = 1, maskChar = "*") {
1543
2128
  */
1544
2129
  function toLeetSpeak(text) {
1545
2130
  const leetMap = {
1546
- a: ["4", "@"],
1547
- b: ["8", "6"],
1548
- c: ["<", "(", "{"],
1549
- e: ["3"],
1550
- g: ["9"],
1551
- i: ["1", "!"],
1552
- l: ["1", "|"],
1553
- o: ["0"],
1554
- s: ["5", "$"],
1555
- t: ["7", "+"],
1556
- z: ["2"],
2131
+ a: ['4', '@'],
2132
+ b: ['8', '6'],
2133
+ c: ['<', '(', '{'],
2134
+ e: ['3'],
2135
+ g: ['9'],
2136
+ i: ['1', '!'],
2137
+ l: ['1', '|'],
2138
+ o: ['0'],
2139
+ s: ['5', '$'],
2140
+ t: ['7', '+'],
2141
+ z: ['2'],
1557
2142
  };
1558
2143
  return text
1559
- .split("")
2144
+ .split('')
1560
2145
  .map((char) => {
1561
2146
  const lowerChar = char.toLowerCase();
1562
2147
  return leetMap[lowerChar] || char;
1563
2148
  })
1564
- .join("");
2149
+ .join('');
1565
2150
  }
1566
2151
  /**
1567
2152
  * memisahkan teks menajdi kelimat
@@ -1571,9 +2156,7 @@ function toLeetSpeak(text) {
1571
2156
  */
1572
2157
  function splitIntoSentences(text) {
1573
2158
  // split berdasarkan titik, seru, taya yagn diikuti spasi atau akhir string
1574
- return text
1575
- .split(/(?<=[.!?])\s+|(?<=[.!?])$/)
1576
- .filter((sentence) => sentence.trim().length > 0);
2159
+ return text.split(/(?<=[.!?])\s+|(?<=[.!?])$/).filter((sentence) => sentence.trim().length > 0);
1577
2160
  }
1578
2161
  /**
1579
2162
  * mengambil kata-kata di sekitar indeks tertentu
@@ -1585,7 +2168,7 @@ function splitIntoSentences(text) {
1585
2168
  */
1586
2169
  function getContextAroundIndex(text, index, windowSize = 5) {
1587
2170
  if (!text || index < 0 || index >= text.length)
1588
- return "";
2171
+ return '';
1589
2172
  const words = text.split(/\s+/);
1590
2173
  let currentPosition = 0;
1591
2174
  let targetWordIndex = -1;
@@ -1599,11 +2182,11 @@ function getContextAroundIndex(text, index, windowSize = 5) {
1599
2182
  currentPosition += wordLength + 1;
1600
2183
  }
1601
2184
  if (targetWordIndex === -1)
1602
- return "";
2185
+ return '';
1603
2186
  // Ambil kata-kata di sekitar
1604
2187
  const startIndex = Math.max(0, targetWordIndex - windowSize);
1605
2188
  const endIndex = Math.min(words.length, targetWordIndex + windowSize + 1);
1606
- return words.slice(startIndex, endIndex).join(" ");
2189
+ return words.slice(startIndex, endIndex).join(' ');
1607
2190
  }
1608
2191
 
1609
2192
  /**
@@ -1634,7 +2217,7 @@ function createWordRegex(word, options = {}) {
1634
2217
  pattern = `\\b${pattern}\\b`;
1635
2218
  }
1636
2219
  // Buat regex dengan flag case-insensitive jika diminta
1637
- return new RegExp(pattern, caseSensitive ? "g" : "gi");
2220
+ return new RegExp(pattern, caseSensitive ? 'g' : 'gi');
1638
2221
  }
1639
2222
  /**
1640
2223
  * Menambahkan variasi leet speak ke pola regex
@@ -1648,29 +2231,29 @@ function createWordRegex(word, options = {}) {
1648
2231
  */
1649
2232
  function addLeetSpeakVariations(pattern) {
1650
2233
  const leetMap = {
1651
- a: ["a", "4", "@"],
1652
- b: ["b", "8", "6"],
1653
- c: ["c", "(", "{", "<"],
1654
- e: ["e", "3"],
1655
- g: ["g", "6", "9"],
1656
- i: ["i", "1", "!", "|"],
1657
- l: ["l", "1", "|"],
1658
- o: ["o", "0"],
1659
- s: ["s", "5", "$"],
1660
- t: ["t", "7", "+"],
1661
- z: ["z", "2"],
2234
+ a: ['a', '4', '@'],
2235
+ b: ['b', '8', '6'],
2236
+ c: ['c', '(', '{', '<'],
2237
+ e: ['e', '3'],
2238
+ g: ['g', '6', '9'],
2239
+ i: ['i', '1', '!', '|'],
2240
+ l: ['l', '1', '|'],
2241
+ o: ['o', '0'],
2242
+ s: ['s', '5', '$'],
2243
+ t: ['t', '7', '+'],
2244
+ z: ['z', '2'],
1662
2245
  };
1663
2246
  return pattern
1664
- .split("")
2247
+ .split('')
1665
2248
  .map((char) => {
1666
2249
  const lowerChar = char.toLowerCase();
1667
2250
  const variations = leetMap[lowerChar];
1668
2251
  if (variations && variations.length > 1) {
1669
- return `[${variations.join("")}]`;
2252
+ return `[${variations.join('')}]`;
1670
2253
  }
1671
2254
  return char;
1672
2255
  })
1673
- .join("");
2256
+ .join('');
1674
2257
  }
1675
2258
  /**
1676
2259
  * Menambahkan kemungkinan split/pemisahan antar karakter
@@ -1680,7 +2263,7 @@ function addLeetSpeakVariations(pattern) {
1680
2263
  */
1681
2264
  function addSplitVariations(pattern) {
1682
2265
  // Tambahkan kemungkinan spasi atau karakter penghubung di antara setiap huruf
1683
- return pattern.split("").join("[\\s\\-._*+]?");
2266
+ return pattern.split('').join('[\\s\\-._*+]?');
1684
2267
  }
1685
2268
  /**
1686
2269
  * Membuat regex untuk mencari kata dengan variasi spasi dan karakter penghubung
@@ -1692,7 +2275,7 @@ function addSplitVariations(pattern) {
1692
2275
  function createEvasionRegex(word) {
1693
2276
  // Tambahkan kemungkinan spasi atau karakter penghubung di antara setiap huruf
1694
2277
  const pattern = addSplitVariations(escapeRegExp(word));
1695
- return new RegExp(pattern, "gi");
2278
+ return new RegExp(pattern, 'gi');
1696
2279
  }
1697
2280
  /**
1698
2281
  * Menambahkan variasi ejaan Bahasa Indonesia
@@ -1703,27 +2286,27 @@ function createEvasionRegex(word) {
1703
2286
  function addIndonesianVariations(pattern) {
1704
2287
  // Variasi ejaan dalam Bahasa Indonesia
1705
2288
  const variationMap = {
1706
- c: ["c", "k"], // contoh: becok/bekok
1707
- k: ["k", "c", "q"], // contoh: kacau/qacau
1708
- j: ["j", "dj"], // contoh: jualan/djualan (ejaan lama)
1709
- y: ["y", "j"], // contoh: ya/ja
1710
- u: ["u", "oe"], // contoh: untuk/oentoek (ejaan lama)
1711
- f: ["f", "p", "v"], // contoh: kafir/kapir
1712
- z: ["z", "j", "s"], // contoh: zaman/jaman
1713
- x: ["x", "ks"], // contoh: taxi/taksi
2289
+ c: ['c', 'k'], // contoh: becok/bekok
2290
+ k: ['k', 'c', 'q'], // contoh: kacau/qacau
2291
+ j: ['j', 'dj'], // contoh: jualan/djualan (ejaan lama)
2292
+ y: ['y', 'j'], // contoh: ya/ja
2293
+ u: ['u', 'oe'], // contoh: untuk/oentoek (ejaan lama)
2294
+ f: ['f', 'p', 'v'], // contoh: kafir/kapir
2295
+ z: ['z', 'j', 's'], // contoh: zaman/jaman
2296
+ x: ['x', 'ks'], // contoh: taxi/taksi
1714
2297
  };
1715
2298
  // Ganti tiap karakter dengan variasinya
1716
2299
  return pattern
1717
- .split("")
2300
+ .split('')
1718
2301
  .map((char) => {
1719
2302
  const lowerChar = char.toLowerCase();
1720
2303
  const variations = variationMap[lowerChar];
1721
2304
  if (variations && variations.length > 1) {
1722
- return `[${variations.join("")}]`;
2305
+ return `[${variations.join('')}]`;
1723
2306
  }
1724
2307
  return char;
1725
2308
  })
1726
- .join("");
2309
+ .join('');
1727
2310
  }
1728
2311
  /**
1729
2312
  * Membuat regex untuk mencocokkan kata dengan mempertimbangkan variasi ejaan Bahasa Indonesia
@@ -1733,7 +2316,7 @@ function addIndonesianVariations(pattern) {
1733
2316
  */
1734
2317
  function createIndonesianVariationRegex(word) {
1735
2318
  const pattern = addIndonesianVariations(escapeRegExp(word));
1736
- return new RegExp(`\\b${pattern}\\b`, "gi");
2319
+ return new RegExp(`\\b${pattern}\\b`, 'gi');
1737
2320
  }
1738
2321
  /**
1739
2322
  * Membuat regex untuk mencocokkan kata dengan konteks
@@ -1746,7 +2329,7 @@ function createContextRegex(word, contextSize = 3) {
1746
2329
  const wordPattern = escapeRegExp(word);
1747
2330
  // Membuat pola yang menangkap beberapa kata sebelum dan setelah kata target
1748
2331
  const pattern = `((?:\\S+\\s+){0,${contextSize}})(\\b${wordPattern}\\b)((?:\\s+\\S+){0,${contextSize}})`;
1749
- return new RegExp(pattern, "gi");
2332
+ return new RegExp(pattern, 'gi');
1750
2333
  }
1751
2334
  /**
1752
2335
  * Membuat regex untuk mencocokkan variasi penulisan kata
@@ -1757,8 +2340,8 @@ function createContextRegex(word, contextSize = 3) {
1757
2340
  function createWordFormRegex(word) {
1758
2341
  // Implementasi sederhana untuk mencocokkan berbagai imbuhan
1759
2342
  // Ini bisa dikembangkan lebih lanjut untuk mencocokkan bentukan kata yang lebih kompleks
1760
- const prefixes = ["", "me", "pe", "ber", "di", "ter", "se"];
1761
- const suffixes = ["", "kan", "an", "i", "nya"];
2343
+ const prefixes = ['', 'me', 'pe', 'ber', 'di', 'ter', 'se'];
2344
+ const suffixes = ['', 'kan', 'an', 'i', 'nya'];
1762
2345
  const patterns = [];
1763
2346
  // Kombinasikan prefix dan suffix
1764
2347
  for (const prefix of prefixes) {
@@ -1766,7 +2349,7 @@ function createWordFormRegex(word) {
1766
2349
  patterns.push(`\\b${prefix}${escapeRegExp(word)}${suffix}\\b`);
1767
2350
  }
1768
2351
  }
1769
- return new RegExp(patterns.join("|"), "gi");
2352
+ return new RegExp(patterns.join('|'), 'gi');
1770
2353
  }
1771
2354
 
1772
2355
  /**
@@ -1800,7 +2383,8 @@ function levenshteinDistance(str1, str2) {
1800
2383
  const cost = s1[i - 1] === s2[j - 1] ? 0 : 1;
1801
2384
  matrix[i][j] = Math.min(matrix[i - 1][j] + 1, // deletion
1802
2385
  matrix[i][j - 1] + 1, // insertion
1803
- matrix[i - 1][j - 1] + cost);
2386
+ matrix[i - 1][j - 1] + cost // substitution
2387
+ );
1804
2388
  }
1805
2389
  }
1806
2390
  return matrix[len1][len2];
@@ -1979,8 +2563,7 @@ function findPossibleProfanityBySimiliarity(text, profanityWords, threshold = 0.
1979
2563
  let bestMatch = null;
1980
2564
  for (const profanity of lengthFilteredCandidates) {
1981
2565
  const similarity = stringSimilarity(word, profanity);
1982
- if (similarity >= threshold &&
1983
- (!bestMatch || similarity > bestMatch.similarity)) {
2566
+ if (similarity >= threshold && (!bestMatch || similarity > bestMatch.similarity)) {
1984
2567
  bestMatch = {
1985
2568
  word,
1986
2569
  original: profanity,
@@ -2029,8 +2612,7 @@ function findProfanityByLevenshteinDistance(text, profanityWords, threshold = 0.
2029
2612
  const distance = levenshteinDistance(word, profanity);
2030
2613
  if (distance <= maxDistance) {
2031
2614
  const similarity = 1 - distance / Math.max(word.length, profanity.length);
2032
- if (similarity >= threshold &&
2033
- (!bestMatch || similarity > bestMatch.similarity)) {
2615
+ if (similarity >= threshold && (!bestMatch || similarity > bestMatch.similarity)) {
2034
2616
  bestMatch = {
2035
2617
  word,
2036
2618
  original: profanity,
@@ -2076,7 +2658,7 @@ function isCharacterCountSimilar(str1, str2, maxDifference) {
2076
2658
  }
2077
2659
 
2078
2660
  const DEFAULT_OPTIONS = {
2079
- replaceWith: "*",
2661
+ replaceWith: '*',
2080
2662
  fullWordCensor: true,
2081
2663
  detectLeetSpeak: true,
2082
2664
  checkSubstring: false,
@@ -2099,7 +2681,7 @@ const FILTER_PRESETS = {
2099
2681
  light: {
2100
2682
  ...DEFAULT_OPTIONS,
2101
2683
  severityThreshold: 0.7,
2102
- categories: ["sexual", "slur", "blasphemy"],
2684
+ categories: ['sexual', 'slur', 'blasphemy'],
2103
2685
  },
2104
2686
  childSafe: {
2105
2687
  ...DEFAULT_OPTIONS,
@@ -2112,49 +2694,49 @@ const FILTER_PRESETS = {
2112
2694
  const CATEGORY_PRESETS = {
2113
2695
  sexual: {
2114
2696
  ...DEFAULT_OPTIONS,
2115
- categories: ["sexual"],
2697
+ categories: ['sexual'],
2116
2698
  },
2117
2699
  insults: {
2118
2700
  ...DEFAULT_OPTIONS,
2119
- categories: ["insult"],
2701
+ categories: ['insult'],
2120
2702
  },
2121
2703
  profanity: {
2122
2704
  ...DEFAULT_OPTIONS,
2123
- categories: ["profanity"],
2705
+ categories: ['profanity'],
2124
2706
  },
2125
2707
  };
2126
2708
  const REGION_PRESETS = {
2127
2709
  general: {
2128
2710
  ...DEFAULT_OPTIONS,
2129
- regions: ["general"],
2711
+ regions: ['general'],
2130
2712
  },
2131
2713
  jawa: {
2132
2714
  ...DEFAULT_OPTIONS,
2133
- regions: ["jawa"],
2715
+ regions: ['jawa'],
2134
2716
  },
2135
2717
  sunda: {
2136
2718
  ...DEFAULT_OPTIONS,
2137
- regions: ["sunda"],
2719
+ regions: ['sunda'],
2138
2720
  },
2139
2721
  betawi: {
2140
2722
  ...DEFAULT_OPTIONS,
2141
- regions: ["betawi"],
2723
+ regions: ['betawi'],
2142
2724
  },
2143
2725
  batak: {
2144
2726
  ...DEFAULT_OPTIONS,
2145
- regions: ["batak"],
2727
+ regions: ['batak'],
2146
2728
  },
2147
2729
  };
2148
2730
  const REPLACEMENT_CHARS = {
2149
- asterisk: "*",
2150
- hash: "#",
2151
- dollar: "$",
2152
- at: "@",
2153
- percent: "%",
2154
- underscore: "_",
2155
- dash: "-",
2156
- dot: ".",
2157
- grawlix: "#@$%&!",
2731
+ asterisk: '*',
2732
+ hash: '#',
2733
+ dollar: '$',
2734
+ at: '@',
2735
+ percent: '%',
2736
+ underscore: '_',
2737
+ dash: '-',
2738
+ dot: '.',
2739
+ grawlix: '#@$%&!',
2158
2740
  };
2159
2741
  /**
2160
2742
  * Membuat opsi custom dengan menggabungkan dengan default
@@ -2181,8 +2763,7 @@ function getPresetOptions(presetName, additionalOptions = {}) {
2181
2763
  presetOptions = FILTER_PRESETS[presetName];
2182
2764
  }
2183
2765
  else if (presetName in CATEGORY_PRESETS) {
2184
- presetOptions =
2185
- CATEGORY_PRESETS[presetName];
2766
+ presetOptions = CATEGORY_PRESETS[presetName];
2186
2767
  }
2187
2768
  else if (presetName in REGION_PRESETS) {
2188
2769
  presetOptions = REGION_PRESETS[presetName];
@@ -2201,7 +2782,7 @@ function getPresetOptions(presetName, additionalOptions = {}) {
2201
2782
  * @param type Tipe karakter pengganti
2202
2783
  * @returns Karakter pengganti
2203
2784
  */
2204
- function getReplacementChar(type = "asterisk") {
2785
+ function getReplacementChar(type = 'asterisk') {
2205
2786
  return REPLACEMENT_CHARS[type] || REPLACEMENT_CHARS.asterisk;
2206
2787
  }
2207
2788
  /**
@@ -2220,7 +2801,7 @@ function getRandomGrawlix() {
2220
2801
  * @returns String pengganti
2221
2802
  */
2222
2803
  function makeRandomGrawlixString(length) {
2223
- let result = "";
2804
+ let result = '';
2224
2805
  const grawlix = REPLACEMENT_CHARS.grawlix;
2225
2806
  for (let i = 0; i < length; i++) {
2226
2807
  result += grawlix[Math.floor(Math.random() * grawlix.length)];
@@ -2248,7 +2829,7 @@ class AhoCorasick {
2248
2829
  */
2249
2830
  addPattern(pattern) {
2250
2831
  if (this.built) {
2251
- throw new Error("Cannot add patterns after the automaton is built");
2832
+ throw new Error('Cannot add patterns after the automaton is built');
2252
2833
  }
2253
2834
  let node = this.root;
2254
2835
  const normalizedPattern = pattern.toLowerCase();
@@ -2385,9 +2966,7 @@ function findProfanity(text, options = {}) {
2385
2966
  let baseWordsToCheck = wordList.length > 0 ? wordList : [];
2386
2967
  if (baseWordsToCheck.length === 0) {
2387
2968
  const filteredWords = wordObjects.filter((word) => {
2388
- const matchCategory = categories
2389
- ? categories.includes(word.category)
2390
- : true;
2969
+ const matchCategory = categories ? categories.includes(word.category) : true;
2391
2970
  const matchRegion = regions ? regions.includes(word.region) : true;
2392
2971
  const matchSeverity = word.severity >= severityThreshold;
2393
2972
  return matchCategory && matchRegion && matchSeverity;
@@ -2397,9 +2976,7 @@ function findProfanity(text, options = {}) {
2397
2976
  const aliasMap = new Map();
2398
2977
  wordObjects.forEach((wordObj) => {
2399
2978
  if (wordObj.aliases && wordObj.aliases.length > 0) {
2400
- const matchCategory = categories
2401
- ? categories.includes(wordObj.category)
2402
- : true;
2979
+ const matchCategory = categories ? categories.includes(wordObj.category) : true;
2403
2980
  const matchRegion = regions ? regions.includes(wordObj.region) : true;
2404
2981
  const matchSeverity = wordObj.severity >= severityThreshold;
2405
2982
  if (matchCategory && matchRegion && matchSeverity) {
@@ -2409,10 +2986,7 @@ function findProfanity(text, options = {}) {
2409
2986
  }
2410
2987
  }
2411
2988
  });
2412
- const wordsToCheck = [
2413
- ...baseWordsToCheck,
2414
- ...Array.from(aliasMap.keys()),
2415
- ].filter((word) => !whitelist.includes(word.toLowerCase()));
2989
+ const wordsToCheck = [...baseWordsToCheck, ...Array.from(aliasMap.keys())].filter((word) => !whitelist.includes(word.toLowerCase()));
2416
2990
  if (wordsToCheck.length === 0) {
2417
2991
  return [];
2418
2992
  }
@@ -2492,8 +3066,7 @@ function findProfanity(text, options = {}) {
2492
3066
  if (useLevenshtein) {
2493
3067
  const possibleProfanity = findProfanityByLevenshteinDistance(text, wordsToCheck, similarityThreshold, maxLevenshteinDistance);
2494
3068
  possibleProfanity.forEach((item) => {
2495
- const originalWord = aliasMap.get(item.original.toLowerCase()) ||
2496
- item.original.toLowerCase();
3069
+ const originalWord = aliasMap.get(item.original.toLowerCase()) || item.original.toLowerCase();
2497
3070
  matches.add(originalWord);
2498
3071
  if (!actualMatches.has(originalWord)) {
2499
3072
  actualMatches.set(originalWord, []);
@@ -2505,8 +3078,7 @@ function findProfanity(text, options = {}) {
2505
3078
  const possibleProfanity = findPossibleProfanityBySimiliarity(text, wordsToCheck, similarityThreshold);
2506
3079
  possibleProfanity.forEach((item) => {
2507
3080
  matches.add(item.original.toLowerCase());
2508
- const originalWord = aliasMap.get(item.original.toLowerCase()) ||
2509
- item.original.toLowerCase();
3081
+ const originalWord = aliasMap.get(item.original.toLowerCase()) || item.original.toLowerCase();
2510
3082
  if (!actualMatches.has(originalWord)) {
2511
3083
  actualMatches.set(originalWord, []);
2512
3084
  }
@@ -2532,8 +3104,7 @@ function findProfanityWithMetadata(text, options = {}) {
2532
3104
  return matches
2533
3105
  .map((word) => {
2534
3106
  const wordObject = wordObjects.find((obj) => obj.word.toLowerCase() === word.toLowerCase() ||
2535
- (obj.aliases &&
2536
- obj.aliases.some((alias) => alias.toLowerCase() === word.toLowerCase())));
3107
+ (obj.aliases && obj.aliases.some((alias) => alias.toLowerCase() === word.toLowerCase())));
2537
3108
  return wordObject;
2538
3109
  })
2539
3110
  .filter((word) => word !== undefined);
@@ -2604,7 +3175,7 @@ function calculateSeverity(matchDetails) {
2604
3175
  * @returns FilterResult dengan hasil filter
2605
3176
  */
2606
3177
  function filter(text, options = {}) {
2607
- const { replaceWith = "*", fullWordCensor = true, detectLeetSpeak = true, whitelist = [], checkSubstring = false, useRandomGrawlix = false, keepFirstAndLast = false, indonesianVariation = false, detectSplit = false, detectSimilarity = false, useLevenshtein = false, maxLevenshteinDistance = 2, similarityThreshold = 0.8, } = { ...DEFAULT_OPTIONS, ...options };
3178
+ const { replaceWith = '*', fullWordCensor = true, detectLeetSpeak = true, whitelist = [], checkSubstring = false, useRandomGrawlix = false, keepFirstAndLast = false, indonesianVariation = false, detectSplit = false, detectSimilarity = false, useLevenshtein = false, maxLevenshteinDistance = 2, similarityThreshold = 0.8, } = { ...DEFAULT_OPTIONS, ...options };
2608
3179
  const matches = findProfanity(text, {
2609
3180
  ...options,
2610
3181
  detectLeetSpeak,
@@ -2630,13 +3201,12 @@ function filter(text, options = {}) {
2630
3201
  const replacements = [];
2631
3202
  matches.forEach((word) => {
2632
3203
  const metadata = matchDetails.find((m) => m.word.toLowerCase() === word.toLowerCase() ||
2633
- (m.aliases &&
2634
- m.aliases.some((alias) => alias.toLowerCase() === word.toLowerCase())));
3204
+ (m.aliases && m.aliases.some((alias) => alias.toLowerCase() === word.toLowerCase())));
2635
3205
  const variants = actualMatches.get(word.toLowerCase()) || [];
2636
3206
  variants.push(word);
2637
3207
  const uniqueVariants = [...new Set(variants)];
2638
3208
  uniqueVariants.forEach((variant) => {
2639
- const regex = new RegExp(`\\b${escapeRegExp(variant)}\\b`, "gi");
3209
+ const regex = new RegExp(`\\b${escapeRegExp(variant)}\\b`, 'gi');
2640
3210
  let match;
2641
3211
  while ((match = regex.exec(filteredText)) !== null) {
2642
3212
  const originalWord = match[0];
@@ -2654,7 +3224,7 @@ function filter(text, options = {}) {
2654
3224
  censored: censoredWord,
2655
3225
  metadata,
2656
3226
  });
2657
- filteredText = filteredText.replace(new RegExp(`\\b${escapeRegExp(originalWord)}\\b`, "g"), censoredWord);
3227
+ filteredText = filteredText.replace(new RegExp(`\\b${escapeRegExp(originalWord)}\\b`, 'g'), censoredWord);
2658
3228
  }
2659
3229
  });
2660
3230
  if (detectSplit || detectLeetSpeak) {
@@ -2683,7 +3253,7 @@ function filter(text, options = {}) {
2683
3253
  censored: censoredWord,
2684
3254
  metadata,
2685
3255
  });
2686
- filteredText = filteredText.replace(new RegExp(escapeRegExp(originalWord), "g"), censoredWord);
3256
+ filteredText = filteredText.replace(new RegExp(escapeRegExp(originalWord), 'g'), censoredWord);
2687
3257
  }
2688
3258
  }
2689
3259
  if (detectSplit) {
@@ -2711,7 +3281,7 @@ function filter(text, options = {}) {
2711
3281
  censored: censoredWord,
2712
3282
  metadata,
2713
3283
  });
2714
- filteredText = filteredText.replace(new RegExp(escapeRegExp(originalWord), "g"), censoredWord);
3284
+ filteredText = filteredText.replace(new RegExp(escapeRegExp(originalWord), 'g'), censoredWord);
2715
3285
  }
2716
3286
  }
2717
3287
  }
@@ -2719,11 +3289,10 @@ function filter(text, options = {}) {
2719
3289
  if (detectSimilarity && useLevenshtein) {
2720
3290
  matches.forEach((word) => {
2721
3291
  const metadata = matchDetails.find((m) => m.word.toLowerCase() === word.toLowerCase() ||
2722
- (m.aliases &&
2723
- m.aliases.some((alias) => alias.toLowerCase() === word.toLowerCase())));
3292
+ (m.aliases && m.aliases.some((alias) => alias.toLowerCase() === word.toLowerCase())));
2724
3293
  const variants = actualMatches.get(word.toLowerCase()) || [];
2725
3294
  variants.forEach((variant) => {
2726
- const exactVariantRegex = new RegExp(`\\b${escapeRegExp(variant)}\\b`, "gi");
3295
+ const exactVariantRegex = new RegExp(`\\b${escapeRegExp(variant)}\\b`, 'gi');
2727
3296
  let match;
2728
3297
  while ((match = exactVariantRegex.exec(filteredText)) !== null) {
2729
3298
  const originalWord = match[0];
@@ -2741,7 +3310,7 @@ function filter(text, options = {}) {
2741
3310
  censored: censoredWord,
2742
3311
  metadata,
2743
3312
  });
2744
- filteredText = filteredText.replace(new RegExp(`\\b${escapeRegExp(originalWord)}\\b`, "g"), censoredWord);
3313
+ filteredText = filteredText.replace(new RegExp(`\\b${escapeRegExp(originalWord)}\\b`, 'g'), censoredWord);
2745
3314
  }
2746
3315
  });
2747
3316
  });
@@ -2900,9 +3469,9 @@ function analyzeWithContext(text, contextWindowSize = 5, options = {}) {
2900
3469
  const regex = createContextRegex(word, contextWindowSize);
2901
3470
  let match;
2902
3471
  while ((match = regex.exec(text)) !== null) {
2903
- const beforeContext = match[1] || "";
3472
+ const beforeContext = match[1] || '';
2904
3473
  const wordMatch = match[2];
2905
- const afterContext = match[3] || "";
3474
+ const afterContext = match[3] || '';
2906
3475
  result.push({
2907
3476
  word: wordMatch,
2908
3477
  context: beforeContext + wordMatch + afterContext,
@@ -3003,10 +3572,7 @@ class IDProfanityFilter {
3003
3572
  * @param word Kata yang akan diabaikan
3004
3573
  */
3005
3574
  addToWhitelist(word) {
3006
- this.options.whitelist = [
3007
- ...(this.options.whitelist || []),
3008
- word.toLowerCase(),
3009
- ];
3575
+ this.options.whitelist = [...(this.options.whitelist || []), word.toLowerCase()];
3010
3576
  }
3011
3577
  /**
3012
3578
  * Menghapus kata dari whitelist