smol-toml 1.3.4 → 1.4.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/README.md +43 -3
- package/dist/extract.d.ts +3 -2
- package/dist/extract.js +4 -4
- package/dist/index.cjs +46 -49
- package/dist/index.d.ts +4 -1
- package/dist/parse.d.ts +10 -4
- package/dist/parse.js +2 -3
- package/dist/primitive.d.ts +2 -1
- package/dist/primitive.js +27 -21
- package/dist/stringify.d.ts +2 -1
- package/dist/stringify.js +20 -19
- package/dist/struct.d.ts +4 -3
- package/dist/struct.js +17 -25
- package/dist/util.d.ts +9 -3
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -16,6 +16,9 @@ parser didn't feel too out of place.
|
|
|
16
16
|
|
|
17
17
|
*[insert xkcd 927]*
|
|
18
18
|
|
|
19
|
+
Nowadays, smol-toml is the most downloaded TOML parser on npm thanks to its quality. From frameworks to tooling, it
|
|
20
|
+
has been battle-tested and is actively used in production systems.
|
|
21
|
+
|
|
19
22
|
smol-toml passes most of the tests from the [`toml-test` suite](https://github.com/toml-lang/toml-test); use the
|
|
20
23
|
`run-toml-test.bash` script to run the tests. Due to the nature of JavaScript and the limits of the language,
|
|
21
24
|
it doesn't pass certain tests, namely:
|
|
@@ -24,7 +27,9 @@ it doesn't pass certain tests, namely:
|
|
|
24
27
|
- Certain invalid dates are not rejected
|
|
25
28
|
- For instance, `2023-02-30` would be accepted and parsed as `2023-03-02`. While additional checks could be performed
|
|
26
29
|
to reject these, they've not been added for performance reasons.
|
|
27
|
-
|
|
30
|
+
|
|
31
|
+
Please also note that by default, the behavior regarding integers doesn't preserve type information, nor does it allow
|
|
32
|
+
deserializing integers larger than 53 bits. See [Integers](#integers).
|
|
28
33
|
|
|
29
34
|
You can see a list of all tests smol-toml fails (and the reason why it fails these) in the list of skipped tests in
|
|
30
35
|
`run-toml-test.bash`. Note that some failures are *not* specification violations per-se. For instance, the TOML spec
|
|
@@ -59,11 +64,42 @@ A few notes on the `stringify` function:
|
|
|
59
64
|
- `undefined` and `null` values on objects are ignored (does not produce a key/value).
|
|
60
65
|
- `undefined` and `null` values in arrays are **rejected**.
|
|
61
66
|
- Functions, classes and symbols are **rejected**.
|
|
62
|
-
- floats will be serialized as integers if they don't have a decimal part.
|
|
67
|
+
- By default, floats will be serialized as integers if they don't have a decimal part. See [Integers](#integers)
|
|
63
68
|
- `stringify(parse('a = 1.0')) === 'a = 1'`
|
|
64
69
|
- JS `Date` will be serialized as Offset Date Time
|
|
65
70
|
- Use the [`TomlDate` object](#dates) for representing other types.
|
|
66
71
|
|
|
72
|
+
### Integers
|
|
73
|
+
When parsing, both integers and floats are read as plain JavaScript numbers, which essentially are floats. This means
|
|
74
|
+
loss of type information, and makes it impossible to safely represent integers beyond 53 bits.
|
|
75
|
+
|
|
76
|
+
When serializing, numbers without a decimal part are serialized as integers. This allows in most cases to preserve
|
|
77
|
+
whether a number is an integer or not, but fails to preserve type information for numbers like `1.0`.
|
|
78
|
+
|
|
79
|
+
#### Enabling BigInt support and type preservation
|
|
80
|
+
To parse integers beyond 53 bits, it's possible to tell the parser to return all integers as BigInt. This will
|
|
81
|
+
therefore preserve the type information at the cost of using a slightly more expensive container.
|
|
82
|
+
|
|
83
|
+
```js
|
|
84
|
+
import { parse } from 'smol-toml'
|
|
85
|
+
|
|
86
|
+
const doc = '...'
|
|
87
|
+
const parsed = parse(doc, { integersAsBigInt: true })
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
If you want to keep numbers for integers that can safely be represented as a JavaScript number, you can pass
|
|
91
|
+
`"asNeeded"` instead.
|
|
92
|
+
|
|
93
|
+
To get end-to-end type preservation, you can tell the serializer to always treat numbers as floating point numbers.
|
|
94
|
+
Then, only BigInts will be serialized as integers and numbers without a decimal part will still be serialized as float.
|
|
95
|
+
|
|
96
|
+
```js
|
|
97
|
+
import { stringify } from 'smol-toml'
|
|
98
|
+
|
|
99
|
+
const obj = { ... }
|
|
100
|
+
const toml = stringify(obj, { numbersAsFloat: true })
|
|
101
|
+
```
|
|
102
|
+
|
|
67
103
|
### Dates
|
|
68
104
|
`smol-toml` uses an extended `Date` object to represent all types of TOML Dates. In the future, `smol-toml` will use
|
|
69
105
|
objects from the Temporal proposal, but for now we're stuck with the legacy Date object.
|
|
@@ -107,6 +143,10 @@ const localTime = TomlDate.wrapAsLocalTime(jsDate)
|
|
|
107
143
|
```
|
|
108
144
|
|
|
109
145
|
## Performance
|
|
146
|
+
> [!NOTE]
|
|
147
|
+
> These benchmarks are starting to get a bit old. They will be updated in the (hopefully near) future to better
|
|
148
|
+
> reflect numbers of the latest version of smol-toml on the latest version of Node.js.
|
|
149
|
+
|
|
110
150
|
A note on these performance numbers: in some highly synthetic tests, other parsers such as `fast-toml` greatly
|
|
111
151
|
outperform other parsers, mostly due to their lack of compliance with the spec. For example, to parse a string,
|
|
112
152
|
`fast-toml` skips the entire string while `smol-toml` does validate the string, costing a fair share of performance.
|
|
@@ -187,7 +227,7 @@ I initially tried to benchmark `toml-nodejs`, but the 0.3.0 package is broken.
|
|
|
187
227
|
I initially reported this to the library author, but the author decided to
|
|
188
228
|
- a) advise to use a custom loader (via *experimental* flag) to circumvent the invalid imports.
|
|
189
229
|
- Said flag, `--experimental-specifier-resolution`, has been removed in Node v20.
|
|
190
|
-
- b) [delete the issue](https://github.com/huan231/toml-nodejs/issues/12) when pointed out links to the
|
|
230
|
+
- b) [delete the issue](https://github.com/huan231/toml-nodejs/issues/12) when pointed out links to the Node.js
|
|
191
231
|
documentation about the flag removal and standard resolution algorithm.
|
|
192
232
|
|
|
193
233
|
For the reference anyway, `toml-nodejs` (with proper imports) is ~8x slower on both parse benchmark with:
|
package/dist/extract.d.ts
CHANGED
|
@@ -25,5 +25,6 @@
|
|
|
25
25
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
26
26
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
27
27
|
*/
|
|
28
|
-
import { type
|
|
29
|
-
|
|
28
|
+
import { type IntegersAsBigInt } from './primitive.js';
|
|
29
|
+
import { type TomlValue } from './util.js';
|
|
30
|
+
export declare function extractValue(str: string, ptr: number, end: string | undefined, depth: number, integersAsBigInt: IntegersAsBigInt): [TomlValue, number];
|
package/dist/extract.js
CHANGED
|
@@ -50,7 +50,7 @@ function sliceAndTrimEndOf(str, startPtr, endPtr, allowNewLines) {
|
|
|
50
50
|
}
|
|
51
51
|
return [trimmed, commentIdx];
|
|
52
52
|
}
|
|
53
|
-
export function extractValue(str, ptr, end, depth
|
|
53
|
+
export function extractValue(str, ptr, end, depth, integersAsBigInt) {
|
|
54
54
|
if (depth === 0) {
|
|
55
55
|
throw new TomlError('document contains excessively nested structures. aborting.', {
|
|
56
56
|
toml: str,
|
|
@@ -60,8 +60,8 @@ export function extractValue(str, ptr, end, depth = -1) {
|
|
|
60
60
|
let c = str[ptr];
|
|
61
61
|
if (c === '[' || c === '{') {
|
|
62
62
|
let [value, endPtr] = c === '['
|
|
63
|
-
? parseArray(str, ptr, depth)
|
|
64
|
-
: parseInlineTable(str, ptr, depth);
|
|
63
|
+
? parseArray(str, ptr, depth, integersAsBigInt)
|
|
64
|
+
: parseInlineTable(str, ptr, depth, integersAsBigInt);
|
|
65
65
|
let newPtr = end ? skipUntil(str, endPtr, ',', end) : endPtr;
|
|
66
66
|
if (endPtr - newPtr && end === '}') {
|
|
67
67
|
let nextNewLine = indexOfNewline(str, endPtr, newPtr);
|
|
@@ -103,7 +103,7 @@ export function extractValue(str, ptr, end, depth = -1) {
|
|
|
103
103
|
endPtr += +(str[endPtr] === ',');
|
|
104
104
|
}
|
|
105
105
|
return [
|
|
106
|
-
parseValue(slice[0], str, ptr),
|
|
106
|
+
parseValue(slice[0], str, ptr, integersAsBigInt),
|
|
107
107
|
endPtr,
|
|
108
108
|
];
|
|
109
109
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -315,7 +315,7 @@ function parseString(str, ptr = 0, endPtr = str.length) {
|
|
|
315
315
|
}
|
|
316
316
|
return parsed + str.slice(sliceStart, endPtr - 1);
|
|
317
317
|
}
|
|
318
|
-
function parseValue(value, toml, ptr) {
|
|
318
|
+
function parseValue(value, toml, ptr, integersAsBigInt) {
|
|
319
319
|
if (value === "true")
|
|
320
320
|
return true;
|
|
321
321
|
if (value === "false")
|
|
@@ -327,31 +327,36 @@ function parseValue(value, toml, ptr) {
|
|
|
327
327
|
if (value === "nan" || value === "+nan" || value === "-nan")
|
|
328
328
|
return NaN;
|
|
329
329
|
if (value === "-0")
|
|
330
|
-
return 0;
|
|
331
|
-
let isInt;
|
|
332
|
-
if (
|
|
330
|
+
return integersAsBigInt ? 0n : 0;
|
|
331
|
+
let isInt = INT_REGEX.test(value);
|
|
332
|
+
if (isInt || FLOAT_REGEX.test(value)) {
|
|
333
333
|
if (LEADING_ZERO.test(value)) {
|
|
334
334
|
throw new TomlError("leading zeroes are not allowed", {
|
|
335
335
|
toml,
|
|
336
336
|
ptr
|
|
337
337
|
});
|
|
338
338
|
}
|
|
339
|
-
|
|
339
|
+
value = value.replace(/_/g, "");
|
|
340
|
+
let numeric = +value;
|
|
340
341
|
if (isNaN(numeric)) {
|
|
341
342
|
throw new TomlError("invalid number", {
|
|
342
343
|
toml,
|
|
343
344
|
ptr
|
|
344
345
|
});
|
|
345
346
|
}
|
|
346
|
-
if (isInt
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
347
|
+
if (isInt) {
|
|
348
|
+
if ((isInt = !Number.isSafeInteger(numeric)) && !integersAsBigInt) {
|
|
349
|
+
throw new TomlError("integer value cannot be represented losslessly", {
|
|
350
|
+
toml,
|
|
351
|
+
ptr
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
if (isInt || integersAsBigInt === true)
|
|
355
|
+
numeric = BigInt(value);
|
|
351
356
|
}
|
|
352
357
|
return numeric;
|
|
353
358
|
}
|
|
354
|
-
|
|
359
|
+
const date = new TomlDate(value);
|
|
355
360
|
if (!date.isValid()) {
|
|
356
361
|
throw new TomlError("invalid value", {
|
|
357
362
|
toml,
|
|
@@ -381,7 +386,7 @@ function sliceAndTrimEndOf(str, startPtr, endPtr, allowNewLines) {
|
|
|
381
386
|
}
|
|
382
387
|
return [trimmed, commentIdx];
|
|
383
388
|
}
|
|
384
|
-
function extractValue(str, ptr, end, depth
|
|
389
|
+
function extractValue(str, ptr, end, depth, integersAsBigInt) {
|
|
385
390
|
if (depth === 0) {
|
|
386
391
|
throw new TomlError("document contains excessively nested structures. aborting.", {
|
|
387
392
|
toml: str,
|
|
@@ -390,7 +395,7 @@ function extractValue(str, ptr, end, depth = -1) {
|
|
|
390
395
|
}
|
|
391
396
|
let c = str[ptr];
|
|
392
397
|
if (c === "[" || c === "{") {
|
|
393
|
-
let [value, endPtr2] = c === "[" ? parseArray(str, ptr, depth) : parseInlineTable(str, ptr, depth);
|
|
398
|
+
let [value, endPtr2] = c === "[" ? parseArray(str, ptr, depth, integersAsBigInt) : parseInlineTable(str, ptr, depth, integersAsBigInt);
|
|
394
399
|
let newPtr = end ? skipUntil(str, endPtr2, ",", end) : endPtr2;
|
|
395
400
|
if (endPtr2 - newPtr && end === "}") {
|
|
396
401
|
let nextNewLine = indexOfNewline(str, endPtr2, newPtr);
|
|
@@ -432,7 +437,7 @@ function extractValue(str, ptr, end, depth = -1) {
|
|
|
432
437
|
endPtr += +(str[endPtr] === ",");
|
|
433
438
|
}
|
|
434
439
|
return [
|
|
435
|
-
parseValue(slice[0], str, ptr),
|
|
440
|
+
parseValue(slice[0], str, ptr, integersAsBigInt),
|
|
436
441
|
endPtr
|
|
437
442
|
];
|
|
438
443
|
}
|
|
@@ -506,28 +511,20 @@ function parseKey(str, ptr, end = "=") {
|
|
|
506
511
|
} while (dot + 1 && dot < endPtr);
|
|
507
512
|
return [parsed, skipVoid(str, endPtr + 1, true, true)];
|
|
508
513
|
}
|
|
509
|
-
function parseInlineTable(str, ptr, depth
|
|
514
|
+
function parseInlineTable(str, ptr, depth, integersAsBigInt) {
|
|
510
515
|
let res = {};
|
|
511
516
|
let seen = /* @__PURE__ */ new Set();
|
|
512
517
|
let c;
|
|
513
518
|
let comma = 0;
|
|
514
519
|
ptr++;
|
|
515
520
|
while ((c = str[ptr++]) !== "}" && c) {
|
|
521
|
+
let err = { toml: str, ptr: ptr - 1 };
|
|
516
522
|
if (c === "\n") {
|
|
517
|
-
throw new TomlError("newlines are not allowed in inline tables",
|
|
518
|
-
toml: str,
|
|
519
|
-
ptr: ptr - 1
|
|
520
|
-
});
|
|
523
|
+
throw new TomlError("newlines are not allowed in inline tables", err);
|
|
521
524
|
} else if (c === "#") {
|
|
522
|
-
throw new TomlError("inline tables cannot contain comments",
|
|
523
|
-
toml: str,
|
|
524
|
-
ptr: ptr - 1
|
|
525
|
-
});
|
|
525
|
+
throw new TomlError("inline tables cannot contain comments", err);
|
|
526
526
|
} else if (c === ",") {
|
|
527
|
-
throw new TomlError("expected key-value, found comma",
|
|
528
|
-
toml: str,
|
|
529
|
-
ptr: ptr - 1
|
|
530
|
-
});
|
|
527
|
+
throw new TomlError("expected key-value, found comma", err);
|
|
531
528
|
} else if (c !== " " && c !== " ") {
|
|
532
529
|
let k;
|
|
533
530
|
let t = res;
|
|
@@ -553,7 +550,7 @@ function parseInlineTable(str, ptr, depth = -1) {
|
|
|
553
550
|
ptr
|
|
554
551
|
});
|
|
555
552
|
}
|
|
556
|
-
let [value, valueEndPtr] = extractValue(str, keyEndPtr, "}", depth - 1);
|
|
553
|
+
let [value, valueEndPtr] = extractValue(str, keyEndPtr, "}", depth - 1, integersAsBigInt);
|
|
557
554
|
seen.add(value);
|
|
558
555
|
t[k] = value;
|
|
559
556
|
ptr = valueEndPtr;
|
|
@@ -574,7 +571,7 @@ function parseInlineTable(str, ptr, depth = -1) {
|
|
|
574
571
|
}
|
|
575
572
|
return [res, ptr];
|
|
576
573
|
}
|
|
577
|
-
function parseArray(str, ptr, depth
|
|
574
|
+
function parseArray(str, ptr, depth, integersAsBigInt) {
|
|
578
575
|
let res = [];
|
|
579
576
|
let c;
|
|
580
577
|
ptr++;
|
|
@@ -587,7 +584,7 @@ function parseArray(str, ptr, depth = -1) {
|
|
|
587
584
|
} else if (c === "#")
|
|
588
585
|
ptr = skipComment(str, ptr);
|
|
589
586
|
else if (c !== " " && c !== " " && c !== "\n" && c !== "\r") {
|
|
590
|
-
let e = extractValue(str, ptr - 1, "]", depth - 1);
|
|
587
|
+
let e = extractValue(str, ptr - 1, "]", depth - 1, integersAsBigInt);
|
|
591
588
|
res.push(e[0]);
|
|
592
589
|
ptr = e[1];
|
|
593
590
|
}
|
|
@@ -661,8 +658,7 @@ function peekTable(key, table, meta, type) {
|
|
|
661
658
|
}
|
|
662
659
|
return [k, t, state.c];
|
|
663
660
|
}
|
|
664
|
-
function parse(toml,
|
|
665
|
-
let maxDepth = opts?.maxDepth ?? 1e3;
|
|
661
|
+
function parse(toml, { maxDepth = 1e3, integersAsBigInt } = {}) {
|
|
666
662
|
let res = {};
|
|
667
663
|
let meta = {};
|
|
668
664
|
let tbl = res;
|
|
@@ -711,7 +707,7 @@ function parse(toml, opts) {
|
|
|
711
707
|
ptr
|
|
712
708
|
});
|
|
713
709
|
}
|
|
714
|
-
let v = extractValue(toml, k[1], void 0, maxDepth);
|
|
710
|
+
let v = extractValue(toml, k[1], void 0, maxDepth, integersAsBigInt);
|
|
715
711
|
p[1][p[0]] = v[0];
|
|
716
712
|
ptr = v[1];
|
|
717
713
|
}
|
|
@@ -749,7 +745,7 @@ function isArrayOfTables(obj) {
|
|
|
749
745
|
function formatString(s) {
|
|
750
746
|
return JSON.stringify(s).replace(/\x7f/g, "\\u007f");
|
|
751
747
|
}
|
|
752
|
-
function stringifyValue(val, type, depth) {
|
|
748
|
+
function stringifyValue(val, type, depth, numberAsFloat) {
|
|
753
749
|
if (depth === 0) {
|
|
754
750
|
throw new Error("Could not stringify the object: maximum object depth exceeded");
|
|
755
751
|
}
|
|
@@ -760,6 +756,8 @@ function stringifyValue(val, type, depth) {
|
|
|
760
756
|
return "inf";
|
|
761
757
|
if (val === -Infinity)
|
|
762
758
|
return "-inf";
|
|
759
|
+
if (numberAsFloat && Number.isInteger(val))
|
|
760
|
+
return val.toFixed(1);
|
|
763
761
|
return val.toString();
|
|
764
762
|
}
|
|
765
763
|
if (type === "bigint" || type === "boolean") {
|
|
@@ -775,13 +773,13 @@ function stringifyValue(val, type, depth) {
|
|
|
775
773
|
return val.toISOString();
|
|
776
774
|
}
|
|
777
775
|
if (type === "object") {
|
|
778
|
-
return stringifyInlineTable(val, depth);
|
|
776
|
+
return stringifyInlineTable(val, depth, numberAsFloat);
|
|
779
777
|
}
|
|
780
778
|
if (type === "array") {
|
|
781
|
-
return stringifyArray(val, depth);
|
|
779
|
+
return stringifyArray(val, depth, numberAsFloat);
|
|
782
780
|
}
|
|
783
781
|
}
|
|
784
|
-
function stringifyInlineTable(obj, depth) {
|
|
782
|
+
function stringifyInlineTable(obj, depth, numberAsFloat) {
|
|
785
783
|
let keys = Object.keys(obj);
|
|
786
784
|
if (keys.length === 0)
|
|
787
785
|
return "{}";
|
|
@@ -792,11 +790,11 @@ function stringifyInlineTable(obj, depth) {
|
|
|
792
790
|
res += ", ";
|
|
793
791
|
res += BARE_KEY.test(k) ? k : formatString(k);
|
|
794
792
|
res += " = ";
|
|
795
|
-
res += stringifyValue(obj[k], extendedTypeOf(obj[k]), depth - 1);
|
|
793
|
+
res += stringifyValue(obj[k], extendedTypeOf(obj[k]), depth - 1, numberAsFloat);
|
|
796
794
|
}
|
|
797
795
|
return res + " }";
|
|
798
796
|
}
|
|
799
|
-
function stringifyArray(array, depth) {
|
|
797
|
+
function stringifyArray(array, depth, numberAsFloat) {
|
|
800
798
|
if (array.length === 0)
|
|
801
799
|
return "[]";
|
|
802
800
|
let res = "[ ";
|
|
@@ -806,11 +804,11 @@ function stringifyArray(array, depth) {
|
|
|
806
804
|
if (array[i] === null || array[i] === void 0) {
|
|
807
805
|
throw new TypeError("arrays cannot contain null or undefined values");
|
|
808
806
|
}
|
|
809
|
-
res += stringifyValue(array[i], extendedTypeOf(array[i]), depth - 1);
|
|
807
|
+
res += stringifyValue(array[i], extendedTypeOf(array[i]), depth - 1, numberAsFloat);
|
|
810
808
|
}
|
|
811
809
|
return res + " ]";
|
|
812
810
|
}
|
|
813
|
-
function stringifyArrayTable(array, key, depth) {
|
|
811
|
+
function stringifyArrayTable(array, key, depth, numberAsFloat) {
|
|
814
812
|
if (depth === 0) {
|
|
815
813
|
throw new Error("Could not stringify the object: maximum object depth exceeded");
|
|
816
814
|
}
|
|
@@ -818,12 +816,12 @@ function stringifyArrayTable(array, key, depth) {
|
|
|
818
816
|
for (let i = 0; i < array.length; i++) {
|
|
819
817
|
res += `[[${key}]]
|
|
820
818
|
`;
|
|
821
|
-
res += stringifyTable(array[i], key, depth);
|
|
819
|
+
res += stringifyTable(array[i], key, depth, numberAsFloat);
|
|
822
820
|
res += "\n\n";
|
|
823
821
|
}
|
|
824
822
|
return res;
|
|
825
823
|
}
|
|
826
|
-
function stringifyTable(obj, prefix, depth) {
|
|
824
|
+
function stringifyTable(obj, prefix, depth, numberAsFloat) {
|
|
827
825
|
if (depth === 0) {
|
|
828
826
|
throw new Error("Could not stringify the object: maximum object depth exceeded");
|
|
829
827
|
}
|
|
@@ -839,17 +837,17 @@ function stringifyTable(obj, prefix, depth) {
|
|
|
839
837
|
}
|
|
840
838
|
let key = BARE_KEY.test(k) ? k : formatString(k);
|
|
841
839
|
if (type === "array" && isArrayOfTables(obj[k])) {
|
|
842
|
-
tables += stringifyArrayTable(obj[k], prefix ? `${prefix}.${key}` : key, depth - 1);
|
|
840
|
+
tables += stringifyArrayTable(obj[k], prefix ? `${prefix}.${key}` : key, depth - 1, numberAsFloat);
|
|
843
841
|
} else if (type === "object") {
|
|
844
842
|
let tblKey = prefix ? `${prefix}.${key}` : key;
|
|
845
843
|
tables += `[${tblKey}]
|
|
846
844
|
`;
|
|
847
|
-
tables += stringifyTable(obj[k], tblKey, depth - 1);
|
|
845
|
+
tables += stringifyTable(obj[k], tblKey, depth - 1, numberAsFloat);
|
|
848
846
|
tables += "\n\n";
|
|
849
847
|
} else {
|
|
850
848
|
preamble += key;
|
|
851
849
|
preamble += " = ";
|
|
852
|
-
preamble += stringifyValue(obj[k], type, depth);
|
|
850
|
+
preamble += stringifyValue(obj[k], type, depth, numberAsFloat);
|
|
853
851
|
preamble += "\n";
|
|
854
852
|
}
|
|
855
853
|
}
|
|
@@ -857,12 +855,11 @@ function stringifyTable(obj, prefix, depth) {
|
|
|
857
855
|
return `${preamble}
|
|
858
856
|
${tables}`.trim();
|
|
859
857
|
}
|
|
860
|
-
function stringify(obj,
|
|
858
|
+
function stringify(obj, { maxDepth = 1e3, numbersAsFloat = false } = {}) {
|
|
861
859
|
if (extendedTypeOf(obj) !== "object") {
|
|
862
860
|
throw new TypeError("stringify can only be called with an object");
|
|
863
861
|
}
|
|
864
|
-
|
|
865
|
-
return stringifyTable(obj, "", maxDepth);
|
|
862
|
+
return stringifyTable(obj, "", maxDepth, numbersAsFloat);
|
|
866
863
|
}
|
|
867
864
|
|
|
868
865
|
// dist/index.js
|
package/dist/index.d.ts
CHANGED
|
@@ -29,7 +29,7 @@ import { parse } from './parse.js';
|
|
|
29
29
|
import { stringify } from './stringify.js';
|
|
30
30
|
import { TomlDate } from './date.js';
|
|
31
31
|
import { TomlError } from './error.js';
|
|
32
|
-
export type {
|
|
32
|
+
export type { TomlValue, TomlTable, TomlValueWithoutBigInt, TomlTableWithoutBigInt } from './util.js';
|
|
33
33
|
declare const _default: {
|
|
34
34
|
parse: typeof parse;
|
|
35
35
|
stringify: typeof stringify;
|
|
@@ -38,3 +38,6 @@ declare const _default: {
|
|
|
38
38
|
};
|
|
39
39
|
export default _default;
|
|
40
40
|
export { parse, stringify, TomlDate, TomlError };
|
|
41
|
+
export type {
|
|
42
|
+
/** @deprecated use TomlValue instead */
|
|
43
|
+
TomlValue as TomlPrimitive } from './util.js';
|
package/dist/parse.d.ts
CHANGED
|
@@ -25,7 +25,13 @@
|
|
|
25
25
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
26
26
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
27
27
|
*/
|
|
28
|
-
import {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
import type { IntegersAsBigInt } from './primitive.js';
|
|
29
|
+
import { type TomlTable, type TomlTableWithoutBigInt } from './util.js';
|
|
30
|
+
export interface ParseOptions {
|
|
31
|
+
maxDepth?: number;
|
|
32
|
+
integersAsBigInt?: IntegersAsBigInt;
|
|
33
|
+
}
|
|
34
|
+
export declare function parse(toml: string, options?: ParseOptions & {
|
|
35
|
+
integersAsBigInt: Exclude<IntegersAsBigInt, undefined | false>;
|
|
36
|
+
}): TomlTable;
|
|
37
|
+
export declare function parse(toml: string, options?: ParseOptions): TomlTableWithoutBigInt;
|
package/dist/parse.js
CHANGED
|
@@ -93,8 +93,7 @@ function peekTable(key, table, meta, type) {
|
|
|
93
93
|
}
|
|
94
94
|
return [k, t, state.c];
|
|
95
95
|
}
|
|
96
|
-
export function parse(toml,
|
|
97
|
-
let maxDepth = opts?.maxDepth ?? 1000;
|
|
96
|
+
export function parse(toml, { maxDepth = 1000, integersAsBigInt } = {}) {
|
|
98
97
|
let res = {};
|
|
99
98
|
let meta = {};
|
|
100
99
|
let tbl = res;
|
|
@@ -132,7 +131,7 @@ export function parse(toml, opts) {
|
|
|
132
131
|
ptr: ptr,
|
|
133
132
|
});
|
|
134
133
|
}
|
|
135
|
-
let v = extractValue(toml, k[1], void 0, maxDepth);
|
|
134
|
+
let v = extractValue(toml, k[1], void 0, maxDepth, integersAsBigInt);
|
|
136
135
|
p[1][p[0]] = v[0];
|
|
137
136
|
ptr = v[1];
|
|
138
137
|
}
|
package/dist/primitive.d.ts
CHANGED
|
@@ -27,4 +27,5 @@
|
|
|
27
27
|
*/
|
|
28
28
|
import { TomlDate } from './date.js';
|
|
29
29
|
export declare function parseString(str: string, ptr?: number, endPtr?: number): string;
|
|
30
|
-
export
|
|
30
|
+
export type IntegersAsBigInt = undefined | boolean | 'asNeeded';
|
|
31
|
+
export declare function parseValue(value: string, toml: string, ptr: number, integersAsBigInt: IntegersAsBigInt): boolean | number | bigint | TomlDate;
|
package/dist/primitive.js
CHANGED
|
@@ -42,7 +42,7 @@ let ESC_MAP = {
|
|
|
42
42
|
'\\': '\\',
|
|
43
43
|
};
|
|
44
44
|
export function parseString(str, ptr = 0, endPtr = str.length) {
|
|
45
|
-
let isLiteral = str[ptr] ===
|
|
45
|
+
let isLiteral = str[ptr] === '\'';
|
|
46
46
|
let isMultiline = str[ptr++] === str[ptr] && str[ptr] === str[ptr + 1];
|
|
47
47
|
if (isMultiline) {
|
|
48
48
|
endPtr -= 2;
|
|
@@ -61,14 +61,14 @@ export function parseString(str, ptr = 0, endPtr = str.length) {
|
|
|
61
61
|
if (!isMultiline) {
|
|
62
62
|
throw new TomlError('newlines are not allowed in strings', {
|
|
63
63
|
toml: str,
|
|
64
|
-
ptr: ptr - 1
|
|
64
|
+
ptr: ptr - 1,
|
|
65
65
|
});
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
else if ((c < '\x20' && c !== '\t') || c === '\x7f') {
|
|
69
69
|
throw new TomlError('control characters are not allowed in strings', {
|
|
70
70
|
toml: str,
|
|
71
|
-
ptr: ptr - 1
|
|
71
|
+
ptr: ptr - 1,
|
|
72
72
|
});
|
|
73
73
|
}
|
|
74
74
|
if (isEscape) {
|
|
@@ -79,7 +79,7 @@ export function parseString(str, ptr = 0, endPtr = str.length) {
|
|
|
79
79
|
if (!ESCAPE_REGEX.test(code)) {
|
|
80
80
|
throw new TomlError('invalid unicode escape', {
|
|
81
81
|
toml: str,
|
|
82
|
-
ptr: tmp
|
|
82
|
+
ptr: tmp,
|
|
83
83
|
});
|
|
84
84
|
}
|
|
85
85
|
try {
|
|
@@ -88,7 +88,7 @@ export function parseString(str, ptr = 0, endPtr = str.length) {
|
|
|
88
88
|
catch {
|
|
89
89
|
throw new TomlError('invalid unicode escape', {
|
|
90
90
|
toml: str,
|
|
91
|
-
ptr: tmp
|
|
91
|
+
ptr: tmp,
|
|
92
92
|
});
|
|
93
93
|
}
|
|
94
94
|
}
|
|
@@ -98,7 +98,7 @@ export function parseString(str, ptr = 0, endPtr = str.length) {
|
|
|
98
98
|
if (str[ptr] !== '\n' && str[ptr] !== '\r') {
|
|
99
99
|
throw new TomlError('invalid escape: only line-ending whitespace may be escaped', {
|
|
100
100
|
toml: str,
|
|
101
|
-
ptr: tmp
|
|
101
|
+
ptr: tmp,
|
|
102
102
|
});
|
|
103
103
|
}
|
|
104
104
|
ptr = skipVoid(str, ptr);
|
|
@@ -110,7 +110,7 @@ export function parseString(str, ptr = 0, endPtr = str.length) {
|
|
|
110
110
|
else {
|
|
111
111
|
throw new TomlError('unrecognized escape sequence', {
|
|
112
112
|
toml: str,
|
|
113
|
-
ptr: tmp
|
|
113
|
+
ptr: tmp,
|
|
114
114
|
});
|
|
115
115
|
}
|
|
116
116
|
sliceStart = ptr;
|
|
@@ -123,7 +123,7 @@ export function parseString(str, ptr = 0, endPtr = str.length) {
|
|
|
123
123
|
}
|
|
124
124
|
return parsed + str.slice(sliceStart, endPtr - 1);
|
|
125
125
|
}
|
|
126
|
-
export function parseValue(value, toml, ptr) {
|
|
126
|
+
export function parseValue(value, toml, ptr, integersAsBigInt) {
|
|
127
127
|
// Constant values
|
|
128
128
|
if (value === 'true')
|
|
129
129
|
return true;
|
|
@@ -135,37 +135,43 @@ export function parseValue(value, toml, ptr) {
|
|
|
135
135
|
return Infinity;
|
|
136
136
|
if (value === 'nan' || value === '+nan' || value === '-nan')
|
|
137
137
|
return NaN;
|
|
138
|
+
// Avoid FP representation of -0
|
|
138
139
|
if (value === '-0')
|
|
139
|
-
return
|
|
140
|
+
return integersAsBigInt ? 0n : 0;
|
|
140
141
|
// Numbers
|
|
141
|
-
let isInt;
|
|
142
|
-
if (
|
|
142
|
+
let isInt = INT_REGEX.test(value);
|
|
143
|
+
if (isInt || FLOAT_REGEX.test(value)) {
|
|
143
144
|
if (LEADING_ZERO.test(value)) {
|
|
144
145
|
throw new TomlError('leading zeroes are not allowed', {
|
|
145
146
|
toml: toml,
|
|
146
|
-
ptr: ptr
|
|
147
|
+
ptr: ptr,
|
|
147
148
|
});
|
|
148
149
|
}
|
|
149
|
-
|
|
150
|
+
value = value.replace(/_/g, '');
|
|
151
|
+
let numeric = +value;
|
|
150
152
|
if (isNaN(numeric)) {
|
|
151
153
|
throw new TomlError('invalid number', {
|
|
152
154
|
toml: toml,
|
|
153
|
-
ptr: ptr
|
|
155
|
+
ptr: ptr,
|
|
154
156
|
});
|
|
155
157
|
}
|
|
156
|
-
if (isInt
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
158
|
+
if (isInt) {
|
|
159
|
+
if ((isInt = !Number.isSafeInteger(numeric)) && !integersAsBigInt) {
|
|
160
|
+
throw new TomlError('integer value cannot be represented losslessly', {
|
|
161
|
+
toml: toml,
|
|
162
|
+
ptr: ptr,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
if (isInt || integersAsBigInt === true)
|
|
166
|
+
numeric = BigInt(value);
|
|
161
167
|
}
|
|
162
168
|
return numeric;
|
|
163
169
|
}
|
|
164
|
-
|
|
170
|
+
const date = new TomlDate(value);
|
|
165
171
|
if (!date.isValid()) {
|
|
166
172
|
throw new TomlError('invalid value', {
|
|
167
173
|
toml: toml,
|
|
168
|
-
ptr: ptr
|
|
174
|
+
ptr: ptr,
|
|
169
175
|
});
|
|
170
176
|
}
|
|
171
177
|
return date;
|
package/dist/stringify.d.ts
CHANGED
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
26
26
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
27
27
|
*/
|
|
28
|
-
export declare function stringify(obj: any,
|
|
28
|
+
export declare function stringify(obj: any, { maxDepth, numbersAsFloat }?: {
|
|
29
29
|
maxDepth?: number;
|
|
30
|
+
numbersAsFloat?: boolean;
|
|
30
31
|
}): string;
|
package/dist/stringify.js
CHANGED
|
@@ -46,9 +46,9 @@ function isArrayOfTables(obj) {
|
|
|
46
46
|
function formatString(s) {
|
|
47
47
|
return JSON.stringify(s).replace(/\x7f/g, '\\u007f');
|
|
48
48
|
}
|
|
49
|
-
function stringifyValue(val, type, depth) {
|
|
49
|
+
function stringifyValue(val, type, depth, numberAsFloat) {
|
|
50
50
|
if (depth === 0) {
|
|
51
|
-
throw new Error(
|
|
51
|
+
throw new Error('Could not stringify the object: maximum object depth exceeded');
|
|
52
52
|
}
|
|
53
53
|
if (type === 'number') {
|
|
54
54
|
if (isNaN(val))
|
|
@@ -57,6 +57,8 @@ function stringifyValue(val, type, depth) {
|
|
|
57
57
|
return 'inf';
|
|
58
58
|
if (val === -Infinity)
|
|
59
59
|
return '-inf';
|
|
60
|
+
if (numberAsFloat && Number.isInteger(val))
|
|
61
|
+
return val.toFixed(1);
|
|
60
62
|
return val.toString();
|
|
61
63
|
}
|
|
62
64
|
if (type === 'bigint' || type === 'boolean') {
|
|
@@ -72,13 +74,13 @@ function stringifyValue(val, type, depth) {
|
|
|
72
74
|
return val.toISOString();
|
|
73
75
|
}
|
|
74
76
|
if (type === 'object') {
|
|
75
|
-
return stringifyInlineTable(val, depth);
|
|
77
|
+
return stringifyInlineTable(val, depth, numberAsFloat);
|
|
76
78
|
}
|
|
77
79
|
if (type === 'array') {
|
|
78
|
-
return stringifyArray(val, depth);
|
|
80
|
+
return stringifyArray(val, depth, numberAsFloat);
|
|
79
81
|
}
|
|
80
82
|
}
|
|
81
|
-
function stringifyInlineTable(obj, depth) {
|
|
83
|
+
function stringifyInlineTable(obj, depth, numberAsFloat) {
|
|
82
84
|
let keys = Object.keys(obj);
|
|
83
85
|
if (keys.length === 0)
|
|
84
86
|
return '{}';
|
|
@@ -89,11 +91,11 @@ function stringifyInlineTable(obj, depth) {
|
|
|
89
91
|
res += ', ';
|
|
90
92
|
res += BARE_KEY.test(k) ? k : formatString(k);
|
|
91
93
|
res += ' = ';
|
|
92
|
-
res += stringifyValue(obj[k], extendedTypeOf(obj[k]), depth - 1);
|
|
94
|
+
res += stringifyValue(obj[k], extendedTypeOf(obj[k]), depth - 1, numberAsFloat);
|
|
93
95
|
}
|
|
94
96
|
return res + ' }';
|
|
95
97
|
}
|
|
96
|
-
function stringifyArray(array, depth) {
|
|
98
|
+
function stringifyArray(array, depth, numberAsFloat) {
|
|
97
99
|
if (array.length === 0)
|
|
98
100
|
return '[]';
|
|
99
101
|
let res = '[ ';
|
|
@@ -103,25 +105,25 @@ function stringifyArray(array, depth) {
|
|
|
103
105
|
if (array[i] === null || array[i] === void 0) {
|
|
104
106
|
throw new TypeError('arrays cannot contain null or undefined values');
|
|
105
107
|
}
|
|
106
|
-
res += stringifyValue(array[i], extendedTypeOf(array[i]), depth - 1);
|
|
108
|
+
res += stringifyValue(array[i], extendedTypeOf(array[i]), depth - 1, numberAsFloat);
|
|
107
109
|
}
|
|
108
110
|
return res + ' ]';
|
|
109
111
|
}
|
|
110
|
-
function stringifyArrayTable(array, key, depth) {
|
|
112
|
+
function stringifyArrayTable(array, key, depth, numberAsFloat) {
|
|
111
113
|
if (depth === 0) {
|
|
112
|
-
throw new Error(
|
|
114
|
+
throw new Error('Could not stringify the object: maximum object depth exceeded');
|
|
113
115
|
}
|
|
114
116
|
let res = '';
|
|
115
117
|
for (let i = 0; i < array.length; i++) {
|
|
116
118
|
res += `[[${key}]]\n`;
|
|
117
|
-
res += stringifyTable(array[i], key, depth);
|
|
119
|
+
res += stringifyTable(array[i], key, depth, numberAsFloat);
|
|
118
120
|
res += '\n\n';
|
|
119
121
|
}
|
|
120
122
|
return res;
|
|
121
123
|
}
|
|
122
|
-
function stringifyTable(obj, prefix, depth) {
|
|
124
|
+
function stringifyTable(obj, prefix, depth, numberAsFloat) {
|
|
123
125
|
if (depth === 0) {
|
|
124
|
-
throw new Error(
|
|
126
|
+
throw new Error('Could not stringify the object: maximum object depth exceeded');
|
|
125
127
|
}
|
|
126
128
|
let preamble = '';
|
|
127
129
|
let tables = '';
|
|
@@ -135,28 +137,27 @@ function stringifyTable(obj, prefix, depth) {
|
|
|
135
137
|
}
|
|
136
138
|
let key = BARE_KEY.test(k) ? k : formatString(k);
|
|
137
139
|
if (type === 'array' && isArrayOfTables(obj[k])) {
|
|
138
|
-
tables += stringifyArrayTable(obj[k], prefix ? `${prefix}.${key}` : key, depth - 1);
|
|
140
|
+
tables += stringifyArrayTable(obj[k], prefix ? `${prefix}.${key}` : key, depth - 1, numberAsFloat);
|
|
139
141
|
}
|
|
140
142
|
else if (type === 'object') {
|
|
141
143
|
let tblKey = prefix ? `${prefix}.${key}` : key;
|
|
142
144
|
tables += `[${tblKey}]\n`;
|
|
143
|
-
tables += stringifyTable(obj[k], tblKey, depth - 1);
|
|
145
|
+
tables += stringifyTable(obj[k], tblKey, depth - 1, numberAsFloat);
|
|
144
146
|
tables += '\n\n';
|
|
145
147
|
}
|
|
146
148
|
else {
|
|
147
149
|
preamble += key;
|
|
148
150
|
preamble += ' = ';
|
|
149
|
-
preamble += stringifyValue(obj[k], type, depth);
|
|
151
|
+
preamble += stringifyValue(obj[k], type, depth, numberAsFloat);
|
|
150
152
|
preamble += '\n';
|
|
151
153
|
}
|
|
152
154
|
}
|
|
153
155
|
}
|
|
154
156
|
return `${preamble}\n${tables}`.trim();
|
|
155
157
|
}
|
|
156
|
-
export function stringify(obj,
|
|
158
|
+
export function stringify(obj, { maxDepth = 1000, numbersAsFloat = false } = {}) {
|
|
157
159
|
if (extendedTypeOf(obj) !== 'object') {
|
|
158
160
|
throw new TypeError('stringify can only be called with an object');
|
|
159
161
|
}
|
|
160
|
-
|
|
161
|
-
return stringifyTable(obj, '', maxDepth);
|
|
162
|
+
return stringifyTable(obj, '', maxDepth, numbersAsFloat);
|
|
162
163
|
}
|
package/dist/struct.d.ts
CHANGED
|
@@ -25,7 +25,8 @@
|
|
|
25
25
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
26
26
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
27
27
|
*/
|
|
28
|
-
import { type
|
|
28
|
+
import { type IntegersAsBigInt } from './primitive.js';
|
|
29
|
+
import { type TomlTable, type TomlValue } from './util.js';
|
|
29
30
|
export declare function parseKey(str: string, ptr: number, end?: string): [string[], number];
|
|
30
|
-
export declare function parseInlineTable(str: string, ptr: number, depth
|
|
31
|
-
export declare function parseArray(str: string, ptr: number, depth
|
|
31
|
+
export declare function parseInlineTable(str: string, ptr: number, depth: number, integersAsBigInt: IntegersAsBigInt): [TomlTable, number];
|
|
32
|
+
export declare function parseArray(str: string, ptr: number, depth: number, integersAsBigInt: IntegersAsBigInt): [TomlValue[], number];
|
package/dist/struct.js
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
*/
|
|
28
28
|
import { parseString } from './primitive.js';
|
|
29
29
|
import { extractValue } from './extract.js';
|
|
30
|
-
import {
|
|
30
|
+
import { getStringEnd, indexOfNewline, skipComment, skipVoid } from './util.js';
|
|
31
31
|
import { TomlError } from './error.js';
|
|
32
32
|
let KEY_PART_RE = /^[a-zA-Z0-9-_]+[ \t]*$/;
|
|
33
33
|
export function parseKey(str, ptr, end = '=') {
|
|
@@ -37,7 +37,7 @@ export function parseKey(str, ptr, end = '=') {
|
|
|
37
37
|
if (endPtr < 0) {
|
|
38
38
|
throw new TomlError('incomplete key-value: cannot find end of key', {
|
|
39
39
|
toml: str,
|
|
40
|
-
ptr: ptr
|
|
40
|
+
ptr: ptr,
|
|
41
41
|
});
|
|
42
42
|
}
|
|
43
43
|
do {
|
|
@@ -45,7 +45,7 @@ export function parseKey(str, ptr, end = '=') {
|
|
|
45
45
|
// If it's whitespace, ignore
|
|
46
46
|
if (c !== ' ' && c !== '\t') {
|
|
47
47
|
// If it's a string
|
|
48
|
-
if (c === '"' || c ===
|
|
48
|
+
if (c === '"' || c === '\'') {
|
|
49
49
|
if (c === str[ptr + 1] && c === str[ptr + 2]) {
|
|
50
50
|
throw new TomlError('multiline strings are not allowed in keys', {
|
|
51
51
|
toml: str,
|
|
@@ -102,30 +102,22 @@ export function parseKey(str, ptr, end = '=') {
|
|
|
102
102
|
} while (dot + 1 && dot < endPtr);
|
|
103
103
|
return [parsed, skipVoid(str, endPtr + 1, true, true)];
|
|
104
104
|
}
|
|
105
|
-
export function parseInlineTable(str, ptr, depth
|
|
105
|
+
export function parseInlineTable(str, ptr, depth, integersAsBigInt) {
|
|
106
106
|
let res = {};
|
|
107
107
|
let seen = new Set();
|
|
108
108
|
let c;
|
|
109
109
|
let comma = 0;
|
|
110
110
|
ptr++;
|
|
111
111
|
while ((c = str[ptr++]) !== '}' && c) {
|
|
112
|
+
let err = { toml: str, ptr: ptr - 1 };
|
|
112
113
|
if (c === '\n') {
|
|
113
|
-
throw new TomlError('newlines are not allowed in inline tables',
|
|
114
|
-
toml: str,
|
|
115
|
-
ptr: ptr - 1
|
|
116
|
-
});
|
|
114
|
+
throw new TomlError('newlines are not allowed in inline tables', err);
|
|
117
115
|
}
|
|
118
116
|
else if (c === '#') {
|
|
119
|
-
throw new TomlError('inline tables cannot contain comments',
|
|
120
|
-
toml: str,
|
|
121
|
-
ptr: ptr - 1
|
|
122
|
-
});
|
|
117
|
+
throw new TomlError('inline tables cannot contain comments', err);
|
|
123
118
|
}
|
|
124
119
|
else if (c === ',') {
|
|
125
|
-
throw new TomlError('expected key-value, found comma',
|
|
126
|
-
toml: str,
|
|
127
|
-
ptr: ptr - 1
|
|
128
|
-
});
|
|
120
|
+
throw new TomlError('expected key-value, found comma', err);
|
|
129
121
|
}
|
|
130
122
|
else if (c !== ' ' && c !== '\t') {
|
|
131
123
|
let k;
|
|
@@ -139,7 +131,7 @@ export function parseInlineTable(str, ptr, depth = -1) {
|
|
|
139
131
|
if ((hasOwn = Object.hasOwn(t, k)) && (typeof t[k] !== 'object' || seen.has(t[k]))) {
|
|
140
132
|
throw new TomlError('trying to redefine an already defined value', {
|
|
141
133
|
toml: str,
|
|
142
|
-
ptr: ptr
|
|
134
|
+
ptr: ptr,
|
|
143
135
|
});
|
|
144
136
|
}
|
|
145
137
|
if (!hasOwn && k === '__proto__') {
|
|
@@ -149,10 +141,10 @@ export function parseInlineTable(str, ptr, depth = -1) {
|
|
|
149
141
|
if (hasOwn) {
|
|
150
142
|
throw new TomlError('trying to redefine an already defined value', {
|
|
151
143
|
toml: str,
|
|
152
|
-
ptr: ptr
|
|
144
|
+
ptr: ptr,
|
|
153
145
|
});
|
|
154
146
|
}
|
|
155
|
-
let [value, valueEndPtr] = extractValue(str, keyEndPtr, '}', depth - 1);
|
|
147
|
+
let [value, valueEndPtr] = extractValue(str, keyEndPtr, '}', depth - 1, integersAsBigInt);
|
|
156
148
|
seen.add(value);
|
|
157
149
|
t[k] = value;
|
|
158
150
|
ptr = valueEndPtr;
|
|
@@ -162,18 +154,18 @@ export function parseInlineTable(str, ptr, depth = -1) {
|
|
|
162
154
|
if (comma) {
|
|
163
155
|
throw new TomlError('trailing commas are not allowed in inline tables', {
|
|
164
156
|
toml: str,
|
|
165
|
-
ptr: comma
|
|
157
|
+
ptr: comma,
|
|
166
158
|
});
|
|
167
159
|
}
|
|
168
160
|
if (!c) {
|
|
169
161
|
throw new TomlError('unfinished table encountered', {
|
|
170
162
|
toml: str,
|
|
171
|
-
ptr: ptr
|
|
163
|
+
ptr: ptr,
|
|
172
164
|
});
|
|
173
165
|
}
|
|
174
166
|
return [res, ptr];
|
|
175
167
|
}
|
|
176
|
-
export function parseArray(str, ptr, depth
|
|
168
|
+
export function parseArray(str, ptr, depth, integersAsBigInt) {
|
|
177
169
|
let res = [];
|
|
178
170
|
let c;
|
|
179
171
|
ptr++;
|
|
@@ -181,13 +173,13 @@ export function parseArray(str, ptr, depth = -1) {
|
|
|
181
173
|
if (c === ',') {
|
|
182
174
|
throw new TomlError('expected value, found comma', {
|
|
183
175
|
toml: str,
|
|
184
|
-
ptr: ptr - 1
|
|
176
|
+
ptr: ptr - 1,
|
|
185
177
|
});
|
|
186
178
|
}
|
|
187
179
|
else if (c === '#')
|
|
188
180
|
ptr = skipComment(str, ptr);
|
|
189
181
|
else if (c !== ' ' && c !== '\t' && c !== '\n' && c !== '\r') {
|
|
190
|
-
let e = extractValue(str, ptr - 1, ']', depth - 1);
|
|
182
|
+
let e = extractValue(str, ptr - 1, ']', depth - 1, integersAsBigInt);
|
|
191
183
|
res.push(e[0]);
|
|
192
184
|
ptr = e[1];
|
|
193
185
|
}
|
|
@@ -195,7 +187,7 @@ export function parseArray(str, ptr, depth = -1) {
|
|
|
195
187
|
if (!c) {
|
|
196
188
|
throw new TomlError('unfinished array encountered', {
|
|
197
189
|
toml: str,
|
|
198
|
-
ptr: ptr
|
|
190
|
+
ptr: ptr,
|
|
199
191
|
});
|
|
200
192
|
}
|
|
201
193
|
return [res, ptr];
|
package/dist/util.d.ts
CHANGED
|
@@ -26,9 +26,15 @@
|
|
|
26
26
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
27
27
|
*/
|
|
28
28
|
import type { TomlDate } from './date.js';
|
|
29
|
-
export type TomlPrimitive = string | number |
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
export type TomlPrimitive = string | number | bigint | boolean | TomlDate;
|
|
30
|
+
export type TomlTable = {
|
|
31
|
+
[key: string]: TomlValue;
|
|
32
|
+
};
|
|
33
|
+
export type TomlValue = TomlPrimitive | TomlValue[] | TomlTable;
|
|
34
|
+
export type TomlTableWithoutBigInt = {
|
|
35
|
+
[key: string]: TomlValueWithoutBigInt;
|
|
36
|
+
};
|
|
37
|
+
export type TomlValueWithoutBigInt = Exclude<TomlPrimitive, bigint> | TomlValueWithoutBigInt[] | TomlTableWithoutBigInt;
|
|
32
38
|
export declare function indexOfNewline(str: string, start?: number, end?: number): number;
|
|
33
39
|
export declare function skipComment(str: string, ptr: number): number;
|
|
34
40
|
export declare function skipVoid(str: string, ptr: number, banNewLines?: boolean, banComments?: boolean): number;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "smol-toml",
|
|
3
3
|
"license": "BSD-3-Clause",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.4.1",
|
|
5
5
|
"description": "A small, fast, and correct TOML parser/serializer",
|
|
6
6
|
"author": "Cynthia <cyyynthia@borkenware.com>",
|
|
7
7
|
"repository": "github:squirrelchat/smol-toml",
|
|
@@ -19,15 +19,15 @@
|
|
|
19
19
|
"devDependencies": {
|
|
20
20
|
"@iarna/toml": "3.0.0",
|
|
21
21
|
"@ltd/j-toml": "^1.38.0",
|
|
22
|
-
"@tsconfig/node-lts": "^22.0.
|
|
22
|
+
"@tsconfig/node-lts": "^22.0.2",
|
|
23
23
|
"@tsconfig/strictest": "^2.0.5",
|
|
24
|
-
"@types/node": "^
|
|
25
|
-
"@vitest/ui": "^3.
|
|
26
|
-
"esbuild": "^0.25.
|
|
24
|
+
"@types/node": "^24.0.7",
|
|
25
|
+
"@vitest/ui": "^3.2.4",
|
|
26
|
+
"esbuild": "^0.25.5",
|
|
27
27
|
"fast-toml": "^0.5.4",
|
|
28
|
-
"pin-github-action": "^3.
|
|
28
|
+
"pin-github-action": "^3.4.0",
|
|
29
29
|
"typescript": "^5.8.3",
|
|
30
|
-
"vitest": "^3.
|
|
30
|
+
"vitest": "^3.2.4"
|
|
31
31
|
},
|
|
32
32
|
"main": "./dist/index.cjs",
|
|
33
33
|
"module": "./dist/index.js",
|