jsonfixerdev 1.0.2 → 1.0.3

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