diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..27df642 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,25 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Debug Current Test File", + "autoAttachChildProcesses": true, + "skipFiles": [ + "/**", + "**/node_modules/**" + ], + "program": "${workspaceRoot}/node_modules/vitest/vitest.mjs", + "args": [ + "run", + "${relativeFile}" + ], + "smartStep": true, + "console": "integratedTerminal" + } + ] +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..5c8d9a1 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Fityandhiya Islam Nugroho + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index cea4328..e6832c7 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Wisely -Replace sensitive phrases with special characters to avoid bans. Everyone is free to speak as long as they do so **wisely**. +Obfuscating text or phrases with random uncommon characters to avoid banning. Everyone is free to speak as long as they do so **wisely**. ## Prerequisites @@ -20,11 +20,11 @@ import wisely from 'wisely'; const text = 'Palestine will be free! Freedom is the right of ALL nations!'; -// Replace the whole text +// Obscuring the whole text await wisely({ text }); // Output: P@l3$t|n3 w!ll 83 fr33! Fr33d0m |$ t#3 r!6#t 0f @LL n4t|0n5! -// Only replace the specified phrases +// Only obscures the specified phrases await wisely({ text, phrases: ['palestine', 'free'] }); // Output: P4l35t1n3 will be fr33! Freedom is the right of ALL nations! ``` @@ -33,7 +33,7 @@ await wisely({ text, phrases: ['palestine', 'free'] }); ### wisely(options) -Returns a `Promise` that resolves to a `string` with the replaced text. +Returns a `Promise` that resolves to a `string` with the obsfucated text. #### options @@ -44,34 +44,43 @@ Type: `object` Type: `string` Required: `true` -The text to be replaced. +The text to be obscured. ##### phrases Type: `string[]` \ Required: `false` -The specific phrases to be replaced. If not specified, the whole text will be replaced. +The specific phrases to be obscured. If not specified, the whole text will be obscured. ##### caseSensitive Type: `boolean` \ Default: `false` -Whether to replace the phrases in a case-sensitive manner. +Whether to obscure in a case-sensitive manner. ##### charSet Type: `string` \ Default: `'latin'` \ -Values: `'latin'` +Values: `'latin'` | `'latin-1'` -The character set to be used for replacing. Currently, only the [Basic Latin](https://unicodeplus.com/block/0000) is supported. +The character set that will be used for obfuscation. -> In the future, we will add support for more character sets to improve the variety of the replaced text. Also, we will add support to define custom character sets. +> In the future, we will add support for more character sets to improve the variety of the obsfucated text. Also, we will add support to define custom character sets. ## Support This Project Give a ⭐️ if this project helped you! Also please consider supporting this project by **becoming a sponsor**. Your donation will help us to maintain and develop this project and provide you with better support. + +## Character Sets + +Below is the built-in character sets available. See the details of each character set in the [charsets](./charsets) directory. + +| `charSet` | Block Name | Block Range | +| ---- | --------- | ----- | +| `latin` | [Basic Latin](https://unicodeplus.com/block/0000) | \u0000 - \u007f | +| `latin-1` | [Latin-1 Supplement](https://unicodeplus.com/block/0080) | \u0080 - \u00ff | diff --git a/charsets/latin-1.json b/charsets/latin-1.json new file mode 100644 index 0000000..1014c83 --- /dev/null +++ b/charsets/latin-1.json @@ -0,0 +1,25 @@ +{ + "A": ["\u00c0", "\u00c1", "\u00c2", "\u00c3", "\u00c4", "\u00c5"], + "a": ["\u00e0", "\u00e1", "\u00e2", "\u00e3", "\u00e4", "\u00e5", "\u00aa"], + "B": ["\u00df"], + "C": ["\u00a2", "\u00a9", "\u00c7"], + "c": ["\u00e7"], + "D": ["\u00d0"], + "E": ["\u00a3", "\u00c8", "\u00c9", "\u00ca", "\u00cb"], + "e": ["\u00e8", "\u00e9", "\u00ea", "\u00eb"], + "I": ["\u00cc", "\u00cd", "\u00ce", "\u00cf"], + "i": ["\u00a1", "\u00ec", "\u00ed", "\u00ee", "\u00ef"], + "N": ["\u00d1"], + "n": ["\u00f1"], + "O": ["\u00d2", "\u00d3", "\u00d4", "\u00d5", "\u00d6", "\u00d8"], + "o": ["\u00ba", "\u00f2", "\u00f3", "\u00f4", "\u00f5", "\u00f6", "\u00f8"], + "P": ["\u00b6"], + "p": ["\u00de"], + "R": ["\u00ae"], + "S": ["\u00a7"], + "U": ["\u00d9", "\u00da", "\u00db", "\u00dc"], + "u": ["\u00f9", "\u00fa", "\u00fb", "\u00fc"], + "x": ["\u00d7"], + "Y": ["\u00a5", "\u00dd"], + "y": ["\u00fd", "\u00ff"] +} diff --git a/src/charsets/latin.json b/charsets/latin.json similarity index 100% rename from src/charsets/latin.json rename to charsets/latin.json diff --git a/package.json b/package.json index a65aef7..977bbe4 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,14 @@ { "name": "wisely", "version": "0.1.0", - "description": "Replace sensitive phrases with special characters to avoid bans.", + "description": "Obfuscating text or phrases with random uncommon characters to avoid banning.", "type": "module", "main": "dist/index.js", "types": "dist/index.d.ts", + "files": [ + "charsets/", + "dist/" + ], "scripts": { "lint": "eslint .", "lint:fix": "eslint . --fix", @@ -21,8 +25,11 @@ "keywords": [ "ban", "filter", + "random", "regex", "obsfucation", + "obfuscate", + "obscure", "string", "text", "unicode", diff --git a/src/index.ts b/src/index.ts index 4950c5c..5b5a45d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,8 +1,8 @@ -export type CharSetNames = 'latin'; +export type CharSetNames = 'latin' | 'latin-1'; export type CharSet = Record; async function getCharSet(name: CharSetNames = 'latin'): Promise { - return import(`./charsets/${name}.json`) as Promise; + return import(`../charsets/${name}.json`) as Promise; } function getChar(char: string, charSet: CharSet, caseSensitive?: boolean) { @@ -33,7 +33,7 @@ export default async function wisely(options: Options): Promise { .map((char) => getChar(char, charSet, options.caseSensitive)) .join(''); - if (!options.phrases?.length) { + if (!options.phrases) { return censor(options.text); } diff --git a/test/index.spec.ts b/test/index.spec.ts index 7e88c50..3938307 100644 --- a/test/index.spec.ts +++ b/test/index.spec.ts @@ -10,6 +10,7 @@ describe('wisely', () => { expect(result).not.equal(''); expect(result).not.equal(text); expect(result).not.contain('will be'); + expect(result).toHaveLength(text.length); }); test.each([ @@ -22,6 +23,7 @@ describe('wisely', () => { expect(result).contain(unaffected); expect(result).not.match(new RegExp(`\\b${phrase}\\b`, 'i')); + expect(result).toHaveLength(text.length); }); test.each([ @@ -37,9 +39,35 @@ describe('wisely', () => { notContains.split('').forEach((char) => { expect(result).not.contain(char); }); + + expect(result).toHaveLength(testText.length); }); test('no phrases found in the text', async () => { expect(await wisely({ text, phrases: ['foo'] })).toEqual(text); }); + + test('empty text', async () => { + expect(await wisely({ text: '' })).toEqual(''); + }); + + test('empty phrases', async () => { + expect(await wisely({ text, phrases: [] })).toEqual(text); + }); + + test.each([ + { testText: 'AaBbCcDdXxZz', contains: '\u00df\u00d7Zz', notContains: 'AaBbCcDdXx' }, + ])('with specific charSet (latin-1): $testText', async ({ testText, contains, notContains }) => { + const result = await wisely({ text: testText, charSet: 'latin-1' }); + + contains.split('').forEach((char) => { + expect(result).contain(char); + }); + + notContains.split('').forEach((char) => { + expect(result).not.contain(char); + }); + + expect(result).toHaveLength(testText.length); + }); });