@reliverse/relifso 1.4.0 → 1.4.2
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/LICENSES +16 -0
- package/README.md +48 -17
- package/bin/impl/bun.d.ts +5 -28
- package/bin/impl/bun.js +2 -126
- package/bin/impl/copy.js +8 -7
- package/bin/impl/create.d.ts +34 -0
- package/bin/impl/create.js +54 -0
- package/bin/impl/dive.d.ts +10 -0
- package/bin/impl/dive.js +89 -0
- package/bin/impl/empty.d.ts +28 -0
- package/bin/impl/empty.js +75 -0
- package/bin/impl/extras.d.ts +22 -2
- package/bin/impl/extras.js +68 -3
- package/bin/impl/json-utils.d.ts +30 -0
- package/bin/impl/json-utils.js +46 -0
- package/bin/impl/output-file.d.ts +3 -2
- package/bin/impl/output-json.d.ts +7 -2
- package/bin/impl/output-json.js +73 -11
- package/bin/impl/read-file.d.ts +15 -4
- package/bin/impl/read-file.js +88 -10
- package/bin/impl/read-json.d.ts +6 -0
- package/bin/impl/read-json.js +133 -21
- package/bin/impl/stats.d.ts +31 -0
- package/bin/impl/stats.js +141 -0
- package/bin/impl/write-file.d.ts +19 -8
- package/bin/impl/write-file.js +153 -24
- package/bin/impl/write-json.d.ts +13 -2
- package/bin/impl/write-json.js +46 -7
- package/bin/mod.d.ts +84 -36
- package/bin/mod.js +108 -39
- package/bin/utils/json/helpers/JSONRepairError.d.ts +4 -0
- package/bin/utils/json/helpers/JSONRepairError.js +7 -0
- package/bin/utils/json/helpers/JsonSchemaError.d.ts +6 -0
- package/bin/utils/json/helpers/JsonSchemaError.js +6 -0
- package/bin/utils/json/helpers/stringUtils.d.ts +64 -0
- package/bin/utils/json/helpers/stringUtils.js +87 -0
- package/bin/utils/json/regular/jsonc.d.ts +45 -0
- package/bin/utils/json/regular/jsonc.js +88 -0
- package/bin/utils/json/regular/jsonrepair.d.ts +17 -0
- package/bin/utils/json/regular/jsonrepair.js +576 -0
- package/bin/utils/json/regular/validate.d.ts +22 -0
- package/bin/utils/json/regular/validate.js +52 -0
- package/bin/utils/json/stream/JsonStreamError.d.ts +6 -0
- package/bin/utils/json/stream/JsonStreamError.js +6 -0
- package/bin/utils/json/stream/buffer/InputBuffer.d.ts +13 -0
- package/bin/utils/json/stream/buffer/InputBuffer.js +68 -0
- package/bin/utils/json/stream/buffer/OutputBuffer.d.ts +17 -0
- package/bin/utils/json/stream/buffer/OutputBuffer.js +101 -0
- package/bin/utils/json/stream/core.d.ts +10 -0
- package/bin/utils/json/stream/core.js +695 -0
- package/bin/utils/json/stream/jsonl.d.ts +21 -0
- package/bin/utils/json/stream/jsonl.js +55 -0
- package/bin/utils/json/stream/parser.d.ts +14 -0
- package/bin/utils/json/stream/parser.js +81 -0
- package/bin/utils/json/stream/stack.d.ts +19 -0
- package/bin/utils/json/stream/stack.js +43 -0
- package/bin/utils/json/stream/stream.d.ts +6 -0
- package/bin/utils/json/stream/stream.js +30 -0
- package/bin/utils/json/stream/writer.d.ts +14 -0
- package/bin/utils/json/stream/writer.js +44 -0
- package/package.json +3 -2
- package/bin/impl/create-file.d.ts +0 -2
- package/bin/impl/create-file.js +0 -21
- package/bin/impl/dive-async.d.ts +0 -11
- package/bin/impl/dive-async.js +0 -88
- package/bin/impl/empty-dir.d.ts +0 -2
- package/bin/impl/empty-dir.js +0 -24
- package/bin/impl/file-utils.d.ts +0 -20
- package/bin/impl/file-utils.js +0 -63
- /package/bin/{impl/logger.d.ts → utils/log.d.ts} +0 -0
- /package/bin/{impl/logger.js → utils/log.js} +0 -0
|
@@ -0,0 +1,695 @@
|
|
|
1
|
+
import { JSONRepairError } from "../helpers/JSONRepairError.js";
|
|
2
|
+
import {
|
|
3
|
+
isControlCharacter,
|
|
4
|
+
isDelimiter,
|
|
5
|
+
isDigit,
|
|
6
|
+
isDoubleQuote,
|
|
7
|
+
isDoubleQuoteLike,
|
|
8
|
+
isFunctionNameChar,
|
|
9
|
+
isFunctionNameCharStart,
|
|
10
|
+
isHex,
|
|
11
|
+
isQuote,
|
|
12
|
+
isSingleQuote,
|
|
13
|
+
isSingleQuoteLike,
|
|
14
|
+
isSpecialWhitespace,
|
|
15
|
+
isStartOfValue,
|
|
16
|
+
isUnquotedStringDelimiter,
|
|
17
|
+
isValidStringCharacter,
|
|
18
|
+
isWhitespace,
|
|
19
|
+
isWhitespaceExceptNewline,
|
|
20
|
+
regexUrlChar,
|
|
21
|
+
regexUrlStart
|
|
22
|
+
} from "../helpers/stringUtils.js";
|
|
23
|
+
import { createInputBuffer } from "./buffer/InputBuffer.js";
|
|
24
|
+
import { createOutputBuffer } from "./buffer/OutputBuffer.js";
|
|
25
|
+
import { Caret, StackType, createStack } from "./stack.js";
|
|
26
|
+
const controlCharacters = {
|
|
27
|
+
"\b": "\\b",
|
|
28
|
+
"\f": "\\f",
|
|
29
|
+
"\n": "\\n",
|
|
30
|
+
"\r": "\\r",
|
|
31
|
+
" ": "\\t"
|
|
32
|
+
};
|
|
33
|
+
const escapeCharacters = {
|
|
34
|
+
'"': '"',
|
|
35
|
+
"\\": "\\",
|
|
36
|
+
"/": "/",
|
|
37
|
+
b: "\b",
|
|
38
|
+
f: "\f",
|
|
39
|
+
n: "\n",
|
|
40
|
+
r: "\r",
|
|
41
|
+
t: " "
|
|
42
|
+
// note that \u is handled separately in parseString()
|
|
43
|
+
};
|
|
44
|
+
export function jsonrepairCore({
|
|
45
|
+
onData,
|
|
46
|
+
bufferSize = 65536,
|
|
47
|
+
chunkSize = 65536
|
|
48
|
+
}) {
|
|
49
|
+
const input = createInputBuffer();
|
|
50
|
+
const output = createOutputBuffer({
|
|
51
|
+
write: onData,
|
|
52
|
+
bufferSize,
|
|
53
|
+
chunkSize
|
|
54
|
+
});
|
|
55
|
+
let i = 0;
|
|
56
|
+
let iFlushed = 0;
|
|
57
|
+
const stack = createStack();
|
|
58
|
+
function flushInputBuffer() {
|
|
59
|
+
while (iFlushed < i - bufferSize - chunkSize) {
|
|
60
|
+
iFlushed += chunkSize;
|
|
61
|
+
input.flush(iFlushed);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function transform(chunk) {
|
|
65
|
+
input.push(chunk);
|
|
66
|
+
while (i < input.currentLength() - bufferSize && parse()) {
|
|
67
|
+
}
|
|
68
|
+
flushInputBuffer();
|
|
69
|
+
}
|
|
70
|
+
function flush() {
|
|
71
|
+
input.close();
|
|
72
|
+
while (parse()) {
|
|
73
|
+
}
|
|
74
|
+
output.flush();
|
|
75
|
+
}
|
|
76
|
+
function parse() {
|
|
77
|
+
parseWhitespaceAndSkipComments();
|
|
78
|
+
switch (stack.type) {
|
|
79
|
+
case StackType.object: {
|
|
80
|
+
switch (stack.caret) {
|
|
81
|
+
case Caret.beforeKey:
|
|
82
|
+
return skipEllipsis() || parseObjectKey() || parseUnexpectedColon() || parseRepairTrailingComma() || parseRepairObjectEndOrComma();
|
|
83
|
+
case Caret.beforeValue:
|
|
84
|
+
return parseValue() || parseRepairMissingObjectValue();
|
|
85
|
+
case Caret.afterValue:
|
|
86
|
+
return parseObjectComma() || parseObjectEnd() || parseRepairObjectEndOrComma();
|
|
87
|
+
default:
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
case StackType.array: {
|
|
92
|
+
switch (stack.caret) {
|
|
93
|
+
case Caret.beforeValue:
|
|
94
|
+
return skipEllipsis() || parseValue() || parseRepairTrailingComma() || parseRepairArrayEnd();
|
|
95
|
+
case Caret.afterValue:
|
|
96
|
+
return parseArrayComma() || parseArrayEnd() || parseRepairMissingComma() || parseRepairArrayEnd();
|
|
97
|
+
default:
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
case StackType.ndJson: {
|
|
102
|
+
switch (stack.caret) {
|
|
103
|
+
case Caret.beforeValue:
|
|
104
|
+
return parseValue() || parseRepairTrailingComma();
|
|
105
|
+
case Caret.afterValue:
|
|
106
|
+
return parseArrayComma() || parseRepairMissingComma() || parseRepairNdJsonEnd();
|
|
107
|
+
default:
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
case StackType.functionCall: {
|
|
112
|
+
switch (stack.caret) {
|
|
113
|
+
case Caret.beforeValue:
|
|
114
|
+
return parseValue();
|
|
115
|
+
case Caret.afterValue:
|
|
116
|
+
return parseFunctionCallEnd();
|
|
117
|
+
default:
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
case StackType.root: {
|
|
122
|
+
switch (stack.caret) {
|
|
123
|
+
case Caret.beforeValue:
|
|
124
|
+
return parseRootStart();
|
|
125
|
+
case Caret.afterValue:
|
|
126
|
+
return parseRootEnd();
|
|
127
|
+
default:
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
default:
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
function parseValue() {
|
|
136
|
+
return parseObjectStart() || parseArrayStart() || parseString() || parseNumber() || parseKeywords() || parseRepairUnquotedString() || parseRepairRegex() || false;
|
|
137
|
+
}
|
|
138
|
+
function parseObjectStart() {
|
|
139
|
+
if (parseCharacter("{")) {
|
|
140
|
+
parseWhitespaceAndSkipComments();
|
|
141
|
+
skipEllipsis();
|
|
142
|
+
if (skipCharacter(",")) {
|
|
143
|
+
parseWhitespaceAndSkipComments();
|
|
144
|
+
}
|
|
145
|
+
if (parseCharacter("}")) {
|
|
146
|
+
return stack.update(Caret.afterValue);
|
|
147
|
+
}
|
|
148
|
+
return stack.push(StackType.object, Caret.beforeKey);
|
|
149
|
+
}
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
function parseArrayStart() {
|
|
153
|
+
if (parseCharacter("[")) {
|
|
154
|
+
parseWhitespaceAndSkipComments();
|
|
155
|
+
skipEllipsis();
|
|
156
|
+
if (skipCharacter(",")) {
|
|
157
|
+
parseWhitespaceAndSkipComments();
|
|
158
|
+
}
|
|
159
|
+
if (parseCharacter("]")) {
|
|
160
|
+
return stack.update(Caret.afterValue);
|
|
161
|
+
}
|
|
162
|
+
return stack.push(StackType.array, Caret.beforeValue);
|
|
163
|
+
}
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
function parseRepairUnquotedString() {
|
|
167
|
+
let j = i;
|
|
168
|
+
if (isFunctionNameCharStart(input.charAt(j))) {
|
|
169
|
+
while (!input.isEnd(j) && isFunctionNameChar(input.charAt(j))) {
|
|
170
|
+
j++;
|
|
171
|
+
}
|
|
172
|
+
let k = j;
|
|
173
|
+
while (isWhitespace(input, k)) {
|
|
174
|
+
k++;
|
|
175
|
+
}
|
|
176
|
+
if (input.charAt(k) === "(") {
|
|
177
|
+
k++;
|
|
178
|
+
i = k;
|
|
179
|
+
return stack.push(StackType.functionCall, Caret.beforeValue);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
const nextDelimiter = findNextDelimiter(false, j);
|
|
183
|
+
if (nextDelimiter === null) {
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
j = nextDelimiter;
|
|
187
|
+
if (j !== null) {
|
|
188
|
+
if (input.charAt(j - 1) === ":" && regexUrlStart.test(input.substring(i, j + 2))) {
|
|
189
|
+
while (!input.isEnd(j) && regexUrlChar.test(input.charAt(j))) {
|
|
190
|
+
j++;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
const symbol = input.substring(i, j);
|
|
194
|
+
i = j;
|
|
195
|
+
output.push(symbol === "undefined" ? "null" : JSON.stringify(symbol));
|
|
196
|
+
if (input.charAt(i) === '"') {
|
|
197
|
+
i++;
|
|
198
|
+
}
|
|
199
|
+
return stack.update(Caret.afterValue);
|
|
200
|
+
}
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
function parseRepairRegex() {
|
|
204
|
+
if (input.charAt(i) === "/") {
|
|
205
|
+
const start = i;
|
|
206
|
+
i++;
|
|
207
|
+
while (!input.isEnd(i) && (input.charAt(i) !== "/" || input.charAt(i - 1) === "\\")) {
|
|
208
|
+
i++;
|
|
209
|
+
}
|
|
210
|
+
i++;
|
|
211
|
+
output.push(`"${input.substring(start, i)}"`);
|
|
212
|
+
return stack.update(Caret.afterValue);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
function parseRepairMissingObjectValue() {
|
|
216
|
+
output.push("null");
|
|
217
|
+
return stack.update(Caret.afterValue);
|
|
218
|
+
}
|
|
219
|
+
function parseRepairTrailingComma() {
|
|
220
|
+
if (output.endsWithIgnoringWhitespace(",")) {
|
|
221
|
+
output.stripLastOccurrence(",");
|
|
222
|
+
return stack.update(Caret.afterValue);
|
|
223
|
+
}
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
function parseUnexpectedColon() {
|
|
227
|
+
if (input.charAt(i) === ":") {
|
|
228
|
+
throwObjectKeyExpected();
|
|
229
|
+
}
|
|
230
|
+
return false;
|
|
231
|
+
}
|
|
232
|
+
function parseUnexpectedEnd() {
|
|
233
|
+
if (input.isEnd(i)) {
|
|
234
|
+
throwUnexpectedEnd();
|
|
235
|
+
} else {
|
|
236
|
+
throwUnexpectedCharacter();
|
|
237
|
+
}
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
function parseObjectKey() {
|
|
241
|
+
const parsedKey = parseString() || parseUnquotedKey();
|
|
242
|
+
if (parsedKey) {
|
|
243
|
+
parseWhitespaceAndSkipComments();
|
|
244
|
+
if (parseCharacter(":")) {
|
|
245
|
+
return stack.update(Caret.beforeValue);
|
|
246
|
+
}
|
|
247
|
+
const truncatedText = input.isEnd(i);
|
|
248
|
+
if (isStartOfValue(input.charAt(i)) || truncatedText) {
|
|
249
|
+
output.insertBeforeLastWhitespace(":");
|
|
250
|
+
return stack.update(Caret.beforeValue);
|
|
251
|
+
}
|
|
252
|
+
throwColonExpected();
|
|
253
|
+
}
|
|
254
|
+
return false;
|
|
255
|
+
}
|
|
256
|
+
function parseObjectComma() {
|
|
257
|
+
if (parseCharacter(",")) {
|
|
258
|
+
return stack.update(Caret.beforeKey);
|
|
259
|
+
}
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
function parseObjectEnd() {
|
|
263
|
+
if (parseCharacter("}")) {
|
|
264
|
+
return stack.pop();
|
|
265
|
+
}
|
|
266
|
+
return false;
|
|
267
|
+
}
|
|
268
|
+
function parseRepairObjectEndOrComma() {
|
|
269
|
+
if (input.charAt(i) === "{") {
|
|
270
|
+
output.stripLastOccurrence(",");
|
|
271
|
+
output.insertBeforeLastWhitespace("}");
|
|
272
|
+
return stack.pop();
|
|
273
|
+
}
|
|
274
|
+
if (!input.isEnd(i) && isStartOfValue(input.charAt(i))) {
|
|
275
|
+
output.insertBeforeLastWhitespace(",");
|
|
276
|
+
return stack.update(Caret.beforeKey);
|
|
277
|
+
}
|
|
278
|
+
output.insertBeforeLastWhitespace("}");
|
|
279
|
+
return stack.pop();
|
|
280
|
+
}
|
|
281
|
+
function parseArrayComma() {
|
|
282
|
+
if (parseCharacter(",")) {
|
|
283
|
+
return stack.update(Caret.beforeValue);
|
|
284
|
+
}
|
|
285
|
+
return false;
|
|
286
|
+
}
|
|
287
|
+
function parseArrayEnd() {
|
|
288
|
+
if (parseCharacter("]")) {
|
|
289
|
+
return stack.pop();
|
|
290
|
+
}
|
|
291
|
+
return false;
|
|
292
|
+
}
|
|
293
|
+
function parseRepairMissingComma() {
|
|
294
|
+
if (!input.isEnd(i) && isStartOfValue(input.charAt(i))) {
|
|
295
|
+
output.insertBeforeLastWhitespace(",");
|
|
296
|
+
return stack.update(Caret.beforeValue);
|
|
297
|
+
}
|
|
298
|
+
return false;
|
|
299
|
+
}
|
|
300
|
+
function parseRepairArrayEnd() {
|
|
301
|
+
output.insertBeforeLastWhitespace("]");
|
|
302
|
+
return stack.pop();
|
|
303
|
+
}
|
|
304
|
+
function parseRepairNdJsonEnd() {
|
|
305
|
+
if (input.isEnd(i)) {
|
|
306
|
+
output.push("\n]");
|
|
307
|
+
return stack.pop();
|
|
308
|
+
}
|
|
309
|
+
throwUnexpectedEnd();
|
|
310
|
+
return false;
|
|
311
|
+
}
|
|
312
|
+
function parseFunctionCallEnd() {
|
|
313
|
+
if (skipCharacter(")")) {
|
|
314
|
+
skipCharacter(";");
|
|
315
|
+
}
|
|
316
|
+
return stack.pop();
|
|
317
|
+
}
|
|
318
|
+
function parseRootStart() {
|
|
319
|
+
parseMarkdownCodeBlock();
|
|
320
|
+
return parseValue() || parseUnexpectedEnd();
|
|
321
|
+
}
|
|
322
|
+
function parseRootEnd() {
|
|
323
|
+
parseMarkdownCodeBlock();
|
|
324
|
+
const parsedComma = parseCharacter(",");
|
|
325
|
+
parseWhitespaceAndSkipComments();
|
|
326
|
+
if (isStartOfValue(input.charAt(i)) && (output.endsWithIgnoringWhitespace(",") || output.endsWithIgnoringWhitespace("\n"))) {
|
|
327
|
+
if (!parsedComma) {
|
|
328
|
+
output.insertBeforeLastWhitespace(",");
|
|
329
|
+
}
|
|
330
|
+
output.unshift("[\n");
|
|
331
|
+
return stack.push(StackType.ndJson, Caret.beforeValue);
|
|
332
|
+
}
|
|
333
|
+
if (parsedComma) {
|
|
334
|
+
output.stripLastOccurrence(",");
|
|
335
|
+
return stack.update(Caret.afterValue);
|
|
336
|
+
}
|
|
337
|
+
while (input.charAt(i) === "}" || input.charAt(i) === "]") {
|
|
338
|
+
i++;
|
|
339
|
+
parseWhitespaceAndSkipComments();
|
|
340
|
+
}
|
|
341
|
+
if (!input.isEnd(i)) {
|
|
342
|
+
throwUnexpectedCharacter();
|
|
343
|
+
}
|
|
344
|
+
return false;
|
|
345
|
+
}
|
|
346
|
+
function parseWhitespaceAndSkipComments(skipNewline = true) {
|
|
347
|
+
const start = i;
|
|
348
|
+
let changed = parseWhitespace(skipNewline);
|
|
349
|
+
do {
|
|
350
|
+
changed = parseComment();
|
|
351
|
+
if (changed) {
|
|
352
|
+
changed = parseWhitespace(skipNewline);
|
|
353
|
+
}
|
|
354
|
+
} while (changed);
|
|
355
|
+
return i > start;
|
|
356
|
+
}
|
|
357
|
+
function parseWhitespace(skipNewline) {
|
|
358
|
+
const _isWhiteSpace = skipNewline ? isWhitespace : isWhitespaceExceptNewline;
|
|
359
|
+
let whitespace = "";
|
|
360
|
+
while (true) {
|
|
361
|
+
if (_isWhiteSpace(input, i)) {
|
|
362
|
+
whitespace += input.charAt(i);
|
|
363
|
+
i++;
|
|
364
|
+
} else if (isSpecialWhitespace(input, i)) {
|
|
365
|
+
whitespace += " ";
|
|
366
|
+
i++;
|
|
367
|
+
} else {
|
|
368
|
+
break;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
if (whitespace.length > 0) {
|
|
372
|
+
output.push(whitespace);
|
|
373
|
+
return true;
|
|
374
|
+
}
|
|
375
|
+
return false;
|
|
376
|
+
}
|
|
377
|
+
function parseComment() {
|
|
378
|
+
if (input.charAt(i) === "/" && input.charAt(i + 1) === "*") {
|
|
379
|
+
while (!input.isEnd(i) && !atEndOfBlockComment(i)) {
|
|
380
|
+
i++;
|
|
381
|
+
}
|
|
382
|
+
i += 2;
|
|
383
|
+
return true;
|
|
384
|
+
}
|
|
385
|
+
if (input.charAt(i) === "/" && input.charAt(i + 1) === "/") {
|
|
386
|
+
while (!input.isEnd(i) && input.charAt(i) !== "\n") {
|
|
387
|
+
i++;
|
|
388
|
+
}
|
|
389
|
+
return true;
|
|
390
|
+
}
|
|
391
|
+
return false;
|
|
392
|
+
}
|
|
393
|
+
function parseMarkdownCodeBlock() {
|
|
394
|
+
if (input.substring(i, i + 3) === "```") {
|
|
395
|
+
i += 3;
|
|
396
|
+
if (isFunctionNameCharStart(input.charAt(i))) {
|
|
397
|
+
while (!input.isEnd(i) && isFunctionNameChar(input.charAt(i))) {
|
|
398
|
+
i++;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
parseWhitespaceAndSkipComments();
|
|
402
|
+
return true;
|
|
403
|
+
}
|
|
404
|
+
return false;
|
|
405
|
+
}
|
|
406
|
+
function parseCharacter(char) {
|
|
407
|
+
if (input.charAt(i) === char) {
|
|
408
|
+
output.push(input.charAt(i));
|
|
409
|
+
i++;
|
|
410
|
+
return true;
|
|
411
|
+
}
|
|
412
|
+
return false;
|
|
413
|
+
}
|
|
414
|
+
function skipCharacter(char) {
|
|
415
|
+
if (input.charAt(i) === char) {
|
|
416
|
+
i++;
|
|
417
|
+
return true;
|
|
418
|
+
}
|
|
419
|
+
return false;
|
|
420
|
+
}
|
|
421
|
+
function skipEscapeCharacter() {
|
|
422
|
+
return skipCharacter("\\");
|
|
423
|
+
}
|
|
424
|
+
function skipEllipsis() {
|
|
425
|
+
parseWhitespaceAndSkipComments();
|
|
426
|
+
if (input.charAt(i) === "." && input.charAt(i + 1) === "." && input.charAt(i + 2) === ".") {
|
|
427
|
+
i += 3;
|
|
428
|
+
parseWhitespaceAndSkipComments();
|
|
429
|
+
skipCharacter(",");
|
|
430
|
+
return true;
|
|
431
|
+
}
|
|
432
|
+
return false;
|
|
433
|
+
}
|
|
434
|
+
function parseString(stopAtDelimiter = false, stopAtIndex = -1) {
|
|
435
|
+
let skipEscapeChars = input.charAt(i) === "\\";
|
|
436
|
+
if (skipEscapeChars) {
|
|
437
|
+
i++;
|
|
438
|
+
skipEscapeChars = true;
|
|
439
|
+
}
|
|
440
|
+
if (isQuote(input.charAt(i))) {
|
|
441
|
+
const isEndQuote = isDoubleQuote(input.charAt(i)) ? isDoubleQuote : isSingleQuote(input.charAt(i)) ? isSingleQuote : isSingleQuoteLike(input.charAt(i)) ? isSingleQuoteLike : isDoubleQuoteLike;
|
|
442
|
+
const iBefore = i;
|
|
443
|
+
const oBefore = output.length();
|
|
444
|
+
output.push('"');
|
|
445
|
+
i++;
|
|
446
|
+
while (true) {
|
|
447
|
+
if (input.isEnd(i)) {
|
|
448
|
+
const iPrev = prevNonWhitespaceIndex(i - 1);
|
|
449
|
+
if (!stopAtDelimiter && isDelimiter(input.charAt(iPrev))) {
|
|
450
|
+
i = iBefore;
|
|
451
|
+
output.remove(oBefore);
|
|
452
|
+
return parseString(true);
|
|
453
|
+
}
|
|
454
|
+
output.insertBeforeLastWhitespace('"');
|
|
455
|
+
return stack.update(Caret.afterValue);
|
|
456
|
+
} else if (i === stopAtIndex) {
|
|
457
|
+
output.insertBeforeLastWhitespace('"');
|
|
458
|
+
return stack.update(Caret.afterValue);
|
|
459
|
+
} else if (isEndQuote(input.charAt(i))) {
|
|
460
|
+
const iQuote = i;
|
|
461
|
+
const oQuote = output.length();
|
|
462
|
+
output.push('"');
|
|
463
|
+
i++;
|
|
464
|
+
parseWhitespaceAndSkipComments(false);
|
|
465
|
+
if (stopAtDelimiter || input.isEnd(i) || isDelimiter(input.charAt(i)) || isQuote(input.charAt(i)) || isDigit(input.charAt(i))) {
|
|
466
|
+
parseConcatenatedString();
|
|
467
|
+
return stack.update(Caret.afterValue);
|
|
468
|
+
}
|
|
469
|
+
const iPrevChar = prevNonWhitespaceIndex(iQuote - 1);
|
|
470
|
+
const prevChar = input.charAt(iPrevChar);
|
|
471
|
+
if (prevChar === ",") {
|
|
472
|
+
i = iBefore;
|
|
473
|
+
output.remove(oBefore);
|
|
474
|
+
return parseString(false, iPrevChar);
|
|
475
|
+
}
|
|
476
|
+
if (isDelimiter(prevChar)) {
|
|
477
|
+
i = iBefore;
|
|
478
|
+
output.remove(oBefore);
|
|
479
|
+
return parseString(true);
|
|
480
|
+
}
|
|
481
|
+
output.remove(oQuote + 1);
|
|
482
|
+
i = iQuote + 1;
|
|
483
|
+
output.insertAt(oQuote, "\\");
|
|
484
|
+
} else if (stopAtDelimiter && isUnquotedStringDelimiter(input.charAt(i))) {
|
|
485
|
+
if (input.charAt(i - 1) === ":" && regexUrlStart.test(input.substring(iBefore + 1, i + 2))) {
|
|
486
|
+
while (!input.isEnd(i) && regexUrlChar.test(input.charAt(i))) {
|
|
487
|
+
output.push(input.charAt(i));
|
|
488
|
+
i++;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
output.insertBeforeLastWhitespace('"');
|
|
492
|
+
parseConcatenatedString();
|
|
493
|
+
return stack.update(Caret.afterValue);
|
|
494
|
+
} else if (input.charAt(i) === "\\") {
|
|
495
|
+
const char = input.charAt(i + 1);
|
|
496
|
+
const escapeChar = escapeCharacters[char];
|
|
497
|
+
if (escapeChar !== void 0) {
|
|
498
|
+
output.push(input.substring(i, i + 2));
|
|
499
|
+
i += 2;
|
|
500
|
+
} else if (char === "u") {
|
|
501
|
+
let j = 2;
|
|
502
|
+
while (j < 6 && isHex(input.charAt(i + j))) {
|
|
503
|
+
j++;
|
|
504
|
+
}
|
|
505
|
+
if (j === 6) {
|
|
506
|
+
output.push(input.substring(i, i + 6));
|
|
507
|
+
i += 6;
|
|
508
|
+
} else if (input.isEnd(i + j)) {
|
|
509
|
+
i += j;
|
|
510
|
+
} else {
|
|
511
|
+
throwInvalidUnicodeCharacter();
|
|
512
|
+
}
|
|
513
|
+
} else {
|
|
514
|
+
output.push(char);
|
|
515
|
+
i += 2;
|
|
516
|
+
}
|
|
517
|
+
} else {
|
|
518
|
+
const char = input.charAt(i);
|
|
519
|
+
if (char === '"' && input.charAt(i - 1) !== "\\") {
|
|
520
|
+
output.push(`\\${char}`);
|
|
521
|
+
i++;
|
|
522
|
+
} else if (isControlCharacter(char)) {
|
|
523
|
+
const escaped = controlCharacters[char];
|
|
524
|
+
if (escaped === void 0) {
|
|
525
|
+
throwInvalidCharacter(char);
|
|
526
|
+
}
|
|
527
|
+
output.push(escaped);
|
|
528
|
+
i++;
|
|
529
|
+
} else {
|
|
530
|
+
if (!isValidStringCharacter(char)) {
|
|
531
|
+
throwInvalidCharacter(char);
|
|
532
|
+
}
|
|
533
|
+
output.push(char);
|
|
534
|
+
i++;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
if (skipEscapeChars) {
|
|
538
|
+
skipEscapeCharacter();
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
return false;
|
|
543
|
+
}
|
|
544
|
+
function parseConcatenatedString() {
|
|
545
|
+
let parsed = false;
|
|
546
|
+
parseWhitespaceAndSkipComments();
|
|
547
|
+
while (input.charAt(i) === "+") {
|
|
548
|
+
parsed = true;
|
|
549
|
+
i++;
|
|
550
|
+
parseWhitespaceAndSkipComments();
|
|
551
|
+
output.stripLastOccurrence('"', true);
|
|
552
|
+
const start = output.length();
|
|
553
|
+
const parsedStr = parseString();
|
|
554
|
+
if (parsedStr) {
|
|
555
|
+
output.remove(start, start + 1);
|
|
556
|
+
} else {
|
|
557
|
+
output.insertBeforeLastWhitespace('"');
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
return parsed;
|
|
561
|
+
}
|
|
562
|
+
function parseNumber() {
|
|
563
|
+
const start = i;
|
|
564
|
+
if (input.charAt(i) === "-") {
|
|
565
|
+
i++;
|
|
566
|
+
if (atEndOfNumber()) {
|
|
567
|
+
repairNumberEndingWithNumericSymbol(start);
|
|
568
|
+
return stack.update(Caret.afterValue);
|
|
569
|
+
}
|
|
570
|
+
if (!isDigit(input.charAt(i))) {
|
|
571
|
+
i = start;
|
|
572
|
+
return false;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
while (isDigit(input.charAt(i))) {
|
|
576
|
+
i++;
|
|
577
|
+
}
|
|
578
|
+
if (input.charAt(i) === ".") {
|
|
579
|
+
i++;
|
|
580
|
+
if (atEndOfNumber()) {
|
|
581
|
+
repairNumberEndingWithNumericSymbol(start);
|
|
582
|
+
return stack.update(Caret.afterValue);
|
|
583
|
+
}
|
|
584
|
+
if (!isDigit(input.charAt(i))) {
|
|
585
|
+
i = start;
|
|
586
|
+
return false;
|
|
587
|
+
}
|
|
588
|
+
while (isDigit(input.charAt(i))) {
|
|
589
|
+
i++;
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
if (input.charAt(i) === "e" || input.charAt(i) === "E") {
|
|
593
|
+
i++;
|
|
594
|
+
if (input.charAt(i) === "-" || input.charAt(i) === "+") {
|
|
595
|
+
i++;
|
|
596
|
+
}
|
|
597
|
+
if (atEndOfNumber()) {
|
|
598
|
+
repairNumberEndingWithNumericSymbol(start);
|
|
599
|
+
return stack.update(Caret.afterValue);
|
|
600
|
+
}
|
|
601
|
+
if (!isDigit(input.charAt(i))) {
|
|
602
|
+
i = start;
|
|
603
|
+
return false;
|
|
604
|
+
}
|
|
605
|
+
while (isDigit(input.charAt(i))) {
|
|
606
|
+
i++;
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
if (!atEndOfNumber()) {
|
|
610
|
+
i = start;
|
|
611
|
+
return false;
|
|
612
|
+
}
|
|
613
|
+
if (i > start) {
|
|
614
|
+
const num = input.substring(start, i);
|
|
615
|
+
const hasInvalidLeadingZero = /^0\d/.test(num);
|
|
616
|
+
output.push(hasInvalidLeadingZero ? `"${num}"` : num);
|
|
617
|
+
return stack.update(Caret.afterValue);
|
|
618
|
+
}
|
|
619
|
+
return false;
|
|
620
|
+
}
|
|
621
|
+
function parseKeywords() {
|
|
622
|
+
return parseKeyword("true", "true") || parseKeyword("false", "false") || parseKeyword("null", "null") || // repair Python keywords True, False, None
|
|
623
|
+
parseKeyword("True", "true") || parseKeyword("False", "false") || parseKeyword("None", "null");
|
|
624
|
+
}
|
|
625
|
+
function parseKeyword(name, value) {
|
|
626
|
+
if (input.substring(i, i + name.length) === name) {
|
|
627
|
+
output.push(value);
|
|
628
|
+
i += name.length;
|
|
629
|
+
return stack.update(Caret.afterValue);
|
|
630
|
+
}
|
|
631
|
+
return false;
|
|
632
|
+
}
|
|
633
|
+
function parseUnquotedKey() {
|
|
634
|
+
let end = findNextDelimiter(true, i);
|
|
635
|
+
if (end !== null) {
|
|
636
|
+
while (isWhitespace(input, end - 1) && end > i) {
|
|
637
|
+
end--;
|
|
638
|
+
}
|
|
639
|
+
const symbol = input.substring(i, end);
|
|
640
|
+
output.push(JSON.stringify(symbol));
|
|
641
|
+
i = end;
|
|
642
|
+
if (input.charAt(i) === '"') {
|
|
643
|
+
i++;
|
|
644
|
+
}
|
|
645
|
+
return stack.update(Caret.afterValue);
|
|
646
|
+
}
|
|
647
|
+
return false;
|
|
648
|
+
}
|
|
649
|
+
function findNextDelimiter(isKey, start) {
|
|
650
|
+
let j = start;
|
|
651
|
+
while (!input.isEnd(j) && !isUnquotedStringDelimiter(input.charAt(j)) && !isQuote(input.charAt(j)) && (!isKey || input.charAt(j) !== ":")) {
|
|
652
|
+
j++;
|
|
653
|
+
}
|
|
654
|
+
return j > i ? j : null;
|
|
655
|
+
}
|
|
656
|
+
function prevNonWhitespaceIndex(start) {
|
|
657
|
+
let prev = start;
|
|
658
|
+
while (prev > 0 && isWhitespace(input, prev)) {
|
|
659
|
+
prev--;
|
|
660
|
+
}
|
|
661
|
+
return prev;
|
|
662
|
+
}
|
|
663
|
+
function atEndOfNumber() {
|
|
664
|
+
return input.isEnd(i) || isDelimiter(input.charAt(i)) || isWhitespace(input, i);
|
|
665
|
+
}
|
|
666
|
+
function repairNumberEndingWithNumericSymbol(start) {
|
|
667
|
+
output.push(`${input.substring(start, i)}0`);
|
|
668
|
+
}
|
|
669
|
+
function throwInvalidCharacter(char) {
|
|
670
|
+
throw new JSONRepairError(`Invalid character ${JSON.stringify(char)}`, i);
|
|
671
|
+
}
|
|
672
|
+
function throwUnexpectedCharacter() {
|
|
673
|
+
throw new JSONRepairError(`Unexpected character ${JSON.stringify(input.charAt(i))}`, i);
|
|
674
|
+
}
|
|
675
|
+
function throwUnexpectedEnd() {
|
|
676
|
+
throw new JSONRepairError("Unexpected end of json string", i);
|
|
677
|
+
}
|
|
678
|
+
function throwObjectKeyExpected() {
|
|
679
|
+
throw new JSONRepairError("Object key expected", i);
|
|
680
|
+
}
|
|
681
|
+
function throwColonExpected() {
|
|
682
|
+
throw new JSONRepairError("Colon expected", i);
|
|
683
|
+
}
|
|
684
|
+
function throwInvalidUnicodeCharacter() {
|
|
685
|
+
const chars = input.substring(i, i + 6);
|
|
686
|
+
throw new JSONRepairError(`Invalid unicode character "${chars}"`, i);
|
|
687
|
+
}
|
|
688
|
+
function atEndOfBlockComment(i2) {
|
|
689
|
+
return input.charAt(i2) === "*" && input.charAt(i2 + 1) === "/";
|
|
690
|
+
}
|
|
691
|
+
return {
|
|
692
|
+
transform,
|
|
693
|
+
flush
|
|
694
|
+
};
|
|
695
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Transform } from "node:stream";
|
|
2
|
+
interface JsonlOptions {
|
|
3
|
+
chunkSize?: number;
|
|
4
|
+
reviver?: (key: string, value: unknown) => unknown;
|
|
5
|
+
replacer?: (key: string, value: unknown) => unknown | (number | string)[] | null;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Creates a transform stream that parses JSONL (JSON Lines) data.
|
|
9
|
+
*
|
|
10
|
+
* @param options - Parser options
|
|
11
|
+
* @returns A transform stream that emits parsed JSON objects
|
|
12
|
+
*/
|
|
13
|
+
export declare function createJsonlParser(options?: JsonlOptions): Transform;
|
|
14
|
+
/**
|
|
15
|
+
* Creates a transform stream that writes JSONL (JSON Lines) data.
|
|
16
|
+
*
|
|
17
|
+
* @param options - Writer options
|
|
18
|
+
* @returns A transform stream that accepts objects and outputs JSONL strings
|
|
19
|
+
*/
|
|
20
|
+
export declare function createJsonlWriter(options?: JsonlOptions): Transform;
|
|
21
|
+
export {};
|