From 0cdc86c37df31f075b327e57ccf69980ea7da422 Mon Sep 17 00:00:00 2001 From: GDS K S <39922405+gagandua078@users.noreply.github.com> Date: Fri, 2 Aug 2024 19:17:20 -0500 Subject: [PATCH] New Enhancments Release --- .DS_Store | Bin 6148 -> 6148 bytes package.json | 17 ++--- src/App.tsx | 112 ++++++++++++++++++++++++++++--- src/filters/Filter.ts | 32 ++++++--- src/hooks/useProfanityChecker.ts | 30 +++++++-- src/index.ts | 4 +- src/index.tsx | 10 +++ src/types/Language.ts | 23 ------- src/types/types.ts | 30 +++++++++ tsconfig.json | 5 +- webpack.config.js | 11 +-- 11 files changed, 212 insertions(+), 62 deletions(-) create mode 100644 src/index.tsx delete mode 100644 src/types/Language.ts create mode 100644 src/types/types.ts diff --git a/.DS_Store b/.DS_Store index 5172429f264de2441865cb4700216d4256da9242..34ae22a891b7ba169777719d6b11517b8fcaae3d 100644 GIT binary patch delta 328 zcmZoMXfc=|#>B)qu~3YagMop8V`8C*EEA9c0?a_n$iN`LkW^k=kd%|31my47Sh$?A z9wfuUkiwA3P|Q$*ESpr2lUZD1U~r9*iJ66!jh&s7otr&2I3vG2xFoTpwAd-JC>q2I z$5S!Fq!;)4(#E zoE)6-0ut5LCdOtu3MLkowK@vbmPQ6ZwwXz7EhmSlvc7dte0EN5UVazQ!9c(W^bQ#C zLTMP)4P?MQR2E#6my@5DK2bw{WBL!4$p#`Uo4Gl-Ie_7`vG6dc2Vd6 delta 79 zcmZoMXfc=|#>AjHu~2yOXC@gzCI$##1X4gOz_5v#oprMU^9rWT>>T_YK$V*XnZGkn X<`+@q1gS{?DW7b@qr5prWCb$-J=P8z diff --git a/package.json b/package.json index 2bb0d59..df1e00e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "glin-profanity", - "version": "1.0.1", + "version": "1.1.0", "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.", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -9,8 +9,12 @@ "start": "webpack serve --mode development", "build": "webpack --mode production" }, - "keywords": [], - "author": "", + "repository": { + "type": "git", + "url": "https://github.com/GLINCKER/glin-profanity" + }, + "keywords": ["glin-profanity","glincker","glin","profanity"], + "author": "gdsks", "license": "ISC", "dependencies": { "react": "^18.3.1", @@ -27,12 +31,9 @@ "@typescript-eslint/eslint-plugin": "^7.18.0", "@typescript-eslint/parser": "^7.18.0", "babel-loader": "^9.1.3", - "eslint": "^8.57.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-prettier": "^5.2.1", + "eslint": "^8.57.0", "eslint-plugin-react": "^7.35.0", - "html-webpack-plugin": "^5.6.0", - "prettier": "^3.3.3", + "html-webpack-plugin": "^5.6.0", "typescript": "^5.5.4", "webpack": "^5.93.0", "webpack-cli": "^5.1.4", diff --git a/src/App.tsx b/src/App.tsx index fb6ff89..c0dccf9 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -4,9 +4,17 @@ import { useProfanityChecker } from './hooks/useProfanityChecker'; const App: React.FC = () => { const [text, setText] = useState(''); const [checkAllLanguages, setCheckAllLanguages] = useState(false); - const { result, checkText } = useProfanityChecker( - checkAllLanguages ? { allLanguages: true } : { languages: ['english', 'french'] } - ); + const [caseSensitive, setCaseSensitive] = useState(false); + const [wordBoundaries, setWordBoundaries] = useState(true); + const [customWords, setCustomWords] = useState([]); + const [uploadStatus, setUploadStatus] = useState(''); + + const { result, checkText } = useProfanityChecker({ + allLanguages: checkAllLanguages, + caseSensitive: caseSensitive, + wordBoundaries: wordBoundaries, + customWords: customWords, + }); const handleChange = (e: React.ChangeEvent) => { setText(e.target.value); @@ -16,26 +24,112 @@ const App: React.FC = () => { checkText(text); }; + const handleFileUpload = (e: React.ChangeEvent) => { + const file = e.target.files?.[0]; + if (file) { + const reader = new FileReader(); + reader.onload = (event) => { + try { + const words = JSON.parse(event.target?.result as string); + if (Array.isArray(words)) { + setCustomWords(words); + setUploadStatus('Custom words loaded successfully.'); + } else { + setUploadStatus('Invalid JSON format: expected an array of strings.'); + } + } catch (error) { + setUploadStatus('Error parsing JSON: ' + error.message); + } + }; + reader.readAsText(file); + } + }; + + const handleReset = () => { + setText(''); + setCheckAllLanguages(false); + setCaseSensitive(false); + setWordBoundaries(true); + setCustomWords([]); + setUploadStatus(''); + }; + return (

Welcome to Glin-Profanity

- - -
+ + + +
+
+ +
+
+ +
+
+ + {uploadStatus &&

{uploadStatus}

} +
+ {customWords.length > 0 && ( +
+

Custom Words:

+
    + {customWords.map((word, index) => ( +
  • {word}
  • + ))} +
+
+ )} {result && ( -
-

Contains Profanity: {result.containsProfanity ? 'Yes' : 'No'}

+
+

Contains Profanity: {result.containsProfanity ? 'Yes' : 'No'}

{result.containsProfanity && ( -

Profane Words: {result.profaneWords.join(', ')}

+

Profane Words: {result.profaneWords.join(', ')}

)}
)} diff --git a/src/filters/Filter.ts b/src/filters/Filter.ts index 6165ba9..3238b1f 100644 --- a/src/filters/Filter.ts +++ b/src/filters/Filter.ts @@ -1,16 +1,23 @@ import dictionary from '../data/dictionary'; -import { Language } from '../types/Language'; +import { Language, CheckProfanityResult } from '../types/types'; -interface CheckProfanityResult { - containsProfanity: boolean; - profaneWords: string[]; +interface FilterConfig { + languages?: Language[]; + allLanguages?: boolean; + caseSensitive?: boolean; + wordBoundaries?: boolean; + customWords?: string[]; } class Filter { private words: Set; + private caseSensitive: boolean; + private wordBoundaries: boolean; - constructor(config?: { languages?: Language[]; allLanguages?: boolean }) { + constructor(config?: FilterConfig) { let words: string[] = []; + this.caseSensitive = config?.caseSensitive ?? false; + this.wordBoundaries = config?.wordBoundaries ?? true; if (config?.allLanguages) { for (const lang in dictionary) { @@ -27,12 +34,19 @@ class Filter { }); } } + + if (config?.customWords) { + words = [...words, ...config.customWords]; + } + this.words = new Set(words); } isProfane(value: string): boolean { + const flags = this.caseSensitive ? 'g' : 'gi'; for (const word of this.words) { - const wordExp = new RegExp(`\\b${word.replace(/(\W)/g, '\\$1')}\\b`, 'gi'); + const boundary = this.wordBoundaries ? '\\b' : ''; + const wordExp = new RegExp(`${boundary}${word.replace(/(\W)/g, '\\$1')}${boundary}`, flags); if (wordExp.test(value)) return true; } return false; @@ -43,16 +57,16 @@ class Filter { const profaneWords: string[] = []; for (const word of words) { - if (this.words.has(word.toLowerCase())) { + if (this.isProfane(word)) { profaneWords.push(word); } } return { containsProfanity: profaneWords.length > 0, - profaneWords + profaneWords, }; } } -export { Filter, CheckProfanityResult }; +export { Filter }; diff --git a/src/hooks/useProfanityChecker.ts b/src/hooks/useProfanityChecker.ts index 4bf2600..3ebfd9e 100644 --- a/src/hooks/useProfanityChecker.ts +++ b/src/hooks/useProfanityChecker.ts @@ -1,10 +1,16 @@ import { useState } from 'react'; -import { Filter, CheckProfanityResult } from '../filters/Filter'; -import { Language } from '../types/Language'; +import { Filter } from '../filters/Filter'; +import { CheckProfanityResult, Language } from '../types/types'; interface ProfanityCheckerConfig { languages?: Language[]; allLanguages?: boolean; + caseSensitive?: boolean; + wordBoundaries?: boolean; + customWords?: string[]; + replaceWith?: string; + severityLevels?: boolean; + customActions?: (result: CheckProfanityResult) => void; } export const useProfanityChecker = (config?: ProfanityCheckerConfig) => { @@ -12,11 +18,27 @@ export const useProfanityChecker = (config?: ProfanityCheckerConfig) => { const filter = new Filter(config); const checkText = (text: string) => { - setResult(filter.checkProfanity(text)); + const checkResult = filter.checkProfanity(text); + setResult(checkResult); + if (config?.customActions) { + config.customActions(checkResult); + } + }; + + const checkTextAsync = async (text: string) => { + return new Promise((resolve) => { + const checkResult = filter.checkProfanity(text); + setResult(checkResult); + if (config?.customActions) { + config.customActions(checkResult); + } + resolve(checkResult); + }); }; return { result, - checkText + checkText, + checkTextAsync, }; }; diff --git a/src/index.ts b/src/index.ts index 4898688..0704ece 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,3 @@ -export { Filter, CheckProfanityResult } from './filters/Filter'; +export { Filter } from './filters/Filter'; export { useProfanityChecker } from './hooks/useProfanityChecker'; -export type { Language } from './types/Language'; +export type { Language, CheckProfanityResult } from './types/types'; diff --git a/src/index.tsx b/src/index.tsx new file mode 100644 index 0000000..f6e6d92 --- /dev/null +++ b/src/index.tsx @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import App from './App'; + +ReactDOM.render( + + + , + document.getElementById('root') +); diff --git a/src/types/Language.ts b/src/types/Language.ts deleted file mode 100644 index 92703a1..0000000 --- a/src/types/Language.ts +++ /dev/null @@ -1,23 +0,0 @@ -export type Language = -| 'arabic' -| 'chinese' -| 'czech' -| 'danish' -| 'english' -| 'esperanto' -| 'finnish' -| 'french' -| 'german' -| 'hindi' -| 'hungarian' -| 'italian' -| 'japanese' -| 'korean' -| 'norwegian' -| 'persian' -| 'polish' -| 'portuguese' -| 'russian' -| 'turkish' -| 'swedish' -| 'thai'; \ No newline at end of file diff --git a/src/types/types.ts b/src/types/types.ts new file mode 100644 index 0000000..39722a0 --- /dev/null +++ b/src/types/types.ts @@ -0,0 +1,30 @@ +// src/types/types.ts +export interface CheckProfanityResult { + containsProfanity: boolean; + profaneWords: string[]; + processedText?: string; + severityMap?: { [word: string]: number }; +} +export type Language = + | 'arabic' + | 'chinese' + | 'czech' + | 'danish' + | 'english' + | 'esperanto' + | 'finnish' + | 'french' + | 'german' + | 'hindi' + | 'hungarian' + | 'italian' + | 'japanese' + | 'korean' + | 'norwegian' + | 'persian' + | 'polish' + | 'portuguese' + | 'russian' + | 'turkish' + | 'swedish' + | 'thai'; diff --git a/tsconfig.json b/tsconfig.json index c09620d..85f5304 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { - "target": "ES5", - "module": "CommonJS", + "target": "es2015", + "module": "commonjs", "lib": [ "dom", "es2015" @@ -13,6 +13,7 @@ "moduleResolution": "node", "esModuleInterop": true, "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, "resolveJsonModule": true, "allowSyntheticDefaultImports": true }, diff --git a/webpack.config.js b/webpack.config.js index 2890aea..ecd92dd 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -2,10 +2,13 @@ const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { - entry: './src/index.ts', + entry: './src/index.ts', output: { path: path.resolve(__dirname, 'dist'), - filename: 'bundle.js' + filename: 'index.js', + libraryTarget: 'umd', + globalObject: 'this', + library: 'Glin-profanity' }, resolve: { extensions: ['.ts', '.tsx', '.js'] @@ -15,9 +18,7 @@ module.exports = { { test: /\.tsx?$/, exclude: /node_modules/, - use: { - loader: 'babel-loader' - } + use: 'babel-loader' } ] },