glin-profanity 3.1.2 → 3.2.0

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/README.md CHANGED
@@ -1,630 +1,148 @@
1
1
  <p align="center">
2
2
  <a href="https://www.glincker.com/tools/glin-profanity" target="_blank">
3
- <img src="../../assets/glinr-logo.png" alt="Glin Profanity" width="40" />
3
+ <img src="../../og-image.png" alt="Glin Profanity - ML-Powered Profanity Detection" width="800" />
4
4
  </a>
5
5
  </p>
6
6
 
7
- <h1 align="center">GLIN PROFANITY</h1>
7
+ <h1 align="center">GLIN PROFANITY - JavaScript/TypeScript</h1>
8
8
 
9
9
  <p align="center">
10
- <strong>A multilingual profanity detection and filtering engine for modern applications — by <a href="https://glincker.com">GLINCKER</a></strong>
11
- </p>
12
- <p align="center">
13
- <a href="https://www.glincker.com/tools/glin-profanity">
14
- <img src="https://img.shields.io/badge/🚀%20Try%20Live%20Demo-online-blue" alt="Try Live Demo" />
15
- </a>
10
+ <strong>ML-Powered Profanity Detection for the Modern Web</strong>
16
11
  </p>
17
12
 
18
13
  <p align="center">
19
- <a href="https://www.npmjs.com/package/glin-profanity">
20
- <img src="https://img.shields.io/npm/v/glin-profanity" alt="NPM Version" />
21
- </a>
22
- <a href="https://github.com/GLINCKER/glin-profanity/blob/main/LICENSE">
23
- <img src="https://img.shields.io/badge/license-MIT-green" alt="MIT License" />
24
- </a>
25
- <a href="https://github.com/GLINCKER/glin-profanity/actions">
26
- <img src="https://img.shields.io/github/actions/workflow/status/GLINCKER/glin-profanity/ci.yml" alt="CI Status" />
27
- </a>
28
- <a href="https://www.npmjs.com/package/glin-profanity">
29
- <img src="https://img.shields.io/npm/dw/glin-profanity" alt="Weekly Downloads" />
30
- </a>
31
- <a href="https://pepy.tech/projects/glin-profanity">
32
- <img src="https://static.pepy.tech/personalized-badge/glin-profanity?period=total&units=international_system&left_color=black&right_color=green&left_text=Python%20Downloads" alt="PyPI Downloads" />
33
- </a>
34
- <a href="https://github.com/GLINCKER/glin-profanity/issues">
35
- <img src="https://img.shields.io/github/issues/GLINCKER/glin-profanity" alt="Open Issues" />
36
- </a>
37
- <a href="https://github.com/GLINCKER/glin-profanity/pulls">
38
- <img src="https://img.shields.io/github/issues-pr/GLINCKER/glin-profanity" alt="Open PRs" />
39
- </a>
40
- <a href="https://github.com/GLINCKER/glin-profanity/commits/main">
41
- <img src="https://img.shields.io/github/last-commit/GLINCKER/glin-profanity" alt="Last Commit" />
42
- </a>
43
- <a href="https://github.com/GLINCKER/glin-profanity/stargazers">
44
- <img src="https://img.shields.io/github/stars/GLINCKER/glin-profanity" alt="GitHub Stars" />
45
- </a>
46
- <a href="https://github.com/GLINCKER/glin-profanity/network/members">
47
- <img src="https://img.shields.io/github/forks/GLINCKER/glin-profanity" alt="GitHub Forks" />
48
- </a>
49
- <a href="https://github.com/GLINCKER/glin-profanity/graphs/contributors">
50
- <img src="https://img.shields.io/github/contributors/GLINCKER/glin-profanity" alt="Contributors" />
51
- </a>
52
- <a href="#-table-of-contents">
53
- <img src="https://img.shields.io/badge/-Table%20of%20Contents-blue" alt="Table Of Contents" />
54
- </a>
14
+ <a href="https://www.npmjs.com/package/glin-profanity"><img src="https://img.shields.io/npm/v/glin-profanity" alt="NPM" /></a>
15
+ <a href="https://github.com/GLINCKER/glin-profanity/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-green" alt="MIT" /></a>
16
+ <a href="https://www.npmjs.com/package/glin-profanity"><img src="https://img.shields.io/npm/dw/glin-profanity" alt="Downloads" /></a>
17
+ <a href="https://www.glincker.com/tools/glin-profanity"><img src="https://img.shields.io/badge/Live_Demo-online-blue" alt="Demo" /></a>
55
18
  </p>
56
19
 
57
20
  ---
58
21
 
59
-
60
- > A multilingual profanity detection and filtering engine for modern applications — by [GLINCKER](https://glincker.com)
61
-
62
- [![Glin Profanity Preview](../../assets/glin-profanity-preview.png)](https://www.glincker.com/tools/glin-profanity)
63
-
64
- ---
65
-
66
- ## ✨ Overview
67
-
68
- **Glin-Profanity** is a high-performance JavaScript/TypeScript library built to detect, filter, and sanitize profane or harmful language in user-generated content. With support for over 20+ languages, configurable severity levels, obfuscation detection, and framework-agnostic design, it's perfect for developers who care about building safe, inclusive platforms.
69
-
70
- Whether you're moderating chat messages, community forums, or content input forms, Glin-Profanity empowers you to:
71
-
72
- - 🧼 Filter text with real-time or batch processing
73
- - 🗣️ Detect offensive terms in **20+ human languages**
74
- - 💬 Catch obfuscated profanity like `sh1t`, `f*ck`, `a$$hole`
75
- - 🎚️ Adjust severity thresholds (`Exact`, `Fuzzy`, `Merged`)
76
- - 🔁 Replace bad words with symbols or emojis
77
- - 🧩 Works in **any JavaScript environment** - <img src="https://img.shields.io/badge/Node.js-339933?style=flat&logo=nodedotjs&logoColor=white" alt="Node.js" height="16" /> <img src="https://img.shields.io/badge/React-20232A?style=flat&logo=react&logoColor=61DAFB" alt="React" height="16" /> <img src="https://img.shields.io/badge/Vue-35495E?style=flat&logo=vuedotjs&logoColor=4FC08D" alt="Vue" height="16" /> <img src="https://img.shields.io/badge/Angular-DD0031?style=flat&logo=angular&logoColor=white" alt="Angular" height="16" /> <img src="https://img.shields.io/badge/TypeScript-007ACC?style=flat&logo=typescript&logoColor=white" alt="TypeScript" height="16" />
78
- - 🛡️ Add custom word lists or ignore specific terms
79
-
80
- ## 🚀 Key Features
81
-
82
- <div align="center">
83
- <img src="https://img.shields.io/badge/Multi--Language-🌍-blue?style=for-the-badge" alt="Multi-Language" />
84
- <img src="https://img.shields.io/badge/Real--Time-⚡-yellow?style=for-the-badge" alt="Real-Time" />
85
- <img src="https://img.shields.io/badge/Obfuscation_Detection-🕵️-purple?style=for-the-badge" alt="Obfuscation" />
86
- <img src="https://img.shields.io/badge/Framework_Agnostic-🧩-green?style=for-the-badge" alt="Framework Agnostic" />
87
- <img src="https://img.shields.io/badge/ML_Powered-🤖-orange?style=for-the-badge" alt="ML Powered" />
88
- </div>
89
-
90
- ### 💡 Why glin-profanity?
91
-
92
- | | |
93
- |---|---|
94
- | 🔒 **Privacy First** | Runs entirely on-device. No API calls, no data leaves your app. GDPR/CCPA friendly. |
95
- | ⚡ **Blazing Fast** | 23K-115K ops/sec rule-based, 21M+ ops/sec with caching. Sub-millisecond latency. |
96
- | 🌍 **Truly Multilingual** | 23 languages with unified dictionary. Consistent detection across locales. |
97
- | 🛡️ **Evasion Resistant** | Catches leetspeak (`f4ck`), Unicode tricks (`fυck`), zero-width chars, and homoglyphs. |
98
- | 🤖 **AI-Ready** | Optional ML integration for context-aware toxicity detection beyond keywords. |
99
- | 🧩 **Zero Config** | Works out of the box. No API keys, no server, no setup required. |
100
- | 📦 **Lightweight** | ~90KB core bundle. Tree-shakeable. No heavy dependencies for basic usage. |
101
-
102
- ### ✨ What's New in v3.0
103
-
104
- - **Leetspeak Detection** — Catch `f4ck`, `@ss`, `$h!t` with 3 intensity levels
105
- - **Unicode Normalization** — Detect Cyrillic/Greek lookalikes, full-width chars, zero-width spaces
106
- - **Result Caching** — 800x speedup for repeated checks
107
- - **ML Integration** — Optional TensorFlow.js toxicity model for nuanced detection
108
- - **Performance** — Optimized for high-throughput production workloads
109
-
110
- ## 📚 Table of Contents
111
-
112
- - [🚀 Key Features](#-key-features)
113
- - [📦 Installation](#installation)
114
- - [🌍 Supported Languages](#supported-languages)
115
- - [⚙️ Usage](#usage)
116
- - [Basic Usage](#basic-usage)
117
- - [Framework Examples](#framework-examples)
118
- - [🧠 API](#api)
119
- - [Core Functions](#core-functions)
120
- - [Filter Class](#filter-class)
121
- - [Constructor](#constructor)
122
- - [FilterConfig Options](#filterconfig-options)
123
- - [Methods](#methods)
124
- - [isProfane](#isprofane)
125
- - [checkProfanity](#checkprofanity)
126
- - [useProfanityChecker Hook](#useprofanitychecker-hook)
127
- - [Parameters](#parameters)
128
- - [Return Value](#return-value)
129
- - [⚠️ Note](#note)
130
- - [🛠 Use Cases](#-use-cases)
131
- - [🔬 Advanced Features](#-advanced-features)
132
- - [Leetspeak Detection](#leetspeak-detection)
133
- - [Unicode Normalization](#unicode-normalization)
134
- - [Result Caching](#result-caching)
135
- - [Configuration Management](#configuration-management)
136
- - [ML-Based Detection](#ml-based-detection)
137
- - [📊 Benchmarks](#-benchmarks)
138
- - [📄 License](#license)
139
- - [MIT License](#mit-license)
140
-
141
22
  ## Installation
142
23
 
143
- <div align="center">
144
- <img src="https://img.shields.io/badge/npm-CB3837?style=for-the-badge&logo=npm&logoColor=white" alt="npm" />
145
- <img src="https://img.shields.io/badge/Yarn-2C8EBB?style=for-the-badge&logo=yarn&logoColor=white" alt="yarn" />
146
- <img src="https://img.shields.io/badge/pnpm-F69220?style=for-the-badge&logo=pnpm&logoColor=white" alt="pnpm" />
147
- </div>
148
-
149
- <br />
150
-
151
- To install Glin-Profanity, use npm:
152
-
153
24
  ```bash
154
25
  npm install glin-profanity
155
26
  ```
156
- OR
157
-
158
- ```bash
159
- yarn add glin-profanity
160
- ```
161
- OR
162
-
163
- ```bash
164
- pnpm add glin-profanity
165
- ```
166
-
167
- ## Supported Languages
168
-
169
- Glin-Profanity includes comprehensive profanity dictionaries for **23 languages**:
170
-
171
- 🇸🇦 **Arabic** • 🇨🇳 **Chinese** • 🇨🇿 **Czech** • 🇩🇰 **Danish** • 🇬🇧 **English** • 🌍 **Esperanto** • 🇫🇮 **Finnish** • 🇫🇷 **French** • 🇩🇪 **German** • 🇮🇳 **Hindi** • 🇭🇺 **Hungarian** • 🇮🇹 **Italian** • 🇯🇵 **Japanese** • 🇰🇷 **Korean** • 🇳🇴 **Norwegian** • 🇮🇷 **Persian** • 🇵🇱 **Polish** • 🇵🇹 **Portuguese** • 🇷🇺 **Russian** • 🇪🇸 **Spanish** • 🇸🇪 **Swedish** • 🇹🇭 **Thai** • 🇹🇷 **Turkish**
172
-
173
- > **Note**: The JavaScript and Python packages maintain cross-language parity, ensuring consistent profanity detection across both ecosystems.
174
-
175
- ## Usage
176
-
177
- ### Basic Usage
178
27
 
179
- Glin-Profanity now provides framework-agnostic core functions alongside React-specific hooks:
180
-
181
- #### 🟢 Node.js / Vanilla JavaScript
28
+ ## Quick Start
182
29
 
183
30
  ```javascript
184
- const { checkProfanity } = require('glin-profanity');
31
+ import { checkProfanity, Filter } from 'glin-profanity';
185
32
 
186
- const text = "This is some bad text with damn words";
187
- const result = checkProfanity(text, {
188
- languages: ['english', 'spanish'],
189
- replaceWith: '***'
33
+ // Simple check
34
+ const result = checkProfanity("This is f4ck1ng bad", {
35
+ detectLeetspeak: true,
36
+ languages: ['english']
190
37
  });
191
38
 
192
- console.log(result.containsProfanity); // true
193
- console.log(result.profaneWords); // ['damn']
194
- console.log(result.processedText); // "This is some bad text with *** words"
195
- ```
196
-
197
- #### 🔷 TypeScript
39
+ result.containsProfanity // true
40
+ result.profaneWords // ['fucking']
198
41
 
199
- ```typescript
200
- import { checkProfanity, ProfanityCheckerConfig } from 'glin-profanity';
201
-
202
- const config: ProfanityCheckerConfig = {
203
- languages: ['english', 'spanish'],
204
- severityLevels: true,
205
- autoReplace: true,
206
- replaceWith: '🤬'
207
- };
208
-
209
- const result = checkProfanity("inappropriate text", config);
42
+ // With replacement
43
+ const filter = new Filter({
44
+ replaceWith: '***',
45
+ detectLeetspeak: true
46
+ });
47
+ filter.checkProfanity("sh1t happens").processedText // "*** happens"
210
48
  ```
211
49
 
212
- ### Framework Examples
213
-
214
- <div align="center">
215
- <img src="https://img.shields.io/badge/Node.js-339933?style=for-the-badge&logo=nodedotjs&logoColor=white" alt="Node.js" />
216
- <img src="https://img.shields.io/badge/React-20232A?style=for-the-badge&logo=react&logoColor=61DAFB" alt="React" />
217
- <img src="https://img.shields.io/badge/Vue.js-35495E?style=for-the-badge&logo=vuedotjs&logoColor=4FC08D" alt="Vue.js" />
218
- <img src="https://img.shields.io/badge/Angular-DD0031?style=for-the-badge&logo=angular&logoColor=white" alt="Angular" />
219
- <img src="https://img.shields.io/badge/TypeScript-007ACC?style=for-the-badge&logo=typescript&logoColor=white" alt="TypeScript" />
220
- </div>
221
-
222
- #### ⚛️ React
50
+ ## React Hook
223
51
 
224
52
  ```tsx
225
- import React, { useState } from 'react';
226
- import { useProfanityChecker, SeverityLevel } from 'glin-profanity';
53
+ import { useProfanityChecker } from 'glin-profanity';
227
54
 
228
- const App = () => {
229
- const [text, setText] = useState('');
230
-
55
+ function ChatInput() {
231
56
  const { result, checkText } = useProfanityChecker({
232
- languages: ['english', 'spanish'],
233
- severityLevels: true,
234
- autoReplace: true,
235
- replaceWith: '***',
236
- minSeverity: SeverityLevel.EXACT
57
+ detectLeetspeak: true
237
58
  });
238
59
 
239
60
  return (
240
- <div>
241
- <input value={text} onChange={(e) => setText(e.target.value)} />
242
- <button onClick={() => checkText(text)}>Scan</button>
243
-
244
- {result && result.containsProfanity && (
245
- <p>Cleaned: {result.processedText}</p>
246
- )}
247
- </div>
61
+ <>
62
+ <input onChange={(e) => checkText(e.target.value)} />
63
+ {result?.containsProfanity && <span>Clean up your language</span>}
64
+ </>
248
65
  );
249
- };
250
- ```
251
-
252
- #### 💚 Vue 3
253
-
254
- ```vue
255
- <template>
256
- <div>
257
- <input v-model="text" @input="checkContent" />
258
- <p v-if="hasProfanity">{{ cleanedText }}</p>
259
- </div>
260
- </template>
261
-
262
- <script setup>
263
- import { ref } from 'vue';
264
- import { checkProfanity } from 'glin-profanity';
265
-
266
- const text = ref('');
267
- const hasProfanity = ref(false);
268
- const cleanedText = ref('');
269
-
270
- const checkContent = () => {
271
- const result = checkProfanity(text.value, {
272
- languages: ['english'],
273
- autoReplace: true,
274
- replaceWith: '***'
275
- });
276
-
277
- hasProfanity.value = result.containsProfanity;
278
- cleanedText.value = result.autoReplaced;
279
- };
280
- </script>
281
- ```
282
-
283
- #### 🔴 Angular
284
-
285
- ```typescript
286
- import { Component } from '@angular/core';
287
- import { checkProfanity, ProfanityCheckResult } from 'glin-profanity';
288
-
289
- @Component({
290
- selector: 'app-comment',
291
- template: `
292
- <textarea [(ngModel)]="comment" (ngModelChange)="validateComment()"></textarea>
293
- <div *ngIf="profanityResult?.containsProfanity" class="error">
294
- Please remove inappropriate language
295
- </div>
296
- `
297
- })
298
- export class CommentComponent {
299
- comment = '';
300
- profanityResult: ProfanityCheckResult | null = null;
301
-
302
- validateComment() {
303
- this.profanityResult = checkProfanity(this.comment, {
304
- languages: ['english', 'spanish'],
305
- severityLevels: true
306
- });
307
- }
308
66
  }
309
67
  ```
310
68
 
311
- #### 🚂 Express.js Middleware
69
+ ## Features
312
70
 
313
- ```javascript
314
- const express = require('express');
315
- const { checkProfanity } = require('glin-profanity');
316
-
317
- const profanityMiddleware = (req, res, next) => {
318
- const result = checkProfanity(req.body.message || '', {
319
- languages: ['english'],
320
- autoReplace: true,
321
- replaceWith: '[censored]'
322
- });
323
-
324
- if (result.containsProfanity) {
325
- req.body.message = result.autoReplaced;
326
- }
327
-
328
- next();
329
- };
330
-
331
- app.post('/comment', profanityMiddleware, (req, res) => {
332
- // Message is now sanitized
333
- res.json({ message: req.body.message });
334
- });
335
- ```
71
+ | Feature | Description |
72
+ |---------|-------------|
73
+ | Leetspeak detection | Catches `f4ck`, `sh1t`, `@ss` |
74
+ | Unicode normalization | Handles Cyrillic/Greek lookalikes |
75
+ | ML toxicity detection | TensorFlow.js integration |
76
+ | 23 languages | Arabic to Turkish |
77
+ | Result caching | LRU cache for repeated checks |
78
+ | React hook | `useProfanityChecker` built-in |
336
79
 
337
80
  ## API
338
81
 
339
- ### 🎯 Core Functions
340
-
341
- #### `checkProfanity`
342
-
343
- Framework-agnostic function for profanity detection.
344
-
345
- ```typescript
346
- checkProfanity(text: string, config?: ProfanityCheckerConfig): ProfanityCheckResult
347
- ```
348
-
349
- #### `checkProfanityAsync`
350
-
351
- Async version of checkProfanity.
82
+ ### Core Functions
352
83
 
353
84
  ```typescript
354
- checkProfanityAsync(text: string, config?: ProfanityCheckerConfig): Promise<ProfanityCheckResult>
355
- ```
356
-
357
- #### `isWordProfane`
85
+ // Full check with options
86
+ checkProfanity(text: string, config?: FilterConfig): ProfanityCheckResult
358
87
 
359
- Quick check if a single word is profane.
88
+ // Quick boolean check
89
+ isProfane(text: string): boolean
360
90
 
361
- ```typescript
362
- isWordProfane(word: string, config?: ProfanityCheckerConfig): boolean
91
+ // Async version
92
+ checkProfanityAsync(text: string, config?: FilterConfig): Promise<ProfanityCheckResult>
363
93
  ```
364
94
 
365
- ### 🔧 `Filter` Class
366
-
367
- #### Constructor
95
+ ### Filter Class
368
96
 
369
97
  ```typescript
370
- new Filter(config?: FilterConfig);
371
- ```
372
-
373
- #### FilterConfig Options:
374
-
375
- | Option | Type | Description |
376
- |-------------------------|--------------------|-------------|
377
- | `languages` | `Language[]` | Languages to include (e.g., ['english', 'spanish']) |
378
- | `allLanguages` | `boolean` | If true, scan all available languages |
379
- | `caseSensitive` | `boolean` | Match case exactly |
380
- | `wordBoundaries` | `boolean` | Only match full words (turn off for substring matching) |
381
- | `customWords` | `string[]` | Add your own words |
382
- | `replaceWith` | `string` | Replace matched words with this string |
383
- | `severityLevels` | `boolean` | Enable severity mapping (Exact, Fuzzy, Merged) |
384
- | `ignoreWords` | `string[]` | Words to skip even if found |
385
- | `logProfanity` | `boolean` | Log results via console |
386
- | `allowObfuscatedMatch` | `boolean` | Enable fuzzy pattern matching like `f*ck` |
387
- | `fuzzyToleranceLevel` | `number (0–1)` | Adjust how tolerant fuzzy matching is |
388
- | `autoReplace` | `boolean` | Whether to auto-replace flagged words |
389
- | `minSeverity` | `SeverityLevel` | Minimum severity to include in final list |
390
- | `customActions` | `(result) => void` | Custom logging/callback support |
391
- | `detectLeetspeak` | `boolean` | Enable leetspeak detection (e.g., `f4ck` → `fuck`) |
392
- | `leetspeakLevel` | `'basic' \| 'moderate' \| 'aggressive'` | Leetspeak detection intensity |
393
- | `normalizeUnicode` | `boolean` | Enable Unicode normalization for homoglyphs |
394
- | `cacheResults` | `boolean` | Cache results for repeated checks |
395
- | `maxCacheSize` | `number` | Maximum cache size (default: 1000) |
396
-
397
- ---
398
-
399
- #### Methods
400
-
401
- ##### `isProfane`
402
-
403
- Checks if a given text contains profanities.
404
-
405
- ```typescript
406
- isProfane(value: string): boolean;
407
- ```
408
-
409
- - `value`: The text to check.
410
- - Returns: `boolean` - `true` if the text contains profanities, `false` otherwise.
411
-
412
- ##### `checkProfanity`
413
-
414
- Returns details about profanities found in the text.
415
-
416
- ```typescript
417
- checkProfanity(text: string): CheckProfanityResult;
418
- ```
419
-
420
- - `text`: The text to check.
421
- - Returns: `CheckProfanityResult`
422
- - `containsProfanity`: `boolean` - `true` if the text contains profanities, `false` otherwise.
423
- - `profaneWords`: `string[]` - An array of profane words found in the text.
424
- - `processedText`: `string` - The text with profane words replaced (if `replaceWith` is specified).
425
- - `severityMap`: `{ [word: string]: number }` - A map of profane words to their severity levels (if `severityLevels` is specified).
426
-
427
- ### ⚛️ `useProfanityChecker` Hook
428
-
429
- A custom React hook for using the profanity checker.
430
-
431
- #### Parameters
432
-
433
- - `config`: An optional configuration object (same as ProfanityCheckerConfig).
434
-
435
- #### Return Value
436
-
437
- - `result`: The result of the profanity check.
438
- - `checkText`: A function to check a given text for profanities.
439
- - `checkTextAsync`: A function to check a given text for profanities asynchronously.
440
- - `reset`: A function to reset the result state.
441
- - `isDirty`: Boolean indicating if profanity was found.
442
- - `isWordProfane`: Function to check if a single word is profane.
443
-
444
- ```typescript
445
- const { result, checkText, checkTextAsync, reset, isDirty, isWordProfane } = useProfanityChecker(config);
446
- ```
447
-
448
- ## Note
449
- ⚠️ Glin-Profanity is a best-effort tool. Language evolves, and no filter is perfect. Always supplement with human moderation for high-risk platforms.
450
-
451
- ## 🛠 Use Cases
452
-
453
- - 🔐 Chat moderation in messaging apps
454
- - 🧼 Comment sanitization for blogs or forums
455
- - 🕹️ Game lobbies & multiplayer chats
456
- - 🤖 AI content filters before processing input
457
-
458
- ## 🔬 Advanced Features
459
-
460
- ### Leetspeak Detection
461
-
462
- Detect and normalize leetspeak variations like `f4ck`, `@ss`, `$h!t`:
463
-
464
- ```typescript
465
- import { Filter } from 'glin-profanity';
466
-
467
- const filter = new Filter({
468
- languages: ['english'],
469
- detectLeetspeak: true,
470
- leetspeakLevel: 'moderate', // 'basic' | 'moderate' | 'aggressive'
471
- });
472
-
473
- filter.isProfane('f4ck'); // true
474
- filter.isProfane('@ss'); // true
475
- filter.isProfane('$h!t'); // true
476
- filter.isProfane('f u c k'); // true (spaced characters)
477
- ```
478
-
479
- **Leetspeak Levels:**
480
- - `basic`: Numbers only (0→o, 1→i, 3→e, 4→a, 5→s)
481
- - `moderate`: Basic + common symbols (@→a, $→s, !→i)
482
- - `aggressive`: All known substitutions including rare ones
483
-
484
- ### Unicode Normalization
485
-
486
- Detect homoglyphs and Unicode obfuscation:
487
-
488
- ```typescript
489
- import { Filter } from 'glin-profanity';
490
-
491
- const filter = new Filter({
492
- languages: ['english'],
493
- normalizeUnicode: true, // enabled by default
494
- });
495
-
496
- // Detects various Unicode tricks:
497
- filter.isProfane('fυck'); // true (Greek upsilon υ → u)
498
- filter.isProfane('fᴜck'); // true (Small caps ᴜ → u)
499
- filter.isProfane('f​u​c​k'); // true (Zero-width spaces removed)
500
- filter.isProfane('fuck'); // true (Full-width characters)
501
- ```
502
-
503
- ### Result Caching
504
-
505
- Enable caching for high-performance repeated checks:
506
-
507
- ```typescript
508
- import { Filter } from 'glin-profanity';
509
-
510
- const filter = new Filter({
511
- languages: ['english'],
512
- cacheResults: true,
513
- maxCacheSize: 1000, // LRU eviction when full
514
- });
515
-
516
- // First call computes result
517
- filter.checkProfanity('hello world'); // ~0.04ms
518
-
519
- // Subsequent calls return cached result
520
- filter.checkProfanity('hello world'); // ~0.00005ms (800x faster!)
521
-
522
- // Cache management
523
- console.log(filter.getCacheSize()); // 1
524
- filter.clearCache();
525
- ```
526
-
527
- ### Configuration Management
528
-
529
- Export and import filter configurations for sharing between environments:
530
-
531
- ```typescript
532
- import { Filter } from 'glin-profanity';
533
-
534
98
  const filter = new Filter({
535
99
  languages: ['english', 'spanish'],
536
100
  detectLeetspeak: true,
537
- leetspeakLevel: 'aggressive',
101
+ leetspeakLevel: 'moderate', // basic | moderate | aggressive
102
+ normalizeUnicode: true,
538
103
  cacheResults: true,
104
+ maxCacheSize: 1000,
105
+ replaceWith: '***'
539
106
  });
540
107
 
541
- // Export configuration
542
- const config = filter.getConfig();
543
- // Save to file: fs.writeFileSync('filter.config.json', JSON.stringify(config));
544
-
545
- // Later, restore configuration
546
- // const savedConfig = JSON.parse(fs.readFileSync('filter.config.json'));
547
- // const restoredFilter = new Filter(savedConfig);
548
-
549
- // Get dictionary size for monitoring
550
- console.log(filter.getWordCount()); // 406
551
- ```
552
-
553
- ### ML-Based Detection
554
-
555
- Optional TensorFlow.js-powered toxicity detection for context-aware filtering:
556
-
557
- ```bash
558
- # Install optional dependencies
559
- npm install @tensorflow/tfjs @tensorflow-models/toxicity
560
- ```
561
-
562
- ```typescript
563
- import { HybridFilter } from 'glin-profanity/ml';
564
-
565
- const filter = new HybridFilter({
566
- languages: ['english'],
567
- detectLeetspeak: true,
568
- enableML: true,
569
- mlThreshold: 0.85,
570
- combinationMode: 'or', // 'or' | 'and' | 'ml-override' | 'rules-first'
571
- });
572
-
573
- // Initialize ML model (async)
574
- await filter.initialize();
575
-
576
- // Hybrid check (rules + ML)
577
- const result = await filter.checkProfanityAsync('you are terrible');
578
- console.log(result.isToxic); // true
579
- console.log(result.mlResult?.matchedCategories); // ['insult', 'toxicity']
580
- console.log(result.confidence); // 0.92
581
-
582
- // Sync rule-based check (fast, no ML)
583
- filter.isProfane('badword'); // true
108
+ filter.isProfane('f4ck'); // true
109
+ filter.checkProfanity('bad word').profaneWords; // ['bad']
110
+ filter.clearCache();
584
111
  ```
585
112
 
586
- **ML Categories Detected:**
587
- - `toxicity` - General toxic content
588
- - `insult` - Insults and personal attacks
589
- - `threat` - Threatening language
590
- - `obscene` - Obscene/vulgar content
591
- - `identity_attack` - Identity-based hate
592
- - `sexual_explicit` - Sexually explicit content
593
- - `severe_toxicity` - Highly toxic content
594
-
595
- ## 📊 Benchmarks
596
-
597
- Performance benchmarks on a MacBook Pro (M1):
598
-
599
- | Operation | Throughput | Average Time |
600
- |-----------|------------|--------------|
601
- | `isProfane` (clean text) | 23,524 ops/sec | 0.04ms |
602
- | `isProfane` (profane text) | 114,666 ops/sec | 0.009ms |
603
- | With leetspeak detection | 22,904 ops/sec | 0.04ms |
604
- | With Unicode normalization | 24,058 ops/sec | 0.04ms |
605
- | With caching (cached hit) | **21,396,095 ops/sec** | 0.00005ms |
606
- | `checkProfanity` (detailed) | 3,677 ops/sec | 0.27ms |
607
- | Multi-language (4 langs) | 24,855 ops/sec | 0.04ms |
608
- | All languages (23 langs) | 14,114 ops/sec | 0.07ms |
609
-
610
- **Key Findings:**
611
- - Leetspeak and Unicode normalization add minimal overhead
612
- - Caching provides **800x speedup** for repeated checks
613
- - Multi-language support scales well
614
-
615
- Run benchmarks yourself:
616
- ```bash
617
- npm run benchmark
618
- ```
113
+ ### Configuration Options
114
+
115
+ | Option | Type | Default | Description |
116
+ |--------|------|---------|-------------|
117
+ | `languages` | `string[]` | `['english']` | Languages to check |
118
+ | `allLanguages` | `boolean` | `false` | Check all 23 languages |
119
+ | `detectLeetspeak` | `boolean` | `false` | Enable leetspeak detection |
120
+ | `leetspeakLevel` | `string` | `'basic'` | `basic` / `moderate` / `aggressive` |
121
+ | `normalizeUnicode` | `boolean` | `true` | Normalize Unicode homoglyphs |
122
+ | `cacheResults` | `boolean` | `false` | Cache results for repeated checks |
123
+ | `maxCacheSize` | `number` | `1000` | LRU cache limit |
124
+ | `replaceWith` | `string` | `undefined` | Replacement string |
125
+ | `customWords` | `string[]` | `[]` | Add custom profane words |
126
+ | `ignoreWords` | `string[]` | `[]` | Whitelist words |
127
+ | `severityLevels` | `boolean` | `false` | Enable severity mapping |
128
+
129
+ ## Documentation
130
+
131
+ | Resource | Link |
132
+ |----------|------|
133
+ | Getting Started | [docs/getting-started.md](../../docs/getting-started.md) |
134
+ | API Reference | [docs/api-reference.md](../../docs/api-reference.md) |
135
+ | Framework Examples | [docs/framework-examples.md](../../docs/framework-examples.md) |
136
+ | Advanced Features | [docs/advanced-features.md](../../docs/advanced-features.md) |
137
+ | ML Guide | [docs/ML-GUIDE.md](../../docs/ML-GUIDE.md) |
138
+ | Main README | [README.md](../../README.md) |
619
139
 
620
140
  ## License
621
141
 
622
- This software is also available under the GLINCKER LLC proprietary license. The proprietary license allows for use, modification, and distribution of the software with certain restrictions and conditions as set forth by GLINCKER LLC.
142
+ MIT License - see [LICENSE](../../LICENSE)
623
143
 
624
- You are free to use this software for reference and educational purposes. However, any commercial use, distribution, or modification outside the terms of the MIT License requires explicit permission from GLINCKER LLC.
625
-
626
- By using the software in any form, you agree to adhere to the terms of both the MIT License and the GLINCKER LLC proprietary license, where applicable. If there is any conflict between the terms of the MIT License and the GLINCKER LLC proprietary license, the terms of the GLINCKER LLC proprietary license shall prevail.
627
-
628
- ### MIT License
144
+ ---
629
145
 
630
- GLIN PROFANITY is [MIT licensed](./LICENSE).
146
+ <div align="center">
147
+ <sub>Built by <a href="https://glincker.com">GLINCKER</a></sub>
148
+ </div>