@uni-helper/jsonu 0.0.1

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/dist/index.mjs ADDED
@@ -0,0 +1,1765 @@
1
+ //#region node_modules/.pnpm/@humanwhocodes+momoa@3.3.10/node_modules/@humanwhocodes/momoa/dist/momoa.js
2
+ /**
3
+ * @fileoverview Character codes.
4
+ * @author Nicholas C. Zakas
5
+ */
6
+ const CHAR_0 = 48;
7
+ const CHAR_1 = 49;
8
+ const CHAR_9 = 57;
9
+ const CHAR_BACKSLASH = 92;
10
+ const CHAR_DOLLAR = 36;
11
+ const CHAR_DOT = 46;
12
+ const CHAR_DOUBLE_QUOTE = 34;
13
+ const CHAR_LOWER_A = 97;
14
+ const CHAR_LOWER_E = 101;
15
+ const CHAR_LOWER_F = 102;
16
+ const CHAR_LOWER_N = 110;
17
+ const CHAR_LOWER_T = 116;
18
+ const CHAR_LOWER_U = 117;
19
+ const CHAR_LOWER_X = 120;
20
+ const CHAR_LOWER_Z = 122;
21
+ const CHAR_MINUS = 45;
22
+ const CHAR_NEWLINE = 10;
23
+ const CHAR_PLUS = 43;
24
+ const CHAR_RETURN = 13;
25
+ const CHAR_SINGLE_QUOTE = 39;
26
+ const CHAR_SLASH = 47;
27
+ const CHAR_SPACE = 32;
28
+ const CHAR_TAB = 9;
29
+ const CHAR_UNDERSCORE = 95;
30
+ const CHAR_UPPER_A = 65;
31
+ const CHAR_UPPER_E = 69;
32
+ const CHAR_UPPER_F = 70;
33
+ const CHAR_UPPER_N = 78;
34
+ const CHAR_UPPER_X = 88;
35
+ const CHAR_UPPER_Z = 90;
36
+ const CHAR_LOWER_B = 98;
37
+ const CHAR_LOWER_R = 114;
38
+ const CHAR_LOWER_V = 118;
39
+ const CHAR_LINE_SEPARATOR = 8232;
40
+ const CHAR_PARAGRAPH_SEPARATOR = 8233;
41
+ const CHAR_UPPER_I = 73;
42
+ const CHAR_STAR = 42;
43
+ const CHAR_VTAB = 11;
44
+ const CHAR_FORM_FEED = 12;
45
+ const CHAR_NBSP = 160;
46
+ const CHAR_BOM = 65279;
47
+ const CHAR_NON_BREAKING_SPACE = 160;
48
+ const CHAR_EN_QUAD = 8192;
49
+ const CHAR_EM_QUAD = 8193;
50
+ const CHAR_EN_SPACE = 8194;
51
+ const CHAR_EM_SPACE = 8195;
52
+ const CHAR_THREE_PER_EM_SPACE = 8196;
53
+ const CHAR_FOUR_PER_EM_SPACE = 8197;
54
+ const CHAR_SIX_PER_EM_SPACE = 8198;
55
+ const CHAR_FIGURE_SPACE = 8199;
56
+ const CHAR_PUNCTUATION_SPACE = 8200;
57
+ const CHAR_THIN_SPACE = 8201;
58
+ const CHAR_HAIR_SPACE = 8202;
59
+ const CHAR_NARROW_NO_BREAK_SPACE = 8239;
60
+ const CHAR_MEDIUM_MATHEMATICAL_SPACE = 8287;
61
+ const CHAR_IDEOGRAPHIC_SPACE = 12288;
62
+ /**
63
+ * @fileoverview JSON syntax helpers
64
+ * @author Nicholas C. Zakas
65
+ */
66
+ /** @typedef {import("./typedefs.js").TokenType} TokenType */
67
+ const LBRACKET = "[";
68
+ const RBRACKET = "]";
69
+ const LBRACE = "{";
70
+ const RBRACE = "}";
71
+ const COLON = ":";
72
+ const COMMA = ",";
73
+ const TRUE = "true";
74
+ const FALSE = "false";
75
+ const NULL = "null";
76
+ const NAN$1 = "NaN";
77
+ const INFINITY$1 = "Infinity";
78
+ const QUOTE = "\"";
79
+ const escapeToChar = new Map([
80
+ [CHAR_DOUBLE_QUOTE, QUOTE],
81
+ [CHAR_BACKSLASH, "\\"],
82
+ [CHAR_SLASH, "/"],
83
+ [CHAR_LOWER_B, "\b"],
84
+ [CHAR_LOWER_N, "\n"],
85
+ [CHAR_LOWER_F, "\f"],
86
+ [CHAR_LOWER_R, "\r"],
87
+ [CHAR_LOWER_T, " "]
88
+ ]);
89
+ const json5EscapeToChar = new Map([
90
+ ...escapeToChar,
91
+ [CHAR_LOWER_V, "\v"],
92
+ [CHAR_0, "\0"]
93
+ ]);
94
+ new Map([
95
+ ...new Map([
96
+ [QUOTE, QUOTE],
97
+ ["\\", "\\"],
98
+ ["/", "/"],
99
+ ["\b", "b"],
100
+ ["\n", "n"],
101
+ ["\f", "f"],
102
+ ["\r", "r"],
103
+ [" ", "t"]
104
+ ]),
105
+ ["\v", "v"],
106
+ ["\0", "0"],
107
+ ["\u2028", "u2028"],
108
+ ["\u2029", "u2029"]
109
+ ]);
110
+ /** @type {Map<string,TokenType>} */
111
+ const knownTokenTypes = new Map([
112
+ [LBRACKET, "LBracket"],
113
+ [RBRACKET, "RBracket"],
114
+ [LBRACE, "LBrace"],
115
+ [RBRACE, "RBrace"],
116
+ [COLON, "Colon"],
117
+ [COMMA, "Comma"],
118
+ [TRUE, "Boolean"],
119
+ [FALSE, "Boolean"],
120
+ [NULL, "Null"]
121
+ ]);
122
+ /** @type {Map<string,TokenType>} */
123
+ const knownJSON5TokenTypes = new Map([
124
+ ...knownTokenTypes,
125
+ [NAN$1, "Number"],
126
+ [INFINITY$1, "Number"]
127
+ ]);
128
+ const json5LineTerminators = new Set([
129
+ CHAR_NEWLINE,
130
+ CHAR_RETURN,
131
+ CHAR_LINE_SEPARATOR,
132
+ CHAR_PARAGRAPH_SEPARATOR
133
+ ]);
134
+ /**
135
+ * @fileoverview JSON tokenization/parsing errors
136
+ * @author Nicholas C. Zakas
137
+ */
138
+ /** @typedef {import("./typedefs.js").Location} Location */
139
+ /** @typedef {import("./typedefs.js").Token} Token */
140
+ /**
141
+ * Base class that attaches location to an error.
142
+ */
143
+ var ErrorWithLocation = class extends Error {
144
+ /**
145
+ * Creates a new instance.
146
+ * @param {string} message The error message to report.
147
+ * @param {Location} loc The location information for the error.
148
+ */
149
+ constructor(message, { line, column, offset }) {
150
+ super(`${message} (${line}:${column})`);
151
+ /**
152
+ * The line on which the error occurred.
153
+ * @type {number}
154
+ */
155
+ this.line = line;
156
+ /**
157
+ * The column on which the error occurred.
158
+ * @type {number}
159
+ */
160
+ this.column = column;
161
+ /**
162
+ * The index into the string where the error occurred.
163
+ * @type {number}
164
+ */
165
+ this.offset = offset;
166
+ }
167
+ };
168
+ /**
169
+ * Error thrown when an unexpected character is found during tokenizing.
170
+ */
171
+ var UnexpectedChar = class extends ErrorWithLocation {
172
+ /**
173
+ * Creates a new instance.
174
+ * @param {number} unexpected The character that was found.
175
+ * @param {Location} loc The location information for the found character.
176
+ */
177
+ constructor(unexpected, loc) {
178
+ super(`Unexpected character '${String.fromCharCode(unexpected)}' found.`, loc);
179
+ }
180
+ };
181
+ /**
182
+ * Error thrown when an unexpected identifier is found during tokenizing.
183
+ */
184
+ var UnexpectedIdentifier = class extends ErrorWithLocation {
185
+ /**
186
+ * Creates a new instance.
187
+ * @param {string} unexpected The character that was found.
188
+ * @param {Location} loc The location information for the found character.
189
+ */
190
+ constructor(unexpected, loc) {
191
+ super(`Unexpected identifier '${unexpected}' found.`, loc);
192
+ }
193
+ };
194
+ /**
195
+ * Error thrown when an unexpected token is found during parsing.
196
+ */
197
+ var UnexpectedToken = class extends ErrorWithLocation {
198
+ /**
199
+ * Creates a new instance.
200
+ * @param {Token} token The token that was found.
201
+ */
202
+ constructor(token) {
203
+ super(`Unexpected token ${token.type} found.`, token.loc.start);
204
+ }
205
+ };
206
+ /**
207
+ * Error thrown when the end of input is found where it isn't expected.
208
+ */
209
+ var UnexpectedEOF = class extends ErrorWithLocation {
210
+ /**
211
+ * Creates a new instance.
212
+ * @param {Location} loc The location information for the found character.
213
+ */
214
+ constructor(loc) {
215
+ super("Unexpected end of input found.", loc);
216
+ }
217
+ };
218
+ const ID_Start = /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF19]|\uD806[\uDCA0-\uDCDF\uDCFF\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE83\uDE86-\uDE89\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]/;
219
+ const ID_Continue = /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u08D4-\u08E1\u08E3-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u09FC\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0AF9-\u0AFF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58-\u0C5A\u0C60-\u0C63\u0C66-\u0C6F\u0C80-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D00-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D54-\u0D57\u0D5F-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1CD0-\u1CD2\u1CD4-\u1CF9\u1D00-\u1DF9\u1DFB-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C5\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA8FD\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDCA-\uDDCC\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE37\uDE3E\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF00-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF50\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC00-\uDC4A\uDC50-\uDC59\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDDD8-\uDDDD\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9\uDF00-\uDF19\uDF1D-\uDF2B\uDF30-\uDF39]|\uD806[\uDCA0-\uDCE9\uDCFF\uDE00-\uDE3E\uDE47\uDE50-\uDE83\uDE86-\uDE99\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC36\uDC38-\uDC40\uDC50-\uDC59\uDC72-\uDC8F\uDC92-\uDCA7\uDCA9-\uDCB6\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD36\uDD3A\uDD3C\uDD3D\uDD3F-\uDD47\uDD50-\uDD59]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD838[\uDC00-\uDC06\uDC08-\uDC18\uDC1B-\uDC21\uDC23\uDC24\uDC26-\uDC2A]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6\uDD00-\uDD4A\uDD50-\uDD59]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/;
220
+ /**
221
+ * @fileoverview A charactor code reader.
222
+ * @author Nicholas C. Zakas
223
+ */
224
+ const CHAR_CR = 13;
225
+ const CHAR_LF = 10;
226
+ /**
227
+ * A reader that reads character codes from a string.
228
+ */
229
+ var CharCodeReader = class {
230
+ /**
231
+ * The text to read from.
232
+ * @type {string}
233
+ */
234
+ #text = "";
235
+ /**
236
+ * The current line number.
237
+ * @type {number}
238
+ */
239
+ #line = 1;
240
+ /**
241
+ * The current column number.
242
+ * @type {number}
243
+ */
244
+ #column = 0;
245
+ /**
246
+ * The current offset in the text.
247
+ * @type {number}
248
+ */
249
+ #offset = -1;
250
+ /**
251
+ * Whether the last character read was a new line.
252
+ * @type {boolean}
253
+ */
254
+ #newLine = false;
255
+ /**
256
+ * The last character code read.
257
+ * @type {number}
258
+ */
259
+ #last = -1;
260
+ /**
261
+ * Whether the reader has ended.
262
+ * @type {boolean}
263
+ */
264
+ #ended = false;
265
+ /**
266
+ * Creates a new instance.
267
+ * @param {string} text The text to read from
268
+ */
269
+ constructor(text) {
270
+ this.#text = text;
271
+ }
272
+ /**
273
+ * Ends the reader.
274
+ * @returns {void}
275
+ */
276
+ #end() {
277
+ if (this.#ended) return;
278
+ this.#column++;
279
+ this.#offset++;
280
+ this.#last = -1;
281
+ this.#ended = true;
282
+ }
283
+ /**
284
+ * Returns the current position of the reader.
285
+ * @returns {Location} An object with line, column, and offset properties.
286
+ */
287
+ locate() {
288
+ return {
289
+ line: this.#line,
290
+ column: this.#column,
291
+ offset: this.#offset
292
+ };
293
+ }
294
+ /**
295
+ * Reads the next character code in the text.
296
+ * @returns {number} The next character code, or -1 if there are no more characters.
297
+ */
298
+ next() {
299
+ if (this.#offset >= this.#text.length - 1) {
300
+ this.#end();
301
+ return -1;
302
+ }
303
+ this.#offset++;
304
+ const charCode = this.#text.charCodeAt(this.#offset);
305
+ if (this.#newLine) {
306
+ this.#line++;
307
+ this.#column = 1;
308
+ this.#newLine = false;
309
+ } else this.#column++;
310
+ if (charCode === CHAR_CR) {
311
+ this.#newLine = true;
312
+ if (this.peek() === CHAR_LF) this.#offset++;
313
+ } else if (charCode === CHAR_LF) this.#newLine = true;
314
+ this.#last = charCode;
315
+ return charCode;
316
+ }
317
+ /**
318
+ * Peeks at the next character code in the text.
319
+ * @returns {number} The next character code, or -1 if there are no more characters.
320
+ */
321
+ peek() {
322
+ if (this.#offset === this.#text.length - 1) return -1;
323
+ return this.#text.charCodeAt(this.#offset + 1);
324
+ }
325
+ /**
326
+ * Determines if the next character code in the text matches a specific character code.
327
+ * @param {(number) => boolean} fn A function to call on the next character.
328
+ * @returns {boolean} True if the next character code matches, false if not.
329
+ */
330
+ match(fn) {
331
+ if (fn(this.peek())) {
332
+ this.next();
333
+ return true;
334
+ }
335
+ return false;
336
+ }
337
+ /**
338
+ * Returns the last character code read.
339
+ * @returns {number} The last character code read.
340
+ */
341
+ current() {
342
+ return this.#last;
343
+ }
344
+ };
345
+ /**
346
+ * @fileoverview JSON tokenizer
347
+ * @author Nicholas C. Zakas
348
+ */
349
+ /** @typedef {import("./typedefs.js").Range} Range */
350
+ /** @typedef {import("./typedefs.js").TokenizeOptions} TokenizeOptions */
351
+ const INFINITY = "Infinity";
352
+ const NAN = "NaN";
353
+ const keywordStarts = new Set([
354
+ CHAR_LOWER_T,
355
+ CHAR_LOWER_F,
356
+ CHAR_LOWER_N
357
+ ]);
358
+ const whitespace = new Set([
359
+ CHAR_SPACE,
360
+ CHAR_TAB,
361
+ CHAR_NEWLINE,
362
+ CHAR_RETURN
363
+ ]);
364
+ const json5Whitespace = new Set([
365
+ ...whitespace,
366
+ CHAR_VTAB,
367
+ CHAR_FORM_FEED,
368
+ CHAR_NBSP,
369
+ CHAR_LINE_SEPARATOR,
370
+ CHAR_PARAGRAPH_SEPARATOR,
371
+ CHAR_BOM,
372
+ CHAR_NON_BREAKING_SPACE,
373
+ CHAR_EN_QUAD,
374
+ CHAR_EM_QUAD,
375
+ CHAR_EN_SPACE,
376
+ CHAR_EM_SPACE,
377
+ CHAR_THREE_PER_EM_SPACE,
378
+ CHAR_FOUR_PER_EM_SPACE,
379
+ CHAR_SIX_PER_EM_SPACE,
380
+ CHAR_FIGURE_SPACE,
381
+ CHAR_PUNCTUATION_SPACE,
382
+ CHAR_THIN_SPACE,
383
+ CHAR_HAIR_SPACE,
384
+ CHAR_NARROW_NO_BREAK_SPACE,
385
+ CHAR_MEDIUM_MATHEMATICAL_SPACE,
386
+ CHAR_IDEOGRAPHIC_SPACE
387
+ ]);
388
+ /** @type {TokenizeOptions} */
389
+ const DEFAULT_OPTIONS$1 = {
390
+ mode: "json",
391
+ ranges: false
392
+ };
393
+ const jsonKeywords = new Set([
394
+ "true",
395
+ "false",
396
+ "null"
397
+ ]);
398
+ const tt = {
399
+ EOF: 0,
400
+ Number: 1,
401
+ String: 2,
402
+ Boolean: 3,
403
+ Null: 4,
404
+ NaN: 5,
405
+ Infinity: 6,
406
+ Identifier: 7,
407
+ Colon: 20,
408
+ LBrace: 21,
409
+ RBrace: 22,
410
+ LBracket: 23,
411
+ RBracket: 24,
412
+ Comma: 25,
413
+ LineComment: 40,
414
+ BlockComment: 41
415
+ };
416
+ /**
417
+ * Determines if a given character is a decimal digit.
418
+ * @param {number} c The character to check.
419
+ * @returns {boolean} `true` if the character is a digit.
420
+ */
421
+ function isDigit(c) {
422
+ return c >= CHAR_0 && c <= CHAR_9;
423
+ }
424
+ /**
425
+ * Determines if a given character is a hexadecimal digit.
426
+ * @param {number} c The character to check.
427
+ * @returns {boolean} `true` if the character is a hexadecimal digit.
428
+ */
429
+ function isHexDigit(c) {
430
+ return isDigit(c) || c >= CHAR_UPPER_A && c <= CHAR_UPPER_F || c >= CHAR_LOWER_A && c <= CHAR_LOWER_F;
431
+ }
432
+ /**
433
+ * Determines if a given character is a positive digit (1-9).
434
+ * @param {number} c The character to check.
435
+ * @returns {boolean} `true` if the character is a positive digit.
436
+ */
437
+ function isPositiveDigit(c) {
438
+ return c >= CHAR_1 && c <= CHAR_9;
439
+ }
440
+ /**
441
+ * Determines if a given character is the start of a keyword.
442
+ * @param {number} c The character to check.
443
+ * @returns {boolean} `true` if the character is the start of a keyword.
444
+ */
445
+ function isKeywordStart(c) {
446
+ return keywordStarts.has(c);
447
+ }
448
+ /**
449
+ * Determines if a given character is the start of a number.
450
+ * @param {number} c The character to check.
451
+ * @returns {boolean} `true` if the character is the start of a number.
452
+ */
453
+ function isNumberStart(c) {
454
+ return isDigit(c) || c === CHAR_DOT || c === CHAR_MINUS;
455
+ }
456
+ /**
457
+ * Determines if a given character is the start of a JSON5 number.
458
+ * @param {number} c The character to check.
459
+ * @returns {boolean} `true` if the character is the start of a JSON5 number.
460
+ */
461
+ function isJSON5NumberStart(c) {
462
+ return isNumberStart(c) || c === CHAR_PLUS;
463
+ }
464
+ /**
465
+ * Determines if a given character is the start of a string.
466
+ * @param {number} c The character to check.
467
+ * @param {boolean} json5 `true` if JSON5 mode is enabled.
468
+ * @returns {boolean} `true` if the character is the start of a string.
469
+ */
470
+ function isStringStart(c, json5) {
471
+ return c === CHAR_DOUBLE_QUOTE || json5 && c === CHAR_SINGLE_QUOTE;
472
+ }
473
+ /**
474
+ * Tests that a given character is a valid first character of a
475
+ * JSON5 identifier
476
+ * @param {number} c The character to check.
477
+ * @returns {boolean} `true` if the character is a valid first character.
478
+ */
479
+ function isJSON5IdentifierStart(c) {
480
+ if (c === CHAR_DOLLAR || c === CHAR_UNDERSCORE || c === CHAR_BACKSLASH) return true;
481
+ if (c >= CHAR_LOWER_A && c <= CHAR_LOWER_Z || c >= CHAR_UPPER_A && c <= CHAR_UPPER_Z) return true;
482
+ if (c === 8204 || c === 8205) return true;
483
+ const ct = String.fromCharCode(c);
484
+ return ID_Start.test(ct);
485
+ }
486
+ /**
487
+ * Tests that a given character is a valid part of a JSON5 identifier.
488
+ * @param {number} c The character to check.
489
+ * @returns {boolean} `true` if the character is a valid part of an identifier.
490
+ */
491
+ function isJSON5IdentifierPart(c) {
492
+ if (isJSON5IdentifierStart(c) || isDigit(c)) return true;
493
+ const ct = String.fromCharCode(c);
494
+ return ID_Continue.test(ct);
495
+ }
496
+ var Tokenizer = class {
497
+ /**
498
+ * Options for the tokenizer.
499
+ * @type {TokenizeOptions}
500
+ */
501
+ #options;
502
+ /**
503
+ * The source text to tokenize.
504
+ * @type {string}
505
+ */
506
+ #text;
507
+ /**
508
+ * The reader for the source text.
509
+ * @type {CharCodeReader}
510
+ */
511
+ #reader;
512
+ /**
513
+ * Indicates if the tokenizer is in JSON5 mode.
514
+ * @type {boolean}
515
+ */
516
+ #json5;
517
+ /**
518
+ * Indicates if comments are allowed.
519
+ * @type {boolean}
520
+ */
521
+ #allowComments;
522
+ /**
523
+ * Indicates if ranges should be included in the tokens.
524
+ * @type {boolean}
525
+ */
526
+ #ranges;
527
+ /**
528
+ * The last token type read.
529
+ * @type {Token}
530
+ */
531
+ #token;
532
+ /**
533
+ * Determines if a character is an escaped character.
534
+ * @type {(c:number) => boolean}
535
+ */
536
+ #isEscapedCharacter;
537
+ /**
538
+ * Determines if a character is a JSON5 line terminator.
539
+ * @type {(c:number) => boolean}
540
+ */
541
+ #isJSON5LineTerminator;
542
+ /**
543
+ * Determines if a character is a JSON5 hex escape.
544
+ * @type {(c:number) => boolean}
545
+ */
546
+ #isJSON5HexEscape;
547
+ /**
548
+ * Determines if a character is whitespace.
549
+ * @type {(c:number) => boolean}
550
+ */
551
+ #isWhitespace;
552
+ /**
553
+ * Creates a new instance of the tokenizer.
554
+ * @param {string} text The source text
555
+ * @param {TokenizeOptions} [options] Options for the tokenizer.
556
+ */
557
+ constructor(text, options) {
558
+ this.#text = text;
559
+ this.#options = {
560
+ ...DEFAULT_OPTIONS$1,
561
+ ...options
562
+ };
563
+ this.#reader = new CharCodeReader(text);
564
+ this.#json5 = this.#options.mode === "json5";
565
+ this.#allowComments = this.#options.mode !== "json";
566
+ this.#ranges = this.#options.ranges;
567
+ this.#isEscapedCharacter = this.#json5 ? json5EscapeToChar.has.bind(json5EscapeToChar) : escapeToChar.has.bind(escapeToChar);
568
+ this.#isJSON5LineTerminator = this.#json5 ? json5LineTerminators.has.bind(json5LineTerminators) : () => false;
569
+ this.#isJSON5HexEscape = this.#json5 ? (c) => c === CHAR_LOWER_X : () => false;
570
+ this.#isWhitespace = this.#json5 ? json5Whitespace.has.bind(json5Whitespace) : whitespace.has.bind(whitespace);
571
+ }
572
+ /**
573
+ * Convenience function for throwing unexpected character errors.
574
+ * @param {number} c The unexpected character.
575
+ * @param {Location} [loc] The location of the unexpected character.
576
+ * @returns {never}
577
+ * @throws {UnexpectedChar} always.
578
+ */
579
+ #unexpected(c, loc = this.#reader.locate()) {
580
+ throw new UnexpectedChar(c, loc);
581
+ }
582
+ /**
583
+ * Convenience function for throwing unexpected identifier errors.
584
+ * @param {string} identifier The unexpected identifier.
585
+ * @param {Location} [loc] The location of the unexpected identifier.
586
+ * @returns {never}
587
+ * @throws {UnexpectedIdentifier} always.
588
+ */
589
+ #unexpectedIdentifier(identifier, loc = this.#reader.locate()) {
590
+ throw new UnexpectedIdentifier(identifier, loc);
591
+ }
592
+ /**
593
+ * Convenience function for throwing unexpected EOF errors.
594
+ * @returns {never}
595
+ * @throws {UnexpectedEOF} always.
596
+ */
597
+ #unexpectedEOF() {
598
+ throw new UnexpectedEOF(this.#reader.locate());
599
+ }
600
+ /**
601
+ * Creates a new token.
602
+ * @param {TokenType} tokenType The type of token to create.
603
+ * @param {number} length The length of the token.
604
+ * @param {Location} startLoc The start location for the token.
605
+ * @param {Location} [endLoc] The end location for the token.
606
+ * @returns {Token} The token.
607
+ */
608
+ #createToken(tokenType, length, startLoc, endLoc) {
609
+ const endOffset = startLoc.offset + length;
610
+ let range = this.#options.ranges ? { range: [startLoc.offset, endOffset] } : void 0;
611
+ return {
612
+ type: tokenType,
613
+ loc: {
614
+ start: startLoc,
615
+ end: endLoc || {
616
+ line: startLoc.line,
617
+ column: startLoc.column + length,
618
+ offset: endOffset
619
+ }
620
+ },
621
+ ...range
622
+ };
623
+ }
624
+ /**
625
+ * Reads in a specific number of hex digits.
626
+ * @param {number} count The number of hex digits to read.
627
+ * @returns {string} The hex digits read.
628
+ */
629
+ #readHexDigits(count) {
630
+ let value = "";
631
+ let c;
632
+ for (let i = 0; i < count; i++) {
633
+ c = this.#reader.peek();
634
+ if (isHexDigit(c)) {
635
+ this.#reader.next();
636
+ value += String.fromCharCode(c);
637
+ continue;
638
+ }
639
+ this.#unexpected(c);
640
+ }
641
+ return value;
642
+ }
643
+ /**
644
+ * Reads in a JSON5 identifier. Also used for JSON but we validate
645
+ * the identifier later.
646
+ * @param {number} c The first character of the identifier.
647
+ * @returns {string} The identifier read.
648
+ * @throws {UnexpectedChar} when the identifier cannot be read.
649
+ */
650
+ #readIdentifier(c) {
651
+ let value = "";
652
+ do {
653
+ value += String.fromCharCode(c);
654
+ if (c === CHAR_BACKSLASH) {
655
+ c = this.#reader.next();
656
+ if (c !== CHAR_LOWER_U) this.#unexpected(c);
657
+ value += String.fromCharCode(c);
658
+ const hexDigits = this.#readHexDigits(4);
659
+ const charCode = parseInt(hexDigits, 16);
660
+ if (value.length === 2 && !isJSON5IdentifierStart(charCode)) {
661
+ const loc = this.#reader.locate();
662
+ this.#unexpected(CHAR_BACKSLASH, {
663
+ line: loc.line,
664
+ column: loc.column - 5,
665
+ offset: loc.offset - 5
666
+ });
667
+ } else if (!isJSON5IdentifierPart(charCode)) {
668
+ const loc = this.#reader.locate();
669
+ this.#unexpected(charCode, {
670
+ line: loc.line,
671
+ column: loc.column - 5,
672
+ offset: loc.offset - 5
673
+ });
674
+ }
675
+ value += hexDigits;
676
+ }
677
+ c = this.#reader.peek();
678
+ if (!isJSON5IdentifierPart(c)) break;
679
+ this.#reader.next();
680
+ } while (true);
681
+ return value;
682
+ }
683
+ /**
684
+ * Reads in a string. Works for both JSON and JSON5.
685
+ * @param {number} c The first character of the string (either " or ').
686
+ * @returns {number} The length of the string.
687
+ * @throws {UnexpectedChar} when the string cannot be read.
688
+ * @throws {UnexpectedEOF} when EOF is reached before the string is finalized.
689
+ */
690
+ #readString(c) {
691
+ const delimiter = c;
692
+ let length = 1;
693
+ c = this.#reader.peek();
694
+ while (c !== -1 && c !== delimiter) {
695
+ this.#reader.next();
696
+ length++;
697
+ if (c === CHAR_BACKSLASH) {
698
+ c = this.#reader.peek();
699
+ if (this.#isEscapedCharacter(c) || this.#isJSON5LineTerminator(c)) {
700
+ this.#reader.next();
701
+ length++;
702
+ } else if (c === CHAR_LOWER_U) {
703
+ this.#reader.next();
704
+ length++;
705
+ const result = this.#readHexDigits(4);
706
+ length += result.length;
707
+ } else if (this.#isJSON5HexEscape(c)) {
708
+ this.#reader.next();
709
+ length++;
710
+ const result = this.#readHexDigits(2);
711
+ length += result.length;
712
+ } else if (this.#json5) {
713
+ this.#reader.next();
714
+ length++;
715
+ } else this.#unexpected(c);
716
+ }
717
+ c = this.#reader.peek();
718
+ }
719
+ if (c === -1) {
720
+ this.#reader.next();
721
+ this.#unexpectedEOF();
722
+ }
723
+ this.#reader.next();
724
+ length++;
725
+ return length;
726
+ }
727
+ /**
728
+ * Reads a number. Works for both JSON and JSON5.
729
+ * @param {number} c The first character of the number.
730
+ * @returns {number} The length of the number.
731
+ * @throws {UnexpectedChar} when the number cannot be read.
732
+ * @throws {UnexpectedEOF} when EOF is reached before the number is finalized.
733
+ */
734
+ #readNumber(c) {
735
+ let length = 1;
736
+ if (c === CHAR_MINUS || this.#json5 && c === CHAR_PLUS) {
737
+ c = this.#reader.peek();
738
+ if (this.#json5) {
739
+ if (c === CHAR_UPPER_I || c === CHAR_UPPER_N) {
740
+ this.#reader.next();
741
+ const identifier = this.#readIdentifier(c);
742
+ if (identifier !== INFINITY && identifier !== NAN) this.#unexpected(c);
743
+ return length + identifier.length;
744
+ }
745
+ }
746
+ if (!isDigit(c)) this.#unexpected(c);
747
+ this.#reader.next();
748
+ length++;
749
+ }
750
+ if (c === CHAR_0) {
751
+ c = this.#reader.peek();
752
+ if (this.#json5 && (c === CHAR_LOWER_X || c === CHAR_UPPER_X)) {
753
+ this.#reader.next();
754
+ length++;
755
+ c = this.#reader.peek();
756
+ if (!isHexDigit(c)) {
757
+ this.#reader.next();
758
+ this.#unexpected(c);
759
+ }
760
+ do {
761
+ this.#reader.next();
762
+ length++;
763
+ c = this.#reader.peek();
764
+ } while (isHexDigit(c));
765
+ } else if (isDigit(c)) this.#unexpected(c);
766
+ } else if (!this.#json5 || c !== CHAR_DOT) {
767
+ if (!isPositiveDigit(c)) this.#unexpected(c);
768
+ c = this.#reader.peek();
769
+ while (isDigit(c)) {
770
+ this.#reader.next();
771
+ length++;
772
+ c = this.#reader.peek();
773
+ }
774
+ }
775
+ if (c === CHAR_DOT) {
776
+ let digitCount = -1;
777
+ this.#reader.next();
778
+ length++;
779
+ digitCount++;
780
+ c = this.#reader.peek();
781
+ while (isDigit(c)) {
782
+ this.#reader.next();
783
+ length++;
784
+ digitCount++;
785
+ c = this.#reader.peek();
786
+ }
787
+ if (!this.#json5 && digitCount === 0) {
788
+ this.#reader.next();
789
+ if (c) this.#unexpected(c);
790
+ else this.#unexpectedEOF();
791
+ }
792
+ }
793
+ if (c === CHAR_LOWER_E || c === CHAR_UPPER_E) {
794
+ this.#reader.next();
795
+ length++;
796
+ c = this.#reader.peek();
797
+ if (c === CHAR_PLUS || c === CHAR_MINUS) {
798
+ this.#reader.next();
799
+ length++;
800
+ c = this.#reader.peek();
801
+ }
802
+ if (c === -1) {
803
+ this.#reader.next();
804
+ this.#unexpectedEOF();
805
+ }
806
+ if (!isDigit(c)) {
807
+ this.#reader.next();
808
+ this.#unexpected(c);
809
+ }
810
+ while (isDigit(c)) {
811
+ this.#reader.next();
812
+ length++;
813
+ c = this.#reader.peek();
814
+ }
815
+ }
816
+ return length;
817
+ }
818
+ /**
819
+ * Reads a comment. Works for both JSON and JSON5.
820
+ * @param {number} c The first character of the comment.
821
+ * @returns {{length: number, multiline: boolean}} The length of the comment, and whether the comment is multi-line.
822
+ * @throws {UnexpectedChar} when the comment cannot be read.
823
+ * @throws {UnexpectedEOF} when EOF is reached before the comment is finalized.
824
+ */
825
+ #readComment(c) {
826
+ let length = 1;
827
+ c = this.#reader.peek();
828
+ if (c === CHAR_SLASH) {
829
+ do {
830
+ this.#reader.next();
831
+ length += 1;
832
+ c = this.#reader.peek();
833
+ } while (c > -1 && c !== CHAR_RETURN && c !== CHAR_NEWLINE);
834
+ return {
835
+ length,
836
+ multiline: false
837
+ };
838
+ }
839
+ if (c === CHAR_STAR) {
840
+ this.#reader.next();
841
+ length += 1;
842
+ while (c > -1) {
843
+ c = this.#reader.peek();
844
+ if (c === CHAR_STAR) {
845
+ this.#reader.next();
846
+ length += 1;
847
+ c = this.#reader.peek();
848
+ if (c === CHAR_SLASH) {
849
+ this.#reader.next();
850
+ length += 1;
851
+ return {
852
+ length,
853
+ multiline: true
854
+ };
855
+ }
856
+ } else {
857
+ this.#reader.next();
858
+ length += 1;
859
+ }
860
+ }
861
+ this.#reader.next();
862
+ this.#unexpectedEOF();
863
+ }
864
+ this.#reader.next();
865
+ this.#unexpected(c);
866
+ }
867
+ /**
868
+ * Returns the next token in the source text.
869
+ * @returns {number} The code for the next token.
870
+ */
871
+ next() {
872
+ let c = this.#reader.next();
873
+ while (this.#isWhitespace(c)) c = this.#reader.next();
874
+ if (c === -1) return tt.EOF;
875
+ const start = this.#reader.locate();
876
+ const ct = String.fromCharCode(c);
877
+ if (this.#json5) if (knownJSON5TokenTypes.has(ct)) this.#token = this.#createToken(knownJSON5TokenTypes.get(ct), 1, start);
878
+ else if (isJSON5IdentifierStart(c)) {
879
+ const value = this.#readIdentifier(c);
880
+ if (knownJSON5TokenTypes.has(value)) this.#token = this.#createToken(knownJSON5TokenTypes.get(value), value.length, start);
881
+ else this.#token = this.#createToken("Identifier", value.length, start);
882
+ } else if (isJSON5NumberStart(c)) {
883
+ const result = this.#readNumber(c);
884
+ this.#token = this.#createToken("Number", result, start);
885
+ } else if (isStringStart(c, this.#json5)) {
886
+ const result = this.#readString(c);
887
+ const lastCharLoc = this.#reader.locate();
888
+ this.#token = this.#createToken("String", result, start, {
889
+ line: lastCharLoc.line,
890
+ column: lastCharLoc.column + 1,
891
+ offset: lastCharLoc.offset + 1
892
+ });
893
+ } else if (c === CHAR_SLASH && this.#allowComments) {
894
+ const result = this.#readComment(c);
895
+ const lastCharLoc = this.#reader.locate();
896
+ this.#token = this.#createToken(!result.multiline ? "LineComment" : "BlockComment", result.length, start, {
897
+ line: lastCharLoc.line,
898
+ column: lastCharLoc.column + 1,
899
+ offset: lastCharLoc.offset + 1
900
+ });
901
+ } else this.#unexpected(c);
902
+ else if (knownTokenTypes.has(ct)) this.#token = this.#createToken(knownTokenTypes.get(ct), 1, start);
903
+ else if (isKeywordStart(c)) {
904
+ const value = this.#readIdentifier(c);
905
+ if (!jsonKeywords.has(value)) this.#unexpectedIdentifier(value, start);
906
+ this.#token = this.#createToken(knownTokenTypes.get(value), value.length, start);
907
+ } else if (isNumberStart(c)) {
908
+ const result = this.#readNumber(c);
909
+ this.#token = this.#createToken("Number", result, start);
910
+ } else if (isStringStart(c, this.#json5)) {
911
+ const result = this.#readString(c);
912
+ this.#token = this.#createToken("String", result, start);
913
+ } else if (c === CHAR_SLASH && this.#allowComments) {
914
+ const result = this.#readComment(c);
915
+ const lastCharLoc = this.#reader.locate();
916
+ this.#token = this.#createToken(!result.multiline ? "LineComment" : "BlockComment", result.length, start, {
917
+ line: lastCharLoc.line,
918
+ column: lastCharLoc.column + 1,
919
+ offset: lastCharLoc.offset + 1
920
+ });
921
+ } else this.#unexpected(c);
922
+ return tt[this.#token.type];
923
+ }
924
+ /**
925
+ * Returns the current token in the source text.
926
+ * @returns {Token} The current token.
927
+ */
928
+ get token() {
929
+ return this.#token;
930
+ }
931
+ };
932
+ /**
933
+ * @fileoverview JSON AST types
934
+ * @author Nicholas C. Zakas
935
+ */
936
+ /** @typedef {import("./typedefs.js").LocationRange} LocationRange */
937
+ /** @typedef {import("./typedefs.js").NodeParts} NodeParts */
938
+ /** @typedef {import("./typedefs.js").DocumentNode} DocumentNode */
939
+ /** @typedef {import("./typedefs.js").StringNode} StringNode */
940
+ /** @typedef {import("./typedefs.js").NumberNode} NumberNode */
941
+ /** @typedef {import("./typedefs.js").BooleanNode} BooleanNode */
942
+ /** @typedef {import("./typedefs.js").MemberNode} MemberNode */
943
+ /** @typedef {import("./typedefs.js").ObjectNode} ObjectNode */
944
+ /** @typedef {import("./typedefs.js").ElementNode} ElementNode */
945
+ /** @typedef {import("./typedefs.js").ArrayNode} ArrayNode */
946
+ /** @typedef {import("./typedefs.js").NullNode} NullNode */
947
+ /** @typedef {import("./typedefs.js").ValueNode} ValueNode */
948
+ /** @typedef {import("./typedefs.js").IdentifierNode} IdentifierNode */
949
+ /** @typedef {import("./typedefs.js").NaNNode} NaNNode */
950
+ /** @typedef {import("./typedefs.js").InfinityNode} InfinityNode */
951
+ /** @typedef {import("./typedefs.js").Sign} Sign */
952
+ const types = {
953
+ /**
954
+ * Creates a document node.
955
+ * @param {ValueNode} body The body of the document.
956
+ * @param {NodeParts} parts Additional properties for the node.
957
+ * @returns {DocumentNode} The document node.
958
+ */
959
+ document(body, parts = {}) {
960
+ return {
961
+ type: "Document",
962
+ body,
963
+ loc: parts.loc,
964
+ ...parts
965
+ };
966
+ },
967
+ /**
968
+ * Creates a string node.
969
+ * @param {string} value The value for the string.
970
+ * @param {NodeParts} parts Additional properties for the node.
971
+ * @returns {StringNode} The string node.
972
+ */
973
+ string(value, parts = {}) {
974
+ return {
975
+ type: "String",
976
+ value,
977
+ loc: parts.loc,
978
+ ...parts
979
+ };
980
+ },
981
+ /**
982
+ * Creates a number node.
983
+ * @param {number} value The value for the number.
984
+ * @param {NodeParts} parts Additional properties for the node.
985
+ * @returns {NumberNode} The number node.
986
+ */
987
+ number(value, parts = {}) {
988
+ return {
989
+ type: "Number",
990
+ value,
991
+ loc: parts.loc,
992
+ ...parts
993
+ };
994
+ },
995
+ /**
996
+ * Creates a boolean node.
997
+ * @param {boolean} value The value for the boolean.
998
+ * @param {NodeParts} parts Additional properties for the node.
999
+ * @returns {BooleanNode} The boolean node.
1000
+ */
1001
+ boolean(value, parts = {}) {
1002
+ return {
1003
+ type: "Boolean",
1004
+ value,
1005
+ loc: parts.loc,
1006
+ ...parts
1007
+ };
1008
+ },
1009
+ /**
1010
+ * Creates a null node.
1011
+ * @param {NodeParts} parts Additional properties for the node.
1012
+ * @returns {NullNode} The null node.
1013
+ */
1014
+ null(parts = {}) {
1015
+ return {
1016
+ type: "Null",
1017
+ loc: parts.loc,
1018
+ ...parts
1019
+ };
1020
+ },
1021
+ /**
1022
+ * Creates an array node.
1023
+ * @param {Array<ElementNode>} elements The elements to add.
1024
+ * @param {NodeParts} parts Additional properties for the node.
1025
+ * @returns {ArrayNode} The array node.
1026
+ */
1027
+ array(elements, parts = {}) {
1028
+ return {
1029
+ type: "Array",
1030
+ elements,
1031
+ loc: parts.loc,
1032
+ ...parts
1033
+ };
1034
+ },
1035
+ /**
1036
+ * Creates an element node.
1037
+ * @param {ValueNode} value The value for the element.
1038
+ * @param {NodeParts} parts Additional properties for the node.
1039
+ * @returns {ElementNode} The element node.
1040
+ */
1041
+ element(value, parts = {}) {
1042
+ return {
1043
+ type: "Element",
1044
+ value,
1045
+ loc: parts.loc,
1046
+ ...parts
1047
+ };
1048
+ },
1049
+ /**
1050
+ * Creates an object node.
1051
+ * @param {Array<MemberNode>} members The members to add.
1052
+ * @param {NodeParts} parts Additional properties for the node.
1053
+ * @returns {ObjectNode} The object node.
1054
+ */
1055
+ object(members, parts = {}) {
1056
+ return {
1057
+ type: "Object",
1058
+ members,
1059
+ loc: parts.loc,
1060
+ ...parts
1061
+ };
1062
+ },
1063
+ /**
1064
+ * Creates a member node.
1065
+ * @param {StringNode|IdentifierNode} name The name for the member.
1066
+ * @param {ValueNode} value The value for the member.
1067
+ * @param {NodeParts} parts Additional properties for the node.
1068
+ * @returns {MemberNode} The member node.
1069
+ */
1070
+ member(name, value, parts = {}) {
1071
+ return {
1072
+ type: "Member",
1073
+ name,
1074
+ value,
1075
+ loc: parts.loc,
1076
+ ...parts
1077
+ };
1078
+ },
1079
+ /**
1080
+ * Creates an identifier node.
1081
+ * @param {string} name The name for the identifier.
1082
+ * @param {NodeParts} parts Additional properties for the node.
1083
+ * @returns {IdentifierNode} The identifier node.
1084
+ */
1085
+ identifier(name, parts = {}) {
1086
+ return {
1087
+ type: "Identifier",
1088
+ name,
1089
+ loc: parts.loc,
1090
+ ...parts
1091
+ };
1092
+ },
1093
+ /**
1094
+ * Creates a NaN node.
1095
+ * @param {Sign} sign The sign for the Infinity.
1096
+ * @param {NodeParts} parts Additional properties for the node.
1097
+ * @returns {NaNNode} The NaN node.
1098
+ */
1099
+ nan(sign = "", parts = {}) {
1100
+ return {
1101
+ type: "NaN",
1102
+ sign,
1103
+ loc: parts.loc,
1104
+ ...parts
1105
+ };
1106
+ },
1107
+ /**
1108
+ * Creates an Infinity node.
1109
+ * @param {Sign} sign The sign for the Infinity.
1110
+ * @param {NodeParts} parts Additional properties for the node.
1111
+ * @returns {InfinityNode} The Infinity node.
1112
+ */
1113
+ infinity(sign = "", parts = {}) {
1114
+ return {
1115
+ type: "Infinity",
1116
+ sign,
1117
+ loc: parts.loc,
1118
+ ...parts
1119
+ };
1120
+ }
1121
+ };
1122
+ /**
1123
+ * @fileoverview JSON parser
1124
+ * @author Nicholas C. Zakas
1125
+ */
1126
+ /** @typedef {import("./typedefs.js").Node} Node */
1127
+ /** @typedef {import("./typedefs.js").Mode} Mode */
1128
+ /** @typedef {import("./typedefs.js").ParseOptions} ParseOptions */
1129
+ /** @type {ParseOptions} */
1130
+ const DEFAULT_OPTIONS = {
1131
+ mode: "json",
1132
+ ranges: false,
1133
+ tokens: false,
1134
+ allowTrailingCommas: false
1135
+ };
1136
+ const UNICODE_SEQUENCE = /\\u[\da-fA-F]{4}/gu;
1137
+ /**
1138
+ * Normalizes a JSON5 identifier by converting Unicode escape sequences into
1139
+ * their corresponding characters.
1140
+ * @param {string} identifier The identifier to normalize.
1141
+ * @returns {string} The normalized identifier.
1142
+ */
1143
+ function normalizeIdentifier(identifier) {
1144
+ return identifier.replace(UNICODE_SEQUENCE, (unicodeEscape) => {
1145
+ return String.fromCharCode(parseInt(unicodeEscape.slice(2), 16));
1146
+ });
1147
+ }
1148
+ /**
1149
+ * Calculates the location at the end of the given text.
1150
+ * @param {string} text The text to calculate the end location for.
1151
+ * @returns {Location} The location at the end of the text.
1152
+ */
1153
+ function getEndLocation(text) {
1154
+ let line = 1;
1155
+ let column = 1;
1156
+ for (let i = 0; i < text.length; i++) {
1157
+ const char = text[i];
1158
+ if (char === "\n") {
1159
+ line++;
1160
+ column = 1;
1161
+ } else if (char === "\r") {
1162
+ if (text[i + 1] === "\n") i++;
1163
+ line++;
1164
+ column = 1;
1165
+ } else column++;
1166
+ }
1167
+ return {
1168
+ line,
1169
+ column,
1170
+ offset: text.length
1171
+ };
1172
+ }
1173
+ /**
1174
+ * Converts a JSON-encoded string into a JavaScript string, interpreting each
1175
+ * escape sequence.
1176
+ * @param {string} value The text for the token.
1177
+ * @param {Token} token The string token to convert into a JavaScript string.
1178
+ * @param {boolean} json5 `true` if parsing JSON5, `false` otherwise.
1179
+ * @returns {string} A JavaScript string.
1180
+ */
1181
+ function getStringValue(value, token, json5 = false) {
1182
+ let result = "";
1183
+ let escapeIndex = value.indexOf("\\");
1184
+ let lastIndex = 0;
1185
+ while (escapeIndex >= 0) {
1186
+ result += value.slice(lastIndex, escapeIndex);
1187
+ const escapeChar = value.charAt(escapeIndex + 1);
1188
+ const escapeCharCode = escapeChar.charCodeAt(0);
1189
+ if (json5 && json5EscapeToChar.has(escapeCharCode)) {
1190
+ result += json5EscapeToChar.get(escapeCharCode);
1191
+ lastIndex = escapeIndex + 2;
1192
+ } else if (escapeToChar.has(escapeCharCode)) {
1193
+ result += escapeToChar.get(escapeCharCode);
1194
+ lastIndex = escapeIndex + 2;
1195
+ } else if (escapeChar === "u") {
1196
+ const hexCode = value.slice(escapeIndex + 2, escapeIndex + 6);
1197
+ if (hexCode.length < 4 || /[^0-9a-f]/i.test(hexCode)) throw new ErrorWithLocation(`Invalid unicode escape \\u${hexCode}.`, {
1198
+ line: token.loc.start.line,
1199
+ column: token.loc.start.column + escapeIndex,
1200
+ offset: token.loc.start.offset + escapeIndex
1201
+ });
1202
+ result += String.fromCharCode(parseInt(hexCode, 16));
1203
+ lastIndex = escapeIndex + 6;
1204
+ } else if (json5 && escapeChar === "x") {
1205
+ const hexCode = value.slice(escapeIndex + 2, escapeIndex + 4);
1206
+ if (hexCode.length < 2 || /[^0-9a-f]/i.test(hexCode)) throw new ErrorWithLocation(`Invalid hex escape \\x${hexCode}.`, {
1207
+ line: token.loc.start.line,
1208
+ column: token.loc.start.column + escapeIndex,
1209
+ offset: token.loc.start.offset + escapeIndex
1210
+ });
1211
+ result += String.fromCharCode(parseInt(hexCode, 16));
1212
+ lastIndex = escapeIndex + 4;
1213
+ } else if (json5 && json5LineTerminators.has(escapeCharCode)) {
1214
+ lastIndex = escapeIndex + 2;
1215
+ if (escapeChar === "\r" && value.charAt(lastIndex) === "\n") lastIndex++;
1216
+ } else if (json5) {
1217
+ result += escapeChar;
1218
+ lastIndex = escapeIndex + 2;
1219
+ } else throw new ErrorWithLocation(`Invalid escape \\${escapeChar}.`, {
1220
+ line: token.loc.start.line,
1221
+ column: token.loc.start.column + escapeIndex,
1222
+ offset: token.loc.start.offset + escapeIndex
1223
+ });
1224
+ escapeIndex = value.indexOf("\\", lastIndex);
1225
+ }
1226
+ result += value.slice(lastIndex);
1227
+ return result;
1228
+ }
1229
+ /**
1230
+ * Gets the JavaScript value represented by a JSON token.
1231
+ * @param {string} value The text value of the token.
1232
+ * @param {Token} token The JSON token to get a value for.
1233
+ * @param {boolean} json5 `true` if parsing JSON5, `false` otherwise.
1234
+ * @returns {string|boolean|number} A number, string, or boolean.
1235
+ * @throws {TypeError} If an unknown token type is found.
1236
+ */
1237
+ function getLiteralValue(value, token, json5 = false) {
1238
+ switch (token.type) {
1239
+ case "Boolean": return value === "true";
1240
+ case "Number":
1241
+ if (json5) {
1242
+ if (value.charCodeAt(0) === 45) return -Number(value.slice(1));
1243
+ if (value.charCodeAt(0) === 43) return Number(value.slice(1));
1244
+ }
1245
+ return Number(value);
1246
+ case "String": return getStringValue(value.slice(1, -1), token, json5);
1247
+ default: throw new TypeError(`Unknown token type "${token.type}.`);
1248
+ }
1249
+ }
1250
+ /**
1251
+ *
1252
+ * @param {string} text The text to parse.
1253
+ * @param {ParseOptions} [options] The options object.
1254
+ * @returns {DocumentNode} The AST representing the parsed JSON.
1255
+ * @throws {Error} When there is a parsing error.
1256
+ */
1257
+ function parse$1(text, options) {
1258
+ options = Object.freeze({
1259
+ ...DEFAULT_OPTIONS,
1260
+ ...options
1261
+ });
1262
+ const tokens = [];
1263
+ const tokenizer = new Tokenizer(text, {
1264
+ mode: options.mode,
1265
+ ranges: options.ranges
1266
+ });
1267
+ const json5 = options.mode === "json5";
1268
+ const allowTrailingCommas = options.allowTrailingCommas || json5;
1269
+ /**
1270
+ * Returns the next token knowing there are no comments.
1271
+ * @returns {number} The next token type or 0 if no next token.
1272
+ */
1273
+ function nextNoComments() {
1274
+ const nextType = tokenizer.next();
1275
+ if (nextType && options.tokens) tokens.push(tokenizer.token);
1276
+ return nextType;
1277
+ }
1278
+ /**
1279
+ * Returns the next token knowing there are comments to skip.
1280
+ * @returns {number} The next token type or 0 if no next token.
1281
+ */
1282
+ function nextSkipComments() {
1283
+ const nextType = tokenizer.next();
1284
+ if (nextType && options.tokens) tokens.push(tokenizer.token);
1285
+ if (nextType >= tt.LineComment) return nextSkipComments();
1286
+ return nextType;
1287
+ }
1288
+ const next = options.mode === "json" ? nextNoComments : nextSkipComments;
1289
+ /**
1290
+ * Asserts a token has the given type.
1291
+ * @param {number} token The token to check.
1292
+ * @param {number} type The token type.
1293
+ * @throws {UnexpectedToken} If the token type isn't expected.
1294
+ * @returns {void}
1295
+ */
1296
+ function assertTokenType(token, type) {
1297
+ if (token !== type) throw new UnexpectedToken(tokenizer.token);
1298
+ }
1299
+ /**
1300
+ * Asserts a token has one of the given types.
1301
+ * @param {number} token The token to check.
1302
+ * @param {number[]} types The token types.
1303
+ * @returns {void}
1304
+ * @throws {UnexpectedToken} If the token type isn't expected.
1305
+ */
1306
+ function assertTokenTypes(token, types) {
1307
+ if (!types.includes(token)) throw new UnexpectedToken(tokenizer.token);
1308
+ }
1309
+ /**
1310
+ * Creates a range only if ranges are specified.
1311
+ * @param {Location} start The start offset for the range.
1312
+ * @param {Location} end The end offset for the range.
1313
+ * @returns {{range:[number,number]}|undefined} An object with a
1314
+ */
1315
+ function createRange(start, end) {
1316
+ return options.ranges ? { range: [start.offset, end.offset] } : void 0;
1317
+ }
1318
+ /**
1319
+ * Creates a node for a string, boolean, or number.
1320
+ * @param {number} tokenType The token representing the literal.
1321
+ * @returns {StringNode|NumberNode|BooleanNode} The node representing
1322
+ * the value.
1323
+ */
1324
+ function createLiteralNode(tokenType) {
1325
+ const token = tokenizer.token;
1326
+ const range = createRange(token.loc.start, token.loc.end);
1327
+ const value = getLiteralValue(text.slice(token.loc.start.offset, token.loc.end.offset), token, json5);
1328
+ const parts = {
1329
+ loc: {
1330
+ start: { ...token.loc.start },
1331
+ end: { ...token.loc.end }
1332
+ },
1333
+ ...range
1334
+ };
1335
+ switch (tokenType) {
1336
+ case tt.String: return types.string(value, parts);
1337
+ case tt.Number: return types.number(value, parts);
1338
+ case tt.Boolean: return types.boolean(value, parts);
1339
+ default: throw new TypeError(`Unknown token type ${token.type}.`);
1340
+ }
1341
+ }
1342
+ /**
1343
+ * Creates a node for a JSON5 identifier.
1344
+ * @param {Token} token The token representing the identifer.
1345
+ * @returns {NaNNode|InfinityNode|IdentifierNode} The node representing
1346
+ * the value.
1347
+ */
1348
+ function createJSON5IdentifierNode(token) {
1349
+ const range = createRange(token.loc.start, token.loc.end);
1350
+ const identifier = text.slice(token.loc.start.offset, token.loc.end.offset);
1351
+ const parts = {
1352
+ loc: {
1353
+ start: { ...token.loc.start },
1354
+ end: { ...token.loc.end }
1355
+ },
1356
+ ...range
1357
+ };
1358
+ if (token.type !== "Identifier") {
1359
+ let sign = "";
1360
+ if (identifier[0] === "+" || identifier[0] === "-") sign = identifier[0];
1361
+ return types[identifier.includes("NaN") ? "nan" : "infinity"](sign, parts);
1362
+ }
1363
+ return types.identifier(normalizeIdentifier(identifier), parts);
1364
+ }
1365
+ /**
1366
+ * Creates a node for a null.
1367
+ * @param {Token} token The token representing null.
1368
+ * @returns {NullNode} The node representing null.
1369
+ */
1370
+ function createNullNode(token) {
1371
+ const range = createRange(token.loc.start, token.loc.end);
1372
+ return types.null({
1373
+ loc: {
1374
+ start: { ...token.loc.start },
1375
+ end: { ...token.loc.end }
1376
+ },
1377
+ ...range
1378
+ });
1379
+ }
1380
+ /**
1381
+ * Parses a property in an object.
1382
+ * @param {number} tokenType The token representing the property.
1383
+ * @returns {MemberNode} The node representing the property.
1384
+ * @throws {UnexpectedToken} When an unexpected token is found.
1385
+ * @throws {UnexpectedEOF} When the end of the file is reached.
1386
+ */
1387
+ function parseProperty(tokenType) {
1388
+ if (json5) assertTokenTypes(tokenType, [
1389
+ tt.String,
1390
+ tt.Identifier,
1391
+ tt.Number
1392
+ ]);
1393
+ else assertTokenType(tokenType, tt.String);
1394
+ const token = tokenizer.token;
1395
+ if (json5 && tokenType === tt.Number && /[+\-0-9]/.test(text[token.loc.start.offset])) throw new UnexpectedToken(token);
1396
+ let key = tokenType === tt.String ? createLiteralNode(tokenType) : createJSON5IdentifierNode(token);
1397
+ if (json5 && (key.type === "NaN" || key.type === "Infinity")) {
1398
+ if (key.sign !== "") throw new UnexpectedToken(tokenizer.token);
1399
+ key = types.identifier(key.type, {
1400
+ loc: key.loc,
1401
+ ...createRange(key.loc.start, key.loc.end)
1402
+ });
1403
+ }
1404
+ tokenType = next();
1405
+ assertTokenType(tokenType, tt.Colon);
1406
+ const value = parseValue();
1407
+ const range = createRange(key.loc.start, value.loc.end);
1408
+ return types.member(key, value, {
1409
+ loc: {
1410
+ start: { ...key.loc.start },
1411
+ end: { ...value.loc.end }
1412
+ },
1413
+ ...range
1414
+ });
1415
+ }
1416
+ /**
1417
+ * Parses an object literal.
1418
+ * @param {number} firstTokenType The first token type in the object.
1419
+ * @returns {ObjectNode} The object node.
1420
+ * @throws {UnexpectedEOF} When the end of the file is reached.
1421
+ * @throws {UnexpectedToken} When an unexpected token is found.
1422
+ */
1423
+ function parseObject(firstTokenType) {
1424
+ assertTokenType(firstTokenType, tt.LBrace);
1425
+ const firstToken = tokenizer.token;
1426
+ const members = [];
1427
+ let tokenType = next();
1428
+ if (tokenType !== tt.RBrace) do {
1429
+ members.push(parseProperty(tokenType));
1430
+ tokenType = next();
1431
+ if (!tokenType) throw new UnexpectedEOF(members[members.length - 1].loc.end);
1432
+ if (tokenType === tt.Comma) {
1433
+ tokenType = next();
1434
+ if (allowTrailingCommas && tokenType === tt.RBrace) break;
1435
+ } else break;
1436
+ } while (tokenType);
1437
+ assertTokenType(tokenType, tt.RBrace);
1438
+ const lastToken = tokenizer.token;
1439
+ const range = createRange(firstToken.loc.start, lastToken.loc.end);
1440
+ return types.object(members, {
1441
+ loc: {
1442
+ start: { ...firstToken.loc.start },
1443
+ end: { ...lastToken.loc.end }
1444
+ },
1445
+ ...range
1446
+ });
1447
+ }
1448
+ /**
1449
+ * Parses an array literal.
1450
+ * @param {number} firstTokenType The first token in the array.
1451
+ * @returns {ArrayNode} The array node.
1452
+ * @throws {UnexpectedToken} When an unexpected token is found.
1453
+ * @throws {UnexpectedEOF} When the end of the file is reached.
1454
+ */
1455
+ function parseArray(firstTokenType) {
1456
+ assertTokenType(firstTokenType, tt.LBracket);
1457
+ const firstToken = tokenizer.token;
1458
+ const elements = [];
1459
+ let tokenType = next();
1460
+ if (tokenType !== tt.RBracket) do {
1461
+ const value = parseValue(tokenType);
1462
+ elements.push(types.element(value, { loc: value.loc }));
1463
+ tokenType = next();
1464
+ if (tokenType === tt.Comma) {
1465
+ tokenType = next();
1466
+ if (allowTrailingCommas && tokenType === tt.RBracket) break;
1467
+ } else break;
1468
+ } while (tokenType);
1469
+ assertTokenType(tokenType, tt.RBracket);
1470
+ const lastToken = tokenizer.token;
1471
+ const range = createRange(firstToken.loc.start, lastToken.loc.end);
1472
+ return types.array(elements, {
1473
+ loc: {
1474
+ start: { ...firstToken.loc.start },
1475
+ end: { ...lastToken.loc.end }
1476
+ },
1477
+ ...range
1478
+ });
1479
+ }
1480
+ /**
1481
+ * Parses a JSON value.
1482
+ * @param {number} [tokenType] The token type to parse.
1483
+ * @returns {ValueNode|IdentifierNode} The node representing the value.
1484
+ */
1485
+ function parseValue(tokenType) {
1486
+ tokenType = tokenType ?? next();
1487
+ const token = tokenizer.token;
1488
+ switch (tokenType) {
1489
+ case tt.String:
1490
+ case tt.Boolean: return createLiteralNode(tokenType);
1491
+ case tt.Number:
1492
+ if (json5) {
1493
+ let tokenText = text.slice(token.loc.start.offset, token.loc.end.offset);
1494
+ if (tokenText[0] === "+" || tokenText[0] === "-") tokenText = tokenText.slice(1);
1495
+ if (tokenText === "NaN" || tokenText === "Infinity") return createJSON5IdentifierNode(token);
1496
+ }
1497
+ return createLiteralNode(tokenType);
1498
+ case tt.Null: return createNullNode(token);
1499
+ case tt.LBrace: return parseObject(tokenType);
1500
+ case tt.LBracket: return parseArray(tokenType);
1501
+ default: throw new UnexpectedToken(token);
1502
+ }
1503
+ }
1504
+ const docBody = parseValue();
1505
+ if (next()) throw new UnexpectedToken(tokenizer.token);
1506
+ const docParts = { loc: {
1507
+ start: {
1508
+ line: 1,
1509
+ column: 1,
1510
+ offset: 0
1511
+ },
1512
+ end: { ...getEndLocation(text) }
1513
+ } };
1514
+ if (options.tokens) docParts.tokens = tokens;
1515
+ if (options.ranges) docParts.range = [docParts.loc.start.offset, docParts.loc.end.offset];
1516
+ return types.document(docBody, docParts);
1517
+ }
1518
+ //#endregion
1519
+ //#region src/conditions.ts
1520
+ const RE_IFDEF = /^\/\/ #ifdef (\S.*)$|^\/\* #ifdef (\S.*?) \*\/$/;
1521
+ const RE_IFNDEF = /^\/\/ #ifndef (\S.*)$|^\/\* #ifndef (\S.*?) \*\/$/;
1522
+ const RE_ENDIF = /^\/\/ #endif$|^\/\* #endif \*\/$/;
1523
+ function parseConditions(tokens) {
1524
+ const ranges = [];
1525
+ const stack = [];
1526
+ for (const token of tokens) {
1527
+ const text = token.text;
1528
+ const ifdef = text.match(RE_IFDEF);
1529
+ const ifndef = text.match(RE_IFNDEF);
1530
+ const endif = text.match(RE_ENDIF);
1531
+ if (ifdef) stack.push({
1532
+ condition: {
1533
+ kind: "ifdef",
1534
+ platform: (ifdef[1] ?? ifdef[2]).trim()
1535
+ },
1536
+ start: token.range[1]
1537
+ });
1538
+ else if (ifndef) stack.push({
1539
+ condition: {
1540
+ kind: "ifndef",
1541
+ platform: (ifndef[1] ?? ifndef[2]).trim()
1542
+ },
1543
+ start: token.range[1]
1544
+ });
1545
+ else if (endif) {
1546
+ const top = stack.pop();
1547
+ if (!top) throw new Error("多余的 #endif");
1548
+ ranges.push({
1549
+ start: top.start,
1550
+ end: token.range[0],
1551
+ condition: top.condition
1552
+ });
1553
+ }
1554
+ }
1555
+ if (stack.length > 0) throw new Error(`未闭合的 #${stack[stack.length - 1].condition.kind}`);
1556
+ return ranges;
1557
+ }
1558
+ function findRange(ranges, offset) {
1559
+ let match;
1560
+ for (const r of ranges) if (offset >= r.start && offset <= r.end) {
1561
+ if (!match || r.start >= match.start && r.end <= match.end) match = r;
1562
+ }
1563
+ return match;
1564
+ }
1565
+ function matchPlatform(condition, platform) {
1566
+ const hit = condition.platform.split("||").map((p) => p.trim()).includes(platform);
1567
+ return condition.kind === "ifdef" ? hit : !hit;
1568
+ }
1569
+ //#endregion
1570
+ //#region src/tree.ts
1571
+ function buildTree(node, ranges, inheritedRange) {
1572
+ const n = node;
1573
+ switch (n.type) {
1574
+ case "String": return {
1575
+ type: "value",
1576
+ value: n.value
1577
+ };
1578
+ case "Number": return {
1579
+ type: "value",
1580
+ value: n.value
1581
+ };
1582
+ case "Boolean": return {
1583
+ type: "value",
1584
+ value: n.value
1585
+ };
1586
+ case "Null": return {
1587
+ type: "value",
1588
+ value: null
1589
+ };
1590
+ case "Object": return {
1591
+ type: "object",
1592
+ members: n.members.map((m) => {
1593
+ const r = findRange(ranges, m.range[0]);
1594
+ const condition = r && r !== inheritedRange ? r.condition : void 0;
1595
+ return {
1596
+ key: m.name.value,
1597
+ value: buildTree(m.value, ranges, r ?? inheritedRange),
1598
+ ...condition ? { condition } : {}
1599
+ };
1600
+ })
1601
+ };
1602
+ case "Array": return {
1603
+ type: "array",
1604
+ elements: n.elements.map((el) => {
1605
+ const r = findRange(ranges, el.value.range[0]);
1606
+ const condition = r && r !== inheritedRange ? r.condition : void 0;
1607
+ return {
1608
+ value: buildTree(el.value, ranges, r ?? inheritedRange),
1609
+ ...condition ? { condition } : {}
1610
+ };
1611
+ })
1612
+ };
1613
+ default: throw new Error(`未知的节点类型: ${node.type}`);
1614
+ }
1615
+ }
1616
+ function evaluateTree(node, platform) {
1617
+ switch (node.type) {
1618
+ case "value": return node.value;
1619
+ case "object": {
1620
+ const result = {};
1621
+ for (const m of node.members) {
1622
+ if (m.condition && !matchPlatform(m.condition, platform)) continue;
1623
+ result[m.key] = evaluateTree(m.value, platform);
1624
+ }
1625
+ return result;
1626
+ }
1627
+ case "array": return node.elements.filter((el) => !el.condition || matchPlatform(el.condition, platform)).map((el) => evaluateTree(el.value, platform));
1628
+ }
1629
+ }
1630
+ function stringifyTree(node, indent = 2) {
1631
+ return stringifyNode(node, 1, indent);
1632
+ }
1633
+ function stringifyNode(node, depth, indent) {
1634
+ const pad = " ".repeat(depth * indent);
1635
+ const padEnd = " ".repeat((depth - 1) * indent);
1636
+ switch (node.type) {
1637
+ case "value": return JSON.stringify(node.value);
1638
+ case "object":
1639
+ if (node.members.length === 0) return "{}";
1640
+ return `{\n${node.members.map((m, i) => {
1641
+ const valueStr = stringifyNode(m.value, depth + 1, indent);
1642
+ const comma = i < node.members.length - 1 ? "," : "";
1643
+ const line = `${pad}"${m.key}": ${valueStr}${comma}`;
1644
+ return m.condition ? wrapCondition(line, m.condition, pad) : line;
1645
+ }).join("\n")}\n${padEnd}}`;
1646
+ case "array":
1647
+ if (node.elements.length === 0) return "[]";
1648
+ return `[\n${node.elements.map((el, i) => {
1649
+ const line = `${pad}${stringifyNode(el.value, depth + 1, indent)}${i < node.elements.length - 1 ? "," : ""}`;
1650
+ return el.condition ? wrapCondition(line, el.condition, pad) : line;
1651
+ }).join("\n")}\n${padEnd}]`;
1652
+ }
1653
+ }
1654
+ function wrapCondition(line, condition, pad) {
1655
+ return `${pad}// #${condition.kind} ${condition.platform}\n${line}\n${pad}// #endif`;
1656
+ }
1657
+ //#endregion
1658
+ //#region src/index.ts
1659
+ var JsonuDocument = class {
1660
+ root;
1661
+ constructor(root) {
1662
+ this.root = root;
1663
+ }
1664
+ evaluate(platform) {
1665
+ return evaluateTree(this.root, platform);
1666
+ }
1667
+ stringify(indent = 2) {
1668
+ return stringifyTree(this.root, indent);
1669
+ }
1670
+ set(platform, data, path) {
1671
+ const container = this.navigate(path);
1672
+ this.removeConditional(container, platform);
1673
+ this.addConditional(container, data, platform);
1674
+ return this;
1675
+ }
1676
+ merge(platform, data, path) {
1677
+ const container = this.navigate(path);
1678
+ this.addConditional(container, data, platform);
1679
+ return this;
1680
+ }
1681
+ delete(platform, path) {
1682
+ const container = this.navigate(path);
1683
+ this.removeConditional(container, platform);
1684
+ return this;
1685
+ }
1686
+ navigate(path) {
1687
+ const segs = normalizePath(path);
1688
+ let current = this.root;
1689
+ for (const seg of segs) if (typeof seg === "number") {
1690
+ if (current.type !== "array") throw new Error(`路径期望数组,但遇到 ${current.type}`);
1691
+ current = current.elements[seg].value;
1692
+ } else {
1693
+ if (current.type !== "object") throw new Error(`路径期望对象,但遇到 ${current.type}`);
1694
+ const member = current.members.find((m) => m.key === seg);
1695
+ if (!member) throw new Error(`找不到键: ${seg}`);
1696
+ current = member.value;
1697
+ }
1698
+ return current;
1699
+ }
1700
+ removeConditional(container, platform) {
1701
+ if (container.type === "object") container.members = container.members.filter((m) => !(m.condition && m.condition.platform === platform));
1702
+ else if (container.type === "array") container.elements = container.elements.filter((el) => !(el.condition && el.condition.platform === platform));
1703
+ }
1704
+ addConditional(container, data, platform) {
1705
+ const condition = {
1706
+ kind: "ifdef",
1707
+ platform
1708
+ };
1709
+ const node = toTreeNode(data);
1710
+ if (container.type === "object") {
1711
+ if (node.type !== "object") throw new Error("对象容器需要对象数据");
1712
+ for (const m of node.members) container.members.push({
1713
+ ...m,
1714
+ condition
1715
+ });
1716
+ } else if (container.type === "array") {
1717
+ if (node.type !== "array") throw new Error("数组容器需要数组数据");
1718
+ for (const el of node.elements) container.elements.push({
1719
+ ...el,
1720
+ condition
1721
+ });
1722
+ } else throw new Error(`无法在 ${container.type} 上添加条件数据`);
1723
+ }
1724
+ };
1725
+ function normalizePath(path) {
1726
+ if (!path) return [];
1727
+ if (Array.isArray(path)) return path;
1728
+ return path.split(".").map((seg) => /^\d+$/.test(seg) ? Number(seg) : seg);
1729
+ }
1730
+ function toTreeNode(value) {
1731
+ if (value === null) return {
1732
+ type: "value",
1733
+ value: null
1734
+ };
1735
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return {
1736
+ type: "value",
1737
+ value
1738
+ };
1739
+ if (Array.isArray(value)) return {
1740
+ type: "array",
1741
+ elements: value.map((v) => ({ value: toTreeNode(v) }))
1742
+ };
1743
+ if (typeof value === "object") return {
1744
+ type: "object",
1745
+ members: Object.entries(value).map(([k, v]) => ({
1746
+ key: k,
1747
+ value: toTreeNode(v)
1748
+ }))
1749
+ };
1750
+ throw new Error(`不支持的数据类型: ${typeof value}`);
1751
+ }
1752
+ function parse(jsonu) {
1753
+ const ast = parse$1(jsonu, {
1754
+ mode: "jsonc",
1755
+ ranges: true,
1756
+ tokens: true
1757
+ });
1758
+ const ranges = parseConditions((ast.tokens ?? []).filter((t) => t.type === "LineComment" || t.type === "BlockComment").map((t) => ({
1759
+ range: t.range,
1760
+ text: jsonu.slice(...t.range)
1761
+ })));
1762
+ return new JsonuDocument(buildTree(ast.body, ranges));
1763
+ }
1764
+ //#endregion
1765
+ export { JsonuDocument, evaluateTree, parse, stringifyTree };