@nocobase/plugin-ai 2.1.0-beta.17 → 2.1.0-beta.19

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 (57) hide show
  1. package/dist/ai/ai-employees/atlas/prompt.md +28 -22
  2. package/dist/ai/ai-employees/viz.js +14 -88
  3. package/dist/ai/skills/business-analysis-report/SKILLS.md +8 -3
  4. package/dist/ai/skills/business-analysis-report/tools/businessReportGenerator.js +49 -8
  5. package/dist/client/280.003b9e9788599244.js +10 -0
  6. package/dist/client/{646.51313bb0d85d6366.js → 646.cba98d80e9e6ea74.js} +1 -1
  7. package/dist/client/index.js +4 -4
  8. package/dist/common/recommended-models.js +1 -25
  9. package/dist/externalVersion.js +14 -14
  10. package/dist/locale/en-US.json +9 -0
  11. package/dist/locale/zh-CN.json +9 -0
  12. package/dist/node_modules/fast-glob/package.json +1 -1
  13. package/dist/node_modules/flexsearch/package.json +1 -1
  14. package/dist/node_modules/fs-extra/package.json +1 -1
  15. package/dist/node_modules/jsonrepair/bin/cli.js +179 -0
  16. package/dist/node_modules/jsonrepair/lib/cjs/index.js +1 -0
  17. package/dist/node_modules/jsonrepair/lib/cjs/package.json +3 -0
  18. package/dist/node_modules/jsonrepair/lib/cjs/regular/jsonrepair.js +746 -0
  19. package/dist/node_modules/jsonrepair/lib/cjs/stream.js +13 -0
  20. package/dist/node_modules/jsonrepair/lib/cjs/streaming/buffer/InputBuffer.js +75 -0
  21. package/dist/node_modules/jsonrepair/lib/cjs/streaming/buffer/OutputBuffer.js +117 -0
  22. package/dist/node_modules/jsonrepair/lib/cjs/streaming/core.js +824 -0
  23. package/dist/node_modules/jsonrepair/lib/cjs/streaming/stack.js +51 -0
  24. package/dist/node_modules/jsonrepair/lib/cjs/streaming/stream.js +37 -0
  25. package/dist/node_modules/jsonrepair/lib/cjs/utils/JSONRepairError.js +14 -0
  26. package/dist/node_modules/jsonrepair/lib/cjs/utils/stringUtils.js +174 -0
  27. package/dist/node_modules/jsonrepair/lib/esm/index.js +4 -0
  28. package/dist/node_modules/jsonrepair/lib/esm/regular/jsonrepair.js +740 -0
  29. package/dist/node_modules/jsonrepair/lib/esm/stream.js +3 -0
  30. package/dist/node_modules/jsonrepair/lib/esm/streaming/buffer/InputBuffer.js +69 -0
  31. package/dist/node_modules/jsonrepair/lib/esm/streaming/buffer/OutputBuffer.js +111 -0
  32. package/dist/node_modules/jsonrepair/lib/esm/streaming/core.js +818 -0
  33. package/dist/node_modules/jsonrepair/lib/esm/streaming/stack.js +44 -0
  34. package/dist/node_modules/jsonrepair/lib/esm/streaming/stream.js +31 -0
  35. package/dist/node_modules/jsonrepair/lib/esm/utils/JSONRepairError.js +7 -0
  36. package/dist/node_modules/jsonrepair/lib/esm/utils/stringUtils.js +147 -0
  37. package/dist/node_modules/jsonrepair/lib/types/index.d.ts +3 -0
  38. package/dist/node_modules/jsonrepair/lib/types/regular/jsonrepair.d.ts +18 -0
  39. package/dist/node_modules/jsonrepair/lib/types/stream.d.ts +2 -0
  40. package/dist/node_modules/jsonrepair/lib/types/streaming/buffer/InputBuffer.d.ts +14 -0
  41. package/dist/node_modules/jsonrepair/lib/types/streaming/buffer/OutputBuffer.d.ts +18 -0
  42. package/dist/node_modules/jsonrepair/lib/types/streaming/core.d.ts +11 -0
  43. package/dist/node_modules/jsonrepair/lib/types/streaming/stack.d.ts +20 -0
  44. package/dist/node_modules/jsonrepair/lib/types/streaming/stream.d.ts +7 -0
  45. package/dist/node_modules/jsonrepair/lib/types/utils/JSONRepairError.d.ts +5 -0
  46. package/dist/node_modules/jsonrepair/lib/types/utils/stringUtils.d.ts +65 -0
  47. package/dist/node_modules/jsonrepair/lib/umd/jsonrepair.js +903 -0
  48. package/dist/node_modules/jsonrepair/lib/umd/jsonrepair.min.js +3 -0
  49. package/dist/node_modules/jsonrepair/lib/umd/package.json +3 -0
  50. package/dist/node_modules/jsonrepair/package.json +1 -0
  51. package/dist/node_modules/nodejs-snowflake/package.json +1 -1
  52. package/dist/node_modules/openai/package.json +1 -1
  53. package/dist/node_modules/zod/package.json +1 -1
  54. package/dist/server/resource/aiEmployees.js +15 -1
  55. package/dist/server/resource/aiSkills.js +1 -1
  56. package/package.json +2 -2
  57. package/dist/client/280.029428b83d62155f.js +0 -10
@@ -0,0 +1,746 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.jsonrepair = jsonrepair;
7
+ var _JSONRepairError = require("../utils/JSONRepairError.js");
8
+ var _stringUtils = require("../utils/stringUtils.js");
9
+ const controlCharacters = {
10
+ '\b': '\\b',
11
+ '\f': '\\f',
12
+ '\n': '\\n',
13
+ '\r': '\\r',
14
+ '\t': '\\t'
15
+ };
16
+
17
+ // map with all escape characters
18
+ const escapeCharacters = {
19
+ '"': '"',
20
+ '\\': '\\',
21
+ '/': '/',
22
+ b: '\b',
23
+ f: '\f',
24
+ n: '\n',
25
+ r: '\r',
26
+ t: '\t'
27
+ // note that \u is handled separately in parseString()
28
+ };
29
+
30
+ /**
31
+ * Repair a string containing an invalid JSON document.
32
+ * For example changes JavaScript notation into JSON notation.
33
+ *
34
+ * Example:
35
+ *
36
+ * try {
37
+ * const json = "{name: 'John'}"
38
+ * const repaired = jsonrepair(json)
39
+ * console.log(repaired)
40
+ * // '{"name": "John"}'
41
+ * } catch (err) {
42
+ * console.error(err)
43
+ * }
44
+ *
45
+ */
46
+ function jsonrepair(text) {
47
+ let i = 0; // current index in text
48
+ let output = ''; // generated output
49
+
50
+ parseMarkdownCodeBlock(['```', '[```', '{```']);
51
+ const processed = parseValue();
52
+ if (!processed) {
53
+ throwUnexpectedEnd();
54
+ }
55
+ parseMarkdownCodeBlock(['```', '```]', '```}']);
56
+ const processedComma = parseCharacter(',');
57
+ if (processedComma) {
58
+ parseWhitespaceAndSkipComments();
59
+ }
60
+ if ((0, _stringUtils.isStartOfValue)(text[i]) && (0, _stringUtils.endsWithCommaOrNewline)(output)) {
61
+ // start of a new value after end of the root level object: looks like
62
+ // newline delimited JSON -> turn into a root level array
63
+ if (!processedComma) {
64
+ // repair missing comma
65
+ output = (0, _stringUtils.insertBeforeLastWhitespace)(output, ',');
66
+ }
67
+ parseNewlineDelimitedJSON();
68
+ } else if (processedComma) {
69
+ // repair: remove trailing comma
70
+ output = (0, _stringUtils.stripLastOccurrence)(output, ',');
71
+ }
72
+
73
+ // repair redundant end quotes
74
+ while (text[i] === '}' || text[i] === ']') {
75
+ i++;
76
+ parseWhitespaceAndSkipComments();
77
+ }
78
+ if (i >= text.length) {
79
+ // reached the end of the document properly
80
+ return output;
81
+ }
82
+ throwUnexpectedCharacter();
83
+ function parseValue() {
84
+ parseWhitespaceAndSkipComments();
85
+ const processed = parseObject() || parseArray() || parseString() || parseNumber() || parseKeywords() || parseUnquotedString(false) || parseRegex();
86
+ parseWhitespaceAndSkipComments();
87
+ return processed;
88
+ }
89
+ function parseWhitespaceAndSkipComments() {
90
+ let skipNewline = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
91
+ const start = i;
92
+ let changed = parseWhitespace(skipNewline);
93
+ do {
94
+ changed = parseComment();
95
+ if (changed) {
96
+ changed = parseWhitespace(skipNewline);
97
+ }
98
+ } while (changed);
99
+ return i > start;
100
+ }
101
+ function parseWhitespace(skipNewline) {
102
+ const _isWhiteSpace = skipNewline ? _stringUtils.isWhitespace : _stringUtils.isWhitespaceExceptNewline;
103
+ let whitespace = '';
104
+ while (true) {
105
+ if (_isWhiteSpace(text, i)) {
106
+ whitespace += text[i];
107
+ i++;
108
+ } else if ((0, _stringUtils.isSpecialWhitespace)(text, i)) {
109
+ // repair special whitespace
110
+ whitespace += ' ';
111
+ i++;
112
+ } else {
113
+ break;
114
+ }
115
+ }
116
+ if (whitespace.length > 0) {
117
+ output += whitespace;
118
+ return true;
119
+ }
120
+ return false;
121
+ }
122
+ function parseComment() {
123
+ // find a block comment '/* ... */'
124
+ if (text[i] === '/' && text[i + 1] === '*') {
125
+ // repair block comment by skipping it
126
+ while (i < text.length && !atEndOfBlockComment(text, i)) {
127
+ i++;
128
+ }
129
+ i += 2;
130
+ return true;
131
+ }
132
+
133
+ // find a line comment '// ...'
134
+ if (text[i] === '/' && text[i + 1] === '/') {
135
+ // repair line comment by skipping it
136
+ while (i < text.length && text[i] !== '\n') {
137
+ i++;
138
+ }
139
+ return true;
140
+ }
141
+ return false;
142
+ }
143
+ function parseMarkdownCodeBlock(blocks) {
144
+ // find and skip over a Markdown fenced code block:
145
+ // ``` ... ```
146
+ // or
147
+ // ```json ... ```
148
+ if (skipMarkdownCodeBlock(blocks)) {
149
+ if ((0, _stringUtils.isFunctionNameCharStart)(text[i])) {
150
+ // strip the optional language specifier like "json"
151
+ while (i < text.length && (0, _stringUtils.isFunctionNameChar)(text[i])) {
152
+ i++;
153
+ }
154
+ }
155
+ parseWhitespaceAndSkipComments();
156
+ return true;
157
+ }
158
+ return false;
159
+ }
160
+ function skipMarkdownCodeBlock(blocks) {
161
+ parseWhitespace(true);
162
+ for (const block of blocks) {
163
+ const end = i + block.length;
164
+ if (text.slice(i, end) === block) {
165
+ i = end;
166
+ return true;
167
+ }
168
+ }
169
+ return false;
170
+ }
171
+ function parseCharacter(char) {
172
+ if (text[i] === char) {
173
+ output += text[i];
174
+ i++;
175
+ return true;
176
+ }
177
+ return false;
178
+ }
179
+ function skipCharacter(char) {
180
+ if (text[i] === char) {
181
+ i++;
182
+ return true;
183
+ }
184
+ return false;
185
+ }
186
+ function skipEscapeCharacter() {
187
+ return skipCharacter('\\');
188
+ }
189
+
190
+ /**
191
+ * Skip ellipsis like "[1,2,3,...]" or "[1,2,3,...,9]" or "[...,7,8,9]"
192
+ * or a similar construct in objects.
193
+ */
194
+ function skipEllipsis() {
195
+ parseWhitespaceAndSkipComments();
196
+ if (text[i] === '.' && text[i + 1] === '.' && text[i + 2] === '.') {
197
+ // repair: remove the ellipsis (three dots) and optionally a comma
198
+ i += 3;
199
+ parseWhitespaceAndSkipComments();
200
+ skipCharacter(',');
201
+ return true;
202
+ }
203
+ return false;
204
+ }
205
+
206
+ /**
207
+ * Parse an object like '{"key": "value"}'
208
+ */
209
+ function parseObject() {
210
+ if (text[i] === '{') {
211
+ output += '{';
212
+ i++;
213
+ parseWhitespaceAndSkipComments();
214
+
215
+ // repair: skip leading comma like in {, message: "hi"}
216
+ if (skipCharacter(',')) {
217
+ parseWhitespaceAndSkipComments();
218
+ }
219
+ let initial = true;
220
+ while (i < text.length && text[i] !== '}') {
221
+ let processedComma;
222
+ if (!initial) {
223
+ processedComma = parseCharacter(',');
224
+ if (!processedComma) {
225
+ // repair missing comma
226
+ output = (0, _stringUtils.insertBeforeLastWhitespace)(output, ',');
227
+ }
228
+ parseWhitespaceAndSkipComments();
229
+ } else {
230
+ processedComma = true;
231
+ initial = false;
232
+ }
233
+ skipEllipsis();
234
+ const processedKey = parseString() || parseUnquotedString(true);
235
+ if (!processedKey) {
236
+ if (text[i] === '}' || text[i] === '{' || text[i] === ']' || text[i] === '[' || text[i] === undefined) {
237
+ // repair trailing comma
238
+ output = (0, _stringUtils.stripLastOccurrence)(output, ',');
239
+ } else {
240
+ throwObjectKeyExpected();
241
+ }
242
+ break;
243
+ }
244
+ parseWhitespaceAndSkipComments();
245
+ const processedColon = parseCharacter(':');
246
+ const truncatedText = i >= text.length;
247
+ if (!processedColon) {
248
+ if ((0, _stringUtils.isStartOfValue)(text[i]) || truncatedText) {
249
+ // repair missing colon
250
+ output = (0, _stringUtils.insertBeforeLastWhitespace)(output, ':');
251
+ } else {
252
+ throwColonExpected();
253
+ }
254
+ }
255
+ const processedValue = parseValue();
256
+ if (!processedValue) {
257
+ if (processedColon || truncatedText) {
258
+ // repair missing object value
259
+ output += 'null';
260
+ } else {
261
+ throwColonExpected();
262
+ }
263
+ }
264
+ }
265
+ if (text[i] === '}') {
266
+ output += '}';
267
+ i++;
268
+ } else {
269
+ // repair missing end bracket
270
+ output = (0, _stringUtils.insertBeforeLastWhitespace)(output, '}');
271
+ }
272
+ return true;
273
+ }
274
+ return false;
275
+ }
276
+
277
+ /**
278
+ * Parse an array like '["item1", "item2", ...]'
279
+ */
280
+ function parseArray() {
281
+ if (text[i] === '[') {
282
+ output += '[';
283
+ i++;
284
+ parseWhitespaceAndSkipComments();
285
+
286
+ // repair: skip leading comma like in [,1,2,3]
287
+ if (skipCharacter(',')) {
288
+ parseWhitespaceAndSkipComments();
289
+ }
290
+ let initial = true;
291
+ while (i < text.length && text[i] !== ']') {
292
+ if (!initial) {
293
+ const processedComma = parseCharacter(',');
294
+ if (!processedComma) {
295
+ // repair missing comma
296
+ output = (0, _stringUtils.insertBeforeLastWhitespace)(output, ',');
297
+ }
298
+ } else {
299
+ initial = false;
300
+ }
301
+ skipEllipsis();
302
+ const processedValue = parseValue();
303
+ if (!processedValue) {
304
+ // repair trailing comma
305
+ output = (0, _stringUtils.stripLastOccurrence)(output, ',');
306
+ break;
307
+ }
308
+ }
309
+ if (text[i] === ']') {
310
+ output += ']';
311
+ i++;
312
+ } else {
313
+ // repair missing closing array bracket
314
+ output = (0, _stringUtils.insertBeforeLastWhitespace)(output, ']');
315
+ }
316
+ return true;
317
+ }
318
+ return false;
319
+ }
320
+
321
+ /**
322
+ * Parse and repair Newline Delimited JSON (NDJSON):
323
+ * multiple JSON objects separated by a newline character
324
+ */
325
+ function parseNewlineDelimitedJSON() {
326
+ // repair NDJSON
327
+ let initial = true;
328
+ let processedValue = true;
329
+ while (processedValue) {
330
+ if (!initial) {
331
+ // parse optional comma, insert when missing
332
+ const processedComma = parseCharacter(',');
333
+ if (!processedComma) {
334
+ // repair: add missing comma
335
+ output = (0, _stringUtils.insertBeforeLastWhitespace)(output, ',');
336
+ }
337
+ } else {
338
+ initial = false;
339
+ }
340
+ processedValue = parseValue();
341
+ }
342
+ if (!processedValue) {
343
+ // repair: remove trailing comma
344
+ output = (0, _stringUtils.stripLastOccurrence)(output, ',');
345
+ }
346
+
347
+ // repair: wrap the output inside array brackets
348
+ output = `[\n${output}\n]`;
349
+ }
350
+
351
+ /**
352
+ * Parse a string enclosed by double quotes "...". Can contain escaped quotes
353
+ * Repair strings enclosed in single quotes or special quotes
354
+ * Repair an escaped string
355
+ *
356
+ * The function can run in two stages:
357
+ * - First, it assumes the string has a valid end quote
358
+ * - If it turns out that the string does not have a valid end quote followed
359
+ * by a delimiter (which should be the case), the function runs again in a
360
+ * more conservative way, stopping the string at the first next delimiter
361
+ * and fixing the string by inserting a quote there, or stopping at a
362
+ * stop index detected in the first iteration.
363
+ */
364
+ function parseString() {
365
+ let stopAtDelimiter = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
366
+ let stopAtIndex = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : -1;
367
+ let skipEscapeChars = text[i] === '\\';
368
+ if (skipEscapeChars) {
369
+ // repair: remove the first escape character
370
+ i++;
371
+ skipEscapeChars = true;
372
+ }
373
+ if ((0, _stringUtils.isQuote)(text[i])) {
374
+ // double quotes are correct JSON,
375
+ // single quotes come from JavaScript for example, we assume it will have a correct single end quote too
376
+ // otherwise, we will match any double-quote-like start with a double-quote-like end,
377
+ // or any single-quote-like start with a single-quote-like end
378
+ const isEndQuote = (0, _stringUtils.isDoubleQuote)(text[i]) ? _stringUtils.isDoubleQuote : (0, _stringUtils.isSingleQuote)(text[i]) ? _stringUtils.isSingleQuote : (0, _stringUtils.isSingleQuoteLike)(text[i]) ? _stringUtils.isSingleQuoteLike : _stringUtils.isDoubleQuoteLike;
379
+ const iBefore = i;
380
+ const oBefore = output.length;
381
+ let str = '"';
382
+ i++;
383
+ while (true) {
384
+ if (i >= text.length) {
385
+ // end of text, we are missing an end quote
386
+
387
+ const iPrev = prevNonWhitespaceIndex(i - 1);
388
+ if (!stopAtDelimiter && (0, _stringUtils.isDelimiter)(text.charAt(iPrev))) {
389
+ // if the text ends with a delimiter, like ["hello],
390
+ // so the missing end quote should be inserted before this delimiter
391
+ // retry parsing the string, stopping at the first next delimiter
392
+ i = iBefore;
393
+ output = output.substring(0, oBefore);
394
+ return parseString(true);
395
+ }
396
+
397
+ // repair missing quote
398
+ str = (0, _stringUtils.insertBeforeLastWhitespace)(str, '"');
399
+ output += str;
400
+ return true;
401
+ }
402
+ if (i === stopAtIndex) {
403
+ // use the stop index detected in the first iteration, and repair end quote
404
+ str = (0, _stringUtils.insertBeforeLastWhitespace)(str, '"');
405
+ output += str;
406
+ return true;
407
+ }
408
+ if (isEndQuote(text[i])) {
409
+ // end quote
410
+ // let us check what is before and after the quote to verify whether this is a legit end quote
411
+ const iQuote = i;
412
+ const oQuote = str.length;
413
+ str += '"';
414
+ i++;
415
+ output += str;
416
+ parseWhitespaceAndSkipComments(false);
417
+ if (stopAtDelimiter || i >= text.length || (0, _stringUtils.isDelimiter)(text[i]) || (0, _stringUtils.isQuote)(text[i]) || (0, _stringUtils.isDigit)(text[i])) {
418
+ // The quote is followed by the end of the text, a delimiter,
419
+ // or a next value. So the quote is indeed the end of the string.
420
+ parseConcatenatedString();
421
+ return true;
422
+ }
423
+ const iPrevChar = prevNonWhitespaceIndex(iQuote - 1);
424
+ const prevChar = text.charAt(iPrevChar);
425
+ if (prevChar === ',') {
426
+ // A comma followed by a quote, like '{"a":"b,c,"d":"e"}'.
427
+ // We assume that the quote is a start quote, and that the end quote
428
+ // should have been located right before the comma but is missing.
429
+ i = iBefore;
430
+ output = output.substring(0, oBefore);
431
+ return parseString(false, iPrevChar);
432
+ }
433
+ if ((0, _stringUtils.isDelimiter)(prevChar)) {
434
+ // This is not the right end quote: it is preceded by a delimiter,
435
+ // and NOT followed by a delimiter. So, there is an end quote missing
436
+ // parse the string again and then stop at the first next delimiter
437
+ i = iBefore;
438
+ output = output.substring(0, oBefore);
439
+ return parseString(true);
440
+ }
441
+
442
+ // revert to right after the quote but before any whitespace, and continue parsing the string
443
+ output = output.substring(0, oBefore);
444
+ i = iQuote + 1;
445
+
446
+ // repair unescaped quote
447
+ str = `${str.substring(0, oQuote)}\\${str.substring(oQuote)}`;
448
+ } else if (stopAtDelimiter && (0, _stringUtils.isUnquotedStringDelimiter)(text[i])) {
449
+ // we're in the mode to stop the string at the first delimiter
450
+ // because there is an end quote missing
451
+
452
+ // test start of an url like "https://..." (this would be parsed as a comment)
453
+ if (text[i - 1] === ':' && _stringUtils.regexUrlStart.test(text.substring(iBefore + 1, i + 2))) {
454
+ while (i < text.length && _stringUtils.regexUrlChar.test(text[i])) {
455
+ str += text[i];
456
+ i++;
457
+ }
458
+ }
459
+
460
+ // repair missing quote
461
+ str = (0, _stringUtils.insertBeforeLastWhitespace)(str, '"');
462
+ output += str;
463
+ parseConcatenatedString();
464
+ return true;
465
+ } else if (text[i] === '\\') {
466
+ // handle escaped content like \n or \u2605
467
+ const char = text.charAt(i + 1);
468
+ const escapeChar = escapeCharacters[char];
469
+ if (escapeChar !== undefined) {
470
+ str += text.slice(i, i + 2);
471
+ i += 2;
472
+ } else if (char === 'u') {
473
+ let j = 2;
474
+ while (j < 6 && (0, _stringUtils.isHex)(text[i + j])) {
475
+ j++;
476
+ }
477
+ if (j === 6) {
478
+ str += text.slice(i, i + 6);
479
+ i += 6;
480
+ } else if (i + j >= text.length) {
481
+ // repair invalid or truncated unicode char at the end of the text
482
+ // by removing the unicode char and ending the string here
483
+ i = text.length;
484
+ } else {
485
+ throwInvalidUnicodeCharacter();
486
+ }
487
+ } else {
488
+ // repair invalid escape character: remove it
489
+ str += char;
490
+ i += 2;
491
+ }
492
+ } else {
493
+ // handle regular characters
494
+ const char = text.charAt(i);
495
+ if (char === '"' && text[i - 1] !== '\\') {
496
+ // repair unescaped double quote
497
+ str += `\\${char}`;
498
+ i++;
499
+ } else if ((0, _stringUtils.isControlCharacter)(char)) {
500
+ // unescaped control character
501
+ str += controlCharacters[char];
502
+ i++;
503
+ } else {
504
+ if (!(0, _stringUtils.isValidStringCharacter)(char)) {
505
+ throwInvalidCharacter(char);
506
+ }
507
+ str += char;
508
+ i++;
509
+ }
510
+ }
511
+ if (skipEscapeChars) {
512
+ // repair: skipped escape character (nothing to do)
513
+ skipEscapeCharacter();
514
+ }
515
+ }
516
+ }
517
+ return false;
518
+ }
519
+
520
+ /**
521
+ * Repair concatenated strings like "hello" + "world", change this into "helloworld"
522
+ */
523
+ function parseConcatenatedString() {
524
+ let processed = false;
525
+ parseWhitespaceAndSkipComments();
526
+ while (text[i] === '+') {
527
+ processed = true;
528
+ i++;
529
+ parseWhitespaceAndSkipComments();
530
+
531
+ // repair: remove the end quote of the first string
532
+ output = (0, _stringUtils.stripLastOccurrence)(output, '"', true);
533
+ const start = output.length;
534
+ const parsedStr = parseString();
535
+ if (parsedStr) {
536
+ // repair: remove the start quote of the second string
537
+ output = (0, _stringUtils.removeAtIndex)(output, start, 1);
538
+ } else {
539
+ // repair: remove the + because it is not followed by a string
540
+ output = (0, _stringUtils.insertBeforeLastWhitespace)(output, '"');
541
+ }
542
+ }
543
+ return processed;
544
+ }
545
+
546
+ /**
547
+ * Parse a number like 2.4 or 2.4e6
548
+ */
549
+ function parseNumber() {
550
+ const start = i;
551
+ if (text[i] === '-') {
552
+ i++;
553
+ if (atEndOfNumber()) {
554
+ repairNumberEndingWithNumericSymbol(start);
555
+ return true;
556
+ }
557
+ if (!(0, _stringUtils.isDigit)(text[i])) {
558
+ i = start;
559
+ return false;
560
+ }
561
+ }
562
+
563
+ // Note that in JSON leading zeros like "00789" are not allowed.
564
+ // We will allow all leading zeros here though and at the end of parseNumber
565
+ // check against trailing zeros and repair that if needed.
566
+ // Leading zeros can have meaning, so we should not clear them.
567
+ while ((0, _stringUtils.isDigit)(text[i])) {
568
+ i++;
569
+ }
570
+ if (text[i] === '.') {
571
+ i++;
572
+ if (atEndOfNumber()) {
573
+ repairNumberEndingWithNumericSymbol(start);
574
+ return true;
575
+ }
576
+ if (!(0, _stringUtils.isDigit)(text[i])) {
577
+ i = start;
578
+ return false;
579
+ }
580
+ while ((0, _stringUtils.isDigit)(text[i])) {
581
+ i++;
582
+ }
583
+ }
584
+ if (text[i] === 'e' || text[i] === 'E') {
585
+ i++;
586
+ if (text[i] === '-' || text[i] === '+') {
587
+ i++;
588
+ }
589
+ if (atEndOfNumber()) {
590
+ repairNumberEndingWithNumericSymbol(start);
591
+ return true;
592
+ }
593
+ if (!(0, _stringUtils.isDigit)(text[i])) {
594
+ i = start;
595
+ return false;
596
+ }
597
+ while ((0, _stringUtils.isDigit)(text[i])) {
598
+ i++;
599
+ }
600
+ }
601
+
602
+ // if we're not at the end of the number by this point, allow this to be parsed as another type
603
+ if (!atEndOfNumber()) {
604
+ i = start;
605
+ return false;
606
+ }
607
+ if (i > start) {
608
+ // repair a number with leading zeros like "00789"
609
+ const num = text.slice(start, i);
610
+ const hasInvalidLeadingZero = /^0\d/.test(num);
611
+ output += hasInvalidLeadingZero ? `"${num}"` : num;
612
+ return true;
613
+ }
614
+ return false;
615
+ }
616
+
617
+ /**
618
+ * Parse keywords true, false, null
619
+ * Repair Python keywords True, False, None
620
+ */
621
+ function parseKeywords() {
622
+ return parseKeyword('true', 'true') || parseKeyword('false', 'false') || parseKeyword('null', 'null') ||
623
+ // repair Python keywords True, False, None
624
+ parseKeyword('True', 'true') || parseKeyword('False', 'false') || parseKeyword('None', 'null');
625
+ }
626
+ function parseKeyword(name, value) {
627
+ if (text.slice(i, i + name.length) === name) {
628
+ output += value;
629
+ i += name.length;
630
+ return true;
631
+ }
632
+ return false;
633
+ }
634
+
635
+ /**
636
+ * Repair an unquoted string by adding quotes around it
637
+ * Repair a MongoDB function call like NumberLong("2")
638
+ * Repair a JSONP function call like callback({...});
639
+ */
640
+ function parseUnquotedString(isKey) {
641
+ // note that the symbol can end with whitespaces: we stop at the next delimiter
642
+ // also, note that we allow strings to contain a slash / in order to support repairing regular expressions
643
+ const start = i;
644
+ if ((0, _stringUtils.isFunctionNameCharStart)(text[i])) {
645
+ while (i < text.length && (0, _stringUtils.isFunctionNameChar)(text[i])) {
646
+ i++;
647
+ }
648
+ let j = i;
649
+ while ((0, _stringUtils.isWhitespace)(text, j)) {
650
+ j++;
651
+ }
652
+ if (text[j] === '(') {
653
+ // repair a MongoDB function call like NumberLong("2")
654
+ // repair a JSONP function call like callback({...});
655
+ i = j + 1;
656
+ parseValue();
657
+ if (text[i] === ')') {
658
+ // repair: skip close bracket of function call
659
+ i++;
660
+ if (text[i] === ';') {
661
+ // repair: skip semicolon after JSONP call
662
+ i++;
663
+ }
664
+ }
665
+ return true;
666
+ }
667
+ }
668
+ while (i < text.length && !(0, _stringUtils.isUnquotedStringDelimiter)(text[i]) && !(0, _stringUtils.isQuote)(text[i]) && (!isKey || text[i] !== ':')) {
669
+ i++;
670
+ }
671
+
672
+ // test start of an url like "https://..." (this would be parsed as a comment)
673
+ if (text[i - 1] === ':' && _stringUtils.regexUrlStart.test(text.substring(start, i + 2))) {
674
+ while (i < text.length && _stringUtils.regexUrlChar.test(text[i])) {
675
+ i++;
676
+ }
677
+ }
678
+ if (i > start) {
679
+ // repair unquoted string
680
+ // also, repair undefined into null
681
+
682
+ // first, go back to prevent getting trailing whitespaces in the string
683
+ while ((0, _stringUtils.isWhitespace)(text, i - 1) && i > 0) {
684
+ i--;
685
+ }
686
+ const symbol = text.slice(start, i);
687
+ output += symbol === 'undefined' ? 'null' : JSON.stringify(symbol);
688
+ if (text[i] === '"') {
689
+ // we had a missing start quote, but now we encountered the end quote, so we can skip that one
690
+ i++;
691
+ }
692
+ return true;
693
+ }
694
+ }
695
+ function parseRegex() {
696
+ if (text[i] === '/') {
697
+ const start = i;
698
+ i++;
699
+ while (i < text.length && (text[i] !== '/' || text[i - 1] === '\\')) {
700
+ i++;
701
+ }
702
+ i++;
703
+ output += `"${text.substring(start, i)}"`;
704
+ return true;
705
+ }
706
+ }
707
+ function prevNonWhitespaceIndex(start) {
708
+ let prev = start;
709
+ while (prev > 0 && (0, _stringUtils.isWhitespace)(text, prev)) {
710
+ prev--;
711
+ }
712
+ return prev;
713
+ }
714
+ function atEndOfNumber() {
715
+ return i >= text.length || (0, _stringUtils.isDelimiter)(text[i]) || (0, _stringUtils.isWhitespace)(text, i);
716
+ }
717
+ function repairNumberEndingWithNumericSymbol(start) {
718
+ // repair numbers cut off at the end
719
+ // this will only be called when we end after a '.', '-', or 'e' and does not
720
+ // change the number more than it needs to make it valid JSON
721
+ output += `${text.slice(start, i)}0`;
722
+ }
723
+ function throwInvalidCharacter(char) {
724
+ throw new _JSONRepairError.JSONRepairError(`Invalid character ${JSON.stringify(char)}`, i);
725
+ }
726
+ function throwUnexpectedCharacter() {
727
+ throw new _JSONRepairError.JSONRepairError(`Unexpected character ${JSON.stringify(text[i])}`, i);
728
+ }
729
+ function throwUnexpectedEnd() {
730
+ throw new _JSONRepairError.JSONRepairError('Unexpected end of json string', text.length);
731
+ }
732
+ function throwObjectKeyExpected() {
733
+ throw new _JSONRepairError.JSONRepairError('Object key expected', i);
734
+ }
735
+ function throwColonExpected() {
736
+ throw new _JSONRepairError.JSONRepairError('Colon expected', i);
737
+ }
738
+ function throwInvalidUnicodeCharacter() {
739
+ const chars = text.slice(i, i + 6);
740
+ throw new _JSONRepairError.JSONRepairError(`Invalid unicode character "${chars}"`, i);
741
+ }
742
+ }
743
+ function atEndOfBlockComment(text, i) {
744
+ return text[i] === '*' && text[i + 1] === '/';
745
+ }
746
+ //# sourceMappingURL=jsonrepair.js.map