censorship-id 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,71 @@
1
+ # censorship-id
2
+
3
+ [![npm version](https://img.shields.io/npm/v/censorship-id.svg?style=flat-square)](https://www.npmjs.com/package/censorship-id)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ A robust and simple npm package for detecting and masking Indonesian profanity, slang, and inappropriate words.
7
+
8
+ ## Features
9
+
10
+ - **Comprehensive Dictionary**: Pre-loaded with hundreds of common Indonesian bad words.
11
+ - **Regex Powered**: Uses word boundaries to avoid false positives (e.g., masking "tai" but not "pantai").
12
+ - **Customizable**: Add your own words to the list and choose your mask character.
13
+ - **Keep First and Last**: Option to keep the first and last letters visible for better context.
14
+ - **Case-Insensitive**: Matches words regardless of their case.
15
+ - **Lightweight**: Zero dependencies (only uses Jest for development).
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ npm install censorship-id
21
+ ```
22
+
23
+ ## Usage
24
+
25
+ ### Basic Usage
26
+
27
+ ```javascript
28
+ const { censorId } = require('censorship-id');
29
+
30
+ const text = "Dasar anjing kau, babi!";
31
+ const censored = censorId(text);
32
+ console.log(censored);
33
+ // Output: Dasar ****** kau, ****!
34
+ ```
35
+
36
+ ### Advanced Usage (Options)
37
+
38
+ ```javascript
39
+ const { censorId } = require('censorship-id');
40
+
41
+ const text = "Dasar anjing kau, babi!";
42
+
43
+ // 1. Using a custom mask
44
+ const customMask = censorId(text, { mask: '#' });
45
+ console.log(customMask);
46
+ // Output: Dasar ###### kau, ####!
47
+
48
+ // 2. Keeping first and last letters
49
+ const visible = censorId(text, { keepFirstAndLast: true });
50
+ console.log(visible);
51
+ // Output: Dasar a****g kau, b**i!
52
+
53
+ // 3. Adding custom words to censor
54
+ const customWords = censorId("Kamu sangat malas!", { customWords: ['malas'] });
55
+ console.log(customWords);
56
+ // Output: Kamu sangat *****!
57
+ ```
58
+
59
+ ## API Reference
60
+
61
+ ### `censorId(text, options)`
62
+
63
+ - **`text`** (string): The input text to be filtered.
64
+ - **`options`** (object): Optional configuration.
65
+ - **`mask`** (string): The character used to mask words (default: `*`).
66
+ - **`customWords`** (string[]): Additional words to censor.
67
+ - **`keepFirstAndLast`** (boolean): If `true`, the first and last letters of the word remain visible (default: `false`).
68
+
69
+ ## License
70
+
71
+ MIT © [rheatkhs](https://github.com/rheatkhs)
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Options for the censorship filter.
3
+ */
4
+ interface CensorIdOptions {
5
+ /**
6
+ * The character used to mask the words.
7
+ * @default '*'
8
+ */
9
+ mask?: string;
10
+
11
+ /**
12
+ * An array of additional words to censor.
13
+ */
14
+ customWords?: string[];
15
+
16
+ /**
17
+ * If true, keeps the first and last letters visible (e.g., "a****g").
18
+ * @default false
19
+ */
20
+ keepFirstAndLast?: boolean;
21
+ }
22
+
23
+ /**
24
+ * Censors Indonesian profanity and inappropriate words from the given text.
25
+ *
26
+ * @param text The input text to be filtered.
27
+ * @param options Configuration for filtering behavior.
28
+ * @returns The censored text.
29
+ */
30
+ declare function censorId(text: string, options?: CensorIdOptions): string;
31
+ declare function censorId<T>(text: T, options?: CensorIdOptions): T;
32
+
33
+ /**
34
+ * The default dictionary of Indonesian profanity used by the filter.
35
+ */
36
+ declare const dictionary: string[];
37
+
38
+ export { type CensorIdOptions, censorId, dictionary };
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Options for the censorship filter.
3
+ */
4
+ interface CensorIdOptions {
5
+ /**
6
+ * The character used to mask the words.
7
+ * @default '*'
8
+ */
9
+ mask?: string;
10
+
11
+ /**
12
+ * An array of additional words to censor.
13
+ */
14
+ customWords?: string[];
15
+
16
+ /**
17
+ * If true, keeps the first and last letters visible (e.g., "a****g").
18
+ * @default false
19
+ */
20
+ keepFirstAndLast?: boolean;
21
+ }
22
+
23
+ /**
24
+ * Censors Indonesian profanity and inappropriate words from the given text.
25
+ *
26
+ * @param text The input text to be filtered.
27
+ * @param options Configuration for filtering behavior.
28
+ * @returns The censored text.
29
+ */
30
+ declare function censorId(text: string, options?: CensorIdOptions): string;
31
+ declare function censorId<T>(text: T, options?: CensorIdOptions): T;
32
+
33
+ /**
34
+ * The default dictionary of Indonesian profanity used by the filter.
35
+ */
36
+ declare const dictionary: string[];
37
+
38
+ export { type CensorIdOptions, censorId, dictionary };
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ var f=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var i=f((m,a)=>{var j=["anjing","asu","babi","bangsat","bajing","bajingan","bedebah","berak","bejat","brengsek","buto","cuk","dancuk","entot","goblok","itil","jancuk","jembut","kontol","kunyuk","lonte","memek","monyet","ngentot","pantat","perek","puki","setan","siak","sinting","tai","tolol"];a.exports=j});var c=i();function y(t,e={}){if(typeof t!="string")return t;let{mask:r="*",customWords:g=[],keepFirstAndLast:l=!1}=e,u=[...new Set([...c,...g])].map(s=>s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")),o=t;return u.forEach(s=>{let d=new RegExp(`(?<=\\s|^|[^a-zA-Z0-9])${s}(?=\\s|$|[^a-zA-Z0-9])`,"gi");o=o.replace(d,n=>{if(l&&n.length>2){let k=n[0],p=n[n.length-1],b=r.repeat(n.length-2);return k+b+p}return r.repeat(n.length)})}),o}module.exports={censorId:y,dictionary:c};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../dictionary.js","../index.js"],"sourcesContent":["/**\r\n * A comprehensive list of common Indonesian profanity, slang, and inappropriate words.\r\n */\r\nconst dictionary = [\r\n \"anjing\",\r\n \"asu\",\r\n \"babi\",\r\n \"bangsat\",\r\n \"bajing\",\r\n \"bajingan\",\r\n \"bedebah\",\r\n \"berak\",\r\n \"bejat\",\r\n \"brengsek\",\r\n \"buto\",\r\n \"cuk\",\r\n \"dancuk\",\r\n \"entot\",\r\n \"goblok\",\r\n \"itil\",\r\n \"jancuk\",\r\n \"jembut\",\r\n \"kontol\",\r\n \"kunyuk\",\r\n \"lonte\",\r\n \"memek\",\r\n \"monyet\",\r\n \"ngentot\",\r\n \"pantat\",\r\n \"perek\",\r\n \"puki\",\r\n \"setan\",\r\n \"siak\",\r\n \"sinting\",\r\n \"tai\",\r\n \"tolol\"\r\n];\r\n\r\nmodule.exports = dictionary;\r\n","const defaultDictionary = require(\"./dictionary\");\r\n\r\n/**\r\n * Censor Indonesian profanity and inappropriate words.\r\n *\r\n * @param {string} text - The input text to be filtered.\r\n * @param {object} options - Filtering options.\r\n * @param {string} options.mask - The character used to mask the words (default is '*').\r\n * @param {string[]} options.customWords - An array of additional words to censor.\r\n * @param {boolean} options.keepFirstAndLast - If true, keeps the first and last letters visible (default is false).\r\n * @returns {string} - The censored text.\r\n */\r\nfunction censorId(text, options = {}) {\r\n if (typeof text !== \"string\") {\r\n return text;\r\n }\r\n\r\n const {\r\n mask = \"*\",\r\n customWords = [],\r\n keepFirstAndLast = false\r\n } = options;\r\n\r\n // Merge default dictionary with custom words\r\n const wordsToCensor = [...new Set([...defaultDictionary, ...customWords])];\r\n\r\n // Escape special characters in words for safety in Regex\r\n const escapedWords = wordsToCensor.map(word =>\r\n word.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")\r\n );\r\n\r\n let censoredText = text;\r\n\r\n // Iterate over each word and apply masking\r\n escapedWords.forEach(word => {\r\n // Regex with word boundaries (\\b) and case-insensitive flag (i)\r\n // Note: \\b doesn't work well with non-ASCII characters, but for Indonesian it's generally fine.\r\n // However, for more robustness with various symbols, we use a pattern that matches word start/end.\r\n const regex = new RegExp(`(?<=\\\\s|^|[^a-zA-Z0-9])${word}(?=\\\\s|$|[^a-zA-Z0-9])`, \"gi\");\r\n\r\n censoredText = censoredText.replace(regex, (match) => {\r\n if (keepFirstAndLast && match.length > 2) {\r\n const first = match[0];\r\n const last = match[match.length - 1];\r\n const middle = mask.repeat(match.length - 2);\r\n return first + middle + last;\r\n }\r\n return mask.repeat(match.length);\r\n });\r\n });\r\n\r\n return censoredText;\r\n}\r\n\r\nmodule.exports = {\r\n censorId,\r\n dictionary: defaultDictionary\r\n};\r\n"],"mappings":"8DAAA,IAAAA,EAAAC,EAAA,CAAAC,EAAAC,IAAA,CAGA,IAAMC,EAAa,CACjB,SACA,MACA,OACA,UACA,SACA,WACA,UACA,QACA,QACA,WACA,OACA,MACA,SACA,QACA,SACA,OACA,SACA,SACA,SACA,SACA,QACA,QACA,SACA,UACA,SACA,QACA,OACA,QACA,OACA,UACA,MACA,OACF,EAEAD,EAAO,QAAUC,ICtCjB,IAAMC,EAAoB,IAY1B,SAASC,EAASC,EAAMC,EAAU,CAAC,EAAG,CAClC,GAAI,OAAOD,GAAS,SAChB,OAAOA,EAGX,GAAM,CACF,KAAAE,EAAO,IACP,YAAAC,EAAc,CAAC,EACf,iBAAAC,EAAmB,EACvB,EAAIH,EAMEI,EAHgB,CAAC,GAAG,IAAI,IAAI,CAAC,GAAGP,EAAmB,GAAGK,CAAW,CAAC,CAAC,EAGtC,IAAIG,GACnCA,EAAK,QAAQ,sBAAuB,MAAM,CAC9C,EAEIC,EAAeP,EAGnB,OAAAK,EAAa,QAAQC,GAAQ,CAIzB,IAAME,EAAQ,IAAI,OAAO,0BAA0BF,CAAI,yBAA0B,IAAI,EAErFC,EAAeA,EAAa,QAAQC,EAAQC,GAAU,CAClD,GAAIL,GAAoBK,EAAM,OAAS,EAAG,CACtC,IAAMC,EAAQD,EAAM,CAAC,EACfE,EAAOF,EAAMA,EAAM,OAAS,CAAC,EAC7BG,EAASV,EAAK,OAAOO,EAAM,OAAS,CAAC,EAC3C,OAAOC,EAAQE,EAASD,CAC5B,CACA,OAAOT,EAAK,OAAOO,EAAM,MAAM,CACnC,CAAC,CACL,CAAC,EAEMF,CACX,CAEA,OAAO,QAAU,CACb,SAAAR,EACA,WAAYD,CAChB","names":["require_dictionary","__commonJSMin","exports","module","dictionary","defaultDictionary","censorId","text","options","mask","customWords","keepFirstAndLast","escapedWords","word","censoredText","regex","match","first","last","middle"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,2 @@
1
+ var a=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var c=a((A,i)=>{var y=["anjing","asu","babi","bangsat","bajing","bajingan","bedebah","berak","bejat","brengsek","buto","cuk","dancuk","entot","goblok","itil","jancuk","jembut","kontol","kunyuk","lonte","memek","monyet","ngentot","pantat","perek","puki","setan","siak","sinting","tai","tolol"];i.exports=y});var $=a((T,l)=>{var g=c();function w(t,e={}){if(typeof t!="string")return t;let{mask:r="*",customWords:u=[],keepFirstAndLast:d=!1}=e,k=[...new Set([...g,...u])].map(s=>s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")),o=t;return k.forEach(s=>{let p=new RegExp(`(?<=\\s|^|[^a-zA-Z0-9])${s}(?=\\s|$|[^a-zA-Z0-9])`,"gi");o=o.replace(p,n=>{if(d&&n.length>2){let b=n[0],f=n[n.length-1],j=r.repeat(n.length-2);return b+j+f}return r.repeat(n.length)})}),o}l.exports={censorId:w,dictionary:g}});export default $();
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../dictionary.js","../index.js"],"sourcesContent":["/**\r\n * A comprehensive list of common Indonesian profanity, slang, and inappropriate words.\r\n */\r\nconst dictionary = [\r\n \"anjing\",\r\n \"asu\",\r\n \"babi\",\r\n \"bangsat\",\r\n \"bajing\",\r\n \"bajingan\",\r\n \"bedebah\",\r\n \"berak\",\r\n \"bejat\",\r\n \"brengsek\",\r\n \"buto\",\r\n \"cuk\",\r\n \"dancuk\",\r\n \"entot\",\r\n \"goblok\",\r\n \"itil\",\r\n \"jancuk\",\r\n \"jembut\",\r\n \"kontol\",\r\n \"kunyuk\",\r\n \"lonte\",\r\n \"memek\",\r\n \"monyet\",\r\n \"ngentot\",\r\n \"pantat\",\r\n \"perek\",\r\n \"puki\",\r\n \"setan\",\r\n \"siak\",\r\n \"sinting\",\r\n \"tai\",\r\n \"tolol\"\r\n];\r\n\r\nmodule.exports = dictionary;\r\n","const defaultDictionary = require(\"./dictionary\");\r\n\r\n/**\r\n * Censor Indonesian profanity and inappropriate words.\r\n *\r\n * @param {string} text - The input text to be filtered.\r\n * @param {object} options - Filtering options.\r\n * @param {string} options.mask - The character used to mask the words (default is '*').\r\n * @param {string[]} options.customWords - An array of additional words to censor.\r\n * @param {boolean} options.keepFirstAndLast - If true, keeps the first and last letters visible (default is false).\r\n * @returns {string} - The censored text.\r\n */\r\nfunction censorId(text, options = {}) {\r\n if (typeof text !== \"string\") {\r\n return text;\r\n }\r\n\r\n const {\r\n mask = \"*\",\r\n customWords = [],\r\n keepFirstAndLast = false\r\n } = options;\r\n\r\n // Merge default dictionary with custom words\r\n const wordsToCensor = [...new Set([...defaultDictionary, ...customWords])];\r\n\r\n // Escape special characters in words for safety in Regex\r\n const escapedWords = wordsToCensor.map(word =>\r\n word.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")\r\n );\r\n\r\n let censoredText = text;\r\n\r\n // Iterate over each word and apply masking\r\n escapedWords.forEach(word => {\r\n // Regex with word boundaries (\\b) and case-insensitive flag (i)\r\n // Note: \\b doesn't work well with non-ASCII characters, but for Indonesian it's generally fine.\r\n // However, for more robustness with various symbols, we use a pattern that matches word start/end.\r\n const regex = new RegExp(`(?<=\\\\s|^|[^a-zA-Z0-9])${word}(?=\\\\s|$|[^a-zA-Z0-9])`, \"gi\");\r\n\r\n censoredText = censoredText.replace(regex, (match) => {\r\n if (keepFirstAndLast && match.length > 2) {\r\n const first = match[0];\r\n const last = match[match.length - 1];\r\n const middle = mask.repeat(match.length - 2);\r\n return first + middle + last;\r\n }\r\n return mask.repeat(match.length);\r\n });\r\n });\r\n\r\n return censoredText;\r\n}\r\n\r\nmodule.exports = {\r\n censorId,\r\n dictionary: defaultDictionary\r\n};\r\n"],"mappings":"8DAAA,IAAAA,EAAAC,EAAA,CAAAC,EAAAC,IAAA,CAGA,IAAMC,EAAa,CACjB,SACA,MACA,OACA,UACA,SACA,WACA,UACA,QACA,QACA,WACA,OACA,MACA,SACA,QACA,SACA,OACA,SACA,SACA,SACA,SACA,QACA,QACA,SACA,UACA,SACA,QACA,OACA,QACA,OACA,UACA,MACA,OACF,EAEAD,EAAO,QAAUC,ICtCjB,IAAAC,EAAAC,EAAA,CAAAC,EAAAC,IAAA,KAAMC,EAAoB,IAY1B,SAASC,EAASC,EAAMC,EAAU,CAAC,EAAG,CAClC,GAAI,OAAOD,GAAS,SAChB,OAAOA,EAGX,GAAM,CACF,KAAAE,EAAO,IACP,YAAAC,EAAc,CAAC,EACf,iBAAAC,EAAmB,EACvB,EAAIH,EAMEI,EAHgB,CAAC,GAAG,IAAI,IAAI,CAAC,GAAGP,EAAmB,GAAGK,CAAW,CAAC,CAAC,EAGtC,IAAIG,GACnCA,EAAK,QAAQ,sBAAuB,MAAM,CAC9C,EAEIC,EAAeP,EAGnB,OAAAK,EAAa,QAAQC,GAAQ,CAIzB,IAAME,EAAQ,IAAI,OAAO,0BAA0BF,CAAI,yBAA0B,IAAI,EAErFC,EAAeA,EAAa,QAAQC,EAAQC,GAAU,CAClD,GAAIL,GAAoBK,EAAM,OAAS,EAAG,CACtC,IAAMC,EAAQD,EAAM,CAAC,EACfE,EAAOF,EAAMA,EAAM,OAAS,CAAC,EAC7BG,EAASV,EAAK,OAAOO,EAAM,OAAS,CAAC,EAC3C,OAAOC,EAAQE,EAASD,CAC5B,CACA,OAAOT,EAAK,OAAOO,EAAM,MAAM,CACnC,CAAC,CACL,CAAC,EAEMF,CACX,CAEAV,EAAO,QAAU,CACb,SAAAE,EACA,WAAYD,CAChB","names":["require_dictionary","__commonJSMin","exports","module","dictionary","require_index","__commonJSMin","exports","module","defaultDictionary","censorId","text","options","mask","customWords","keepFirstAndLast","escapedWords","word","censoredText","regex","match","first","last","middle"]}
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "censorship-id",
3
+ "version": "1.0.0",
4
+ "description": "A robust Indonesian profanity filter for detecting and masking inappropriate words.",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "require": "./dist/index.js",
11
+ "import": "./dist/index.mjs",
12
+ "types": "./dist/index.d.ts"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsup",
20
+ "dev": "tsup --watch",
21
+ "test": "jest",
22
+ "lint": "eslint ."
23
+ },
24
+ "keywords": [
25
+ "indonesia",
26
+ "profanity",
27
+ "filter",
28
+ "sensor",
29
+ "kata kasar",
30
+ "censorship",
31
+ "bahasa-indonesia",
32
+ "slang"
33
+ ],
34
+ "author": "rheatkhs",
35
+ "license": "MIT",
36
+ "engines": {
37
+ "node": ">=12.0.0"
38
+ },
39
+ "devDependencies": {
40
+ "jest": "^29.7.0",
41
+ "tsup": "^8.5.1",
42
+ "typescript": "^6.0.2"
43
+ }
44
+ }