Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

feat: use TS and output cjs, es, umd and minified/uglified version #2

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
dist
156 changes: 0 additions & 156 deletions JSONCrush.js

This file was deleted.

2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
<br>Uncrushed URI Encoded Component:
<br><textarea disabled id=textarea_uncrushed cols=80 rows=10></textarea>
<br><div id=div_uncrushed_check></div>
<script src="JSONCrush.js"></script>
<script src="JSONCrush.min.js"></script>
<script>

"use strict"; // strict mode
Expand Down
31 changes: 31 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"name": "jsoncrush",
"version": "1.0.0",
"description": "This simple system allows for excellent compression of uri encoded JSON strings using the JSCrush algorithm.",
"main": "JSONCrush.js",
"scripts": {
"build": "yarn build:es2015 && yarn build:esm && yarn build:cjs && yarn build:umd && yarn build:min",
"build:es2015": "tsc --module es2015 --target es2015 --outDir dist/es2015",
"build:esm": "tsc --module es2015 --target es5 --outDir dist/esm",
"build:cjs": "tsc --module commonjs --target es5 --outDir dist/cjs",
"build:umd": "rollup --config",
"build:min": "uglifyjs --compress --mangle --screw-ie8 --comments -o dist/JSONCrush.min.js -- dist/umd/JSONCrush.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/KilledByAPixel/JSONCrush.git"
},
"author": "Frank Force",
"license": "MIT",
"bugs": {
"url": "https://github.com/KilledByAPixel/JSONCrush/issues"
},
"homepage": "https://github.com/KilledByAPixel/JSONCrush#readme",
"devDependencies": {
"rollup": "^1.27.5",
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-node-resolve": "^5.2.0",
"typescript": "^3.7.2",
"uglify-js": "^3.7.0"
}
}
21 changes: 21 additions & 0 deletions rollup.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import resolve from "rollup-plugin-node-resolve";
import commonjs from "rollup-plugin-commonjs";

export default {
input: "dist/esm/index.js",
output: {
file: "dist/umd/JSONCrush.js",
format: "umd",
name: "window",
extend: true
},
plugins: [
resolve({
browser: true,
customResolveOptions: {
moduleDirectory: "dist/esm"
}
}),
commonjs()
]
};
105 changes: 105 additions & 0 deletions src/JSONCrush.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
///////////////////////////////////////////////////////////////////////
// JSONCrush by Frank Force [MIT] https://github.com/KilledByAPixel/JSONCrush
// Based on JSCrush - Javascript crusher by @aivopaas. [MIT] http://www.iteral.com/jscrush
///////////////////////////////////////////////////////////////////////
import { JSONCrushSwap } from "./JSONCrushSwap";

interface Carry {
[key: string]: number;
[key: number]: number;
}

export function JSONCrush(string: string) {
const JSCrush = (string: string, characters: string[]) => {
// JSCrush Algorithm (remove repeated substrings)
const ByteLength = (string: string) =>
encodeURI(string).replace(/%../g, "i").length;
let maxSubstringLength = 50; // speed it up by limiting max length
let o: Carry = {};
let X, O, m, i, N, M, t, j, R;
let c: string | number;
let e: string | number;
let Q: string[] = characters;
let x: string;
let s: string = string;
X = 1;
m = "";
while (true) {
for (M = N = e = c = 0, i = Q.length; !c && i--; )
!~s.indexOf(Q[i]) && (c = Q[i]);
if (!c) break;
if (O) {
o = {};
for (x in O)
for (j = s.indexOf(x), o[x] = 0; ~j; o[x]++)
j = s.indexOf(x, j + x.length);
O = o;
} else
for (O = o = {}, t = 1; X && t < maxSubstringLength; t++)
for (X = i = 0; ++i < s.length - t; )
if (!o[(x = s.substr((j = i), t))])
if (~(j = s.indexOf(x, j + t)))
for (X = t, o[x] = 1; ~j; o[x]++) j = s.indexOf(x, j + t);
for (let x in O) {
j = ByteLength(x);
if ((j = (R = O[x]) * j - j - (R + 1) * ByteLength(c as string)))
(j > M || (j == M && R > N)) && ((M = j), (N = R), (e = x));
if (j < 1) delete O[x];
}
o = {};
for (let x in O) o[x.split(e as string).join(c as string)] = 1;
O = o;
if (!e) break;
s = s.split(e as string).join(c as string) + c + e;
m = c + m;
}

return { a: s, b: m };
};

// remove \u0001 if it is found in the string so it can be used as a delimiter
string = string.replace(/\u0001/g, "");

// swap out common json characters
string = JSONCrushSwap(string);

// create a string of characters that will not be escaped by encodeURIComponent
let characters = [];
const unescapedCharacters = `-_.!~*'()`;
for (let i = 127; --i; ) {
if (
(i >= 48 && i <= 57) || // 0-9
(i >= 65 && i <= 90) || // A-Z
(i >= 97 && i <= 122) || // a-z
unescapedCharacters.includes(String.fromCharCode(i))
)
characters.push(String.fromCharCode(i));
}

// check if every character is used
let allUsed = true;
for (let i in characters) {
let c = characters[i];
if (!string.includes(c)) {
allUsed = false;
break;
}
}

if (allUsed) {
// use extended set if all the unescaped ones are used
for (let i = 2; i < 255; ++i) {
let c = String.fromCharCode(i);
if (c != "\\" && !characters.includes(c)) characters.unshift(c);
}
}

// crush with JS crush
let crushed = JSCrush(string, characters);

// use \u0001 as a delimiter between JSCrush parts
let crushedString = crushed.a + "\u0001" + crushed.b;

// encode URI
return encodeURIComponent(crushedString);
}
35 changes: 35 additions & 0 deletions src/JSONCrushSwap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
///////////////////////////////////////////////////////////////////////
// JSONCrush by Frank Force [MIT] https://github.com/KilledByAPixel/JSONCrush
// Based on JSCrush - Javascript crusher by @aivopaas. [MIT] http://www.iteral.com/jscrush
///////////////////////////////////////////////////////////////////////
interface Grouping {
[key: number]: string;
}

export function JSONCrushSwap(string: string, forward: boolean = true) {
// swap out characters for lesser used ones that wont get escaped
const swapGroups = [
['"', "'"],
["':", "!"],
[",'", "~"],
["}", ")", "\\", "\\"],
["{", "(", "\\", "\\"]
];

function Swap(string: string, g: Grouping) {
let regex = new RegExp(
`${(g[2] ? g[2] : "") + g[0]}|${(g[3] ? g[3] : "") + g[1]}`,
"g"
);
return string.replace(regex, $1 => ($1 === g[0] ? g[1] : g[0]));
}

// need to be able to swap characters in reverse direction for uncrush
if (forward)
for (let i = 0; i < swapGroups.length; ++i)
string = Swap(string, swapGroups[i]);
else
for (let i = swapGroups.length; i--; ) string = Swap(string, swapGroups[i]);

return string;
}
23 changes: 23 additions & 0 deletions src/JSONUncrush.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
///////////////////////////////////////////////////////////////////////
// JSONCrush by Frank Force [MIT] https://github.com/KilledByAPixel/JSONCrush
// Based on JSCrush - Javascript crusher by @aivopaas. [MIT] http://www.iteral.com/jscrush
///////////////////////////////////////////////////////////////////////
import { JSONCrushSwap } from "./JSONCrushSwap";

export function JSONUncrush(string: string) {
// string must be a decoded URI component, searchParams.get() does this automatically

// unsplit the string
let splitString: string[] = string.split("\u0001");

// JSUncrush algorithm
let a: string = splitString[0];
let b: string = splitString[1];
for (let c in b.split("")) {
let d = a.split(b[c]);
a = d.join(d.pop());
}

// unswap the json characters in reverse direction
return JSONCrushSwap(a, !!0);
}
4 changes: 4 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { JSONCrush } from "./JSONCrush";
import { JSONUncrush } from "./JSONUncrush";

export { JSONCrush, JSONUncrush };
Loading