Showing preview only (393K chars total). Download the full file or copy to clipboard to get everything.
Repository: Blaspsoft/blasp
Branch: main
Commit: e0a2ea52cbe7
Files: 84
Total size: 367.1 KB
Directory structure:
gitextract_qpmp_x7w/
├── .github/
│ └── workflows/
│ └── main.yml
├── .gitignore
├── .styleci.yml
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE.md
├── README.md
├── composer.json
├── config/
│ ├── blasp.php
│ └── languages/
│ ├── english.php
│ ├── french.php
│ ├── german.php
│ └── spanish.php
├── phpunit.xml
├── src/
│ ├── BlaspManager.php
│ ├── BlaspServiceProvider.php
│ ├── Blaspable.php
│ ├── Console/
│ │ ├── ClearCommand.php
│ │ ├── LanguagesCommand.php
│ │ └── TestCommand.php
│ ├── Core/
│ │ ├── Analyzer.php
│ │ ├── Contracts/
│ │ │ ├── DriverInterface.php
│ │ │ └── MaskStrategyInterface.php
│ │ ├── Dictionary.php
│ │ ├── Masking/
│ │ │ ├── CallbackMask.php
│ │ │ ├── CharacterMask.php
│ │ │ └── GrawlixMask.php
│ │ ├── MatchedWord.php
│ │ ├── Matchers/
│ │ │ ├── CompoundWordDetector.php
│ │ │ ├── FalsePositiveFilter.php
│ │ │ ├── PhoneticMatcher.php
│ │ │ └── RegexMatcher.php
│ │ ├── Normalizers/
│ │ │ ├── EnglishNormalizer.php
│ │ │ ├── FrenchNormalizer.php
│ │ │ ├── GermanNormalizer.php
│ │ │ ├── NullNormalizer.php
│ │ │ ├── SpanishNormalizer.php
│ │ │ └── StringNormalizer.php
│ │ ├── Result.php
│ │ └── Score.php
│ ├── Drivers/
│ │ ├── PatternDriver.php
│ │ ├── PhoneticDriver.php
│ │ ├── PipelineDriver.php
│ │ └── RegexDriver.php
│ ├── Enums/
│ │ └── Severity.php
│ ├── Events/
│ │ ├── ContentBlocked.php
│ │ ├── ModelProfanityDetected.php
│ │ └── ProfanityDetected.php
│ ├── Exceptions/
│ │ └── ProfanityRejectedException.php
│ ├── Facades/
│ │ └── Blasp.php
│ ├── Middleware/
│ │ └── CheckProfanity.php
│ ├── PendingCheck.php
│ ├── Rules/
│ │ └── Profanity.php
│ └── Testing/
│ └── BlaspFake.php
└── tests/
├── AllLanguagesApiTest.php
├── AllLanguagesDetectionTest.php
├── BladeDirectiveTest.php
├── BlaspCheckTest.php
├── BlaspCheckValidationTest.php
├── BlaspableTest.php
├── BypassVulnerabilityTest.php
├── CacheDriverConfigurationTest.php
├── ConfigurationLoaderLanguageTest.php
├── ConfigurationLoaderTest.php
├── CustomMaskCharacterTest.php
├── DetectionStrategyRegistryTest.php
├── EdgeCaseTest.php
├── EmptyInputTest.php
├── FrenchStringNormalizerTest.php
├── GermanStringNormalizerTest.php
├── Issue24Test.php
├── Issue32FalsePositiveTest.php
├── MiddlewareAliasTest.php
├── MultiLanguageDetectionConfigTest.php
├── MultiLanguageProfanityTest.php
├── PhoneticDriverTest.php
├── PipelineDriverTest.php
├── ProfanityExpressionGeneratorTest.php
├── ResultCachingTest.php
├── SeverityMapTest.php
├── SpanishStringNormalizerTest.php
├── StrMacroTest.php
├── TestCase.php
└── UuidFalsePositiveTest.php
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/workflows/main.yml
================================================
name: Run Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
# Step 1: Check out the repository
- name: Checkout code
uses: actions/checkout@v4
# Step 2: Set up PHP
- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: "8.2" # Set your desired PHP version
extensions: mbstring, dom, zip
# Step 3: Install Composer dependencies
- name: Install dependencies
run: composer install --no-interaction --prefer-dist
# Step 4: Run PHPUnit tests
- name: Run tests
run: php ./vendor/bin/phpunit
================================================
FILE: .gitignore
================================================
/vendor
composer.lock
.phpunit.result.cache
/.idea
================================================
FILE: .styleci.yml
================================================
preset: laravel
disabled:
- single_class_element_per_statement
================================================
FILE: CHANGELOG.md
================================================
# Changelog
All notable changes to `blasp` will be documented in this file
## 3.0.0 - 2025-01-05
### Added
- Custom mask character support with `maskWith()` method
- Simplified API with Laravel facade pattern and method chaining
- Comprehensive multi-language support (Spanish, German, French)
- Expanded test coverage across all languages
- Comprehensive extensibility system with full test coverage
- Basic registry pattern for language normalizers
- Language files publishing to ServiceProvider
- Comprehensive documentation for maskWith() and all chainable methods
### Changed
- Implemented dependency injection and simplified service dependencies
- Extracted expression generation logic to dedicated generator
- Improved substitution detection across all languages
- Updated README with simplified chainable API documentation
- Updated README with comprehensive multi-language support documentation
- Updated README with language files publishing options
- Updated README for v3.0 features
### Fixed
- Resolved language switching not loading correct profanities
- Prevented cross-word-boundary profanity matches
### Removed
- Strategy factory, plugin manager, and default detection strategy
- Domain-specific detection strategies (email, URL, phone)
- Unused strict() and lenient() detection modes
- README duplications and outdated references
## 1.0.0 - 201X-XX-XX
- initial release
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing
Contributions are **welcome** and will be fully **credited**.
Please read and understand the contribution guide before creating an issue or pull request.
## Etiquette
This project is open source, and as such, the maintainers give their free time to build and maintain the source code
held within. They make the code freely available in the hope that it will be of use to other developers. It would be
extremely unfair for them to suffer abuse or anger for their hard work.
Please be considerate towards maintainers when raising issues or presenting pull requests. Let's show the
world that developers are civilized and selfless people.
It's the duty of the maintainer to ensure that all submissions to the project are of sufficient
quality to benefit the project. Many developers have different skillsets, strengths, and weaknesses. Respect the maintainer's decision, and do not be upset or abusive if your submission is not used.
## Viability
When requesting or submitting new features, first consider whether it might be useful to others. Open
source projects are used by many developers, who may have entirely different needs to your own. Think about
whether or not your feature is likely to be used by other users of the project.
## Procedure
Before filing an issue:
- Attempt to replicate the problem, to ensure that it wasn't a coincidental incident.
- Check to make sure your feature suggestion isn't already present within the project.
- Check the pull requests tab to ensure that the bug doesn't have a fix in progress.
- Check the pull requests tab to ensure that the feature isn't already in progress.
Before submitting a pull request:
- Check the codebase to ensure that your feature doesn't already exist.
- Check the pull requests to ensure that another person hasn't already submitted the feature or fix.
## Requirements
If the project maintainer has any additional requirements, you will find them listed here.
- **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](https://pear.php.net/package/PHP_CodeSniffer).
- **Add tests!** - Your patch won't be accepted if it doesn't have tests.
- **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date.
- **Consider our release cycle** - We try to follow [SemVer v2.0.0](https://semver.org/). Randomly breaking public APIs is not an option.
- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests.
- **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please [squash them](https://www.git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages) before submitting.
**Happy coding**!
================================================
FILE: LICENSE.md
================================================
MIT License
Copyright (c) Michael Deeming
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
<p align="center">
<img src="./assets/icon.png" alt="Blasp Icon" width="150" height="150"/>
</p>
> **Official API Available!** This package powers [blasp.app](https://blasp.app/) - a universal profanity filtering REST API that works with any language. Free tier with 1,000 requests/month, multi-language support, and custom word lists.
<p align="center">
<a href="https://github.com/Blaspsoft/blasp/actions/workflows/main.yml"><img alt="GitHub Workflow Status (main)" src="https://github.com/Blaspsoft/blasp/actions/workflows/main.yml/badge.svg"></a>
<a href="https://packagist.org/packages/blaspsoft/blasp"><img alt="Total Downloads" src="https://img.shields.io/packagist/dt/blaspsoft/blasp"></a>
<a href="https://packagist.org/packages/blaspsoft/blasp"><img alt="Latest Version" src="https://img.shields.io/packagist/v/blaspsoft/blasp"></a>
<a href="https://packagist.org/packages/blaspsoft/blasp"><img alt="License" src="https://img.shields.io/packagist/l/blaspsoft/blasp"></a>
</p>
# Blasp - Advanced Profanity Filter for Laravel
Blasp is a powerful, extensible profanity filter for Laravel. Version 4 is a ground-up rewrite with a driver-based architecture, severity scoring, masking strategies, Eloquent model integration, and a clean fluent API.
## Features
- **Driver Architecture** — `regex` (detects obfuscation, substitutions, separators), `pattern` (fast exact matching), `phonetic` (catches sound-alike evasions), or `pipeline` (chains multiple drivers together). Extend with custom drivers.
- **Multi-Language** — English, Spanish, German, French with language-specific normalizers. Check one, many, or all at once.
- **Severity Scoring** — Words categorised as mild/moderate/high/extreme. Filter by minimum severity and get a 0-100 score.
- **Masking Strategies** — Character mask (`*`, `#`), grawlix (`!@#$%`), or a custom callback.
- **Eloquent Integration** — `Blaspable` trait auto-sanitizes or rejects profanity on model save.
- **Middleware** — Reject or sanitize profane request fields with configurable severity.
- **Validation Rules** — Fluent validation rule with language, severity, and score threshold support.
- **Testing Utilities** — `Blasp::fake()` for test doubles with assertions.
- **Events** — `ProfanityDetected`, `ContentBlocked`, and `ModelProfanityDetected`.
## Requirements
- PHP 8.2+
- Laravel 8.0+
## Installation
```bash
composer require blaspsoft/blasp
```
Publish configuration:
```bash
# Everything (config + language files)
php artisan vendor:publish --tag="blasp"
# Config only
php artisan vendor:publish --tag="blasp-config"
# Language files only
php artisan vendor:publish --tag="blasp-languages"
```
## Quick Start
```php
use Blaspsoft\Blasp\Facades\Blasp;
$result = Blasp::check('This is a fucking sentence');
$result->isOffensive(); // true
$result->clean(); // "This is a ******* sentence"
$result->original(); // "This is a fucking sentence"
$result->score(); // 30
$result->count(); // 1
$result->uniqueWords(); // ['fucking']
$result->severity(); // Severity::High
```
## Fluent API
All builder methods return a `PendingCheck` and can be chained:
```php
// Language selection
Blasp::in('spanish')->check($text);
Blasp::in('english', 'french')->check($text);
Blasp::inAllLanguages()->check($text);
// Language shortcuts
Blasp::english()->check($text);
Blasp::spanish()->check($text);
Blasp::german()->check($text);
Blasp::french()->check($text);
// Driver selection
Blasp::driver('regex')->check($text); // Full obfuscation detection (default)
Blasp::driver('pattern')->check($text); // Fast exact matching
Blasp::driver('phonetic')->check($text); // Sound-alike detection (e.g. "phuck", "sheit")
Blasp::driver('pipeline')->check($text); // Chain multiple drivers (config-based)
// Ad-hoc pipeline — chain any drivers without config
Blasp::pipeline('regex', 'phonetic')->check($text);
Blasp::pipeline('pattern', 'phonetic')->in('english')->mask('#')->check($text);
// Shorthand modes
Blasp::strict()->check($text); // Forces regex driver
Blasp::lenient()->check($text); // Forces pattern driver
// Masking
Blasp::mask('*')->check($text); // Character mask (default)
Blasp::mask('#')->check($text); // Custom character
Blasp::mask('grawlix')->check($text); // !@#$% cycling
Blasp::mask(fn($word, $len) => '[CENSORED]')->check($text); // Callback
// Severity filtering
use Blaspsoft\Blasp\Enums\Severity;
Blasp::withSeverity(Severity::High)->check($text); // Ignores mild/moderate
// Allow/block lists (merged with config)
Blasp::allow('damn', 'hell')->check($text);
Blasp::block('customword')->check($text);
// Chain everything
Blasp::spanish()
->mask('#')
->withSeverity(Severity::Moderate)
->check($text);
// Batch checking
$results = Blasp::checkMany(['text one', 'text two']);
```
## Result Object
The `Result` object is returned by every `check()` call:
| Method | Returns | Description |
|--------|---------|-------------|
| `isOffensive()` | `bool` | Text contains profanity |
| `isClean()` | `bool` | Text is clean |
| `clean()` | `string` | Text with profanities masked |
| `original()` | `string` | Original unmodified text |
| `score()` | `int` | Severity score (0-100) |
| `count()` | `int` | Total profanity matches |
| `uniqueWords()` | `array` | Unique base words detected |
| `severity()` | `?Severity` | Highest severity in matches |
| `words()` | `Collection` | `MatchedWord` objects with position, length, severity |
| `toArray()` | `array` | Full result as array |
| `toJson()` | `string` | Full result as JSON |
`Result` implements `JsonSerializable`, `Stringable` (returns clean text), and `Countable`.
## Detection Types
The regex driver detects obfuscated profanity:
| Type | Example | Detected As |
|------|---------|-------------|
| Straight match | `fucking` | `fucking` |
| Substitution | `fÛck!ng`, `f4ck` | `fucking`, `fuck` |
| Separators | `f-u-c-k-i-n-g`, `f@ck` | `fucking`, `fuck` |
| Doubled | `ffuucckkiinngg` | `fucking` |
| Combination | `f-uuck!ng` | `fucking` |
> **Separator limit:** The regex driver allows up to 3 separator characters between each letter (e.g., `f--u--c--k`). This covers all realistic obfuscation patterns while keeping regex complexity low enough for PHP-FPM environments.
The pattern driver only detects straight word-boundary matches.
The phonetic driver uses `metaphone()` + Levenshtein distance to catch words that *sound like* profanity but are spelled differently:
| Type | Example | Detected As |
|------|---------|-------------|
| Phonetic spelling | `phuck` | `fuck` |
| Shortened form | `fuk` | `fuck` |
| Sound-alike | `sheit` | `shit` |
Configure sensitivity in `config/blasp.php` under `drivers.phonetic`. A curated false-positive list prevents common words like "fork", "duck", and "beach" from being flagged.
### Pipeline Driver
The pipeline driver chains multiple drivers together so a single `check()` call runs all of them. It uses **union merge** semantics — text is flagged if **any** driver finds a match.
```php
// Config-based: set 'default' => 'pipeline' or use driver('pipeline')
Blasp::driver('pipeline')->check('phuck this sh1t');
// Ad-hoc: pick drivers on the fly (no config needed)
Blasp::pipeline('regex', 'phonetic')->check('phuck this sh1t');
Blasp::pipeline('regex', 'pattern', 'phonetic')->check($text);
```
When multiple drivers detect the same word at the same position, duplicates are removed — only the longest match is kept. Masks are applied from the merged result, and the score is recalculated across all matches.
Configure the default sub-drivers in `config/blasp.php`:
```php
'drivers' => [
'pipeline' => [
'drivers' => ['regex', 'phonetic'], // Drivers to chain
],
],
```
## Eloquent Integration
The `Blaspable` trait automatically checks model attributes during save:
```php
use Blaspsoft\Blasp\Blaspable;
class Comment extends Model
{
use Blaspable;
protected array $blaspable = ['body', 'title'];
}
```
```php
// Sanitize mode (default) — profanity is masked, model saves
$comment = Comment::create(['body' => 'This is fucking great']);
$comment->body; // "This is ******* great"
// Check what happened
$comment->hadProfanity(); // true
$comment->blaspResults(); // ['body' => Result, 'title' => Result]
$comment->blaspResult('body'); // Result instance
```
### Per-Model Overrides
```php
class Comment extends Model
{
use Blaspable;
protected array $blaspable = ['body', 'title'];
protected string $blaspMode = 'reject'; // 'sanitize' (default) | 'reject'
protected string $blaspLanguage = 'spanish'; // null = config default
protected string $blaspMask = '#'; // null = config default
}
```
### Reject Mode
In reject mode, saving a model with profanity throws `ProfanityRejectedException` and the model is not persisted:
```php
use Blaspsoft\Blasp\Exceptions\ProfanityRejectedException;
try {
$comment = Comment::create(['body' => 'profane text']);
} catch (ProfanityRejectedException $e) {
$e->attribute; // 'body'
$e->result; // Result instance
$e->model; // The unsaved model
}
```
### Disabling Checking
```php
Comment::withoutBlaspChecking(function () {
Comment::create(['body' => 'unchecked content']);
});
```
### Events
A `ModelProfanityDetected` event fires whenever profanity is detected on a model attribute (both sanitize and reject modes):
```php
use Blaspsoft\Blasp\Events\ModelProfanityDetected;
Event::listen(ModelProfanityDetected::class, function ($event) {
$event->model; // The model instance
$event->attribute; // Which attribute had profanity
$event->result; // Result instance
});
```
## Middleware
Use `CheckProfanity` to filter incoming request fields. A `blasp` middleware alias is registered automatically:
```php
// Using the short alias (recommended)
Route::post('/comment', CommentController::class)
->middleware('blasp');
// With parameters: action, severity
Route::post('/comment', CommentController::class)
->middleware('blasp:sanitize,mild');
// Or using the class directly
use Blaspsoft\Blasp\Middleware\CheckProfanity;
Route::post('/comment', CommentController::class)
->middleware(CheckProfanity::class);
```
| Action | Behaviour |
|--------|-----------|
| `reject` (default) | Returns 422 JSON with field errors |
| `sanitize` | Replaces profane fields in the request and continues |
Configure which fields to check in `config/blasp.php`:
```php
'middleware' => [
'action' => 'reject',
'fields' => ['*'], // '*' = all fields
'except' => ['password', 'email', '_token'], // Always skipped
'severity' => 'mild',
],
```
## Validation Rules
### String Rule
```php
$request->validate([
'comment' => ['required', 'blasp_check'],
'bio' => ['required', 'blasp_check:spanish'],
]);
```
### Fluent Rule Object
```php
use Blaspsoft\Blasp\Rules\Profanity;
use Blaspsoft\Blasp\Enums\Severity;
$request->validate([
'comment' => ['required', Profanity::in('english')],
'bio' => ['required', Profanity::severity(Severity::High)],
'tagline' => ['required', Profanity::maxScore(50)],
]);
```
## Blade Directive
The `@clean` directive sanitizes and escapes text for safe display in views:
```blade
<p>@clean($comment->body)</p>
{{-- Equivalent to: {{ app('blasp')->check($comment->body)->clean() }} --}}
```
Output is HTML-escaped via `e()` for XSS safety.
## Str / Stringable Macros
Blasp registers macros on Laravel's `Str` and `Stringable` classes:
```php
use Illuminate\Support\Str;
// Static methods
Str::isProfane('fuck this'); // true
Str::isProfane('hello'); // false
Str::cleanProfanity('fuck this'); // '**** this'
Str::cleanProfanity('hello'); // 'hello'
// Fluent Stringable methods
Str::of('fuck this')->isProfane(); // true
Str::of('fuck this')->cleanProfanity(); // Stringable('**** this')
Str::of('hello')->cleanProfanity()->upper(); // 'HELLO' (chaining works)
```
## Configuration
Full `config/blasp.php` reference:
```php
return [
'default' => env('BLASP_DRIVER', 'regex'), // 'regex' | 'pattern' | 'phonetic' | 'pipeline'
'language' => env('BLASP_LANGUAGE', 'english'), // Default language
'mask' => '*', // Default mask character
'severity' => 'mild', // Minimum severity
'events' => false, // Fire ProfanityDetected events
'cache' => [
'enabled' => true,
'driver' => env('BLASP_CACHE_DRIVER'),
'ttl' => 86400,
'results' => true, // Cache check() results by content hash
],
'middleware' => [
'action' => 'reject',
'fields' => ['*'],
'except' => ['password', 'email', '_token'],
'severity' => 'mild',
],
'model' => [
'mode' => env('BLASP_MODEL_MODE', 'sanitize'), // 'sanitize' | 'reject'
],
'drivers' => [
'pipeline' => [
'drivers' => ['regex', 'phonetic'], // Sub-drivers to chain
],
'phonetic' => [
'phonemes' => 4, // metaphone code length (2-8)
'min_word_length' => 3, // skip short words
'max_distance_ratio' => 0.6, // levenshtein threshold (0.3-0.8)
'supported_languages' => ['english'], // metaphone is English-oriented
'false_positives' => ['fork', '...'], // never flag these words
],
],
'allow' => [], // Global allow-list
'block' => [], // Global block-list
'separators' => [...], // Characters treated as separators
'substitutions' => [...], // Character leet-speak mappings
'false_positives' => [...], // Words that should never be flagged
];
```
## Custom Drivers
Implement `DriverInterface` and register with the manager:
```php
use Blaspsoft\Blasp\Core\Contracts\DriverInterface;
use Blaspsoft\Blasp\Core\Result;
use Blaspsoft\Blasp\Core\Dictionary;
use Blaspsoft\Blasp\Core\Contracts\MaskStrategyInterface;
class MyDriver implements DriverInterface
{
public function detect(string $text, Dictionary $dictionary, MaskStrategyInterface $mask, array $options = []): Result
{
// Your detection logic
}
}
// Register in a service provider
Blasp::extend('my-driver', fn($app) => new MyDriver());
// Use it
Blasp::driver('my-driver')->check($text);
```
## Caching
Blasp caches `check()` results by default. When the same text is checked with the same configuration (language, driver, severity, allow/block lists), the cached result is returned instantly.
```php
// First call — runs full analysis, caches result
$result = Blasp::check('some text');
// Second call — returns cached result
$result = Blasp::check('some text');
```
Configure caching in `config/blasp.php`:
```php
'cache' => [
'enabled' => true, // Master switch for all caching
'driver' => env('BLASP_CACHE_DRIVER'), // null = default cache driver
'ttl' => 86400, // Cache lifetime in seconds
'results' => true, // Cache check() results (disable independently)
],
```
Result caching is automatically bypassed when using a `CallbackMask` (closures can't be serialized). Clear both dictionary and result caches with:
```bash
php artisan blasp:clear
```
Or programmatically:
```php
Dictionary::clearCache();
```
## Artisan Commands
```bash
# Clear the profanity cache
php artisan blasp:clear
# Test text from the command line
php artisan blasp:test "some text to check" --lang=english --detail
# List available languages with word counts
php artisan blasp:languages
```
## Testing
### Faking
```php
use Blaspsoft\Blasp\Facades\Blasp;
use Blaspsoft\Blasp\Core\Result;
// Replace with a fake — all checks return clean by default
Blasp::fake();
// Pre-configure specific responses
Blasp::fake([
'bad text' => Result::withMatches(['fuck']),
'clean text' => Result::none('clean text'),
]);
$result = Blasp::check('bad text');
$result->isOffensive(); // true
// Assertions
Blasp::assertChecked();
Blasp::assertCheckedTimes(1);
Blasp::assertCheckedWith('bad text');
```
### Disabling Filtering
```php
Blasp::withoutFiltering(function () {
// All checks return clean results
});
```
## Events
Enable global events with `'events' => true` in config:
| Event | Fired When | Properties |
|-------|------------|------------|
| `ProfanityDetected` | `check()` finds profanity | `result`, `originalText` |
| `ContentBlocked` | Middleware detects profanity | `result`, `request`, `field`, `action` |
| `ModelProfanityDetected` | Blaspable trait detects profanity | `model`, `attribute`, `result` |
`ModelProfanityDetected` always fires (not gated by the `events` config).
## Migrating from v3
### Namespace Changes
| v3 | v4 |
|----|-----|
| `Blaspsoft\Blasp\Facades\Blasp` | `Blaspsoft\Blasp\Facades\Blasp` (unchanged) |
| `Blaspsoft\Blasp\ServiceProvider` | `Blaspsoft\Blasp\BlaspServiceProvider` |
The Laravel auto-discovery handles provider/alias registration automatically. The facade namespace is the same as v3, so no import changes are needed for the facade.
### Config Changes
| v3 Key | v4 Key | Notes |
|--------|--------|-------|
| `default_language` | `language` | `default_language` still works as alias |
| `mask_character` | `mask` | `mask_character` still works as alias |
| `cache_driver` | `cache.driver` | `cache_driver` still works as alias |
| — | `default` | New: driver selection (`regex`/`pattern`) |
| — | `severity` | New: minimum severity level |
| — | `events` | New: enable global events |
| — | `allow` / `block` | New: global allow/block lists |
| — | `middleware` | New: middleware configuration section |
| — | `model` | New: Blaspable trait configuration |
### Result API Changes
| v3 Method | v4 Method |
|-----------|-----------|
| `hasProfanity()` | `isOffensive()` |
| `getCleanString()` | `clean()` |
| `getSourceString()` | `original()` |
| `getProfanitiesCount()` | `count()` |
| `getUniqueProfanitiesFound()` | `uniqueWords()` |
All v3 methods still work as deprecated aliases.
### Builder API Changes
| v3 Method | v4 Method |
|-----------|-----------|
| `maskWith($char)` | `mask($char)` |
| `allLanguages()` | `inAllLanguages()` |
| `language($lang)` | `in($lang)` |
| `configure($profanities, $falsePositives)` | `block(...$words)` / `allow(...$words)` |
All v3 methods still work as deprecated aliases.
### New in v4
- **Driver architecture** — `regex` and `pattern` drivers, custom driver support
- **Severity system** — Mild/Moderate/High/Extreme levels with scoring
- **Masking strategies** — Grawlix and callback masking
- **Blaspable trait** — Automatic Eloquent model profanity checking
- **Middleware** — Request-level profanity filtering
- **Fluent validation rule** — `Profanity::in('spanish')->severity(Severity::High)`
- **Testing utilities** — `Blasp::fake()`, assertions, `withoutFiltering()`
- **Events** — `ProfanityDetected`, `ContentBlocked`, `ModelProfanityDetected`
- **Artisan commands** — `blasp:clear`, `blasp:test`, `blasp:languages`
- **Batch checking** — `Blasp::checkMany([...])`
- **Multi-language in one call** — `Blasp::in('english', 'spanish')->check($text)`
## Contributing
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
## Changelog
See [CHANGELOG.md](CHANGELOG.md) for detailed version history.
## License
Blasp is open-sourced software licensed under the [MIT license](LICENSE).
================================================
FILE: composer.json
================================================
{
"name": "blaspsoft/blasp",
"description": "Blasp is a powerful and customisable profanity filter package for Laravel applications",
"keywords": [
"blaspsoft",
"blasp"
],
"homepage": "https://github.com/blaspsoft/blasp",
"license": "MIT",
"type": "library",
"authors": [
{
"name": "Michael Deeming",
"email": "michael.deeming90@gmail.com",
"role": "Developer"
}
],
"require": {
"php": "^8.2",
"illuminate/support": "^8.0|^9.0|^10.0|^11.0|^12.0|^13.0"
},
"require-dev": {
"orchestra/testbench": "^10.0|^11.0",
"phpunit/phpunit": "^11.0|^12.5.12"
},
"autoload": {
"psr-4": {
"Blaspsoft\\Blasp\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Blaspsoft\\Blasp\\Tests\\": "tests"
}
},
"minimum-stability": "stable",
"prefer-stable": true,
"scripts": {
"test": "vendor/bin/phpunit",
"test-coverage": "vendor/bin/phpunit --coverage-html coverage"
},
"config": {
"sort-packages": true
},
"extra": {
"laravel": {
"providers": [
"Blaspsoft\\Blasp\\BlaspServiceProvider"
],
"aliases": {
"Blasp": "Blaspsoft\\Blasp\\Facades\\Blasp"
}
}
}
}
================================================
FILE: config/blasp.php
================================================
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Driver
|--------------------------------------------------------------------------
|
| The default detection driver. 'regex' provides full obfuscation
| detection. 'pattern' is faster but only matches exact words.
|
*/
'default' => env('BLASP_DRIVER', 'regex'),
/*
|--------------------------------------------------------------------------
| Default Language
|--------------------------------------------------------------------------
|
| The default language to use for profanity detection.
|
*/
'language' => env('BLASP_LANGUAGE', 'english'),
// Backward compat alias
'default_language' => env('BLASP_LANGUAGE', 'english'),
/*
|--------------------------------------------------------------------------
| Mask Character
|--------------------------------------------------------------------------
|
| The character used to mask detected profanities.
|
*/
'mask' => '*',
// Backward compat alias
'mask_character' => '*',
/*
|--------------------------------------------------------------------------
| Minimum Severity
|--------------------------------------------------------------------------
|
| The minimum severity level to detect. Words below this severity
| will be ignored. Options: mild, moderate, high, extreme
|
*/
'severity' => 'mild',
/*
|--------------------------------------------------------------------------
| Events
|--------------------------------------------------------------------------
|
| When enabled, ProfanityDetected events will be fired automatically
| when profanity is found during a check.
|
*/
'events' => false,
/*
|--------------------------------------------------------------------------
| Cache Configuration
|--------------------------------------------------------------------------
*/
'cache' => [
'enabled' => true,
'driver' => env('BLASP_CACHE_DRIVER'),
'ttl' => 86400,
'results' => true,
],
// Backward compat alias
'cache_driver' => env('BLASP_CACHE_DRIVER'),
/*
|--------------------------------------------------------------------------
| Middleware Configuration
|--------------------------------------------------------------------------
*/
'middleware' => [
'action' => 'reject',
'fields' => ['*'],
'except' => ['password', 'email', '_token'],
'severity' => 'mild',
],
/*
|--------------------------------------------------------------------------
| Model Configuration
|--------------------------------------------------------------------------
|
| Controls how the Blaspable trait behaves on Eloquent models.
| 'sanitize' replaces profanity with the mask character.
| 'reject' throws a ProfanityRejectedException instead of saving.
|
*/
'model' => [
'mode' => env('BLASP_MODEL_MODE', 'sanitize'),
],
/*
|--------------------------------------------------------------------------
| Driver-Specific Configuration
|--------------------------------------------------------------------------
*/
'drivers' => [
'pipeline' => [
'drivers' => ['regex', 'phonetic'],
],
'phonetic' => [
'phonemes' => 4, // metaphone code length (2-8, lower=more aggressive)
'min_word_length' => 3, // skip words shorter than this
'max_distance_ratio' => 0.6, // levenshtein threshold (0.3-0.8, lower=stricter)
'supported_languages' => ['english'],
'false_positives' => [
'fork', 'forked', 'forking',
'beach', 'beaches',
'witch', 'witches',
'sheet', 'sheets',
'deck', 'decks',
'count', 'counts', 'counter', 'county',
'ship', 'shipped', 'shipping',
'duck', 'ducked', 'ducking',
'fudge', 'fudging',
'buck', 'bucks',
'puck', 'pucks',
'bass',
'mass',
'pass', 'passed',
'heck',
'shoot', 'shot',
'what', 'white', 'while', 'whole',
],
],
],
/*
|--------------------------------------------------------------------------
| Character Separators
|--------------------------------------------------------------------------
*/
'separators' => [
'@', '#', '%', '&', '_', ';', "'", '"', ',', '~', '`', '|',
'!', '$', '^', '*', '(', ')', '-', '+', '=', '{', '}',
'[', ']', ':', '<', '>', '?', '.', '/',
],
/*
|--------------------------------------------------------------------------
| Character Substitutions
|--------------------------------------------------------------------------
*/
'substitutions' => [
'/a/' => ['a', '4', '@', '*', 'Á', 'á', 'À', 'Â', 'à', 'Â', 'â', 'Ä', 'ä', 'Ã', 'ã', 'Å', 'å', 'æ', 'Æ', 'α', 'Δ', 'Λ', 'λ'],
'/b/' => ['b', '8', '\\', '3', '*', 'ß', 'Β', 'β'],
'/c/' => ['c', '*', 'Ç', 'ç', 'ć', 'Ć', 'č', 'Č', '¢', '€', '<', '(', '{', '©'],
'/d/' => ['d', '*', '\\', ')', 'Þ', 'þ', 'Ð', 'ð'],
'/e/' => ['e', '3', '*', '€', 'È', 'è', 'É', 'é', 'Ê', 'ê', 'ë', 'Ë', 'ē', 'Ē', 'ė', 'Ė', 'ę', 'Ę', '∑'],
'/f/' => ['f', '*', 'ƒ'],
'/g/' => ['g', '6', '9', '*'],
'/h/' => ['h', '*', 'Η'],
'/i/' => ['i', '!', '|', ']', '[', '1', '*', '∫', 'Ì', 'Í', 'Î', 'Ï', 'ì', 'í', 'î', 'ï', 'ī', 'Ī', 'į', 'Į'],
'/j/' => ['j', '*'],
'/k/' => ['k', '*', 'Κ', 'κ'],
'/l/' => ['l', '!', '|', ']', '[', '*', '£', '∫', 'Ì', 'Í', 'Î', 'Ï', 'ł', 'Ł'],
'/m/' => ['m', '*'],
'/n/' => ['n', '*', 'η', 'Ν', 'Π', 'ñ', 'Ñ', 'ń', 'Ń'],
'/o/' => ['o', '0', '*', 'Ο', 'ο', 'Φ', '¤', '°', 'ø', 'ô', 'Ô', 'ö', 'Ö', 'ò', 'Ò', 'ó', 'Ó', 'œ', 'Œ', 'ø', 'Ø', 'ō', 'Ō', 'õ', 'Õ'],
'/p/' => ['p', '*', 'ρ', 'Ρ', '¶', 'þ'],
'/q/' => ['q', '*'],
'/r/' => ['r', '*', '®'],
'/s/' => ['s', '5', '*', '\$', '§', 'ß', 'Ś', 'ś', 'Š', 'š'],
'/t/' => ['t', '*', 'Τ', 'τ'],
'/u/' => ['u', 'υ', 'µ', 'û', 'ü', 'ù', 'ú', 'ū', 'Û', 'Ü', 'Ù', 'Ú', 'Ū', '@', '*'],
'/v/' => ['v', '*', 'υ', 'ν'],
'/w/' => ['w', '*', 'ω', 'ψ', 'Ψ'],
'/x/' => ['x', '*', 'Χ', 'χ'],
'/y/' => ['y', '*', '¥', 'γ', 'ÿ', 'ý', 'Ÿ', 'Ý'],
'/z/' => ['z', '*', 'Ζ', 'ž', 'Ž', 'ź', 'Ź', 'ż', 'Ż'],
],
/*
|--------------------------------------------------------------------------
| False Positives
|--------------------------------------------------------------------------
*/
'false_positives' => [
'hello', 'scunthorpe', 'cockburn', 'penistone', 'lightwater',
'assume', 'bass', 'class', 'compass', 'pass',
'dickinson', 'middlesex', 'cockerel', 'butterscotch', 'blackcock',
'countryside', 'arsenal', 'flick', 'flicker', 'analyst',
'cocktail', 'musicals hit', 'is hit', 'blackcocktail', 'its not',
],
/*
|--------------------------------------------------------------------------
| Global Allow List
|--------------------------------------------------------------------------
|
| Words in this list will never be flagged as profanity.
|
*/
'allow' => [],
/*
|--------------------------------------------------------------------------
| Global Block List
|--------------------------------------------------------------------------
|
| Additional words to always flag as profanity.
|
*/
'block' => [],
/*
|--------------------------------------------------------------------------
| Backward Compatibility: Profanities
|--------------------------------------------------------------------------
|
| Basic profanity list for backward compatibility.
| Full lists are in config/languages/*.php
|
*/
'profanities' => [
'fuck', 'shit', 'damn', 'bitch', 'ass', 'hell',
],
];
================================================
FILE: config/languages/english.php
================================================
<?php
return [
'severity' => [
'mild' => [
'damn', 'hell', 'crap', 'arse', 'sucks', 'piss', 'bloody',
'bollocks', 'bugger', 'crikey', 'darn', 'heck', 'turd',
'puke', 'puuke', 'puuker', 'shat', 'trots', 'vomit',
'waysted', 'wuss', 'wuzzie',
],
'moderate' => [
'ass', 'bitch', 'bastard', 'slut', 'whore', 'douche',
'douchebag', 'skank', 'slag', 'tramp', 'tosser', 'wanker',
'wanking', 'prick', 'dick', 'knob', 'bellend', 'minger',
'git', 'twit', 'dipshit', 'jackass', 'smartass', 'dumbass',
'asshole', 'arsehole', 'shag', 'shagger', 'shagging',
'hooker', 'hussy', 'floozy', 'tart', 'sissy', 'pansy',
],
'high' => [
'fuck', 'shit', 'cock', 'pussy', 'cunt', 'twat', 'tit', 'tits',
'fucking', 'fucker', 'motherfucker', 'bullshit', 'horseshit',
'shithead', 'shithole', 'shitface', 'fuckface', 'fuckhead',
'cocksucker', 'asswipe', 'clusterfuck', 'mindfuck',
'dumbfuck', 'fuckwit', 'shitbag', 'shitcunt',
'thundercunt', 'cum', 'jizz', 'dildo', 'blowjob',
'handjob', 'rimjob', 'fellatio', 'cunnilingus',
],
'extreme' => [
'nigger', 'nigga', 'niggers', 'niggas', 'coon', 'darkie',
'kike', 'spic', 'spick', 'wetback', 'chink', 'gook',
'paki', 'raghead', 'towelhead', 'sandnigger', 'beaner',
'gringo', 'wop', 'dago', 'polack', 'retard', 'retarded',
'faggot', 'fag', 'dyke', 'tranny',
],
],
'profanities' => [
'abbo',
'abortionist',
'abuser',
'ahole',
'alabama hotpocket',
'alligatorbait',
'anal',
'analannie',
'analsex',
'areola',
'arse',
'arsebagger',
'arsebandit',
'arseblaster',
'arsecowboy',
'arsefuck',
'arsefucker',
'arsehat',
'arsehole',
'arseholes',
'arsehore',
'arsejockey',
'arsekiss',
'arsekisser',
'arselick',
'arselicker',
'arselover',
'arseman',
'arsemonkey',
'arsemunch',
'arsemuncher',
'arsepacker',
'arsepirate',
'arsepuppies',
'arseranger',
'arses',
'arsewhore',
'arsewipe',
'ass',
'assbag',
'assbagger',
'assbandit',
'assbanger',
'assbite',
'assblaster',
'assclown',
'asscock',
'asscowboy',
'asscracker',
'asses',
'assface',
'assfuck',
'assfucker',
'assgoblin',
'ass-hat',
'asshat',
'asshead',
'asshole',
'assholes',
'assholz',
'asshopper',
'asshore',
'ass-jabber',
'assjacker',
'assjockey',
'asskiss',
'asskisser',
'assklown',
'asslick',
'asslicker',
'asslover',
'assman',
'assmonkey',
'ass monkey',
'assmunch',
'assmuncher',
'assnigger',
'asspacker',
'ass-pirate',
'asspirate',
'asspuppies',
'assranger',
'assshit',
'assshole',
'asssucker',
'asswad',
'asswhore',
'asswipe',
'axwound',
'azzhole',
'backdoorman',
'badfuck',
'baldy',
'ball licker',
'balllicker',
'ballsack',
'bampot',
'banging',
'barelylegal',
'barface',
'barfface',
'bassterds',
'bastard',
'bastards',
'bastardz',
'basterds',
'basterdz',
'bazongas',
'bazooms',
'beaner',
'beastality',
'beastial',
'beastiality',
'beat-off',
'beatoff',
'beatyourmeat',
'bestial',
'bestiality',
'biatch',
'bicurious',
'bigass',
'bigbastard',
'bigbutt',
'bitch',
'bitchass',
'bitcher',
'bitches',
'bitchez',
'bitchin',
'bitching',
'bitchslap',
'bitchtits',
'bitchy',
'biteme',
'blow job',
'blowjob',
'boffing',
'bohunk',
'bollick',
'bollock',
'bollocks',
'bollox',
'bondage',
'boner',
'boob',
'boobies',
'boobs',
'booby',
'bootycall',
'bountybar',
'breastjob',
'breastlover',
'breastman',
'brothel',
'brotherfucker',
'bugger',
'buggered',
'buggery',
'bukake',
'bullcrap',
'bulldike',
'bulldyke',
'bullshit',
'bumblefuck',
'bumfuck',
'bungabunga',
'bunghole',
'butchbabes',
'butchdike',
'butchdyke',
'butt-bang',
'buttbang',
'buttcheeks',
'buttface',
'butt-fuck',
'buttfuck',
'buttfucka',
'butt-fucker',
'buttfucker',
'butt-fuckers',
'buttfuckers',
'butthead',
'butthole',
'buttman',
'buttmunch',
'buttmuncher',
'butt-pirate',
'buttpirate',
'butt plug',
'buttplug',
'buttstain',
'buttwipe',
'byatch',
'cacker',
'cameljockey',
'camel toe',
'cameltoe',
'carpet muncher',
'carpetmuncher',
'cawk',
'cawks',
'chav',
'cherrypopper',
'chesticle',
'chickslick',
'chinc',
'chink',
'choad',
'chode',
'clamdigger',
'clamdiver',
'clit',
'clitface',
'clitfuck',
'clitoris',
'clogwog',
'clunge',
'clusterfuck',
'cnts',
'cntz',
'cock',
'cockass',
'cockbite',
'cockblock',
'cockblocker',
'cockburger',
'cockcowboy',
'cockface',
'cockfight',
'cockfucker',
'cock-head',
'cockhead',
'cockjockey',
'cockknob',
'cockknoker',
'cocklicker',
'cocklover',
'cockmaster',
'cockmongler',
'cockmongruel',
'cockmonkey',
'cockmuncher',
'cocknob',
'cocknose',
'cocknugget',
'cockqueen',
'cockrider',
'cocks',
'cockshit',
'cocksman',
'cocksmith',
'cocksmoke',
'cocksmoker',
'cocksniffer',
'cocksucer',
'cocksuck',
'cocksucked',
'cock-sucker',
'cocksucker',
'cocksucking',
'cocktease',
'cockwaffle',
'cocky',
'coitus',
'cok',
'commie',
'coochie',
'coochy',
'coon',
'coondog',
'cooter',
'copulate',
'cracker',
'crackpipe',
'crack-whore',
'crackwhore',
'crap',
'crappy',
'crotchjockey',
'crotchmonkey',
'crotchrot',
'cuck',
'cum',
'cumbubble',
'cumdumpster',
'cumfest',
'cumguzzler',
'cumjockey',
'cumm',
'cumquat',
'cumqueen',
'cumshot',
'cumslut',
'cumtart',
'cunilingus',
'cunillingus',
'cunnie',
'cunnilingus',
'cunntt',
'cunt',
'cuntass',
'cunteyed',
'cuntface',
'cuntfucker',
'cunthole',
'cuntlick',
'cuntlicker',
'cuntlicker',
'cuntlicking',
'cuntrag',
'cunts',
'cuntslut',
'cuntsucker',
'cuntz',
'cybersex',
'cyberslimer',
'dago',
'dammit',
'damn',
'damnation',
'damnit',
'darkie',
'darky',
'datnigga',
'deapthroat',
'deepthroat',
'deggo',
'dego',
'devilworshipper',
'dick',
'dickbag',
'dickbeaters',
'dickbrain',
'dickface',
'dickforbrains',
'dickfuck',
'dickfucker',
'dickhead',
'dickhole',
'dickjuice',
'dickless',
'dicklick',
'dicklicker',
'dickmilk',
'dickmonger',
'dicks',
'dickslap',
'dick-sneeze',
'dicksucker',
'dicksucking',
'dicktickler',
'dickwad',
'dickweasel',
'dickweed',
'dickwod',
'dike',
'dildo',
'dildos',
'dilldo',
'dilldos',
'dipshit',
'dipstick',
'dixiedike',
'dixiedyke',
'doggiestyle',
'doggystyle',
'dominatricks',
'dominatrics',
'dominatrix',
'doochbag',
'dookie',
'douch',
'douchbag',
'douche',
'douchebag',
'douche-fag',
'douchewaffle',
'drag queen',
'dragqueen',
'dragqween',
'dripdick',
'dumass',
'dumb ass',
'dumbass',
'dumbbitch',
'dumbfuck',
'dumbshit',
'dumshit',
'dyke',
'easyslut',
'eatballs',
'eatme',
'eatpussy',
'ejaculate',
'ejaculated',
'ejaculating',
'ejaculation',
'enema',
'excrement',
'facefucker',
'facist',
'faeces',
'fag',
'fagbag',
'faget',
'fagfucker',
'fagging',
'faggit',
'faggot',
'faggotcock',
'faggots',
'fagit',
'fagot',
'fags',
'fagtard',
'fagz',
'faig',
'faigs',
'fannyfucker',
'fark',
'farted',
'farting',
'farty',
'fastfuck',
'fatass',
'fatfuck',
'fatfucker',
'fatso',
'feces',
'felatio',
'felch',
'felcher',
'felching',
'fellatio',
'feltch',
'feltcher',
'feltching',
'fingerfuck',
'fingerfucked',
'fingerfucker',
'fingerfuckers',
'fingerfucking',
'fister',
'fistfuck',
'fistfucked',
'fistfucker',
'fistfucking',
'fisting',
'flamer',
'flasher',
'flid',
'flipping the bird',
'flyd',
'flydie',
'flydye',
'fondle',
'footaction',
'footfuck',
'footfucker',
'footlicker',
'fornicate',
'freakfuck',
'freakyfucker',
'freefuck',
'fubar',
'fucck',
'fuck',
'fucka',
'fuckable',
'fuckass',
'fuckbag',
'fuckboy',
'fuckbrain',
'fuckbuddy',
'fuckbutt',
'fuckbutter',
'fucked',
'fucker',
'fuckers',
'fuckersucker',
'fuckface',
'fuckfest',
'fuckfreak',
'fuckfriend',
'fuckhead',
'fuckhole',
'fuckin',
'fuckina',
'fucking',
'fuckingbitch',
'fuckinnuts',
'fuckinright',
'fuckit',
'fuckknob',
'fuckmonkey',
'fucknut',
'fucknutt',
'fuckoff',
'fuckpig',
'fuckstick',
'fucktard',
'fucktart',
'fuckup',
'fuckwad',
'fuckwhore',
'fuckwit',
'fuckwitt',
'fuckyou',
'fudge packer',
'fudgepacker',
'Fudge Packer',
'fugly',
'fuk',
'Fukah',
'Fuken',
'fuker',
'Fukin',
'Fukk',
'Fukkah',
'Fukken',
'Fukker',
'Fukkin',
'fuks',
'funfuck',
'fuuck',
'gang bang',
'gangbang',
'gangbanged',
'gangbanger',
'gatorbait',
'gayass',
'gaybob',
'gayboy',
'gaydo',
'gayfuck',
'gayfuckist',
'gaygirl',
'gaylord',
'gaymuthafuckinwhore',
'gays',
'gaysex',
'gaytard',
'gaywad',
'gayz',
'getiton',
'givehead',
'glazeddonut',
'godammit',
'goddamit',
'goddammit',
'goddamn',
'goddamned',
'god-damned',
'goddamnes',
'goddamnit',
'goddamnmuthafucker',
'goldenshower',
'gonorrehea',
'gonzagas',
'gooch',
'gook',
'gotohell',
'greaseball',
'gringo',
'grostulation',
'guido',
'gypo',
'gypp',
'gyppie',
'gyppo',
'gyppy',
'handjob',
'hard on',
'hardon',
'headfuck',
'heeb',
'hell',
'herpes',
'hijacker',
'hijacking',
'hillbillies',
'hindoo',
'hitler',
'hitlerism',
'hitlerist',
'hoar',
'hobo',
'hoe',
'hoes',
'holestuffer',
'homo',
'homobangers',
'homodumbshit',
'honger',
'honkers',
'honkey',
'honky',
'hookers',
'hoor',
'hoore',
'hore',
'horney',
'horniest',
'horny',
'horseshit',
'hosejob',
'hotdamn',
'hotpussy',
'hottotrot',
'humping',
'hymen',
'iblowu',
'idiot',
'incest',
'insest',
'internet wife',
'inthebuff',
'jackass',
'jackoff',
'jackshit',
'jagoff',
'jap',
'japcrap',
'japs',
'jerkass',
'jerk off',
'jerk-off',
'jerkoff',
'jesuschrist',
'jigaboo',
'jiggabo',
'jihad',
'jijjiboo',
'jisim',
'jism',
'jiss',
'jizim',
'jizjuice',
'jizm',
'jizm',
'jizz',
'jizzim',
'jizzum',
'jubblies',
'juggalo',
'jungle bunny',
'junglebunny',
'kiddy fiddler',
'kike',
'kinky',
'kissass',
'knobz',
'kondum',
'kooch',
'kootch',
'krap',
'krappy',
'kraut',
'kumbubble',
'kumbullbe',
'kummer',
'kumming',
'kums',
'kunilingus',
'kunnilingus',
'kunt',
'kunts',
'kuntz',
'kyke',
'labia',
'lactate',
'lady boy',
'ladyboy',
'lameass',
'lapdance',
'lardass',
'lesbain',
'lesbayn',
'lesbian',
'lesbin',
'lesbo',
'lezbe',
'lezbefriends',
'lezbo',
'lezz',
'lezzer',
'lezzie',
'lezzo',
'libido',
'lickme',
'limpdick',
'lipshits',
'lipshitz',
'livesex',
'lmfao',
'loadedgun',
'lovebone',
'lovegoo',
'lovegun',
'lovejuice',
'lovemuscle',
'lovepistol',
'loverocket',
'low life',
'lowlife',
'lubejob',
'luckycameltoe',
'manhater',
'manpaste',
'masochist',
'masokist',
'massterbait',
'masstrbait',
'masstrbate',
'mastabate',
'mastabater',
'masterbaiter',
'masterbate',
'master bates',
'masterbates',
'mastrabator',
'masturbate',
'masturbating',
'mattressprincess',
'mcfagget',
'meatbeater',
'meatrack',
'mgger',
'mggor',
'milf',
'minge',
'mofo',
'molest',
'molestation',
'molester',
'molestor',
'moneyshot',
'mooncricket',
'moron',
'mothafuck',
'mothafucka',
'mothafuckaz',
'mothafucked',
'mothafucker',
'motha fucker',
'mothafuckin',
'mothafucking',
'mothafuckings',
'motha fuker',
'motha fukkah',
'motha fukker',
'motherfuck',
'motherfucked',
'mother-fucker',
'motherfucker',
'mother fucker',
'motherfuckin',
'motherfucking',
'motherfuckings',
'mother fukah',
'mother fuker',
'mother fukkah',
'mother fukker',
'motherlovebone',
'muff',
'muffdive',
'muffdiver',
'muffindiver',
'mufflikcer',
'muncher',
'munging',
'muthafucker',
'mutha fucker',
'mutha fukah',
'mutha fuker',
'mutha fukkah',
'mutha fukker',
'nastt',
'nastybitch',
'nastyho',
'nastyslut',
'nastywhore',
'nazi',
'necro',
'negro',
'negroes',
'negroid',
'nigaboo',
'nigga',
'niggah',
'niggaracci',
'niggard',
'niggarded',
'niggarding',
'niggardliness',
"niggardliness's",
'niggardly',
"niggard's",
'niggards',
'niggaz',
'nigger',
'niggerhead',
'niggerhole',
"nigger's",
'niggers',
'niggle',
'niggled',
'niggles',
'niggling',
'nigglings',
'niggor',
'niggur',
'niglet',
'nignog',
'nigr',
'nigra',
'nigre',
'nigur',
'niiger',
'niigr',
'nipple',
'nipplering',
'nittit',
'nlgger',
'nlggor',
'nofuckingway',
'nonce',
'nookey',
'nookie',
'nudger',
'nut case',
'nutcase',
'nutfucker',
'nut sack',
'nutsack',
'ontherag',
'orafis',
'orgasim',
'orgasim',
'orgasm',
'orgasum',
'orgies',
'orgy',
'oriface',
'orifice',
'orifiss',
'osama bin laden',
'packi',
'packie',
'packy',
'paedo',
'paedofile',
'paedophile',
'paki',
'pakie',
'paky',
'palesimian',
'panooch',
'panti',
'pearlnecklace',
'pecker',
'peckerhead',
'peckerwood',
'peedo',
'peeenus',
'peeenusss',
'peehole',
'peenus',
'peinus',
'penas',
'penile',
'penisbanger',
'penis-breath',
'penises',
'penisfucker',
'penispuffer',
'penus',
'penuus',
'perv',
'perversion',
'pervert',
'phonesex',
'phuc',
'phuck',
'phuk',
'phuked',
'phuker',
'phuking',
'phukked',
'phukker',
'phukking',
'phungky',
'phuq',
'pi55',
'picaninny',
'piccaninny',
'pickaninny',
'pikey',
'piky',
'pimper',
'pimpjuic',
'pimpjuice',
'pimpsimp',
'pindick',
'piss',
'pissed',
'pissed off',
'pisser',
'pisses',
'pissflaps',
'pisshead',
'pissin',
'pissing',
'pissoff',
'play boy',
'playboy',
'play bunny',
'playbunny',
'play girl',
'playgirl',
'plumper',
'pocketpool',
'polac',
'polack',
'polak',
'polesmoker',
'pollock',
'poon',
'poonani',
'poonany',
'poontang',
'pooperscooper',
'pooping',
'poorwhitetrash',
'poostabber',
'popimp',
'porch monkey',
'porchmonkey',
'porn',
'pornflick',
'pornking',
'porno',
'pornprincess',
'pric',
'prick',
'prik',
'prickhead',
'prostitute',
'pu55i',
'pu55y',
'pube',
'pubiclice',
'puke',
'punanny',
'punta',
'puntang',
'purinaprincess',
'pusse',
'pussee',
'pussie',
'pussies',
'pussy',
'pussyeater',
'pussyfucker',
'pussylicker',
'pussylicking',
'pussylips',
'pussylover',
'pussypounder',
'pusy',
'puto',
'puuke',
'puuker',
'queef',
'queer',
'queerbait',
'queerhole',
'queers',
'queerz',
'quim',
'qweers',
'qweerz',
'qweir',
'rag head',
'raghead',
'raped',
'rapist',
'rearend',
'rearentry',
'recktum',
'rectum',
'redneck',
'renob',
'rentafuck',
'rimjob',
'rimming',
'ruski',
'russki',
'russkie',
'sadist',
'sadom',
'saeema butt',
'sandm',
'sand nigger',
'sandnigger',
'scag',
'scank',
'scat',
'schlong',
'screwing',
'screwyou',
'scrote',
'scrotum',
'scum',
'scumbag',
'seaman staines',
'semen',
'sexed',
'sexfarm',
'sexhound',
'sexhouse',
'sexing',
'sexkitten',
'sexpot',
'sexslave',
'sextogo',
'sextoy',
'sextoys',
'sexwhore',
'sexymoma',
'sexy-slim',
'seymour butts',
'shag',
'shagger',
'shaggin',
'shagging',
'shat',
'shhit',
'shit',
'shitass',
'shitbag',
'shitbagger',
'shitbrains',
'shitbreath',
'shitcan',
'shitcanned',
'shitcunt',
'shitdick',
'shite',
'shiteater',
'shited',
'shiter',
'shitface',
'shitfaced',
'shitfit',
'shitforbrains',
'shitfuck',
'shitfucker',
'shitfull',
'shithapens',
'shithappens',
'shithead',
'shithole',
'shithouse',
'shiting',
'shitlist',
'shitola',
'shitoutofluck',
'shits',
'shitspitter',
'shitstain',
'shitted',
'shitter',
'shittiest',
'shitting',
'shitty',
'shity',
'shitz',
'shiz',
'shiznit',
'shortfuck',
'shyt',
'shyte',
'shytty',
'shyty',
'sissy',
'sixsixsix',
'sixtynine',
'sixtyniner',
'skanck',
'skank',
'skankbitch',
'skankee',
'skankey',
'skankfuck',
'skanks',
'skankwhore',
'skanky',
'skankybitch',
'skankywhore',
'skeet',
'skinflute',
'skullfuck',
'skum',
'skumbag',
'slanteye',
'slantyeye',
'slapper',
'slavedriver',
'sleezebag',
'sleezeball',
'slideitin',
'slimeball',
'slimebucket',
'slopehead',
'slopey',
'slopy',
'slut',
'slutbag',
'sluts',
'slutt',
'slutting',
'slutty',
'slutwear',
'slutwhore',
'slutz',
'smackthemonkey',
'smeg',
'smelly',
'smut',
'snatch',
'snatchpatch',
'snot',
'snowback',
'snownigger',
'sodom',
'sodomise',
'sodomite',
'sodomize',
'sodomy',
'son-of-a-bitch',
'sonofabitch',
'sonofbitch',
'spac',
'spacca',
'spaghettibender',
'spaghettinigger',
'spankthemonkey',
'spazza',
'sperm',
'spermacide',
'spermbag',
'spermhearder',
'spermherder',
'spic',
'spick',
'spig',
'spigotty',
'spik',
'spitter',
'splittail',
'splooge',
'spooge',
'spook',
'spreadeagle',
'squaw',
'stabber',
'stiffy',
'strapon',
'stripclub',
'stroking',
'stupidfuck',
'stupidfucker',
'suckass',
'suckdick',
'sucker',
'suckme',
'suckmyass',
'suckmydick',
'suckmytit',
'suckoff',
'swastika',
'tampon',
'tarbaby',
'tard',
'teat',
'teste',
'testicle',
'testicles',
'thicklips',
'thicko',
'thirdeye',
'thirdleg',
'threesome',
'thundercunt',
'timbernigger',
'tit',
'titbitnipply',
'titfuck',
'titfucker',
'titfuckin',
'titjob',
'titlicker',
'titlover',
'tits',
'tittie',
'titties',
'titty',
'tittyfuck',
'tonguethrust',
'tonguethruster',
'tonguetramp',
'torture',
'tosser',
'tosspot',
'towel head',
'towelhead',
'trailertrash',
'tramp',
'trannie',
'tranny',
'trots',
'trouser snake',
'tuckahoe',
'tunneloflove',
'turd',
'twat',
'twatlips',
'twats',
'twatwaffle',
'twink',
'twinkie',
'twobitwhore',
'unclefucker',
'unfuckable',
'upskirt',
'uptheass',
'upthebutt',
'urinate',
'urine',
'usama bin laden',
'uterus',
'vag',
'vagina',
'vaginal',
'vajayjay',
'vajina',
'va-j-j',
'valjina',
'vibrater',
'vibrator',
'vietcong',
'violate',
'violation',
'virginbreaker',
'vjayjay',
'vomit',
'vullva',
'vulva',
'wank',
'wanker',
'wanking',
'wankjob',
'waysted',
'welcher',
'wetback',
'wetspot',
'whacker',
'whigger',
'whiskeydick',
'whiskydick',
'whitenigger',
'whitetrash',
'whitey',
'whoor',
'whop',
'whore',
'whorebag',
'whoreface',
'whorefucker',
'whorehouse',
'wife beater',
'williewanker',
'wog',
'wop',
'wuss',
'wuzzie',
'x-rated',
'xrated',
'yellowman',
'zigabo',
'zipperhea',
'zipper head',
'sucks',
'bloody',
'crikey',
'darn',
'heck',
'slag',
'knob',
'bellend',
'minger',
'git',
'twit',
'smartass',
'hooker',
'hussy',
'floozy',
'tart',
'pansy',
'mindfuck',
'niggas',
'retard',
'retarded',
],
'false_positives' => [
'hello',
'scunthorpe',
'cockburn',
'penistone',
'lightwater',
'assume',
'bass',
'class',
'compass',
'pass',
'dickinson',
'middlesex',
'cockerel',
'butterscotch',
'blackcock',
'countryside',
'arsenal',
'flick',
'flicker',
'analyst',
'cocktail',
'musicals hit',
'is hit',
'blackcocktail',
'its not',
// Common words containing "ass"
'assignment',
'assign',
'assigned',
'assigns',
'assigning',
'assist',
'assistant',
'assisted',
'assists',
'assistance',
'associate',
'associated',
'associates',
'association',
'associations',
'assemble',
'assembled',
'assembles',
'assembly',
'assert',
'asserted',
'assertion',
'assertions',
'asserts',
'assess',
'assessed',
'assesses',
'assessing',
'assessment',
'assessments',
'asset',
'assets',
'assure',
'assured',
'assures',
'assurance',
'assorted',
'assortment',
'assassin',
'assassins',
'assassination',
'assassinated',
'assault',
'assaulted',
'assaults',
'passion',
'passionate',
'passions',
'passive',
'passively',
'passenger',
'passengers',
'passage',
'passages',
'passing',
'passed',
'passes',
'passport',
'passports',
'password',
'passwords',
'bypass',
'bypassed',
'bypasses',
'bypassing',
'classroom',
'classrooms',
'classic',
'classical',
'classics',
'classification',
'classifications',
'classified',
'classify',
'classmate',
'classmates',
'classed',
'classes',
'classy',
'mass',
'masses',
'massive',
'massively',
'massage',
'massages',
'massacre',
'massacres',
'embassy',
'embassies',
'ambassador',
'ambassadors',
'embarrass',
'embarrassed',
'embarrassing',
'embarrassment',
'harass',
'harassed',
'harassing',
'harassment',
'brass',
'brassy',
'crass',
'glass',
'glasses',
'glassy',
'grass',
'grasses',
'grassy',
'lass',
'lassie',
'molasses',
'morass',
'sass',
'sassy',
'trespass',
'trespassed',
'trespassing',
'surpass',
'surpassed',
'surpasses',
'compassion',
'compassionate',
'encompass',
'encompassed',
'encompasses',
'encompassing',
// Common words containing "tit"
'title',
'titles',
'titled',
'subtitle',
'subtitles',
'entity',
'entities',
'identity',
'identities',
'quantity',
'quantities',
'constitution',
'constitutional',
'constitutions',
'constitute',
'constitutes',
'institution',
'institutional',
'institutions',
'petition',
'petitions',
'petitioner',
'competition',
'competitions',
'competitive',
'competitor',
'competitors',
'repetition',
'repetitions',
'repetitive',
'appetite',
'appetites',
'gratitude',
'attitude',
'attitudes',
'altitude',
'altitudes',
'aptitude',
'multitude',
'fortitude',
'latitude',
'latitudes',
'partition',
'partitions',
'practitioner',
'practitioners',
'restitution',
'prostitution',
'superstition',
'superstitions',
'superstitious',
'titillate',
'titan',
'titans',
'titanium',
// Common words containing "cum"
'document',
'documents',
'documentary',
'documentation',
'documented',
'circumstance',
'circumstances',
'circumference',
'accumulate',
'accumulated',
'accumulation',
'cucumber',
'cucumbers',
'incumbent',
'incumbents',
// Common words containing "ho" / "hoe"
'shoe',
'shoes',
'shoelace',
'horseshoe',
// Common words containing "nig"
'night',
'nights',
'nightclub',
'nightfall',
'nightlife',
'nightmare',
'nightmares',
'nightstand',
'nighttime',
'tonight',
'overnight',
'knight',
'knights',
// Common words containing "rap"
'grape',
'grapes',
'drape',
'drapes',
'scrape',
'scraped',
'scraper',
'therapy',
'therapies',
'therapist',
'therapists',
// Common words containing "nob"
'noble',
'nobles',
'nobleman',
'nobility',
'snob',
'snobs',
'snobbish',
'snobby',
],
'substitutions' => [
'/a/' => ['a', '4', '@', 'Á', 'á', 'À', 'Â', 'à', 'Â', 'â', 'Ä', 'ä', 'Ã', 'ã', 'Å', 'å', 'æ', 'Æ', 'α', 'Δ', 'Λ', 'λ'],
'/e/' => ['e', '3', '€', 'È', 'è', 'É', 'é', 'Ê', 'ê', 'ë', 'Ë', 'ē', 'Ē', 'ė', 'Ė', 'ę', 'Ę', '∑'],
'/i/' => ['i', '!', '|', ']', '[', '1', '∫', 'Ì', 'Í', 'Î', 'Ï', 'ì', 'í', 'î', 'ï', 'ī', 'Ī', 'į', 'Į'],
'/o/' => ['o', '0', 'Ο', 'ο', 'Φ', '¤', '°', 'ø', 'ô', 'Ô', 'ö', 'Ö', 'ò', 'Ò', 'ó', 'Ó', 'œ', 'Œ', 'ø', 'Ø', 'ō', 'Ō', 'õ', 'Õ'],
'/u/' => ['u', 'υ', 'µ', 'û', 'ü', 'ù', 'ú', 'ū', 'Û', 'Ü', 'Ù', 'Ú', 'Ū', '@', '*'],
]
];
================================================
FILE: config/languages/french.php
================================================
<?php
return [
'severity' => [
'mild' => [
'crotte', 'crottes', 'caca', 'cacas', 'zut',
'punaise',
'idiot', 'idiots', 'idiote', 'idiotes',
'bête', 'bete', 'bêtes', 'betes',
'sot', 'sots', 'sotte', 'sottes',
'niais', 'niaise', 'niaises',
'ballot', 'ballots', 'andouille', 'andouilles',
],
'moderate' => [
'connard', 'connarde', 'con', 'conne',
'salaud', 'salope', 'garce', 'garces',
'pétasse', 'petasse', 'pétasses', 'petasses',
'bâtard', 'batard', 'bâtards', 'batards',
'bâtarde', 'batarde', 'bâtardes', 'batardes',
'abruti', 'abrutis', 'abrutie', 'abruties',
'crétin', 'cretin', 'crétins', 'cretins',
'crétine', 'cretine', 'crétines', 'cretines',
'débile', 'debile', 'débiles', 'debiles',
'imbécile', 'imbecile', 'imbéciles', 'imbeciles',
'cul', 'culs', 'trou du cul', 'trou de balle',
'cochon', 'cochons', 'cochonne', 'cochonnes',
],
'high' => [
'merde', 'putain', 'enculé', 'encule',
'niquer', 'nique', 'baiser', 'baise',
'foutre', 'foutu', 'foutue', 'chier',
'bite', 'pute', 'fils de pute',
],
'extreme' => [
'pédé', 'pede', 'pédés', 'pedes',
'pédéraste', 'pederaste', 'pédérastes', 'pederastes',
'tapette', 'tapettes', 'tantouze', 'tantouzes',
'fiotte', 'fiottes', 'tarlouze', 'tarlouzes',
'gouine', 'gouines',
'attardé', 'attarde', 'attardés', 'attardes',
'attardée', 'attardee', 'attardées', 'attardees',
],
],
'profanities' => [
// Common French profanities and vulgar expressions
'merde',
'putain',
'connard',
'connarde',
'con',
'conne',
'salaud',
'salope',
'enculé',
'encule',
'enculée',
'enculee',
'fils de pute',
'fils de putain',
'bordel',
'chier',
'chiasse',
'chieur',
'chieuse',
'emmerde',
'emmerder',
'emmerdeur',
'emmerdeuse',
'baiser',
'baise',
'baisé',
'baise',
'baisée',
'baisee',
'foutre',
'foutue',
'foutu',
'niquer',
'nique',
'niqué',
'nique',
'niquée',
'niquee',
'bite',
'bites',
'pine',
'pines',
'queue',
'queues',
'vit',
'verge',
'zob',
'zobs',
'biroute',
'biroutes',
'braquemart',
'braquemarts',
'dard',
'dards',
'gourdin',
'gourdins',
'gland',
'glands',
'prépuce',
'prepuce',
'prépuces',
'prepuces',
'couilles',
'couille',
'couillon',
'couillonne',
'couillons',
'couillonnes',
'roubignoles',
'roubignole',
'burnes',
'burne',
'roustons',
'rouston',
'testicules',
'testicule',
'génitoires',
'genitoires',
'génitoire',
'genitoire',
'chatte',
'chattes',
'minou',
'minous',
'con',
'cons',
'moule',
'moules',
'fente',
'fentes',
'cramouille',
'cramouilles',
'crevasse',
'crevasses',
'cyprine',
'cyprines',
'foufoune',
'foufounes',
'motte',
'mottes',
'touffe',
'touffes',
'abricot',
'abricots',
'nichons',
'nichon',
'tétons',
'teton',
'téton',
'tetons',
'roberts',
'robert',
'doudounes',
'doudoune',
'lolos',
'lolo',
'miches',
'miche',
'mamelles',
'mamelle',
'seins',
'sein',
'nénés',
'nene',
'nénée',
'nenee',
'roploplos',
'roploplo',
'flotteurs',
'flotteur',
'amortisseurs',
'amortisseur',
'airbags',
'airbag',
'cul',
'culs',
'fesses',
'fesse',
'pétard',
'petard',
'pétards',
'petards',
'postérieur',
'posterieur',
'postérieurs',
'posterieurs',
'derrière',
'derriere',
'derrières',
'derrieres',
'fion',
'fions',
'trou du cul',
'trou de balle',
'anus',
'orifice',
'orifices',
'rosette',
'rosettes',
'rondelle',
'rondelles',
'bague',
'bagues',
'anneau',
'anneaux',
'pédé',
'pede',
'pédés',
'pedes',
'pédéraste',
'pederaste',
'pédérastes',
'pederastes',
'tapette',
'tapettes',
'tante',
'tantes',
'tantouze',
'tantouzes',
'fiotte',
'fiottes',
'tarlouze',
'tarlouzes',
'tafiole',
'tafioles',
'gouine',
'gouines',
'lesbienne',
'lesbiennes',
'tribade',
'tribades',
'saphique',
'saphiques',
'lesbos',
'lesbo',
'garce',
'garces',
'pétasse',
'petasse',
'pétasses',
'petasses',
'traînée',
'trainee',
'traînées',
'trainees',
'pute',
'putes',
'putain',
'putains',
'catin',
'catins',
'caillera',
'cailleras',
'racaille',
'racailles',
'voyou',
'voyous',
'truand',
'truands',
'bandit',
'bandits',
'malfrat',
'malfrats',
'gangster',
'gangsters',
'criminel',
'criminels',
'criminelle',
'criminelles',
'assassin',
'assassins',
'tueur',
'tueurs',
'tueuse',
'tueuses',
'meurtrier',
'meurtriers',
'meurtrière',
'meurtrieres',
'bourrin',
'bourrins',
'bourrine',
'bourrines',
'rustre',
'rustres',
'plouc',
'ploucs',
'péquenaud',
'pequenaud',
'péquenauds',
'pequenauds',
'cul-terreux',
'cul terreux',
'bouseux',
'boueuse',
'bouseux',
'bouseuses',
'bâtard',
'batard',
'bâtards',
'batards',
'bâtarde',
'batarde',
'bâtardes',
'batardes',
'salopard',
'salopards',
'saloparde',
'salopardes',
'fumier',
'fumiers',
'ordure',
'ordures',
'pourriture',
'pourritures',
'charogne',
'charognes',
'raclure',
'raclures',
'déchet',
'dechet',
'déchets',
'dechets',
'rebut',
'rebuts',
'lie',
'lies',
'écume',
'ecume',
'écumes',
'ecumes',
'fange',
'fanges',
'boue',
'boues',
'vase',
'vases',
'crotte',
'crottes',
'étron',
'etron',
'étrons',
'etrons',
'caca',
'cacas',
'bouse',
'bouses',
'fiente',
'fientes',
'colombin',
'colombins',
'boudin',
'boudins',
'saucisse',
'saucisses',
'andouille',
'andouilles',
'crétin',
'cretin',
'crétins',
'cretins',
'crétine',
'cretine',
'crétines',
'cretines',
'débile',
'debile',
'débiles',
'debiles',
'attardé',
'attarde',
'attardés',
'attardes',
'attardée',
'attardee',
'attardées',
'attardees',
'demeuré',
'demeure',
'demeurés',
'demeures',
'demeurée',
'demeuree',
'demeurées',
'demeurees',
'simple',
'simples',
'idiot',
'idiots',
'idiote',
'idiotes',
'imbécile',
'imbecile',
'imbéciles',
'imbeciles',
'stupide',
'stupides',
'bête',
'bete',
'bêtes',
'betes',
'sot',
'sots',
'sotte',
'sottes',
'niais',
'niaise',
'niaises',
'nigaud',
'nigauds',
'nigaude',
'nigaudes',
'benêt',
'benet',
'benêts',
'benets',
'benête',
'benete',
'benêtes',
'benetes',
'ballot',
'ballots',
'ballotte',
'ballottes',
'balourd',
'balourds',
'balourde',
'balourdes',
'lourdaud',
'lourdauds',
'lourdaude',
'lourdaudes',
'abruti',
'abrutis',
'abrutie',
'abruties',
'bourrique',
'bourriques',
'âne',
'ane',
'ânes',
'anes',
'ânesse',
'anesse',
'ânesses',
'anesses',
'baudet',
'baudets',
'bourricot',
'bourricots',
'gourde',
'gourdes',
'cornichon',
'cornichons',
'navet',
'navets',
'nouille',
'nouilles',
'patate',
'patates',
'buse',
'buses',
'dinde',
'dindes',
'dindon',
'dindons',
'oie',
'oies',
'jars',
'bécasse',
'becasse',
'bécasses',
'becasses',
'bécassine',
'becassine',
'bécassines',
'becassines',
'poule',
'poules',
'poulet',
'poulets',
'coquette',
'coquettes',
'coq',
'coqs',
'chapon',
'chapons',
'poularde',
'poulardes',
'poussin',
'poussins',
'poussinière',
'poussiniere',
'poussinières',
'poussinieres',
'cochon',
'cochons',
'cochonne',
'cochonnes',
'porc',
'porcs',
'truie',
'truies',
'pourceau',
'pourceaux',
'goret',
'gorets',
'cochonnet',
'cochonnets',
'cochonnaille',
'cochonnailles',
'verrat',
'verrats',
'bauge',
'bauges',
'porcherie',
'porcheries',
'étable',
'etable',
'étables',
'etables',
'écurie',
'ecurie',
'écuries',
'ecuries',
'box',
'boxs',
'stalle',
'stalles',
'enclos',
'clos',
'parc',
'parcs',
'paddock',
'paddocks',
'pâturage',
'paturage',
'pâturages',
'paturages',
'prairie',
'prairies',
'pré',
'pre',
'prés',
'pres',
'herbage',
'herbages',
'pacage',
'pacages',
'pâture',
'pature',
'pâtures',
'patures',
'fourrage',
'fourrages',
'foin',
'foins',
'paille',
'pailles',
'litière',
'litiere',
'litières',
'litieres',
'fumier',
'fumiers',
'purin',
'purins',
'lisier',
'lisiers',
'compost',
'composts',
'engrais',
'fertilisant',
'fertilisants',
'amendement',
'amendements',
'terreau',
'terreaux',
'humus',
'tourbe',
'tourbes',
'mousse',
'mousses',
'lichen',
'lichens',
'algue',
'algues',
'varech',
'varechs',
'goémon',
'goemon',
'goémons',
'goemons',
'sargasse',
'sargasses',
'zostère',
'zostere',
'zostères',
'zosteres',
'laminaire',
'laminaires',
'fucus',
'ulve',
'ulves',
'spiruline',
'spirulines',
'chlorelle',
'chlorelles',
'microalgue',
'microalgues',
'phytoplancton',
'phytoplanctons',
'zooplancton',
'zooplanctons',
'plancton',
'planctons',
'krill',
'krills',
'copépode',
'copepode',
'copépodes',
'copepodes',
'rotifère',
'rotifere',
'rotifères',
'rotiferes',
'protozoaire',
'protozoaires',
'paramècie',
'paramecie',
'paramécies',
'paramecies',
'amibe',
'amibes',
'euglène',
'euglene',
'euglènes',
'euglenes',
'volvox',
'hydre',
'hydres',
'méduse',
'meduse',
'méduses',
'meduses',
'polype',
'polypes',
'corail',
'coraux',
'anémone',
'anemone',
'anémones',
'anemones',
'actinie',
'actinies',
'éponge',
'eponge',
'éponges',
'eponges',
'spongieux',
'spongieuse',
'spongieuses',
'poreux',
'poreuse',
'poreuses',
'alvéolé',
'alveole',
'alvéolés',
'alveoles',
'alvéolée',
'alveolee',
'alvéolées',
'alveolees',
'cellulaire',
'cellulaires',
'cellule',
'cellules',
'cytoplasme',
'cytoplasmes',
'noyau',
'noyaux',
'nucléole',
'nucleole',
'nucléoles',
'nucleoles',
'chromosome',
'chromosomes',
'chromatine',
'chromatines',
'gène',
'gene',
'gènes',
'genes',
'génome',
'genome',
'génomes',
'genomes',
'génétique',
'genetique',
'génétiques',
'genetiques',
'héréditaire',
'hereditaire',
'héréditaires',
'hereditaires',
'hérédité',
'heredite',
'hérédités',
'heredites',
'descendance',
'descendances',
'progéniture',
'progeniture',
'progénitures',
'progenitures',
'postérité',
'posterite',
'postérités',
'posterites',
'lignée',
'lignee',
'lignées',
'lignees',
'dynastie',
'dynasties',
'famille',
'familles',
'clan',
'clans',
'tribu',
'tribus',
'peuplade',
'peuplades',
'ethnie',
'ethnies',
'race',
'races',
'espèce',
'espece',
'espèces',
'especes',
'genre',
'genres',
'variété',
'variete',
'variétés',
'varietes',
'sous-espèce',
'sous-espece',
'sous-espèces',
'sous-especes',
'subspecies',
'sous-variété',
'sous-variete',
'sous-variétés',
'sous-varietes',
'cultivar',
'cultivars',
'hybride',
'hybrides',
'croisement',
'croisements',
'métissage',
'metissage',
'métissages',
'metissages',
'brassage',
'brassages',
'mélange',
'melange',
'mélanges',
'melanges',
'mixture',
'mixtures',
'composition',
'compositions',
'formule',
'formules',
'recette',
'recettes',
'procédé',
'procede',
'procédés',
'procedes',
'méthode',
'methode',
'méthodes',
'methodes',
'technique',
'techniques',
'procédure',
'procedure',
'procédures',
'procedures',
'protocole',
'protocoles',
'marche',
'marches',
'démarche',
'demarche',
'démarches',
'demarches',
'approche',
'approches',
'façon',
'facon',
'façons',
'facons',
'manière',
'maniere',
'manières',
'manieres',
'mode',
'modes',
'modalité',
'modalite',
'modalités',
'modalites',
'moyen',
'moyens',
'outil',
'outils',
'instrument',
'instruments',
'ustensile',
'ustensiles',
'appareil',
'appareils',
'dispositif',
'dispositifs',
'mécanisme',
'mecanisme',
'mécanismes',
'mecanismes',
'machine',
'machines',
'engin',
'engins',
'équipement',
'equipement',
'équipements',
'equipements',
'matériel',
'materiel',
'matériels',
'materiels',
'outillage',
'outillages',
'machinerie',
'machineries',
'mécanique',
'mecanique',
'mécaniques',
'mecaniques',
'automatique',
'automatiques',
'électrique',
'electrique',
'électriques',
'electriques',
'électronique',
'electronique',
'électroniques',
'electroniques',
'numérique',
'numerique',
'numériques',
'numeriques',
'digital',
'digitaux',
'digitale',
'digitales',
'informatique',
'informatiques',
'ordinateur',
'ordinateurs',
'computer',
'computers',
'pc',
'pcs',
'micro',
'micros',
'portable',
'portables',
'laptop',
'laptops',
'tablette',
'tablettes',
'smartphone',
'smartphones',
'téléphone',
'telephone',
'téléphones',
'telephones',
'mobile',
'mobiles',
'cellulaire',
'cellulaires',
'sans-fil',
'sans fil',
'wifi',
'bluetooth',
'internet',
'web',
'site',
'sites',
'page',
'pages',
'lien',
'liens',
'url',
'urls',
'adresse',
'adresses',
'email',
'emails',
'courriel',
'courriels',
'message',
'messages',
'texto',
'textos',
'sms',
'mms',
'chat',
'chats',
'forum',
'forums',
'blog',
'blogs',
'réseau',
'reseau',
'réseaux',
'reseaux',
'social',
'sociaux',
'sociale',
'sociales',
'facebook',
'twitter',
'instagram',
'linkedin',
'youtube',
'google',
'yahoo',
'bing',
'moteur',
'moteurs',
'recherche',
'recherches',
'requête',
'requete',
'requêtes',
'requetes',
'base',
'bases',
'donnée',
'donnee',
'données',
'donnees',
'information',
'informations',
'renseignement',
'renseignements',
'détail',
'detail',
'détails',
'details',
'précision',
'precision',
'précisions',
'precisions',
'exactitude',
'exactitudes',
'justesse',
'justesses',
'vérité',
'verite',
'vérités',
'verites',
'réalité',
'realite',
'réalités',
'realites',
'fait',
'faits',
'élément',
'element',
'éléments',
'elements',
'composant',
'composants',
'composante',
'composantes',
'partie',
'parties',
'portion',
'portions',
'section',
'sections',
'segment',
'segments',
'fragment',
'fragments',
'morceau',
'morceaux',
'bout',
'bouts',
'extrémité',
'extremite',
'extrémités',
'extremites',
'pointe',
'pointes',
'sommet',
'sommets',
'pic',
'pics',
'cime',
'cimes',
'faîte',
'faite',
'faîtes',
'faites',
'crête',
'crete',
'crêtes',
'cretes',
'arête',
'arete',
'arêtes',
'aretes',
'angle',
'angles',
'coin',
'coins',
'recoin',
'recoins',
'recess',
'alcôve',
'alcove',
'alcôves',
'alcoves',
'niche',
'niches',
'anfractuosité',
'anfractuosite',
'anfractuosités',
'anfractuosites',
'cavité',
'cavite',
'cavités',
'cavites',
'trou',
'trous',
'creux',
'orifice',
'orifices',
'ouverture',
'ouvertures',
'fente',
'fentes',
'fissure',
'fissures',
'crevasse',
'crevasses',
'lézarde',
'lezarde',
'lézardes',
'lezardes',
'gerçure',
'gercure',
'gerçures',
'gercures',
'cassure',
'cassures',
'fracture',
'fractures',
'rupture',
'ruptures',
'brisure',
'brisures',
'félure',
'felure',
'félures',
'felures',
'brèche',
'breche',
'brèches',
'breches',
'trouée',
'trouee',
'trouées',
'trouees',
'percée',
'percee',
'percées',
'percees',
'passage',
'passages',
'couloir',
'couloirs',
'corridor',
'corridors',
'galerie',
'galeries',
'tunnel',
'tunnels',
'souterrain',
'souterrains',
'grotte',
'grottes',
'caverne',
'cavernes',
'antre',
'antres',
'tanière',
'taniere',
'tanières',
'tanieres',
'gîte',
'gite',
'gîtes',
'gites',
'refuge',
'refuges',
'abri',
'abris',
'cachette',
'cachettes',
'planque',
'planques',
'repaire',
'repaires',
'retraite',
'retraites',
'ermitage',
'ermitages',
'solitude',
'solitudes',
'isolement',
'isolements',
'séparation',
'separation',
'séparations',
'separations',
'division',
'divisions',
'cloison',
'cloisons',
'paroi',
'parois',
'mur',
'murs',
'muraille',
'murailles',
'rempart',
'remparts',
'fortification',
'fortifications',
'défense',
'defense',
'défenses',
'defenses',
'protection',
'protections',
'blindage',
'blindages',
'cuirasse',
'cuirasses',
'armure',
'armures',
'bouclier',
'boucliers',
'écu',
'ecu',
'écus',
'ecus',
'pavois',
'rondache',
'rondaches',
'targe',
'targes',
'carapace',
'carapaces',
'coquille',
'coquilles',
'écaille',
'ecaille',
'écailles',
'ecailles',
'plaque',
'plaques',
'lame',
'lames',
'feuille',
'feuilles',
'pellicule',
'pellicules',
'membrane',
'membranes',
'tissu',
'tissus',
'étoffe',
'etoffe',
'étoffes',
'etoffes',
'textile',
'textiles',
'fibre',
'fibres',
'fil',
'fils',
'filament',
'filaments',
'brin',
'brins',
'corde',
'cordes',
'ficelle',
'ficelles',
'câble',
'cable',
'câbles',
'cables',
'chaîne',
'chaine',
'chaînes',
'chaines',
'maillon',
'maillons',
'anneau',
'anneaux',
'bague',
'bagues',
'alliance',
'alliances',
'jonc',
'joncs',
'chevalière',
'chevaliere',
'chevalières',
'chevalieres',
'solitaire',
'solitaires',
'diamant',
'diamants',
'pierre',
'pierres',
'gemme',
'gemmes',
'bijou',
'bijoux',
'joyau',
'joyaux',
'parure',
'parures',
'ornement',
'ornements',
'décoration',
'decoration',
'décorations',
'decorations',
'enjolivement',
'enjolivements',
'embellissement',
'embellissements',
'agrément',
'agrement',
'agréments',
'agrements',
'atour',
'atours',
'apparence',
'apparences',
'aspect',
'aspects',
'allure',
'allures',
'prestance',
'prestances',
'élégance',
'elegance',
'élégances',
'elegances',
'raffinement',
'raffinements',
'distinction',
'distinctions',
'classe',
'classes',
'style',
'styles',
'genre',
'genres',
'mode',
'modes',
'tendance',
'tendances',
'fashion',
'fashions',
'couture',
'coutures',
'prêt-à-porter',
'pret-a-porter',
'haute-couture',
'haute couture',
'confection',
'confections',
'vêtement',
'vetement',
'vêtements',
'vetements',
'habit',
'habits',
'tenue',
'tenues',
'costume',
'costumes',
'toilette',
'toilettes',
'mise',
'mises',
'accoutrement',
'accoutrements',
'harnachement',
'harnachements',
'équipement',
'equipement',
'équipements',
'equipements',
'attirail',
'attirails',
'matériel',
'materiel',
'matériels',
'materiels',
'outillage',
'outillages',
'arsenal',
'arsenaux',
'armement',
'armements',
'panoplie',
'panoplies',
'collection',
'collections',
'assortiment',
'assortiments',
'gamme',
'gammes',
'palette',
'palettes',
'éventail',
'eventail',
'éventails',
'eventails',
'choix',
'sélection',
'selection',
'sélections',
'selections',
'tri',
'tris',
'triage',
'triages',
'criblage',
'criblages',
'filtrage',
'filtrages',
'épuration',
'epuration',
'épurations',
'epurations',
'purification',
'purifications',
'assainissement',
'assainissements',
'nettoyage',
'nettoyages',
'lavage',
'lavages',
'rinçage',
'rincage',
'rinçages',
'rincages',
'lessivage',
'lessivages',
'blanchiment',
'blanchiments',
'dégraissage',
'degraissage',
'dégraissages',
'degraissages',
'détachage',
'detachage',
'détachages',
'detachages',
'décrassage',
'decrassage',
'décrassages',
'decrassages',
'récurage',
'recurage',
'récurages',
'recurages',
'frottage',
'frottages',
'brossage',
'brossages',
'polissage',
'polissages',
'lustrage',
'lustrages',
'cirage',
'cirages',
'encaustique',
'encaustiques',
'cire',
'cires',
'pommade',
'pommades',
'baume',
'baumes',
'crème',
'creme',
'crèmes',
'cremes',
'onguent',
'onguents',
'liniment',
'liniments',
'embrocation',
'embrocations',
'friction',
'frictions',
'massage',
'massages',
'pétrissage',
'petrissage',
'pétrissages',
'petrissages',
'malaxage',
'malaxages',
'manipulation',
'manipulations',
'maniement',
'maniements',
'manutention',
'manutentions',
'transport',
'transports',
'acheminement',
'acheminements',
'convoyage',
'convoyages',
'livraison',
'livraisons',
'distribution',
'distributions',
'répartition',
'repartition',
'répartitions',
'repartitions',
'partage',
'partages',
'division',
'divisions',
'séparation',
'separation',
'séparations',
'separations',
'scission',
'scissions',
'coupure',
'coupures',
'découpage',
'decoupage',
'découpages',
'decoupages',
'sectionnement',
'sectionnements',
'segmentation',
'segmentations',
'morcellement',
'morcellements',
'fragmentation',
'fragmentations',
'émiettement',
'emiettement',
'émiettements',
'emiettements',
'pulvérisation',
'pulverisation',
'pulvérisations',
'pulverisations',
'atomisation',
'atomisations',
'vaporisation',
'vaporisations',
'évaporation',
'evaporation',
'évaporations',
'evaporations',
'sublimation',
'sublimations',
'distillation',
'distillations',
'condensation',
'condensations',
'liquéfaction',
'liquefaction',
'liquéfactions',
'liquefactions',
'solidification',
'solidifications',
'cristallisation',
'cristallisations',
'congélation',
'congelation',
'congélations',
'congelations',
'gel',
'gels',
'glaciation',
'glaciations',
'refroidissement',
'refroidissements',
'réfrigération',
'refrigeration',
'réfrigérations',
'refrigerations',
'zut',
'punaise',
],
'false_positives' => [
// Common French words that might be detected as false positives
'analyse',
'analyses',
'classe',
'classes',
'passer',
'passage',
'passages',
'expression',
'expressions',
'assassin',
'assassins',
'assassiner',
'assassinat',
'assassinats',
'entreprise',
'entreprises',
'entrepreneur',
'entrepreneurs',
'affaire',
'affaires',
'travail',
'travaux',
'travailler',
'travailleur',
'travailleurs',
'travailleuse',
'travailleuses',
'emploi',
'emplois',
'employé',
'employe',
'employés',
'employes',
'employée',
'employee',
'employées',
'employees',
'employeur',
'employeurs',
'bureau',
'bureaux',
'ordinateur',
'ordinateurs',
'machine',
'machines',
'appareil',
'appareils',
'dispositif',
'dispositifs',
'instrument',
'instruments',
'outil',
'outils',
'utilité',
'utilites',
'fonction',
'fonctions',
'fonctionner',
'fonctionnement',
'fonctionnements',
'caractéristique',
'caracteristique',
'caractéristiques',
'caracteristiques',
'spécialité',
'specialite',
'spécialités',
'specialites',
'spécialiste',
'specialiste',
'spécialistes',
'specialistes',
'spécialiser',
'specialiser',
'spécialisé',
'specialise',
'spécialisée',
'specialisee',
'spécialisés',
'specialises',
'spécialisées',
'specialisees',
'spécialisation',
'specialisation',
'spécialisations',
'specialisations',
'professionnel',
'professionnels',
'professionnelle',
'professionnelles',
'profession',
'professions',
'professeur',
'professeurs',
'enseigner',
'enseignement',
'enseignements',
'éducation',
'education',
'éducatif',
'educatif',
'éducative',
'educative',
'éducatifs',
'educatifs',
'éducatives',
'educatives',
'éduquer',
'eduquer',
'éduqué',
'eduque',
'éduquée',
'eduquee',
'éduqués',
'eduques',
'éduquées',
'eduquees',
'éducateur',
'educateur',
'éducateurs',
'educateurs',
'éducatrice',
'educatrice',
'éducatrices',
'educatrices',
'étudiant',
'etudiant',
'étudiants',
'etudiants',
'étudiante',
'etudiante',
'étudiantes',
'etudiantes',
'étudier',
'etudier',
'étude',
'etude',
'études',
'etudes',
'étudié',
'etudie',
'étudiée',
'etudiee',
'étudiés',
'etudies',
'étudiées',
'etudiees',
'recherche',
'recherches',
'rechercher',
'chercheur',
'chercheurs',
'chercheuse',
'chercheuses',
'scientifique',
'scientifiques',
'science',
'sciences',
'connaissance',
'connaissances',
'connaître',
'connaitre',
'connu',
'connue',
'connus',
'connues',
'savoir',
'savoirs',
'su',
'sue',
'sus',
'sues',
'sagesse',
'sagesses',
'sage',
'sages',
'intelligence',
'intelligences',
'intelligent',
'intelligents',
'intelligente',
'intelligentes',
'talent',
'talents',
'talentueux',
'talentueuse',
'talentueuses',
'habileté',
'habilete',
'habiletés',
'habiletes',
'habile',
'habiles',
'adresse',
'adresses',
'adroit',
'adroits',
'adroite',
'adroites',
'maître',
'maitre',
'maîtres',
'maitres',
'maîtresse',
'maitresse',
'maîtresses',
'maitresses',
'maîtrise',
'maitrise',
'maîtrises',
'maitrises',
'maîtriser',
'maitriser',
'maîtrisé',
'maitrise',
'maîtrisée',
'maitrisee',
'maîtrisés',
'maitrises',
'maîtrisées',
'maitrisees',
'domaine',
'domaines',
'dominer',
'dominé',
'domine',
'dominée',
'dominee',
'dominés',
'domines',
'dominées',
'dominees',
'contrôle',
'controle',
'contrôles',
'controles',
'contrôler',
'controler',
'contrôlé',
'controle',
'contrôlée',
'controlee',
'contrôlés',
'controles',
'contrôlées',
'controlees',
'administration',
'administrations',
'administrer',
'administrateur',
'administrateurs',
'administratrice',
'administratrices',
'gestion',
'gestions',
'gérer',
'gerer',
'géré',
'gere',
'gérée',
'geree',
'gérés',
'geres',
'gérées',
'gerees',
'gestionnaire',
'gestionnaires',
'organisation',
'organisations',
'organiser',
'organisé',
'organise',
'organisée',
'organisee',
'organisés',
'organises',
'organisées',
'organisees',
'organisateur',
'organisateurs',
'organisatrice',
'organisatrices',
'système',
'systeme',
'systèmes',
'systemes',
'systématique',
'systematique',
'systématiques',
'systematiques',
'méthode',
'methode',
'méthodes',
'methodes',
'méthodologie',
'methodologie',
'méthodologies',
'methodologies',
'processus',
'traiter',
'traité',
'traite',
'traitée',
'traitee',
'traités',
'traites',
'traitées',
'traitees',
'procédure',
'procedure',
'procédures',
'procedures',
'procéder',
'proceder',
'protocole',
'protocoles',
'norme',
'normes',
'normal',
'normaux',
'normale',
'normales',
'normalité',
'normalite',
'normalités',
'normalites',
'normaliser',
'normalisé',
'normalise',
'normalisée',
'normalisee',
'normalisés',
'normalises',
'normalisées',
'normalisees',
'standard',
'standards',
'standardiser',
'standardisé',
'standardise',
'standardisée',
'standardisee',
'standardisés',
'standardises',
'standardisées',
'standardisees',
'règle',
'regle',
'règles',
'regles',
'règlement',
'reglement',
'règlements',
'reglements',
'réglementer',
'reglementer',
'réglementaire',
'reglementaire',
'réglementaires',
'reglementaires',
'réguler',
'reguler',
'régulier',
'regulier',
'réguliers',
'reguliers',
'régulière',
'reguliere',
'régulières',
'regulieres',
'régularité',
'regularite',
'régularités',
'regularites',
'régulariser',
'regulariser',
'régularisé',
'regularise',
'régularisée',
'regularisee',
'régularisés',
'regularises',
'régularisées',
'regularisees',
'loi',
'lois',
'légal',
'legal',
'légaux',
'legaux',
'légale',
'legale',
'légales',
'legales',
'légalité',
'legalite',
'légalités',
'legalites',
'légaliser',
'legaliser',
'légalisé',
'legalise',
'légalisée',
'legalisee',
'légalisés',
'legalises',
'légalisées',
'legalisees',
'droit',
'droits',
'juridique',
'juridiques',
'justice',
'justices',
'juste',
'justes',
'injuste',
'injustes',
'injustice',
'injustices',
'tribunal',
'tribunaux',
'juge',
'juges',
'jugement',
'jugements',
'juger',
'jugé',
'juge',
'jugée',
'jugee',
'jugés',
'juges',
'jugées',
'jugees',
'sentence',
'sentences',
'condamnation',
'condamnations',
'condamner',
'condamné',
'condamne',
'condamnée',
'condamnee',
'condamnés',
'condamnes',
'condamnées',
'condamnees',
'punition',
'punitions',
'punir',
'puni',
'punie',
'punis',
'punies',
'peine',
'peines',
'prison',
'prisons',
'emprisonner',
'emprisonné',
'emprisonne',
'emprisonnée',
'emprisonnee',
'emprisonnés',
'emprisonnes',
'emprisonnées',
'emprisonnees',
'prisonnier',
'prisonniers',
'prisonnière',
'prisonniere',
'prisonnières',
'prisonnieres',
'détenu',
'detenu',
'détenus',
'detenus',
'détenue',
'detenue',
'détenues',
'detenues',
'pénitencier',
'penitencier',
'pénitenciers',
'penitenciers',
'maison',
'maisons',
'arrêt',
'arret',
'arrêts',
'arrets',
],
'substitutions' => [
'/à/' => ['à', 'a', '@', '4'],
'/â/' => ['â', 'a', '@', '4'],
'/ä/' => ['ä', 'a', '@', '4'],
'/á/' => ['á', 'a', '@', '4'],
'/ã/' => ['ã', 'a', '@', '4'],
'/å/' => ['å', 'a', '@', '4'],
'/æ/' => ['æ', 'ae', 'a'],
'/è/' => ['è', 'e', '3', '€'],
'/é/' => ['é', 'e', '3', '€'],
'/ê/' => ['ê', 'e', '3', '€'],
'/ë/' => ['ë', 'e', '3', '€'],
'/ì/' => ['ì', 'i', '1', '!', '|'],
'/í/' => ['í', 'i', '1', '!', '|'],
'/î/' => ['î', 'i', '1', '!', '|'],
'/ï/' => ['ï', 'i', '1', '!', '|'],
'/ò/' => ['ò', 'o', '0', 'ø'],
'/ó/' => ['ó', 'o', '0', 'ø'],
'/ô/' => ['ô', 'o', '0', 'ø'],
'/ö/' => ['ö', 'o', '0', 'ø'],
'/õ/' => ['õ', 'o', '0', 'ø'],
'/ø/' => ['ø', 'o', '0'],
'/œ/' => ['œ', 'oe', 'o'],
'/ù/' => ['ù', 'u', 'ü'],
'/ú/' => ['ú', 'u', 'ü'],
'/û/' => ['û', 'u', 'ü'],
'/ü/' => ['ü', 'u', 'ù'],
'/u/' => ['u', 'ù', 'ú', 'û', 'ü', '@', '*'],
'/ÿ/' => ['ÿ', 'y', 'i'],
'/ç/' => ['ç', 'c', 's'],
'/ñ/' => ['ñ', 'n', '~n'],
'/c/' => ['c', 'k', 'ç', 's'],
'/k/' => ['k', 'c', 'q'],
'/ph/' => ['ph', 'f'],
'/qu/' => ['qu', 'k', 'q'],
'/x/' => ['x', 'ks', 'gs'],
'/z/' => ['z', 's'],
'/j/' => ['j', 'g'],
'/g/' => ['g', 'j'],
]
];
================================================
FILE: config/languages/german.php
================================================
<?php
return [
'severity' => [
'mild' => [
'mist', 'kacke', 'verdammt', 'verdammte', 'verdammter', 'verdammtes',
'blöd', 'bloed', 'blöde', 'bloede', 'blöder', 'bloeder', 'blödes', 'bloedes',
'doof', 'doofe', 'doofer', 'doofes',
'dumm', 'dumme', 'dummer', 'dummes',
'albern', 'alberne', 'alberner', 'albernes',
'peinlich', 'peinliche', 'peinlicher', 'peinliches',
],
'moderate' => [
'arsch', 'arschloch', 'arschlöcher', 'arschlocher',
'schlampe', 'nutte', 'hure',
'wichser', 'depp', 'trottel',
'idiot', 'vollidiot',
'bescheuert', 'bescheuerte', 'bescheuerter', 'bescheuertes',
'bekloppt', 'bekloppte', 'bekloppter', 'beklopptes',
'schwanz', 'pimmel',
'hintern', 'po', 'popo',
'schwul', 'schwuler', 'schwule', 'schwules',
],
'high' => [
'scheiße', 'scheisse', 'ficken', 'fick', 'gefickt',
'verfickt', 'fotze', 'muschi', 'möse', 'moese',
'hurensohn', 'hurenkind', 'arschficker',
'vögeln', 'voegeln', 'bumsen',
],
'extreme' => [
'tunte', 'tuntig',
'kampflesbe', 'kampflesben',
'kanake', 'kanaken',
'neger', 'negerin',
'zigeuner', 'zigeunerin',
'retardiert', 'retardierte', 'retardierter',
],
],
'profanities' => [
// Common German profanities and vulgar expressions
'scheiße',
'scheisse',
'scheiß',
'scheiss',
'kacke',
'mist',
'arsch',
'arschloch',
'arschlöcher',
'arschlocher',
'ficken',
'fick',
'gefickt',
'verfickt',
'verfickte',
'verfickter',
'verficktes',
'verdammt',
'verdammte',
'verdammter',
'verdammtes',
'hurensohn',
'hurenkind',
'hure',
'nutte',
'schlampe',
'fotze',
'muschi',
'möse',
'moese',
'schwanz',
'pimmel',
'dödel',
'doedel',
'lümmel',
'luemmel',
'rute',
'zipfel',
'glied',
'eier',
'hoden',
'klöten',
'kloeten',
'sack',
'hodensack',
'nüsse',
'nuesse',
'kugeln',
'beutel',
'titten',
'brüste',
'brueste',
'busen',
'möpse',
'moepse',
'hupen',
'vorbau',
'körbchen',
'koerbchen',
'milchdrüsen',
'milchdruesen',
'warzen',
'nippel',
'brustwarzen',
'zitzen',
'hintern',
'po',
'popo',
'gesäß',
'gesaess',
'kehrseite',
'vier buchstaben',
'allerwertester',
'rückseite',
'rueckseite',
'backen',
'pobacken',
'arschbacken',
'speck',
'hinterteil',
'schwul',
'schwuler',
'schwule',
'schwules',
'homo',
'homos',
'homosexuell',
'homosexuelle',
'homosexueller',
'homosexuelles',
'tuntig',
'tunte',
'warm',
'warmer',
'warme',
'warmes',
'lesbe',
'lesben',
'lesbisch',
'lesbische',
'lesbischer',
'lesbisches',
'kampflesbe',
'kampflesben',
'butze',
'butzen',
'wichser',
'wichsen',
'wichst',
'gewichst',
'onanieren',
'onaniert',
'masturbieren',
'masturbiert',
'selbstbefriedigung',
'handjob',
'blasen',
'bläst',
'blaest',
'blowjob',
'oral',
'lecken',
'leckt',
'geleckt',
'cunnilingus',
'fellatio',
'lutschen',
'lutscht',
'gelutscht',
'saugen',
'saugt',
'gesaugt',
'pusten',
'pustet',
'gepustet',
'vögeln',
'voegeln',
'vögelt',
'voegelt',
'gevögelt',
'gevoegelt',
'bumsen',
'bumst',
'gebumst',
'poppen',
'poppt',
'gepoppt',
'knallen',
'knallt',
'geknallt',
'nageln',
'nagelt',
'genagelt',
'rammeln',
'rammelt',
'gerammelt',
'durchnageln',
'durchnagelt',
'durchgenagelt',
'durchficken',
'durchfickt',
'durchgefickt',
'rannehmen',
'rannimmt',
'rangenommen',
'besteigen',
'besteigt',
'bestiegen',
'bespringen',
'bespringt',
'besprungen',
'penis',
'vagina',
'vulva',
'klitoris',
'kitzler',
'schamlippen',
'venushügel',
'venushuegel',
'scham',
'geschlecht',
'geschlechtsteil',
'geschlechtsteile',
'genitalien',
'intimbereich',
'unterkörper',
'unterkoerper',
'lenden',
'lendengegend',
'schritt',
'schrittbereich',
'unterleib',
'becken',
'beckenboden',
'damm',
'perineum',
'anus',
'after',
'poloch',
'arschloch',
'rosette',
'poperze',
'hintertür',
'hintertuer',
'ausgang',
'darmausgang',
'enddarm',
'rektum',
'mastdarm',
'analbereich',
'afterbereich',
'hinterlader',
'arschficker',
'arschficken',
'arschgefickt',
'analverkehr',
'analsex',
'sodomie',
'sodomist',
'sodomistin',
'pervers',
'perverse',
'perverser',
'perverses',
'perversling',
'pervertiert',
'pervertierte',
'pervertierter',
'pervertiertes',
'versaut',
'versaute',
'versauter',
'versautes',
'schmutzig',
'schmutzige',
'schmutziger',
'schmutziges',
'dreckig',
'dreckige',
'dreckiger',
'dreckiges',
'dreck',
'unrat',
'abschaum',
'pack',
'gesindel',
'pöbel',
'poebel',
'mob',
'kanaille',
'lumpen',
'lump',
'schuft',
'schurke',
'halunke',
'gauner',
'ganove',
'gangster',
'verbrecher',
'kriminell',
'kriminelle',
'krimineller',
'kriminelles',
'asozial',
'asoziale',
'asozialer',
'asoziales',
'asi',
'prollig',
'prollige',
'prolliger',
'prolliges',
'proll',
'prolet',
'unterschicht',
'prekariat',
'hartz',
'hartzer',
'arbeitslos',
'arbeitslose',
'arbeitsloser',
'arbeitsloses',
'sozialhilfe',
'sozialschmarotzer',
'schmarotzer',
'parasit',
'parasiten',
'ungeziefer',
'schädling',
'schaedling',
'schädlinge',
'schaedlinge',
'plage',
'pest',
'seuche',
'krankheit',
'leiden',
'übel',
'uebel',
'böse',
'boese',
'schlecht',
'schlimm',
'schrecklich',
'furchtbar',
'entsetzlich',
'grauenhaft',
'grausam',
'brutal',
'roh',
'primitiv',
'primitive',
'primitiver',
'primitives',
'barbarisch',
'barbarische',
'barbarischer',
'barbarisches',
'wild',
'wilde',
'wilder',
'wildes',
'ungezähmt',
'ungebildet',
'ungebildete',
'ungebildeter',
'ungebildetes',
'dumm',
'dumme',
'dummer',
'dummes',
'doof',
'doofe',
'doofer',
'doofes',
'blöd',
'bloed',
'blöde',
'bloede',
'blöder',
'bloeder',
'blödes',
'bloedes',
'bescheuert',
'bescheuerte',
'bescheuerter',
'bescheuertes',
'bekloppt',
'bekloppte',
'bekloppter',
'beklopptes',
'verrückt',
'verrueckt',
'verrückte',
'verrueckte',
'verrückter',
'verrueckter',
'verrücktes',
'verruecktes',
'irre',
'irrer',
'irres',
'wahnsinnig',
'wahnsinnige',
'wahnsinniger',
'wahnsinniges',
'gestört',
'gestoert',
'gestörte',
'gestoerte',
'gestörter',
'gestoerter',
'gestörtes',
'gestoertes',
'krank',
'kranke',
'kranker',
'krankes',
'pathologisch',
'pathologische',
'pathologischer',
'pathologisches',
'abnormal',
'abnormale',
'abnormaler',
'abnormales',
'unnormal',
'unnormale',
'unnormaler',
'unnormales',
'abartig',
'abartige',
'abartiger',
'abartiges',
'widerlich',
'widerliche',
'widerlicher',
'widerliches',
'ekelhaft',
'ekelhafte',
'ekelhafter',
'ekelhaftes',
'eklig',
'eklige',
'ekliger',
'ekliges',
'widerwertig',
'widerwertige',
'widerwertiger',
'widerwertiges',
'abstoßend',
'abstossend',
'abstoßende',
'abstossende',
'abstoßender',
'abstossender',
'abstoßendes',
'abstossendes',
'absurd',
'absurde',
'absurder',
'absurdes',
'lächerlich',
'laecherlich',
'lächerliche',
'laecherliche',
'lächerlicher',
'laecherlicher',
'lächerliches',
'laecherliches',
'albern',
'alberne',
'alberner',
'albernes',
'affig',
'affige',
'affiger',
'affiges',
'närrisch',
'naerrisch',
'närrische',
'naerrische',
'närrischer',
'naerrischer',
'närrisches',
'naerrisches',
'töricht',
'toericht',
'törichte',
'toerichte',
'törichter',
'toerichter',
'törichtes',
'toerichtes',
'blamabel',
'blamable',
'blamabler',
'blamables',
'peinlich',
'peinliche',
'peinlicher',
'peinliches',
'beschämend',
'beschaemend',
'beschämende',
'beschaemende',
'beschämender',
'beschaemender',
'beschämendes',
'beschaemendes',
'schmählich',
'schmaehlich',
'schmähliche',
'schmaehliche',
'schmählicher',
'schmaehlicher',
'schmähliches',
'schmaehliches',
'schändlich',
'schaendlich',
'schändliche',
'schaendliche',
'schändlicher',
'schaendlicher',
'schändliches',
'schaendliches',
'gemein',
'gemeine',
'gemeiner',
'gemeines',
'niederträchtig',
'niedertraechtig',
'niederträchtige',
'niedertraechtige',
'niederträchtiger',
'niedertraechtiger',
'niederträchtiges',
'niedertraechtiges',
'hinterhältig',
'hinterhaeltig',
'hinterhältige',
'hinterhaeltige',
'hinterhältiger',
'hinterhaeltiger',
'hinterhältiges',
'hinterhaeltiges',
'heimtückisch',
'heimtueckisch',
'heimtückische',
'heimtueckische',
'heimtückischer',
'heimtueckischer',
'heimtückisches',
'heimtueckisches',
'falsch',
'falsche',
'falscher',
'falsches',
'verlogen',
'verlogene',
'verlogener',
'verlogenes',
'heuchlerisch',
'heuchlerische',
'heuchlerischer',
'heuchlerisches',
'scheinheilig',
'scheinheilige',
'scheinheiliger',
'scheinheiliges',
'doppelzüngig',
'doppelzuengig',
'doppelzüngige',
'doppelzuengige',
'doppelzüngiger',
'doppelzuengiger',
'doppelzüngiges',
'doppelzuengiges',
'verlogen',
'verlogene',
'verlogener',
'verlogenes',
'unaufrichtig',
'unaufrichtige',
'unaufrichtiger',
'unaufrichtiges',
'unehrlich',
'unehrliche',
'unehrlicher',
'unehrliches',
'betrügerisch',
'betruegerisch',
'betrügerische',
'betruegerische',
'betrügerischer',
'betruegerischer',
'betrügerisches',
'betruegerisches',
'schwindelhaft',
'schwindlerisch',
'schwindlerische',
'schwindlerischer',
'schwindlerisches',
'unredlich',
'unredliche',
'unredlicher',
'unredliches',
'unlauter',
'unlautere',
'unlauterer',
'unlauteres',
'unseriös',
'unserioes',
'unseriöse',
'unserioes',
'unseriöser',
'unserioeser',
'unseriöses',
'unserioes',
'dubios',
'dubiose',
'dubioser',
'dubioses',
'fragwürdig',
'fragwuerdig',
'fragwürdige',
'fragwuerdige',
'fragwürdiger',
'fragwuerdiger',
'fragwürdiges',
'fragwuerdiges',
'zweifelhaft',
'zweifelhafte',
'zweifelhafter',
'zweifelhaftes',
'suspekt',
'suspekte',
'suspekter',
'suspektes',
'verdächtig',
'verdaechtig',
'verdächtige',
'verdaechtige',
'verdächtiger',
'verdaechtiger',
'verdächtiges',
'verdaechtiges',
'obskur',
'obskure',
'obskurer',
'obskures',
'dunkel',
'dunkle',
'dunkler',
'dunkles',
'finster',
'finstere',
'finsterer',
'finsteres',
'schwarz',
'schwarze',
'schwarzer',
'schwarzes',
'düster',
'duester',
'düstere',
'duestere',
'düsterer',
'duesterer',
'düsteres',
'duesteres',
'trüb',
'trueb',
'trübe',
'truebe',
'trüber',
'trueber',
'trübes',
'truebes',
'matt',
'matte',
'matter',
'mattes',
'fahl',
'fahle',
'fahler',
'fahles',
'blass',
'blasse',
'blasser',
'blasses',
'bleich',
'bleiche',
'bleicher',
'bleiches',
'käsig',
'kaesig',
'käsige',
'kaesige',
'käsiger',
'kaesiger',
'käsiges',
'kaesiges',
'kränklich',
'kraenklich',
'kränkliche',
'kraenkliche',
'kränklicher',
'kraenklicher',
'kränkliches',
'kraenkliches',
'schwächlich',
'schwaechlich',
'schwächliche',
'schwaechliche',
'schwächlicher',
'schwaechlicher',
'schwächliches',
'schwaechliches',
'schwach',
'schwache',
'schwacher',
'schwaches',
'kraftlos',
'kraftlose',
'kraftloser',
'kraftloses',
'energielos',
'energielose',
'energieloser',
'energieloses',
'müde',
'muede',
'müder',
'mueder',
'müdes',
'muedes',
'erschöpft',
'erschoepft',
'erschöpfte',
'erschoepfte',
'erschöpfter',
'erschoepfter',
'erschöpftes',
'erschoepftes',
'ausgepowert',
'ausgepowerte',
'ausgepower',
'ausgepowertes',
'kaputt',
'kaputte',
'kaputter',
'kaputtes',
'defekt',
'defekte',
'defekter',
'defektes',
'hinüber',
'hinueber',
'im arsch',
'futsch',
'dahin',
'ruiniert',
'ruinierte',
'ruinierter',
'ruiniertes',
'zerstört',
'zerstoert',
'zerstörte',
'zerstoerte',
'zerstörter',
'zerstoerter',
'zerstörtes',
'zerstoertes',
'zerbrochen',
'zerbrochene',
'zerbrochener',
'zerbrochenes',
'zerschmettert',
'zerschmetterte',
'zerschmetterter',
'zerschmettertes',
'demoliert',
'demolierte',
'demolierter',
'demoliertes',
'vernichtet',
'vernichtete',
'vernichteter',
'vernichtetes',
'ausgelöscht',
'ausgeloescht',
'ausgelöschte',
'ausgeloeschte',
'ausgelöschter',
'ausgeloeschter',
'ausgelöschtes',
'ausgeloeschtes',
'eliminiert',
'eliminierte',
'eliminierter',
'eliminiertes',
'getötet',
'getoetet',
'getötete',
'getoetete',
'getöteter',
'getoeteter',
'getötetes',
'getoetetes',
'umgebracht',
'umgebrachte',
'umgebrachter',
'umgebrachtes',
'ermordet',
'ermordete',
'ermordeter',
'ermordetes',
'hingerichtet',
'hingerichtete',
'hingerichteter',
'hingerichtetes',
'exekutiert',
'exekutierte',
'exekutierter',
'exekutiertes',
'liquidiert',
'liquidierte',
'liquidierter',
'liquidiertes',
'abgemurkst',
'abgemurks',
'abgemurkstes',
'kaltgemacht',
'kaltgemachte',
'kaltgemachter',
'kaltgemachtes',
'plattgemacht',
'plattgemachte',
'plattgemachter',
'plattgemachtes',
'fertiggemacht',
'fertiggemachte',
'fertiggemachter',
'fertiggemachtes',
'kaputtgemacht',
'kaputtgemachte',
'kaputtgemachter',
'kaputtgemachtes',
'totgemacht',
'totgemachte',
'totgemachter',
'totgemachtes',
'totgeschlagen',
'totgeschlagene',
'totgeschlagener',
'totgeschlagenes',
'totgeprügelt',
'totgeprügelte',
'totgeprügelter',
'totgeprügeltes',
'totgetrampelt',
'totgetrampelte',
'totgetrampelter',
'totgetrampe',
'totgefahren',
'totgefahrene',
'totgefahrener',
'totgefahrenes',
'überfahren',
'ueberfahren',
'überfahrene',
'ueberfahrene',
'überfahrener',
'ueberfahrener',
'überfahrenes',
'ueberfahrenes',
'totgefahren',
'totgefahrene',
'totgefahrener',
'totgefahrenes',
'erstickt',
'erstickte',
'erstickter',
'ersticktes',
'erwürgt',
'erwuergt',
'erwürgte',
'erwuergte',
'erwürgter',
'erwuergter',
'erwürgtes',
'erwuergtes',
'erdrosselt',
'erdrosselte',
'erdrosselter',
'erdrosseltes',
'stranguliert',
'strangulierte',
'strangulierter',
'stranguliertes',
'gehängt',
'gehaengt',
'gehängte',
'gehaengte',
'gehängter',
'gehaengter',
'gehängtes',
'gehaengtes',
'aufgehängt',
'aufgehaengt',
'aufgehängte',
'aufgehaengte',
'aufgehängter',
'aufgehaengter',
'aufgehängtes',
'aufgehaengtes',
'erhängt',
'erhaengt',
'erhängte',
'erhaengte',
'erhängter',
'erhaengter',
'erhängtes',
'erhaengtes',
'verbrannt',
'verbrannte',
'verbrannter',
'verbranntes',
'angezündet',
'angezuendet',
'angezündete',
'angezuendete',
'angezündeter',
'angezuendeter',
'angezündetes',
'angezuendetes',
'abgefackelt',
'abgefackelte',
'abgefackelter',
'abgefackeltes',
'niedergebrannt',
'niedergebrannte',
'niedergebrannter',
'niedergebranntes',
'eingeäschert',
'eingeaeschert',
'eingeäscherte',
'eingeaescherte',
'eingeäscherter',
'eingeaescherter',
'eingeäschertes',
'eingeaeschertes',
'verbrannt',
'verbrannte',
'verbrannter',
'verbranntes',
'verkohlt',
'verkohlte',
'verkohlter',
'verkohltes',
'verkocht',
'verkochte',
'verkochter',
'verkochtes',
'versotten',
'versottene',
'versottener',
'versottenes',
'versotten',
'versoffene',
'versoffener',
'versoffenes',
'besoffen',
'besoffene',
'besoffener',
'besoffenes',
'betrunken',
'betrunkene',
'betrunkener',
'betrunkenes',
'angetrunken',
'angetrunkene',
'angetrunkener',
'angetrunkenes',
'alkoholisiert',
'alkoholisierte',
'alkoholisierter',
'alkoholisiertes',
'breit',
'breite',
'breiter',
'breites',
'zu',
'zugedröhnt',
'zugedroehnt',
'zugedröhnte',
'zugedroehnte',
'zugedröhnter',
'zugedroeh',
'zugedröhntes',
'zugedroeh',
'dicht',
'dichte',
'dichter',
'dichtes',
'voll',
'volle',
'voller',
'volles',
'hinüber',
'hinueber',
'weggetreten',
'weggetretene',
'weggetretener',
'weggetretenes',
'weg',
'wege',
'weger',
'weges',
'drauf',
'high',
'highe',
'higher',
'highes',
'stoned',
'stoner',
'stones',
'bekifft',
'bekiffte',
'bekiffter',
'bekifftes',
'zugekifft',
'zugekiffte',
'zugekiffter',
'zugekifftes',
'zugeraucht',
'zugerauchte',
'zugerauchter',
'zugerauchtes',
'stramm',
'stramme',
'strammer',
'strammes',
'dicht',
'dichte',
'dichter',
'dichtes',
'platt',
'platte',
'platter',
'plattes',
'depp',
'trottel',
'idiot',
'vollidiot',
'kanake',
'kanaken',
'neger',
'negerin',
'zigeuner',
'zigeunerin',
'retardiert',
'retardierte',
'retardierter',
],
'false_positives' => [
// Common German words that might be detected as false positives
'analyse',
'analysen',
'analysieren',
'analysiert',
'analysierte',
'analysierter',
'analysiertes',
'klasse',
'klassen',
'klassisch',
'klassische',
'klassischer',
'klassisches',
'passen',
'passt',
'gepasst',
'passage',
'passagen',
'ausdruck',
'ausdrücke',
'ausdruecke',
'ausdrücklich',
'ausdruecklich',
'ausdrückliche',
'ausdrueckliche',
'ausdrücklicher',
'ausdruecklicher',
'ausdrückliches',
'ausdrueckliches',
'mörder',
'moerder',
'morden',
'mordet',
'gemordet',
'mord',
'morde',
'mordtat',
'mordtaten',
'unternehmen',
'unternehmens',
'unternehmung',
'unternehmungen',
'unternehmer',
'unternehmerin',
'geschäft',
'geschaeft',
'geschäfte',
'geschaefte',
'geschäftlich',
'geschaeftlich',
'geschäftliche',
'geschaeftliche',
'geschäftlicher',
'geschaeftlicher',
'geschäftliches',
'geschaeftliches',
'arbeit',
'arbeiten',
'arbeiter',
'arbeiterin',
'arbeiterinnen',
'arbeitsplatz',
'arbeitsplätze',
'arbeitsplaetze',
'anstellung',
'anstellungen',
'angestellt',
'angestellte',
'angestellter',
'angestelltes',
'arbeitgeber',
'arbeitgeberin',
'arbeitnehmer',
'arbeitnehmerin',
'büro',
'buero',
'büros',
'bueros',
'computer',
'computers',
'rechner',
'maschine',
'maschinen',
'maschinell',
'maschinelle',
'maschineller',
'maschinelles',
'gerät',
'geraet',
'geräte',
'geraete',
'apparat',
'apparate',
'vorrichtung',
'vorrichtungen',
'instrument',
'instrumente',
'werkzeug',
'werkzeuge',
'hilfsmittel',
'nutzen',
'nützen',
'nuetzen',
'nützlich',
'nuetzlich',
'nützliche',
'nuetzliche',
'nützlicher',
'nuetzlicher',
'nützliches',
'nuetzliches',
'funktion',
'funktionen',
'funktionieren',
'funktioniert',
'funktionierte',
'funktioniertes',
'eigenschaft',
'eigenschaften',
'charakteristikum',
'charakteristika',
'charakteristisch',
'charakteristische',
'charakteristischer',
'charakteristisches',
'spezialität',
'spezialitaet',
'spezialitäten',
'spezialitaeten',
'spezialist',
'spezialisten',
'spezialistin',
'spezialistinnen',
'spezialisieren',
'spezialisiert',
'spezialisierte',
'spezialisierter',
'spezialisiertes',
'spezialisierung',
'spezialisierungen',
'beruflich',
'berufliche',
'beruflicher',
'berufliches',
'beruf',
'berufe',
'lehrer',
'lehrerin',
'lehrerinnen',
'unterrichten',
'unterrichtet',
'unterrichtete',
'unterrichtetes',
'unterricht',
'lehre',
'lehren',
'lehrte',
'gelehrt',
'gelehrte',
'gelehrter',
'gelehrtes',
'bildung',
'bildungen',
'bildungswesen',
'ausbildung',
'ausbildungen',
'erziehung',
'erziehen',
'erzieht',
'erzogen',
'erzogene',
'erzogener',
'erzogenes',
'erzieher',
'erzieherin',
'erzieherinnen',
'student',
'studenten',
'studentin',
'studentinnen',
'studieren',
'studiert',
'studierte',
'studierter',
'studiertes',
'studium',
'studien',
'studie',
'forschung',
'forschungen',
'forschen',
'forscht',
'forschte',
'geforscht',
'forscher',
'forscherin',
'forscherinnen',
'wissenschaft',
'wissenschaften',
'wissenschaftlich',
'wissenschaftliche',
'wissenschaftlicher',
'wissenschaftliches',
'wissenschaftler',
'wissenschaftlerin',
'wissenschaftlerinnen',
'wissen',
'weiss',
'weiß',
'gewusst',
'wusste',
'wissend',
'wissende',
'wissender',
'wissendes',
'kenntnis',
'kenntnisse',
'kennen',
'kennt',
'kannte',
'gekannt',
'bekannt',
'bekannte',
'bekannter',
'bekanntes',
'erkennen',
'erkennt',
'erkannte',
'erkannt',
'erkannte',
'erkannter',
'erkanntes',
'erkenntnis',
'erkenntnisse',
'weisheit',
'weise',
'weisen',
'wies',
'gewiesen',
'intelligent',
'intelligente',
'intelligenter',
'intelligentes',
'intelligenz',
'talent',
'talente',
'talentiert',
'talentierte',
'talentierter',
'talentiertes',
'fähigkeit',
'faehigkeit',
'fähigkeiten',
'faehigkeiten',
'fähig',
'faehig',
'fähige',
'faehige',
'fähiger',
'faehiger',
'fähiges',
'faehiges',
'geschick',
'geschickt',
'geschickte',
'geschickter',
'geschicktes',
'geschicklichkeit',
'geschicklichkeiten',
'fertigkeit',
'fertigkeiten',
'können',
'koennen',
'kann',
'konnte',
'gekonnt',
'meister',
'meisterin',
'meisterinnen',
'meisterschaft',
'meisterschaften',
'meistern',
'meistert',
'meisterte',
'gemeistert',
'bereich',
'bereiche',
'gebiet',
'gebiete',
'domain',
'domäne',
'domaene',
'domänen',
'domaenen',
'beherrschen',
'beherrscht',
'beherrschte',
'beherrschtes',
'beherrschung',
'kontrolle',
'kontrollieren',
'kontrolliert',
'kontrollierte',
'kontrolliertes',
'verwaltung',
'verwaltungen',
'verwalten',
'verwaltet',
'verwaltete',
'verwaltetes',
'verwalter',
'verwalterin',
'verwalterinnen',
'management',
'managements',
'managen',
'gemanagt',
'manager',
'managerin',
'managerinnen',
'führung',
'fuehrung',
'führungen',
'fuehrungen',
'führen',
'fuehren',
'führt',
'fuehrt',
'führte',
'fuehrte',
'geführt',
'gefuehrt',
'führer',
'fuehrer',
'führerin',
'fuehrerin',
'führerinnen',
'fuehrerinnen',
'leitung',
'leitungen',
'leiten',
'leitet',
'leitete',
'geleitet',
'leiter',
'leiterin',
'leiterinnen',
'organisation',
'organisationen',
'organisieren',
'organisiert',
'organisierte',
'organisierter',
'organisiertes',
'system',
'systeme',
'systematisch',
'systematische',
'systematischer',
'systematisches',
'methode',
'methoden',
'methodisch',
'methodische',
'methodischer',
'methodisches',
'verfahren',
'prozess',
'prozesse',
'prozessieren',
'prozessiert',
'prozessierte',
'prozessiertes',
'ablauf',
'abläufe',
'ablaeufe',
'vorgang',
'vorgänge',
'vorgaenge',
'procedere',
'protokoll',
'protokolle',
'norm',
'normen',
'normieren',
'normiert',
'normierte',
'normierter',
'normiertes',
'normal',
'normale',
'normaler',
'normales',
'normalität',
'normalitaet',
'standard',
'standards',
'standardisieren',
'standardisiert',
'standardisierte',
'standardisierter',
'standardisiertes',
'regel',
'regeln',
'reglement',
'reglements',
'reglementieren',
'reglementiert',
'reglementierte',
'reglementiertes',
'regulieren',
'reguliert',
'regulierte',
'reguliertes',
'regular',
'reguläre',
'regulaere',
'regulärer',
'regulaerer',
'reguläres',
'regulaeres',
'regelmäßig',
'regelmaessig',
'regelmäßige',
'regelmaessige',
'regelmäßiger',
'regelmaessiger',
'regelmäßiges',
'regelmaessiges',
'gesetz',
'gesetze',
'gesetzlich',
'gesetzliche',
'gesetzlicher',
'gesetzliches',
'legal',
'legale',
'legaler',
'legales',
'legalität',
'legalitaet',
'legitimität',
'legitimiatet',
'legitim',
'legitime',
'legitimer',
'legitimes',
'legitimieren',
'legitimiert',
'legitimierte',
'legitimiertes',
'recht',
'rechte',
'rechtlich',
'rechtliche',
'rechtlicher',
'rechtliches',
'rechtmäßig',
'rechtmaessig',
'rechtmäßige',
'rechtmaessige',
'rechtmäßiger',
'rechtmaessiger',
'rechtmäßiges',
'rechtmaessiges',
'gerechtigkeit',
'gerecht',
'gerechte',
'gerechter',
'gerechtes',
'ungerecht',
'ungerechte',
'ungerechter',
'ungerechtes',
'ungerechtigkeit',
'ungerechtigkeiten',
'gericht',
'gerichte',
'richter',
'richterin',
'richterinnen',
'richten',
'richtet',
'richtete',
'gerichtet',
'urteil',
'urteile',
'urteilen',
'beurteilen',
'beurteilt',
'beurteilte',
'beurteiltes',
'beurteilung',
'beurteilungen',
'verurteilung',
'verurteilungen',
'verurteilen',
'verurteilt',
'verurteilte',
'verurteiltes',
'schuld',
'schuldig',
'schuldige',
'schuldiger',
'schuldiges',
'strafe',
'strafen',
'bestrafen',
'bestraft',
'bestrafte',
'bestrafter',
'bestrafftes',
'bestrafung',
'bestrafungen',
'gefängnis',
'gefaengnis',
'gefängnisse',
'gefaengnisse',
'knast',
'einsperren',
'eingesperrt',
'eingesperrte',
'eingesperrter',
'eingesperrtes',
'häftling',
'haeftling',
'häftlinge',
'haeftlinge',
'sträfling',
'straefling',
'sträflinge',
'straeflinge',
'inhaftiert',
'inhaftierte',
'inhaftierter',
'inhaftiertes',
'inhaftierung',
'inhaftierungen',
'festnahme',
'festnahmen',
'festnehmen',
'festgenommen',
'verhaftung',
'verhaftungen',
'verhaften',
'verhaftet',
'verhaftete',
'verhafteter',
'verhaftetes',
'arrest',
'arrestieren',
'arrestiert',
'arrestierte',
'arrestiertes',
],
'substitutions' => [
'/ä/' => ['ä', 'a', 'ae', '@', '4'],
'/ö/' => ['ö', 'o', 'oe', '0', 'ø'],
'/ü/' => ['ü', 'u', 'ue'],
'/ß/' => ['ß', 'ss', 's'],
'/á/' => ['á', 'a', '@', '4'],
'/à/' => ['à', 'a', '@', '4'],
'/â/' => ['â', 'a', '@', '4'],
'/ã/' => ['ã', 'a', '@', '4'],
'/å/' => ['å', 'a', '@', '4'],
'/æ/' => ['æ', 'ae', 'a'],
'/é/' => ['é', 'e', '3', '€'],
'/è/' => ['è', 'e', '3', '€'],
'/ê/' => ['ê', 'e', '3', '€'],
'/ë/' => ['ë', 'e', '3', '€'],
'/í/' => ['í', 'i', '1', '!', '|'],
'/ì/' => ['ì', 'i', '1', '!', '|'],
'/î/' => ['î', 'i', '1', '!', '|'],
'/ï/' => ['ï', 'i', '1', '!', '|'],
'/ó/' => ['ó', 'o', '0', 'ø'],
'/ò/' => ['ò', 'o', '0', 'ø'],
'/ô/' => ['ô', 'o', '0', 'ø'],
'/õ/' => ['õ', 'o', '0', 'ø'],
'/ø/' => ['ø', 'o', '0'],
'/ú/' => ['ú', 'u', 'ü'],
'/ù/' => ['ù', 'u', 'ü'],
'/û/' => ['û', 'u', 'ü'],
'/u/' => ['u', 'ü', 'ù', 'ú', 'û', '@', '*'],
'/c/' => ['c', 'k', 's', 'z'],
'/k/' => ['k', 'c', 'ck'],
'/ck/' => ['ck', 'k', 'c'],
'/z/' => ['z', 's', 'tz'],
'/tz/' => ['tz', 'z', 's'],
'/pf/' => ['pf', 'f', 'p'],
'/ph/' => ['ph', 'f'],
'/sch/' => ['sch', 'sh', 'ch'],
'/ch/' => ['ch', 'sh', 'x'],
'/ie/' => ['ie', 'i', 'y'],
'/ei/' => ['ei', 'ai', 'ey'],
'/ai/' => ['ai', 'ei', 'ay'],
'/au/' => ['au', 'aw', 'ou'],
'/eu/' => ['eu', 'oi', 'oy'],
'/äu/' => ['äu', 'aeu', 'oy'],
'/dt/' => ['dt', 't', 'd'],
'/st/' => ['st', 's', 't'],
]
];
================================================
FILE: config/languages/spanish.php
================================================
<?php
return [
'severity' => [
'mild' => [
'maldito', 'maldita', 'maldición', 'maldicion', 'carajo',
'hostia', 'hostias', 'jolines', 'joline', 'jobar', 'joroba',
'caca', 'mear', 'meada', 'peo', 'pedorro', 'pedorra', 'pedos',
'tonto', 'tonta', 'bobo', 'boba', 'baboso', 'babosa',
'cursi', 'pesado', 'pesada', 'latoso', 'latosa',
],
'moderate' => [
'cabrón', 'cabron', 'cabrona', 'cabrones', 'cabronazo',
'perra', 'zorra', 'gilipollas', 'gilipolla',
'imbécil', 'imbecil', 'idiota', 'estúpido', 'estupido', 'estúpida', 'estupida',
'pendejo', 'pendeja', 'mamón', 'mamon',
'boludo', 'boluda', 'pelotudo', 'pelotuda',
'culo', 'ojete', 'putilla', 'putita',
'capullo', 'coñazo', 'conazo', 'putada',
],
'high' => [
'mierda', 'joder', 'coño', 'puta', 'puto',
'chingar', 'chingado', 'chingada', 'pinche',
'verga', 'follar', 'follada', 'follando',
'hijo de puta', 'hijoputa', 'concha', 'cojones',
],
'extreme' => [
'maricón', 'maricon', 'marica', 'maricona', 'mariconazo',
'tortillera', 'bollera',
'retrasado', 'retrasada', 'retardado', 'retardada',
'mongoloide', 'subnormal',
],
],
'profanities' => [
// Common Spanish profanities and vulgar expressions
'mierda',
'joder',
'coño',
'cabrón',
'cabron',
'puta',
'puto',
'jodido',
'jodida',
'hijo de puta',
'hijoputa',
'gilipollas',
'gilipolla',
'imbécil',
'imbecil',
'idiota',
'estúpido',
'estupido',
'pendejo',
'pendeja',
'mamón',
'mamon',
'mamada',
'chingar',
'chingas',
'chingado',
'chingada',
'pinche',
'verga',
'carajo',
'cojones',
'huevos',
'huevón',
'huevon',
'maricón',
'maricon',
'marica',
'homosexual',
'tortillera',
'bollera',
'follar',
'folla',
'follada',
'follando',
'culiar',
'culear',
'culo',
'ojete',
'concha',
'chocha',
'chochito',
'chucha',
'almeja',
'zorra',
'zorro',
'putilla',
'putita',
'perra',
'perro',
'cabrona',
'cabrones',
'puton',
'putón',
'putona',
'putañero',
'putanero',
'polla',
'picha',
'rabo',
'nabo',
'cipote',
'chorizo',
'salchicha',
'salchichón',
'salchichon',
'miembro',
'pene',
'pijo',
'capullo',
'caput',
'gusano',
'rata',
'caca',
'mear',
'meada',
'orín',
'orin',
'orina',
'orinarse',
'cagar',
'cagada',
'cagarse',
'cagón',
'cagon',
'cagona',
'culiacan',
'culiao',
'culiado',
'culero',
'culera',
'nalgas',
'trasero',
'pompis',
'pompas',
'tetona',
'tetuda',
'tetas',
'pechos',
'chichonas',
'chichona',
'zángano',
'zangano',
'cabronazo',
'hijoelagranputa',
'hijoeputa',
'malparido',
'malparida',
'desgraciado',
'desgraciada',
'sinvergüenza',
'sinverguenza',
'cochino',
'cochina',
'guarro',
'guarra',
'sucio',
'sucia',
'asqueroso',
'asquerosa',
'repugnante',
'vomitivo',
'vomitiva',
'nauseabundo',
'nauseabunda',
'escoria',
'basura',
'porquería',
'porqueria',
'maldito',
'maldita',
'condenado',
'condenada',
'jodón',
'jodon',
'jodona',
'molesto',
'molesta',
'fastidioso',
'fastidiosa',
'cabronazo',
'maricona',
'mariconazo',
'bolludo',
'bolluda',
'boludo',
'boluda',
'pelotudo',
'pelotuda',
'tarado',
'tarada',
'retrasado',
'retrasada',
'retardado',
'retardada',
'mongoloide',
'subnormal',
'anormal',
'deficiente',
'tonto',
'tonta',
'bobo',
'boba',
'baboso',
'babosa',
'babas',
'ñoño',
'ñona',
'cursi',
'ridículo',
'ridiculo',
'ridícula',
'ridicula',
'estúpida',
'estupida',
'gorda',
'gordo',
'gordinflas',
'gordinfla',
'ballena',
'vaca',
'cerda',
'cerdo',
'chancho',
'chancha',
'marrano',
'marrana',
'cochino',
'cochina',
'puerco',
'puerca',
'animal',
'bestia',
'salvaje',
'bárbaro',
'barbaro',
'bárbara',
'barbara',
'bruto',
'bruta',
'burro',
'burra',
'asno',
'asna',
'mula',
'mulo',
'bestia',
'fiera',
'demonio',
'diablo',
'diabla',
'satanás',
'satanas',
'lucifer',
'maldición',
'maldicion',
'carajo',
'hostia',
'hostias',
'jolines',
'joline',
'jobar',
'joroba',
'cojonudo',
'cojonuda',
'cojudo',
'cojuda',
'acojonante',
'descojonarse',
'descojonar',
'tocapelotas',
'tocacojones',
'rompepelotas',
'rompecojones',
'pelmazos',
'pelmazo',
'pelma',
'plasta',
'pesado',
'pesada',
'pesao',
'pesá',
'latoso',
'latosa',
'coñazo',
'conazo',
'putada',
'jodienda',
'follón',
'follon',
'lío',
'lio',
'marrón',
'marron',
'peo',
'pedorro',
'pedorra',
'pedos',
'ventosidad',
'flatulencia',
'gases',
'tirarse pedos',
'echar pedos',
'soltar pedos',
'heder',
'apestar',
'oler mal',
'tufo',
'peste',
'pestilencia',
'putrefacción',
'putrefaccion',
'putrefacto',
'putrefacta',
'podrido',
'podrida',
'rancio',
'rancia',
'agrio',
'agria',
'amargo',
'amarga',
'salado',
'salada',
'soso',
'sosa',
'insípido',
'insipido',
'insípida',
'insipida',
'desabrido',
'desabrida',
'malo',
'mala',
'malísimo',
'malisimo',
'malísima',
'malisima',
'pésimo',
'pesimo',
'pésima',
'pesima',
'horrible',
'horroroso',
'horrorosa',
'terrorífico',
'terrorifico',
'terrorífica',
'terrorifica',
'espantoso',
'espantosa',
'horripilante',
'espeluznante',
'escalofriante',
'siniestro',
'siniestra',
'tenebroso',
'tenebrosa',
'lúgubre',
'lugubre',
'sombrío',
'sombrio',
'sombría',
'sombria',
'triste',
'melancólico',
'melancolico',
'melancólica',
'melancolica',
'deprimido',
'deprimida',
'depresivo',
'depresiva',
'suicida',
'morir',
'muerte',
'muerto',
'muerta',
'cadáver',
'cadaver',
'difunto',
'difunta',
'finado',
'finada',
'fallecido',
'fallecida',
'occiso',
'occisa',
'fiambre',
'estirar la pata',
'diñar',
'dinar',
'palmar',
'pelar',
'espichar',
'fenecer',
'expirar',
'perecer',
'sucumbir',
'fallecer',
'óbito',
'obito',
'defunción',
'defuncion',
'deceso',
'tránsito',
'transito',
'partida',
'despedida',
'adiós',
'adios',
'hasta la vista',
'hasta luego',
'hasta pronto',
'hasta mañana',
'hasta manana',
'chau',
'chao',
'bye',
'goodbye',
],
'false_positives' => [
// Common Spanish words that might be detected as false positives
'análisis',
'analisis',
'clase',
'clases',
'paso',
'pasos',
'expresión',
'expresion',
'expresiones',
'asesino',
'asesina',
'asesinar',
'asesinato',
'empresa',
'empresas',
'empresario',
'empresaria',
'negocio',
'negocios',
'trabajo',
'trabajos',
'trabajar',
'trabajador',
'trabajadora',
'empleo',
'empleos',
'empleado',
'empleada',
'empleador',
'empleadora',
'oficina',
'oficinas',
'oficinista',
'escritorio',
'escritorios',
'computadora',
'computadoras',
'computador',
'computadores',
'ordenador',
'ordenadores',
'máquina',
'maquina',
'máquinas',
'maquinas',
'aparato',
'aparatos',
'dispositivo',
'dispositivos',
'instrumento',
'instrumentos',
'herramienta',
'herramientas',
'útil',
'util',
'útiles',
'utiles',
'utilidad',
'utilidades',
'función',
'funcion',
'funciones',
'funcional',
'funcionalidad',
'funcionalidades',
'característico',
'caracteristico',
'característica',
'caracteristica',
'características',
'caracteristicas',
'especialidad',
'especialidades',
'especialista',
'especialistas',
'especializar',
'especializado',
'especializada',
'especialización',
'especializacion',
'profesional',
'profesionales',
'profesión',
'profesion',
'profesiones',
'profesor',
'profesora',
'profesores',
'profesoras',
'enseñar',
'ensenar',
'enseñanza',
'ensenanza',
'enseñanzas',
'ensenanzas',
'educación',
'educacion',
'educativo',
'educativa',
'educativos',
'educativas',
'educar',
'educado',
'educada',
'educador',
'educadora',
'educadores',
'educadoras',
'estudiante',
'estudiantes',
'estudiar',
'estudio',
'estudios',
'estudiado',
'estudiada',
'investigación',
'investigacion',
'investigaciones',
'investigar',
'investigador',
'investigadora',
'investigadores',
'investigadoras',
'científico',
'cientifico',
'científica',
'cientifica',
'científicos',
'cientificos',
'científicas',
'cientificas',
'ciencia',
'ciencias',
'conocimiento',
'conocimientos',
'conocer',
'conocido',
'conocida',
'conocidos',
'conocidas',
'saber',
'sabido',
'sabida',
'sabidos',
'sabidas',
'sabiduría',
'sabiduria',
'sabio',
'sabia',
'sabios',
'sabias',
'inteligente',
'inteligentes',
'inteligencia',
'inteligencias',
'talento',
'talentos',
'talentoso',
'talentosa',
'talentosos',
'talentosas',
'habilidad',
'habilidades',
'hábil',
'habil',
'hábiles',
'habiles',
'destreza',
'destrezas',
'destro',
'destra',
'diestro',
'diestra',
'diestros',
'diestras',
'maestro',
'maestra',
'maestros',
'maestras',
'maestría',
'maestria',
'maestrías',
'maestrias',
'dominio',
'dominios',
'dominar',
'dominado',
'dominada',
'dominados',
'dominadas',
'control',
'controles',
'controlar',
'controlado',
'controlada',
'controlados',
'controladas',
'administración',
'administracion',
'administrar',
'administrador',
'administradora',
'administradores',
'administradoras',
'gestión',
'gestion',
'gestiones',
'gestionar',
'gestor',
'gestora',
'gestores',
'gestoras',
'organización',
'organizacion',
'organizaciones',
'organizar',
'organizador',
'organizadora',
'organizadores',
'organizadoras',
'sistema',
'sistemas',
'sistemático',
'sistematico',
'sistemática',
'sistematica',
'sistemáticos',
'sistematicos',
'sistemáticas',
'sistematicas',
'método',
'metodo',
'métodos',
'metodos',
'metodología',
'metodologia',
'metodologías',
'metodologias',
'proceso',
'procesos',
'procesar',
'procesado',
'procesada',
'procesados',
'procesadas',
'procedimiento',
'procedimientos',
'proceder',
'protocolo',
'protocolos',
'norma',
'normas',
'normal',
'normales',
'normalidad',
'normalidades',
'normalizar',
'normalizado',
'normalizada',
'normalizados',
'normalizadas',
'estándar',
'estandar',
'estándares',
'estandares',
'estandarizar',
'estandarizado',
'estandarizada',
'estandarizados',
'estandarizadas',
'regla',
'reglas',
'reglamento',
'reglamentos',
'reglamentar',
'reglamentario',
'reglamentaria',
'reglamentarios',
'reglamentarias',
'regular',
'regulares',
'regularidad',
'regularidades',
'regularizar',
'regularizado',
'regularizada',
'regularizados',
'regularizadas',
'ley',
'leyes',
'legal',
'legales',
'legalidad',
'legalidades',
'legalizar',
'legalizado',
'legalizada',
'legalizados',
'legalizadas',
'derecho',
'derechos',
'jurídico',
'juridico',
'jurídica',
'juridica',
'jurídicos',
'juridicos',
'jurídicas',
'juridicas',
'justicia',
'justicias',
'justo',
'justa',
'justos',
'justas',
'injusto',
'injusta',
'injustos',
'injustas',
'injusticia',
'injusticias',
'tribunal',
'tribunales',
'juez',
'jueces',
'jueza',
'juezas',
'juzgar',
'juzgado',
'juzgada',
'juzgados',
'juzgadas',
'sentencia',
'sentencias',
'sentenciar',
'sentenciado',
'sentenciada',
'sentenciados',
'sentenciadas',
'condena',
'condenas',
'condenar',
'condenado',
'condenada',
'condenados',
'condenadas',
'castigo',
'castigos',
'castigar',
'castigado',
'castigada',
'castigados',
'castigadas',
'pena',
'penas',
'penar',
'penado',
'penada',
'penados',
'penadas',
'prisión',
'prision',
'prisiones',
'cárcel',
'carcel',
'cárceles',
'carceles',
'encarcelar',
'encarcelado',
'encarcelada',
'encarcelados',
'encarceladas',
'preso',
'presa',
'presos',
'presas',
'presidio',
'presidios',
'penitenciaría',
'penitenciaria',
'penitenciarías',
'penitenciarias',
'reformatorio',
'reformatorios',
],
'substitutions' => [
'/ñ/' => ['ñ', 'n', '~n', 'ni'],
'/á/' => ['á', 'a', '@', '4'],
'/é/' => ['é', 'e', '3', '€'],
'/í/' => ['í', 'i', '1', '!', '|'],
'/ó/' => ['ó', 'o', '0', 'ø'],
'/ú/' => ['ú', 'u', 'ü'],
'/ü/' => ['ü', 'u', 'ú'],
'/u/' => ['u', 'ú', 'ü', '@', '*'],
'/c/' => ['c', 'k', 'ç'],
'/ll/' => ['ll', 'y', 'i'],
'/rr/' => ['rr', 'r'],
'/ch/' => ['ch', 'x'],
'/z/' => ['z', 's', 'c'],
'/j/' => ['j', 'x', 'h'],
'/g/' => ['g', 'j', 'h'],
'/b/' => ['b', 'v', 'w'],
'/v/' => ['v', 'b', 'w'],
]
];
================================================
FILE: phpunit.xml
================================================
<phpunit bootstrap="vendor/autoload.php" colors="true">
<testsuites>
<testsuite name="Application Tests">
<directory>./tests</directory>
</testsuite>
</testsuites>
<php>
<env name="APP_ENV" value="testing"/>
</php>
</phpunit>
================================================
FILE: src/BlaspManager.php
================================================
<?php
namespace Blaspsoft\Blasp;
use Closure;
use Illuminate\Contracts\Foundation\Application;
use Blaspsoft\Blasp\Core\Contracts\DriverInterface;
use Blaspsoft\Blasp\Drivers\RegexDriver;
use Blaspsoft\Blasp\Drivers\PatternDriver;
use Blaspsoft\Blasp\Drivers\PhoneticDriver;
use Blaspsoft\Blasp\Drivers\PipelineDriver;
use InvalidArgumentException;
class BlaspManager
{
protected Application $app;
protected array $drivers = [];
protected array $customCreators = [];
public function __construct(Application $app)
{
$this->app = $app;
}
public function driver(?string $driver = null): PendingCheck
{
return $this->newPendingCheck()->driver($driver ?? $this->getDefaultDriver());
}
public function resolveDriver(string $name): DriverInterface
{
if (!isset($this->drivers[$name])) {
$this->drivers[$name] = $this->createDriver($name);
}
return $this->drivers[$name];
}
protected function createDriver(string $name): DriverInterface
{
if (isset($this->customCreators[$name])) {
return ($this->customCreators[$name])($this->app);
}
$method = 'create' . ucfirst($name) . 'Driver';
if (method_exists($this, $method)) {
return $this->$method();
}
throw new InvalidArgumentException("Driver [{$name}] not supported.");
}
public function createRegexDriver(): DriverInterface
{
return new RegexDriver();
}
public function createPatternDriver(): DriverInterface
{
return new PatternDriver();
}
public function createPhoneticDriver(): DriverInterface
{
$config = $this->app['config']->get('blasp.drivers.phonetic', []);
return new PhoneticDriver(
phonemes: $config['phonemes'] ?? 4,
minWordLength: $config['min_word_length'] ?? 3,
maxDistanceRatio: $config['max_distance_ratio'] ?? 0.6,
phoneticFalsePositives: $config['false_positives'] ?? [],
supportedLanguages: $config['supported_languages'] ?? ['english'],
);
}
public function createPipelineDriver(): DriverInterface
{
$config = $this->app['config']->get('blasp.drivers.pipeline', []);
$driverNames = $config['drivers'] ?? ['regex', 'phonetic'];
if (!is_array($driverNames)) {
throw new InvalidArgumentException('blasp.drivers.pipeline.drivers must be an array of driver names.');
}
foreach ($driverNames as $name) {
if (!is_string($name) || trim($name) === '') {
throw new InvalidArgumentException('Each pipeline driver name must be a non-empty string.');
}
if (strtolower(trim($name)) === 'pipeline') {
throw new InvalidArgumentException('Pipeline driver cannot contain itself. Remove "pipeline" from blasp.drivers.pipeline.drivers.');
}
}
$resolvedDrivers = array_map(
fn (string $name) => $this->resolveDriver($name),
$driverNames,
);
return new PipelineDriver($resolvedDrivers);
}
public function extend(string $driver, Closure $callback): self
{
$this->customCreators[$driver] = $callback;
return $this;
}
public function getDefaultDriver(): string
{
return $this->app['config']->get('blasp.default', 'regex');
}
public function newPendingCheck(): PendingCheck
{
return new PendingCheck($this);
}
public function pipeline(string ...$drivers): PendingCheck
{
return $this->newPendingCheck()->pipeline(...$drivers);
}
// --- Shortcut methods that create PendingCheck ---
public function check(?string $text): \Blaspsoft\Blasp\Core\Result
{
return $this->newPendingCheck()->check($text);
}
public function checkMany(array $texts): array
{
return $this->newPendingCheck()->checkMany($texts);
}
public function __call(string $method, array $parameters): mixed
{
return $this->newPendingCheck()->$method(...$parameters);
}
public function getApp(): Application
{
return $this->app;
}
}
================================================
FILE: src/BlaspServiceProvider.php
================================================
<?php
namespace Blaspsoft\Blasp;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Str;
use Illuminate\Support\Stringable;
class BlaspServiceProvider extends ServiceProvider
{
public function boot(): void
{
if ($this->app->runningInConsole()) {
$this->publishes([
__DIR__ . '/../config/blasp.php' => config_path('blasp.php'),
], 'blasp-config');
$this->publishes([
__DIR__ . '/../config/languages' => config_path('languages'),
], 'blasp-languages');
$this->publishes([
__DIR__ . '/../config/blasp.php' => config_path('blasp.php'),
__DIR__ . '/../config/languages' => config_path('languages'),
], 'blasp');
$this->commands([
Console\ClearCommand::class,
Console\TestCommand::class,
Console\LanguagesCommand::class,
]);
}
$this->registerValidationRule();
$this->registerMiddlewareAlias();
$this->registerBladeDirectives();
$this->registerStringMacros();
}
public function register(): void
{
$this->mergeConfigFrom(__DIR__ . '/../config/blasp.php', 'blasp');
$this->app->singleton('blasp', function ($app) {
return new BlaspManager($app);
});
$this->app->alias('blasp', BlaspManager::class);
}
protected function registerValidationRule(): void
{
$this->app['validator']->extend('blasp_check', function ($attribute, $value, $parameters) {
if (!is_string($value) || $value === '') {
return true;
}
$language = $parameters[0] ?? config('blasp.language', config('blasp.default_language', 'english'));
$manager = $this->app->make('blasp');
$result = $manager->in($language)->check($value);
return !$result->isOffensive();
}, 'The :attribute contains profanity.');
}
protected function registerMiddlewareAlias(): void
{
$this->app['router']->aliasMiddleware('blasp', Middleware\CheckProfanity::class);
}
protected function registerBladeDirectives(): void
{
Blade::directive('clean', function (string $expression) {
return "<?php echo e(app('blasp')->check({$expression})->clean()); ?>";
});
}
protected function registerStringMacros(): void
{
Str::macro('isProfane', function (string $text): bool {
return app('blasp')->check($text)->isOffensive();
});
Str::macro('cleanProfanity', function (string $text): string {
return app('blasp')->check($text)->clean();
});
Stringable::macro('isProfane', function (): bool {
return app('blasp')->check((string) $this)->isOffensive();
});
Stringable::macro('cleanProfanity', function (): Stringable {
return new Stringable(app('blasp')->check((string) $this)->clean());
});
}
}
================================================
FILE: src/Blaspable.php
================================================
<?php
namespace Blaspsoft\Blasp;
use Closure;
use Blaspsoft\Blasp\Core\Result;
use Blaspsoft\Blasp\Events\ModelProfanityDetected;
use Blaspsoft\Blasp\Exceptions\ProfanityRejectedException;
use Illuminate\Database\Eloquent\Model;
/**
* @mixin \Illuminate\Database\Eloquent\Model
*
* @property array $blaspable
* @property string $blaspMode
* @property string|null $blaspLanguage
* @property string|null $blaspMask
*/
trait Blaspable
{
protected static bool $blaspCheckingDisabled = false;
/** @var array<string, Result> */
protected array $blaspResultsCache = [];
public static function bootBlaspable(): void
{
static::saving(function (Model $model) {
if (static::$blaspCheckingDisabled) {
return;
}
$model->blaspResultsCache = [];
$attributes = $model->blaspable ?? [];
$dirty = $model->getDirty();
$mode = $model->blaspMode ?? config('blasp.model.mode', 'sanitize');
foreach ($attributes as $attr) {
if (!isset($dirty[$attr]) || !is_string($dirty[$attr])) {
continue;
}
/** @var PendingCheck $check */
$check = app('blasp')->newPendingCheck();
if ($lang = ($model->blaspLanguage ?? null)) {
$check = $check->in($lang);
}
if ($mask = ($model->blaspMask ?? null)) {
$check = $check->mask($mask);
}
$result = $check->check($dirty[$attr]);
$model->blaspResultsCache[$attr] = $result;
if ($result->isOffensive()) {
event(new ModelProfanityDetected($model, $attr, $result));
if ($mode === 'reject') {
throw ProfanityRejectedException::forModel($model, $attr, $result);
}
$model->setAttribute($attr, $result->clean());
}
}
});
}
public function hadProfanity(): bool
{
foreach ($this->blaspResultsCache as $result) {
if ($result->isOffensive()) {
return true;
}
}
return false;
}
/** @return array<string, Result> */
public function blaspResults(): array
{
return $this->blaspResultsCache;
}
public function blaspResult(string $attribute): ?Result
{
return $this->blaspResultsCache[$attribute] ?? null;
}
public static function withoutBlaspChecking(Closure $callback): mixed
{
$previousState = static::$blaspCheckingDisabled;
static::$blaspCheckingDisabled = true;
try {
return $callback();
} finally {
static::$blaspCheckingDisabled = $previousState;
}
}
}
================================================
FILE: src/Console/ClearCommand.php
================================================
<?php
namespace Blaspsoft\Blasp\Console;
use Illuminate\Console\Command;
use Blaspsoft\Blasp\Core\Dictionary;
class ClearCommand extends Command
{
protected $signature = 'blasp:clear';
protected $description = 'Clear the Blasp profanity cache';
public function handle(): void
{
Dictionary::clearCache();
$this->info('Blasp cache cleared successfully!');
}
}
================================================
FILE: src/Console/LanguagesCommand.php
================================================
<?php
namespace Blaspsoft\Blasp\Console;
use Illuminate\Console\Command;
use Blaspsoft\Blasp\Core\Dictionary;
class LanguagesCommand extends Command
{
protected $signature = 'blasp:languages';
protected $description = 'List available languages and their word counts';
public function handle(): void
{
$languages = Dictionary::getAvailableLanguages();
$rows = [];
foreach ($languages as $language) {
$config = Dictionary::loadLanguageConfig($language);
$profanityCount = count($config['profanities'] ?? []);
$falsePositiveCount = count($config['false_positives'] ?? []);
$hasSeverity = isset($config['severity']) ? 'Yes' : 'No';
$rows[] = [
ucfirst($language),
$profanityCount,
$falsePositiveCount,
$hasSeverity,
];
}
$this->table(['Language', 'Profanities', 'False Positives', 'Severity Map'], $rows);
}
}
================================================
FILE: src/Console/TestCommand.php
================================================
<?php
namespace Blaspsoft\Blasp\Console;
use Illuminate\Console\Command;
class TestCommand extends Command
{
protected $signature = 'blasp:test {text} {--lang= : Language to check against} {--detail}';
protected $description = 'Test profanity detection on a given text';
public function handle(): void
{
$text = $this->argument('text');
$language = $this->option('lang') ?? config('blasp.language', config('blasp.default_language', 'english'));
$manager = app('blasp');
$result = $manager->in($language)->check($text);
$this->info("Input: {$text}");
$this->info("Language: {$language}");
$this->newLine();
if ($result->isOffensive()) {
$this->error('Profanity detected!');
$this->table(
['Property', 'Value'],
[
['Clean text', $result->clean()],
['Score', $result->score()],
['Count', $result->count()],
['Severity', $result->severity()?->value ?? 'n/a'],
['Unique words', implode(', ', $result->uniqueWords())],
]
);
if ($this->option('detail')) {
$this->newLine();
$this->info('Matched words:');
$rows = [];
foreach ($result->words() as $word) {
$rows[] = [
$word->text,
$word->base,
$word->severity->value,
$word->position,
$word->length,
];
}
$this->table(['Text', 'Base', 'Severity', 'Position', 'Length'], $rows);
}
} else {
$this->info('No profanity detected. Text is clean.');
}
}
}
================================================
FILE: src/Core/Analyzer.php
================================================
<?php
namespace Blaspsoft\Blasp\Core;
use Blaspsoft\Blasp\Core\Contracts\DriverInterface;
use Blaspsoft\Blasp\Core\Contracts\MaskStrategyInterface;
use Blaspsoft\Blasp\Core\Masking\CharacterMask;
class Analyzer
{
public function analyze(
string $text,
DriverInterface $driver,
Dictionary $dictionary,
?MaskStrategyInterface $mask = null,
array $options = [],
): Result {
$mask = $mask ?? new CharacterMask(config('blasp.mask', config('blasp.mask_character', '*')));
// Strip invisible Unicode format characters (zero-width spaces, invisible separators, etc.)
// before any driver sees the text, ensuring consistent positions across pipeline drivers
$text = preg_replace('/\p{Cf}/u', '', $text) ?? $text;
return $driver->detect($text, $dictionary, $mask, $options);
}
}
================================================
FILE: src/Core/Contracts/DriverInterface.php
================================================
<?php
namespace Blaspsoft\Blasp\Core\Contracts;
use Blaspsoft\Blasp\Core\Dictionary;
use Blaspsoft\Blasp\Core\Result;
interface DriverInterface
{
public function detect(string $text, Dictionary $dictionary, MaskStrategyInterface $mask, array $options = []): Result;
}
================================================
FILE: src/Core/Contracts/MaskStrategyInterface.php
================================================
<?php
namespace Blaspsoft\Blasp\Core\Contracts;
interface MaskStrategyInterface
{
public function mask(string $word, int $length): string;
}
================================================
FILE: src/Core/Dictionary.php
================================================
<?php
namespace Blaspsoft\Blasp\Core;
use Blaspsoft\Blasp\Enums\Severity;
use Blaspsoft\Blasp\Core\Matchers\RegexMatcher;
use Blaspsoft\Blasp\Core\Normalizers\StringNormalizer;
use Blaspsoft\Blasp\Core\Normalizers\EnglishNormalizer;
use Blaspsoft\Blasp\Core\Normalizers\SpanishNormalizer;
use Blaspsoft\Blasp\Core\Normalizers\GermanNormalizer;
use Blaspsoft\Blasp\Core\Normalizers\FrenchNormalizer;
use Illuminate\Support\Facades\Cache;
class Dictionary
{
private const CACHE_TTL = 86400;
private array $profanities;
private array $falsePositives;
private array $separators;
private array $substitutions;
private array $severityMap;
private array $profanityExpressions;
private StringNormalizer $normalizer;
private array $allowList;
private array $blockList;
private string $language;
private static array $normalizers = [];
public function __construct(
array $profanities,
array $falsePositives,
array $separators,
array $substitutions,
array $severityMap,
StringNormalizer $normalizer,
array $allowList = [],
array $blockList = [],
string $language = 'english',
?array $profanityExpressions = null,
) {
$this->profanities = $profanities;
$this->falsePositives = $falsePositives;
$this->separators = $separators;
$this->substitutions = $substitutions;
$this->severityMap = $severityMap;
$this->normalizer = $normalizer;
$this->allowList = array_map('strtolower', $allowList);
$this->blockList = array_map('strtolower', $blockList);
$this->language = $language;
// Apply block list — add extra words to profanities
foreach ($this->blockList as $word) {
if (!in_array($word, $this->profanities)) {
$this->profanities[] = $word;
$this->severityMap[$word] = Severity::High;
}
}
// Remove allow-listed words
if (!empty($this->allowList)) {
$this->profanities = array_values(array_filter(
$this->profanities,
fn($p) => !in_array(strtolower($p), $this->allowList)
));
}
if ($profanityExpressions !== null) {
$this->profanityExpressions = $profanityExpressions;
} else {
$this->profanityExpressions = (new RegexMatcher())->generateExpressions(
$this->profanities,
$this->separators,
$this->substitutions
);
}
}
public static function forLanguage(string $language, array $options = []): self
{
if (!preg_match('/^[a-zA-Z0-9_-]+$/', $language)) {
return new self(
profanities: [],
falsePositives: [],
separators: [],
substitutions: [],
severityMap: [],
normalizer: new EnglishNormalizer(),
language: $language,
);
}
$config = self::loadLanguageConfig($language);
$globalConfig = self::loadGlobalConfig();
$profanities = $config['profanities'] ?? [];
$falsePositives = $config['false_positives'] ?? [];
$severityMap = self::buildSeverityMap($config);
$substitutions = $globalConfig['substitutions'] ?? [];
if (isset($config['substitutions']) && is_array($config['substitutions'])) {
foreach ($config['substitutions'] as $pattern => $values) {
if (is_array($values)) {
$substitutions[$pattern] = array_values(array_unique(array_merge(
$substitutions[$pattern] ?? [],
$values
)));
}
}
}
return new self(
profanities: $profanities,
falsePositives: $falsePositives,
separators: $globalConfig['separators'] ?? [],
substitutions: $substitutions,
severityMap: $severityMap,
normalizer: self::getNormalizerForLanguage($language),
allowList: $options['allow'] ?? [],
blockList: $options['block'] ?? [],
language: $language,
);
}
public static function forLanguages(array $languages, array $options = []): self
{
$allProfanities = [];
$allFalsePositives = [];
$allSeverityMap = [];
$globalConfig = self::loadGlobalConfig();
$substitutions = $globalConfig['substitutions'] ?? [];
foreach ($languages as $language) {
if (!preg_match('/^[a-zA-Z0-9_-]+$/', $language)) {
continue;
}
$config = self::loadLanguageConfig($language);
$allProfanities = array_merge($allProfanities, $config['profanities'] ?? []);
$allFalsePositives = array_merge($allFalsePositives, $config['false_positives'] ?? []);
$allSeverityMap = array_merge($allSeverityMap, self::buildSeverityMap($config));
// Merge accent/diacritic substitutions only
if (isset($config['substitutions']) && is_array($config['substitutions'])) {
foreach ($config['substitutions'] as $pattern => $values) {
if (is_array($values)) {
$plainKey = trim($pattern, '/');
if (mb_strlen($plainKey, 'UTF-8') > 1 || preg_match('/^[a-zA-Z]$/', $plainKey)) {
continue;
}
$substitutions[$pattern] = array_values(array_unique(array_merge(
$substitutions[$pattern] ?? [],
$values
)));
}
}
}
}
return new self(
profanities: array_values(array_unique($allProfanities)),
falsePositives: array_values(array_unique($allFalsePositives)),
separators: $globalConfig['separators'] ?? [],
substitutions: $substitutions,
severityMap: $allSeverityMap,
normalizer: self::getNormalizerForLanguage('english'),
allowList: $options['allow'] ?? [],
blockList: $options['block'] ?? [],
language: implode(',', $languages),
);
}
public static function forAllLanguages(array $options = []): self
{
$languages = self::getAvailableLanguages();
return self::forLanguages($languages, $options);
}
public function getProfanities(): array
{
return $this->profanities;
}
public function getFalsePositives(): array
{
return $this->falsePositives;
}
public function getProfanityExpressions(): array
{
return $this->profanityExpressions;
}
public function getSeverity(string $word): Severity
{
$lower = strtolower($word);
return $this->severityMap[$lower] ?? Severity::High;
}
public function getNormalizer(): StringNormalizer
{
return $this->normalizer;
}
public function getLanguage(): string
{
return $this->language;
}
public function getSeparators(): array
{
return $this->separators;
}
public function getSubstitutions(): array
{
return $this->substitutions;
}
// --- Static helpers ---
public static function getAvailableLanguages(): array
{
$possiblePaths = [
config_path('languages'),
__DIR__ . '/../../config/languages',
realpath(__DIR__ . '/../../config/languages'),
];
$languagesPath = null;
foreach ($possiblePaths as $path) {
if ($path && is_dir($path)) {
$languagesPath = $path;
break;
}
}
if (!$languagesPath) {
return ['english'];
}
$languageFiles = glob($languagesPath . '/*.php');
$languages = [];
foreach ($languageFiles as $languageFile) {
$languages[] = basename($languageFile, '.php');
}
return empty($languages) ? ['english'] : $languages;
}
public static function loadLanguageConfig(string $language): array
{
if (!preg_match('/^[a-zA-Z0-9_-]+$/', $language)) {
return ['profanities' => [], 'false_positives' => []];
}
$possiblePaths = [
config_path("languages/{$language}.php"),
__DIR__ . "/../../config/languages/{$language}.php",
realpath(__DIR__ . "/../../config/languages/{$language}.php"),
];
$languageFile = null;
foreach ($possiblePaths as $path) {
if ($path && file_exists($path)) {
$languageFile = $path;
break;
}
}
if (!$languageFile) {
return ['profanities' => [], 'false_positives' => []];
}
$config = require $languageFile;
if (!is_array($config) || !isset($config['profanities'])) {
return ['profanities' => [], 'false_positives' => []];
}
return $config;
}
private static function loadGlobalConfig(): array
{
return [
'separators' => config('blasp.separators', config('blasp.drivers.regex.separators', [])),
'substitutions' => config('blasp.substitutions', config('blasp.drivers.regex.substitutions', [])),
'false_positives' => config('blasp.false_positives', []),
];
}
private static function buildSeverityMap(array $config): array
{
$map = [];
if (isset($config['severity']) && is_array($config['severity'])) {
foreach ($config['severity'] as $level => $words) {
$severity = Severity::tryFrom($level) ?? Severity::High;
foreach ($words as $word) {
$map[strtolower($word)] = $severity;
}
}
}
// Words only in profanities (not in severity map) default to High
if (isset($config['profanities'])) {
foreach ($config['profanities'] as $word) {
$lower = strtolower($word);
if (!isset($map[$lower])) {
$map[$lower] = Severity::High;
}
}
}
return $map;
}
public static function getNormalizerForLanguage(string $language): StringNormalizer
{
if (!isset(self::$normalizers[$language])) {
self::$normalizers[$language] = match (strtolower($language)) {
'english' => new EnglishNormalizer(),
'spanish' => new SpanishNormalizer(),
'german' => new GermanNormalizer(),
'french' => new FrenchNormalizer(),
default => new EnglishNormalizer(),
};
}
return self::$normalizers[$language];
}
// --- Caching ---
public static function clearCache(): void
{
$cache = self::getCache();
$keys = $cache->get('blasp_cache_keys', []);
foreach ($keys as $key) {
$cache->forget($key);
}
$cache->forget('blasp_cache_keys');
// Also clear result cache keys
$resultKeys = $cache->get('blasp_result_cache_keys', []);
foreach ($resultKeys as $key) {
$cache->forget($key);
}
$cache->forget('blasp_result_cache_keys');
}
private static function getCache(): \Illuminate\Contracts\Cache\Repository
{
$driver = config('blasp.cache.driver', config('blasp.cache_driver'));
return $driver !== null ? Cache::store($driver) : Cache::store();
}
}
================================================
FILE: src/Core/Masking/CallbackMask.php
================================================
<?php
namespace Blaspsoft\Blasp\Core\Masking;
use Closure;
use Blaspsoft\Blasp\Core\Contracts\MaskStrategyInterface;
class CallbackMask implements MaskStrategyInterface
{
public function __construct(
private Closure $callback
) {}
public function mask(string $word, int $length): string
{
return ($this->callback)($word, $length);
}
}
================================================
FILE: src/Core/Masking/CharacterMask.php
================================================
<?php
namespace Blaspsoft\Blasp\Core\Masking;
use Blaspsoft\Blasp\Core\Contracts\MaskStrategyInterface;
class CharacterMask implements MaskStrategyInterface
{
public function __construct(
private string $character = '*'
) {
$this->character = mb_substr($character, 0, 1);
}
public function mask(string $word, int $length): string
{
return str_repeat($this->character, $length);
}
}
================================================
FILE: src/Core/Masking/GrawlixMask.php
================================================
<?php
namespace Blaspsoft\Blasp\Core\Masking;
use Blaspsoft\Blasp\Core\Contracts\MaskStrategyInterface;
class GrawlixMask implements MaskStrategyInterface
{
private const CHARS = ['!', '@', '#', '$', '%'];
public function mask(string $word, int $length): string
{
$result = '';
for ($i = 0; $i < $length; $i++) {
$result .= self::CHARS[$i % count(self::CHARS)];
}
return $result;
}
}
================================================
FILE: src/Core/MatchedWord.php
================================================
<?php
namespace Blaspsoft\Blasp\Core;
use Blaspsoft\Blasp\Enums\Severity;
use JsonSerializable;
readonly class MatchedWord implements JsonSerializable
{
public function
gitextract_qpmp_x7w/
├── .github/
│ └── workflows/
│ └── main.yml
├── .gitignore
├── .styleci.yml
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE.md
├── README.md
├── composer.json
├── config/
│ ├── blasp.php
│ └── languages/
│ ├── english.php
│ ├── french.php
│ ├── german.php
│ └── spanish.php
├── phpunit.xml
├── src/
│ ├── BlaspManager.php
│ ├── BlaspServiceProvider.php
│ ├── Blaspable.php
│ ├── Console/
│ │ ├── ClearCommand.php
│ │ ├── LanguagesCommand.php
│ │ └── TestCommand.php
│ ├── Core/
│ │ ├── Analyzer.php
│ │ ├── Contracts/
│ │ │ ├── DriverInterface.php
│ │ │ └── MaskStrategyInterface.php
│ │ ├── Dictionary.php
│ │ ├── Masking/
│ │ │ ├── CallbackMask.php
│ │ │ ├── CharacterMask.php
│ │ │ └── GrawlixMask.php
│ │ ├── MatchedWord.php
│ │ ├── Matchers/
│ │ │ ├── CompoundWordDetector.php
│ │ │ ├── FalsePositiveFilter.php
│ │ │ ├── PhoneticMatcher.php
│ │ │ └── RegexMatcher.php
│ │ ├── Normalizers/
│ │ │ ├── EnglishNormalizer.php
│ │ │ ├── FrenchNormalizer.php
│ │ │ ├── GermanNormalizer.php
│ │ │ ├── NullNormalizer.php
│ │ │ ├── SpanishNormalizer.php
│ │ │ └── StringNormalizer.php
│ │ ├── Result.php
│ │ └── Score.php
│ ├── Drivers/
│ │ ├── PatternDriver.php
│ │ ├── PhoneticDriver.php
│ │ ├── PipelineDriver.php
│ │ └── RegexDriver.php
│ ├── Enums/
│ │ └── Severity.php
│ ├── Events/
│ │ ├── ContentBlocked.php
│ │ ├── ModelProfanityDetected.php
│ │ └── ProfanityDetected.php
│ ├── Exceptions/
│ │ └── ProfanityRejectedException.php
│ ├── Facades/
│ │ └── Blasp.php
│ ├── Middleware/
│ │ └── CheckProfanity.php
│ ├── PendingCheck.php
│ ├── Rules/
│ │ └── Profanity.php
│ └── Testing/
│ └── BlaspFake.php
└── tests/
├── AllLanguagesApiTest.php
├── AllLanguagesDetectionTest.php
├── BladeDirectiveTest.php
├── BlaspCheckTest.php
├── BlaspCheckValidationTest.php
├── BlaspableTest.php
├── BypassVulnerabilityTest.php
├── CacheDriverConfigurationTest.php
├── ConfigurationLoaderLanguageTest.php
├── ConfigurationLoaderTest.php
├── CustomMaskCharacterTest.php
├── DetectionStrategyRegistryTest.php
├── EdgeCaseTest.php
├── EmptyInputTest.php
├── FrenchStringNormalizerTest.php
├── GermanStringNormalizerTest.php
├── Issue24Test.php
├── Issue32FalsePositiveTest.php
├── MiddlewareAliasTest.php
├── MultiLanguageDetectionConfigTest.php
├── MultiLanguageProfanityTest.php
├── PhoneticDriverTest.php
├── PipelineDriverTest.php
├── ProfanityExpressionGeneratorTest.php
├── ResultCachingTest.php
├── SeverityMapTest.php
├── SpanishStringNormalizerTest.php
├── StrMacroTest.php
├── TestCase.php
└── UuidFalsePositiveTest.php
SYMBOL INDEX (551 symbols across 70 files)
FILE: src/BlaspManager.php
class BlaspManager (line 14) | class BlaspManager
method __construct (line 20) | public function __construct(Application $app)
method driver (line 25) | public function driver(?string $driver = null): PendingCheck
method resolveDriver (line 30) | public function resolveDriver(string $name): DriverInterface
method createDriver (line 39) | protected function createDriver(string $name): DriverInterface
method createRegexDriver (line 53) | public function createRegexDriver(): DriverInterface
method createPatternDriver (line 58) | public function createPatternDriver(): DriverInterface
method createPhoneticDriver (line 63) | public function createPhoneticDriver(): DriverInterface
method createPipelineDriver (line 76) | public function createPipelineDriver(): DriverInterface
method extend (line 103) | public function extend(string $driver, Closure $callback): self
method getDefaultDriver (line 109) | public function getDefaultDriver(): string
method newPendingCheck (line 114) | public function newPendingCheck(): PendingCheck
method pipeline (line 119) | public function pipeline(string ...$drivers): PendingCheck
method check (line 126) | public function check(?string $text): \Blaspsoft\Blasp\Core\Result
method checkMany (line 131) | public function checkMany(array $texts): array
method __call (line 136) | public function __call(string $method, array $parameters): mixed
method getApp (line 141) | public function getApp(): Application
FILE: src/BlaspServiceProvider.php
class BlaspServiceProvider (line 9) | class BlaspServiceProvider extends ServiceProvider
method boot (line 11) | public function boot(): void
method register (line 40) | public function register(): void
method registerValidationRule (line 51) | protected function registerValidationRule(): void
method registerMiddlewareAlias (line 68) | protected function registerMiddlewareAlias(): void
method registerBladeDirectives (line 73) | protected function registerBladeDirectives(): void
method registerStringMacros (line 80) | protected function registerStringMacros(): void
FILE: src/Blaspable.php
type Blaspable (line 19) | trait Blaspable
method bootBlaspable (line 26) | public static function bootBlaspable(): void
method hadProfanity (line 71) | public function hadProfanity(): bool
method blaspResults (line 83) | public function blaspResults(): array
method blaspResult (line 88) | public function blaspResult(string $attribute): ?Result
method withoutBlaspChecking (line 93) | public static function withoutBlaspChecking(Closure $callback): mixed
FILE: src/Console/ClearCommand.php
class ClearCommand (line 8) | class ClearCommand extends Command
method handle (line 13) | public function handle(): void
FILE: src/Console/LanguagesCommand.php
class LanguagesCommand (line 8) | class LanguagesCommand extends Command
method handle (line 13) | public function handle(): void
FILE: src/Console/TestCommand.php
class TestCommand (line 7) | class TestCommand extends Command
method handle (line 12) | public function handle(): void
FILE: src/Core/Analyzer.php
class Analyzer (line 9) | class Analyzer
method analyze (line 11) | public function analyze(
FILE: src/Core/Contracts/DriverInterface.php
type DriverInterface (line 8) | interface DriverInterface
method detect (line 10) | public function detect(string $text, Dictionary $dictionary, MaskStrat...
FILE: src/Core/Contracts/MaskStrategyInterface.php
type MaskStrategyInterface (line 5) | interface MaskStrategyInterface
method mask (line 7) | public function mask(string $word, int $length): string;
FILE: src/Core/Dictionary.php
class Dictionary (line 14) | class Dictionary
method __construct (line 31) | public function __construct(
method forLanguage (line 80) | public static function forLanguage(string $language, array $options = ...
method forLanguages (line 126) | public static function forLanguages(array $languages, array $options =...
method forAllLanguages (line 173) | public static function forAllLanguages(array $options = []): self
method getProfanities (line 179) | public function getProfanities(): array
method getFalsePositives (line 184) | public function getFalsePositives(): array
method getProfanityExpressions (line 189) | public function getProfanityExpressions(): array
method getSeverity (line 194) | public function getSeverity(string $word): Severity
method getNormalizer (line 200) | public function getNormalizer(): StringNormalizer
method getLanguage (line 205) | public function getLanguage(): string
method getSeparators (line 210) | public function getSeparators(): array
method getSubstitutions (line 215) | public function getSubstitutions(): array
method getAvailableLanguages (line 222) | public static function getAvailableLanguages(): array
method loadLanguageConfig (line 252) | public static function loadLanguageConfig(string $language): array
method loadGlobalConfig (line 285) | private static function loadGlobalConfig(): array
method buildSeverityMap (line 294) | private static function buildSeverityMap(array $config): array
method getNormalizerForLanguage (line 320) | public static function getNormalizerForLanguage(string $language): Str...
method clearCache (line 337) | public static function clearCache(): void
method getCache (line 358) | private static function getCache(): \Illuminate\Contracts\Cache\Reposi...
FILE: src/Core/Masking/CallbackMask.php
class CallbackMask (line 8) | class CallbackMask implements MaskStrategyInterface
method __construct (line 10) | public function __construct(
method mask (line 14) | public function mask(string $word, int $length): string
FILE: src/Core/Masking/CharacterMask.php
class CharacterMask (line 7) | class CharacterMask implements MaskStrategyInterface
method __construct (line 9) | public function __construct(
method mask (line 15) | public function mask(string $word, int $length): string
FILE: src/Core/Masking/GrawlixMask.php
class GrawlixMask (line 7) | class GrawlixMask implements MaskStrategyInterface
method mask (line 11) | public function mask(string $word, int $length): string
FILE: src/Core/MatchedWord.php
class MatchedWord (line 8) | readonly class MatchedWord implements JsonSerializable
method __construct (line 10) | public function __construct(
method toArray (line 19) | public function toArray(): array
method jsonSerialize (line 31) | public function jsonSerialize(): mixed
FILE: src/Core/Matchers/CompoundWordDetector.php
class CompoundWordDetector (line 5) | class CompoundWordDetector
method isPureAlphaSubstring (line 9) | public function isPureAlphaSubstring(string $matchedText, string $full...
FILE: src/Core/Matchers/FalsePositiveFilter.php
class FalsePositiveFilter (line 5) | class FalsePositiveFilter
method __construct (line 9) | public function __construct(array $falsePositives)
method isFalsePositive (line 14) | public function isFalsePositive(string $word): bool
method isInsideHexToken (line 19) | public function isInsideHexToken(string $string, int $start, int $leng...
method isSpanningWordBoundary (line 49) | public function isSpanningWordBoundary(string $matchedText, string $fu...
method getFullWordContext (line 125) | public function getFullWordContext(string $string, int $start, int $le...
FILE: src/Core/Matchers/PhoneticMatcher.php
class PhoneticMatcher (line 5) | class PhoneticMatcher
method __construct (line 10) | public function __construct(
method buildIndex (line 21) | private function buildIndex(array $profanities): void
method match (line 43) | public function match(string $word): ?string
FILE: src/Core/Matchers/RegexMatcher.php
class RegexMatcher (line 5) | class RegexMatcher
method generateExpressions (line 10) | public function generateExpressions(array $profanities, array $separat...
method generateSeparatorExpression (line 28) | public function generateSeparatorExpression(array $separators): string
method generateSubstitutionExpressions (line 37) | public function generateSubstitutionExpressions(array $substitutions):...
method generateProfanityExpression (line 66) | public function generateProfanityExpression(string $profanity, array $...
method generateEscapedExpression (line 103) | private function generateEscapedExpression(array $characters = [], arr...
FILE: src/Core/Normalizers/EnglishNormalizer.php
class EnglishNormalizer (line 5) | class EnglishNormalizer implements StringNormalizer
method normalize (line 7) | public function normalize(string $string): string
FILE: src/Core/Normalizers/FrenchNormalizer.php
class FrenchNormalizer (line 5) | class FrenchNormalizer implements StringNormalizer
method normalize (line 7) | public function normalize(string $string): string
FILE: src/Core/Normalizers/GermanNormalizer.php
class GermanNormalizer (line 5) | class GermanNormalizer implements StringNormalizer
method normalize (line 7) | public function normalize(string $string): string
FILE: src/Core/Normalizers/NullNormalizer.php
class NullNormalizer (line 5) | class NullNormalizer implements StringNormalizer
method normalize (line 7) | public function normalize(string $string): string
FILE: src/Core/Normalizers/SpanishNormalizer.php
class SpanishNormalizer (line 5) | class SpanishNormalizer implements StringNormalizer
method normalize (line 7) | public function normalize(string $string): string
FILE: src/Core/Normalizers/StringNormalizer.php
type StringNormalizer (line 5) | interface StringNormalizer
method normalize (line 7) | public function normalize(string $string): string;
FILE: src/Core/Result.php
class Result (line 11) | class Result implements JsonSerializable, Stringable, Countable
method __construct (line 15) | public function __construct(
method isClean (line 26) | public function isClean(): bool
method isOffensive (line 31) | public function isOffensive(): bool
method clean (line 36) | public function clean(): string
method original (line 41) | public function original(): string
method score (line 46) | public function score(): int
method count (line 51) | public function count(): int
method uniqueWords (line 56) | public function uniqueWords(): array
method severity (line 61) | public function severity(): ?Severity
method words (line 73) | public function words(): Collection
method hasProfanity (line 81) | public function hasProfanity(): bool
method getCleanString (line 87) | public function getCleanString(): string
method getSourceString (line 93) | public function getSourceString(): string
method getProfanitiesCount (line 99) | public function getProfanitiesCount(): int
method getUniqueProfanitiesFound (line 105) | public function getUniqueProfanitiesFound(): array
method none (line 112) | public static function none(string $text): self
method fromArray (line 117) | public static function fromArray(array $data): self
method withMatches (line 139) | public static function withMatches(array $words, string $originalText ...
method toArray (line 164) | public function toArray(): array
method toJson (line 178) | public function toJson(int $options = 0): string
method jsonSerialize (line 183) | public function jsonSerialize(): mixed
method __toString (line 188) | public function __toString(): string
FILE: src/Core/Score.php
class Score (line 5) | class Score
method calculate (line 7) | public static function calculate(array $matchedWords, int $totalWordCo...
FILE: src/Drivers/PatternDriver.php
class PatternDriver (line 13) | class PatternDriver implements DriverInterface
method detect (line 15) | public function detect(string $text, Dictionary $dictionary, MaskStrat...
FILE: src/Drivers/PhoneticDriver.php
class PhoneticDriver (line 15) | class PhoneticDriver implements DriverInterface
method __construct (line 17) | public function __construct(
method detect (line 25) | public function detect(string $text, Dictionary $dictionary, MaskStrat...
FILE: src/Drivers/PipelineDriver.php
class PipelineDriver (line 12) | class PipelineDriver implements DriverInterface
method __construct (line 15) | public function __construct(private array $drivers) {}
method detect (line 17) | public function detect(string $text, Dictionary $dictionary, MaskStrat...
FILE: src/Drivers/RegexDriver.php
class RegexDriver (line 15) | class RegexDriver implements DriverInterface
method detect (line 20) | public function detect(string $text, Dictionary $dictionary, MaskStrat...
FILE: src/Enums/Severity.php
method weight (line 12) | public function weight(): int
method isAtLeast (line 22) | public function isAtLeast(self $minimum): bool
FILE: src/Events/ContentBlocked.php
class ContentBlocked (line 8) | class ContentBlocked
method __construct (line 10) | public function __construct(
FILE: src/Events/ModelProfanityDetected.php
class ModelProfanityDetected (line 8) | class ModelProfanityDetected
method __construct (line 10) | public function __construct(
FILE: src/Events/ProfanityDetected.php
class ProfanityDetected (line 7) | class ProfanityDetected
method __construct (line 9) | public function __construct(
FILE: src/Exceptions/ProfanityRejectedException.php
class ProfanityRejectedException (line 9) | class ProfanityRejectedException extends RuntimeException
method __construct (line 11) | public function __construct(
method forModel (line 19) | public static function forModel(Model $model, string $attribute, Resul...
FILE: src/Facades/Blasp.php
class Blasp (line 38) | class Blasp extends BaseFacade
method getFacadeAccessor (line 40) | protected static function getFacadeAccessor(): string
method fake (line 45) | public static function fake(array $responses = []): BlaspFake
method withoutFiltering (line 52) | public static function withoutFiltering(Closure $callback): mixed
method assertChecked (line 64) | public static function assertChecked(): void
method assertCheckedTimes (line 73) | public static function assertCheckedTimes(int $times): void
FILE: src/Middleware/CheckProfanity.php
class CheckProfanity (line 12) | class CheckProfanity
method __construct (line 14) | public function __construct(
method handle (line 18) | public function handle(Request $request, Closure $next, ?string $actio...
method extractTextFields (line 63) | protected function extractTextFields(array $input): array
FILE: src/PendingCheck.php
class PendingCheck (line 18) | class PendingCheck
method __construct (line 32) | public function __construct(BlaspManager $manager)
method driver (line 39) | public function driver(string $driver): self
method in (line 45) | public function in(string ...$languages): self
method inAllLanguages (line 51) | public function inAllLanguages(): self
method mask (line 57) | public function mask(string|Closure $mask): self
method allow (line 69) | public function allow(string ...$words): self
method block (line 75) | public function block(string ...$words): self
method withSeverity (line 81) | public function withSeverity(Severity $severity): self
method strict (line 87) | public function strict(): self
method lenient (line 94) | public function lenient(): self
method pipeline (line 101) | public function pipeline(string ...$drivers): self
method maskWith (line 110) | public function maskWith(string $character): self
method allLanguages (line 116) | public function allLanguages(): self
method language (line 122) | public function language(string $language): self
method english (line 129) | public function english(): self
method spanish (line 134) | public function spanish(): self
method german (line 139) | public function german(): self
method french (line 144) | public function french(): self
method configure (line 151) | public function configure(?array $profanities = null, ?array $falsePos...
method check (line 161) | public function check(?string $text): Result
method performCheck (line 186) | protected function performCheck(string $text): Result
method checkMany (line 208) | public function checkMany(array $texts): array
method buildDictionary (line 219) | protected function buildDictionary(): Dictionary
method resolveDriver (line 241) | protected function resolveDriver(): \Blaspsoft\Blasp\Core\Contracts\Dr...
method resolveMask (line 261) | protected function resolveMask(): MaskStrategyInterface
method shouldCache (line 273) | protected function shouldCache(): bool
method buildCacheKey (line 290) | protected function buildCacheKey(string $text): string
method getCache (line 309) | protected function getCache(): \Illuminate\Contracts\Cache\Repository
method trackCacheKey (line 316) | protected function trackCacheKey(string $key): void
FILE: src/Rules/Profanity.php
class Profanity (line 9) | class Profanity implements ValidationRule
method make (line 15) | public static function make(): self
method in (line 20) | public function in(string $language): self
method maxScore (line 26) | public function maxScore(int $score): self
method severity (line 32) | public function severity(Severity $severity): self
method __callStatic (line 38) | public static function __callStatic(string $name, array $arguments): self
method validate (line 43) | public function validate(string $attribute, mixed $value, Closure $fai...
FILE: src/Testing/BlaspFake.php
class BlaspFake (line 9) | class BlaspFake
method __construct (line 14) | public function __construct(array $fakeResults = [])
method check (line 19) | public function check(?string $text): Result
method checkMany (line 31) | public function checkMany(array $texts): array
method assertChecked (line 40) | public function assertChecked(): void
method assertCheckedTimes (line 45) | public function assertCheckedTimes(int $times): void
method assertCheckedWith (line 54) | public function assertCheckedWith(string $text): void
method __call (line 60) | public function __call(string $method, array $parameters): self
method in (line 65) | public function in(string ...$languages): self
method inAllLanguages (line 70) | public function inAllLanguages(): self
method allLanguages (line 75) | public function allLanguages(): self
method english (line 80) | public function english(): self
method spanish (line 85) | public function spanish(): self
method german (line 90) | public function german(): self
method french (line 95) | public function french(): self
method mask (line 100) | public function mask(string $mask): self
method maskWith (line 105) | public function maskWith(string $character): self
method language (line 110) | public function language(string $language): self
method driver (line 115) | public function driver(string $driver): self
method configure (line 120) | public function configure(?array $profanities = null, ?array $falsePos...
FILE: tests/AllLanguagesApiTest.php
class AllLanguagesApiTest (line 7) | class AllLanguagesApiTest extends TestCase
method test_all_languages_detection (line 9) | public function test_all_languages_detection()
method test_mixed_language_content (line 28) | public function test_mixed_language_content()
method test_chainable_all_languages (line 36) | public function test_chainable_all_languages()
method test_language_shortcuts_vs_all (line 42) | public function test_language_shortcuts_vs_all()
method test_direct_manager_all_languages (line 58) | public function test_direct_manager_all_languages()
method test_configure_with_all_languages (line 66) | public function test_configure_with_all_languages()
FILE: tests/AllLanguagesDetectionTest.php
class AllLanguagesDetectionTest (line 7) | class AllLanguagesDetectionTest extends TestCase
method test_all_languages_profanity_detection (line 9) | public function test_all_languages_profanity_detection()
method test_language_variations (line 64) | public function test_language_variations()
method test_language_normalizers (line 100) | public function test_language_normalizers()
FILE: tests/BladeDirectiveTest.php
class BladeDirectiveTest (line 7) | class BladeDirectiveTest extends TestCase
method renderBlade (line 9) | protected function renderBlade(string $template, array $data = []): st...
method test_clean_directive_masks_profane_text (line 19) | public function test_clean_directive_masks_profane_text()
method test_clean_directive_passes_clean_text_unchanged (line 27) | public function test_clean_directive_passes_clean_text_unchanged()
method test_clean_directive_escapes_html_for_xss_safety (line 34) | public function test_clean_directive_escapes_html_for_xss_safety()
FILE: tests/BlaspCheckTest.php
class BlaspCheckTest (line 7) | class BlaspCheckTest extends TestCase
method test_real_blasp_service (line 9) | public function test_real_blasp_service()
method test_straight_match (line 15) | public function test_straight_match()
method test_substitution_match (line 25) | public function test_substitution_match()
method test_obscured_match (line 35) | public function test_obscured_match()
method test_doubled_match (line 45) | public function test_doubled_match()
method test_combination_match (line 55) | public function test_combination_match()
method test_multiple_profanities_no_spaces (line 65) | public function test_multiple_profanities_no_spaces()
method test_multiple_profanities (line 75) | public function test_multiple_profanities()
method test_scunthorpe_problem (line 84) | public function test_scunthorpe_problem()
method test_penistone_problem (line 94) | public function test_penistone_problem()
method test_false_positives (line 104) | public function test_false_positives()
method test_cuntfuck_fuckcunt (line 122) | public function test_cuntfuck_fuckcunt()
method test_fucking_shit_cunt_fuck (line 131) | public function test_fucking_shit_cunt_fuck()
method test_billy_butcher (line 140) | public function test_billy_butcher()
method test_paragraph (line 149) | public function test_paragraph()
method test_word_boudary (line 163) | public function test_word_boudary()
method test_pural_profanity (line 175) | public function test_pural_profanity()
method test_this_musicals_hit (line 184) | public function test_this_musicals_hit()
method test_ass_subtitution (line 193) | public function test_ass_subtitution()
method test_embedded_profanities (line 202) | public function test_embedded_profanities()
method test_multiple_profanities_with_spaces (line 211) | public function test_multiple_profanities_with_spaces()
method test_spaced_profanity_with_substitution (line 220) | public function test_spaced_profanity_with_substitution()
method test_spaced_profanity_without_substitution (line 227) | public function test_spaced_profanity_without_substitution()
method test_partial_spacing_s_hit (line 233) | public function test_partial_spacing_s_hit()
method test_partial_spacing_f_uck (line 240) | public function test_partial_spacing_f_uck()
method test_partial_spacing_t_wat (line 247) | public function test_partial_spacing_t_wat()
method test_partial_spacing_fu_c_k (line 254) | public function test_partial_spacing_fu_c_k()
method test_partial_spacing_tw_a_t (line 261) | public function test_partial_spacing_tw_a_t()
method test_no_false_positive_musicals_hit_embedded (line 268) | public function test_no_false_positive_musicals_hit_embedded()
method test_no_false_positive_an_alert (line 275) | public function test_no_false_positive_an_alert()
method test_no_false_positive_has_5_faces (line 282) | public function test_no_false_positive_has_5_faces()
method test_detects_at_ss_obfuscation (line 289) | public function test_detects_at_ss_obfuscation()
method test_no_false_positive_space_words (line 295) | public function test_no_false_positive_space_words()
FILE: tests/BlaspCheckValidationTest.php
class BlaspCheckValidationTest (line 6) | class BlaspCheckValidationTest extends TestCase
method test_blasp_check_validation_passes_with_clean_text (line 13) | public function test_blasp_check_validation_passes_with_clean_text()
method test_blasp_check_validation_fails_with_profanity (line 29) | public function test_blasp_check_validation_fails_with_profanity()
FILE: tests/BlaspableTest.php
class BlaspableTestModel (line 14) | class BlaspableTestModel extends Model
class BlaspableRejectModel (line 25) | class BlaspableRejectModel extends Model
class BlaspableSpanishModel (line 37) | class BlaspableSpanishModel extends Model
class BlaspableCustomMaskModel (line 49) | class BlaspableCustomMaskModel extends Model
class BlaspableTest (line 61) | class BlaspableTest extends TestCase
method setUp (line 63) | protected function setUp(): void
method tearDown (line 75) | protected function tearDown(): void
method test_sanitize_mode_masks_profanity_on_save (line 81) | public function test_sanitize_mode_masks_profanity_on_save()
method test_reject_mode_throws_exception (line 94) | public function test_reject_mode_throws_exception()
method test_reject_mode_does_not_persist_model (line 105) | public function test_reject_mode_does_not_persist_model()
method test_clean_text_passes_through_untouched (line 118) | public function test_clean_text_passes_through_untouched()
method test_only_dirty_attributes_are_checked (line 129) | public function test_only_dirty_attributes_are_checked()
method test_non_blaspable_attributes_are_ignored (line 144) | public function test_non_blaspable_attributes_are_ignored()
method test_per_model_language_override (line 154) | public function test_per_model_language_override()
method test_per_model_mask_override (line 164) | public function test_per_model_mask_override()
method test_had_profanity_returns_true_when_profanity_detected (line 175) | public function test_had_profanity_returns_true_when_profanity_detected()
method test_had_profanity_returns_false_for_clean_text (line 184) | public function test_had_profanity_returns_false_for_clean_text()
method test_blasp_results_returns_results_array (line 193) | public function test_blasp_results_returns_results_array()
method test_blasp_result_returns_single_attribute_result (line 209) | public function test_blasp_result_returns_single_attribute_result()
method test_blasp_result_returns_null_for_unknown_attribute (line 221) | public function test_blasp_result_returns_null_for_unknown_attribute()
method test_without_blasp_checking_disables_profanity_check (line 230) | public function test_without_blasp_checking_disables_profanity_check()
method test_model_profanity_detected_event_fires_in_sanitize_mode (line 242) | public function test_model_profanity_detected_event_fires_in_sanitize_...
method test_model_profanity_detected_event_fires_in_reject_mode (line 257) | public function test_model_profanity_detected_event_fires_in_reject_mo...
method test_event_not_fired_for_clean_text (line 274) | public function test_event_not_fired_for_clean_text()
method test_update_triggers_sanitization (line 285) | public function test_update_triggers_sanitization()
method test_multiple_profane_attributes_are_sanitized (line 298) | public function test_multiple_profane_attributes_are_sanitized()
method test_null_attributes_are_skipped (line 310) | public function test_null_attributes_are_skipped()
method test_profanity_rejected_exception_contains_model_and_attribute (line 321) | public function test_profanity_rejected_exception_contains_model_and_a...
FILE: tests/BypassVulnerabilityTest.php
class BypassVulnerabilityTest (line 7) | class BypassVulnerabilityTest extends TestCase
method test_invisible_separator_in_fuck (line 13) | public function test_invisible_separator_in_fuck()
method test_zero_width_space_in_shit (line 20) | public function test_zero_width_space_in_shit()
method test_multiple_invisible_chars_in_profanity (line 27) | public function test_multiple_invisible_chars_in_profanity()
method test_invisible_chars_in_clean_text_no_false_positive (line 34) | public function test_invisible_chars_in_clean_text_no_false_positive()
method test_invisible_separator_clean_output_masks_profanity (line 40) | public function test_invisible_separator_clean_output_masks_profanity()
method test_asterisk_censored_fag (line 51) | public function test_asterisk_censored_fag()
method test_asterisk_censored_fuck (line 58) | public function test_asterisk_censored_fuck()
method test_asterisk_censored_shit (line 64) | public function test_asterisk_censored_shit()
method test_asterisk_fully_censored_fuck (line 70) | public function test_asterisk_fully_censored_fuck()
method test_asterisk_in_non_profane_word_no_false_positive (line 76) | public function test_asterisk_in_non_profane_word_no_false_positive()
method test_invisible_char_plus_asterisk_censoring (line 86) | public function test_invisible_char_plus_asterisk_censoring()
FILE: tests/CacheDriverConfigurationTest.php
class CacheDriverConfigurationTest (line 9) | class CacheDriverConfigurationTest extends TestCase
method setUp (line 11) | public function setUp(): void
method test_dictionary_can_be_created_without_cache (line 18) | public function test_dictionary_can_be_created_without_cache(): void
method test_clear_cache_works (line 28) | public function test_clear_cache_works(): void
method test_dictionary_loads_consistently (line 34) | public function test_dictionary_loads_consistently(): void
method test_different_languages_have_different_profanities (line 43) | public function test_different_languages_have_different_profanities():...
method test_clear_cache_with_custom_driver (line 51) | public function test_clear_cache_with_custom_driver(): void
FILE: tests/ConfigurationLoaderLanguageTest.php
class ConfigurationLoaderLanguageTest (line 11) | class ConfigurationLoaderLanguageTest extends TestCase
method test_get_available_languages (line 13) | public function test_get_available_languages()
method test_load_specific_language_english (line 24) | public function test_load_specific_language_english()
method test_load_specific_language_spanish (line 39) | public function test_load_specific_language_spanish()
method test_load_specific_language_french (line 56) | public function test_load_specific_language_french()
method test_load_specific_language_german (line 74) | public function test_load_specific_language_german()
method test_load_nonexistent_language (line 93) | public function test_load_nonexistent_language()
method test_normalizer_for_languages (line 99) | public function test_normalizer_for_languages()
method test_language_substitutions_are_merged (line 107) | public function test_language_substitutions_are_merged()
FILE: tests/ConfigurationLoaderTest.php
class ConfigurationLoaderTest (line 8) | class ConfigurationLoaderTest extends TestCase
method setUp (line 10) | public function setUp(): void
method test_for_language_returns_dictionary (line 17) | public function test_for_language_returns_dictionary()
method test_dictionary_has_profanity_expressions (line 26) | public function test_dictionary_has_profanity_expressions()
method test_for_languages_returns_multi_language_dictionary (line 37) | public function test_for_languages_returns_multi_language_dictionary()
method test_for_all_languages_returns_all_language_dictionary (line 46) | public function test_for_all_languages_returns_all_language_dictionary()
method test_allow_list_removes_words (line 57) | public function test_allow_list_removes_words()
method test_block_list_adds_words (line 65) | public function test_block_list_adds_words()
method test_severity_map_is_populated (line 72) | public function test_severity_map_is_populated()
method test_clear_cache (line 80) | public function test_clear_cache()
method test_get_available_languages (line 86) | public function test_get_available_languages()
method test_load_language_config (line 97) | public function test_load_language_config()
method test_load_nonexistent_language_config (line 106) | public function test_load_nonexistent_language_config()
method test_normalizer_is_set (line 114) | public function test_normalizer_is_set()
method test_separators_and_substitutions_loaded (line 121) | public function test_separators_and_substitutions_loaded()
FILE: tests/CustomMaskCharacterTest.php
class CustomMaskCharacterTest (line 7) | class CustomMaskCharacterTest extends TestCase
method test_default_mask_character_is_asterisk (line 9) | public function test_default_mask_character_is_asterisk()
method test_custom_mask_character_with_hash (line 15) | public function test_custom_mask_character_with_hash()
method test_custom_mask_character_with_dash (line 21) | public function test_custom_mask_character_with_dash()
method test_custom_mask_character_with_underscore (line 27) | public function test_custom_mask_character_with_underscore()
method test_custom_mask_character_with_unicode (line 33) | public function test_custom_mask_character_with_unicode()
method test_custom_mask_character_only_uses_first_character (line 39) | public function test_custom_mask_character_only_uses_first_character()
method test_mask_character_can_be_chained_with_language (line 45) | public function test_mask_character_can_be_chained_with_language()
method test_mask_character_works_with_multiple_profanities (line 51) | public function test_mask_character_works_with_multiple_profanities()
method test_mask_character_with_block_list (line 58) | public function test_mask_character_with_block_list()
method test_different_mask_characters_can_be_used_independently (line 64) | public function test_different_mask_characters_can_be_used_independent...
FILE: tests/DetectionStrategyRegistryTest.php
class DetectionStrategyRegistryTest (line 14) | class DetectionStrategyRegistryTest extends TestCase
method setUp (line 18) | public function setUp(): void
method test_default_driver_is_regex (line 24) | public function test_default_driver_is_regex()
method test_resolve_regex_driver (line 29) | public function test_resolve_regex_driver()
method test_resolve_pattern_driver (line 35) | public function test_resolve_pattern_driver()
method test_resolve_unknown_driver_throws_exception (line 41) | public function test_resolve_unknown_driver_throws_exception()
method test_extend_registers_custom_driver (line 47) | public function test_extend_registers_custom_driver()
method test_manager_check_returns_result (line 62) | public function test_manager_check_returns_result()
method test_manager_creates_pending_check (line 69) | public function test_manager_creates_pending_check()
method test_driver_method_returns_pending_check (line 75) | public function test_driver_method_returns_pending_check()
FILE: tests/EdgeCaseTest.php
class EdgeCaseTest (line 7) | class EdgeCaseTest extends TestCase
method test_fuckme_not_detected_across_word_boundaries (line 9) | public function test_fuckme_not_detected_across_word_boundaries()
method test_removed_compound_profanities_not_detected (line 23) | public function test_removed_compound_profanities_not_detected()
method test_legitimate_compound_profanities_still_work (line 34) | public function test_legitimate_compound_profanities_still_work()
FILE: tests/EmptyInputTest.php
class EmptyInputTest (line 7) | class EmptyInputTest extends TestCase
method test_empty_string_returns_no_profanity (line 9) | public function test_empty_string_returns_no_profanity()
method test_empty_string_returns_empty_source_and_clean_strings (line 18) | public function test_empty_string_returns_empty_source_and_clean_strin...
method test_null_returns_no_profanity (line 26) | public function test_null_returns_no_profanity()
method test_profanity_still_detected_after_empty_check (line 35) | public function test_profanity_still_detected_after_empty_check()
FILE: tests/FrenchStringNormalizerTest.php
class FrenchStringNormalizerTest (line 7) | class FrenchStringNormalizerTest extends TestCase
method setUp (line 11) | public function setUp(): void
method test_normalize_accented_vowels (line 17) | public function test_normalize_accented_vowels()
method test_normalize_cedilla (line 26) | public function test_normalize_cedilla()
method test_normalize_ligatures (line 33) | public function test_normalize_ligatures()
method test_normalize_french_profanity_variants (line 40) | public function test_normalize_french_profanity_variants()
method test_normalize_circumflex_accent (line 49) | public function test_normalize_circumflex_accent()
method test_normalize_grave_accent (line 58) | public function test_normalize_grave_accent()
method test_normalize_acute_accent (line 67) | public function test_normalize_acute_accent()
method test_normalize_diaeresis (line 76) | public function test_normalize_diaeresis()
method test_normalize_mixed_case_preservation (line 85) | public function test_normalize_mixed_case_preservation()
method test_normalize_preserves_non_french_characters (line 93) | public function test_normalize_preserves_non_french_characters()
method test_normalize_empty_and_special_strings (line 100) | public function test_normalize_empty_and_special_strings()
method test_normalize_complex_french_text (line 108) | public function test_normalize_complex_french_text()
method test_normalize_all_french_accents (line 115) | public function test_normalize_all_french_accents()
method test_normalize_numbers_and_special_chars (line 145) | public function test_normalize_numbers_and_special_chars()
method test_normalize_french_profanities_from_config (line 152) | public function test_normalize_french_profanities_from_config()
FILE: tests/GermanStringNormalizerTest.php
class GermanStringNormalizerTest (line 7) | class GermanStringNormalizerTest extends TestCase
method setUp (line 11) | public function setUp(): void
method test_normalize_umlauts (line 17) | public function test_normalize_umlauts()
method test_normalize_eszett (line 27) | public function test_normalize_eszett()
method test_normalize_sch_combinations (line 35) | public function test_normalize_sch_combinations()
method test_normalize_german_profanity_variants (line 42) | public function test_normalize_german_profanity_variants()
method test_normalize_preserves_non_german_characters (line 50) | public function test_normalize_preserves_non_german_characters()
method test_normalize_mixed_case_preservation (line 56) | public function test_normalize_mixed_case_preservation()
method test_normalize_empty_and_special_strings (line 63) | public function test_normalize_empty_and_special_strings()
FILE: tests/Issue24Test.php
class Issue24Test (line 7) | class Issue24Test extends TestCase
method test_etre_not_flagged_as_profanity (line 9) | public function test_etre_not_flagged_as_profanity()
method test_are_accent_not_flagged (line 15) | public function test_are_accent_not_flagged()
method test_tete_not_flagged (line 21) | public function test_tete_not_flagged()
method test_actual_profanity_still_detected (line 27) | public function test_actual_profanity_still_detected()
FILE: tests/Issue32FalsePositiveTest.php
class Issue32FalsePositiveTest (line 8) | class Issue32FalsePositiveTest extends TestCase
method test_legitimate_words_not_flagged (line 10) | #[DataProvider('legitimateWordsProvider')]
method legitimateWordsProvider (line 20) | public static function legitimateWordsProvider(): array
method test_actual_profanity_still_detected (line 36) | public function test_actual_profanity_still_detected()
FILE: tests/MiddlewareAliasTest.php
class MiddlewareAliasTest (line 7) | class MiddlewareAliasTest extends TestCase
method test_blasp_alias_resolves_to_check_profanity_middleware (line 9) | public function test_blasp_alias_resolves_to_check_profanity_middleware()
FILE: tests/MultiLanguageDetectionConfigTest.php
class MultiLanguageDetectionConfigTest (line 8) | class MultiLanguageDetectionConfigTest extends TestCase
method test_for_language_sets_language (line 10) | public function test_for_language_sets_language()
method test_for_languages_merges_profanities (line 16) | public function test_for_languages_merges_profanities()
method test_for_all_languages_includes_all (line 25) | public function test_for_all_languages_includes_all()
method test_profanity_expressions_generated (line 36) | public function test_profanity_expressions_generated()
method test_severity_map_populated (line 46) | public function test_severity_map_populated()
method test_false_positives_loaded (line 54) | public function test_false_positives_loaded()
method test_allow_list_removes_profanities (line 64) | public function test_allow_list_removes_profanities()
method test_block_list_adds_profanities (line 71) | public function test_block_list_adds_profanities()
method test_block_list_gets_severity (line 78) | public function test_block_list_gets_severity()
method test_separators_and_substitutions_present (line 86) | public function test_separators_and_substitutions_present()
FILE: tests/MultiLanguageProfanityTest.php
class MultiLanguageProfanityTest (line 8) | class MultiLanguageProfanityTest extends TestCase
method test_english_profanities (line 10) | public function test_english_profanities()
method test_spanish_profanities (line 26) | public function test_spanish_profanities()
method test_german_profanities (line 41) | public function test_german_profanities()
method test_french_profanities (line 57) | public function test_french_profanities()
method test_profanity_variations (line 72) | public function test_profanity_variations()
method test_case_insensitivity (line 90) | public function test_case_insensitivity()
method test_false_positives_not_flagged (line 110) | public function test_false_positives_not_flagged()
method test_comprehensive_language_coverage (line 123) | public function test_comprehensive_language_coverage()
FILE: tests/PhoneticDriverTest.php
class PhoneticDriverTest (line 9) | class PhoneticDriverTest extends TestCase
method setUp (line 11) | protected function setUp(): void
method test_matcher_exact_profanity_match (line 47) | public function test_matcher_exact_profanity_match()
method test_matcher_phonetic_variant_detection (line 55) | public function test_matcher_phonetic_variant_detection()
method test_matcher_short_word_skipping (line 64) | public function test_matcher_short_word_skipping()
method test_matcher_phonetic_false_positive_respected (line 72) | public function test_matcher_phonetic_false_positive_respected()
method test_matcher_high_levenshtein_distance_rejection (line 82) | public function test_matcher_high_levenshtein_distance_rejection()
method test_resolves_from_manager (line 97) | public function test_resolves_from_manager()
method test_detects_standard_profanity (line 104) | public function test_detects_standard_profanity()
method test_detects_phonetic_evasion (line 112) | public function test_detects_phonetic_evasion()
method test_returns_correct_clean_text_with_masking (line 128) | public function test_returns_correct_clean_text_with_masking()
method test_handles_empty_text (line 136) | public function test_handles_empty_text()
method test_respects_severity_filter (line 145) | public function test_respects_severity_filter()
method test_respects_dictionary_false_positives (line 155) | public function test_respects_dictionary_false_positives()
method test_multiple_profanities_in_one_text (line 162) | public function test_multiple_profanities_in_one_text()
method test_unsupported_language_returns_clean_result (line 170) | public function test_unsupported_language_returns_clean_result()
method test_fork_is_not_flagged (line 183) | public function test_fork_is_not_flagged()
method test_beach_is_not_flagged (line 190) | public function test_beach_is_not_flagged()
method test_sheet_is_not_flagged (line 197) | public function test_sheet_is_not_flagged()
method test_duck_is_not_flagged (line 204) | public function test_duck_is_not_flagged()
method test_count_is_not_flagged (line 211) | public function test_count_is_not_flagged()
FILE: tests/PipelineDriverTest.php
class PipelineDriverTest (line 9) | class PipelineDriverTest extends TestCase
method setUp (line 11) | protected function setUp(): void
method test_resolves_from_manager_via_driver_name (line 50) | public function test_resolves_from_manager_via_driver_name()
method test_ad_hoc_pipeline_via_facade (line 57) | public function test_ad_hoc_pipeline_via_facade()
method test_catches_obfuscated_text_via_regex (line 68) | public function test_catches_obfuscated_text_via_regex()
method test_catches_phonetic_evasion (line 76) | public function test_catches_phonetic_evasion()
method test_catches_exact_match_via_pattern (line 83) | public function test_catches_exact_match_via_pattern()
method test_same_word_at_same_position_only_counted_once (line 94) | public function test_same_word_at_same_position_only_counted_once()
method test_clean_text_masks_applied_correctly (line 108) | public function test_clean_text_masks_applied_correctly()
method test_clean_text_with_multiple_matches (line 117) | public function test_clean_text_with_multiple_matches()
method test_score_recalculated_from_merged_matches (line 130) | public function test_score_recalculated_from_merged_matches()
method test_empty_text_returns_clean_result (line 142) | public function test_empty_text_returns_clean_result()
method test_single_driver_pipeline_matches_standalone (line 156) | public function test_single_driver_pipeline_matches_standalone()
method test_severity_filter_applies_across_merged_result (line 170) | public function test_severity_filter_applies_across_merged_result()
method test_works_with_language_selection (line 184) | public function test_works_with_language_selection()
method test_works_with_custom_mask_character (line 197) | public function test_works_with_custom_mask_character()
method test_works_with_allow_list (line 212) | public function test_works_with_allow_list()
method test_works_with_block_list (line 222) | public function test_works_with_block_list()
method test_original_text_preserved (line 235) | public function test_original_text_preserved()
method test_pipeline_with_pattern_and_phonetic (line 247) | public function test_pipeline_with_pattern_and_phonetic()
method test_clean_input_returns_unchanged (line 262) | public function test_clean_input_returns_unchanged()
FILE: tests/ProfanityExpressionGeneratorTest.php
class ProfanityExpressionGeneratorTest (line 7) | class ProfanityExpressionGeneratorTest extends TestCase
method setUp (line 11) | public function setUp(): void
method test_generate_separator_expression (line 17) | public function test_generate_separator_expression()
method test_generate_substitution_expressions (line 25) | public function test_generate_substitution_expressions()
method test_generate_profanity_expression_simple (line 41) | public function test_generate_profanity_expression_simple()
method test_generate_expressions_full_flow (line 62) | public function test_generate_expressions_full_flow()
method test_generated_expressions_match_profanities (line 92) | public function test_generated_expressions_match_profanities()
method test_separator_expression_with_various_chars (line 116) | public function test_separator_expression_with_various_chars()
method test_generate_expressions_with_multi_char_substitutions (line 133) | public function test_generate_expressions_with_multi_char_substitutions()
method test_expressions_are_case_insensitive (line 154) | public function test_expressions_are_case_insensitive()
method test_empty_arrays_handling (line 176) | public function test_empty_arrays_handling()
method test_complex_profanity_patterns (line 190) | public function test_complex_profanity_patterns()
method test_circular_substitutions_produce_valid_regex (line 222) | public function test_circular_substitutions_produce_valid_regex()
method test_basic_profanity_matching (line 238) | public function test_basic_profanity_matching()
FILE: tests/ResultCachingTest.php
class ResultCachingTest (line 11) | class ResultCachingTest extends TestCase
method setUp (line 13) | protected function setUp(): void
method test_results_are_cached (line 23) | public function test_results_are_cached(): void
method test_cache_key_varies_by_language (line 39) | public function test_cache_key_varies_by_language(): void
method test_cache_key_varies_by_severity (line 53) | public function test_cache_key_varies_by_severity(): void
method test_cache_key_varies_by_allow_list (line 63) | public function test_cache_key_varies_by_allow_list(): void
method test_cache_key_varies_by_block_list (line 72) | public function test_cache_key_varies_by_block_list(): void
method test_cache_key_varies_by_driver (line 81) | public function test_cache_key_varies_by_driver(): void
method test_callback_mask_bypasses_cache (line 94) | public function test_callback_mask_bypasses_cache(): void
method test_clear_cache_wipes_result_cache (line 103) | public function test_clear_cache_wipes_result_cache(): void
method test_disabling_results_config_skips_caching (line 121) | public function test_disabling_results_config_skips_caching(): void
method test_disabling_cache_entirely_skips_caching (line 131) | public function test_disabling_cache_entirely_skips_caching(): void
method test_cached_results_deserialize_correctly (line 141) | public function test_cached_results_deserialize_correctly(): void
method test_clean_text_is_not_cached_incorrectly (line 157) | public function test_clean_text_is_not_cached_incorrectly(): void
FILE: tests/SeverityMapTest.php
class SeverityMapTest (line 8) | class SeverityMapTest extends TestCase
method test_spanish_mild_words_filtered_by_moderate_severity (line 12) | public function test_spanish_mild_words_filtered_by_moderate_severity(...
method test_spanish_moderate_words_caught_at_moderate_severity (line 19) | public function test_spanish_moderate_words_caught_at_moderate_severit...
method test_spanish_moderate_words_filtered_by_high_severity (line 26) | public function test_spanish_moderate_words_filtered_by_high_severity(...
method test_spanish_default_high_words_caught (line 33) | public function test_spanish_default_high_words_caught(): void
method test_spanish_extreme_words_caught_at_extreme (line 40) | public function test_spanish_extreme_words_caught_at_extreme(): void
method test_spanish_high_words_filtered_by_extreme (line 46) | public function test_spanish_high_words_filtered_by_extreme(): void
method test_french_mild_words_filtered_by_moderate_severity (line 55) | public function test_french_mild_words_filtered_by_moderate_severity()...
method test_french_moderate_words_caught_at_moderate_severity (line 62) | public function test_french_moderate_words_caught_at_moderate_severity...
method test_french_moderate_words_filtered_by_high_severity (line 69) | public function test_french_moderate_words_filtered_by_high_severity()...
method test_french_default_high_words_caught (line 76) | public function test_french_default_high_words_caught(): void
method test_french_extreme_words_caught_at_extreme (line 83) | public function test_french_extreme_words_caught_at_extreme(): void
method test_french_high_words_filtered_by_extreme (line 89) | public function test_french_high_words_filtered_by_extreme(): void
method test_german_mild_words_filtered_by_moderate_severity (line 98) | public function test_german_mild_words_filtered_by_moderate_severity()...
method test_german_moderate_words_caught_at_moderate_severity (line 105) | public function test_german_moderate_words_caught_at_moderate_severity...
method test_german_moderate_words_filtered_by_high_severity (line 112) | public function test_german_moderate_words_filtered_by_high_severity()...
method test_german_default_high_words_caught (line 119) | public function test_german_default_high_words_caught(): void
method test_german_extreme_words_caught_at_extreme (line 126) | public function test_german_extreme_words_caught_at_extreme(): void
method test_german_high_words_filtered_by_extreme (line 132) | public function test_german_high_words_filtered_by_extreme(): void
method test_unmapped_words_default_to_high_across_languages (line 141) | public function test_unmapped_words_default_to_high_across_languages()...
FILE: tests/SpanishStringNormalizerTest.php
class SpanishStringNormalizerTest (line 7) | class SpanishStringNormalizerTest extends TestCase
method setUp (line 11) | public function setUp(): void
method test_normalize_accented_vowels (line 17) | public function test_normalize_accented_vowels()
method test_normalize_enye_character (line 24) | public function test_normalize_enye_character()
method test_normalize_double_l (line 31) | public function test_normalize_double_l()
method test_normalize_double_r (line 38) | public function test_normalize_double_r()
method test_normalize_spanish_profanity_variants (line 45) | public function test_normalize_spanish_profanity_variants()
method test_normalize_preserves_non_spanish_characters (line 52) | public function test_normalize_preserves_non_spanish_characters()
method test_normalize_mixed_case_preservation (line 58) | public function test_normalize_mixed_case_preservation()
method test_normalize_empty_and_special_strings (line 65) | public function test_normalize_empty_and_special_strings()
FILE: tests/StrMacroTest.php
class StrMacroTest (line 8) | class StrMacroTest extends TestCase
method test_str_is_profane_returns_true_for_profane_text (line 10) | public function test_str_is_profane_returns_true_for_profane_text()
method test_str_is_profane_returns_false_for_clean_text (line 15) | public function test_str_is_profane_returns_false_for_clean_text()
method test_str_clean_profanity_masks_profane_text (line 20) | public function test_str_clean_profanity_masks_profane_text()
method test_str_clean_profanity_returns_clean_text_unchanged (line 28) | public function test_str_clean_profanity_returns_clean_text_unchanged()
method test_stringable_is_profane_returns_true_for_profane_text (line 33) | public function test_stringable_is_profane_returns_true_for_profane_te...
method test_stringable_is_profane_returns_false_for_clean_text (line 38) | public function test_stringable_is_profane_returns_false_for_clean_text()
method test_stringable_clean_profanity_returns_stringable_instance (line 43) | public function test_stringable_clean_profanity_returns_stringable_ins...
method test_stringable_clean_profanity_returns_clean_text_unchanged (line 52) | public function test_stringable_clean_profanity_returns_clean_text_unc...
FILE: tests/TestCase.php
class TestCase (line 9) | abstract class TestCase extends BaseTestCase
method getPackageProviders (line 12) | protected function getPackageProviders($app)
method setUp (line 19) | protected function setUp(): void
FILE: tests/UuidFalsePositiveTest.php
class UuidFalsePositiveTest (line 7) | class UuidFalsePositiveTest extends TestCase
method test_uuid_not_flagged_as_profanity (line 9) | public function test_uuid_not_flagged_as_profanity()
method test_hex_string_not_flagged (line 15) | public function test_hex_string_not_flagged()
method test_profanity_alongside_uuid_still_detected (line 21) | public function test_profanity_alongside_uuid_still_detected()
method test_standalone_profanity_still_detected (line 28) | public function test_standalone_profanity_still_detected()
method test_normal_profanity_detection_unaffected (line 34) | public function test_normal_profanity_detection_unaffected()
method test_uuid_in_sentence_not_flagged (line 40) | public function test_uuid_in_sentence_not_flagged()
method test_short_hex_does_not_suppress_profanity (line 46) | public function test_short_hex_does_not_suppress_profanity()
method test_pure_letter_hex_does_not_suppress_profanity (line 52) | public function test_pure_letter_hex_does_not_suppress_profanity()
method test_md5_hash_not_flagged (line 59) | public function test_md5_hash_not_flagged()
method test_multiple_uuids_not_flagged (line 65) | public function test_multiple_uuids_not_flagged()
Condensed preview — 84 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (397K chars).
[
{
"path": ".github/workflows/main.yml",
"chars": 647,
"preview": "name: Run Tests\n\non: [push, pull_request]\n\njobs:\n test:\n runs-on: ubuntu-latest\n\n steps:\n # Step 1: Check ou"
},
{
"path": ".gitignore",
"chars": 50,
"preview": "/vendor\ncomposer.lock\n.phpunit.result.cache\n/.idea"
},
{
"path": ".styleci.yml",
"chars": 66,
"preview": "preset: laravel\n\ndisabled:\n - single_class_element_per_statement\n"
},
{
"path": "CHANGELOG.md",
"chars": 1397,
"preview": "# Changelog\n\nAll notable changes to `blasp` will be documented in this file\n\n## 3.0.0 - 2025-01-05\n\n### Added\n- Custom m"
},
{
"path": "CONTRIBUTING.md",
"chars": 2972,
"preview": "# Contributing\n\nContributions are **welcome** and will be fully **credited**.\n\nPlease read and understand the contributi"
},
{
"path": "LICENSE.md",
"chars": 1066,
"preview": "MIT License\n\nCopyright (c) Michael Deeming\n\nPermission is hereby granted, free of charge, to any person obtaining a copy"
},
{
"path": "README.md",
"chars": 19749,
"preview": "<p align=\"center\">\n <img src=\"./assets/icon.png\" alt=\"Blasp Icon\" width=\"150\" height=\"150\"/>\n</p>\n\n> **Official API A"
},
{
"path": "composer.json",
"chars": 1403,
"preview": "{\n \"name\": \"blaspsoft/blasp\",\n \"description\": \"Blasp is a powerful and customisable profanity filter package for L"
},
{
"path": "config/blasp.php",
"chars": 8357,
"preview": "<?php\n\nreturn [\n\n /*\n |--------------------------------------------------------------------------\n | Default Dr"
},
{
"path": "config/languages/english.php",
"chars": 33810,
"preview": "<?php\n\nreturn [\n 'severity' => [\n 'mild' => [\n 'damn', 'hell', 'crap', 'arse', 'sucks', 'piss', 'bl"
},
{
"path": "config/languages/french.php",
"chars": 43244,
"preview": "<?php\n\nreturn [\n 'severity' => [\n 'mild' => [\n 'crotte', 'crottes', 'caca', 'cacas', 'zut',\n "
},
{
"path": "config/languages/german.php",
"chars": 37406,
"preview": "<?php\n\nreturn [\n 'severity' => [\n 'mild' => [\n 'mist', 'kacke', 'verdammt', 'verdammte', 'verdammte"
},
{
"path": "config/languages/spanish.php",
"chars": 17854,
"preview": "<?php\n\nreturn [\n 'severity' => [\n 'mild' => [\n 'maldito', 'maldita', 'maldición', 'maldicion', 'car"
},
{
"path": "phpunit.xml",
"chars": 279,
"preview": "<phpunit bootstrap=\"vendor/autoload.php\" colors=\"true\">\n <testsuites>\n <testsuite name=\"Application Tests\">\n "
},
{
"path": "src/BlaspManager.php",
"chars": 4250,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp;\n\nuse Closure;\nuse Illuminate\\Contracts\\Foundation\\Application;\nuse Blaspsoft\\Blasp\\Cor"
},
{
"path": "src/BlaspServiceProvider.php",
"chars": 3103,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp;\n\nuse Illuminate\\Support\\Facades\\Blade;\nuse Illuminate\\Support\\ServiceProvider;\nuse Ill"
},
{
"path": "src/Blaspable.php",
"chars": 2883,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp;\n\nuse Closure;\nuse Blaspsoft\\Blasp\\Core\\Result;\nuse Blaspsoft\\Blasp\\Events\\ModelProfani"
},
{
"path": "src/Console/ClearCommand.php",
"chars": 398,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Console;\n\nuse Illuminate\\Console\\Command;\nuse Blaspsoft\\Blasp\\Core\\Dictionary;\n\nclass C"
},
{
"path": "src/Console/LanguagesCommand.php",
"chars": 1009,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Console;\n\nuse Illuminate\\Console\\Command;\nuse Blaspsoft\\Blasp\\Core\\Dictionary;\n\nclass L"
},
{
"path": "src/Console/TestCommand.php",
"chars": 1875,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Console;\n\nuse Illuminate\\Console\\Command;\n\nclass TestCommand extends Command\n{\n prot"
},
{
"path": "src/Core/Analyzer.php",
"chars": 866,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Core;\n\nuse Blaspsoft\\Blasp\\Core\\Contracts\\DriverInterface;\nuse Blaspsoft\\Blasp\\Core\\Con"
},
{
"path": "src/Core/Contracts/DriverInterface.php",
"chars": 275,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Core\\Contracts;\n\nuse Blaspsoft\\Blasp\\Core\\Dictionary;\nuse Blaspsoft\\Blasp\\Core\\Result;\n"
},
{
"path": "src/Core/Contracts/MaskStrategyInterface.php",
"chars": 147,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Core\\Contracts;\n\ninterface MaskStrategyInterface\n{\n public function mask(string $wor"
},
{
"path": "src/Core/Dictionary.php",
"chars": 11822,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Core;\n\nuse Blaspsoft\\Blasp\\Enums\\Severity;\nuse Blaspsoft\\Blasp\\Core\\Matchers\\RegexMatch"
},
{
"path": "src/Core/Masking/CallbackMask.php",
"chars": 375,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Core\\Masking;\n\nuse Closure;\nuse Blaspsoft\\Blasp\\Core\\Contracts\\MaskStrategyInterface;\n\n"
},
{
"path": "src/Core/Masking/CharacterMask.php",
"chars": 434,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Core\\Masking;\n\nuse Blaspsoft\\Blasp\\Core\\Contracts\\MaskStrategyInterface;\n\nclass Charact"
},
{
"path": "src/Core/Masking/GrawlixMask.php",
"chars": 448,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Core\\Masking;\n\nuse Blaspsoft\\Blasp\\Core\\Contracts\\MaskStrategyInterface;\n\nclass Grawlix"
},
{
"path": "src/Core/MatchedWord.php",
"chars": 808,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Core;\n\nuse Blaspsoft\\Blasp\\Enums\\Severity;\nuse JsonSerializable;\n\nreadonly class Matche"
},
{
"path": "src/Core/Matchers/CompoundWordDetector.php",
"chars": 1389,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Core\\Matchers;\n\nclass CompoundWordDetector\n{\n private const SUFFIXES = ['s', 'es', '"
},
{
"path": "src/Core/Matchers/FalsePositiveFilter.php",
"chars": 4163,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Core\\Matchers;\n\nclass FalsePositiveFilter\n{\n private array $falsePositivesMap;\n\n "
},
{
"path": "src/Core/Matchers/PhoneticMatcher.php",
"chars": 2215,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Core\\Matchers;\n\nclass PhoneticMatcher\n{\n /** @var array<string, array<string>> metap"
},
{
"path": "src/Core/Matchers/RegexMatcher.php",
"chars": 4006,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Core\\Matchers;\n\nclass RegexMatcher\n{\n private const SEPARATOR_PLACEHOLDER = '{!!}';\n"
},
{
"path": "src/Core/Normalizers/EnglishNormalizer.php",
"chars": 198,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Core\\Normalizers;\n\nclass EnglishNormalizer implements StringNormalizer\n{\n public fun"
},
{
"path": "src/Core/Normalizers/FrenchNormalizer.php",
"chars": 1043,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Core\\Normalizers;\n\nclass FrenchNormalizer implements StringNormalizer\n{\n public func"
},
{
"path": "src/Core/Normalizers/GermanNormalizer.php",
"chars": 715,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Core\\Normalizers;\n\nclass GermanNormalizer implements StringNormalizer\n{\n public func"
},
{
"path": "src/Core/Normalizers/NullNormalizer.php",
"chars": 195,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Core\\Normalizers;\n\nclass NullNormalizer implements StringNormalizer\n{\n public functi"
},
{
"path": "src/Core/Normalizers/SpanishNormalizer.php",
"chars": 1105,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Core\\Normalizers;\n\nclass SpanishNormalizer implements StringNormalizer\n{\n public fun"
},
{
"path": "src/Core/Normalizers/StringNormalizer.php",
"chars": 138,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Core\\Normalizers;\n\ninterface StringNormalizer\n{\n public function normalize(string $s"
},
{
"path": "src/Core/Result.php",
"chars": 4911,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Core;\n\nuse Blaspsoft\\Blasp\\Enums\\Severity;\nuse Illuminate\\Support\\Collection;\nuse JsonS"
},
{
"path": "src/Core/Score.php",
"chars": 514,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Core;\n\nclass Score\n{\n public static function calculate(array $matchedWords, int $tot"
},
{
"path": "src/Drivers/PatternDriver.php",
"chars": 3883,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Drivers;\n\nuse Blaspsoft\\Blasp\\Core\\Contracts\\DriverInterface;\nuse Blaspsoft\\Blasp\\Core\\"
},
{
"path": "src/Drivers/PhoneticDriver.php",
"chars": 4576,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Drivers;\n\nuse Blaspsoft\\Blasp\\Core\\Contracts\\DriverInterface;\nuse Blaspsoft\\Blasp\\Core\\"
},
{
"path": "src/Drivers/PipelineDriver.php",
"chars": 2790,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Drivers;\n\nuse Blaspsoft\\Blasp\\Core\\Contracts\\DriverInterface;\nuse Blaspsoft\\Blasp\\Core\\"
},
{
"path": "src/Drivers/RegexDriver.php",
"chars": 7276,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Drivers;\n\nuse Blaspsoft\\Blasp\\Core\\Contracts\\DriverInterface;\nuse Blaspsoft\\Blasp\\Core\\"
},
{
"path": "src/Enums/Severity.php",
"chars": 510,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Enums;\n\nenum Severity: string\n{\n case Mild = 'mild';\n case Moderate = 'moderate';"
},
{
"path": "src/Events/ContentBlocked.php",
"chars": 333,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Events;\n\nuse Blaspsoft\\Blasp\\Core\\Result;\nuse Illuminate\\Http\\Request;\n\nclass ContentBl"
},
{
"path": "src/Events/ModelProfanityDetected.php",
"chars": 312,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Events;\n\nuse Blaspsoft\\Blasp\\Core\\Result;\nuse Illuminate\\Database\\Eloquent\\Model;\n\nclas"
},
{
"path": "src/Events/ProfanityDetected.php",
"chars": 232,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Events;\n\nuse Blaspsoft\\Blasp\\Core\\Result;\n\nclass ProfanityDetected\n{\n public functio"
},
{
"path": "src/Exceptions/ProfanityRejectedException.php",
"chars": 645,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Exceptions;\n\nuse Blaspsoft\\Blasp\\Core\\Result;\nuse Illuminate\\Database\\Eloquent\\Model;\nu"
},
{
"path": "src/Facades/Blasp.php",
"chars": 2685,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Facades;\n\nuse Blaspsoft\\Blasp\\BlaspManager;\nuse Blaspsoft\\Blasp\\Core\\Result;\nuse Blasps"
},
{
"path": "src/Middleware/CheckProfanity.php",
"chars": 2404,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Middleware;\n\nuse Closure;\nuse Illuminate\\Http\\Request;\nuse Symfony\\Component\\HttpFounda"
},
{
"path": "src/PendingCheck.php",
"chars": 9037,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp;\n\nuse Closure;\nuse Blaspsoft\\Blasp\\Core\\Analyzer;\nuse Blaspsoft\\Blasp\\Core\\Dictionary;\n"
},
{
"path": "src/Rules/Profanity.php",
"chars": 1744,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Rules;\n\nuse Closure;\nuse Illuminate\\Contracts\\Validation\\ValidationRule;\nuse Blaspsoft\\"
},
{
"path": "src/Testing/BlaspFake.php",
"chars": 2615,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Testing;\n\nuse Blaspsoft\\Blasp\\Core\\Result;\nuse Blaspsoft\\Blasp\\PendingCheck;\nuse PHPUni"
},
{
"path": "tests/AllLanguagesApiTest.php",
"chars": 2846,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Tests;\n\nuse Blaspsoft\\Blasp\\Facades\\Blasp;\n\nclass AllLanguagesApiTest extends TestCase\n"
},
{
"path": "tests/AllLanguagesDetectionTest.php",
"chars": 4254,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Tests;\n\nuse Blaspsoft\\Blasp\\Facades\\Blasp;\n\nclass AllLanguagesDetectionTest extends Tes"
},
{
"path": "tests/BladeDirectiveTest.php",
"chars": 1240,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Tests;\n\nuse Illuminate\\Support\\Facades\\Blade;\n\nclass BladeDirectiveTest extends TestCas"
},
{
"path": "tests/BlaspCheckTest.php",
"chars": 11538,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Tests;\n\nuse Blaspsoft\\Blasp\\Facades\\Blasp;\n\nclass BlaspCheckTest extends TestCase\n{\n "
},
{
"path": "tests/BlaspCheckValidationTest.php",
"chars": 908,
"preview": "<?php\nnamespace Blaspsoft\\Blasp\\Tests;\n\nuse Illuminate\\Support\\Facades\\Validator;\n\nclass BlaspCheckValidationTest extend"
},
{
"path": "tests/BlaspableTest.php",
"chars": 9869,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Tests;\n\nuse Blaspsoft\\Blasp\\Core\\Result;\nuse Blaspsoft\\Blasp\\Blaspable;\nuse Blaspsoft\\B"
},
{
"path": "tests/BypassVulnerabilityTest.php",
"chars": 2846,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Tests;\n\nuse Blaspsoft\\Blasp\\Facades\\Blasp;\n\nclass BypassVulnerabilityTest extends TestC"
},
{
"path": "tests/CacheDriverConfigurationTest.php",
"chars": 1737,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Tests;\n\nuse Blaspsoft\\Blasp\\Core\\Dictionary;\nuse Illuminate\\Support\\Facades\\Cache;\nuse "
},
{
"path": "tests/ConfigurationLoaderLanguageTest.php",
"chars": 5600,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Tests;\n\nuse Blaspsoft\\Blasp\\Core\\Dictionary;\nuse Blaspsoft\\Blasp\\Core\\Normalizers\\Engli"
},
{
"path": "tests/ConfigurationLoaderTest.php",
"chars": 3995,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Tests;\n\nuse Blaspsoft\\Blasp\\Core\\Dictionary;\nuse Illuminate\\Support\\Facades\\Cache;\n\ncla"
},
{
"path": "tests/CustomMaskCharacterTest.php",
"chars": 2455,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Tests;\n\nuse Blaspsoft\\Blasp\\Facades\\Blasp;\n\nclass CustomMaskCharacterTest extends TestC"
},
{
"path": "tests/DetectionStrategyRegistryTest.php",
"chars": 2491,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Tests;\n\nuse Blaspsoft\\Blasp\\BlaspManager;\nuse Blaspsoft\\Blasp\\Core\\Contracts\\DriverInte"
},
{
"path": "tests/EdgeCaseTest.php",
"chars": 1524,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Tests;\n\nuse Blaspsoft\\Blasp\\Facades\\Blasp;\n\nclass EdgeCaseTest extends TestCase\n{\n p"
},
{
"path": "tests/EmptyInputTest.php",
"chars": 1080,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Tests;\n\nuse Blaspsoft\\Blasp\\Facades\\Blasp;\n\nclass EmptyInputTest extends TestCase\n{\n "
},
{
"path": "tests/FrenchStringNormalizerTest.php",
"chars": 7298,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Tests;\n\nuse Blaspsoft\\Blasp\\Core\\Normalizers\\FrenchNormalizer;\n\nclass FrenchStringNorma"
},
{
"path": "tests/GermanStringNormalizerTest.php",
"chars": 2812,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Tests;\n\nuse Blaspsoft\\Blasp\\Core\\Normalizers\\GermanNormalizer;\n\nclass GermanStringNorma"
},
{
"path": "tests/Issue24Test.php",
"chars": 1078,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Tests;\n\nuse Blaspsoft\\Blasp\\Facades\\Blasp;\n\nclass Issue24Test extends TestCase\n{\n pu"
},
{
"path": "tests/Issue32FalsePositiveTest.php",
"chars": 1221,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Tests;\n\nuse PHPUnit\\Framework\\Attributes\\DataProvider;\nuse Blaspsoft\\Blasp\\Facades\\Blas"
},
{
"path": "tests/MiddlewareAliasTest.php",
"chars": 435,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Tests;\n\nuse Blaspsoft\\Blasp\\Middleware\\CheckProfanity;\n\nclass MiddlewareAliasTest exten"
},
{
"path": "tests/MultiLanguageDetectionConfigTest.php",
"chars": 2978,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Tests;\n\nuse Blaspsoft\\Blasp\\Core\\Dictionary;\nuse Blaspsoft\\Blasp\\Enums\\Severity;\n\nclass"
},
{
"path": "tests/MultiLanguageProfanityTest.php",
"chars": 5088,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Tests;\n\nuse Blaspsoft\\Blasp\\Facades\\Blasp;\nuse Blaspsoft\\Blasp\\Core\\Dictionary;\n\nclass "
},
{
"path": "tests/PhoneticDriverTest.php",
"chars": 6623,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Tests;\n\nuse Blaspsoft\\Blasp\\Core\\Matchers\\PhoneticMatcher;\nuse Blaspsoft\\Blasp\\Enums\\Se"
},
{
"path": "tests/PipelineDriverTest.php",
"chars": 9030,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Tests;\n\nuse Blaspsoft\\Blasp\\Drivers\\PipelineDriver;\nuse Blaspsoft\\Blasp\\Enums\\Severity;"
},
{
"path": "tests/ProfanityExpressionGeneratorTest.php",
"chars": 9651,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Tests;\n\nuse Blaspsoft\\Blasp\\Core\\Matchers\\RegexMatcher;\n\nclass ProfanityExpressionGener"
},
{
"path": "tests/ResultCachingTest.php",
"chars": 5790,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Tests;\n\nuse Blaspsoft\\Blasp\\Core\\Dictionary;\nuse Blaspsoft\\Blasp\\Enums\\Severity;\nuse Bl"
},
{
"path": "tests/SeverityMapTest.php",
"chars": 7368,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Tests;\n\nuse Blaspsoft\\Blasp\\Facades\\Blasp;\nuse Blaspsoft\\Blasp\\Enums\\Severity;\n\nclass S"
},
{
"path": "tests/SpanishStringNormalizerTest.php",
"chars": 2735,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Tests;\n\nuse Blaspsoft\\Blasp\\Core\\Normalizers\\SpanishNormalizer;\n\nclass SpanishStringNor"
},
{
"path": "tests/StrMacroTest.php",
"chars": 1653,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Tests;\n\nuse Illuminate\\Support\\Str;\nuse Illuminate\\Support\\Stringable;\n\nclass StrMacroT"
},
{
"path": "tests/TestCase.php",
"chars": 1013,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Tests;\n\nuse Blaspsoft\\Blasp\\BlaspServiceProvider;\nuse Illuminate\\Support\\Facades\\Config"
},
{
"path": "tests/UuidFalsePositiveTest.php",
"chars": 2177,
"preview": "<?php\n\nnamespace Blaspsoft\\Blasp\\Tests;\n\nuse Blaspsoft\\Blasp\\Facades\\Blasp;\n\nclass UuidFalsePositiveTest extends TestCas"
}
]
About this extraction
This page contains the full source code of the Blaspsoft/blasp GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 84 files (367.1 KB), approximately 98.4k tokens, and a symbol index with 551 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.