@nzrm/text-shield

A powerful, lightweight, and framework-agnostic profanity filter library with built-in multilingual support for English and Arabic
594
Install
npm install @nzrm/text-shield
Latest Version:1.0.1
License:MIT
Last Updated:Dec 29, 2025
Links: npm
Maintainer: nizar_masadeh

🛡️ Text Shield

npm version npm downloads License: MIT TypeScript

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-shield
yarn add @nzrm/text-shield
pnpm 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"); // true

Arabic Only

const filter = new ProfanityFilter({ languages: ["ar"] });
filter.isProfane("كس"); // true

Both 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"); // false
containsProfanity(text: string): boolean

Check if text contains any profanity.

filter.containsProfanity("This is bad"); // true
filter.containsProfanity("This is good"); // false
getProfaneWords(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()); // 150
exportWords(): 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

⭐ Show Your Support

Give a ⭐️ if this project helped you!


Made with ❤️ by Nizar Masadeh

Related Packages

iraqi-dialect-bad-words

An Iraqi dialect profanity filter for React, React Native Expo, Vue, and Node.js

1,005 4
@safetype/vue

Vue 3 directive, components and composables for SafeType.js content moderation

432 3
@agnostico/browser-solidity-compiler

Solidity compiler that works in the browser

1,548 18
ts-profanity-filter

TypeScript profanity filter that returns text segments for UI rendering. English...

0 1
@propeller-commerce/propeller-sdk-v2

TypeScript GraphQL client for Propeller eCommerce V2 Platform - works with React...

8,078 1

Version History

Version Released License
1.0.1 MIT
1.0.0 MIT