@nzrm/text-shield
v1.0.1
Published
A powerful, lightweight, and framework-agnostic profanity filter library with built-in multilingual support for English and Arabic
Maintainers
Readme
🛡️ Text Shield
A powerful, lightweight, and framework-agnostic profanity filter library with built-in multilingual support for English and Arabic. Perfect for content moderation in Node.js, NestJS, React, Angular, Vue, and browser applications.
✨ Features
- 🌍 Multilingual Support - Built-in English and Arabic profanity detection
- ⚡ High Performance - O(1) lookup time with Set-based architecture
- 🎯 Flexible Matching - Whole word or partial matching modes
- 🔧 Framework Agnostic - Works with Node.js, React, Angular, Vue, NestJS, Express, and more
- 📦 Zero Dependencies - Lightweight with no external dependencies
- 💪 TypeScript First - Written in TypeScript with full type definitions
- 🎨 Customizable - Add custom words, change placeholders, configure sensitivity
- 📝 Easy Integration - Simple API that works everywhere
- 🔒 Privacy Focused - All processing done locally, no external API calls
📦 Installation
npm install @nzrm/text-shieldyarn add @nzrm/text-shieldpnpm add @nzrm/text-shield🚀 Quick Start
import { ProfanityFilter } from "@nzrm/text-shield";
// Initialize with English
const filter = new ProfanityFilter({ languages: ["en"] });
// Check if text contains profanity
if (filter.containsProfanity("This is a damn shame")) {
console.log("Profanity detected!");
}
// Clean the text
const cleaned = filter.clean("What the hell is this?");
console.log(cleaned); // "What the *** is this?"
// Get specific profane words
const words = filter.getProfaneWords("This shit is bad");
console.log(words); // ['shit', 'bad']🌐 Multilingual Support
English Only
const filter = new ProfanityFilter({ languages: ["en"] });
filter.isProfane("damn"); // trueArabic Only
const filter = new ProfanityFilter({ languages: ["ar"] });
filter.isProfane("كس"); // trueBoth Languages
const filter = new ProfanityFilter({ languages: ["en", "ar"] });
filter.clean("This is shit وهذا كس أيضا"); // "This is *** وهذا *** أيضا"📖 API Documentation
Constructor
new ProfanityFilter(options?: ProfanityFilterOptions)Options
interface ProfanityFilterOptions {
languages?: ("en" | "ar")[]; // Default: ['en']
customWords?: string[]; // Additional words to filter
caseSensitive?: boolean; // Default: false
wholeWord?: boolean; // Default: true
placeholder?: string; // Default: '***'
}Methods
isProfane(word: string): boolean
Check if a single word is profane.
filter.isProfane("damn"); // true
filter.isProfane("hello"); // falsecontainsProfanity(text: string): boolean
Check if text contains any profanity.
filter.containsProfanity("This is bad"); // true
filter.containsProfanity("This is good"); // falsegetProfaneWords(text: string): string[]
Get an array of all profane words found in the text.
filter.getProfaneWords("damn this shit"); // ['damn', 'shit']clean(text: string): string
Replace profane words with the placeholder.
filter.clean("What the hell"); // 'What the ***'addWords(words: string[]): void
Add custom words to the filter dynamically.
filter.addWords(["spam", "junk"]);removeWords(words: string[]): void
Remove words from the filter.
filter.removeWords(["damn", "hell"]);getWordCount(): number
Get the total number of words in the filter.
console.log(filter.getWordCount()); // 150exportWords(): string[]
Export all filtered words as an array.
const allWords = filter.exportWords();Static Methods
ProfanityFilter.fromFile(filePath: string, options?: ProfanityFilterOptions): Promise<ProfanityFilter>
Load custom word list from a JSON file.
const filter = await ProfanityFilter.fromFile("./custom-words.json", {
languages: ["en"],
placeholder: "[CENSORED]",
});🔧 Framework Integration Examples
Node.js / Express
const express = require("express");
const { ProfanityFilter } = require("text-shield");
const app = express();
app.use(express.json());
const filter = new ProfanityFilter({ languages: ["en", "ar"] });
app.post("/api/comment", (req, res) => {
if (filter.containsProfanity(req.body.text)) {
return res.status(400).json({
error: "Comment contains inappropriate content",
profaneWords: filter.getProfaneWords(req.body.text),
});
}
res.json({ message: "Comment posted successfully" });
});
app.listen(3000);NestJS
// profanity.service.ts
import { Injectable } from "@nestjs/common";
import { ProfanityFilter } from "@nzrm/text-shield";
@Injectable()
export class ProfanityService {
private filter: ProfanityFilter;
constructor() {
this.filter = new ProfanityFilter({
languages: ["en", "ar"],
});
}
validate(text: string): boolean {
return !this.filter.containsProfanity(text);
}
clean(text: string): string {
return this.filter.clean(text);
}
}React
import { useState, useEffect } from "react";
import { ProfanityFilter } from "@nzrm/text-shield";
function CommentForm() {
const [filter, setFilter] = useState(null);
const [comment, setComment] = useState("");
const [error, setError] = useState("");
useEffect(() => {
const profanityFilter = new ProfanityFilter({
languages: ["en", "ar"],
});
setFilter(profanityFilter);
}, []);
const handleSubmit = (e) => {
e.preventDefault();
if (filter?.containsProfanity(comment)) {
setError("Comment contains inappropriate content");
return;
}
console.log("Comment approved");
};
return (
<form onSubmit={handleSubmit}>
<textarea value={comment} onChange={(e) => setComment(e.target.value)} />
{error && <p style={{ color: "red" }}>{error}</p>}
<button type="submit">Submit</button>
</form>
);
}Angular
// profanity.service.ts
import { Injectable } from "@angular/core";
import { ProfanityFilter } from "@nzrm/text-shield";
@Injectable({
providedIn: "root",
})
export class ProfanityService {
private filter: ProfanityFilter;
constructor() {
this.filter = new ProfanityFilter({
languages: ["en", "ar"],
});
}
isProfane(text: string): boolean {
return this.filter.containsProfanity(text);
}
clean(text: string): string {
return this.filter.clean(text);
}
}Vue
<template>
<div>
<textarea v-model="comment" @input="validateComment"></textarea>
<p v-if="error" class="error">{{ error }}</p>
<button @click="submitComment">Submit</button>
</div>
</template>
<script>
import { ref } from "vue";
import { ProfanityFilter } from "@nzrm/text-shield";
export default {
setup() {
const filter = new ProfanityFilter({ languages: ["en", "ar"] });
const comment = ref("");
const error = ref("");
const validateComment = () => {
if (filter.containsProfanity(comment.value)) {
error.value = "Contains inappropriate content";
} else {
error.value = "";
}
};
const submitComment = () => {
if (filter.containsProfanity(comment.value)) {
error.value = "Cannot submit inappropriate content";
return;
}
console.log("Comment submitted");
};
return { comment, error, validateComment, submitComment };
},
};
</script>⚙️ Advanced Usage
Custom Word Lists
// Add custom words
const filter = new ProfanityFilter({
languages: ["en"],
customWords: ["spam", "junk", "troll"],
});
// Or add them later
filter.addWords(["scam", "fake"]);Load from External File
// words.json: ["word1", "word2", "word3"]
const filter = await ProfanityFilter.fromFile("./words.json", {
languages: ["en"],
placeholder: "[REMOVED]",
});Partial Word Matching
const filter = new ProfanityFilter({
languages: ["en"],
wholeWord: false, // Will match 'bad' in 'badass'
});Case Sensitive Mode
const filter = new ProfanityFilter({
languages: ["en"],
caseSensitive: true, // 'DAMN' and 'damn' treated differently
});Custom Placeholder
const filter = new ProfanityFilter({
languages: ["en"],
placeholder: "[CENSORED]",
});
filter.clean("This is bad"); // 'This is [CENSORED]'🔒 Privacy & Security
- No External API Calls - All processing is done locally
- No Data Collection - Your text never leaves your application
- Open Source - Fully transparent and auditable code
- No Analytics - We don't track usage or collect statistics
🌟 Use Cases
- Social media platforms
- Comment systems
- Chat applications
- Content moderation tools
- Form validation
- User-generated content filtering
- Forum moderation
- Review systems
- Gaming chat filters
- Educational platforms
📊 Performance
- Lookup Time: O(1) - Constant time for word checking
- Memory: Efficient Set-based storage
- Bundle Size: ~15KB minified
- Zero Dependencies: No external packages required
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
📝 Changelog
See CHANGELOG.md for a list of changes.
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🙏 Acknowledgments
- Built with TypeScript
- Bundled with Rollup
- Inspired by the need for better multilingual content moderation
🐛 Bug Reports
Found a bug? Please open an issue
💬 Support
- 📧 Email: [email protected]
- 💬 GitHub Issues: Create an issue
- 📖 Documentation: Full docs
⭐ Show Your Support
Give a ⭐️ if this project helped you!
Made with ❤️ by Nizar Masadeh
