js-dev-tool 1.2.12 → 1.2.15
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/extras/json-minify.d.ts +14 -1
- package/extras/json-minify.js +100 -79
- package/extras/jsonl.d.ts +19 -2
- package/extras/jsonl.js +2 -2
- package/extras/toggle-jsonl.js +60 -0
- package/package.json +7 -5
package/extras/json-minify.d.ts
CHANGED
|
@@ -13,4 +13,17 @@ export type TScannerFunction = (source: string, offset: number, out: TJsonSource
|
|
|
13
13
|
* @returns {string}
|
|
14
14
|
* @version 2.0
|
|
15
15
|
*/
|
|
16
|
-
export function jsonMinify(source: string): string;
|
|
16
|
+
export function jsonMinify(source: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Parse JSON or JSONL text into an array of top-level JSON values.
|
|
19
|
+
*
|
|
20
|
+
* - A single top-level value is returned as a one-element array.
|
|
21
|
+
* - Multiple top-level values separated by whitespace are returned in order.
|
|
22
|
+
* - Whitespace-only input returns an empty array.
|
|
23
|
+
*
|
|
24
|
+
* @template {unknown} T
|
|
25
|
+
* @param {string} source
|
|
26
|
+
* @returns {T[]}
|
|
27
|
+
* @since 2026/04/10 19:51:10
|
|
28
|
+
*/
|
|
29
|
+
export function parseJsonl<T extends unknown>(source: string): T[];
|
package/extras/json-minify.js
CHANGED
|
@@ -9,45 +9,30 @@
|
|
|
9
9
|
/**
|
|
10
10
|
* @file extras/json-minify.js
|
|
11
11
|
* @version 2.3 2026/04/06 16:11:36
|
|
12
|
+
* @version 2.4 2026/04/08 08:31:11 - expand `sjv` to v25x
|
|
12
13
|
*/
|
|
13
|
-
const
|
|
14
|
+
const { ECC_MAP } = require("ts-cc-map");
|
|
14
15
|
/**
|
|
15
16
|
* @typedef {{ src: string }} TJsonSourceEnvelop
|
|
16
17
|
* @typedef {[ open: number, close: number ]} TBlacketPairCode
|
|
17
18
|
*/
|
|
18
19
|
/** @type {TBlacketPairCode} */
|
|
19
|
-
const array = [
|
|
20
|
+
const array = [ECC_MAP.LEFT_BRACKET, ECC_MAP.RIGHT_BRACKET];
|
|
20
21
|
/** @type {TBlacketPairCode} */
|
|
21
|
-
const object = [
|
|
22
|
+
const object = [ECC_MAP.LEFT_BRACE, ECC_MAP.RIGHT_BRACE];
|
|
22
23
|
/**
|
|
23
24
|
* ### (O)thers (M)ap
|
|
24
25
|
*
|
|
25
26
|
* @type {(0 | 1)[]}
|
|
26
27
|
*/
|
|
27
28
|
const om = Array(127).fill(0);
|
|
28
|
-
om[
|
|
29
|
-
om[
|
|
30
|
-
om[
|
|
31
|
-
om[
|
|
32
|
-
om[
|
|
33
|
-
om[
|
|
34
|
-
om[
|
|
35
|
-
/**
|
|
36
|
-
* @typedef {(source: string, offset: number, out: TJsonSourceEnvelop) => number} TScannerFunction
|
|
37
|
-
*/
|
|
38
|
-
/**
|
|
39
|
-
* ### (O)thers (M)ap
|
|
40
|
-
*
|
|
41
|
-
* @type {TScannerFunction[]}
|
|
42
|
-
*/
|
|
43
|
-
const scanners = Array(127).fill(0);
|
|
44
|
-
scanners[ccMap.DOUBLE_QUOTE] = (source, offset, out) => {
|
|
45
|
-
const next = sqs(source, offset);
|
|
46
|
-
out.src += source.slice(offset, next);
|
|
47
|
-
return next;
|
|
48
|
-
};
|
|
49
|
-
scanners[ccMap.LEFT_BRACKET] = sjoCode;
|
|
50
|
-
scanners[ccMap.LEFT_BRACE] = sjoCode;
|
|
29
|
+
om[ECC_MAP.DOUBLE_QUOTE] = 1;
|
|
30
|
+
om[ECC_MAP.COMMA] = 1;
|
|
31
|
+
om[ECC_MAP.COLON] = 1;
|
|
32
|
+
om[ECC_MAP.LEFT_BRACKET] = 1;
|
|
33
|
+
om[ECC_MAP.RIGHT_BRACKET] = 1;
|
|
34
|
+
om[ECC_MAP.LEFT_BRACE] = 1;
|
|
35
|
+
om[ECC_MAP.RIGHT_BRACE] = 1;
|
|
51
36
|
/**
|
|
52
37
|
* @param {string} message
|
|
53
38
|
* @param {number} offset
|
|
@@ -87,51 +72,23 @@ function v25x(source) {
|
|
|
87
72
|
}
|
|
88
73
|
out.src += "\n";
|
|
89
74
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
if (typeof source !== "string") {
|
|
107
|
-
throw new TypeError("jsonMinify(source): source must be a string");
|
|
108
|
-
}
|
|
109
|
-
/** @type {TJsonSourceEnvelop} */
|
|
110
|
-
const out = { src: "" };
|
|
111
|
-
const sourceLen = source.length;
|
|
112
|
-
const scans = scanners;
|
|
113
|
-
let offset = 0;
|
|
114
|
-
let count = 0;
|
|
115
|
-
while (true) {
|
|
116
|
-
const next = skipWhitespaces(source, offset);
|
|
117
|
-
if (next >= sourceLen) {
|
|
118
|
-
break;
|
|
119
|
-
}
|
|
120
|
-
if (count > 0) {
|
|
121
|
-
if (next === offset) {
|
|
122
|
-
throwJsonSyntaxError("Missing whitespace between top-level JSON values", next);
|
|
75
|
+
switch (source.charCodeAt(next)) {
|
|
76
|
+
case ECC_MAP.DOUBLE_QUOTE: {
|
|
77
|
+
const skiped = sqs(source, next);
|
|
78
|
+
out.src += source.slice(next, skiped);
|
|
79
|
+
offset = skiped;
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
case ECC_MAP.LEFT_BRACKET:
|
|
83
|
+
case ECC_MAP.LEFT_BRACE:
|
|
84
|
+
offset = sjoCode(source, next, out);
|
|
85
|
+
break;
|
|
86
|
+
default: {
|
|
87
|
+
const skiped = skipOthers(source, next);
|
|
88
|
+
out.src += source.slice(next, skiped);
|
|
89
|
+
offset = skiped;
|
|
90
|
+
break;
|
|
123
91
|
}
|
|
124
|
-
out.src += "\n";
|
|
125
|
-
}
|
|
126
|
-
const scanner = scans[
|
|
127
|
-
source.charCodeAt(next)
|
|
128
|
-
];
|
|
129
|
-
if (!scanner) {
|
|
130
|
-
const skiped = skipOthers(source, next);
|
|
131
|
-
out.src += source.slice(next, skiped);
|
|
132
|
-
offset = skiped;
|
|
133
|
-
} else {
|
|
134
|
-
offset = scanner(source, next, out);
|
|
135
92
|
}
|
|
136
93
|
count++;
|
|
137
94
|
}
|
|
@@ -146,9 +103,9 @@ function v24x(source) {
|
|
|
146
103
|
*/
|
|
147
104
|
function sjv(source, offset, out) {
|
|
148
105
|
switch (source.charCodeAt(offset)) {
|
|
149
|
-
case
|
|
150
|
-
case
|
|
151
|
-
case
|
|
106
|
+
case ECC_MAP.LEFT_BRACE:
|
|
107
|
+
case ECC_MAP.LEFT_BRACKET: return sjoCode(source, offset, out);
|
|
108
|
+
case ECC_MAP.DOUBLE_QUOTE: {
|
|
152
109
|
const next = sqs(source, offset);
|
|
153
110
|
out.src += source.slice(offset, next);
|
|
154
111
|
return next;
|
|
@@ -160,6 +117,7 @@ function sjv(source, offset, out) {
|
|
|
160
117
|
}
|
|
161
118
|
}
|
|
162
119
|
}
|
|
120
|
+
void sjv;
|
|
163
121
|
/**
|
|
164
122
|
* (S)can (J)son (O)bject
|
|
165
123
|
*
|
|
@@ -178,8 +136,8 @@ function sjoCode(source, offset, out) {
|
|
|
178
136
|
const sourceLen = source.length;
|
|
179
137
|
while (offset < sourceLen) {
|
|
180
138
|
const code = source.charCodeAt(offset++);
|
|
181
|
-
if (code <= 32 /*
|
|
182
|
-
if (code === 34 /*
|
|
139
|
+
if (code <= 32 /* ECC_MAP.SPACE */) continue;
|
|
140
|
+
if (code === 34 /* ECC_MAP.DOUBLE_QUOTE */) {
|
|
183
141
|
const next = sqs(source, offset - 1);
|
|
184
142
|
sourceRef += source.slice(offset - 1, next);
|
|
185
143
|
offset = next;
|
|
@@ -230,11 +188,11 @@ function sqs(source, offset) {
|
|
|
230
188
|
let inEscape = false;
|
|
231
189
|
while (next < srcLen) {
|
|
232
190
|
const code = source.charCodeAt(next++);
|
|
233
|
-
if (code === 92 /*
|
|
191
|
+
if (code === 92 /* ECC_MAP.BACKSLASH */) {
|
|
234
192
|
inEscape = !inEscape;
|
|
235
193
|
} else if (inEscape) {
|
|
236
194
|
inEscape = false;
|
|
237
|
-
} else if (code === 34 /*
|
|
195
|
+
} else if (code === 34 /* ECC_MAP.DOUBLE_QUOTE */) {
|
|
238
196
|
return next;
|
|
239
197
|
}
|
|
240
198
|
}
|
|
@@ -260,7 +218,70 @@ const skipWhitespaces = (source, offset) => {
|
|
|
260
218
|
}
|
|
261
219
|
return offset;
|
|
262
220
|
};
|
|
263
|
-
const jsonMinify =
|
|
221
|
+
const jsonMinify = v25x;
|
|
222
|
+
const jparse = JSON.parse;
|
|
223
|
+
/**
|
|
224
|
+
* Parse JSON or JSONL text into an array of top-level JSON values.
|
|
225
|
+
*
|
|
226
|
+
* - A single top-level value is returned as a one-element array.
|
|
227
|
+
* - Multiple top-level values separated by whitespace are returned in order.
|
|
228
|
+
* - Whitespace-only input returns an empty array.
|
|
229
|
+
*
|
|
230
|
+
* @template {unknown} T
|
|
231
|
+
* @param {string} source
|
|
232
|
+
* @returns {T[]}
|
|
233
|
+
* @since 2026/04/10 19:51:10
|
|
234
|
+
*/
|
|
235
|
+
function parseJsonl(source) {
|
|
236
|
+
if (typeof source !== "string") {
|
|
237
|
+
throw new TypeError("parseJsonl(source): source must be a string");
|
|
238
|
+
}
|
|
239
|
+
/** @type {TJsonSourceEnvelop} */
|
|
240
|
+
const out = { src: "" };
|
|
241
|
+
const sourceLen = source.length;
|
|
242
|
+
let offset = 0;
|
|
243
|
+
let count = 0;
|
|
244
|
+
/** @type {T[]} */
|
|
245
|
+
const jsons = [];
|
|
246
|
+
while (true) {
|
|
247
|
+
const next = skipWhitespaces(source, offset);
|
|
248
|
+
if (next >= sourceLen) {
|
|
249
|
+
break;
|
|
250
|
+
}
|
|
251
|
+
if (count > 0) {
|
|
252
|
+
if (next === offset) {
|
|
253
|
+
throwJsonSyntaxError("Missing whitespace between top-level JSON values", next);
|
|
254
|
+
}
|
|
255
|
+
jsons.push(
|
|
256
|
+
jparse(out.src)
|
|
257
|
+
);
|
|
258
|
+
out.src = "";
|
|
259
|
+
}
|
|
260
|
+
switch (source.charCodeAt(next)) {
|
|
261
|
+
case ECC_MAP.DOUBLE_QUOTE: {
|
|
262
|
+
const skiped = sqs(source, next);
|
|
263
|
+
out.src += source.slice(next, skiped);
|
|
264
|
+
offset = skiped;
|
|
265
|
+
break;
|
|
266
|
+
}
|
|
267
|
+
case ECC_MAP.LEFT_BRACKET:
|
|
268
|
+
case ECC_MAP.LEFT_BRACE:
|
|
269
|
+
offset = sjoCode(source, next, out);
|
|
270
|
+
break;
|
|
271
|
+
default: {
|
|
272
|
+
const skiped = skipOthers(source, next);
|
|
273
|
+
out.src += source.slice(next, skiped);
|
|
274
|
+
offset = skiped;
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
count++;
|
|
279
|
+
}
|
|
280
|
+
count && jsons.push(
|
|
281
|
+
jparse(out.src)
|
|
282
|
+
);
|
|
283
|
+
return jsons;
|
|
284
|
+
}
|
|
264
285
|
module.exports = {
|
|
265
|
-
jsonMinify,
|
|
286
|
+
jsonMinify, parseJsonl
|
|
266
287
|
};
|
package/extras/jsonl.d.ts
CHANGED
|
@@ -115,9 +115,26 @@ export function readJsonlMapByKey<TRow = any, TOut = TRow>(fileName: string, opt
|
|
|
115
115
|
*/
|
|
116
116
|
export function fastGetIntFieldCheap(line: string, key: string): number | undefined;
|
|
117
117
|
/**
|
|
118
|
-
* Minify JSON or JSONL text by removing JSON whitespace outside strings.
|
|
118
|
+
* Minify JSON or JSONL text by removing JSON whitespace outside double-quoted strings.
|
|
119
119
|
*
|
|
120
120
|
* - A single top-level value is returned as minified JSON.
|
|
121
121
|
* - Multiple top-level values are returned as minified JSONL separated by `"\n"`.
|
|
122
|
+
*
|
|
123
|
+
* @param {string} source
|
|
124
|
+
* @returns {string}
|
|
125
|
+
* @version 2.0
|
|
126
|
+
*/
|
|
127
|
+
export function jsonMinify(source: string): string;
|
|
128
|
+
/**
|
|
129
|
+
* Parse JSON or JSONL text into an array of top-level JSON values.
|
|
130
|
+
*
|
|
131
|
+
* - A single top-level value is returned as a one-element array.
|
|
132
|
+
* - Multiple top-level values separated by whitespace are returned in order.
|
|
133
|
+
* - Whitespace-only input returns an empty array.
|
|
134
|
+
*
|
|
135
|
+
* @template {unknown} T
|
|
136
|
+
* @param {string} source
|
|
137
|
+
* @returns {T[]}
|
|
138
|
+
* @since 2026/04/10 19:51:10
|
|
122
139
|
*/
|
|
123
|
-
export function
|
|
140
|
+
export function parseJsonl<T extends unknown>(source: string): T[];
|
package/extras/jsonl.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
const fs = require("fs");
|
|
13
13
|
const path = require("path");
|
|
14
|
-
const { jsonMinify } = require("./json-minify.js");
|
|
14
|
+
const { jsonMinify, parseJsonl } = require("./json-minify.js");
|
|
15
15
|
/**
|
|
16
16
|
* @import { TJsonlReadOption, TJsonlReadBaseOption } from "./jsonl.js";
|
|
17
17
|
*/
|
|
@@ -202,5 +202,5 @@ module.exports = {
|
|
|
202
202
|
readJsonlArray,
|
|
203
203
|
readJsonlMapByKey,
|
|
204
204
|
fastGetIntFieldCheap,
|
|
205
|
-
jsonMinify,
|
|
205
|
+
jsonMinify, parseJsonl
|
|
206
206
|
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/*!
|
|
3
|
+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
4
|
+
// Copyright (C) 2026 jeffy-g <hirotom1107@gmail.com>
|
|
5
|
+
// Released under the MIT license
|
|
6
|
+
// https://opensource.org/licenses/mit-license.php
|
|
7
|
+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
8
|
+
*/
|
|
9
|
+
"use strict";
|
|
10
|
+
/**
|
|
11
|
+
* @file extras/toggle-jsonl.js
|
|
12
|
+
* @command tgl-jsonl [-un] <jsonl path> <jsonl path>
|
|
13
|
+
* @command node extras/toggle-jsonl.js
|
|
14
|
+
*/
|
|
15
|
+
const tinArgs = require("tin-args");
|
|
16
|
+
const utils = require("../utils.js");
|
|
17
|
+
const { parseJsonl } = require("./json-minify.js");
|
|
18
|
+
const reset = "\x1b[0m";
|
|
19
|
+
const green = "\x1b[32m";
|
|
20
|
+
const yellow = "\x1b[33m";
|
|
21
|
+
const blue = "\x1b[34m";
|
|
22
|
+
const orange = "\x1b[38;5;208m";
|
|
23
|
+
/**
|
|
24
|
+
* @typedef TToggleJsonArgs
|
|
25
|
+
* @prop {true=} un un format jsonl file
|
|
26
|
+
*/
|
|
27
|
+
/** @type {tinArgs.TTinArgsReturnType<TToggleJsonArgs>} */
|
|
28
|
+
const args = tinArgs();
|
|
29
|
+
const files = args.args;
|
|
30
|
+
if (files) {
|
|
31
|
+
const needFormat = !args.un;
|
|
32
|
+
for (const file of files) {
|
|
33
|
+
utils.log(`${blue}[toggle-jsonl]${reset}: convert to ${yellow}${needFormat ? "" : "un-"}formatted jsonl${reset} - ${green}${file}${reset}`);
|
|
34
|
+
let jsonlSource = "";
|
|
35
|
+
const source = utils.readText(file);
|
|
36
|
+
/** @type {Record<string, any>[]} */
|
|
37
|
+
const jsonArray = parseJsonl(source);
|
|
38
|
+
if (needFormat) {
|
|
39
|
+
for (const json of jsonArray) {
|
|
40
|
+
jsonlSource += utils.formatedStringify(json) + "\n";
|
|
41
|
+
}
|
|
42
|
+
} else {
|
|
43
|
+
for (const json of jsonArray) {
|
|
44
|
+
jsonlSource += JSON.stringify(json) + "\n";
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
utils.writeText(jsonlSource, file);
|
|
48
|
+
}
|
|
49
|
+
} else {
|
|
50
|
+
utils.log(
|
|
51
|
+
`${orange}Please specify the path to the JSONL file to process...${reset}` +
|
|
52
|
+
`
|
|
53
|
+
|
|
54
|
+
Usage: ${yellow}tgl-jsonl${reset} [-un] <jsonl path> <jsonl path>
|
|
55
|
+
|
|
56
|
+
about: options
|
|
57
|
+
-un: convert to "un-formatted jsonl", if not spcedified then will be formatted jsonl source
|
|
58
|
+
`
|
|
59
|
+
);
|
|
60
|
+
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "js-dev-tool",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.15",
|
|
4
4
|
"bin": {
|
|
5
|
-
"jstool": "tools.js"
|
|
5
|
+
"jstool": "tools.js",
|
|
6
|
+
"tgl-jsonl": "extras/toggle-jsonl.js"
|
|
6
7
|
},
|
|
7
8
|
"types": "./index.d.ts",
|
|
8
9
|
"main": "./index.js",
|
|
@@ -76,7 +77,7 @@
|
|
|
76
77
|
"!regex-test.ts",
|
|
77
78
|
"!extras/npm",
|
|
78
79
|
"!/**/*.png",
|
|
79
|
-
"
|
|
80
|
+
"!*@*.*",
|
|
80
81
|
"!*fragments*",
|
|
81
82
|
"!tool.sh"
|
|
82
83
|
],
|
|
@@ -91,7 +92,8 @@
|
|
|
91
92
|
"mini-semaphore": "^1.5.4",
|
|
92
93
|
"replace": "^1.2.2",
|
|
93
94
|
"rm-cstyle-cmts": "^3.4.4",
|
|
94
|
-
"terser": "^5.46.
|
|
95
|
-
"tin-args": "^0.1.
|
|
95
|
+
"terser": "^5.46.1",
|
|
96
|
+
"tin-args": "^0.1.5",
|
|
97
|
+
"ts-cc-map": "^1.1.0"
|
|
96
98
|
}
|
|
97
99
|
}
|