glin-profanity 2.3.5 → 2.3.7

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/dist/index.cjs CHANGED
@@ -2229,6 +2229,7 @@ var require_react = __commonJS({
2229
2229
  var index_exports = {};
2230
2230
  __export(index_exports, {
2231
2231
  Filter: () => Filter,
2232
+ ProfanityFilter: () => Filter,
2232
2233
  SeverityLevel: () => SeverityLevel,
2233
2234
  checkProfanity: () => checkProfanity,
2234
2235
  checkProfanityAsync: () => checkProfanityAsync,
@@ -5133,19 +5134,7 @@ var ContextAnalyzer = class {
5133
5134
  isWhitelisted: false
5134
5135
  };
5135
5136
  }
5136
- tokenize(text) {
5137
- return text.toLowerCase().replace(/[^\w\s]/g, " ").split(/\s+/).filter((word) => word.length > 0);
5138
- }
5139
- findWordIndex(words, charIndex) {
5140
- let currentPos = 0;
5141
- for (let i = 0; i < words.length; i++) {
5142
- if (currentPos >= charIndex) {
5143
- return Math.max(0, i - 1);
5144
- }
5145
- currentPos += words[i].length + 1;
5146
- }
5147
- return words.length - 1;
5148
- }
5137
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
5149
5138
  checkPhraseContext(contextText, matchWord) {
5150
5139
  for (const [phrase, score] of POSITIVE_PHRASES.entries()) {
5151
5140
  if (contextText.includes(phrase)) {
@@ -5167,6 +5156,7 @@ var ContextAnalyzer = class {
5167
5156
  }
5168
5157
  return null;
5169
5158
  }
5159
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
5170
5160
  isDomainWhitelisted(contextWords, matchWord) {
5171
5161
  for (const word of contextWords) {
5172
5162
  if (this.domainWhitelists.has(word) || GAMING_POSITIVE.has(word)) {
@@ -5175,10 +5165,33 @@ var ContextAnalyzer = class {
5175
5165
  }
5176
5166
  return false;
5177
5167
  }
5168
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
5169
+ generateReason(score, contextWords) {
5170
+ if (score >= 0.7) {
5171
+ return "Positive context detected - likely not profanity";
5172
+ } else if (score <= 0.3) {
5173
+ return "Negative context detected - likely profanity";
5174
+ } else {
5175
+ return "Neutral context - uncertain classification";
5176
+ }
5177
+ }
5178
+ tokenize(text) {
5179
+ return text.toLowerCase().replace(/[^\w\s]/g, " ").split(/\s+/).filter((word) => word.length > 0);
5180
+ }
5181
+ findWordIndex(words, charIndex) {
5182
+ let currentPos = 0;
5183
+ for (let i = 0; i < words.length; i++) {
5184
+ if (currentPos >= charIndex) {
5185
+ return Math.max(0, i - 1);
5186
+ }
5187
+ currentPos += words[i].length + 1;
5188
+ }
5189
+ return words.length - 1;
5190
+ }
5178
5191
  calculateSentimentScore(contextWords, matchPosition) {
5179
5192
  let positiveCount = 0;
5180
5193
  let negativeCount = 0;
5181
- let totalWords = contextWords.length;
5194
+ const totalWords = contextWords.length;
5182
5195
  for (let i = 0; i < contextWords.length; i++) {
5183
5196
  const word = contextWords[i];
5184
5197
  const distance = Math.abs(i - matchPosition);
@@ -5195,6 +5208,8 @@ var ContextAnalyzer = class {
5195
5208
  }
5196
5209
  const rawScore = positiveCount / totalSentiment;
5197
5210
  let adjustedScore = rawScore;
5211
+ const confidenceMultiplier = Math.min(1, totalWords / 5);
5212
+ adjustedScore = 0.5 + (adjustedScore - 0.5) * confidenceMultiplier;
5198
5213
  const hasPersonalPronouns = contextWords.some(
5199
5214
  (word) => ["you", "your", "u", "ur"].includes(word)
5200
5215
  );
@@ -5209,15 +5224,6 @@ var ContextAnalyzer = class {
5209
5224
  }
5210
5225
  return Math.max(0, Math.min(1, adjustedScore));
5211
5226
  }
5212
- generateReason(score, contextWords) {
5213
- if (score >= 0.7) {
5214
- return "Positive context detected - likely not profanity";
5215
- } else if (score <= 0.3) {
5216
- return "Negative context detected - likely profanity";
5217
- } else {
5218
- return "Neutral context - uncertain classification";
5219
- }
5220
- }
5221
5227
  /**
5222
5228
  * Updates the domain whitelist for this analyzer instance
5223
5229
  */
@@ -5261,7 +5267,7 @@ var Filter = class {
5261
5267
  this.fuzzyToleranceLevel = (_l = config == null ? void 0 : config.fuzzyToleranceLevel) != null ? _l : 0.8;
5262
5268
  if (config == null ? void 0 : config.allLanguages) {
5263
5269
  for (const lang in dictionary_default) {
5264
- if (dictionary_default.hasOwnProperty(lang)) {
5270
+ if (Object.prototype.hasOwnProperty.call(dictionary_default, lang)) {
5265
5271
  words = [...words, ...dictionary_default[lang]];
5266
5272
  }
5267
5273
  }
@@ -5324,7 +5330,7 @@ var Filter = class {
5324
5330
  return void 0;
5325
5331
  }
5326
5332
  isProfane(value) {
5327
- let input = this.allowObfuscatedMatch ? this.normalizeObfuscated(value) : value;
5333
+ const input = this.allowObfuscatedMatch ? this.normalizeObfuscated(value) : value;
5328
5334
  for (const word of this.words.keys()) {
5329
5335
  if (!this.ignoreWords.has(word.toLowerCase()) && this.evaluateSeverity(word, input) !== void 0) {
5330
5336
  return true;
@@ -5558,6 +5564,7 @@ var useProfanityChecker = (config) => {
5558
5564
  // Annotate the CommonJS export names for ESM import in node:
5559
5565
  0 && (module.exports = {
5560
5566
  Filter,
5567
+ ProfanityFilter,
5561
5568
  SeverityLevel,
5562
5569
  checkProfanity,
5563
5570
  checkProfanityAsync,
package/dist/index.d.cts CHANGED
@@ -55,6 +55,36 @@ interface FilteredProfanityResult {
55
55
  filteredWords: string[];
56
56
  }
57
57
 
58
+ declare class Filter {
59
+ private words;
60
+ private caseSensitive;
61
+ private wordBoundaries;
62
+ private replaceWith?;
63
+ private severityLevels;
64
+ private ignoreWords;
65
+ private logProfanity;
66
+ private allowObfuscatedMatch;
67
+ private fuzzyToleranceLevel;
68
+ private enableContextAware;
69
+ private contextWindow;
70
+ private confidenceThreshold;
71
+ private contextAnalyzer?;
72
+ private primaryLanguage;
73
+ constructor(config?: FilterConfig);
74
+ private debugLog;
75
+ private normalizeObfuscated;
76
+ private getRegex;
77
+ private isFuzzyToleranceMatch;
78
+ private evaluateSeverity;
79
+ isProfane(value: string): boolean;
80
+ matches(word: string): boolean;
81
+ checkProfanity(text: string): CheckProfanityResult;
82
+ checkProfanityWithMinSeverity(text: string, minSeverity?: SeverityLevel): {
83
+ filteredWords: string[];
84
+ result: CheckProfanityResult;
85
+ };
86
+ }
87
+
58
88
  interface ProfanityCheckerConfig {
59
89
  languages?: Language[];
60
90
  allLanguages?: boolean;
@@ -87,34 +117,4 @@ declare const useProfanityChecker: (config?: ProfanityCheckerConfig) => {
87
117
  isWordProfane: (word: string) => boolean;
88
118
  };
89
119
 
90
- declare class Filter {
91
- private words;
92
- private caseSensitive;
93
- private wordBoundaries;
94
- private replaceWith?;
95
- private severityLevels;
96
- private ignoreWords;
97
- private logProfanity;
98
- private allowObfuscatedMatch;
99
- private fuzzyToleranceLevel;
100
- private enableContextAware;
101
- private contextWindow;
102
- private confidenceThreshold;
103
- private contextAnalyzer?;
104
- private primaryLanguage;
105
- constructor(config?: FilterConfig);
106
- private debugLog;
107
- private normalizeObfuscated;
108
- private getRegex;
109
- private isFuzzyToleranceMatch;
110
- private evaluateSeverity;
111
- isProfane(value: string): boolean;
112
- matches(word: string): boolean;
113
- checkProfanity(text: string): CheckProfanityResult;
114
- checkProfanityWithMinSeverity(text: string, minSeverity?: SeverityLevel): {
115
- filteredWords: string[];
116
- result: CheckProfanityResult;
117
- };
118
- }
119
-
120
- export { type CheckProfanityResult, type ContextAwareConfig, Filter, type FilterConfig, type FilteredProfanityResult, type Language, type Match, type ProfanityCheckResult, type ProfanityCheckerConfig, SeverityLevel, checkProfanity, checkProfanityAsync, isWordProfane, useProfanityChecker };
120
+ export { type CheckProfanityResult, type ContextAwareConfig, Filter, type FilterConfig, type FilteredProfanityResult, type Language, type Match, type ProfanityCheckResult, type ProfanityCheckerConfig, Filter as ProfanityFilter, SeverityLevel, checkProfanity, checkProfanityAsync, isWordProfane, useProfanityChecker };
package/dist/index.d.ts CHANGED
@@ -55,6 +55,36 @@ interface FilteredProfanityResult {
55
55
  filteredWords: string[];
56
56
  }
57
57
 
58
+ declare class Filter {
59
+ private words;
60
+ private caseSensitive;
61
+ private wordBoundaries;
62
+ private replaceWith?;
63
+ private severityLevels;
64
+ private ignoreWords;
65
+ private logProfanity;
66
+ private allowObfuscatedMatch;
67
+ private fuzzyToleranceLevel;
68
+ private enableContextAware;
69
+ private contextWindow;
70
+ private confidenceThreshold;
71
+ private contextAnalyzer?;
72
+ private primaryLanguage;
73
+ constructor(config?: FilterConfig);
74
+ private debugLog;
75
+ private normalizeObfuscated;
76
+ private getRegex;
77
+ private isFuzzyToleranceMatch;
78
+ private evaluateSeverity;
79
+ isProfane(value: string): boolean;
80
+ matches(word: string): boolean;
81
+ checkProfanity(text: string): CheckProfanityResult;
82
+ checkProfanityWithMinSeverity(text: string, minSeverity?: SeverityLevel): {
83
+ filteredWords: string[];
84
+ result: CheckProfanityResult;
85
+ };
86
+ }
87
+
58
88
  interface ProfanityCheckerConfig {
59
89
  languages?: Language[];
60
90
  allLanguages?: boolean;
@@ -87,34 +117,4 @@ declare const useProfanityChecker: (config?: ProfanityCheckerConfig) => {
87
117
  isWordProfane: (word: string) => boolean;
88
118
  };
89
119
 
90
- declare class Filter {
91
- private words;
92
- private caseSensitive;
93
- private wordBoundaries;
94
- private replaceWith?;
95
- private severityLevels;
96
- private ignoreWords;
97
- private logProfanity;
98
- private allowObfuscatedMatch;
99
- private fuzzyToleranceLevel;
100
- private enableContextAware;
101
- private contextWindow;
102
- private confidenceThreshold;
103
- private contextAnalyzer?;
104
- private primaryLanguage;
105
- constructor(config?: FilterConfig);
106
- private debugLog;
107
- private normalizeObfuscated;
108
- private getRegex;
109
- private isFuzzyToleranceMatch;
110
- private evaluateSeverity;
111
- isProfane(value: string): boolean;
112
- matches(word: string): boolean;
113
- checkProfanity(text: string): CheckProfanityResult;
114
- checkProfanityWithMinSeverity(text: string, minSeverity?: SeverityLevel): {
115
- filteredWords: string[];
116
- result: CheckProfanityResult;
117
- };
118
- }
119
-
120
- export { type CheckProfanityResult, type ContextAwareConfig, Filter, type FilterConfig, type FilteredProfanityResult, type Language, type Match, type ProfanityCheckResult, type ProfanityCheckerConfig, SeverityLevel, checkProfanity, checkProfanityAsync, isWordProfane, useProfanityChecker };
120
+ export { type CheckProfanityResult, type ContextAwareConfig, Filter, type FilterConfig, type FilteredProfanityResult, type Language, type Match, type ProfanityCheckResult, type ProfanityCheckerConfig, Filter as ProfanityFilter, SeverityLevel, checkProfanity, checkProfanityAsync, isWordProfane, useProfanityChecker };
package/dist/index.js CHANGED
@@ -5116,19 +5116,7 @@ var ContextAnalyzer = class {
5116
5116
  isWhitelisted: false
5117
5117
  };
5118
5118
  }
5119
- tokenize(text) {
5120
- return text.toLowerCase().replace(/[^\w\s]/g, " ").split(/\s+/).filter((word) => word.length > 0);
5121
- }
5122
- findWordIndex(words, charIndex) {
5123
- let currentPos = 0;
5124
- for (let i = 0; i < words.length; i++) {
5125
- if (currentPos >= charIndex) {
5126
- return Math.max(0, i - 1);
5127
- }
5128
- currentPos += words[i].length + 1;
5129
- }
5130
- return words.length - 1;
5131
- }
5119
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
5132
5120
  checkPhraseContext(contextText, matchWord) {
5133
5121
  for (const [phrase, score] of POSITIVE_PHRASES.entries()) {
5134
5122
  if (contextText.includes(phrase)) {
@@ -5150,6 +5138,7 @@ var ContextAnalyzer = class {
5150
5138
  }
5151
5139
  return null;
5152
5140
  }
5141
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
5153
5142
  isDomainWhitelisted(contextWords, matchWord) {
5154
5143
  for (const word of contextWords) {
5155
5144
  if (this.domainWhitelists.has(word) || GAMING_POSITIVE.has(word)) {
@@ -5158,10 +5147,33 @@ var ContextAnalyzer = class {
5158
5147
  }
5159
5148
  return false;
5160
5149
  }
5150
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
5151
+ generateReason(score, contextWords) {
5152
+ if (score >= 0.7) {
5153
+ return "Positive context detected - likely not profanity";
5154
+ } else if (score <= 0.3) {
5155
+ return "Negative context detected - likely profanity";
5156
+ } else {
5157
+ return "Neutral context - uncertain classification";
5158
+ }
5159
+ }
5160
+ tokenize(text) {
5161
+ return text.toLowerCase().replace(/[^\w\s]/g, " ").split(/\s+/).filter((word) => word.length > 0);
5162
+ }
5163
+ findWordIndex(words, charIndex) {
5164
+ let currentPos = 0;
5165
+ for (let i = 0; i < words.length; i++) {
5166
+ if (currentPos >= charIndex) {
5167
+ return Math.max(0, i - 1);
5168
+ }
5169
+ currentPos += words[i].length + 1;
5170
+ }
5171
+ return words.length - 1;
5172
+ }
5161
5173
  calculateSentimentScore(contextWords, matchPosition) {
5162
5174
  let positiveCount = 0;
5163
5175
  let negativeCount = 0;
5164
- let totalWords = contextWords.length;
5176
+ const totalWords = contextWords.length;
5165
5177
  for (let i = 0; i < contextWords.length; i++) {
5166
5178
  const word = contextWords[i];
5167
5179
  const distance = Math.abs(i - matchPosition);
@@ -5178,6 +5190,8 @@ var ContextAnalyzer = class {
5178
5190
  }
5179
5191
  const rawScore = positiveCount / totalSentiment;
5180
5192
  let adjustedScore = rawScore;
5193
+ const confidenceMultiplier = Math.min(1, totalWords / 5);
5194
+ adjustedScore = 0.5 + (adjustedScore - 0.5) * confidenceMultiplier;
5181
5195
  const hasPersonalPronouns = contextWords.some(
5182
5196
  (word) => ["you", "your", "u", "ur"].includes(word)
5183
5197
  );
@@ -5192,15 +5206,6 @@ var ContextAnalyzer = class {
5192
5206
  }
5193
5207
  return Math.max(0, Math.min(1, adjustedScore));
5194
5208
  }
5195
- generateReason(score, contextWords) {
5196
- if (score >= 0.7) {
5197
- return "Positive context detected - likely not profanity";
5198
- } else if (score <= 0.3) {
5199
- return "Negative context detected - likely profanity";
5200
- } else {
5201
- return "Neutral context - uncertain classification";
5202
- }
5203
- }
5204
5209
  /**
5205
5210
  * Updates the domain whitelist for this analyzer instance
5206
5211
  */
@@ -5244,7 +5249,7 @@ var Filter = class {
5244
5249
  this.fuzzyToleranceLevel = (_l = config == null ? void 0 : config.fuzzyToleranceLevel) != null ? _l : 0.8;
5245
5250
  if (config == null ? void 0 : config.allLanguages) {
5246
5251
  for (const lang in dictionary_default) {
5247
- if (dictionary_default.hasOwnProperty(lang)) {
5252
+ if (Object.prototype.hasOwnProperty.call(dictionary_default, lang)) {
5248
5253
  words = [...words, ...dictionary_default[lang]];
5249
5254
  }
5250
5255
  }
@@ -5307,7 +5312,7 @@ var Filter = class {
5307
5312
  return void 0;
5308
5313
  }
5309
5314
  isProfane(value) {
5310
- let input = this.allowObfuscatedMatch ? this.normalizeObfuscated(value) : value;
5315
+ const input = this.allowObfuscatedMatch ? this.normalizeObfuscated(value) : value;
5311
5316
  for (const word of this.words.keys()) {
5312
5317
  if (!this.ignoreWords.has(word.toLowerCase()) && this.evaluateSeverity(word, input) !== void 0) {
5313
5318
  return true;
@@ -5540,6 +5545,7 @@ var useProfanityChecker = (config) => {
5540
5545
  };
5541
5546
  export {
5542
5547
  Filter,
5548
+ Filter as ProfanityFilter,
5543
5549
  SeverityLevel,
5544
5550
  checkProfanity,
5545
5551
  checkProfanityAsync,
package/package.json CHANGED
@@ -1,20 +1,20 @@
1
1
  {
2
2
  "name": "glin-profanity",
3
- "version": "2.3.5",
3
+ "version": "2.3.7",
4
4
  "description": "Glin-Profanity is a lightweight and efficient npm package designed to detect and filter profane language in text inputs across multiple languages. Whether you’re building a chat application, a comment section, or any platform where user-generated content is involved, Glin-Profanity helps you maintain a clean and respectful environment.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
- "module": "dist/index.mjs",
7
+ "module": "dist/index.js",
8
8
  "types": "dist/index.d.ts",
9
9
  "exports": {
10
10
  ".": {
11
11
  "require": {
12
- "types": "./dist/index.d.ts",
13
- "default": "./dist/index.js"
12
+ "types": "./dist/index.d.cts",
13
+ "default": "./dist/index.cjs"
14
14
  },
15
15
  "import": {
16
16
  "types": "./dist/index.d.ts",
17
- "default": "./dist/index.mjs"
17
+ "default": "./dist/index.js"
18
18
  }
19
19
  }
20
20
  },
@@ -28,6 +28,9 @@
28
28
  "test:watch": "jest --watch",
29
29
  "test:coverage": "jest --coverage",
30
30
  "test:ci": "jest --ci --coverage --watchAll=false",
31
+ "typecheck": "tsc --noEmit",
32
+ "lint": "eslint src/**/*.ts",
33
+ "lint:fix": "eslint src/**/*.ts --fix",
31
34
  "semantic-release": "semantic-release"
32
35
  },
33
36
  "repository": {
@@ -83,6 +86,7 @@
83
86
  "@semantic-release/git": "^10.0.1",
84
87
  "@semantic-release/github": "^11.0.3",
85
88
  "@semantic-release/npm": "^12.0.2",
89
+ "@testing-library/dom": "^10.4.1",
86
90
  "@testing-library/jest-dom": "^6.6.4",
87
91
  "@testing-library/react": "^16.3.0",
88
92
  "@types/jest": "^30.0.0",