From 9fe71c642eaba1b094566f93e9701000e5a186be Mon Sep 17 00:00:00 2001 From: up2dul Date: Sun, 13 Sep 2026 20:06:50 +0700 Subject: [PATCH 1/4] feat(dictionaries): revise english and indonesian packs --- .changeset/bright-languages-grow.md | 6 + dictionaries/en/metadata.json | 4 +- dictionaries/en/words.txt | 329 +++++++++++++++++---- dictionaries/id/metadata.json | 4 +- dictionaries/id/words.txt | 161 +++++++--- packages/profanity-kit/src/generated/en.ts | 323 +++++++++++++++++--- packages/profanity-kit/src/generated/id.ts | 153 ++++++++-- packages/profanity-kit/src/index.test.ts | 24 +- 8 files changed, 834 insertions(+), 170 deletions(-) create mode 100644 .changeset/bright-languages-grow.md diff --git a/.changeset/bright-languages-grow.md b/.changeset/bright-languages-grow.md new file mode 100644 index 0000000..61af20a --- /dev/null +++ b/.changeset/bright-languages-grow.md @@ -0,0 +1,6 @@ +--- +"profanity-kit": minor +--- + +Revise and expand the reviewed English and Indonesian dictionaries, adding +new entries and removing excluded variants to improve language-pack quality. diff --git a/dictionaries/en/metadata.json b/dictionaries/en/metadata.json index 03d2b84..b6f8617 100644 --- a/dictionaries/en/metadata.json +++ b/dictionaries/en/metadata.json @@ -1,10 +1,10 @@ { "code": "en", "name": "English", - "version": "0.2.0", + "version": "0.3.0", "source": "project-curated", "license": "MIT", - "retrievedAt": "2026-08-31", + "retrievedAt": "2026-09-13", "reviewStatus": "human-reviewed", "reviewer": "project-maintainers" } diff --git a/dictionaries/en/words.txt b/dictionaries/en/words.txt index de81162..9557216 100644 --- a/dictionaries/en/words.txt +++ b/dictionaries/en/words.txt @@ -1,129 +1,286 @@ -englishsentinel +apeshit arse +arseface +arsehat +arsehats +arsehead arsehole arseholes -arses +arselicker +arsemunch arsewipe arsewipes ass assbag +assbags +assbandit +assbanger +assbite +assblaster assclown +assclowns +asscock +asscrack +asscracker asses assface assfaces +assfuck +assfucker +assfuckers +assfucking +assfucks +assgoblin asshat asshats asshead +assheads asshole assholes +assjockey +asskisser +asslick +asslicker +asslickers +asslover +assmaster +assmonkey +assmonkeys +assmunch +assmuncher +assmunchers +assrammer +assshit +asssucker asswad +asswads +asswhole +asswhore asswipe asswipes ballbag +balllicker ballsack +ballsacks +bampot +bassterd bastard bastards -batshit +basterd bellend bellends -beotch biatch +bint bitch bitchass +bitchasses +bitchbag +bitchboy bitched bitcher bitchers bitches +bitchface +bitchfaces +bitchhead bitchin bitching bitchslap +bitchtits bitchy +bloody bollock +bollocking +bollockings bollocks +bollok +bollox +boner bugger buggered -buggering -buggers bullcrap bullshit bullshits bullshitted +bullshitter +bullshitters bullshitting bumfuck +bunghole +buttface +buttfuck +buttfucked +buttfucker +buttfuckers +buttfucking butthead butthole +buttholes buttmunch +buttmuncher +buttwipe +byatch +choad +chode +chodes clusterfuck -clusterfucked -clusterfucking -clusterfucks cock +cockbag +cockbags +cockbite +cockbites +cockblock +cockblocker +cockburger +cockburgers cockface +cockfucker +cockfuckers cockhead cockheads -cockmunch +cockjockey +cockknob +cockknocker +cocklick +cocklicker +cockmaster +cockmasters +cockmongler +cockmonglers cockmuncher +cocknob +cocknose +cocknoses +cocknugget +cockring cocks +cockshit +cocksmoker +cocksniffer +cocksniffers cocksuck -cocksucked cocksucker cocksuckers cocksucking -cocksucks +coochie +cooter +cornhole crap +craphead +crapheads +crapola crapped crapper +crappers crapping crappy -crapola -craps +cuck +cum +cumbubble +cumdump +cumdumps +cumdumpster +cumguzzler +cumjockey +cumming +cumrag +cums +cumshot +cumshots +cumslut +cumsluts +cumstain +cumsucker cunt +cuntbag cuntface +cunthead cunthole +cunting +cuntlick +cuntlicker +cuntrag cunts -cunty +cuntsucker +damm dammit damn +damnation damned +damning damnit dick dickbag +dickbagger +dickbags dickbrain +dickbrains +dickbreath +dickbreaths dickface -dickfaces +dickfucker dickhead dickheads dickhole -dickish +dickholes +dickless +dicklick +dicklicker +dicklickers +dicklicking +dickmunch dicks -dickslap +dicksucker dickwad dickwads +dickwank dickweed +dickweeds +dildo +dildos dipshit dipshits dipstick -doochbag -doosh douche douchebag douchebags -douches +douchecanoe +doucheface douchewaffle dumbass dumbasses dumbfuck -dumbshit -fck -fcuk +dumbfucks +facefucker +fanny +fartknocker +fatass feck fecker ffs +fingerfuck +fingerfucked +fingerfucker +fingerfucking +fistfuck +fistfucked +fistfucker +fistfucking +frigga +frigger fuck fuckass +fuckasses fuckbag +fuckbags +fuckbitch fuckboy fuckboys +fuckbrain +fuckbrains +fuckbucket +fuckbuckets +fuckbutt fucked fucker fuckers @@ -131,40 +288,36 @@ fuckface fuckfaces fuckhead fuckheads +fuckhole fuckin fucking fuckknob +fuckknuckle +fuckmeat +fuckmonkey fucknugget fucknut fucknuts fuckoff +fuckpig +fuckpuppet fucks fuckstick -fucksticks fucktard fucktards +fucktart fuckup -fuckups fuckwad fuckwads +fuckweasel fuckwhit +fuckwhore fuckwit fuckwits -fuckwitt -fuckyou +fuckwitted fugly -fuk -fuker -fukin -fuking -fukk -fukka -fukker -fukkin -fukking -fuuck fvck -fxck +gassyass godammit godamn godamnit @@ -174,82 +327,158 @@ goddammit goddamn goddamned goddamnit -gtfo horseshit jackass jackasses jackoff jackoffs +jackshit jerkoff jerkoffs +knob +knobber +knobend +knobends +knobhead +knobheads +minge +minger +mingers +mothafucka +mothafuckas +mothafuckaz +mothafucker motherfuck motherfucked motherfucker motherfuckers +motherfuckin motherfucking motherfucks +muthafucka +muthafucker +nutsack +nutsacks piss +pissant +pissbag +pissbrain +pissbucket pissed +pissedoff pisser pissers pisses +pissface +pissfaces +pissflap +pissflaps +pissfuck pisshead pissheads +pisshole pissing +pisspot +pisspots prick pricks pussies pussy shit shitass +shitasses shitbag +shitbagger shitbags +shitbird +shitbox +shitbrain +shitbrains +shitbreath +shitbreaths +shitbucket +shitbuckets +shitcunt +shitdick +shite +shited shitface shitfaced shitfaces +shitfuck +shitfucker +shitfuckers shithead shitheads -shite -shited +shitheel shithole shitholes +shitlist +shitload +shitloads +shitlord +shitpile +shitpot shits +shitsack shitshow -shitshows shitstain shitstains shitstorm -shitstorms +shitted shitter shitters shittier shittiest shitting shitty +shitwad +shitweasel +shitwit skank skanks +skanky +slag +slags +slapper +slappers slut sluts slutty +sodoff +sonofabitch stfu +tit +tits +titties +titty tosser tossers +turd +turdface +turdhead +turds twat twathead twats -twatty +twatwaffle wank +wankbag wanked wanker wankers +wankface +wankfest wanking wankjob wanks -wanky +wankshaft +wankshit +wankstain +wankstains +wazzock whore -whorebag -whored -whoreface whores whoring -wtf \ No newline at end of file +whorish +wtf diff --git a/dictionaries/id/metadata.json b/dictionaries/id/metadata.json index 1db25dd..3f13aeb 100644 --- a/dictionaries/id/metadata.json +++ b/dictionaries/id/metadata.json @@ -1,10 +1,10 @@ { "code": "id", "name": "Indonesian", - "version": "0.2.0", + "version": "0.3.0", "source": "project-curated", "license": "MIT", - "retrievedAt": "2026-08-31", + "retrievedAt": "2026-09-13", "reviewStatus": "human-reviewed", "reviewer": "project-maintainers" } diff --git a/dictionaries/id/words.txt b/dictionaries/id/words.txt index 0594749..c316eac 100644 --- a/dictionaries/id/words.txt +++ b/dictionaries/id/words.txt @@ -1,126 +1,221 @@ -indonesiansentinel +ancok +ancuk +ancuruk anjay +anjg anjim anjing -anjingan anjir -anjirr +anjng anjrit anjrot anying +anyir asu +asw +asuwo babi +bacod bacot -bagudung +bacotnya +bajindul +bajing +bajingak bajingan +bajinguk +bajirut bangke +bangkean +bangor bangsat -bejad -bejat +bangsatkau +bangsatmu +bangsatnya bedebah bego -bloon +begoan +bejad +bejat +bjir +blok bodat +borjong brengsek +bujanginam +bujanginang bungul burit -chibai +celeng cibai cibay cocot +cocote cok +cokil +colai coli colmek -congor cuk cuki cukimai +cukimak cukimay -cukin +damput +dancik dancok dancuk -dientot -dientotin +diancuk +dongo +dongok +encuk entot ewe -gathel -gatheli gembel goblog +goblognya goblok +heang hencet henceut idiot -jablay +itil jablai +jablay jancik jancok +jancokmu +jancoknya +jancox jancuk -jancur +jancukmu +jancuknya +jancux +jembot jembut +jembutmu +jembutnya +jing +jingan kacuk kampang kampret +kampretmu kanciang +kelentit +kemem keparat +keparatnya kimak -kimcil -kintil +kimakmu +kimaknya +kimbek +kimpet kirik +klentit kolop konthol kontol +kontolan +kontolkau +kontollo +kontollu +kontolmu +kontolnya koplok kunyuk kwontol +ler lonte +lonteh +lotnok mampus -meki +mek memek -mengentot -mengentoti -mengentotin +memekmu +memeknya modar +modyar +mokad monyet +ndas ndasmu +ndhas ndhasmu +ndlogok nenen -ngehe +ngentod ngentot -ngentotin +ngentotnya ngewe +nggateli +ngolom ngulum -pantek +njing +njir +ogeb +palkon +palkor pantat -pecun -peju +pantek +pantekmu +panteknya +pekok +pekokmu peler +pelerkau +pelerlo +pelerlu +pelermu pentil pepek +pepeklo +pepeklu +pepekmu +pepeknya perek -pilat +pler puki +pukima pukimak +pukimaknya qontol +sange sarap +sat sempak +setan sial sialan +sialanmu silit sinting -sompret sontoloyo -sundal taek +taeknya tahi tai -tailaso +taiayam +taik +taiklo +taiklu +taikmu +taiknya telaso +telek tempek tempik +tete tetek titit +tititmu +titiw toket +toketmu tolol -totong -tusbol \ No newline at end of file +tolollo +tolollu +tololmu +tololnya +tot +tusbol +wedus diff --git a/packages/profanity-kit/src/generated/en.ts b/packages/profanity-kit/src/generated/en.ts index 0cbfa1e..a17790d 100644 --- a/packages/profanity-kit/src/generated/en.ts +++ b/packages/profanity-kit/src/generated/en.ts @@ -1,131 +1,288 @@ // Generated by scripts/generate-dictionaries.mjs; do not edit manually. export const words = Object.freeze([ + "apeshit", "arse", + "arseface", + "arsehat", + "arsehats", + "arsehead", "arsehole", "arseholes", - "arses", + "arselicker", + "arsemunch", "arsewipe", "arsewipes", "ass", "assbag", + "assbags", + "assbandit", + "assbanger", + "assbite", + "assblaster", "assclown", + "assclowns", + "asscock", + "asscrack", + "asscracker", "asses", "assface", "assfaces", + "assfuck", + "assfucker", + "assfuckers", + "assfucking", + "assfucks", + "assgoblin", "asshat", "asshats", "asshead", + "assheads", "asshole", "assholes", + "assjockey", + "asskisser", + "asslick", + "asslicker", + "asslickers", + "asslover", + "assmaster", + "assmonkey", + "assmonkeys", + "assmunch", + "assmuncher", + "assmunchers", + "assrammer", + "assshit", + "asssucker", "asswad", + "asswads", + "asswhole", + "asswhore", "asswipe", "asswipes", "ballbag", + "balllicker", "ballsack", + "ballsacks", + "bampot", + "bassterd", "bastard", "bastards", - "batshit", + "basterd", "bellend", "bellends", - "beotch", "biatch", + "bint", "bitch", "bitchass", + "bitchasses", + "bitchbag", + "bitchboy", "bitched", "bitcher", "bitchers", "bitches", + "bitchface", + "bitchfaces", + "bitchhead", "bitchin", "bitching", "bitchslap", + "bitchtits", "bitchy", + "bloody", "bollock", + "bollocking", + "bollockings", "bollocks", + "bollok", + "bollox", + "boner", "bugger", "buggered", - "buggering", - "buggers", "bullcrap", "bullshit", "bullshits", "bullshitted", + "bullshitter", + "bullshitters", "bullshitting", "bumfuck", + "bunghole", + "buttface", + "buttfuck", + "buttfucked", + "buttfucker", + "buttfuckers", + "buttfucking", "butthead", "butthole", + "buttholes", "buttmunch", + "buttmuncher", + "buttwipe", + "byatch", + "choad", + "chode", + "chodes", "clusterfuck", - "clusterfucked", - "clusterfucking", - "clusterfucks", "cock", + "cockbag", + "cockbags", + "cockbite", + "cockbites", + "cockblock", + "cockblocker", + "cockburger", + "cockburgers", "cockface", + "cockfucker", + "cockfuckers", "cockhead", "cockheads", - "cockmunch", + "cockjockey", + "cockknob", + "cockknocker", + "cocklick", + "cocklicker", + "cockmaster", + "cockmasters", + "cockmongler", + "cockmonglers", "cockmuncher", + "cocknob", + "cocknose", + "cocknoses", + "cocknugget", + "cockring", "cocks", + "cockshit", + "cocksmoker", + "cocksniffer", + "cocksniffers", "cocksuck", - "cocksucked", "cocksucker", "cocksuckers", "cocksucking", - "cocksucks", + "coochie", + "cooter", + "cornhole", "crap", + "craphead", + "crapheads", "crapola", "crapped", "crapper", + "crappers", "crapping", "crappy", - "craps", + "cuck", + "cum", + "cumbubble", + "cumdump", + "cumdumps", + "cumdumpster", + "cumguzzler", + "cumjockey", + "cumming", + "cumrag", + "cums", + "cumshot", + "cumshots", + "cumslut", + "cumsluts", + "cumstain", + "cumsucker", "cunt", + "cuntbag", "cuntface", + "cunthead", "cunthole", + "cunting", + "cuntlick", + "cuntlicker", + "cuntrag", "cunts", - "cunty", + "cuntsucker", + "damm", "dammit", "damn", + "damnation", "damned", + "damning", "damnit", "dick", "dickbag", + "dickbagger", + "dickbags", "dickbrain", + "dickbrains", + "dickbreath", + "dickbreaths", "dickface", - "dickfaces", + "dickfucker", "dickhead", "dickheads", "dickhole", - "dickish", + "dickholes", + "dickless", + "dicklick", + "dicklicker", + "dicklickers", + "dicklicking", + "dickmunch", "dicks", - "dickslap", + "dicksucker", "dickwad", "dickwads", + "dickwank", "dickweed", + "dickweeds", + "dildo", + "dildos", "dipshit", "dipshits", "dipstick", - "doochbag", - "doosh", "douche", "douchebag", "douchebags", - "douches", + "douchecanoe", + "doucheface", "douchewaffle", "dumbass", "dumbasses", "dumbfuck", - "dumbshit", - "englishsentinel", - "fck", - "fcuk", + "dumbfucks", + "facefucker", + "fanny", + "fartknocker", + "fatass", "feck", "fecker", "ffs", + "fingerfuck", + "fingerfucked", + "fingerfucker", + "fingerfucking", + "fistfuck", + "fistfucked", + "fistfucker", + "fistfucking", + "frigga", + "frigger", "fuck", "fuckass", + "fuckasses", "fuckbag", + "fuckbags", + "fuckbitch", "fuckboy", "fuckboys", + "fuckbrain", + "fuckbrains", + "fuckbucket", + "fuckbuckets", + "fuckbutt", "fucked", "fucker", "fuckers", @@ -133,40 +290,36 @@ export const words = Object.freeze([ "fuckfaces", "fuckhead", "fuckheads", + "fuckhole", "fuckin", "fucking", "fuckknob", + "fuckknuckle", + "fuckmeat", + "fuckmonkey", "fucknugget", "fucknut", "fucknuts", "fuckoff", + "fuckpig", + "fuckpuppet", "fucks", "fuckstick", - "fucksticks", "fucktard", "fucktards", + "fucktart", "fuckup", - "fuckups", "fuckwad", "fuckwads", + "fuckweasel", "fuckwhit", + "fuckwhore", "fuckwit", "fuckwits", - "fuckwitt", - "fuckyou", + "fuckwitted", "fugly", - "fuk", - "fuker", - "fukin", - "fuking", - "fukk", - "fukka", - "fukker", - "fukkin", - "fukking", - "fuuck", "fvck", - "fxck", + "gassyass", "godammit", "godamn", "godamnit", @@ -176,84 +329,160 @@ export const words = Object.freeze([ "goddamn", "goddamned", "goddamnit", - "gtfo", "horseshit", "jackass", "jackasses", "jackoff", "jackoffs", + "jackshit", "jerkoff", "jerkoffs", + "knob", + "knobber", + "knobend", + "knobends", + "knobhead", + "knobheads", + "minge", + "minger", + "mingers", + "mothafucka", + "mothafuckas", + "mothafuckaz", + "mothafucker", "motherfuck", "motherfucked", "motherfucker", "motherfuckers", + "motherfuckin", "motherfucking", "motherfucks", + "muthafucka", + "muthafucker", + "nutsack", + "nutsacks", "piss", + "pissant", + "pissbag", + "pissbrain", + "pissbucket", "pissed", + "pissedoff", "pisser", "pissers", "pisses", + "pissface", + "pissfaces", + "pissflap", + "pissflaps", + "pissfuck", "pisshead", "pissheads", + "pisshole", "pissing", + "pisspot", + "pisspots", "prick", "pricks", "pussies", "pussy", "shit", "shitass", + "shitasses", "shitbag", + "shitbagger", "shitbags", + "shitbird", + "shitbox", + "shitbrain", + "shitbrains", + "shitbreath", + "shitbreaths", + "shitbucket", + "shitbuckets", + "shitcunt", + "shitdick", "shite", "shited", "shitface", "shitfaced", "shitfaces", + "shitfuck", + "shitfucker", + "shitfuckers", "shithead", "shitheads", + "shitheel", "shithole", "shitholes", + "shitlist", + "shitload", + "shitloads", + "shitlord", + "shitpile", + "shitpot", "shits", + "shitsack", "shitshow", - "shitshows", "shitstain", "shitstains", "shitstorm", - "shitstorms", + "shitted", "shitter", "shitters", "shittier", "shittiest", "shitting", "shitty", + "shitwad", + "shitweasel", + "shitwit", "skank", "skanks", + "skanky", + "slag", + "slags", + "slapper", + "slappers", "slut", "sluts", "slutty", + "sodoff", + "sonofabitch", "stfu", + "tit", + "tits", + "titties", + "titty", "tosser", "tossers", + "turd", + "turdface", + "turdhead", + "turds", "twat", "twathead", "twats", - "twatty", + "twatwaffle", "wank", + "wankbag", "wanked", "wanker", "wankers", + "wankface", + "wankfest", "wanking", "wankjob", "wanks", - "wanky", + "wankshaft", + "wankshit", + "wankstain", + "wankstains", + "wazzock", "whore", - "whorebag", - "whored", - "whoreface", "whores", "whoring", + "whorish", "wtf", ] as const); -export const version = "0.2.0"; +export const version = "0.3.0"; diff --git a/packages/profanity-kit/src/generated/id.ts b/packages/profanity-kit/src/generated/id.ts index 17e0844..a23d182 100644 --- a/packages/profanity-kit/src/generated/id.ts +++ b/packages/profanity-kit/src/generated/id.ts @@ -1,130 +1,225 @@ // Generated by scripts/generate-dictionaries.mjs; do not edit manually. export const words = Object.freeze([ + "ancok", + "ancuk", + "ancuruk", "anjay", + "anjg", "anjim", "anjing", - "anjingan", "anjir", - "anjirr", + "anjng", "anjrit", "anjrot", "anying", + "anyir", "asu", + "asuwo", + "asw", "babi", + "bacod", "bacot", - "bagudung", + "bacotnya", + "bajindul", + "bajing", + "bajingak", "bajingan", + "bajinguk", + "bajirut", "bangke", + "bangkean", + "bangor", "bangsat", + "bangsatkau", + "bangsatmu", + "bangsatnya", "bedebah", "bego", + "begoan", "bejad", "bejat", - "bloon", + "bjir", + "blok", "bodat", + "borjong", "brengsek", + "bujanginam", + "bujanginang", "bungul", "burit", - "chibai", + "celeng", "cibai", "cibay", "cocot", + "cocote", "cok", + "cokil", + "colai", "coli", "colmek", - "congor", "cuk", "cuki", "cukimai", + "cukimak", "cukimay", - "cukin", + "damput", + "dancik", "dancok", "dancuk", - "dientot", - "dientotin", + "diancuk", + "dongo", + "dongok", + "encuk", "entot", "ewe", - "gathel", - "gatheli", "gembel", "goblog", + "goblognya", "goblok", + "heang", "hencet", "henceut", "idiot", - "indonesiansentinel", + "itil", "jablai", "jablay", "jancik", "jancok", + "jancokmu", + "jancoknya", + "jancox", "jancuk", - "jancur", + "jancukmu", + "jancuknya", + "jancux", + "jembot", "jembut", + "jembutmu", + "jembutnya", + "jing", + "jingan", "kacuk", "kampang", "kampret", + "kampretmu", "kanciang", + "kelentit", + "kemem", "keparat", + "keparatnya", "kimak", - "kimcil", - "kintil", + "kimakmu", + "kimaknya", + "kimbek", + "kimpet", "kirik", + "klentit", "kolop", "konthol", "kontol", + "kontolan", + "kontolkau", + "kontollo", + "kontollu", + "kontolmu", + "kontolnya", "koplok", "kunyuk", "kwontol", + "ler", "lonte", + "lonteh", + "lotnok", "mampus", - "meki", + "mek", "memek", - "mengentot", - "mengentoti", - "mengentotin", + "memekmu", + "memeknya", "modar", + "modyar", + "mokad", "monyet", + "ndas", "ndasmu", + "ndhas", "ndhasmu", + "ndlogok", "nenen", - "ngehe", + "ngentod", "ngentot", - "ngentotin", + "ngentotnya", "ngewe", + "nggateli", + "ngolom", "ngulum", + "njing", + "njir", + "ogeb", + "palkon", + "palkor", "pantat", "pantek", - "pecun", - "peju", + "pantekmu", + "panteknya", + "pekok", + "pekokmu", "peler", + "pelerkau", + "pelerlo", + "pelerlu", + "pelermu", "pentil", "pepek", + "pepeklo", + "pepeklu", + "pepekmu", + "pepeknya", "perek", - "pilat", + "pler", "puki", + "pukima", "pukimak", + "pukimaknya", "qontol", + "sange", "sarap", + "sat", "sempak", + "setan", "sial", "sialan", + "sialanmu", "silit", "sinting", - "sompret", "sontoloyo", - "sundal", "taek", + "taeknya", "tahi", "tai", - "tailaso", + "taiayam", + "taik", + "taiklo", + "taiklu", + "taikmu", + "taiknya", "telaso", + "telek", "tempek", "tempik", + "tete", "tetek", "titit", + "tititmu", + "titiw", "toket", + "toketmu", "tolol", - "totong", + "tolollo", + "tolollu", + "tololmu", + "tololnya", + "tot", "tusbol", + "wedus", ] as const); -export const version = "0.2.0"; +export const version = "0.3.0"; diff --git a/packages/profanity-kit/src/index.test.ts b/packages/profanity-kit/src/index.test.ts index 58f9140..52c1943 100644 --- a/packages/profanity-kit/src/index.test.ts +++ b/packages/profanity-kit/src/index.test.ts @@ -11,16 +11,16 @@ describe("public entry points", () => { const detector = createDetector(); expectTypeOf(detector).toEqualTypeOf>(); - expect(detector.check("englishsentinel")).toBe(true); - expect(detector.check("indonesiansentinel")).toBe(false); + expect(detector.check("bullshit")).toBe(true); + expect(detector.check("brengsek")).toBe(false); }); it("keeps core dictionary-free and infers explicit language codes", () => { const detector = createCoreDetector({ languages: [indonesian] }); expectTypeOf(detector).toEqualTypeOf>(); - expect(detector.check("indonesiansentinel")).toBe(true); - expect(detector.check("englishsentinel")).toBe(false); + expect(detector.check("brengsek")).toBe(true); + expect(detector.check("bullshit")).toBe(false); }); it("freezes built-in pack data", () => { @@ -38,7 +38,7 @@ describe("public entry points", () => { ); }); - it("detects expanded English dictionary entries added in v0.2.0", () => { + it("detects reviewed English dictionary entries", () => { const detector = createDetector(); expect(detector.check("dickhead")).toBe(true); @@ -55,7 +55,7 @@ describe("public entry points", () => { ).toEqual(["crap", "dumbass", "fucking", "wanker"]); }); - it("detects expanded Indonesian dictionary entries added in v0.2.0", () => { + it("detects reviewed Indonesian dictionary entries", () => { const detector = createCoreDetector({ languages: [indonesian] }); expect(detector.check("bajingan")).toBe(true); @@ -71,7 +71,7 @@ describe("public entry points", () => { ).toEqual(["brengsek", "kampret", "goblok", "jancuk"]); }); - it("keeps English and Indonesian expanded packs isolated", () => { + it("keeps built-in English and Indonesian packs isolated", () => { const enDetector = createDetector(); const idDetector = createCoreDetector({ languages: [indonesian] }); @@ -82,4 +82,14 @@ describe("public entry points", () => { expect(mixed.check("brengsek")).toBe(true); expect(mixed.check("bullshit")).toBe(true); }); + + it("keeps intentionally excluded variants clean", () => { + const enDetector = createDetector(); + const idDetector = createCoreDetector({ languages: [indonesian] }); + + expect(enDetector.check("fuk")).toBe(false); + expect(enDetector.check("fuck")).toBe(true); + expect(idDetector.check("ngentotin")).toBe(false); + expect(idDetector.check("ngentot")).toBe(true); + }); }); From b65b63e53672246e497f66642611ec2069289bf3 Mon Sep 17 00:00:00 2001 From: up2dul Date: Sun, 13 Sep 2026 20:06:59 +0700 Subject: [PATCH 2/4] docs: emphasize multilingual language packs --- CONTRIBUTING.md | 2 + README.md | 53 ++++++++++++------- .../content/docs/core-concepts/languages.mdx | 27 ++++++++++ apps/docs/src/content/docs/index.mdx | 23 ++++++-- apps/docs/src/content/docs/quick-start.mdx | 23 +++++++- packages/profanity-kit/README.md | 53 ++++++++++++------- 6 files changed, 139 insertions(+), 42 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cd3a9e6..f4c511a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -39,6 +39,8 @@ To change an existing language dictionary: To add a new language pack: +- Open an issue before beginning substantial corpus work so scope and review + expectations can be agreed first. - Create `dictionaries//words.txt` and `metadata.json`. - Run `pnpm dictionary:generate` to create the generated module. - Add `packages/profanity-kit/src/languages/.ts` and expose it in diff --git a/README.md b/README.md index 2192be6..e2009bd 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Quality MIT License Node.js 22.13.0 or newer - Pre-release + npm version

@@ -23,31 +23,43 @@ GitHub

-Profanity Kit provides predictable, synchronous word filtering without a -moderation service or an opaque machine-learning model. It is a deterministic -profanity detection toolkit, not a contextual moderation or toxicity -classifier. +Profanity Kit is a language-pack-based profanity detection toolkit built for +multilingual applications. Select and combine only the languages you need, or +provide custom packs for specific communities. English and Indonesian packs +are available today, with **more built-in languages coming soon!** + +It provides predictable, synchronous word filtering without a moderation +service or an opaque machine-learning model. It is a deterministic profanity +detection toolkit, not a contextual moderation or toxicity classifier. ## Why Profanity Kit? - Unicode-aware, whole-word matching -- Explicit, bundle-friendly language packs +- Built-in English and Indonesian packs, with more languages planned +- Explicit, bundle-friendly multilingual configuration - Detailed match metadata with source offsets - Immutable detector configuration - Synchronous and runtime agnostic - Zero runtime dependencies -## Installation +## Available languages -> Profanity Kit is in pre-release. The `next` channel will become available -> during the release rehearsal. +| Language | Import | +| ---------- | ---------------------------- | +| English | `profanity-kit/languages/en` | +| Indonesian | `profanity-kit/languages/id` | -| Package manager | Command | -| --------------- | -------------------------------- | -| npm | `npm install profanity-kit@next` | -| pnpm | `pnpm add profanity-kit@next` | -| Yarn | `yarn add profanity-kit@next` | -| Bun | `bun add profanity-kit@next` | +Language packs can be used independently or combined in one detector. Custom +packs support additional languages and communities. + +## Installation + +| Package manager | Command | +| --------------- | --------------------------- | +| npm | `npm install profanity-kit` | +| pnpm | `pnpm add profanity-kit` | +| Yarn | `yarn add profanity-kit` | +| Bun | `bun add profanity-kit` | ## Quick start @@ -62,18 +74,23 @@ detector.check("This contains shit"); // true detector.filter("Hide the shit"); // "Hide the ****" ``` -Use the dictionary-free core when selecting another language explicitly: +Use the dictionary-free core to combine the built-in English and Indonesian +language packs: ```ts import { createDetector } from "profanity-kit/core"; +import { english } from "profanity-kit/languages/en"; import { indonesian } from "profanity-kit/languages/id"; -const detector = createDetector({ languages: [indonesian] }); +const detector = createDetector({ languages: [english, indonesian] }); +detector.check("This contains shit"); // true detector.check("Dasar goblok"); // true -detector.filter("Dasar goblok"); // "Dasar ******" ``` +Load either pack independently when only one language is needed, or supply a +custom language pack for another language or community. + ## Learn more - [Quick Start](https://profanity-kit.up2dul.dev/quick-start) diff --git a/apps/docs/src/content/docs/core-concepts/languages.mdx b/apps/docs/src/content/docs/core-concepts/languages.mdx index 3971a6d..5df30ed 100644 --- a/apps/docs/src/content/docs/core-concepts/languages.mdx +++ b/apps/docs/src/content/docs/core-concepts/languages.mdx @@ -8,6 +8,19 @@ sidebar: Profanity Kit separates its detector engine from language dictionaries. Choose the entry point based on who should control the language data. +English and Indonesian are available as built-in language packs today. You can +use either independently, combine both for multilingual input, or provide a +custom pack for another language or community. + +## Available languages + +| Language | Import | +| ---------- | ---------------------------- | +| English | `profanity-kit/languages/en` | +| Indonesian | `profanity-kit/languages/id` | + +## Choose an entry point + | Import | Dictionaries | Best for | | -------------------- | -------------------------- | ----------------------------------------------------------------- | | `profanity-kit` | English included | English-only applications and shortest setup | @@ -82,3 +95,17 @@ selection or bundle composition should be explicit. You can also supply a custom [`LanguagePack`](/api/types#languagepack). See [Customization](/guides/customization#create-a-custom-language-pack) for a complete example. + +## More languages + +More built-in language packs are planned, but there is no committed language +list or release schedule. Until a built-in pack is available, applications can +provide a custom language pack through the same core API. + +Native speakers and community reviewers are welcome to propose or contribute a +new built-in pack. Open a +[GitHub issue](https://github.com/up2dul/profanity-kit/issues) before beginning +substantial corpus work, then follow the +[contribution guide](https://github.com/up2dul/profanity-kit/blob/main/CONTRIBUTING.md#dictionary-contributions) +and +[dictionary review policy](https://github.com/up2dul/profanity-kit/blob/main/dictionaries/README.md). diff --git a/apps/docs/src/content/docs/index.mdx b/apps/docs/src/content/docs/index.mdx index d1154db..e9efe29 100644 --- a/apps/docs/src/content/docs/index.mdx +++ b/apps/docs/src/content/docs/index.mdx @@ -1,6 +1,6 @@ --- title: Profanity Kit -description: A small, Unicode-aware profanity detector for TypeScript. +description: A multilingual, Unicode-aware profanity detector for TypeScript. sidebar: order: 1 badge: Start here @@ -8,10 +8,14 @@ sidebar: ## Introduction -Profanity Kit is a TypeScript toolkit for detecting configured profane words as -complete, Unicode-aware tokens. It provides detection mechanisms, language -dictionaries, and customization primitives—not a universal list that every -application must reject. +Profanity Kit is a language-pack-based TypeScript toolkit built for multilingual +applications. Select and combine only the languages you need, or provide custom +packs for specific communities. English and Indonesian packs are available +today, with more built-in packs planned. + +It detects configured profane words as complete, Unicode-aware tokens and +provides customization primitives—not a universal list that every application +must reject. "Profanity" commonly means language considered offensive or taboo in a social context; its meaning and impact vary by community and situation. See the @@ -39,4 +43,13 @@ That variation is why dictionaries stay explicit and detectors immutable. Try matching interactively + +
Languages & Dictionaries
+
+ Use English, Indonesian, or custom packs +
+
diff --git a/apps/docs/src/content/docs/quick-start.mdx b/apps/docs/src/content/docs/quick-start.mdx index ec725ff..b044019 100644 --- a/apps/docs/src/content/docs/quick-start.mdx +++ b/apps/docs/src/content/docs/quick-start.mdx @@ -24,7 +24,28 @@ detector.filter("hide the shit"); // "hide the ****" ``` `findAll()` returns ordered match details when you need offsets or language -codes. Next, choose [languages](/core-concepts/languages) or learn [matching](/core-concepts/matching). +codes. + +## Combine languages + +Profanity Kit includes built-in English and Indonesian packs. Import the +dictionary-free core to use either pack independently or combine them in one +detector: + +```ts +import { createDetector } from "profanity-kit/core"; +import { english } from "profanity-kit/languages/en"; +import { indonesian } from "profanity-kit/languages/id"; + +const detector = createDetector({ languages: [english, indonesian] }); + +detector.check("This contains shit"); // true +detector.check("Dasar goblok"); // true +``` + +See [Languages & Dictionaries](/core-concepts/languages) to select one pack, +combine packs, or create a custom pack. You can also learn how +[matching works](/core-concepts/matching). ## Compatibility diff --git a/packages/profanity-kit/README.md b/packages/profanity-kit/README.md index 2192be6..e2009bd 100644 --- a/packages/profanity-kit/README.md +++ b/packages/profanity-kit/README.md @@ -14,7 +14,7 @@ Quality MIT License Node.js 22.13.0 or newer - Pre-release + npm version

@@ -23,31 +23,43 @@ GitHub

-Profanity Kit provides predictable, synchronous word filtering without a -moderation service or an opaque machine-learning model. It is a deterministic -profanity detection toolkit, not a contextual moderation or toxicity -classifier. +Profanity Kit is a language-pack-based profanity detection toolkit built for +multilingual applications. Select and combine only the languages you need, or +provide custom packs for specific communities. English and Indonesian packs +are available today, with **more built-in languages coming soon!** + +It provides predictable, synchronous word filtering without a moderation +service or an opaque machine-learning model. It is a deterministic profanity +detection toolkit, not a contextual moderation or toxicity classifier. ## Why Profanity Kit? - Unicode-aware, whole-word matching -- Explicit, bundle-friendly language packs +- Built-in English and Indonesian packs, with more languages planned +- Explicit, bundle-friendly multilingual configuration - Detailed match metadata with source offsets - Immutable detector configuration - Synchronous and runtime agnostic - Zero runtime dependencies -## Installation +## Available languages -> Profanity Kit is in pre-release. The `next` channel will become available -> during the release rehearsal. +| Language | Import | +| ---------- | ---------------------------- | +| English | `profanity-kit/languages/en` | +| Indonesian | `profanity-kit/languages/id` | -| Package manager | Command | -| --------------- | -------------------------------- | -| npm | `npm install profanity-kit@next` | -| pnpm | `pnpm add profanity-kit@next` | -| Yarn | `yarn add profanity-kit@next` | -| Bun | `bun add profanity-kit@next` | +Language packs can be used independently or combined in one detector. Custom +packs support additional languages and communities. + +## Installation + +| Package manager | Command | +| --------------- | --------------------------- | +| npm | `npm install profanity-kit` | +| pnpm | `pnpm add profanity-kit` | +| Yarn | `yarn add profanity-kit` | +| Bun | `bun add profanity-kit` | ## Quick start @@ -62,18 +74,23 @@ detector.check("This contains shit"); // true detector.filter("Hide the shit"); // "Hide the ****" ``` -Use the dictionary-free core when selecting another language explicitly: +Use the dictionary-free core to combine the built-in English and Indonesian +language packs: ```ts import { createDetector } from "profanity-kit/core"; +import { english } from "profanity-kit/languages/en"; import { indonesian } from "profanity-kit/languages/id"; -const detector = createDetector({ languages: [indonesian] }); +const detector = createDetector({ languages: [english, indonesian] }); +detector.check("This contains shit"); // true detector.check("Dasar goblok"); // true -detector.filter("Dasar goblok"); // "Dasar ******" ``` +Load either pack independently when only one language is needed, or supply a +custom language pack for another language or community. + ## Learn more - [Quick Start](https://profanity-kit.up2dul.dev/quick-start) From e87a184e298112bfe9079fcc0160f8ff6620d0f4 Mon Sep 17 00:00:00 2001 From: up2dul Date: Sun, 13 Sep 2026 20:34:02 +0700 Subject: [PATCH 3/4] fix(release): replace stale sentinel validations --- reports/bundles/phase-2.json | 32 ++++++++++++++--------------- scripts/measure-bundles.mjs | 18 ++++++---------- scripts/validate-package.mjs | 12 +++++------ scripts/verify-registry-release.mjs | 4 ++-- 4 files changed, 30 insertions(+), 36 deletions(-) diff --git a/reports/bundles/phase-2.json b/reports/bundles/phase-2.json index ab7073c..49f919d 100644 --- a/reports/bundles/phase-2.json +++ b/reports/bundles/phase-2.json @@ -13,28 +13,28 @@ "brotli": 1591 }, "root": { - "raw": 10962, - "minified": 7070, - "gzip": 2539, - "brotli": 2295 + "raw": 14303, + "minified": 9495, + "gzip": 3298, + "brotli": 2971 }, "english": { - "raw": 3374, - "minified": 2374, - "gzip": 897, - "brotli": 875 + "raw": 6568, + "minified": 4652, + "gzip": 1634, + "brotli": 1545 }, "indonesian": { - "raw": 1639, - "minified": 1152, - "gzip": 627, - "brotli": 587 + "raw": 2769, + "minified": 1902, + "gzip": 906, + "brotli": 847 }, "combined": { - "raw": 12148, - "minified": 7846, - "gzip": 2959, - "brotli": 2661 + "raw": 16570, + "minified": 10874, + "gzip": 3954, + "brotli": 3561 } }, "assertions": { diff --git a/scripts/measure-bundles.mjs b/scripts/measure-bundles.mjs index 007ef91..466ca15 100644 --- a/scripts/measure-bundles.mjs +++ b/scripts/measure-bundles.mjs @@ -121,27 +121,21 @@ try { join(outputDirectory, "combined.min.js"), "utf8" ); - if ( - coreBundle.includes("englishsentinel") || - coreBundle.includes("indonesiansentinel") - ) { + if (coreBundle.includes("bullshit") || coreBundle.includes("brengsek")) { throw new Error("Core bundle contains built-in dictionary data"); } - if ( - !rootBundle.includes("englishsentinel") || - rootBundle.includes("indonesiansentinel") - ) { + if (!rootBundle.includes("bullshit") || rootBundle.includes("brengsek")) { throw new Error("Root bundle language isolation failed"); } if ( - !indonesianBundle.includes("indonesiansentinel") || - indonesianBundle.includes("englishsentinel") + !indonesianBundle.includes("brengsek") || + indonesianBundle.includes("bullshit") ) { throw new Error("Indonesian bundle language isolation failed"); } if ( - !combinedBundle.includes("englishsentinel") || - !combinedBundle.includes("indonesiansentinel") + !combinedBundle.includes("bullshit") || + !combinedBundle.includes("brengsek") ) { throw new Error("Combined bundle is missing language data"); } diff --git a/scripts/validate-package.mjs b/scripts/validate-package.mjs index c98ed8f..ec744f2 100644 --- a/scripts/validate-package.mjs +++ b/scripts/validate-package.mjs @@ -74,9 +74,9 @@ import { createDetector as createCoreDetector } from "profanity-kit/core"; import { english } from "profanity-kit/languages/en"; import { indonesian } from "profanity-kit/languages/id"; -if (!createDetector().check("englishsentinel")) throw new Error("root ESM failed"); -if (!createCoreDetector({ languages: [english] }).check("englishsentinel")) throw new Error("English ESM failed"); -if (!createCoreDetector({ languages: [indonesian] }).check("indonesiansentinel")) throw new Error("Indonesian ESM failed"); +if (!createDetector().check("bullshit")) throw new Error("root ESM failed"); +if (!createCoreDetector({ languages: [english] }).check("bullshit")) throw new Error("English ESM failed"); +if (!createCoreDetector({ languages: [indonesian] }).check("brengsek")) throw new Error("Indonesian ESM failed"); ` ); writeFileSync( @@ -86,8 +86,8 @@ const { createDetector: createCoreDetector } = require("profanity-kit/core"); const { english } = require("profanity-kit/languages/en"); const { indonesian } = require("profanity-kit/languages/id"); -if (!createDetector().check("englishsentinel")) throw new Error("root require failed"); -if (!createCoreDetector({ languages: [english, indonesian] }).check("indonesiansentinel")) throw new Error("combined require failed"); +if (!createDetector().check("bullshit")) throw new Error("root require failed"); +if (!createCoreDetector({ languages: [english, indonesian] }).check("brengsek")) throw new Error("combined require failed"); ` ); run(process.execPath, [join(temporaryDirectory, "esm.mjs")]); @@ -139,7 +139,7 @@ createDetector({ languages: [indonesian] }); join(temporaryDirectory, "vite-entry.ts"), `import { createDetector } from "profanity-kit/core"; import { indonesian } from "profanity-kit/languages/id"; -document.body.textContent = String(createDetector({ languages: [indonesian] }).check("indonesiansentinel")); +document.body.textContent = String(createDetector({ languages: [indonesian] }).check("brengsek")); ` ); run( diff --git a/scripts/verify-registry-release.mjs b/scripts/verify-registry-release.mjs index a01a6dc..b0e0594 100644 --- a/scripts/verify-registry-release.mjs +++ b/scripts/verify-registry-release.mjs @@ -77,8 +77,8 @@ try { import { createDetector as createCoreDetector } from "profanity-kit/core"; import { indonesian } from "profanity-kit/languages/id"; -if (!createDetector().check("englishsentinel")) throw new Error("root registry import failed"); -if (!createCoreDetector({ languages: [indonesian] }).check("indonesiansentinel")) throw new Error("language registry import failed"); +if (!createDetector().check("bullshit")) throw new Error("root registry import failed"); +if (!createCoreDetector({ languages: [indonesian] }).check("brengsek")) throw new Error("language registry import failed"); ` ); run(process.execPath, [join(temporaryDirectory, "verify.mjs")], { From 2b5e37fc77c4c9b7f04018fc8e7fc87d9e259110 Mon Sep 17 00:00:00 2001 From: up2dul Date: Sun, 13 Sep 2026 20:37:04 +0700 Subject: [PATCH 4/4] test(performance): refresh dictionary benchmark baseline --- reports/performance/phase-4.json | 40 ++++++++++++++++---------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/reports/performance/phase-4.json b/reports/performance/phase-4.json index fa23881..50468cf 100644 --- a/reports/performance/phase-4.json +++ b/reports/performance/phase-4.json @@ -6,66 +6,66 @@ "samples": 5, "measurements": { "initialization.english": { - "medianMs": 595.503 + "medianMs": 1101.126 }, "initialization.oneLanguage": { - "medianMs": 288.682 + "medianMs": 498.971 }, "initialization.multipleLanguages": { - "medianMs": 889.429 + "medianMs": 1610.948 }, "check.shortNoMatch": { - "medianMs": 4.453 + "medianMs": 4.052 }, "check.shortEarlyMatch": { - "medianMs": 3.531 + "medianMs": 2.295 }, "check.longNoMatch": { - "medianMs": 612.804 + "medianMs": 575.046 }, "check.longLateMatch": { - "medianMs": 616.932 + "medianMs": 567.576 }, "findAll.repeatedMatches": { - "medianMs": 10.722 + "medianMs": 7.968 }, "check.indonesian": { - "medianMs": 5.612 + "medianMs": 5.162 }, "check.combined": { - "medianMs": 3.987 + "medianMs": 3.56 } }, "budgets": { "initialization.english": { - "maxMedianMs": 1786.509 + "maxMedianMs": 3303.378 }, "initialization.oneLanguage": { - "maxMedianMs": 866.046 + "maxMedianMs": 1496.913 }, "initialization.multipleLanguages": { - "maxMedianMs": 2668.287 + "maxMedianMs": 4832.844 }, "check.shortNoMatch": { - "maxMedianMs": 13.359 + "maxMedianMs": 12.156 }, "check.shortEarlyMatch": { - "maxMedianMs": 10.593 + "maxMedianMs": 6.885 }, "check.longNoMatch": { - "maxMedianMs": 1838.412 + "maxMedianMs": 1725.138 }, "check.longLateMatch": { - "maxMedianMs": 1850.796 + "maxMedianMs": 1702.728 }, "findAll.repeatedMatches": { - "maxMedianMs": 32.166 + "maxMedianMs": 23.904 }, "check.indonesian": { - "maxMedianMs": 16.836 + "maxMedianMs": 15.486 }, "check.combined": { - "maxMedianMs": 11.961 + "maxMedianMs": 10.68 } }, "comparison": {