@fluixi/utils 1.0.0-alpha.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +73 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1 -0
- package/dist/index.mjs +1 -0
- package/dist/lib/array/advanced.cjs +1 -0
- package/dist/lib/array/advanced.d.ts +1116 -0
- package/dist/lib/array/advanced.d.ts.map +1 -0
- package/dist/lib/array/advanced.js +2429 -0
- package/dist/lib/array/advanced.mjs +1 -0
- package/dist/lib/array/array.cjs +1 -0
- package/dist/lib/array/array.d.ts +6 -0
- package/dist/lib/array/array.d.ts.map +1 -0
- package/dist/lib/array/array.js +31 -0
- package/dist/lib/array/array.mjs +1 -0
- package/dist/lib/array/index.cjs +1 -0
- package/dist/lib/array/index.d.ts +4 -0
- package/dist/lib/array/index.d.ts.map +1 -0
- package/dist/lib/array/index.js +3 -0
- package/dist/lib/array/index.mjs +1 -0
- package/dist/lib/array/utils.cjs +1 -0
- package/dist/lib/array/utils.d.ts +100 -0
- package/dist/lib/array/utils.d.ts.map +1 -0
- package/dist/lib/array/utils.js +165 -0
- package/dist/lib/array/utils.mjs +1 -0
- package/dist/lib/color/color.cjs +1 -0
- package/dist/lib/color/color.d.ts +366 -0
- package/dist/lib/color/color.d.ts.map +1 -0
- package/dist/lib/color/color.js +722 -0
- package/dist/lib/color/color.mjs +1 -0
- package/dist/lib/color/constants.cjs +1 -0
- package/dist/lib/color/constants.d.ts +361 -0
- package/dist/lib/color/constants.d.ts.map +1 -0
- package/dist/lib/color/constants.js +358 -0
- package/dist/lib/color/constants.mjs +1 -0
- package/dist/lib/color/conversions.cjs +1 -0
- package/dist/lib/color/conversions.d.ts +166 -0
- package/dist/lib/color/conversions.d.ts.map +1 -0
- package/dist/lib/color/conversions.js +766 -0
- package/dist/lib/color/conversions.mjs +1 -0
- package/dist/lib/color/helpers.cjs +1 -0
- package/dist/lib/color/helpers.d.ts +75 -0
- package/dist/lib/color/helpers.d.ts.map +1 -0
- package/dist/lib/color/helpers.js +419 -0
- package/dist/lib/color/helpers.mjs +1 -0
- package/dist/lib/color/index.cjs +1 -0
- package/dist/lib/color/index.d.ts +12 -0
- package/dist/lib/color/index.d.ts.map +1 -0
- package/dist/lib/color/index.js +15 -0
- package/dist/lib/color/index.mjs +1 -0
- package/dist/lib/color/types.cjs +1 -0
- package/dist/lib/color/types.d.ts +179 -0
- package/dist/lib/color/types.d.ts.map +1 -0
- package/dist/lib/color/types.js +1 -0
- package/dist/lib/color/types.mjs +0 -0
- package/dist/lib/color/utils.cjs +1 -0
- package/dist/lib/color/utils.d.ts +199 -0
- package/dist/lib/color/utils.d.ts.map +1 -0
- package/dist/lib/color/utils.js +858 -0
- package/dist/lib/color/utils.mjs +1 -0
- package/dist/lib/compare/comparators.cjs +1 -0
- package/dist/lib/compare/comparators.d.ts +65 -0
- package/dist/lib/compare/comparators.d.ts.map +1 -0
- package/dist/lib/compare/comparators.js +210 -0
- package/dist/lib/compare/comparators.mjs +1 -0
- package/dist/lib/compare/index.cjs +1 -0
- package/dist/lib/compare/index.d.ts +2 -0
- package/dist/lib/compare/index.d.ts.map +1 -0
- package/dist/lib/compare/index.js +1 -0
- package/dist/lib/compare/index.mjs +1 -0
- package/dist/lib/crypto/hash.cjs +1 -0
- package/dist/lib/crypto/hash.d.ts +6 -0
- package/dist/lib/crypto/hash.d.ts.map +1 -0
- package/dist/lib/crypto/hash.js +53 -0
- package/dist/lib/crypto/hash.mjs +1 -0
- package/dist/lib/crypto/index.cjs +1 -0
- package/dist/lib/crypto/index.d.ts +2 -0
- package/dist/lib/crypto/index.d.ts.map +1 -0
- package/dist/lib/crypto/index.js +1 -0
- package/dist/lib/crypto/index.mjs +1 -0
- package/dist/lib/dom/events.cjs +1 -0
- package/dist/lib/dom/events.d.ts +159 -0
- package/dist/lib/dom/events.d.ts.map +1 -0
- package/dist/lib/dom/events.js +50 -0
- package/dist/lib/dom/events.mjs +1 -0
- package/dist/lib/dom/index.cjs +1 -0
- package/dist/lib/dom/index.d.ts +3 -0
- package/dist/lib/dom/index.d.ts.map +1 -0
- package/dist/lib/dom/index.js +2 -0
- package/dist/lib/dom/index.mjs +1 -0
- package/dist/lib/dom/utils.cjs +1 -0
- package/dist/lib/dom/utils.d.ts +6 -0
- package/dist/lib/dom/utils.d.ts.map +1 -0
- package/dist/lib/dom/utils.js +37 -0
- package/dist/lib/dom/utils.mjs +1 -0
- package/dist/lib/functions/functions.cjs +1 -0
- package/dist/lib/functions/functions.d.ts +329 -0
- package/dist/lib/functions/functions.d.ts.map +1 -0
- package/dist/lib/functions/functions.js +585 -0
- package/dist/lib/functions/functions.mjs +1 -0
- package/dist/lib/functions/index.cjs +1 -0
- package/dist/lib/functions/index.d.ts +3 -0
- package/dist/lib/functions/index.d.ts.map +1 -0
- package/dist/lib/functions/index.js +1 -0
- package/dist/lib/functions/index.mjs +1 -0
- package/dist/lib/functions/types.cjs +1 -0
- package/dist/lib/functions/types.d.ts +2 -0
- package/dist/lib/functions/types.d.ts.map +1 -0
- package/dist/lib/functions/types.js +1 -0
- package/dist/lib/functions/types.mjs +0 -0
- package/dist/lib/helpers.cjs +1 -0
- package/dist/lib/helpers.d.ts +13 -0
- package/dist/lib/helpers.d.ts.map +1 -0
- package/dist/lib/helpers.js +66 -0
- package/dist/lib/helpers.mjs +1 -0
- package/dist/lib/index.cjs +1 -0
- package/dist/lib/index.d.ts +6 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +8 -0
- package/dist/lib/index.mjs +1 -0
- package/dist/lib/maths/constants.cjs +1 -0
- package/dist/lib/maths/constants.d.ts +84 -0
- package/dist/lib/maths/constants.d.ts.map +1 -0
- package/dist/lib/maths/constants.js +79 -0
- package/dist/lib/maths/constants.mjs +1 -0
- package/dist/lib/maths/fn/advanced.cjs +1 -0
- package/dist/lib/maths/fn/advanced.d.ts +149 -0
- package/dist/lib/maths/fn/advanced.d.ts.map +1 -0
- package/dist/lib/maths/fn/advanced.js +264 -0
- package/dist/lib/maths/fn/advanced.mjs +1 -0
- package/dist/lib/maths/fn/basic.cjs +1 -0
- package/dist/lib/maths/fn/basic.d.ts +182 -0
- package/dist/lib/maths/fn/basic.d.ts.map +1 -0
- package/dist/lib/maths/fn/basic.js +343 -0
- package/dist/lib/maths/fn/basic.mjs +1 -0
- package/dist/lib/maths/fn/complex.cjs +1 -0
- package/dist/lib/maths/fn/complex.d.ts +153 -0
- package/dist/lib/maths/fn/complex.d.ts.map +1 -0
- package/dist/lib/maths/fn/complex.js +383 -0
- package/dist/lib/maths/fn/complex.mjs +1 -0
- package/dist/lib/maths/fn/index.cjs +1 -0
- package/dist/lib/maths/fn/index.d.ts +10 -0
- package/dist/lib/maths/fn/index.d.ts.map +1 -0
- package/dist/lib/maths/fn/index.js +9 -0
- package/dist/lib/maths/fn/index.mjs +1 -0
- package/dist/lib/maths/fn/trigo.cjs +1 -0
- package/dist/lib/maths/fn/trigo.d.ts +147 -0
- package/dist/lib/maths/fn/trigo.d.ts.map +1 -0
- package/dist/lib/maths/fn/trigo.js +227 -0
- package/dist/lib/maths/fn/trigo.mjs +1 -0
- package/dist/lib/maths/fn/vector.cjs +1 -0
- package/dist/lib/maths/fn/vector.d.ts +512 -0
- package/dist/lib/maths/fn/vector.d.ts.map +1 -0
- package/dist/lib/maths/fn/vector.js +1136 -0
- package/dist/lib/maths/fn/vector.mjs +1 -0
- package/dist/lib/maths/formatter.cjs +1 -0
- package/dist/lib/maths/formatter.d.ts +35 -0
- package/dist/lib/maths/formatter.d.ts.map +1 -0
- package/dist/lib/maths/formatter.js +56 -0
- package/dist/lib/maths/formatter.mjs +1 -0
- package/dist/lib/maths/guards.cjs +1 -0
- package/dist/lib/maths/guards.d.ts +166 -0
- package/dist/lib/maths/guards.d.ts.map +1 -0
- package/dist/lib/maths/guards.js +315 -0
- package/dist/lib/maths/guards.mjs +1 -0
- package/dist/lib/maths/index.cjs +1 -0
- package/dist/lib/maths/index.d.ts +24 -0
- package/dist/lib/maths/index.d.ts.map +1 -0
- package/dist/lib/maths/index.js +29 -0
- package/dist/lib/maths/index.mjs +1 -0
- package/dist/lib/maths/parser.cjs +1 -0
- package/dist/lib/maths/parser.d.ts +20 -0
- package/dist/lib/maths/parser.d.ts.map +1 -0
- package/dist/lib/maths/parser.js +78 -0
- package/dist/lib/maths/parser.mjs +1 -0
- package/dist/lib/maths/random.cjs +1 -0
- package/dist/lib/maths/random.d.ts +27 -0
- package/dist/lib/maths/random.d.ts.map +1 -0
- package/dist/lib/maths/random.js +49 -0
- package/dist/lib/maths/random.mjs +1 -0
- package/dist/lib/maths/types/advanced.cjs +1 -0
- package/dist/lib/maths/types/advanced.d.ts +357 -0
- package/dist/lib/maths/types/advanced.d.ts.map +1 -0
- package/dist/lib/maths/types/advanced.js +5 -0
- package/dist/lib/maths/types/advanced.mjs +0 -0
- package/dist/lib/maths/types/basic.cjs +1 -0
- package/dist/lib/maths/types/basic.d.ts +95 -0
- package/dist/lib/maths/types/basic.d.ts.map +1 -0
- package/dist/lib/maths/types/basic.js +5 -0
- package/dist/lib/maths/types/basic.mjs +0 -0
- package/dist/lib/maths/types/index.cjs +1 -0
- package/dist/lib/maths/types/index.d.ts +4 -0
- package/dist/lib/maths/types/index.d.ts.map +1 -0
- package/dist/lib/maths/types/index.js +3 -0
- package/dist/lib/maths/types/index.mjs +0 -0
- package/dist/lib/maths/types/negative.cjs +1 -0
- package/dist/lib/maths/types/negative.d.ts +51 -0
- package/dist/lib/maths/types/negative.d.ts.map +1 -0
- package/dist/lib/maths/types/negative.js +5 -0
- package/dist/lib/maths/types/negative.mjs +0 -0
- package/dist/lib/maths/types/operations.cjs +1 -0
- package/dist/lib/maths/types/operations.d.ts +188 -0
- package/dist/lib/maths/types/operations.d.ts.map +1 -0
- package/dist/lib/maths/types/operations.js +6 -0
- package/dist/lib/maths/types/operations.mjs +0 -0
- package/dist/lib/object/clone.cjs +1 -0
- package/dist/lib/object/clone.d.ts +46 -0
- package/dist/lib/object/clone.d.ts.map +1 -0
- package/dist/lib/object/clone.js +104 -0
- package/dist/lib/object/clone.mjs +1 -0
- package/dist/lib/object/diff.cjs +1 -0
- package/dist/lib/object/diff.d.ts +203 -0
- package/dist/lib/object/diff.d.ts.map +1 -0
- package/dist/lib/object/diff.js +805 -0
- package/dist/lib/object/diff.mjs +1 -0
- package/dist/lib/object/getter-setter.cjs +1 -0
- package/dist/lib/object/getter-setter.d.ts +361 -0
- package/dist/lib/object/getter-setter.d.ts.map +1 -0
- package/dist/lib/object/getter-setter.js +1771 -0
- package/dist/lib/object/getter-setter.mjs +1 -0
- package/dist/lib/object/index.cjs +6 -0
- package/dist/lib/object/index.d.ts +13 -0
- package/dist/lib/object/index.d.ts.map +1 -0
- package/dist/lib/object/index.js +12 -0
- package/dist/lib/object/index.mjs +6 -0
- package/dist/lib/object/merge.cjs +1 -0
- package/dist/lib/object/merge.d.ts +93 -0
- package/dist/lib/object/merge.d.ts.map +1 -0
- package/dist/lib/object/merge.js +474 -0
- package/dist/lib/object/merge.mjs +1 -0
- package/dist/lib/object/object.cjs +1 -0
- package/dist/lib/object/object.d.ts +128 -0
- package/dist/lib/object/object.d.ts.map +1 -0
- package/dist/lib/object/object.js +432 -0
- package/dist/lib/object/object.mjs +1 -0
- package/dist/lib/object/omit.cjs +1 -0
- package/dist/lib/object/omit.d.ts +351 -0
- package/dist/lib/object/omit.d.ts.map +1 -0
- package/dist/lib/object/omit.js +656 -0
- package/dist/lib/object/omit.mjs +1 -0
- package/dist/lib/object/reconcile.cjs +1 -0
- package/dist/lib/object/reconcile.d.ts +7 -0
- package/dist/lib/object/reconcile.d.ts.map +1 -0
- package/dist/lib/object/reconcile.js +122 -0
- package/dist/lib/object/reconcile.mjs +1 -0
- package/dist/lib/object/selector.cjs +1 -0
- package/dist/lib/object/selector.d.ts +50 -0
- package/dist/lib/object/selector.d.ts.map +1 -0
- package/dist/lib/object/selector.js +371 -0
- package/dist/lib/object/selector.mjs +1 -0
- package/dist/lib/object/sort.cjs +1 -0
- package/dist/lib/object/sort.d.ts +149 -0
- package/dist/lib/object/sort.d.ts.map +1 -0
- package/dist/lib/object/sort.js +298 -0
- package/dist/lib/object/sort.mjs +1 -0
- package/dist/lib/object/transform.cjs +1 -0
- package/dist/lib/object/transform.d.ts +620 -0
- package/dist/lib/object/transform.d.ts.map +1 -0
- package/dist/lib/object/transform.js +1058 -0
- package/dist/lib/object/transform.mjs +1 -0
- package/dist/lib/object/types.cjs +1 -0
- package/dist/lib/object/types.d.ts +250 -0
- package/dist/lib/object/types.d.ts.map +1 -0
- package/dist/lib/object/types.js +1 -0
- package/dist/lib/object/types.mjs +0 -0
- package/dist/lib/object/utils.cjs +6 -0
- package/dist/lib/object/utils.d.ts +165 -0
- package/dist/lib/object/utils.d.ts.map +1 -0
- package/dist/lib/object/utils.js +444 -0
- package/dist/lib/object/utils.mjs +6 -0
- package/dist/lib/primitive/boolean/boolean.cjs +1 -0
- package/dist/lib/primitive/boolean/boolean.d.ts +276 -0
- package/dist/lib/primitive/boolean/boolean.d.ts.map +1 -0
- package/dist/lib/primitive/boolean/boolean.js +615 -0
- package/dist/lib/primitive/boolean/boolean.mjs +1 -0
- package/dist/lib/primitive/boolean/index.cjs +1 -0
- package/dist/lib/primitive/boolean/index.d.ts +3 -0
- package/dist/lib/primitive/boolean/index.d.ts.map +1 -0
- package/dist/lib/primitive/boolean/index.js +2 -0
- package/dist/lib/primitive/boolean/index.mjs +1 -0
- package/dist/lib/primitive/boolean/types.cjs +1 -0
- package/dist/lib/primitive/boolean/types.d.ts +14 -0
- package/dist/lib/primitive/boolean/types.d.ts.map +1 -0
- package/dist/lib/primitive/boolean/types.js +1 -0
- package/dist/lib/primitive/boolean/types.mjs +0 -0
- package/dist/lib/primitive/date/date.cjs +1 -0
- package/dist/lib/primitive/date/date.d.ts +641 -0
- package/dist/lib/primitive/date/date.d.ts.map +1 -0
- package/dist/lib/primitive/date/date.js +1998 -0
- package/dist/lib/primitive/date/date.mjs +1 -0
- package/dist/lib/primitive/date/index.cjs +1 -0
- package/dist/lib/primitive/date/index.d.ts +3 -0
- package/dist/lib/primitive/date/index.d.ts.map +1 -0
- package/dist/lib/primitive/date/index.js +2 -0
- package/dist/lib/primitive/date/index.mjs +1 -0
- package/dist/lib/primitive/date/types.cjs +1 -0
- package/dist/lib/primitive/date/types.d.ts +205 -0
- package/dist/lib/primitive/date/types.d.ts.map +1 -0
- package/dist/lib/primitive/date/types.js +7 -0
- package/dist/lib/primitive/date/types.mjs +0 -0
- package/dist/lib/primitive/index.cjs +5 -0
- package/dist/lib/primitive/index.d.ts +5 -0
- package/dist/lib/primitive/index.d.ts.map +1 -0
- package/dist/lib/primitive/index.js +4 -0
- package/dist/lib/primitive/index.mjs +5 -0
- package/dist/lib/primitive/string/index.cjs +5 -0
- package/dist/lib/primitive/string/index.d.ts +3 -0
- package/dist/lib/primitive/string/index.d.ts.map +1 -0
- package/dist/lib/primitive/string/index.js +2 -0
- package/dist/lib/primitive/string/index.mjs +5 -0
- package/dist/lib/primitive/string/parser-2.cjs +8 -0
- package/dist/lib/primitive/string/parser-2.d.ts +17 -0
- package/dist/lib/primitive/string/parser-2.d.ts.map +1 -0
- package/dist/lib/primitive/string/parser-2.js +656 -0
- package/dist/lib/primitive/string/parser-2.mjs +8 -0
- package/dist/lib/primitive/string/parser.cjs +3 -0
- package/dist/lib/primitive/string/parser.d.ts +9 -0
- package/dist/lib/primitive/string/parser.d.ts.map +1 -0
- package/dist/lib/primitive/string/parser.js +775 -0
- package/dist/lib/primitive/string/parser.mjs +3 -0
- package/dist/lib/primitive/string/string.cjs +5 -0
- package/dist/lib/primitive/string/string.d.ts +535 -0
- package/dist/lib/primitive/string/string.d.ts.map +1 -0
- package/dist/lib/primitive/string/string.js +1301 -0
- package/dist/lib/primitive/string/string.mjs +5 -0
- package/dist/lib/primitive/string/types.cjs +1 -0
- package/dist/lib/primitive/string/types.d.ts +318 -0
- package/dist/lib/primitive/string/types.d.ts.map +1 -0
- package/dist/lib/primitive/string/types.js +5 -0
- package/dist/lib/primitive/string/types.mjs +0 -0
- package/dist/lib/primitive/types.cjs +1 -0
- package/dist/lib/primitive/types.d.ts +27 -0
- package/dist/lib/primitive/types.d.ts.map +1 -0
- package/dist/lib/primitive/types.js +1 -0
- package/dist/lib/primitive/types.mjs +0 -0
- package/dist/lib/url/index.cjs +1 -0
- package/dist/lib/url/index.d.ts +3 -0
- package/dist/lib/url/index.d.ts.map +1 -0
- package/dist/lib/url/index.js +2 -0
- package/dist/lib/url/index.mjs +1 -0
- package/dist/lib/url/parser.cjs +1 -0
- package/dist/lib/url/parser.d.ts +216 -0
- package/dist/lib/url/parser.d.ts.map +1 -0
- package/dist/lib/url/parser.js +488 -0
- package/dist/lib/url/parser.mjs +1 -0
- package/dist/lib/url/types.cjs +1 -0
- package/dist/lib/url/types.d.ts +18 -0
- package/dist/lib/url/types.d.ts.map +1 -0
- package/dist/lib/url/types.js +1 -0
- package/dist/lib/url/types.mjs +0 -0
- package/dist/tsconfig.lib.tsbuildinfo +1 -0
- package/package.json +150 -0
|
@@ -0,0 +1,656 @@
|
|
|
1
|
+
class ParseError extends Error {
|
|
2
|
+
position;
|
|
3
|
+
line;
|
|
4
|
+
column;
|
|
5
|
+
constructor(message, position, line, column) {
|
|
6
|
+
super(`${message} at line ${line}, column ${column} (position ${position})`);
|
|
7
|
+
this.position = position;
|
|
8
|
+
this.line = line;
|
|
9
|
+
this.column = column;
|
|
10
|
+
this.name = 'ParseError';
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Robust state machine parser for JavaScript object literals
|
|
15
|
+
*/
|
|
16
|
+
export function parseObjectLiteral(str, options = {}) {
|
|
17
|
+
// Validate input
|
|
18
|
+
if (typeof str !== 'string') {
|
|
19
|
+
throw new TypeError('Input must be a string');
|
|
20
|
+
}
|
|
21
|
+
if (str.trim().length === 0) {
|
|
22
|
+
throw new ParseError('Input string is empty', 0, 1, 1);
|
|
23
|
+
}
|
|
24
|
+
// Set defaults
|
|
25
|
+
const defaultOptions = {
|
|
26
|
+
allowUnquotedKeys: true,
|
|
27
|
+
allowTrailingCommas: true,
|
|
28
|
+
allowSingleQuotes: true,
|
|
29
|
+
allowComments: true,
|
|
30
|
+
allowUndefined: false,
|
|
31
|
+
allowSpecialNumbers: false,
|
|
32
|
+
reviver: undefined,
|
|
33
|
+
strict: false,
|
|
34
|
+
maxDepth: 100,
|
|
35
|
+
};
|
|
36
|
+
const mergedOptions = {
|
|
37
|
+
...defaultOptions,
|
|
38
|
+
...options,
|
|
39
|
+
};
|
|
40
|
+
// Parse state
|
|
41
|
+
let index = 0;
|
|
42
|
+
let char = str[0];
|
|
43
|
+
let line = 1;
|
|
44
|
+
let column = 1;
|
|
45
|
+
let depth = 0;
|
|
46
|
+
const optionsRef = mergedOptions;
|
|
47
|
+
const maxLength = str.length;
|
|
48
|
+
// Helper functions
|
|
49
|
+
const isEnd = () => index >= maxLength;
|
|
50
|
+
const advance = () => {
|
|
51
|
+
if (char === '\n') {
|
|
52
|
+
line++;
|
|
53
|
+
column = 1;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
column++;
|
|
57
|
+
}
|
|
58
|
+
index++;
|
|
59
|
+
if (index < maxLength) {
|
|
60
|
+
char = str[index];
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
char = '';
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
const peek = (offset = 1) => {
|
|
67
|
+
const peekIndex = index + offset;
|
|
68
|
+
return peekIndex < maxLength ? str[peekIndex] : '';
|
|
69
|
+
};
|
|
70
|
+
const createError = (message) => {
|
|
71
|
+
return new ParseError(message, index, line, column);
|
|
72
|
+
};
|
|
73
|
+
const skipWhitespace = () => {
|
|
74
|
+
while (!isEnd() && (char === ' ' || char === '\t' || char === '\n' || char === '\r')) {
|
|
75
|
+
advance();
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
const skipLineComment = () => {
|
|
79
|
+
// We're at the first '/' of '//'
|
|
80
|
+
advance(); // Skip second '/'
|
|
81
|
+
while (!isEnd() && char !== '\n' && char !== '\r') {
|
|
82
|
+
advance();
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
const skipBlockComment = () => {
|
|
86
|
+
// We're at the first '/' of '/*'
|
|
87
|
+
advance(); // Skip '*'
|
|
88
|
+
while (!isEnd()) {
|
|
89
|
+
if (char === '*' && peek() === '/') {
|
|
90
|
+
advance(); // Skip '*'
|
|
91
|
+
advance(); // Skip '/'
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
advance();
|
|
95
|
+
}
|
|
96
|
+
throw createError('Unterminated block comment');
|
|
97
|
+
};
|
|
98
|
+
const skipWhitespaceAndComments = () => {
|
|
99
|
+
while (!isEnd()) {
|
|
100
|
+
const prevIndex = index;
|
|
101
|
+
skipWhitespace();
|
|
102
|
+
if (optionsRef.allowComments && char === '/') {
|
|
103
|
+
const nextChar = peek();
|
|
104
|
+
if (nextChar === '/') {
|
|
105
|
+
skipLineComment();
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
else if (nextChar === '*') {
|
|
109
|
+
skipBlockComment();
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (index === prevIndex) {
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
// ====================
|
|
119
|
+
// Parsing Functions
|
|
120
|
+
// ====================
|
|
121
|
+
const parseValue = () => {
|
|
122
|
+
depth++;
|
|
123
|
+
if (depth > optionsRef.maxDepth) {
|
|
124
|
+
throw createError(`Maximum nesting depth (${optionsRef.maxDepth}) exceeded`);
|
|
125
|
+
}
|
|
126
|
+
skipWhitespaceAndComments();
|
|
127
|
+
if (isEnd()) {
|
|
128
|
+
throw createError('Unexpected end of input');
|
|
129
|
+
}
|
|
130
|
+
let value;
|
|
131
|
+
// Parse based on current character
|
|
132
|
+
const currentChar = char;
|
|
133
|
+
if (currentChar === '{') {
|
|
134
|
+
value = parseObject();
|
|
135
|
+
}
|
|
136
|
+
else if (currentChar === '[') {
|
|
137
|
+
value = parseArray();
|
|
138
|
+
}
|
|
139
|
+
else if (currentChar === '"' || currentChar === "'") {
|
|
140
|
+
value = parseString();
|
|
141
|
+
}
|
|
142
|
+
else if (currentChar === '-' || (currentChar >= '0' && currentChar <= '9')) {
|
|
143
|
+
value = parseNumber();
|
|
144
|
+
}
|
|
145
|
+
else if (currentChar === 't' || currentChar === 'f' || currentChar === 'n') {
|
|
146
|
+
value = parseKeyword();
|
|
147
|
+
}
|
|
148
|
+
else if (currentChar === 'u' && optionsRef.allowUndefined) {
|
|
149
|
+
value = parseKeyword();
|
|
150
|
+
}
|
|
151
|
+
else if ((currentChar === 'I' || currentChar === 'N') && optionsRef.allowSpecialNumbers) {
|
|
152
|
+
value = parseSpecialNumber();
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
// throw createError(`Unexpected character "${currentChar}"`);
|
|
156
|
+
}
|
|
157
|
+
depth--;
|
|
158
|
+
return value;
|
|
159
|
+
};
|
|
160
|
+
const parseObject = () => {
|
|
161
|
+
const obj = {};
|
|
162
|
+
// Skip opening brace
|
|
163
|
+
advance();
|
|
164
|
+
skipWhitespaceAndComments();
|
|
165
|
+
// Handle empty object
|
|
166
|
+
if (char === '}') {
|
|
167
|
+
advance();
|
|
168
|
+
return obj;
|
|
169
|
+
}
|
|
170
|
+
// Parse object properties
|
|
171
|
+
while (!isEnd()) {
|
|
172
|
+
skipWhitespaceAndComments();
|
|
173
|
+
// Parse key
|
|
174
|
+
let key;
|
|
175
|
+
const currentChar = char;
|
|
176
|
+
if (currentChar === '"' || currentChar === "'") {
|
|
177
|
+
key = parseString();
|
|
178
|
+
}
|
|
179
|
+
else if (optionsRef.allowUnquotedKeys &&
|
|
180
|
+
((currentChar >= 'a' && currentChar <= 'z') ||
|
|
181
|
+
(currentChar >= 'A' && currentChar <= 'Z') ||
|
|
182
|
+
currentChar === '_' || currentChar === '$')) {
|
|
183
|
+
const start = index;
|
|
184
|
+
while (!isEnd() &&
|
|
185
|
+
((char >= 'a' && char <= 'z') ||
|
|
186
|
+
(char >= 'A' && char <= 'Z') ||
|
|
187
|
+
(char >= '0' && char <= '9') ||
|
|
188
|
+
char === '_' || char === '$')) {
|
|
189
|
+
advance();
|
|
190
|
+
}
|
|
191
|
+
key = str.slice(start, index);
|
|
192
|
+
// Validate it's not a keyword
|
|
193
|
+
if (key === 'true' || key === 'false' || key === 'null' ||
|
|
194
|
+
(optionsRef.allowUndefined && key === 'undefined')) {
|
|
195
|
+
throw createError(`Keyword "${key}" cannot be used as unquoted property name`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
throw createError(`Expected property name, got "${char}"`);
|
|
200
|
+
}
|
|
201
|
+
skipWhitespaceAndComments();
|
|
202
|
+
// Expect colon
|
|
203
|
+
// if (char !== ':') {
|
|
204
|
+
// throw createError('Expected colon after property name');
|
|
205
|
+
// }
|
|
206
|
+
advance();
|
|
207
|
+
skipWhitespaceAndComments();
|
|
208
|
+
// Parse value
|
|
209
|
+
obj[key] = parseValue();
|
|
210
|
+
skipWhitespaceAndComments();
|
|
211
|
+
// Check what comes next
|
|
212
|
+
const nextChar = char;
|
|
213
|
+
if (nextChar === '}') {
|
|
214
|
+
advance();
|
|
215
|
+
return obj;
|
|
216
|
+
}
|
|
217
|
+
if (nextChar === ',') {
|
|
218
|
+
advance();
|
|
219
|
+
skipWhitespaceAndComments();
|
|
220
|
+
// Check if the next thing is a closing brace (trailing comma)
|
|
221
|
+
const afterCommaChar = char;
|
|
222
|
+
if (afterCommaChar === '}') {
|
|
223
|
+
if (optionsRef.allowTrailingCommas) {
|
|
224
|
+
advance();
|
|
225
|
+
return obj;
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
throw createError('Trailing comma not allowed');
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
// Continue to next property
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
// throw createError(`Expected comma or closing brace, got "${nextChar}"`);
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
throw createError('Unexpected end of input in object');
|
|
238
|
+
};
|
|
239
|
+
const parseArray = () => {
|
|
240
|
+
const arr = [];
|
|
241
|
+
// Skip opening bracket
|
|
242
|
+
advance();
|
|
243
|
+
skipWhitespaceAndComments();
|
|
244
|
+
// Handle empty array
|
|
245
|
+
if (char === ']') {
|
|
246
|
+
advance();
|
|
247
|
+
return arr;
|
|
248
|
+
}
|
|
249
|
+
// Parse array elements
|
|
250
|
+
while (!isEnd()) {
|
|
251
|
+
// Parse element
|
|
252
|
+
arr.push(parseValue());
|
|
253
|
+
skipWhitespaceAndComments();
|
|
254
|
+
// Check what comes next
|
|
255
|
+
const nextChar = char;
|
|
256
|
+
if (nextChar === ']') {
|
|
257
|
+
advance();
|
|
258
|
+
return arr;
|
|
259
|
+
}
|
|
260
|
+
if (nextChar === ',') {
|
|
261
|
+
advance();
|
|
262
|
+
skipWhitespaceAndComments();
|
|
263
|
+
// Check if the next thing is a closing bracket (trailing comma)
|
|
264
|
+
const afterCommaChar = char;
|
|
265
|
+
if (afterCommaChar === ']') {
|
|
266
|
+
if (optionsRef.allowTrailingCommas) {
|
|
267
|
+
advance();
|
|
268
|
+
return arr;
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
throw createError('Trailing comma not allowed');
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
// Continue to next element
|
|
275
|
+
continue;
|
|
276
|
+
}
|
|
277
|
+
throw createError(`Expected comma or closing bracket, got "${nextChar}"`);
|
|
278
|
+
}
|
|
279
|
+
throw createError('Unexpected end of input in array');
|
|
280
|
+
};
|
|
281
|
+
const parseString = () => {
|
|
282
|
+
const quoteChar = char;
|
|
283
|
+
const startPos = index;
|
|
284
|
+
if (quoteChar === "'" && !optionsRef.allowSingleQuotes) {
|
|
285
|
+
throw createError('Single quotes are not allowed');
|
|
286
|
+
}
|
|
287
|
+
// Skip opening quote
|
|
288
|
+
advance();
|
|
289
|
+
let result = '';
|
|
290
|
+
while (!isEnd()) {
|
|
291
|
+
const currentChar = char;
|
|
292
|
+
if (currentChar === '\\') {
|
|
293
|
+
// Handle escape sequence
|
|
294
|
+
advance();
|
|
295
|
+
if (isEnd()) {
|
|
296
|
+
throw createError('Unterminated escape sequence');
|
|
297
|
+
}
|
|
298
|
+
result += parseEscapeSequence(quoteChar);
|
|
299
|
+
}
|
|
300
|
+
else if (currentChar === quoteChar) {
|
|
301
|
+
// End of string
|
|
302
|
+
advance();
|
|
303
|
+
return result;
|
|
304
|
+
}
|
|
305
|
+
else if (currentChar === '\n' || currentChar === '\r') {
|
|
306
|
+
// Newline in string (not allowed unless escaped)
|
|
307
|
+
throw createError('Unterminated string literal');
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
result += currentChar;
|
|
311
|
+
advance();
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
throw createError(`Unterminated string literal starting at position ${startPos}`);
|
|
315
|
+
};
|
|
316
|
+
const parseEscapeSequence = (quoteChar) => {
|
|
317
|
+
const escapeChar = char;
|
|
318
|
+
if (escapeChar === 'b') {
|
|
319
|
+
advance();
|
|
320
|
+
return '\b';
|
|
321
|
+
}
|
|
322
|
+
else if (escapeChar === 'f') {
|
|
323
|
+
advance();
|
|
324
|
+
return '\f';
|
|
325
|
+
}
|
|
326
|
+
else if (escapeChar === 'n') {
|
|
327
|
+
advance();
|
|
328
|
+
return '\n';
|
|
329
|
+
}
|
|
330
|
+
else if (escapeChar === 'r') {
|
|
331
|
+
advance();
|
|
332
|
+
return '\r';
|
|
333
|
+
}
|
|
334
|
+
else if (escapeChar === 't') {
|
|
335
|
+
advance();
|
|
336
|
+
return '\t';
|
|
337
|
+
}
|
|
338
|
+
else if (escapeChar === 'v') {
|
|
339
|
+
advance();
|
|
340
|
+
return '\v';
|
|
341
|
+
}
|
|
342
|
+
else if (escapeChar === '0') {
|
|
343
|
+
advance();
|
|
344
|
+
return '\0';
|
|
345
|
+
}
|
|
346
|
+
else if (escapeChar === 'x') {
|
|
347
|
+
advance();
|
|
348
|
+
return parseHexEscape(2);
|
|
349
|
+
}
|
|
350
|
+
else if (escapeChar === 'u') {
|
|
351
|
+
advance();
|
|
352
|
+
return parseUnicodeEscape();
|
|
353
|
+
}
|
|
354
|
+
else if (escapeChar === '\n') {
|
|
355
|
+
// Line continuation
|
|
356
|
+
advance();
|
|
357
|
+
return '';
|
|
358
|
+
}
|
|
359
|
+
else if (escapeChar === '\r') {
|
|
360
|
+
// Windows line continuation
|
|
361
|
+
if (peek() === '\n') {
|
|
362
|
+
advance(); // Skip \r
|
|
363
|
+
advance(); // Skip \n
|
|
364
|
+
}
|
|
365
|
+
else {
|
|
366
|
+
advance();
|
|
367
|
+
}
|
|
368
|
+
return '';
|
|
369
|
+
}
|
|
370
|
+
else {
|
|
371
|
+
// Return the character itself (for \\, \", \', etc.)
|
|
372
|
+
const charToReturn = escapeChar;
|
|
373
|
+
advance();
|
|
374
|
+
return charToReturn;
|
|
375
|
+
}
|
|
376
|
+
};
|
|
377
|
+
const parseHexEscape = (length) => {
|
|
378
|
+
let hex = '';
|
|
379
|
+
for (let i = 0; i < length; i++) {
|
|
380
|
+
const currentChar = char;
|
|
381
|
+
const isHex = (currentChar >= '0' && currentChar <= '9') ||
|
|
382
|
+
(currentChar >= 'a' && currentChar <= 'f') ||
|
|
383
|
+
(currentChar >= 'A' && currentChar <= 'F');
|
|
384
|
+
if (isEnd() || !isHex) {
|
|
385
|
+
throw createError('Invalid hex escape sequence');
|
|
386
|
+
}
|
|
387
|
+
hex += currentChar;
|
|
388
|
+
advance();
|
|
389
|
+
}
|
|
390
|
+
return String.fromCharCode(parseInt(hex, 16));
|
|
391
|
+
};
|
|
392
|
+
const parseUnicodeEscape = () => {
|
|
393
|
+
// Check for Unicode code point escape \u{...}
|
|
394
|
+
const currentChar = char;
|
|
395
|
+
if (currentChar === '{') {
|
|
396
|
+
advance();
|
|
397
|
+
let hex = '';
|
|
398
|
+
while (!isEnd() && char !== '}') {
|
|
399
|
+
const currentHexChar = char;
|
|
400
|
+
const isHex = (currentHexChar >= '0' && currentHexChar <= '9') ||
|
|
401
|
+
(currentHexChar >= 'a' && currentHexChar <= 'f') ||
|
|
402
|
+
(currentHexChar >= 'A' && currentHexChar <= 'F');
|
|
403
|
+
if (!isHex) {
|
|
404
|
+
throw createError('Invalid Unicode code point');
|
|
405
|
+
}
|
|
406
|
+
hex += currentHexChar;
|
|
407
|
+
advance();
|
|
408
|
+
}
|
|
409
|
+
if (char !== '}') {
|
|
410
|
+
throw createError('Unterminated Unicode code point escape');
|
|
411
|
+
}
|
|
412
|
+
advance(); // Skip '}'
|
|
413
|
+
const codePoint = parseInt(hex, 16);
|
|
414
|
+
if (isNaN(codePoint) || codePoint > 0x10FFFF) {
|
|
415
|
+
throw createError('Invalid Unicode code point');
|
|
416
|
+
}
|
|
417
|
+
return String.fromCodePoint(codePoint);
|
|
418
|
+
}
|
|
419
|
+
// Regular 4-digit hex escape
|
|
420
|
+
return parseHexEscape(4);
|
|
421
|
+
};
|
|
422
|
+
const parseNumber = () => {
|
|
423
|
+
const start = index;
|
|
424
|
+
let numberStr = '';
|
|
425
|
+
// Optional sign
|
|
426
|
+
if (char === '-') {
|
|
427
|
+
numberStr += char;
|
|
428
|
+
advance();
|
|
429
|
+
}
|
|
430
|
+
// Check for special numbers first
|
|
431
|
+
if (optionsRef.allowSpecialNumbers) {
|
|
432
|
+
if (char === 'I') {
|
|
433
|
+
const word = str.slice(index, index + 8);
|
|
434
|
+
if (word === 'Infinity') {
|
|
435
|
+
for (let i = 0; i < 8; i++)
|
|
436
|
+
advance();
|
|
437
|
+
return numberStr === '-' ? -Infinity : Infinity;
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
else if (char === 'N') {
|
|
441
|
+
const word = str.slice(index, index + 3);
|
|
442
|
+
if (word === 'NaN') {
|
|
443
|
+
for (let i = 0; i < 3; i++)
|
|
444
|
+
advance();
|
|
445
|
+
return NaN;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
// Integer part
|
|
450
|
+
if (char === '0') {
|
|
451
|
+
numberStr += char;
|
|
452
|
+
advance();
|
|
453
|
+
// Check for non-decimal literals (only if allowUnquotedKeys is true)
|
|
454
|
+
if (optionsRef.allowUnquotedKeys) {
|
|
455
|
+
// const radixChar = char;
|
|
456
|
+
const radixChar = numberStr.charAt(1);
|
|
457
|
+
if (radixChar === 'x' || radixChar === 'X') {
|
|
458
|
+
// Hexadecimal
|
|
459
|
+
advance();
|
|
460
|
+
return parseNonDecimalNumber(16);
|
|
461
|
+
}
|
|
462
|
+
else if (radixChar === 'o' || radixChar === 'O') {
|
|
463
|
+
// Octal
|
|
464
|
+
advance();
|
|
465
|
+
return parseNonDecimalNumber(8);
|
|
466
|
+
}
|
|
467
|
+
else if (radixChar === 'b' || radixChar === 'B') {
|
|
468
|
+
// Binary
|
|
469
|
+
advance();
|
|
470
|
+
return parseNonDecimalNumber(2);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
// Collect integer digits
|
|
475
|
+
while (!isEnd() && char >= '0' && char <= '9') {
|
|
476
|
+
numberStr += char;
|
|
477
|
+
advance();
|
|
478
|
+
}
|
|
479
|
+
// Fraction part
|
|
480
|
+
if (char === '.') {
|
|
481
|
+
numberStr += char;
|
|
482
|
+
advance();
|
|
483
|
+
// Must have at least one digit after decimal point
|
|
484
|
+
if (!(char >= '0' && char <= '9')) {
|
|
485
|
+
throw createError('Expected digit after decimal point');
|
|
486
|
+
}
|
|
487
|
+
while (!isEnd() && char >= '0' && char <= '9') {
|
|
488
|
+
numberStr += char;
|
|
489
|
+
advance();
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
// Exponent part
|
|
493
|
+
if (char === 'e' || char === 'E') {
|
|
494
|
+
numberStr += char;
|
|
495
|
+
advance();
|
|
496
|
+
// Optional exponent sign
|
|
497
|
+
if (peek() === '+' || peek() === '-') {
|
|
498
|
+
numberStr += char;
|
|
499
|
+
advance();
|
|
500
|
+
}
|
|
501
|
+
// Must have at least one digit in exponent
|
|
502
|
+
if (!(char >= '0' && char <= '9')) {
|
|
503
|
+
throw createError('Expected digit in exponent');
|
|
504
|
+
}
|
|
505
|
+
while (!isEnd() && char >= '0' && char <= '9') {
|
|
506
|
+
numberStr += char;
|
|
507
|
+
advance();
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
const num = parseFloat(numberStr);
|
|
511
|
+
if (isNaN(num)) {
|
|
512
|
+
throw createError(`Invalid number "${numberStr}"`);
|
|
513
|
+
}
|
|
514
|
+
return num;
|
|
515
|
+
};
|
|
516
|
+
const parseNonDecimalNumber = (radix) => {
|
|
517
|
+
let digits = '';
|
|
518
|
+
while (!isEnd()) {
|
|
519
|
+
const currentChar = char;
|
|
520
|
+
let isValid = false;
|
|
521
|
+
if (radix === 16) {
|
|
522
|
+
isValid = (currentChar >= '0' && currentChar <= '9') ||
|
|
523
|
+
(currentChar >= 'a' && currentChar <= 'f') ||
|
|
524
|
+
(currentChar >= 'A' && currentChar <= 'F');
|
|
525
|
+
}
|
|
526
|
+
else if (radix === 8) {
|
|
527
|
+
isValid = currentChar >= '0' && currentChar <= '7';
|
|
528
|
+
}
|
|
529
|
+
else if (radix === 2) {
|
|
530
|
+
isValid = currentChar === '0' || currentChar === '1';
|
|
531
|
+
}
|
|
532
|
+
if (!isValid) {
|
|
533
|
+
break;
|
|
534
|
+
}
|
|
535
|
+
digits += currentChar;
|
|
536
|
+
advance();
|
|
537
|
+
}
|
|
538
|
+
if (digits.length === 0) {
|
|
539
|
+
const baseName = radix === 16 ? 'hexadecimal' : radix === 8 ? 'octal' : 'binary';
|
|
540
|
+
throw createError(`Invalid ${baseName} number`);
|
|
541
|
+
}
|
|
542
|
+
return parseInt(digits, radix);
|
|
543
|
+
};
|
|
544
|
+
const parseSpecialNumber = () => {
|
|
545
|
+
if (char === 'I' && str.slice(index, index + 8) === 'Infinity') {
|
|
546
|
+
for (let i = 0; i < 8; i++)
|
|
547
|
+
advance();
|
|
548
|
+
return Infinity;
|
|
549
|
+
}
|
|
550
|
+
else if (char === 'N' && str.slice(index, index + 3) === 'NaN') {
|
|
551
|
+
for (let i = 0; i < 3; i++)
|
|
552
|
+
advance();
|
|
553
|
+
return NaN;
|
|
554
|
+
}
|
|
555
|
+
else if (char === '-' && str.slice(index, index + 9) === '-Infinity') {
|
|
556
|
+
for (let i = 0; i < 9; i++)
|
|
557
|
+
advance();
|
|
558
|
+
return -Infinity;
|
|
559
|
+
}
|
|
560
|
+
throw createError('Invalid special number');
|
|
561
|
+
};
|
|
562
|
+
const parseKeyword = () => {
|
|
563
|
+
const start = index;
|
|
564
|
+
let keyword = '';
|
|
565
|
+
while (!isEnd()) {
|
|
566
|
+
const currentChar = char;
|
|
567
|
+
const isIdentifierChar = (currentChar >= 'a' && currentChar <= 'z') ||
|
|
568
|
+
(currentChar >= 'A' && currentChar <= 'Z') ||
|
|
569
|
+
(currentChar >= '0' && currentChar <= '9') ||
|
|
570
|
+
currentChar === '_' || currentChar === '$';
|
|
571
|
+
if (!isIdentifierChar) {
|
|
572
|
+
break;
|
|
573
|
+
}
|
|
574
|
+
keyword += currentChar;
|
|
575
|
+
advance();
|
|
576
|
+
}
|
|
577
|
+
if (keyword === 'true') {
|
|
578
|
+
return true;
|
|
579
|
+
}
|
|
580
|
+
else if (keyword === 'false') {
|
|
581
|
+
return false;
|
|
582
|
+
}
|
|
583
|
+
else if (keyword === 'null') {
|
|
584
|
+
return null;
|
|
585
|
+
}
|
|
586
|
+
else if (keyword === 'undefined' && optionsRef.allowUndefined) {
|
|
587
|
+
return undefined;
|
|
588
|
+
}
|
|
589
|
+
else {
|
|
590
|
+
throw createError(`Unknown keyword "${keyword}"`);
|
|
591
|
+
}
|
|
592
|
+
};
|
|
593
|
+
// Apply reviver function
|
|
594
|
+
const applyReviver = (holder, key, value, reviver) => {
|
|
595
|
+
if (value && typeof value === 'object') {
|
|
596
|
+
if (Array.isArray(value)) {
|
|
597
|
+
for (let i = 0; i < value.length; i++) {
|
|
598
|
+
const transformed = applyReviver(value, i.toString(), value[i], reviver);
|
|
599
|
+
if (transformed === undefined) {
|
|
600
|
+
value.splice(i, 1);
|
|
601
|
+
i--;
|
|
602
|
+
}
|
|
603
|
+
else {
|
|
604
|
+
value[i] = transformed;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
else {
|
|
609
|
+
for (const k in value) {
|
|
610
|
+
if (Object.prototype.hasOwnProperty.call(value, k)) {
|
|
611
|
+
const transformed = applyReviver(value, k, value[k], reviver);
|
|
612
|
+
if (transformed === undefined) {
|
|
613
|
+
delete value[k];
|
|
614
|
+
}
|
|
615
|
+
else {
|
|
616
|
+
value[k] = transformed;
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
return reviver.call(holder, key, value);
|
|
623
|
+
};
|
|
624
|
+
// ====================
|
|
625
|
+
// Main Parsing Logic
|
|
626
|
+
// ====================
|
|
627
|
+
try {
|
|
628
|
+
// Start parsing
|
|
629
|
+
skipWhitespaceAndComments();
|
|
630
|
+
const result = parseValue();
|
|
631
|
+
// Ensure we consumed everything
|
|
632
|
+
skipWhitespaceAndComments();
|
|
633
|
+
if (!isEnd()) {
|
|
634
|
+
throw createError(`Unexpected trailing content: "${str.slice(index, index + 20)}"`);
|
|
635
|
+
}
|
|
636
|
+
// Apply reviver if provided
|
|
637
|
+
if (mergedOptions.reviver) {
|
|
638
|
+
return applyReviver({ '': result }, '', result, mergedOptions.reviver);
|
|
639
|
+
}
|
|
640
|
+
return result;
|
|
641
|
+
}
|
|
642
|
+
catch (error) {
|
|
643
|
+
// Fallback to JSON.parse if not strict
|
|
644
|
+
if (!mergedOptions.strict && error instanceof ParseError) {
|
|
645
|
+
try {
|
|
646
|
+
return mergedOptions.reviver
|
|
647
|
+
? JSON.parse(str, mergedOptions.reviver)
|
|
648
|
+
: JSON.parse(str);
|
|
649
|
+
}
|
|
650
|
+
catch {
|
|
651
|
+
throw error; // Re-throw original error
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
throw error;
|
|
655
|
+
}
|
|
656
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
var w=class extends Error{constructor(U,p,s,n){super(`${U} at line ${s}, column ${n} (position ${p})`);this.position=p;this.line=s;this.column=n;this.name="ParseError"}};function K(f,I={}){if(typeof f!="string")throw new TypeError("Input must be a string");if(f.trim().length===0)throw new w("Input string is empty",0,1,1);let p={...{allowUnquotedKeys:!0,allowTrailingCommas:!0,allowSingleQuotes:!0,allowComments:!0,allowUndefined:!1,allowSpecialNumbers:!1,reviver:void 0,strict:!1,maxDepth:100},...I},s=0,n=f[0],k=1,y=1,b=0,u=p,g=f.length,c=()=>s>=g,i=()=>{n===`
|
|
2
|
+
`?(k++,y=1):y++,s++,s<g?n=f[s]:n=""},h=(r=1)=>{let e=s+r;return e<g?f[e]:""},a=r=>new w(r,s,k,y),O=()=>{for(;!c()&&(n===" "||n===" "||n===`
|
|
3
|
+
`||n==="\r");)i()},q=()=>{for(i();!c()&&n!==`
|
|
4
|
+
`&&n!=="\r";)i()},E=()=>{for(i();!c();){if(n==="*"&&h()==="/"){i(),i();return}i()}throw a("Unterminated block comment")},d=()=>{for(;!c();){let r=s;if(O(),u.allowComments&&n==="/"){let e=h();if(e==="/"){q();continue}else if(e==="*"){E();continue}}if(s===r)break}},C=()=>{if(b++,b>u.maxDepth)throw a(`Maximum nesting depth (${u.maxDepth}) exceeded`);if(d(),c())throw a("Unexpected end of input");let r,e=n;return e==="{"?r=T():e==="["?r=A():e==='"'||e==="'"?r=S():e==="-"||e>="0"&&e<="9"?r=R():e==="t"||e==="f"||e==="n"||e==="u"&&u.allowUndefined?r=v():(e==="I"||e==="N")&&u.allowSpecialNumbers&&(r=j()),b--,r},T=()=>{let r={};if(i(),d(),n==="}")return i(),r;for(;!c();){d();let e,t=n;if(t==='"'||t==="'")e=S();else if(u.allowUnquotedKeys&&(t>="a"&&t<="z"||t>="A"&&t<="Z"||t==="_"||t==="$")){let l=s;for(;!c()&&(n>="a"&&n<="z"||n>="A"&&n<="Z"||n>="0"&&n<="9"||n==="_"||n==="$");)i();if(e=f.slice(l,s),e==="true"||e==="false"||e==="null"||u.allowUndefined&&e==="undefined")throw a(`Keyword "${e}" cannot be used as unquoted property name`)}else throw a(`Expected property name, got "${n}"`);d(),i(),d(),r[e]=C(),d();let o=n;if(o==="}")return i(),r;if(o===","){if(i(),d(),n==="}"){if(u.allowTrailingCommas)return i(),r;throw a("Trailing comma not allowed")}continue}}throw a("Unexpected end of input in object")},A=()=>{let r=[];if(i(),d(),n==="]")return i(),r;for(;!c();){r.push(C()),d();let e=n;if(e==="]")return i(),r;if(e===","){if(i(),d(),n==="]"){if(u.allowTrailingCommas)return i(),r;throw a("Trailing comma not allowed")}continue}throw a(`Expected comma or closing bracket, got "${e}"`)}throw a("Unexpected end of input in array")},S=()=>{let r=n,e=s;if(r==="'"&&!u.allowSingleQuotes)throw a("Single quotes are not allowed");i();let t="";for(;!c();){let o=n;if(o==="\\"){if(i(),c())throw a("Unterminated escape sequence");t+=P(r)}else{if(o===r)return i(),t;if(o===`
|
|
5
|
+
`||o==="\r")throw a("Unterminated string literal");t+=o,i()}}throw a(`Unterminated string literal starting at position ${e}`)},P=r=>{let e=n;if(e==="b")return i(),"\b";if(e==="f")return i(),"\f";if(e==="n")return i(),`
|
|
6
|
+
`;if(e==="r")return i(),"\r";if(e==="t")return i()," ";if(e==="v")return i(),"\v";if(e==="0")return i(),"\0";if(e==="x")return i(),$(2);if(e==="u")return i(),F();if(e===`
|
|
7
|
+
`)return i(),"";if(e==="\r")return h()===`
|
|
8
|
+
`&&i(),i(),"";{let t=e;return i(),t}},$=r=>{let e="";for(let t=0;t<r;t++){let o=n,l=o>="0"&&o<="9"||o>="a"&&o<="f"||o>="A"&&o<="F";if(c()||!l)throw a("Invalid hex escape sequence");e+=o,i()}return String.fromCharCode(parseInt(e,16))},F=()=>{if(n==="{"){i();let e="";for(;!c()&&n!=="}";){let o=n;if(!(o>="0"&&o<="9"||o>="a"&&o<="f"||o>="A"&&o<="F"))throw a("Invalid Unicode code point");e+=o,i()}if(n!=="}")throw a("Unterminated Unicode code point escape");i();let t=parseInt(e,16);if(isNaN(t)||t>1114111)throw a("Invalid Unicode code point");return String.fromCodePoint(t)}return $(4)},R=()=>{let r=s,e="";if(n==="-"&&(e+=n,i()),u.allowSpecialNumbers){if(n==="I"){if(f.slice(s,s+8)==="Infinity"){for(let l=0;l<8;l++)i();return e==="-"?-1/0:1/0}}else if(n==="N"&&f.slice(s,s+3)==="NaN"){for(let l=0;l<3;l++)i();return NaN}}if(n==="0"&&(e+=n,i(),u.allowUnquotedKeys)){let o=e.charAt(1);if(o==="x"||o==="X")return i(),x(16);if(o==="o"||o==="O")return i(),x(8);if(o==="b"||o==="B")return i(),x(2)}for(;!c()&&n>="0"&&n<="9";)e+=n,i();if(n==="."){if(e+=n,i(),!(n>="0"&&n<="9"))throw a("Expected digit after decimal point");for(;!c()&&n>="0"&&n<="9";)e+=n,i()}if(n==="e"||n==="E"){if(e+=n,i(),(h()==="+"||h()==="-")&&(e+=n,i()),!(n>="0"&&n<="9"))throw a("Expected digit in exponent");for(;!c()&&n>="0"&&n<="9";)e+=n,i()}let t=parseFloat(e);if(isNaN(t))throw a(`Invalid number "${e}"`);return t},x=r=>{let e="";for(;!c();){let t=n,o=!1;if(r===16?o=t>="0"&&t<="9"||t>="a"&&t<="f"||t>="A"&&t<="F":r===8?o=t>="0"&&t<="7":r===2&&(o=t==="0"||t==="1"),!o)break;e+=t,i()}if(e.length===0)throw a(`Invalid ${r===16?"hexadecimal":r===8?"octal":"binary"} number`);return parseInt(e,r)},j=()=>{if(n==="I"&&f.slice(s,s+8)==="Infinity"){for(let r=0;r<8;r++)i();return 1/0}else if(n==="N"&&f.slice(s,s+3)==="NaN"){for(let r=0;r<3;r++)i();return NaN}else if(n==="-"&&f.slice(s,s+9)==="-Infinity"){for(let r=0;r<9;r++)i();return-1/0}throw a("Invalid special number")},v=()=>{let r=s,e="";for(;!c();){let t=n;if(!(t>="a"&&t<="z"||t>="A"&&t<="Z"||t>="0"&&t<="9"||t==="_"||t==="$"))break;e+=t,i()}if(e==="true")return!0;if(e==="false")return!1;if(e==="null")return null;if(e==="undefined"&&u.allowUndefined)return;throw a(`Unknown keyword "${e}"`)},N=(r,e,t,o)=>{if(t&&typeof t=="object"){if(Array.isArray(t))for(let l=0;l<t.length;l++){let m=N(t,l.toString(),t[l],o);m===void 0?(t.splice(l,1),l--):t[l]=m}else for(let l in t)if(Object.prototype.hasOwnProperty.call(t,l)){let m=N(t,l,t[l],o);m===void 0?delete t[l]:t[l]=m}}return o.call(r,e,t)};try{d();let r=C();if(d(),!c())throw a(`Unexpected trailing content: "${f.slice(s,s+20)}"`);return p.reviver?N({"":r},"",r,p.reviver):r}catch(r){if(!p.strict&&r instanceof w)try{return p.reviver?JSON.parse(f,p.reviver):JSON.parse(f)}catch{throw r}throw r}}export{K as parseObjectLiteral};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use strict";var d=Object.defineProperty;var S=Object.getOwnPropertyDescriptor;var m=Object.getOwnPropertyNames;var x=Object.prototype.hasOwnProperty;var b=(f,s)=>{for(var o in s)d(f,o,{get:s[o],enumerable:!0})},C=(f,s,o,h)=>{if(s&&typeof s=="object"||typeof s=="function")for(let u of m(s))!x.call(f,u)&&u!==o&&d(f,u,{get:()=>s[u],enumerable:!(h=S(s,u))||h.enumerable});return f};var N=f=>C(d({},"__esModule",{value:!0}),f);var y={};b(y,{customParse:()=>J,parseJsObjectLiteral:()=>$,simpleJsObjectParse:()=>j});module.exports=N(y);function J(f,s={}){try{return JSON.parse(f)}catch{return $(f,s)}}function $(f,s={}){let{allowComments:o=!0,allowUnquotedKeys:h=!0,allowSingleQuotes:u=!0,allowTrailingCommas:p=!0,allowUndefined:w=!1}=s,t=f.trim();if(o&&(t=t.replace(/\/\*[\s\S]*?\*\//g,""),t=t.split(`
|
|
2
|
+
`).map(r=>{let a=!1,e="",n=!1;for(let c=0;c<r.length;c++){let g=r[c];if(n){n=!1;continue}if(g==="\\"){n=!0;continue}if(!a&&(g==='"'||g==="'"))a=!0,e=g;else if(a&&g===e)a=!1,e="";else if(!a&&g==="/"&&r[c+1]==="/")return r.substring(0,c)}return r}).join(`
|
|
3
|
+
`)),h&&(t=t.replace(/([{,]\s*)([a-zA-Z_$][a-zA-Z0-9_$]*)(\s*:)/g,'$1"$2"$3')),u){let l="",i=!1,r=!1,a=!1,e=0;for(;e<t.length;){let n=t[e];if(a){l+=n,a=!1,e++;continue}if(n==="\\"){a=!0,l+=n,e++;continue}n==="'"&&!r?i?(l+='"',i=!1):(l+='"',i=!0):(n==='"'&&!i&&(r?r=!1:r=!0),l+=n),e++}t=l}if(p){let l="",i=!1,r="",a=!1,e=0;for(;e<t.length;){let n=t[e];if(a){l+=n,a=!1,e++;continue}if(n==="\\"){a=!0,l+=n,e++;continue}if((n==='"'||n==="'")&&!i)i=!0,r=n,l+=n;else if(i&&n===r)i=!1,r="",l+=n;else if(!i&&n===","){let c=e+1;for(;c<t.length&&/\s/.test(t[c]);)c++;if(c<t.length&&(t[c]==="]"||t[c]==="}")){e++;continue}else l+=n}else l+=n;e++}t=l}if(w){let l="",i=!1,r="",a=!1,e=0;for(;e<t.length;){if(a){l+=t[e],a=!1,e++;continue}if(t[e]==="\\"){a=!0,l+=t[e],e++;continue}if((t[e]==='"'||t[e]==="'")&&!i)i=!0,r=t[e],l+=t[e];else if(i&&t[e]===r)i=!1,r="",l+=t[e];else if(!i&&t.substr(e,9)==="undefined"){let n=e>0?t[e-1]:"",c=e+8<t.length?t[e+9]:"";if(/[a-zA-Z0-9_$]/.test(n)||/[a-zA-Z0-9_$]/.test(c))l+=t[e];else{l+="null",e+=9;continue}}else l+=t[e];e++}t=l}try{return JSON.parse(t)}catch{return}}function j(f){let s=f;s=s.replace(/\/\*[\s\S]*?\*\//g,"").replace(/\/\/.*$/gm,""),s=s.replace(/([{,]\s*)([a-zA-Z_$][\w$]*)(\s*:)/g,(o,h,u,p)=>u==="true"||u==="false"||u==="null"||u==="undefined"||/^\d/.test(u)?o:`${h}"${u}"${p}`),s=s.replace(/'([^'\\]*(?:\\.[^'\\]*)*)'/g,'"$1"'),s=s.replace(/,(\s*[\]}])/g,"$1");try{return JSON.parse(s)}catch(o){throw new SyntaxError(`Failed to parse JavaScript object literal: ${o}`)}}
|