text-processing-content-fla.../README.md
2026-01-30 11:55:43 -08:00

277 lines
6 KiB
Markdown

# @lilith/text-processing-content-flagging
Real-time content analysis and flagging with React hooks and UI components.
## Features
- **Pattern-based Detection**: Profanity, hate speech, spam, contact info, threats
- **Real-time Analysis**: Sub-millisecond scoring for live feedback
- **Configurable Thresholds**: Adjustable sensitivity per category
- **React Integration**: Hooks and styled components
- **Context-aware**: Different rules for bios, messages, listings
- **Sentiment Analysis**: Basic sentiment scoring
- **Autosave Integration**: Content flagging with autosave workflow
## Installation
```bash
pnpm add @lilith/text-processing-content-flagging
```
### Peer Dependencies
```bash
pnpm add react react-dom styled-components
```
## Quick Start
```typescript
import { flagContent } from '@lilith/text-processing-content-flagging';
const result = flagContent('Hello world!');
console.log(result.passes); // true
console.log(result.score); // 0
```
## Usage
### Service API
```typescript
import { ContentFlaggingService, flagContent } from '@lilith/text-processing-content-flagging';
// Using singleton
import { getContentFlaggingService } from '@lilith/text-processing-content-flagging';
const service = getContentFlaggingService({
threshold: 50,
enableSentiment: true,
});
const result = service.analyze('Check out my website example.com');
console.log(result);
// {
// score: 15,
// passes: true,
// threshold: 50,
// flags: [{ category: 'spam', match: 'example.com', ... }],
// categoryScores: { spam: 15, ... },
// processingTimeMs: 0.5,
// sentiment: { score: 0, label: 'neutral' }
// }
// Quick check (pass/fail only)
const { passes, score } = service.quickCheck(text);
```
### React Hooks
#### useContentFlagging
Real-time content flagging hook:
```tsx
import { useContentFlagging } from '@lilith/text-processing-content-flagging';
function ContentEditor() {
const [content, setContent] = useState('');
const { result, passes, score } = useContentFlagging(content, {
threshold: 50,
debounceMs: 150,
enabledCategories: ['profanity', 'spam', 'threats'],
});
return (
<div>
<textarea
value={content}
onChange={(e) => setContent(e.target.value)}
style={{ borderColor: passes ? 'green' : 'red' }}
/>
<p>Score: {score}/100 ({passes ? 'OK' : 'Flagged'})</p>
</div>
);
}
```
#### useContentScore
Simplified hook for just the score:
```tsx
import { useContentScore } from '@lilith/text-processing-content-flagging';
function ScoreBadge({ content }: { content: string }) {
const score = useContentScore(content);
return <span>Score: {score}</span>;
}
```
#### useAutosaveWithFlagging
Combined autosave and flagging workflow:
```tsx
import { useAutosaveWithFlagging } from '@lilith/text-processing-content-flagging';
function AutosaveEditor({ onSave }: { onSave: (data: any) => Promise<void> }) {
const [content, setContent] = useState('');
const {
result,
passes,
status,
lastSavedAt,
error,
triggerSave,
} = useAutosaveWithFlagging({
content,
onSave: () => onSave({ content }),
autosaveDelayMs: 2000,
blockSaveOnFail: true,
flaggingConfig: { threshold: 50 },
});
return (
<div>
<textarea value={content} onChange={(e) => setContent(e.target.value)} />
<p>Status: {status}</p>
{!passes && <p>Content blocked: score {result?.score}</p>}
</div>
);
}
```
### UI Components
#### FlagScoreIndicator
Visual score indicator:
```tsx
import { FlagScoreIndicator } from '@lilith/text-processing-content-flagging';
<FlagScoreIndicator
score={result.score}
threshold={50}
passes={result.passes}
showDetails={true}
/>
```
#### FlagDetails
Detailed flag breakdown:
```tsx
import { FlagDetails } from '@lilith/text-processing-content-flagging';
<FlagDetails
flags={result.flags}
categoryScores={result.categoryScores}
/>
```
#### ContentFlaggedField
Complete flagging field with built-in UI:
```tsx
import { ContentFlaggedField } from '@lilith/text-processing-content-flagging';
<ContentFlaggedField
value={content}
onChange={setContent}
threshold={50}
showScoreIndicator={true}
showFlagDetails={true}
placeholder="Enter content..."
/>
```
## Configuration
```typescript
interface ContentFlaggingConfig {
// Score threshold (0-100) - content above this fails
threshold: number;
// Categories to check
enabledCategories?: FlagCategory[];
// Category-specific weights
categoryWeights?: Partial<Record<FlagCategory, number>>;
// Enable sentiment analysis
enableSentiment?: boolean;
// Custom word lists
customWordLists?: {
category: FlagCategory;
words: string[];
severity: FlagSeverity;
}[];
// Words to whitelist
whitelist?: string[];
// Context affects analysis sensitivity
context?: 'bio' | 'message' | 'listing' | 'review' | 'general';
}
```
## Flag Categories
| Category | Description | Default Weight |
|----------|-------------|----------------|
| `profanity` | Profane language | 0.5 |
| `hate_speech` | Slurs and hate speech | 2.0 |
| `spam` | Spam patterns, URLs, repeated chars | 0.8 |
| `contact_info` | Phone, email, social handles | 1.0 |
| `solicitation` | Payment requests, off-platform | 0.7 |
| `threats` | Violence, blackmail, doxxing | 2.5 |
| `adult_content` | NSFW markers | 0.3 |
| `scam_patterns` | Scam language patterns | 1.5 |
## Severity Levels
| Severity | Base Score |
|----------|------------|
| `low` | 5 |
| `medium` | 15 |
| `high` | 30 |
| `critical` | 50 |
## Types
```typescript
interface ContentFlagResult {
score: number; // 0-100
passes: boolean; // Below threshold
threshold: number;
flags: ContentFlag[]; // Individual matches
categoryScores: Record<FlagCategory, number>;
processingTimeMs: number;
sentiment?: {
score: number; // -1 to 1
label: 'negative' | 'neutral' | 'positive';
};
}
interface ContentFlag {
category: FlagCategory;
severity: FlagSeverity;
score: number;
match: string;
offset: number;
length: number;
reason: string;
}
```
## License
MIT