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.
@@ -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[];
@@ -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 ccMap = require("./cc-map");
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 = [ ccMap.LEFT_BRACKET, ccMap.RIGHT_BRACKET];
20
+ const array = [ECC_MAP.LEFT_BRACKET, ECC_MAP.RIGHT_BRACKET];
20
21
  /** @type {TBlacketPairCode} */
21
- const object = [ ccMap.LEFT_BRACE, ccMap.RIGHT_BRACE];
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[ccMap.DOUBLE_QUOTE] = 1;
29
- om[ccMap.COMMA] = 1;
30
- om[ccMap.COLON] = 1;
31
- om[ccMap.LEFT_BRACKET] = 1;
32
- om[ccMap.RIGHT_BRACKET] = 1;
33
- om[ccMap.LEFT_BRACE] = 1;
34
- om[ccMap.RIGHT_BRACE] = 1;
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
- offset = sjv(source, next, out);
91
- count++;
92
- }
93
- return out.src;
94
- }
95
- /**
96
- * Minify JSON or JSONL text by removing JSON whitespace outside double-quoted strings.
97
- *
98
- * - A single top-level value is returned as minified JSON.
99
- * - Multiple top-level values are returned as minified JSONL separated by `"\n"`.
100
- *
101
- * @param {string} source
102
- * @returns {string}
103
- * @version 2.0
104
- */
105
- function v24x(source) {
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 ccMap.LEFT_BRACE:
150
- case ccMap.LEFT_BRACKET: return sjoCode(source, offset, out);
151
- case ccMap.DOUBLE_QUOTE: {
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 /* ccMap.SPACE */) continue;
182
- if (code === 34 /* ccMap.DOUBLE_QUOTE */) {
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 /* ccMap.BACKSLASH */) {
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 /* ccMap.DOUBLE_QUOTE */) {
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 = process.versions.node.slice(0, 2) <= "24" ? v24x : v25x;
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 jsonMinify(source: string): string;
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.12",
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
- "!*@*.js",
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.0",
95
- "tin-args": "^0.1.4"
95
+ "terser": "^5.46.1",
96
+ "tin-args": "^0.1.5",
97
+ "ts-cc-map": "^1.1.0"
96
98
  }
97
99
  }