jsonfixerdev 1.0.3 → 1.0.4

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.
Files changed (67) hide show
  1. package/package.json +2 -3
  2. package/lib/cjs/index.js +0 -20
  3. package/lib/cjs/index.js.map +0 -1
  4. package/lib/cjs/package.json +0 -3
  5. package/lib/cjs/regular/jsonfixer.js +0 -606
  6. package/lib/cjs/regular/jsonfixer.js.map +0 -1
  7. package/lib/cjs/stream.js +0 -13
  8. package/lib/cjs/stream.js.map +0 -1
  9. package/lib/cjs/streaming/buffer/InputBuffer.js +0 -75
  10. package/lib/cjs/streaming/buffer/InputBuffer.js.map +0 -1
  11. package/lib/cjs/streaming/buffer/OutputBuffer.js +0 -110
  12. package/lib/cjs/streaming/buffer/OutputBuffer.js.map +0 -1
  13. package/lib/cjs/streaming/core.js +0 -674
  14. package/lib/cjs/streaming/core.js.map +0 -1
  15. package/lib/cjs/streaming/stack.js +0 -51
  16. package/lib/cjs/streaming/stack.js.map +0 -1
  17. package/lib/cjs/streaming/stream.js +0 -37
  18. package/lib/cjs/streaming/stream.js.map +0 -1
  19. package/lib/cjs/utils/JSONFixerError.js +0 -15
  20. package/lib/cjs/utils/JSONFixerError.js.map +0 -1
  21. package/lib/cjs/utils/stringUtils.js +0 -186
  22. package/lib/cjs/utils/stringUtils.js.map +0 -1
  23. package/lib/esm/index.js +0 -4
  24. package/lib/esm/index.js.map +0 -1
  25. package/lib/esm/regular/jsonfixer.js +0 -600
  26. package/lib/esm/regular/jsonfixer.js.map +0 -1
  27. package/lib/esm/stream.js +0 -3
  28. package/lib/esm/stream.js.map +0 -1
  29. package/lib/esm/streaming/buffer/InputBuffer.js +0 -69
  30. package/lib/esm/streaming/buffer/InputBuffer.js.map +0 -1
  31. package/lib/esm/streaming/buffer/OutputBuffer.js +0 -104
  32. package/lib/esm/streaming/buffer/OutputBuffer.js.map +0 -1
  33. package/lib/esm/streaming/core.js +0 -668
  34. package/lib/esm/streaming/core.js.map +0 -1
  35. package/lib/esm/streaming/stack.js +0 -44
  36. package/lib/esm/streaming/stack.js.map +0 -1
  37. package/lib/esm/streaming/stream.js +0 -31
  38. package/lib/esm/streaming/stream.js.map +0 -1
  39. package/lib/esm/utils/JSONFixerError.js +0 -8
  40. package/lib/esm/utils/JSONFixerError.js.map +0 -1
  41. package/lib/esm/utils/stringUtils.js +0 -162
  42. package/lib/esm/utils/stringUtils.js.map +0 -1
  43. package/lib/types/index.d.ts +0 -3
  44. package/lib/types/index.d.ts.map +0 -1
  45. package/lib/types/regular/jsonfixer.d.ts +0 -18
  46. package/lib/types/regular/jsonfixer.d.ts.map +0 -1
  47. package/lib/types/stream.d.ts +0 -2
  48. package/lib/types/stream.d.ts.map +0 -1
  49. package/lib/types/streaming/buffer/InputBuffer.d.ts +0 -14
  50. package/lib/types/streaming/buffer/InputBuffer.d.ts.map +0 -1
  51. package/lib/types/streaming/buffer/OutputBuffer.d.ts +0 -17
  52. package/lib/types/streaming/buffer/OutputBuffer.d.ts.map +0 -1
  53. package/lib/types/streaming/core.d.ts +0 -11
  54. package/lib/types/streaming/core.d.ts.map +0 -1
  55. package/lib/types/streaming/stack.d.ts +0 -20
  56. package/lib/types/streaming/stack.d.ts.map +0 -1
  57. package/lib/types/streaming/stream.d.ts +0 -8
  58. package/lib/types/streaming/stream.d.ts.map +0 -1
  59. package/lib/types/utils/JSONFixerError.d.ts +0 -5
  60. package/lib/types/utils/JSONFixerError.d.ts.map +0 -1
  61. package/lib/types/utils/stringUtils.d.ts +0 -84
  62. package/lib/types/utils/stringUtils.d.ts.map +0 -1
  63. package/lib/umd/jsonfixer.js +0 -775
  64. package/lib/umd/jsonfixer.js.map +0 -1
  65. package/lib/umd/jsonfixer.min.js +0 -3
  66. package/lib/umd/jsonfixer.min.js.map +0 -1
  67. package/lib/umd/package.json +0 -3
@@ -1,668 +0,0 @@
1
- import { createInputBuffer } from './buffer/InputBuffer.js';
2
- import { createOutputBuffer } from './buffer/OutputBuffer.js';
3
- import { JSONFixerError } from '../utils/JSONFixerError.js';
4
- import { Caret, createStack, StackType } from './stack.js';
5
- import { codeAsterisk, codeBackslash, codeCloseParenthesis, codeClosingBrace, codeClosingBracket, codeColon, codeComma, codeDot, codeDoubleQuote, codeLowercaseE, codeMinus, codeNewline, codeOpeningBrace, codeOpeningBracket, codeOpenParenthesis, codePlus, codeSemicolon, codeSlash, codeUppercaseE, isControlCharacter, isDelimiter, isDigit, isDoubleQuote, isDoubleQuoteLike, isHex, isQuote, isSingleQuote, isSingleQuoteLike, isSpecialWhitespace, isStartOfValue, isValidStringCharacter, isWhitespace } from '../utils/stringUtils.js';
6
- const controlCharacters = {
7
- '\b': '\\b',
8
- '\f': '\\f',
9
- '\n': '\\n',
10
- '\r': '\\r',
11
- '\t': '\\t'
12
- };
13
-
14
- // map with all escape characters
15
- const escapeCharacters = {
16
- '"': '"',
17
- '\\': '\\',
18
- '/': '/',
19
- b: '\b',
20
- f: '\f',
21
- n: '\n',
22
- r: '\r',
23
- t: '\t'
24
- // note that \u is handled separately in parseString()
25
- };
26
- export function jsonfixerCore(_ref) {
27
- let {
28
- onData,
29
- bufferSize = 65536,
30
- chunkSize = 65536
31
- } = _ref;
32
- const input = createInputBuffer();
33
- const output = createOutputBuffer({
34
- write: onData,
35
- bufferSize,
36
- chunkSize
37
- });
38
- let i = 0;
39
- let iFlushed = 0;
40
- const stack = createStack();
41
- function flushInputBuffer() {
42
- while (iFlushed < i - bufferSize - chunkSize) {
43
- iFlushed += chunkSize;
44
- input.flush(iFlushed);
45
- }
46
- }
47
- function transform(chunk) {
48
- input.push(chunk);
49
- while (i < input.currentLength() - bufferSize && parse()) {
50
- // loop until there is nothing more to process
51
- }
52
- flushInputBuffer();
53
- }
54
- function flush() {
55
- input.close();
56
- while (parse()) {
57
- // loop until there is nothing more to process
58
- }
59
- output.flush();
60
- }
61
- function parse() {
62
- parseWhitespaceAndSkipComments();
63
- switch (stack.type) {
64
- case StackType.object:
65
- {
66
- switch (stack.caret) {
67
- case Caret.beforeKey:
68
- return parseObjectKey() || parseUnexpectedColon() || parseRepairTrailingComma() || parseRepairObjectEndOrComma();
69
- case Caret.beforeValue:
70
- return parseValue() || parseRepairMissingObjectValue();
71
- case Caret.afterValue:
72
- return parseObjectComma() || parseObjectEnd() || parseRepairObjectEndOrComma();
73
- default:
74
- return false;
75
- }
76
- }
77
- case StackType.array:
78
- {
79
- switch (stack.caret) {
80
- case Caret.beforeValue:
81
- return parseValue() || parseRepairTrailingComma() || parseRepairArrayEnd();
82
- case Caret.afterValue:
83
- return parseArrayComma() || parseArrayEnd() || parseRepairMissingComma() || parseRepairArrayEnd();
84
- default:
85
- return false;
86
- }
87
- }
88
- case StackType.ndJson:
89
- {
90
- switch (stack.caret) {
91
- case Caret.beforeValue:
92
- return parseValue() || parseRepairTrailingComma();
93
- case Caret.afterValue:
94
- return parseArrayComma() || parseRepairMissingComma() || parseRepairNdJsonEnd();
95
- default:
96
- return false;
97
- }
98
- }
99
- case StackType.functionCall:
100
- {
101
- switch (stack.caret) {
102
- case Caret.beforeValue:
103
- return parseValue();
104
- case Caret.afterValue:
105
- return parseFunctionCallEnd();
106
- default:
107
- return false;
108
- }
109
- }
110
- case StackType.root:
111
- {
112
- switch (stack.caret) {
113
- case Caret.beforeValue:
114
- return parseValue() || parseUnexpectedEnd();
115
- case Caret.afterValue:
116
- return parseRootEnd();
117
- default:
118
- return false;
119
- }
120
- }
121
- default:
122
- return false;
123
- }
124
- }
125
- function parseValue() {
126
- return parseObjectStart() || parseArrayStart() || parseString() || parseNumber() || parseKeywords() || parseRepairUnquotedString();
127
- }
128
- function parseObjectStart() {
129
- if (parseCharacter(codeOpeningBrace)) {
130
- parseWhitespaceAndSkipComments();
131
- if (parseCharacter(codeClosingBrace)) {
132
- return stack.update(Caret.afterValue);
133
- }
134
- return stack.push(StackType.object, Caret.beforeKey);
135
- }
136
- return false;
137
- }
138
- function parseArrayStart() {
139
- if (parseCharacter(codeOpeningBracket)) {
140
- parseWhitespaceAndSkipComments();
141
- if (parseCharacter(codeClosingBracket)) {
142
- return stack.update(Caret.afterValue);
143
- }
144
- return stack.push(StackType.array, Caret.beforeValue);
145
- }
146
- return false;
147
- }
148
- function parseRepairUnquotedString() {
149
- const unquotedStringEnd = findNextDelimiter();
150
- if (unquotedStringEnd !== null) {
151
- const symbol = input.substring(i, unquotedStringEnd);
152
- i = unquotedStringEnd;
153
- if (skipCharacter(codeOpenParenthesis)) {
154
- // A MongoDB function call like NumberLong("2")
155
- // Or a JSONP function call like callback({...});
156
- // we strip the function call
157
-
158
- return stack.push(StackType.functionCall, Caret.beforeValue);
159
- }
160
- output.push(symbol === 'undefined' ? 'null' : JSON.stringify(symbol));
161
- if (input.charCodeAt(i) === codeDoubleQuote) {
162
- // we had a missing start quote, but now we encountered the end quote, so we can skip that one
163
- i++;
164
- }
165
- return stack.update(Caret.afterValue);
166
- }
167
- return false;
168
- }
169
- function parseRepairMissingObjectValue() {
170
- // repair missing object value
171
- output.push('null');
172
- return stack.update(Caret.afterValue);
173
- }
174
- function parseRepairTrailingComma() {
175
- // repair trailing comma
176
- if (output.endsWithIgnoringWhitespace(',')) {
177
- output.stripLastOccurrence(',');
178
- return stack.update(Caret.afterValue);
179
- }
180
- return false;
181
- }
182
- function parseUnexpectedColon() {
183
- if (input.charCodeAt(i) === codeColon) {
184
- throwObjectKeyExpected();
185
- }
186
- return false;
187
- }
188
- function parseUnexpectedEnd() {
189
- if (input.isEnd(i)) {
190
- throwUnexpectedEnd();
191
- } else {
192
- throwUnexpectedCharacter();
193
- }
194
- return false;
195
- }
196
- function parseObjectKey() {
197
- const parsedKey = parseString() || parseUnquotedKey();
198
- if (parsedKey) {
199
- parseWhitespaceAndSkipComments();
200
- if (parseCharacter(codeColon)) {
201
- // expect a value after the :
202
- return stack.update(Caret.beforeValue);
203
- }
204
- const truncatedText = input.isEnd(i);
205
- if (isStartOfValue(input.charAt(i)) || truncatedText) {
206
- // repair missing colon
207
- output.insertBeforeLastWhitespace(':');
208
- return stack.update(Caret.beforeValue);
209
- }
210
- throwColonExpected();
211
- }
212
- return false;
213
- }
214
- function parseObjectComma() {
215
- if (parseCharacter(codeComma)) {
216
- return stack.update(Caret.beforeKey);
217
- }
218
- return false;
219
- }
220
- function parseObjectEnd() {
221
- if (parseCharacter(codeClosingBrace)) {
222
- return stack.pop();
223
- }
224
- return false;
225
- }
226
- function parseRepairObjectEndOrComma() {
227
- // repair missing object end and trailing comma
228
- if (input.charAt(i) === '{') {
229
- output.stripLastOccurrence(',');
230
- output.insertBeforeLastWhitespace('}');
231
- return stack.pop();
232
- }
233
-
234
- // repair missing comma
235
- if (!input.isEnd(i) && isStartOfValue(input.charAt(i))) {
236
- output.insertBeforeLastWhitespace(',');
237
- return stack.update(Caret.beforeKey);
238
- }
239
-
240
- // repair missing closing brace
241
- output.insertBeforeLastWhitespace('}');
242
- return stack.pop();
243
- }
244
- function parseArrayComma() {
245
- if (parseCharacter(codeComma)) {
246
- return stack.update(Caret.beforeValue);
247
- }
248
- return false;
249
- }
250
- function parseArrayEnd() {
251
- if (parseCharacter(codeClosingBracket)) {
252
- return stack.pop();
253
- }
254
- return false;
255
- }
256
- function parseRepairMissingComma() {
257
- // repair missing comma
258
- if (!input.isEnd(i) && isStartOfValue(input.charAt(i))) {
259
- output.insertBeforeLastWhitespace(',');
260
- return stack.update(Caret.beforeValue);
261
- }
262
- return false;
263
- }
264
- function parseRepairArrayEnd() {
265
- // repair missing closing bracket
266
- output.insertBeforeLastWhitespace(']');
267
- return stack.pop();
268
- }
269
- function parseRepairNdJsonEnd() {
270
- if (input.isEnd(i)) {
271
- output.push('\n]');
272
- return stack.pop();
273
- } else {
274
- throwUnexpectedEnd();
275
- return false; // just to make TS happy
276
- }
277
- }
278
- function parseFunctionCallEnd() {
279
- if (skipCharacter(codeCloseParenthesis)) {
280
- skipCharacter(codeSemicolon);
281
- }
282
- return stack.pop();
283
- }
284
- function parseRootEnd() {
285
- const parsedComma = parseCharacter(codeComma);
286
- parseWhitespaceAndSkipComments();
287
- if (isStartOfValue(input.charAt(i)) && (output.endsWithIgnoringWhitespace(',') || output.endsWithIgnoringWhitespace('\n'))) {
288
- // start of a new value after end of the root level object: looks like
289
- // newline delimited JSON -> turn into a root level array
290
- if (!parsedComma) {
291
- // repair missing comma
292
- output.insertBeforeLastWhitespace(',');
293
- }
294
- output.unshift('[\n');
295
- return stack.push(StackType.ndJson, Caret.beforeValue);
296
- }
297
- if (parsedComma) {
298
- // repair: remove trailing comma
299
- output.stripLastOccurrence(',');
300
- return stack.update(Caret.afterValue);
301
- }
302
-
303
- // repair redundant end braces and brackets
304
- while (input.charCodeAt(i) === codeClosingBrace || input.charCodeAt(i) === codeClosingBracket) {
305
- i++;
306
- parseWhitespaceAndSkipComments();
307
- }
308
- if (!input.isEnd(i)) {
309
- throwUnexpectedCharacter();
310
- }
311
- return false;
312
- }
313
- function parseWhitespaceAndSkipComments() {
314
- const start = i;
315
- let changed = parseWhitespace();
316
- do {
317
- changed = parseComment();
318
- if (changed) {
319
- changed = parseWhitespace();
320
- }
321
- } while (changed);
322
- return i > start;
323
- }
324
- function parseWhitespace() {
325
- let whitespace = '';
326
- let normal;
327
- while ((normal = isWhitespace(input.charCodeAt(i))) || isSpecialWhitespace(input.charCodeAt(i))) {
328
- if (normal) {
329
- whitespace += input.charAt(i);
330
- } else {
331
- // repair special whitespace
332
- whitespace += ' ';
333
- }
334
- i++;
335
- }
336
- if (whitespace.length > 0) {
337
- output.push(whitespace);
338
- return true;
339
- }
340
- return false;
341
- }
342
- function parseComment() {
343
- // find a block comment '/* ... */'
344
- if (input.charCodeAt(i) === codeSlash && input.charCodeAt(i + 1) === codeAsterisk) {
345
- // repair block comment by skipping it
346
- while (!input.isEnd(i) && !atEndOfBlockComment(i)) {
347
- i++;
348
- }
349
- i += 2;
350
- return true;
351
- }
352
-
353
- // find a line comment '// ...'
354
- if (input.charCodeAt(i) === codeSlash && input.charCodeAt(i + 1) === codeSlash) {
355
- // repair line comment by skipping it
356
- while (!input.isEnd(i) && input.charCodeAt(i) !== codeNewline) {
357
- i++;
358
- }
359
- return true;
360
- }
361
- return false;
362
- }
363
- function parseCharacter(code) {
364
- if (input.charCodeAt(i) === code) {
365
- output.push(input.charAt(i));
366
- i++;
367
- return true;
368
- }
369
- return false;
370
- }
371
- function skipCharacter(code) {
372
- if (input.charCodeAt(i) === code) {
373
- i++;
374
- return true;
375
- }
376
- return false;
377
- }
378
- function skipEscapeCharacter() {
379
- return skipCharacter(codeBackslash);
380
- }
381
-
382
- /**
383
- * Parse a string enclosed by double quotes "...". Can contain escaped quotes
384
- * Repair strings enclosed in single quotes or special quotes
385
- * Repair an escaped string
386
- *
387
- * The function can run in two stages:
388
- * - First, it assumes the string has a valid end quote
389
- * - If it turns out that the string does not have a valid end quote followed
390
- * by a delimiter (which should be the case), the function runs again in a
391
- * more conservative way, stopping the string at the first next delimiter
392
- * and fixing the string by inserting a quote there.
393
- */
394
- function parseString() {
395
- let stopAtDelimiter = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
396
- const iBefore = i; // we may need to revert
397
-
398
- let skipEscapeChars = input.charCodeAt(i) === codeBackslash;
399
- if (skipEscapeChars) {
400
- // repair: remove the first escape character
401
- i++;
402
- skipEscapeChars = true;
403
- }
404
- if (isQuote(input.charCodeAt(i))) {
405
- // double quotes are correct JSON,
406
- // single quotes come from JavaScript for example, we assume it will have a correct single end quote too
407
- // otherwise, we will match any double-quote-like start with a double-quote-like end,
408
- // or any single-quote-like start with a single-quote-like end
409
- const isEndQuote = isDoubleQuote(input.charCodeAt(i)) ? isDoubleQuote : isSingleQuote(input.charCodeAt(i)) ? isSingleQuote // eslint-disable-line indent
410
- : isSingleQuoteLike(input.charCodeAt(i)) // eslint-disable-line indent
411
- ? isSingleQuoteLike // eslint-disable-line indent
412
- : isDoubleQuoteLike; // eslint-disable-line indent
413
-
414
- output.push('"');
415
- i++;
416
- const isEndOfString = stopAtDelimiter ? i => isDelimiter(input.charAt(i)) : i => isEndQuote(input.charCodeAt(i));
417
- while (!input.isEnd(i) && !isEndOfString(i)) {
418
- if (input.charCodeAt(i) === codeBackslash) {
419
- const char = input.charAt(i + 1);
420
- const escapeChar = escapeCharacters[char];
421
- if (escapeChar !== undefined) {
422
- output.push(input.substring(i, i + 2));
423
- i += 2;
424
- } else if (char === 'u') {
425
- let j = 2;
426
- while (j < 6 && isHex(input.charCodeAt(i + j))) {
427
- j++;
428
- }
429
- if (j === 6) {
430
- output.push(input.substring(i, i + 6));
431
- i += 6;
432
- } else if (input.isEnd(i + j)) {
433
- // repair invalid or truncated unicode char at the end of the text
434
- // by removing the unicode char and ending the string here
435
- i += j;
436
- } else {
437
- throwInvalidUnicodeCharacter();
438
- }
439
- } else {
440
- // repair invalid escape character: remove it
441
- output.push(char);
442
- i += 2;
443
- }
444
- } else {
445
- const char = input.charAt(i);
446
- const code = char.charCodeAt(0);
447
- if (code === codeDoubleQuote && input.charCodeAt(i - 1) !== codeBackslash) {
448
- // repair unescaped double quote
449
- output.push('\\' + char);
450
- i++;
451
- } else if (isControlCharacter(code)) {
452
- // unescaped control character
453
- output.push(controlCharacters[char]);
454
- i++;
455
- } else {
456
- if (!isValidStringCharacter(code)) {
457
- throwInvalidCharacter(char);
458
- }
459
- output.push(char);
460
- i++;
461
- }
462
- }
463
- if (skipEscapeChars) {
464
- // repair: skipped escape character (nothing to do)
465
- skipEscapeCharacter();
466
- }
467
- }
468
-
469
- // see whether we have an end quote followed by a valid delimiter
470
- const hasEndQuote = isQuote(input.charCodeAt(i));
471
- const valid = hasEndQuote && (input.isEnd(i + 1) || isDelimiter(nextNonWhiteSpaceCharacter(i + 1)));
472
- if (!valid && !stopAtDelimiter) {
473
- // we're dealing with a missing quote somewhere. Let's revert parsing
474
- // this string and try again, running in a more conservative mode,
475
- // stopping at the first next delimiter
476
- i = iBefore;
477
- output.remove(iBefore);
478
- return parseString(true);
479
- }
480
- if (hasEndQuote) {
481
- output.push('"');
482
- i++;
483
- } else {
484
- // repair missing quote
485
- output.insertBeforeLastWhitespace('"');
486
- }
487
- parseConcatenatedString();
488
- return stack.update(Caret.afterValue);
489
- }
490
- return false;
491
- }
492
-
493
- /**
494
- * Repair concatenated strings like "hello" + "world", change this into "helloworld"
495
- */
496
- function parseConcatenatedString() {
497
- let parsed = false;
498
- parseWhitespaceAndSkipComments();
499
- while (input.charCodeAt(i) === codePlus) {
500
- parsed = true;
501
- i++;
502
- parseWhitespaceAndSkipComments();
503
-
504
- // repair: remove the end quote of the first string
505
- output.stripLastOccurrence('"', true);
506
- const start = output.length();
507
- const parsedStr = parseString();
508
- if (parsedStr) {
509
- // repair: remove the start quote of the second string
510
- output.remove(start, start + 1);
511
- } else {
512
- // repair: remove the + because it is not followed by a string
513
- output.insertBeforeLastWhitespace('"');
514
- }
515
- }
516
- return parsed;
517
- }
518
-
519
- /**
520
- * Parse a number like 2.4 or 2.4e6
521
- */
522
- function parseNumber() {
523
- const start = i;
524
- if (input.charCodeAt(i) === codeMinus) {
525
- i++;
526
- if (expectDigitOrRepair(start)) {
527
- return stack.update(Caret.afterValue);
528
- }
529
- }
530
-
531
- // Note that in JSON leading zeros like "00789" are not allowed.
532
- // We will allow all leading zeros here though and at the end of parseNumber
533
- // check against trailing zeros and repair that if needed.
534
- // Leading zeros can have meaning, so we should not clear them.
535
- while (isDigit(input.charCodeAt(i))) {
536
- i++;
537
- }
538
- if (input.charCodeAt(i) === codeDot) {
539
- i++;
540
- if (expectDigitOrRepair(start)) {
541
- return stack.update(Caret.afterValue);
542
- }
543
- while (isDigit(input.charCodeAt(i))) {
544
- i++;
545
- }
546
- }
547
- if (input.charCodeAt(i) === codeLowercaseE || input.charCodeAt(i) === codeUppercaseE) {
548
- i++;
549
- if (input.charCodeAt(i) === codeMinus || input.charCodeAt(i) === codePlus) {
550
- i++;
551
- }
552
- if (expectDigitOrRepair(start)) {
553
- return stack.update(Caret.afterValue);
554
- }
555
- while (isDigit(input.charCodeAt(i))) {
556
- i++;
557
- }
558
- }
559
- if (i > start) {
560
- // repair a number with leading zeros like "00789"
561
- const num = input.substring(start, i);
562
- const hasInvalidLeadingZero = /^0\d/.test(num);
563
- output.push(hasInvalidLeadingZero ? `"${num}"` : num);
564
- return stack.update(Caret.afterValue);
565
- }
566
- return false;
567
- }
568
-
569
- /**
570
- * Parse keywords true, false, null
571
- * Repair Python keywords True, False, None
572
- */
573
- function parseKeywords() {
574
- return parseKeyword('true', 'true') || parseKeyword('false', 'false') || parseKeyword('null', 'null') ||
575
- // repair Python keywords True, False, None
576
- parseKeyword('True', 'true') || parseKeyword('False', 'false') || parseKeyword('None', 'null');
577
- }
578
- function parseKeyword(name, value) {
579
- if (input.substring(i, i + name.length) === name) {
580
- output.push(value);
581
- i += name.length;
582
- return stack.update(Caret.afterValue);
583
- }
584
- return false;
585
- }
586
- function parseUnquotedKey() {
587
- let end = findNextDelimiter();
588
- if (end !== null) {
589
- // first, go back to prevent getting trailing whitespaces in the string
590
- while (isWhitespace(input.charCodeAt(end - 1)) && end > i) {
591
- end--;
592
- }
593
- const symbol = input.substring(i, end);
594
- output.push(JSON.stringify(symbol));
595
- i = end;
596
- if (input.charCodeAt(i) === codeDoubleQuote) {
597
- // we had a missing start quote, but now we encountered the end quote, so we can skip that one
598
- i++;
599
- }
600
- return stack.update(Caret.afterValue); // we do not have a state Caret.afterKey, therefore we use afterValue here
601
- }
602
- return false;
603
- }
604
- function findNextDelimiter() {
605
- // note that the symbol can end with whitespaces: we stop at the next delimiter
606
- let j = i;
607
- while (!input.isEnd(j) && !isDelimiter(input.charAt(j))) {
608
- j++;
609
- }
610
- return j > i ? j : null;
611
- }
612
- function nextNonWhiteSpaceCharacter(start) {
613
- let i = start;
614
- while (isWhitespace(input.charCodeAt(i))) {
615
- i++;
616
- }
617
- return input.charAt(i);
618
- }
619
- function expectDigit(start) {
620
- if (!isDigit(input.charCodeAt(i))) {
621
- const numSoFar = input.substring(start, i);
622
- throw new JSONFixerError(`Invalid number '${numSoFar}', expecting a digit ${got()}`, i);
623
- }
624
- }
625
- function expectDigitOrRepair(start) {
626
- if (input.isEnd(i)) {
627
- // repair numbers cut off at the end
628
- // this will only be called when we end after a '.', '-', or 'e' and does not
629
- // change the number more than it needs to make it valid JSON
630
- output.push(input.substring(start, i) + '0');
631
- return true;
632
- } else {
633
- expectDigit(start);
634
- return false;
635
- }
636
- }
637
- function throwInvalidCharacter(char) {
638
- throw new JSONFixerError('Invalid character ' + JSON.stringify(char), i);
639
- }
640
- function throwUnexpectedCharacter() {
641
- throw new JSONFixerError('Unexpected character ' + JSON.stringify(input.charAt(i)), i);
642
- }
643
- function throwUnexpectedEnd() {
644
- throw new JSONFixerError('Unexpected end of json string', i);
645
- }
646
- function throwObjectKeyExpected() {
647
- throw new JSONFixerError('Object key expected', i);
648
- }
649
- function throwColonExpected() {
650
- throw new JSONFixerError('Colon expected', i);
651
- }
652
- function throwInvalidUnicodeCharacter() {
653
- const chars = input.substring(i, i + 6);
654
- throw new JSONFixerError(`Invalid unicode character "${chars}"`, i);
655
- }
656
- function got() {
657
- const char = input.charAt(i);
658
- return char ? `but got '${char}'` : 'but reached end of input';
659
- }
660
- function atEndOfBlockComment(i) {
661
- return input.charAt(i) === '*' && input.charAt(i + 1) === '/';
662
- }
663
- return {
664
- transform,
665
- flush
666
- };
667
- }
668
- //# sourceMappingURL=core.js.map