@sideid/id-profanity-filter 1.1.0 → 1.9.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/config/options.ts +178 -0
- package/src/constants/categories/index.ts +31 -31
- package/src/constants/categories/insult.ts +114 -114
- package/src/constants/categories/sexual.ts +99 -100
- package/src/constants/regions/batak.ts +17 -17
- package/src/constants/regions/betawi.ts +39 -39
- package/src/constants/regions/general.ts +111 -111
- package/src/constants/regions/index.ts +62 -62
- package/src/constants/regions/jawa.ts +102 -102
- package/src/constants/regions/sunda.ts +35 -35
- package/src/constants/wordList.ts +125 -125
- package/src/core/analyzer.ts +225 -204
- package/src/core/filter.ts +129 -129
- package/src/core/matcher.ts +259 -267
- package/src/index.ts +188 -133
- package/src/types/index.ts +88 -115
- package/src/utils/regexUtils.ts +203 -0
- package/src/utils/similarityUtils.ts +195 -0
- package/src/utils/stringUtils.ts +213 -0
package/package.json
CHANGED
package/src/config/options.ts
CHANGED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { FilterOptions, ProfanityCategory, Region } from "../types";
|
|
2
|
+
|
|
3
|
+
export const DEFAULT_OPTIONS: FilterOptions = {
|
|
4
|
+
replaceWith: "*",
|
|
5
|
+
fullWordCensor: true,
|
|
6
|
+
detectLeetSpeak: true,
|
|
7
|
+
checkSubstring: false,
|
|
8
|
+
whitelist: [],
|
|
9
|
+
severityThreshold: 0,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const FILTER_PRESETS = {
|
|
13
|
+
strict: {
|
|
14
|
+
...DEFAULT_OPTIONS,
|
|
15
|
+
checkSubstring: true,
|
|
16
|
+
detectLeetSpeak: true,
|
|
17
|
+
severityThreshold: 0,
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
moderate: {
|
|
21
|
+
...DEFAULT_OPTIONS,
|
|
22
|
+
severityThreshold: 0.5,
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
light: {
|
|
26
|
+
...DEFAULT_OPTIONS,
|
|
27
|
+
severityThreshold: 0.7,
|
|
28
|
+
categories: ["sexual", "slur", "blasphemy"] as ProfanityCategory[],
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
childSafe: {
|
|
32
|
+
...DEFAULT_OPTIONS,
|
|
33
|
+
checkSubstring: true,
|
|
34
|
+
detectLeetSpeak: true,
|
|
35
|
+
fullWordCensor: true,
|
|
36
|
+
severityThreshold: 0,
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const CATEGORY_PRESETS = {
|
|
41
|
+
sexual: {
|
|
42
|
+
...DEFAULT_OPTIONS,
|
|
43
|
+
categories: ["sexual"] as ProfanityCategory[],
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
insults: {
|
|
47
|
+
...DEFAULT_OPTIONS,
|
|
48
|
+
categories: ["insult"] as ProfanityCategory[],
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
profanity: {
|
|
52
|
+
...DEFAULT_OPTIONS,
|
|
53
|
+
categories: ["profanity"] as ProfanityCategory[],
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export const REGION_PRESETS = {
|
|
58
|
+
general: {
|
|
59
|
+
...DEFAULT_OPTIONS,
|
|
60
|
+
regions: ["general"] as Region[],
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
jawa: {
|
|
64
|
+
...DEFAULT_OPTIONS,
|
|
65
|
+
regions: ["jawa"] as Region[],
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
sunda: {
|
|
69
|
+
...DEFAULT_OPTIONS,
|
|
70
|
+
regions: ["sunda"] as Region[],
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
betawi: {
|
|
74
|
+
...DEFAULT_OPTIONS,
|
|
75
|
+
regions: ["betawi"] as Region[],
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
batak: {
|
|
79
|
+
...DEFAULT_OPTIONS,
|
|
80
|
+
regions: ["batak"] as Region[],
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export const REPLACEMENT_CHARS = {
|
|
85
|
+
asterisk: "*",
|
|
86
|
+
hash: "#",
|
|
87
|
+
dollar: "$",
|
|
88
|
+
at: "@",
|
|
89
|
+
percent: "%",
|
|
90
|
+
underscore: "_",
|
|
91
|
+
dash: "-",
|
|
92
|
+
dot: ".",
|
|
93
|
+
grawlix: "#@$%&!",
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Membuat opsi custom dengan menggabungkan dengan default
|
|
98
|
+
*
|
|
99
|
+
* @param options Opsi yang akan digabungkan dengan default
|
|
100
|
+
* @returns Opsi yang sudah digabungkan
|
|
101
|
+
*/
|
|
102
|
+
export function createOptions(
|
|
103
|
+
options: Partial<FilterOptions> = {},
|
|
104
|
+
): FilterOptions {
|
|
105
|
+
return {
|
|
106
|
+
...DEFAULT_OPTIONS,
|
|
107
|
+
...options,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Mendapatkan opsi dari preset yang ada
|
|
113
|
+
*
|
|
114
|
+
* @param presetName Nama preset filter, kategori, atau region
|
|
115
|
+
* @param additionalOptions Opsi tambahan untuk mengganti preset
|
|
116
|
+
* @returns Opsi yang sudah digabungkan
|
|
117
|
+
*/
|
|
118
|
+
export function getPresetOptions(
|
|
119
|
+
presetName: string,
|
|
120
|
+
additionalOptions: Partial<FilterOptions> = {},
|
|
121
|
+
): FilterOptions {
|
|
122
|
+
let presetOptions: FilterOptions;
|
|
123
|
+
|
|
124
|
+
if (presetName in FILTER_PRESETS) {
|
|
125
|
+
presetOptions = FILTER_PRESETS[presetName as keyof typeof FILTER_PRESETS];
|
|
126
|
+
} else if (presetName in CATEGORY_PRESETS) {
|
|
127
|
+
presetOptions =
|
|
128
|
+
CATEGORY_PRESETS[presetName as keyof typeof CATEGORY_PRESETS];
|
|
129
|
+
} else if (presetName in REGION_PRESETS) {
|
|
130
|
+
presetOptions = REGION_PRESETS[presetName as keyof typeof REGION_PRESETS];
|
|
131
|
+
} else {
|
|
132
|
+
presetOptions = FILTER_PRESETS.strict;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return {
|
|
136
|
+
...presetOptions,
|
|
137
|
+
...additionalOptions,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Mendapatkan karakter pengganti
|
|
143
|
+
*
|
|
144
|
+
* @param type Tipe karakter pengganti
|
|
145
|
+
* @returns Karakter pengganti
|
|
146
|
+
*/
|
|
147
|
+
export function getReplacementChar(
|
|
148
|
+
type: keyof typeof REPLACEMENT_CHARS = "asterisk",
|
|
149
|
+
): string {
|
|
150
|
+
return REPLACEMENT_CHARS[type] || REPLACEMENT_CHARS.asterisk;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Membuat karakter pengganti random dari grawlix
|
|
155
|
+
*
|
|
156
|
+
* @returns Karakter pengganti random
|
|
157
|
+
*/
|
|
158
|
+
export function getRandomGrawlix(): string {
|
|
159
|
+
const grawlix = REPLACEMENT_CHARS.grawlix;
|
|
160
|
+
return grawlix[Math.floor(Math.random() * grawlix.length)];
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Membuat string pengganti untuk kata menggunakan grawlix random
|
|
165
|
+
*
|
|
166
|
+
* @param length Panjang string
|
|
167
|
+
* @returns String pengganti
|
|
168
|
+
*/
|
|
169
|
+
export function makeRandomGrawlixString(length: number): string {
|
|
170
|
+
let result = "";
|
|
171
|
+
const grawlix = REPLACEMENT_CHARS.grawlix;
|
|
172
|
+
|
|
173
|
+
for (let i = 0; i < length; i++) {
|
|
174
|
+
result += grawlix[Math.floor(Math.random() * grawlix.length)];
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return result;
|
|
178
|
+
}
|
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
// import { sexual } from './sexual';
|
|
2
|
-
// import { insult } from './insult';
|
|
3
|
-
// import { profanity } from './profanity';
|
|
4
|
-
// import { slur } from './slur';
|
|
5
|
-
// import { drugs } from './drugs';
|
|
6
|
-
// import { disgusting } from './disgusting';
|
|
7
|
-
// import { blasphemy } from './blasphemy';
|
|
8
|
-
|
|
9
|
-
// export const categories = {
|
|
10
|
-
// sexual, // Kata-kata berbau seksual
|
|
11
|
-
// insult, // Kata-kata penghinaan
|
|
12
|
-
// profanity, // Umpatan umum
|
|
13
|
-
// slur, // Perkataan merendahkan berdasarkan identitas
|
|
14
|
-
// drugs, // Terkait narkoba
|
|
15
|
-
// disgusting, // Kata-kata menjijikkan
|
|
16
|
-
// blasphemy, // Penistaan agama
|
|
17
|
-
// };
|
|
18
|
-
|
|
19
|
-
// export { sexual, insult, profanity, slur, drugs, disgusting, blasphemy };
|
|
20
|
-
|
|
21
|
-
// export const allCategoryWords = [
|
|
22
|
-
// ...sexual,
|
|
23
|
-
// ...insult,
|
|
24
|
-
// ...profanity,
|
|
25
|
-
// ...slur,
|
|
26
|
-
// ...drugs,
|
|
27
|
-
// ...disgusting,
|
|
28
|
-
// ...blasphemy,
|
|
29
|
-
// ];
|
|
30
|
-
|
|
31
|
-
// export default allCategoryWords;
|
|
1
|
+
// import { sexual } from './sexual';
|
|
2
|
+
// import { insult } from './insult';
|
|
3
|
+
// import { profanity } from './profanity';
|
|
4
|
+
// import { slur } from './slur';
|
|
5
|
+
// import { drugs } from './drugs';
|
|
6
|
+
// import { disgusting } from './disgusting';
|
|
7
|
+
// import { blasphemy } from './blasphemy';
|
|
8
|
+
|
|
9
|
+
// export const categories = {
|
|
10
|
+
// sexual, // Kata-kata berbau seksual
|
|
11
|
+
// insult, // Kata-kata penghinaan
|
|
12
|
+
// profanity, // Umpatan umum
|
|
13
|
+
// slur, // Perkataan merendahkan berdasarkan identitas
|
|
14
|
+
// drugs, // Terkait narkoba
|
|
15
|
+
// disgusting, // Kata-kata menjijikkan
|
|
16
|
+
// blasphemy, // Penistaan agama
|
|
17
|
+
// };
|
|
18
|
+
|
|
19
|
+
// export { sexual, insult, profanity, slur, drugs, disgusting, blasphemy };
|
|
20
|
+
|
|
21
|
+
// export const allCategoryWords = [
|
|
22
|
+
// ...sexual,
|
|
23
|
+
// ...insult,
|
|
24
|
+
// ...profanity,
|
|
25
|
+
// ...slur,
|
|
26
|
+
// ...drugs,
|
|
27
|
+
// ...disgusting,
|
|
28
|
+
// ...blasphemy,
|
|
29
|
+
// ];
|
|
30
|
+
|
|
31
|
+
// export default allCategoryWords;
|
|
@@ -1,114 +1,114 @@
|
|
|
1
|
-
import { ProfanityWord } from
|
|
2
|
-
import { general } from
|
|
3
|
-
import { jawa } from
|
|
4
|
-
import { sunda } from
|
|
5
|
-
import { betawi } from
|
|
6
|
-
|
|
7
|
-
export const insult: ProfanityWord[] = [
|
|
8
|
-
...general.filter((word) => word.category ===
|
|
9
|
-
...jawa.filter((word) => word.category ===
|
|
10
|
-
...sunda.filter((word) => word.category ===
|
|
11
|
-
...betawi.filter((word) => word.category ===
|
|
12
|
-
|
|
13
|
-
{
|
|
14
|
-
word:
|
|
15
|
-
category:
|
|
16
|
-
region:
|
|
17
|
-
severity: 0.6,
|
|
18
|
-
aliases: [
|
|
19
|
-
description:
|
|
20
|
-
context:
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
word:
|
|
24
|
-
category:
|
|
25
|
-
region:
|
|
26
|
-
severity: 0.5,
|
|
27
|
-
aliases: [
|
|
28
|
-
description:
|
|
29
|
-
context:
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
word:
|
|
33
|
-
category:
|
|
34
|
-
region:
|
|
35
|
-
severity: 0.6,
|
|
36
|
-
aliases: [
|
|
37
|
-
description:
|
|
38
|
-
|
|
39
|
-
context:
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
word:
|
|
43
|
-
category:
|
|
44
|
-
region:
|
|
45
|
-
severity: 0.6,
|
|
46
|
-
aliases: [
|
|
47
|
-
description:
|
|
48
|
-
|
|
49
|
-
context:
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
word:
|
|
53
|
-
category:
|
|
54
|
-
region:
|
|
55
|
-
severity: 0.5,
|
|
56
|
-
aliases: [
|
|
57
|
-
description:
|
|
58
|
-
context:
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
word:
|
|
62
|
-
category:
|
|
63
|
-
region:
|
|
64
|
-
severity: 0.5,
|
|
65
|
-
aliases: [
|
|
66
|
-
description:
|
|
67
|
-
|
|
68
|
-
context:
|
|
69
|
-
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
word:
|
|
73
|
-
category:
|
|
74
|
-
region:
|
|
75
|
-
severity: 0.5,
|
|
76
|
-
aliases: [
|
|
77
|
-
description:
|
|
78
|
-
|
|
79
|
-
context:
|
|
80
|
-
|
|
81
|
-
},
|
|
82
|
-
{
|
|
83
|
-
word:
|
|
84
|
-
category:
|
|
85
|
-
region:
|
|
86
|
-
severity: 0.5,
|
|
87
|
-
aliases: [
|
|
88
|
-
description:
|
|
89
|
-
context:
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
word:
|
|
93
|
-
category:
|
|
94
|
-
region:
|
|
95
|
-
severity: 0.6,
|
|
96
|
-
aliases: [
|
|
97
|
-
description:
|
|
98
|
-
context:
|
|
99
|
-
},
|
|
100
|
-
{
|
|
101
|
-
word:
|
|
102
|
-
category:
|
|
103
|
-
region:
|
|
104
|
-
severity: 0.7,
|
|
105
|
-
aliases: [
|
|
106
|
-
description:
|
|
107
|
-
context:
|
|
108
|
-
|
|
109
|
-
},
|
|
110
|
-
];
|
|
111
|
-
|
|
112
|
-
export const insultWords = insult.map((item) => item.word);
|
|
113
|
-
|
|
114
|
-
export default insult;
|
|
1
|
+
import { ProfanityWord } from "../../types";
|
|
2
|
+
import { general } from "../regions/general";
|
|
3
|
+
import { jawa } from "../regions/jawa";
|
|
4
|
+
import { sunda } from "../regions/sunda";
|
|
5
|
+
import { betawi } from "../regions/betawi";
|
|
6
|
+
|
|
7
|
+
export const insult: ProfanityWord[] = [
|
|
8
|
+
...general.filter((word) => word.category === "insult"),
|
|
9
|
+
...jawa.filter((word) => word.category === "insult"),
|
|
10
|
+
...sunda.filter((word) => word.category === "insult"),
|
|
11
|
+
...betawi.filter((word) => word.category === "insult"),
|
|
12
|
+
|
|
13
|
+
{
|
|
14
|
+
word: "idiot",
|
|
15
|
+
category: "insult",
|
|
16
|
+
region: "general",
|
|
17
|
+
severity: 0.6,
|
|
18
|
+
aliases: ["idi0t", "idot"],
|
|
19
|
+
description: "Kata yang mengacu pada kebodohan seseorang",
|
|
20
|
+
context: "Hinaan untuk menyebut orang yang dianggap sangat tidak pintar",
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
word: "dungu",
|
|
24
|
+
category: "insult",
|
|
25
|
+
region: "general",
|
|
26
|
+
severity: 0.5,
|
|
27
|
+
aliases: ["dngu", "dongu"],
|
|
28
|
+
description: "Kata yang mengacu pada kebodohan seseorang",
|
|
29
|
+
context: "Hinaan untuk menyebut orang yang dianggap tidak pintar",
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
word: "sinting",
|
|
33
|
+
category: "insult",
|
|
34
|
+
region: "general",
|
|
35
|
+
severity: 0.6,
|
|
36
|
+
aliases: ["sintng", "senteng"],
|
|
37
|
+
description:
|
|
38
|
+
"Kata yang mengacu pada kegilaan atau ketidakwarasan seseorang",
|
|
39
|
+
context: "Hinaan untuk menyebut orang yang dianggap gila atau tidak waras",
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
word: "sarap",
|
|
43
|
+
category: "insult",
|
|
44
|
+
region: "general",
|
|
45
|
+
severity: 0.6,
|
|
46
|
+
aliases: ["saraf", "srap"],
|
|
47
|
+
description:
|
|
48
|
+
"Kata yang mengacu pada kegilaan atau ketidakwarasan seseorang",
|
|
49
|
+
context: "Hinaan untuk menyebut orang yang dianggap gila atau tidak waras",
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
word: "geblek",
|
|
53
|
+
category: "insult",
|
|
54
|
+
region: "general",
|
|
55
|
+
severity: 0.5,
|
|
56
|
+
aliases: ["gblk", "geblk"],
|
|
57
|
+
description: "Kata yang mengacu pada kebodohan seseorang",
|
|
58
|
+
context: "Hinaan untuk menyebut orang yang dianggap tidak pintar",
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
word: "kampungan",
|
|
62
|
+
category: "insult",
|
|
63
|
+
region: "general",
|
|
64
|
+
severity: 0.5,
|
|
65
|
+
aliases: ["kmpngn", "kamphungan"],
|
|
66
|
+
description:
|
|
67
|
+
"Kata yang mengacu pada ketidaksopanan atau kenaifan seseorang",
|
|
68
|
+
context:
|
|
69
|
+
"Hinaan untuk menyebut orang yang dianggap tidak modern atau primitif",
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
word: "udik",
|
|
73
|
+
category: "insult",
|
|
74
|
+
region: "general",
|
|
75
|
+
severity: 0.5,
|
|
76
|
+
aliases: ["udhik", "udek"],
|
|
77
|
+
description:
|
|
78
|
+
"Kata yang mengacu pada ketidaksopanan atau kenaifan seseorang",
|
|
79
|
+
context:
|
|
80
|
+
"Hinaan untuk menyebut orang yang dianggap tidak modern atau primitif",
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
word: "dongo",
|
|
84
|
+
category: "insult",
|
|
85
|
+
region: "general",
|
|
86
|
+
severity: 0.5,
|
|
87
|
+
aliases: ["donggo", "dungu"],
|
|
88
|
+
description: "Kata yang mengacu pada kebodohan seseorang",
|
|
89
|
+
context: "Hinaan untuk menyebut orang yang dianggap tidak pintar",
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
word: "tolol",
|
|
93
|
+
category: "insult",
|
|
94
|
+
region: "general",
|
|
95
|
+
severity: 0.6,
|
|
96
|
+
aliases: ["tol0l", "tollo", "tlol"],
|
|
97
|
+
description: "Kata yang mengacu pada kebodohan seseorang",
|
|
98
|
+
context: "Hinaan untuk menyebut orang yang dianggap tidak pintar",
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
word: "brengsek",
|
|
102
|
+
category: "insult",
|
|
103
|
+
region: "general",
|
|
104
|
+
severity: 0.7,
|
|
105
|
+
aliases: ["brengskek", "brengsik", "brengzek"],
|
|
106
|
+
description: "Kata yang mengacu pada kelakuan buruk atau tidak bermoral",
|
|
107
|
+
context:
|
|
108
|
+
"Hinaan untuk menyebut orang yang dianggap memiliki kelakuan buruk",
|
|
109
|
+
},
|
|
110
|
+
];
|
|
111
|
+
|
|
112
|
+
export const insultWords = insult.map((item) => item.word);
|
|
113
|
+
|
|
114
|
+
export default insult;
|