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