Skip to content

Recipes

Guides stay starred. Wire these into your app, then verify with the playground or npx anti-ttyah.

Browser form

ts
import { contains, mask } from "anti-ttyah";

const form = document.querySelector("form")!;
const comment = document.querySelector<HTMLTextAreaElement>("#comment")!;

form.addEventListener("submit", (event) => {
  if (contains(comment.value)) {
    event.preventDefault();
    comment.value = mask(comment.value);
    comment.setCustomValidity("Please remove blocked language.");
    comment.reportValidity();
  }
});

Node / Express-style fields

ts
import { blockedError } from "anti-ttyah";

export function moderate(title: string, body: string) {
  const err = blockedError({ title, body });
  if (err) return { status: 400, ...err };
  return { status: 200 };
}

blockedError also accepts loose string arguments or string arrays.

Custom list for one product

ts
import { createFilter } from "anti-ttyah";

const comments = createFilter({
  extraTerms: ["competitor-slur"],
  allowlist: ["h*ar"],
  categories: ["sexual", "slur", "insult"],
  maskStyle: "token",
});

CLI in CI

bash
npx anti-ttyah --file comments.txt
# exit 0 clean, 1 blocked

JSON for logs:

bash
npx anti-ttyah --json --file comments.txt
npx anti-ttyah --explain --file comments.txt

GitHub Actions

yaml
name: Moderate comments file
on: [push]
jobs:
  filter:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npx anti-ttyah --file comments.txt

Why not bad-words?

typical EN filterAnti-Ttyah
Englishyesyes
Frenchsometimesyes
Arabic (script + Latin chat)noyes
Franco-arabe digits (3/7/9)noyes
Tamazightnoconservative list
Runs offlineyesyes

MIT license · runs in Node and the browser · zero runtime deps