Skip to content

Commit cefda1e

Browse files
authored
Merge pull request #15 from aminya/comments
2 parents 08bfaaa + 4f07309 commit cefda1e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+203
-47
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ dist
1515
.dub
1616
trace.*
1717

18-
test/fixtures/*-minified.json
18+
test/fixtures/**/*-minified.json

Readme.md

Lines changed: 26 additions & 6 deletions

benchmark/js-benchmark.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@ import { readFile, writeFile } from "fs/promises"
22
import { performance } from "perf_hooks"
33
import jsonMinify from "jsonminify"
44

5-
import { jsonFiles } from "../test/fixtures.mjs"
5+
import { standardFiles } from "../test/fixtures.mjs"
66

77
// warmup
88
const tmp = await jsonMinify("{}")
99

1010
const t1 = performance.now()
1111

1212
await Promise.all(
13-
jsonFiles.map(async (jsonFile) => {
13+
standardFiles.map(async (jsonFile) => {
1414
const jsonString = await readFile(jsonFile, "utf8")
1515
const data = await jsonMinify(jsonString)
1616
return await writeFile(jsonFile, data)

benchmark/native-benchmark.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { performance } from "perf_hooks"
22
import { minifyFiles } from "../dist/lib.js"
33

4-
import { jsonFiles } from "../test/fixtures.mjs"
4+
import { standardFiles } from "../test/fixtures.mjs"
55

66
const t1 = performance.now()
77

8-
await minifyFiles(jsonFiles)
8+
await minifyFiles(standardFiles)
99

1010
const t2 = performance.now()
1111
console.log(((t2 - t1) / 1000).toFixed(3), "seconds")

package.json

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "@aminya/minijson",
33
"author": "Amin Yahyaabdi",
44
"version": "0.4.1",
5-
"description": "Minify JSON files blazing fast! Written in D",
5+
"description": "Minify JSON files blazing fast! Supports Comments. Written in D.",
66
"homepage": "https://github.com/aminya/minijson",
77
"license": "MIT",
88
"files": [
@@ -17,7 +17,7 @@
1717
"test.format": "prettier . --check",
1818
"lint": "eslint . --fix",
1919
"test.lint": "eslint .",
20-
"test": "jasmine ./test/index-test.mjs",
20+
"test": "jasmine ./test/index-test.mjs || shx rm -rf ./test/fixtures/**/*-minified.json",
2121
"clean": "shx rm -rf dist",
2222
"build.native": "dub build --config=executable",
2323
"build.native.release": "pnpm build.native -- --build release-nobounds --compiler=ldc2",
@@ -42,7 +42,8 @@
4242
"parcel": "^2.0.0-beta.3.1",
4343
"prettier-config-atomic": "^2.0.5",
4444
"servor": "^4.0.2",
45-
"shx": "0.3.3"
45+
"shx": "0.3.3",
46+
"strip-json-comments": "^3.1.1"
4647
},
4748
"targets": {
4849
"browser": {
@@ -64,6 +65,17 @@
6465
"mini",
6566
"min",
6667
"minifier",
68+
"jsonc",
69+
"comment",
70+
"comments",
71+
"remove",
72+
"delete",
73+
"multiline",
74+
"strip",
75+
"trim",
76+
"parse",
77+
"jsonc",
78+
"json5",
6779
"js",
6880
"build",
6981
"build-tool",

pnpm-lock.yaml

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/native/cli.d

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,25 @@ import std.getopt : getopt, defaultGetoptPrinter, GetoptResult;
77
/** Print help */
88
void printHelp(GetoptResult optResult) @trusted
99
{
10-
return defaultGetoptPrinter(`Usage: minify json
10+
return defaultGetoptPrinter(`minijson: minify json files with support for comments
1111
minijson --file file1.json --file file2.json
12+
minijson --file file1_with_comment.json --file file2_with_comment.json --comment
13+
1214
minijson --string '{"some_json": "string_here"}'
15+
minijson --string '{"some_json": "string_here"} //comment' --comment
16+
17+
More information at https://github.com/aminya/minijson
1318
`, optResult.options);
1419
}
1520

1621
void main(string[] args) @trusted
1722
{
1823
string[] files;
1924
string jsonString;
25+
bool hasComment = false;
2026

2127
auto optResult = getopt(args, "file", "an array of files to minify", &files, "string",
22-
"a json string to minify", &jsonString);
28+
"a json string to minify", &jsonString, "comment", "a flag to support comments in json", &hasComment);
2329

2430
if (optResult.helpWanted || (!files && !jsonString))
2531
{
@@ -29,14 +35,14 @@ void main(string[] args) @trusted
2935
// minify the given files
3036
if (files)
3137
{
32-
minifyFiles(files);
38+
minifyFiles(files, hasComment);
3339
}
3440

3541
// minify the given string and print to stdout
3642
if (jsonString)
3743
{
3844
import std : write;
3945

40-
write(minifyString(jsonString));
46+
write(minifyString(jsonString, hasComment));
4147
}
4248
}

src/native/lib.d

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ const repeatingBackSlashRegex = ctRegex!(`(\\)*$`);
1515
1616
Params:
1717
jsonString = the json string you want to minify
18-
hasComments = a switch that indicates if the json string has comments. Pass `true` to support parsing comments. Default: `false`.
18+
hasComment = a boolean to support comments in json. Default: `false`.
1919
2020
Return:
2121
the minified json string
2222
*/
23-
string minifyString(string jsonString, bool hasComments = false) @trusted
23+
string minifyString(string jsonString, bool hasComment = false) @trusted
2424
{
2525
auto in_string = false;
2626
auto in_multiline_comment = false;
@@ -29,7 +29,7 @@ string minifyString(string jsonString, bool hasComments = false) @trusted
2929
size_t from = 0;
3030
auto rightContext = "";
3131

32-
const tokenizer = !hasComments ? tokenizerNoComment : tokenizerWithComment;
32+
const tokenizer = !hasComment ? tokenizerNoComment : tokenizerWithComment;
3333

3434
auto match = jsonString.matchAll(tokenizer);
3535

@@ -43,7 +43,8 @@ string minifyString(string jsonString, bool hasComments = false) @trusted
4343
const prevFrom = from;
4444
from = jsonString.length - rightContext.length; // lastIndex
4545

46-
const noCommentOrNotInComment = !hasComments || (!in_multiline_comment && !in_singleline_comment);
46+
const notInComment = (!in_multiline_comment && !in_singleline_comment);
47+
const noCommentOrNotInComment = !hasComment || notInComment;
4748

4849
if (noCommentOrNotInComment)
4950
{
@@ -65,15 +66,11 @@ string minifyString(string jsonString, bool hasComments = false) @trusted
6566
--from; // include " character in next catch
6667
rightContext = jsonString[from .. $];
6768
}
68-
else if (matchFrontHit.matchFirst(spaceOrBreakRegex).empty())
69-
{
70-
new_str ~= matchFrontHit;
71-
}
7269
}
7370
// comments
74-
if (hasComments && !in_string)
71+
if (hasComment && !in_string)
7572
{
76-
if (!in_multiline_comment && !in_singleline_comment)
73+
if (notInComment)
7774
{
7875
if (matchFrontHit == "/*")
7976
{
@@ -83,6 +80,10 @@ string minifyString(string jsonString, bool hasComments = false) @trusted
8380
{
8481
in_singleline_comment = true;
8582
}
83+
else if (notSlashAndNoSpaceOrBreak(matchFrontHit))
84+
{
85+
new_str ~= matchFrontHit;
86+
}
8687
}
8788
else if (in_multiline_comment && !in_singleline_comment && matchFrontHit == "*/")
8889
{
@@ -93,35 +94,44 @@ string minifyString(string jsonString, bool hasComments = false) @trusted
9394
in_singleline_comment = false;
9495
}
9596
}
96-
97+
if (!hasComment && notSlashAndNoSpaceOrBreak(matchFrontHit))
98+
{
99+
new_str ~= matchFrontHit;
100+
}
97101
match.popFront();
98102
}
99103
new_str ~= rightContext;
100104
return new_str.array().join("");
101105
}
102106

103-
bool hasNoSlashOrEvenNumberOfSlashes(string leftContext) @safe
107+
private bool hasNoSlashOrEvenNumberOfSlashes(string leftContext) @safe
104108
{
105109
auto leftContextMatch = leftContext.matchFirst(repeatingBackSlashRegex);
106110
// if not matched the hit length will be 0 (== leftContextMatch.empty())
107111
return leftContextMatch.hit().length % 2 == 0;
108112
}
109113

114+
private bool notSlashAndNoSpaceOrBreak(string matchFrontHit)
115+
{
116+
return matchFrontHit != "\"" && matchFrontHit.matchFirst(spaceOrBreakRegex).empty();
117+
}
118+
110119
/**
111120
Minify the given files in place. It minifies the files in parallel.
112121
113122
Params:
114123
files = the paths to the files.
124+
hasComment = a boolean to support comments in json. Default: `false`.
115125
*/
116-
void minifyFiles(string[] files)
126+
void minifyFiles(string[] files, bool hasComment = false)
117127
{
118128
import std.parallelism : parallel;
119129
import std.file : readText, write;
120130

121131
foreach (ref file; files.parallel())
122132
{
123133
const string jsonString = readText(file);
124-
const minifiedJsonString = minifyString(jsonString);
134+
const minifiedJsonString = minifyString(jsonString, hasComment);
125135
write(file, minifiedJsonString);
126136
}
127137
}

src/native/libc.d

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,17 @@ extern (C):
99
1010
Params:
1111
jsonString = the json string you want to minify
12-
hasComments = a switch that indicates if the json string has comments. Pass `true` to support parsing comments. Default: `false`.
12+
hasComment = a boolean to support comments in json. Default: `false`.
1313
1414
Return:
1515
the minified json string
1616
*/
17-
auto minifyString(char* jsonCString, bool hasComments = false)
17+
auto minifyString(char* jsonCString, bool hasComment = false)
1818
{
1919
import std : fromStringz, toStringz;
2020

2121
const string jsonString = fromStringz(jsonCString).idup;
22-
const minifiedString = minifyString(jsonString, hasComments);
22+
const minifiedString = minifyString(jsonString, hasComment);
2323

2424
return toStringz(minifiedString);
2525
}

src/node/lib.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@ import { join } from "path"
55
* Minify all the given JSON files in place. It minifies the files in parallel.
66
*
77
* @param files An array of paths to the files
8+
* @param hasComment A boolean to support comments in json. Default `false`.
89
* @returns {Promise<void>} Returns a void promise that resolves when all the files are minified
910
* @throws {Promise<string | Error>} The promise is rejected with the reason for failure
1011
*/
11-
export async function minifyFiles(files: string[]): Promise<void> {
12+
export async function minifyFiles(files: string[], hasComment = false): Promise<void> {
1213
const filesNum = files.length
1314
if (filesNum === 0) {
1415
return Promise.resolve()
@@ -21,19 +22,28 @@ export async function minifyFiles(files: string[]): Promise<void> {
2122
args.splice(iSplice, 0, "--file")
2223
}
2324

25+
if (hasComment) {
26+
args.push("--comment")
27+
}
28+
2429
await spawnMinijson(args)
2530
}
2631

2732
/**
2833
* Minify the given JSON string
2934
*
3035
* @param jsonString The json string you want to minify
36+
* @param hasComment A boolean to support comments in json. Default `false`.
3137
* @returns {Promise<string>} The minified json string
3238
* @throws {Promise<string | Error>} The promise is rejected with the reason for failure
3339
*/
34-
export async function minifyString(jsonString: string): Promise<string> {
40+
export async function minifyString(jsonString: string, hasComment = false): Promise<string> {
41+
const args = ["--string", jsonString]
42+
if (hasComment) {
43+
args.push("--comment")
44+
}
3545
// trim is needed due to using stdout for interop
36-
return (await spawnMinijson(["--string", jsonString])).trim()
46+
return (await spawnMinijson(args)).trim()
3747
}
3848

3949
const exeExtention = process.platform === "win32" ? ".exe" : ""

0 commit comments

Comments
 (0)