// src/lang/de.ts — import from 'ts-profanity-filter/lang/de' // // German word lists. Same rules as the English ones: every entry is a regex // source string and matching is substring-based. // // German needs a much larger allowlist than English for two reasons: // 1. Compounding — `Weltklasse`, `Sparkasse`, `Trinkwasser` all end in a stem // that contains the English pattern `ass`, so allow entries are written // permissively as `\p{L}*stem\p{L}*`. // 2. `aggressive` maps `c` to `[c(k<]`, so English patterns start matching // German k-spellings: `cum` suddenly hits `Dokument`, `Kumpel`, `Publikum`. import type { LanguageDefinition } from '../registry.js'; /** * What counts as being *inside* a word, spelled out the same way `enclosingWord` * spells it in filter.ts. * * `\b` cannot be used for this. JavaScript's `\b` is defined in terms of `\w`, * which stays ASCII even under the `u` flag, so every umlaut and every `ß` reads * as a word boundary: `\bschwanz\b` fires inside `Straußschwanz`, and `\bsau\b` * inside `Straußsau`. Both are ordinary German compounds. */ const INSIDE_WORD = '[\\p{L}\\p{M}\\p{N}_]'; /** * Wraps a stem so it only matches as a whole word — the Unicode-aware version * of `\b…\b`. * * The lookbehind is why `filter.ts` compiles its patterns defensively: engines * without lookbehind support fall back rather than throwing. */ const word = (stem: string): string => `(? [c(k<] mapping ----------------------- 'dokument\\p{L}*', '\\p{L}*kummer\\p{L}*', '\\p{L}*kumpel\\p{L}*', '\\p{L}*kumpan\\p{L}*', '\\p{L}*publikum\\p{L}*', 'akkumul\\p{L}*', 'kumul\\p{L}*', 'zirkum\\p{L}*', 'vakuum\\p{L}*', // -- other aggressive-mode collisions ----------------------------------- '\\p{L}*schwank\\p{L}*', // wank: schwanken, Schwankung 'wankel\\p{L}*', 'wanken', 'wankt', 'wankte', 'wankend\\p{L}*', '\\p{L}*spick\\p{L}*', // spic: spicken, Spickzettel '\\p{L}*prickel\\p{L}*', // prick: prickeln, prickelnd '\\p{L}*krapfen\\p{L}*', // crap: Krapfen 'kunterbunt\\p{L}*', // cunt: kunterbunt 'fagott\\p{L}*', // fag: Fagott 'fkk', // fck: Freikörperkultur 'homogen\\p{L}*', 'homolog\\p{L}*', 'homosexuell\\p{L}*', ]; /** Ready to hand to `registerLanguage('de', de)`. Pre-registered already. */ export const de: LanguageDefinition = { profanity: DE_PROFANITY, allow: DE_ALLOWLIST, };