@sideid/id-profanity-filter 1.11.7 → 1.11.9

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 +1166 -438
  3. package/dist/index.esm.js.map +1 -1
  4. package/dist/index.js +1166 -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 +169 -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
@@ -1,22 +1,22 @@
1
- import { ProfanityWord } from "../types";
2
- import { sexualWords } from "./categories/sexual";
3
- import { insultWords } from "./categories/insult";
4
- // import { profanityWords } from './categories/profanity';
5
- // import { slurWords } from './categories/slur';
6
- // import { drugsWords } from './categories/drugs';
7
- // import { disgustingWords } from './categories/disgusting';
8
- // import { blasphemyWords } from './categories/blasphemy';
1
+ import { ProfanityWord } from '../types';
2
+ import { sexualWords } from './categories/sexual';
3
+ import { insultWords } from './categories/insult';
4
+ import { profanityWords } from './categories/profanity';
5
+ import { slurWords } from './categories/slur';
6
+ import { drugsWords } from './categories/drugs';
7
+ import { disgustingWords } from './categories/disgusting';
8
+ import { blasphemyWords } from './categories/blasphemy';
9
9
 
10
- import { general, generalWords } from "./regions/general";
11
- import { jawa, jawaWords } from "./regions/jawa";
12
- import { sunda, sundaWords } from "./regions/sunda";
13
- import { betawi, betawiWords } from "./regions/betawi";
14
- import { batak, batakWords } from "./regions/batak";
15
- // import { minang, minangWords } from './regions/minang';
16
- // import { bali, baliWords } from './regions/bali';
17
- // import { madura, maduraWords } from './regions/madura';
10
+ import { general, generalWords } from './regions/general';
11
+ import { jawa, jawaWords } from './regions/jawa';
12
+ import { sunda, sundaWords } from './regions/sunda';
13
+ import { betawi, betawiWords } from './regions/betawi';
14
+ import { batak, batakWords } from './regions/batak';
15
+ import { minang, minangWords } from './regions/minang';
16
+ import { bali, baliWords } from './regions/bali';
17
+ import { madura, maduraWords } from './regions/madura';
18
18
  // import { bugis, bugisWords } from './regions/bugis';
19
- // import { aceh, acehWords } from './regions/aceh';
19
+ import { aceh, acehWords } from './regions/aceh';
20
20
  // import { ambon, ambonWords } from './regions/ambon';
21
21
  // import { papua, papuaWords } from './regions/papua';
22
22
  // import { manado, manadoWords } from './regions/manado';
@@ -29,11 +29,11 @@ import { batak, batakWords } from "./regions/batak";
29
29
  export const wordCategories = {
30
30
  sexual: sexualWords,
31
31
  insult: insultWords,
32
- // profanity: profanityWords,
33
- // slur: slurWords,
34
- // drugs: drugsWords,
35
- // disgusting: disgustingWords,
36
- // blasphemy: blasphemyWords,
32
+ profanity: profanityWords,
33
+ slur: slurWords,
34
+ drugs: drugsWords,
35
+ disgusting: disgustingWords,
36
+ blasphemy: blasphemyWords,
37
37
  };
38
38
 
39
39
  export const wordRegions = {
@@ -42,11 +42,11 @@ export const wordRegions = {
42
42
  sunda: sundaWords,
43
43
  betawi: betawiWords,
44
44
  batak: batakWords,
45
- // minang: minangWords,
46
- // bali: baliWords,
47
- // madura: maduraWords,
45
+ minang: minangWords,
46
+ bali: baliWords,
47
+ madura: maduraWords,
48
48
  // bugis: bugisWords,
49
- // aceh: acehWords,
49
+ aceh: acehWords,
50
50
  // ambon: ambonWords,
51
51
  // papua: papuaWords,
52
52
  // manado: manadoWords,
@@ -63,11 +63,11 @@ export const wordObjects: ProfanityWord[] = [
63
63
  ...sunda,
64
64
  ...betawi,
65
65
  ...batak,
66
- // ...minang,
67
- // ...bali,
68
- // ...madura,
66
+ ...minang,
67
+ ...bali,
68
+ ...madura,
69
69
  // ...bugis,
70
- // ...aceh,
70
+ ...aceh,
71
71
  // ...ambon,
72
72
  // ...papua,
73
73
  // ...manado,
@@ -122,10 +122,7 @@ export function getWordMetadata(word: string): ProfanityWord | undefined {
122
122
  return wordObjects.find(
123
123
  (item) =>
124
124
  item.word.toLowerCase() === word.toLowerCase() ||
125
- (item.aliases &&
126
- item.aliases.some(
127
- (alias) => alias.toLowerCase() === word.toLowerCase(),
128
- )),
125
+ (item.aliases && item.aliases.some((alias) => alias.toLowerCase() === word.toLowerCase()))
129
126
  );
130
127
  }
131
128
 
@@ -1,23 +1,18 @@
1
- import {
2
- FilterOptions,
3
- AnalysisResult,
4
- ProfanityCategory,
5
- Region,
6
- } from "../types";
1
+ import { FilterOptions, AnalysisResult, ProfanityCategory, Region } from '../types';
7
2
  import {
8
3
  findProfanity,
9
4
  findProfanityWithMetadata,
10
5
  findCategories,
11
6
  findRegions,
12
7
  calculateSeverity,
13
- } from "./matcher";
14
- import { splitIntoSentences } from "../utils/stringUtils";
8
+ } from './matcher';
9
+ import { splitIntoSentences } from '../utils/stringUtils';
15
10
  import {
16
11
  findPossibleProfanityBySimiliarity,
17
12
  findProfanityByLevenshteinDistance,
18
- } from "../utils/similarityUtils";
19
- import { createContextRegex } from "../utils/regexUtils";
20
- import { DEFAULT_OPTIONS } from "../config/options";
13
+ } from '../utils/similarityUtils';
14
+ import { createContextRegex } from '../utils/regexUtils';
15
+ import { DEFAULT_OPTIONS } from '../config/options';
21
16
 
22
17
  /**
23
18
  * Menganalisis teks untuk kata kotor
@@ -26,10 +21,7 @@ import { DEFAULT_OPTIONS } from "../config/options";
26
21
  * @param options Opsi untuk analisis
27
22
  * @return AnalysisResult dengan hasil analisis
28
23
  */
29
- export function analyze(
30
- text: string,
31
- options: FilterOptions = {},
32
- ): AnalysisResult {
24
+ export function analyze(text: string, options: FilterOptions = {}): AnalysisResult {
33
25
  const mergedOptions = { ...DEFAULT_OPTIONS, ...options };
34
26
 
35
27
  const matches = findProfanity(text, mergedOptions);
@@ -65,7 +57,7 @@ export function analyze(
65
57
  text,
66
58
  wordList,
67
59
  mergedOptions.similarityThreshold || 0.8,
68
- mergedOptions.maxLevenshteinDistance || 2,
60
+ mergedOptions.maxLevenshteinDistance || 2
69
61
  );
70
62
 
71
63
  similarWords = levenshteinResults.map((item) => ({
@@ -77,7 +69,7 @@ export function analyze(
77
69
  similarWords = findPossibleProfanityBySimiliarity(
78
70
  text,
79
71
  wordList,
80
- mergedOptions.similarityThreshold || 0.8,
72
+ mergedOptions.similarityThreshold || 0.8
81
73
  );
82
74
  }
83
75
  }
@@ -103,7 +95,7 @@ export function analyze(
103
95
  */
104
96
  export function batchAnalyze(
105
97
  texts: string[],
106
- options: FilterOptions = {},
98
+ options: FilterOptions = {}
107
99
  ): {
108
100
  totalTexts: number;
109
101
  profaneTexts: number;
@@ -116,10 +108,7 @@ export function batchAnalyze(
116
108
  const mergedOptions = { ...DEFAULT_OPTIONS, ...options };
117
109
  const results = texts.map((text) => analyze(text, mergedOptions));
118
110
  const profaneTexts = results.filter((result) => result.hasProfanity).length;
119
- const totalSeverity = results.reduce(
120
- (sum, result) => sum + result.severityScore,
121
- 0,
122
- );
111
+ const totalSeverity = results.reduce((sum, result) => sum + result.severityScore, 0);
123
112
  const averageSeverity = profaneTexts > 0 ? totalSeverity / profaneTexts : 0;
124
113
  const allCategories = results.flatMap((result) => result.categories);
125
114
  const categoryCount: Record<string, number> = {};
@@ -175,7 +164,7 @@ export function batchAnalyze(
175
164
  */
176
165
  export function analyzeBySentence(
177
166
  text: string,
178
- options: FilterOptions = {},
167
+ options: FilterOptions = {}
179
168
  ): Array<AnalysisResult & { sentence: string }> {
180
169
  const sentences = splitIntoSentences(text);
181
170
  const mergedOptions = { ...DEFAULT_OPTIONS, ...options };
@@ -201,7 +190,7 @@ export function analyzeBySentence(
201
190
  export function analyzeWithContext(
202
191
  text: string,
203
192
  contextWindowSize: number = 5,
204
- options: FilterOptions = {},
193
+ options: FilterOptions = {}
205
194
  ): Array<{
206
195
  word: string;
207
196
  context: string;
@@ -221,9 +210,9 @@ export function analyzeWithContext(
221
210
 
222
211
  let match;
223
212
  while ((match = regex.exec(text)) !== null) {
224
- const beforeContext = match[1] || "";
213
+ const beforeContext = match[1] || '';
225
214
  const wordMatch = match[2];
226
- const afterContext = match[3] || "";
215
+ const afterContext = match[3] || '';
227
216
 
228
217
  result.push({
229
218
  word: wordMatch,
@@ -1,8 +1,8 @@
1
- import { FilterOptions, FilterResult, ProfanityWord } from "../types";
2
- import { findProfanity, findProfanityWithMetadata } from "./matcher";
3
- import { censorWord, escapeRegExp } from "../utils/stringUtils";
4
- import { createWordRegex } from "../utils/regexUtils";
5
- import { DEFAULT_OPTIONS, makeRandomGrawlixString } from "../config/options";
1
+ import { FilterOptions, FilterResult, ProfanityWord } from '../types';
2
+ import { findProfanity, findProfanityWithMetadata } from './matcher';
3
+ import { censorWord, escapeRegExp } from '../utils/stringUtils';
4
+ import { createWordRegex } from '../utils/regexUtils';
5
+ import { DEFAULT_OPTIONS, makeRandomGrawlixString } from '../config/options';
6
6
 
7
7
  interface FindProfanityFunction {
8
8
  (text: string, options?: FilterOptions): string[];
@@ -16,12 +16,9 @@ interface FindProfanityFunction {
16
16
  * @param options Opsi untuk filter
17
17
  * @returns FilterResult dengan hasil filter
18
18
  */
19
- export function filter(
20
- text: string,
21
- options: FilterOptions = {},
22
- ): FilterResult {
19
+ export function filter(text: string, options: FilterOptions = {}): FilterResult {
23
20
  const {
24
- replaceWith = "*",
21
+ replaceWith = '*',
25
22
  fullWordCensor = true,
26
23
  detectLeetSpeak = true,
27
24
  whitelist = [],
@@ -74,10 +71,7 @@ export function filter(
74
71
  const metadata = matchDetails.find(
75
72
  (m) =>
76
73
  m.word.toLowerCase() === word.toLowerCase() ||
77
- (m.aliases &&
78
- m.aliases.some(
79
- (alias) => alias.toLowerCase() === word.toLowerCase(),
80
- )),
74
+ (m.aliases && m.aliases.some((alias) => alias.toLowerCase() === word.toLowerCase()))
81
75
  );
82
76
 
83
77
  const variants = actualMatches.get(word.toLowerCase()) || [];
@@ -86,7 +80,7 @@ export function filter(
86
80
  const uniqueVariants = [...new Set(variants)];
87
81
 
88
82
  uniqueVariants.forEach((variant) => {
89
- const regex = new RegExp(`\\b${escapeRegExp(variant)}\\b`, "gi");
83
+ const regex = new RegExp(`\\b${escapeRegExp(variant)}\\b`, 'gi');
90
84
 
91
85
  let match;
92
86
  while ((match = regex.exec(filteredText)) !== null) {
@@ -98,11 +92,7 @@ export function filter(
98
92
  if (useRandomGrawlix) {
99
93
  censoredWord = makeRandomGrawlixString(originalWord.length);
100
94
  } else {
101
- censoredWord = censorWord(
102
- originalWord,
103
- replaceWith,
104
- !fullWordCensor && keepFirstAndLast,
105
- );
95
+ censoredWord = censorWord(originalWord, replaceWith, !fullWordCensor && keepFirstAndLast);
106
96
  }
107
97
 
108
98
  replacements.push({
@@ -112,8 +102,8 @@ export function filter(
112
102
  });
113
103
 
114
104
  filteredText = filteredText.replace(
115
- new RegExp(`\\b${escapeRegExp(originalWord)}\\b`, "g"),
116
- censoredWord,
105
+ new RegExp(`\\b${escapeRegExp(originalWord)}\\b`, 'g'),
106
+ censoredWord
117
107
  );
118
108
  }
119
109
  });
@@ -141,7 +131,7 @@ export function filter(
141
131
  censoredWord = censorWord(
142
132
  originalWord,
143
133
  replaceWith,
144
- !fullWordCensor && keepFirstAndLast,
134
+ !fullWordCensor && keepFirstAndLast
145
135
  );
146
136
  }
147
137
 
@@ -152,8 +142,8 @@ export function filter(
152
142
  });
153
143
 
154
144
  filteredText = filteredText.replace(
155
- new RegExp(escapeRegExp(originalWord), "g"),
156
- censoredWord,
145
+ new RegExp(escapeRegExp(originalWord), 'g'),
146
+ censoredWord
157
147
  );
158
148
  }
159
149
  }
@@ -180,7 +170,7 @@ export function filter(
180
170
  censoredWord = censorWord(
181
171
  originalWord,
182
172
  replaceWith,
183
- !fullWordCensor && keepFirstAndLast,
173
+ !fullWordCensor && keepFirstAndLast
184
174
  );
185
175
  }
186
176
 
@@ -191,8 +181,8 @@ export function filter(
191
181
  });
192
182
 
193
183
  filteredText = filteredText.replace(
194
- new RegExp(escapeRegExp(originalWord), "g"),
195
- censoredWord,
184
+ new RegExp(escapeRegExp(originalWord), 'g'),
185
+ censoredWord
196
186
  );
197
187
  }
198
188
  }
@@ -204,19 +194,13 @@ export function filter(
204
194
  const metadata = matchDetails.find(
205
195
  (m) =>
206
196
  m.word.toLowerCase() === word.toLowerCase() ||
207
- (m.aliases &&
208
- m.aliases.some(
209
- (alias) => alias.toLowerCase() === word.toLowerCase(),
210
- )),
197
+ (m.aliases && m.aliases.some((alias) => alias.toLowerCase() === word.toLowerCase()))
211
198
  );
212
199
 
213
200
  const variants = actualMatches.get(word.toLowerCase()) || [];
214
201
 
215
202
  variants.forEach((variant) => {
216
- const exactVariantRegex = new RegExp(
217
- `\\b${escapeRegExp(variant)}\\b`,
218
- "gi",
219
- );
203
+ const exactVariantRegex = new RegExp(`\\b${escapeRegExp(variant)}\\b`, 'gi');
220
204
 
221
205
  let match;
222
206
  while ((match = exactVariantRegex.exec(filteredText)) !== null) {
@@ -231,7 +215,7 @@ export function filter(
231
215
  censoredWord = censorWord(
232
216
  originalWord,
233
217
  replaceWith,
234
- !fullWordCensor && keepFirstAndLast,
218
+ !fullWordCensor && keepFirstAndLast
235
219
  );
236
220
  }
237
221
 
@@ -242,8 +226,8 @@ export function filter(
242
226
  });
243
227
 
244
228
  filteredText = filteredText.replace(
245
- new RegExp(`\\b${escapeRegExp(originalWord)}\\b`, "g"),
246
- censoredWord,
229
+ new RegExp(`\\b${escapeRegExp(originalWord)}\\b`, 'g'),
230
+ censoredWord
247
231
  );
248
232
  }
249
233
  });
@@ -1,19 +1,14 @@
1
- import {
2
- ProfanityWord,
3
- ProfanityCategory,
4
- Region,
5
- FilterOptions,
6
- } from "../types";
7
-
8
- import { wordObjects } from "../constants/wordList";
9
- import { normalizeText } from "../utils/stringUtils";
10
- import { createWordRegex } from "../utils/regexUtils";
1
+ import { ProfanityWord, ProfanityCategory, Region, FilterOptions } from '../types';
2
+
3
+ import { wordObjects } from '../constants/wordList';
4
+ import { normalizeText } from '../utils/stringUtils';
5
+ import { createWordRegex } from '../utils/regexUtils';
11
6
  import {
12
7
  findPossibleProfanityBySimiliarity,
13
8
  findProfanityByLevenshteinDistance,
14
- } from "../utils/similarityUtils";
15
- import { DEFAULT_OPTIONS } from "../config/options";
16
- import { AhoCorasick } from "../utils/ahoCorasick";
9
+ } from '../utils/similarityUtils';
10
+ import { DEFAULT_OPTIONS } from '../config/options';
11
+ import { AhoCorasick } from '../utils/ahoCorasick';
17
12
 
18
13
  const globalAhoCorasick = new AhoCorasick();
19
14
  let ahoCorasickInitialized = false;
@@ -34,10 +29,7 @@ interface FindProfanityFunction {
34
29
  lastActualMatches?: Map<string, string[]>;
35
30
  }
36
31
 
37
- export function findProfanity(
38
- text: string,
39
- options: FilterOptions = {},
40
- ): string[] {
32
+ export function findProfanity(text: string, options: FilterOptions = {}): string[] {
41
33
  const {
42
34
  wordList = [],
43
35
  detectLeetSpeak = true,
@@ -60,9 +52,7 @@ export function findProfanity(
60
52
 
61
53
  if (baseWordsToCheck.length === 0) {
62
54
  const filteredWords = wordObjects.filter((word) => {
63
- const matchCategory = categories
64
- ? categories.includes(word.category)
65
- : true;
55
+ const matchCategory = categories ? categories.includes(word.category) : true;
66
56
  const matchRegion = regions ? regions.includes(word.region) : true;
67
57
  const matchSeverity = word.severity >= severityThreshold;
68
58
  return matchCategory && matchRegion && matchSeverity;
@@ -74,9 +64,7 @@ export function findProfanity(
74
64
  const aliasMap = new Map<string, string>();
75
65
  wordObjects.forEach((wordObj) => {
76
66
  if (wordObj.aliases && wordObj.aliases.length > 0) {
77
- const matchCategory = categories
78
- ? categories.includes(wordObj.category)
79
- : true;
67
+ const matchCategory = categories ? categories.includes(wordObj.category) : true;
80
68
  const matchRegion = regions ? regions.includes(wordObj.region) : true;
81
69
  const matchSeverity = wordObj.severity >= severityThreshold;
82
70
 
@@ -88,10 +76,9 @@ export function findProfanity(
88
76
  }
89
77
  });
90
78
 
91
- const wordsToCheck = [
92
- ...baseWordsToCheck,
93
- ...Array.from(aliasMap.keys()),
94
- ].filter((word) => !whitelist.includes(word.toLowerCase()));
79
+ const wordsToCheck = [...baseWordsToCheck, ...Array.from(aliasMap.keys())].filter(
80
+ (word) => !whitelist.includes(word.toLowerCase())
81
+ );
95
82
 
96
83
  if (wordsToCheck.length === 0) {
97
84
  return [];
@@ -104,8 +91,7 @@ export function findProfanity(
104
91
 
105
92
  const basicMatches = globalAhoCorasick.searchUnique(normalizedText);
106
93
  for (const match of basicMatches) {
107
- const originalWord =
108
- aliasMap.get(match.toLowerCase()) || match.toLowerCase();
94
+ const originalWord = aliasMap.get(match.toLowerCase()) || match.toLowerCase();
109
95
  matches.add(originalWord);
110
96
 
111
97
  if (!actualMatches.has(originalWord)) {
@@ -126,8 +112,7 @@ export function findProfanity(
126
112
 
127
113
  let match;
128
114
  while ((match = leetRegex.exec(text)) !== null) {
129
- const originalWord =
130
- aliasMap.get(word.toLowerCase()) || word.toLowerCase();
115
+ const originalWord = aliasMap.get(word.toLowerCase()) || word.toLowerCase();
131
116
  matches.add(originalWord);
132
117
 
133
118
  if (!actualMatches.has(originalWord)) {
@@ -150,8 +135,7 @@ export function findProfanity(
150
135
 
151
136
  let match;
152
137
  while ((match = variantRegex.exec(text)) !== null) {
153
- const originalWord =
154
- aliasMap.get(word.toLowerCase()) || word.toLowerCase();
138
+ const originalWord = aliasMap.get(word.toLowerCase()) || word.toLowerCase();
155
139
  matches.add(originalWord);
156
140
 
157
141
  if (!actualMatches.has(originalWord)) {
@@ -174,8 +158,7 @@ export function findProfanity(
174
158
 
175
159
  let match;
176
160
  while ((match = splitRegex.exec(text)) !== null) {
177
- const originalWord =
178
- aliasMap.get(word.toLowerCase()) || word.toLowerCase();
161
+ const originalWord = aliasMap.get(word.toLowerCase()) || word.toLowerCase();
179
162
  matches.add(originalWord);
180
163
 
181
164
  if (!actualMatches.has(originalWord)) {
@@ -192,13 +175,12 @@ export function findProfanity(
192
175
  text,
193
176
  wordsToCheck,
194
177
  similarityThreshold,
195
- maxLevenshteinDistance,
178
+ maxLevenshteinDistance
196
179
  );
197
180
 
198
181
  possibleProfanity.forEach((item) => {
199
182
  const originalWord =
200
- aliasMap.get(item.original.toLowerCase()) ||
201
- item.original.toLowerCase();
183
+ aliasMap.get(item.original.toLowerCase()) || item.original.toLowerCase();
202
184
  matches.add(originalWord);
203
185
 
204
186
  if (!actualMatches.has(originalWord)) {
@@ -210,15 +192,14 @@ export function findProfanity(
210
192
  const possibleProfanity = findPossibleProfanityBySimiliarity(
211
193
  text,
212
194
  wordsToCheck,
213
- similarityThreshold,
195
+ similarityThreshold
214
196
  );
215
197
 
216
198
  possibleProfanity.forEach((item) => {
217
199
  matches.add(item.original.toLowerCase());
218
200
 
219
201
  const originalWord =
220
- aliasMap.get(item.original.toLowerCase()) ||
221
- item.original.toLowerCase();
202
+ aliasMap.get(item.original.toLowerCase()) || item.original.toLowerCase();
222
203
  if (!actualMatches.has(originalWord)) {
223
204
  actualMatches.set(originalWord, []);
224
205
  }
@@ -241,7 +222,7 @@ export function findProfanity(
241
222
  */
242
223
  export function findProfanityWithMetadata(
243
224
  text: string,
244
- options: FilterOptions = {},
225
+ options: FilterOptions = {}
245
226
  ): ProfanityWord[] {
246
227
  const matches = findProfanity(text, options);
247
228
  if (matches.length === 0) {
@@ -253,10 +234,7 @@ export function findProfanityWithMetadata(
253
234
  const wordObject = wordObjects.find(
254
235
  (obj) =>
255
236
  obj.word.toLowerCase() === word.toLowerCase() ||
256
- (obj.aliases &&
257
- obj.aliases.some(
258
- (alias) => alias.toLowerCase() === word.toLowerCase(),
259
- )),
237
+ (obj.aliases && obj.aliases.some((alias) => alias.toLowerCase() === word.toLowerCase()))
260
238
  );
261
239
 
262
240
  return wordObject;
@@ -270,9 +248,7 @@ export function findProfanityWithMetadata(
270
248
  * @param matchDetails Hasil pencarian dari fingProfanityWithMetadata()
271
249
  * @return Array kategori unik
272
250
  */
273
- export function findCategories(
274
- matchDetails: ProfanityWord[],
275
- ): ProfanityCategory[] {
251
+ export function findCategories(matchDetails: ProfanityWord[]): ProfanityCategory[] {
276
252
  const categories = new Set<ProfanityCategory>();
277
253
 
278
254
  matchDetails.forEach((word) => {
package/src/index.ts CHANGED
@@ -8,12 +8,7 @@ export * from './utils/similarityUtils';
8
8
  export * from './config/options';
9
9
 
10
10
  import { filter, isProfane } from './core/filter';
11
- import {
12
- analyze,
13
- batchAnalyze,
14
- analyzeBySentence,
15
- analyzeWithContext,
16
- } from './core/analyzer';
11
+ import { analyze, batchAnalyze, analyzeBySentence, analyzeWithContext } from './core/analyzer';
17
12
  import { FilterOptions, FilterResult, AnalysisResult } from './types';
18
13
  import {
19
14
  DEFAULT_OPTIONS,
@@ -105,10 +100,7 @@ export class IDProfanityFilter {
105
100
  * @param presetName Nama preset yang akan digunakan
106
101
  * @param additionalOptions Opsi tambahan untuk override
107
102
  */
108
- usePreset(
109
- presetName: string,
110
- additionalOptions: Partial<FilterOptions> = {},
111
- ) {
103
+ usePreset(presetName: string, additionalOptions: Partial<FilterOptions> = {}) {
112
104
  this.options = getPresetOptions(presetName, additionalOptions);
113
105
  }
114
106
 
@@ -125,10 +117,7 @@ export class IDProfanityFilter {
125
117
  * @param word Kata yang akan diabaikan
126
118
  */
127
119
  addToWhitelist(word: string) {
128
- this.options.whitelist = [
129
- ...(this.options.whitelist || []),
130
- word.toLowerCase(),
131
- ];
120
+ this.options.whitelist = [...(this.options.whitelist || []), word.toLowerCase()];
132
121
  }
133
122
 
134
123
  /**
@@ -139,7 +128,7 @@ export class IDProfanityFilter {
139
128
  if (!this.options.whitelist) return;
140
129
 
141
130
  this.options.whitelist = this.options.whitelist.filter(
142
- (w) => w.toLowerCase() !== word.toLowerCase(),
131
+ (w) => w.toLowerCase() !== word.toLowerCase()
143
132
  );
144
133
  }
145
134
 
@@ -166,7 +155,7 @@ export class IDProfanityFilter {
166
155
  enableSimilarityDetection(
167
156
  threshold: number = 0.8,
168
157
  useLevenshtein: boolean = false,
169
- maxLevenshteinDistance: number = 2,
158
+ maxLevenshteinDistance: number = 2
170
159
  ) {
171
160
  this.options.detectSimilarity = true;
172
161
  this.options.similarityThreshold = threshold;
@@ -1,31 +1,32 @@
1
1
  export type ProfanityCategory =
2
- | "sexual"
3
- | "insult"
4
- | "profanity"
5
- | "slur"
6
- | "drugs"
7
- | "disgusting"
8
- | "blasphemy";
2
+ | 'sexual'
3
+ | 'insult'
4
+ | 'profanity'
5
+ | 'slur'
6
+ | 'drugs'
7
+ | 'disgusting'
8
+ | 'blasphemy';
9
9
 
10
10
  export type Region =
11
- | "general"
12
- | "jawa"
13
- | "sunda"
14
- | "betawi"
15
- | "batak"
16
- | "minang"
17
- | "bali"
18
- | "madura"
19
- | "bugis"
20
- | "aceh"
21
- | "ambon"
22
- | "papua"
23
- | "manado"
24
- | "banjar"
25
- | "palembang"
26
- | "lampung"
27
- | "ntt"
28
- | "ntb";
11
+ | 'general'
12
+ | 'jawa'
13
+ | 'sunda'
14
+ | 'betawi'
15
+ | 'batak'
16
+ | 'minang'
17
+ | 'bali'
18
+ | 'madura'
19
+ | 'bugis'
20
+ | 'aceh'
21
+ | 'ambon'
22
+ | 'papua'
23
+ | 'manado'
24
+ | 'banjar'
25
+ | 'palembang'
26
+ | 'lampung'
27
+ | 'ntt'
28
+ | 'mandailing'
29
+ | 'ntb';
29
30
 
30
31
  export interface ProfanityWord {
31
32
  word: string;
@@ -30,7 +30,7 @@ export class AhoCorasick {
30
30
  */
31
31
  addPattern(pattern: string): void {
32
32
  if (this.built) {
33
- throw new Error("Cannot add patterns after the automaton is built");
33
+ throw new Error('Cannot add patterns after the automaton is built');
34
34
  }
35
35
 
36
36
  let node = this.root;