Skip to content

Commit

Permalink
update to v1.3.2
Browse files Browse the repository at this point in the history
  • Loading branch information
SkidGod4444 committed Oct 27, 2024
1 parent af6d4c9 commit 4774755
Show file tree
Hide file tree
Showing 10 changed files with 232 additions and 271 deletions.
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Changelog

## [Unreleased]

### Fixed
- **ProfanityResolver**: Updated the `errors` object structure in `ProfanityResolver` to align with expected test output.
- Previously, the error messages included an unnecessary nested object structure with both `isValid` and `message` properties.
- Now, only the `message` string is returned in `errors` when profanity is detected, following the format `{ type: "profanity", message: "Content flagged for: badword" }`.

### Changed
- **Validation Logic**: The `ProfanityResolver` was modified to:
- Store only the `message` string for profane fields, improving compatibility with expected test cases.
- Populate `errors` directly with the `message` string and `type`, instead of the full result object with `isValid` status.
- Ensure `validFields` and `errors` correctly separate valid and invalid fields based on profanity checks.

### Testing
- **Updated Tests**: Adjusted test cases to validate the refined `errors` object structure, ensuring that the resolved errors output matches expectations.

---

**Note:** This change does not impact the overall functionality of `ProfanityResolver` but improves consistency in output format for better test compatibility.
34 changes: 34 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# profanity-validator

A lightweight SDK for profanity filtering in forms. This library is designed to prevent bad word spam by validating user input and throwing errors if profanity is detected. Built to be flexible, it can be integrated easily into any HTML or JavaScript framework, including React, Next.js, and many more.

## Features

- **Profanity Filtering:** Automatically detects and validates user input against a predefined list of profane words.
- **Customizable:** Allows users to add their own custom profanity words to the validation.
- **Framework Agnostic:** Works seamlessly across different frameworks and libraries.
- **Error Handling:** Throws validation errors instead of replacing profanity words, preventing form submission.
- **Asynchronous Validation:** Uses an internal API [(profanity.dev)](https://www.profanity.dev/) to check for profanity, Built by [Josh](https://github.com/joschan21) .

## Installation

You can install the SDK via any nodejs package manager:

```bash
npm install profanity-validator
pnpm add profanity-validator
bun add profanity-validator
yarn add profanity-validator
```

## Contributing

We welcome contributions! Please feel free to submit a pull request or open an issue if you have suggestions or improvements.

## License

This project is licensed under the MIT License. See the [LICENSE](https://github.com/SkidGod4444/profanity-validator?tab=MIT-1-ov-file) file for details.

## Contact

For support or inquiries, please reach out to [connect.saidev@gmail.com](https://dub.sh/saidev-twitter) or join our [discord community!](https://l.devwtf.in/discord)
6 changes: 4 additions & 2 deletions docs/components/ui/input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import * as React from "react"

import { cn } from "@/lib/utils"

export interface InputProps
extends React.InputHTMLAttributes<HTMLInputElement> {}
export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
className?: string;
type: string;
}

const Input = React.forwardRef<HTMLInputElement, InputProps>(
({ className, type, ...props }, ref) => {
Expand Down
93 changes: 93 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,9 @@
"bugs": {
"url": "https://github.com/SkidGod4444/profanity-validator/issues"
},
"homepage": "https://github.com/SkidGod4444/profanity-validator#readme"
"homepage": "https://github.com/SkidGod4444/profanity-validator#readme",
"dependencies": {
"node-fetch": "^3.3.2",
"whatwg-fetch": "^3.6.20"
}
}
55 changes: 32 additions & 23 deletions src/core.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,21 @@
import { ProfanityConfig } from "./types";

export class Profanity {
private config: ProfanityConfig;

constructor(config: ProfanityConfig = {}) {
this.config = {
apiEndpoint: 'https://vector.profanity.dev',
apiHeaders: { 'Content-Type': 'application/json' },
skipApi: false,
excludeFields: [],
heat: 0.909,
...config
};
}

private async checkApi(text: string): Promise<{ isProfane: boolean; words: string[] }> {
if (this.config.skipApi) return { isProfane: false, words: [] };

try {
const response = await fetch(this.config.apiEndpoint!, {
const response = await fetch('https://vector.profanity.dev', {
method: 'POST',
headers: {
...this.config.apiHeaders,
},
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message: text }),
});

Expand All @@ -30,9 +24,23 @@ export class Profanity {
}

const data = await response.json();

let hasProfanity = false;
let profaneWords = [];

if(data){
if(this.config.heat! <= data.score) {
hasProfanity = data.isProfanity;
profaneWords = data.flaggedFor;
} else {
hasProfanity = false;
profaneWords = [];
}
}

return {
isProfane: data.hasProfanity,
words: data.profaneWords || []
isProfane: hasProfanity,
words: profaneWords,
};
} catch (error) {
console.error('API check failed:', error);
Expand All @@ -54,33 +62,34 @@ export class Profanity {
};
}

async validateField(value: string): Promise<true | string> {
if (typeof value !== 'string') return true;

async validateField(value: string): Promise<{ isValid: boolean; message?: string }> {
if (typeof value !== 'string') {
throw new Error("Field value must be a string");
}

const customCheck = this.checkCustomWords(value);
const apiCheck = await this.checkApi(value);

const detectedWords = Array.from(new Set([
...customCheck.words,
...apiCheck.words
]));

if (customCheck.isProfane || apiCheck.isProfane) {
return `Inappropriate content detected: ${detectedWords.join(', ')}`;
return { isValid: false, message: `Content flagged for: ${detectedWords.join(', ')}` };
}

return true;
return { isValid: true };
}


createValidator(fieldName: string) {
if (this.config.excludeFields?.includes(fieldName)) {
return undefined;
}

return async (value: string) => {
const result = await this.validateField(value);
return result === true ? true : result;
return result;
};
}
}

}
23 changes: 9 additions & 14 deletions src/resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,19 @@ export const ProfanityResolver = (profanity: Profanity) => {

await Promise.all(
Object.entries(values).map(async ([field, value]) => {
const result = await profanity.validateField(String(value));
if (result === true) {
validFields[field] = value;
const validator = profanity.createValidator(field);
if (!validator) return;

const result = await validator(String(value));
if (result.isValid === true) {
validFields[field] = value; // Populate validFields for valid fields
} else {
errors[field] = {
type: 'profanity',
message: result
};
errors[field] = { type: 'profanity', message: result.message };
}
})
);

// console.log("Valid Fields:", validFields);
// console.log("Errors:", errors);

return {
values: validFields,
errors
};
return { values: validFields, errors };
};
};

6 changes: 2 additions & 4 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
export interface ProfanityConfig {
customWords?: string[];
apiEndpoint?: string;
apiHeaders?: Record<string, string>;
skipApi?: boolean;
heat?: number;
excludeFields?: string[];
}

export interface ValidationError {
field: string;
message: string;
message: React.ReactNode | string;
detectedWords: string[];
}

Expand Down
Loading

0 comments on commit 4774755

Please sign in to comment.