New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More โ†’
Socket
Sign inDemoInstall
Socket

@2toad/profanity

Package Overview
Dependencies
Maintainers
0
Versions
24
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@2toad/profanity - npm Package Compare versions

Comparing version 2.3.1 to 2.4.0

dist/data/index.d.ts

3

dist/data/profane-words.d.ts

@@ -1,2 +0,1 @@

declare const _default: string[];
export default _default;
export declare const profaneWords: readonly string[];

@@ -5,3 +5,4 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.default = [
exports.profaneWords = void 0;
exports.profaneWords = [
"4r5e",

@@ -8,0 +9,0 @@ "5h1t",

@@ -1,3 +0,4 @@

export * from "./profanity";
export * from "./profanity-options";
export { Profanity, profanity } from "./profanity";
export { ProfanityOptions } from "./profanity-options";
export { CensorType } from "./models";
export { profaneWords } from "./data";
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CensorType = void 0;
__exportStar(require("./profanity"), exports);
__exportStar(require("./profanity-options"), exports);
exports.profaneWords = exports.CensorType = exports.ProfanityOptions = exports.profanity = exports.Profanity = void 0;
var profanity_1 = require("./profanity");
Object.defineProperty(exports, "Profanity", { enumerable: true, get: function () { return profanity_1.Profanity; } });
Object.defineProperty(exports, "profanity", { enumerable: true, get: function () { return profanity_1.profanity; } });
var profanity_options_1 = require("./profanity-options");
Object.defineProperty(exports, "ProfanityOptions", { enumerable: true, get: function () { return profanity_options_1.ProfanityOptions; } });
var models_1 = require("./models");
Object.defineProperty(exports, "CensorType", { enumerable: true, get: function () { return models_1.CensorType; } });
var data_1 = require("./data");
Object.defineProperty(exports, "profaneWords", { enumerable: true, get: function () { return data_1.profaneWords; } });
//# sourceMappingURL=index.js.map

@@ -1,2 +0,2 @@

export * from "./censor-type";
export * from "./list";
export { CensorType } from "./censor-type";
export { List } from "./list";
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./censor-type"), exports);
__exportStar(require("./list"), exports);
exports.List = exports.CensorType = void 0;
var censor_type_1 = require("./censor-type");
Object.defineProperty(exports, "CensorType", { enumerable: true, get: function () { return censor_type_1.CensorType; } });
var list_1 = require("./list");
Object.defineProperty(exports, "List", { enumerable: true, get: function () { return list_1.List; } });
//# sourceMappingURL=index.js.map

@@ -7,3 +7,3 @@ export declare class List {

removeWords(words: string[]): void;
addWords(words: string[]): void;
addWords(words: readonly string[] | string[]): void;
}

@@ -17,3 +17,3 @@ "use strict";

addWords(words) {
this.words = this.words.concat(words);
this.words = this.words.concat(words.map((word) => word.toLowerCase()));
this.onListChanged();

@@ -20,0 +20,0 @@ }

@@ -5,3 +5,3 @@ export declare class ProfanityOptions {

grawlixChar: string;
constructor();
constructor(options?: Partial<ProfanityOptions>);
}

@@ -5,6 +5,7 @@ "use strict";

class ProfanityOptions {
constructor() {
this.wholeWord = true;
this.grawlix = "@#$%&!";
this.grawlixChar = "*";
constructor(options = {}) {
var _a, _b, _c;
this.wholeWord = (_a = options.wholeWord) !== null && _a !== void 0 ? _a : true;
this.grawlix = (_b = options.grawlix) !== null && _b !== void 0 ? _b : "@#$%&!";
this.grawlixChar = (_c = options.grawlixChar) !== null && _c !== void 0 ? _c : "*";
}

@@ -11,0 +12,0 @@ }

@@ -8,5 +8,6 @@ import { ProfanityOptions } from "./profanity-options";

private regex;
constructor(options?: ProfanityOptions);
constructor(options?: ProfanityOptions | Partial<ProfanityOptions>);
exists(text: string): boolean;
censor(text: string, censorType?: CensorType): string;
private replaceProfanity;
addWords(words: string[]): void;

@@ -17,2 +18,1 @@ removeWords(words: string[]): void;

export declare const profanity: Profanity;
export default profanity;
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });

@@ -9,38 +6,59 @@ exports.profanity = exports.Profanity = void 0;

const models_1 = require("./models");
const misc_1 = require("./utils/misc");
const profane_words_1 = __importDefault(require("./data/profane-words"));
const utils_1 = require("./utils");
const data_1 = require("./data");
class Profanity {
constructor(options) {
this.options = options || new profanity_options_1.ProfanityOptions();
this.options = options ? { ...new profanity_options_1.ProfanityOptions(), ...options } : new profanity_options_1.ProfanityOptions();
this.whitelist = new models_1.List(() => this.buildRegex());
this.blacklist = new models_1.List(() => this.buildRegex());
this.blacklist.addWords(profane_words_1.default);
this.blacklist.addWords(data_1.profaneWords);
}
exists(text) {
this.regex.lastIndex = 0;
return this.regex.test(text);
const lowercaseText = text.toLowerCase();
let match;
do {
match = this.regex.exec(lowercaseText);
if (match !== null) {
const matchStart = match.index;
const matchEnd = matchStart + match[0].length;
// Check if the matched word is part of a whitelisted word
const isWhitelisted = this.whitelist.words.some((whitelistedWord) => {
const whitelistedIndex = lowercaseText.indexOf(whitelistedWord, Math.max(0, matchStart - whitelistedWord.length + 1));
if (whitelistedIndex === -1)
return false;
const whitelistedEnd = whitelistedIndex + whitelistedWord.length;
if (this.options.wholeWord) {
// For whole word matching, ensure the whitelisted word exactly matches the profane word
// and is not part of a hyphenated or underscore-separated word
return (matchStart === whitelistedIndex &&
matchEnd === whitelistedEnd &&
(matchStart === 0 || !/[\w-_]/.test(lowercaseText[matchStart - 1])) &&
(matchEnd === lowercaseText.length || !/[\w-_]/.test(lowercaseText[matchEnd])));
}
// For partial matching, check if the profane word is contained within the whitelisted word
return (matchStart >= whitelistedIndex && matchStart < whitelistedEnd) || (matchEnd > whitelistedIndex && matchEnd <= whitelistedEnd);
});
if (!isWhitelisted) {
return true;
}
}
} while (match !== null);
return false;
}
censor(text, censorType = models_1.CensorType.Word) {
const lowercaseText = text.toLowerCase();
switch (censorType) {
case models_1.CensorType.Word:
return text.replace(this.regex, this.options.grawlix);
return text.replace(this.regex, (match) => {
const underscore = match.includes("_") ? "_" : "";
return this.options.grawlix + underscore;
});
case models_1.CensorType.FirstChar: {
let output = text;
Array.from(text.matchAll(this.regex)).forEach((match) => {
const word = match[0];
const grawlix = this.options.grawlixChar + word.slice(1, word.length);
output = output.replace(word, grawlix);
});
return output;
return this.replaceProfanity(text, lowercaseText, (word) => this.options.grawlixChar + word.slice(1));
}
case models_1.CensorType.FirstVowel:
case models_1.CensorType.AllVowels: {
const regex = new RegExp("[aeiou]", censorType === models_1.CensorType.FirstVowel ? "i" : "ig");
let output = text;
Array.from(text.matchAll(this.regex)).forEach((match) => {
const word = match[0];
const grawlix = word.replace(regex, this.options.grawlixChar);
output = output.replace(word, grawlix);
});
return output;
const vowelRegex = new RegExp("[aeiou]", censorType === models_1.CensorType.FirstVowel ? "i" : "ig");
return this.replaceProfanity(text, lowercaseText, (word) => word.replace(vowelRegex, this.options.grawlixChar));
}

@@ -51,2 +69,20 @@ default:

}
replaceProfanity(text, lowercaseText, replacer) {
let result = text;
let offset = 0;
this.regex.lastIndex = 0;
let match;
do {
match = this.regex.exec(lowercaseText);
if (match !== null) {
const matchStart = match.index;
const matchEnd = matchStart + match[0].length;
const originalWord = text.slice(matchStart + offset, matchEnd + offset);
const censoredWord = replacer(originalWord);
result = result.slice(0, matchStart + offset) + censoredWord + result.slice(matchEnd + offset);
offset += censoredWord.length - originalWord.length;
}
} while (match !== null);
return result;
}
addWords(words) {

@@ -56,10 +92,8 @@ this.blacklist.addWords(words);

removeWords(words) {
this.blacklist.removeWords(words);
this.blacklist.removeWords(words.map((word) => word.toLowerCase()));
}
buildRegex() {
const escapedBlacklistWords = this.blacklist.words.map(misc_1.escapeRegExp);
const escapedWhitelistWords = this.whitelist.words.map(misc_1.escapeRegExp);
const blacklistPattern = `${this.options.wholeWord ? "\\b" : ""}(${escapedBlacklistWords.join("|")})${this.options.wholeWord ? "\\b" : ""}`;
const whitelistPattern = this.whitelist.empty ? "" : `(?!${escapedWhitelistWords.join("|")})`;
this.regex = new RegExp(whitelistPattern + blacklistPattern, "ig");
const escapedBlacklistWords = this.blacklist.words.map(utils_1.escapeRegExp);
const profanityPattern = `${this.options.wholeWord ? "(?:\\b|_)" : ""}(${escapedBlacklistWords.join("|")})${this.options.wholeWord ? "(?:\\b|_)" : ""}`;
this.regex = new RegExp(profanityPattern, "gi");
}

@@ -69,3 +103,2 @@ }

exports.profanity = new Profanity();
exports.default = exports.profanity;
//# sourceMappingURL=profanity.js.map
{
"name": "@2toad/profanity",
"version": "2.3.1",
"version": "2.4.0",
"description": "A JavaScript profanity filter",

@@ -17,3 +17,5 @@ "homepage": "https://github.com/2Toad/Profanity",

"local": "npm run build && concurrently -p \"none\" \"npx tsc --watch\" \"nodemon -q dist/index.js\"",
"test": "mocha -r ts-node/register -r mocha-suppress-logs tests/**/*.spec.ts",
"pretest": "npm run build",
"test": "mocha -r ts-node/register tests/**/*.spec.ts",
"test:watch": "npm run test -- --watch",
"lint": "eslint . --cache",

@@ -23,3 +25,3 @@ "lint:fix": "eslint . --cache --fix",

"prettier:fix": "prettier --write **/*.ts",
"prepublishOnly": "npm run lint && npm run prettier && npm run build && npm test",
"prepublishOnly": "npm run lint && npm run prettier && npm test",
"prepare": "husky"

@@ -34,14 +36,19 @@ },

"profane",
"obscenity",
"obscene",
"obscenity",
"obscenities",
"cussing",
"curse",
"cursing",
"swearing",
"swearwords",
"vulgar",
"swear-words",
"vulgarity",
"bad words",
"bad language",
"dirty words"
"badwords",
"bad-words",
"badlanguage",
"bad-language",
"dirtywords",
"dirty-words",
"censor",
"filter"
],

@@ -48,0 +55,0 @@ "devDependencies": {

@@ -17,3 +17,3 @@ # Profanity ๐Ÿงผ

>If you're using Node 11.x or older, you'll need to install [Profanity 1.x](https://github.com/2Toad/Profanity/releases) (e.g., `npm i @2toad/profanity@1.4.0`)
>If you're using Node 11.x or older, you'll need to install [Profanity 1.x](https://github.com/2Toad/Profanity/releases) (e.g., `npm i @2toad/profanity@1.4.1`)

@@ -23,7 +23,8 @@ ## Usage ๐Ÿ“š

```JavaScript
import { profanity } from '@2toad/profanity';
import { profanity, CensorType } from '@2toad/profanity';
// or
var profanity = require('@2toad/profanity').profanity;
const { profanity, CensorType } = require('@2toad/profanity');
```
```JavaScript
profanity.exists('I like big butts and I cannot lie');

@@ -46,10 +47,9 @@ // true

```JavaScript
import { Profanity, ProfanityOptions } from '@2toad/profanity';
import { Profanity } from '@2toad/profanity';
const options = new ProfanityOptions();
options.wholeWord = false;
options.grawlix = '*****';
options.grawlixChar = '$';
const profanity = new Profanity(options);
const profanity = new Profanity({
wholeWord: false,
grawlix: '*****',
grawlixChar: '$',
});
```

@@ -71,2 +71,19 @@

#### Compound Words
Profanity detection works on parts of compound words, rather than treating hyphenated or underscore-separated words as indivisible.
When `wholeWord` is `true`, each portion of a compound word is analyzed for a match:
```JavaScript
profanity.exists("Don't be an arsenic-monster");
// false
profanity.exists("Don't be an arse-monster");
// true (matched on arse)
```
Setting `wholeWord` to `false`, results in partial word matches on each portion of a compound word:
```JavaScript
profanity.exists("Don't be an arsenic-monster");
// true (matched on arse)
```
### grawlix ๐Ÿ’ฅ

@@ -73,0 +90,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with โšก๏ธ by Socket Inc