smol-toml 1.0.0 → 1.1.0
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 +139 -22
- package/dist/date.d.ts +1 -1
- package/dist/date.js +22 -12
- package/dist/extract.d.ts +29 -0
- package/dist/extract.js +92 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -62
- package/dist/parse.d.ts +1 -2
- package/dist/parse.js +110 -99
- package/dist/primitive.js +41 -40
- package/dist/stringify.d.ts +28 -0
- package/dist/stringify.js +148 -0
- package/dist/struct.d.ts +1 -1
- package/dist/struct.js +72 -25
- package/dist/util.d.ts +2 -2
- package/dist/util.js +48 -54
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# smol-toml
|
|
2
|
+
[](https://toml.io/en/v1.0.0)
|
|
2
3
|
[](https://github.com/squirrelchat/smol-toml/blob/mistress/LICENSE)
|
|
3
4
|
[](https://npm.im/smol-toml)
|
|
4
5
|
|
|
5
|
-
A small, fast, and correct TOML parser. smol-toml is fully spec-compliant with TOML v1.0.0.
|
|
6
|
+
A small, fast, and correct TOML parser and serializer. smol-toml is fully(ish) spec-compliant with TOML v1.0.0.
|
|
6
7
|
|
|
7
8
|
Why yet another TOML parser? Well, the ecosystem of TOML parsers in JavaScript is quite underwhelming, most likely due
|
|
8
9
|
to a lack of interest. With most parsers being outdated, unmaintained, non-compliant, or a combination of these, a new
|
|
@@ -10,7 +11,32 @@ parser didn't feel too out of place.
|
|
|
10
11
|
|
|
11
12
|
*[insert xkcd 927]*
|
|
12
13
|
|
|
13
|
-
smol-toml
|
|
14
|
+
smol-toml passes most of the tests from [BurntSushi's `toml-test` suite](https://github.com/BurntSushi/toml-test).
|
|
15
|
+
However, due to the nature of JavaScript and the limits of the language, it doesn't pass certain tests, namely:
|
|
16
|
+
- Invalid UTF-8 strings are not rejected
|
|
17
|
+
- Certain invalid UTF-8 codepoints are not rejected
|
|
18
|
+
- smol-toml doesn't preserve type information between integers and floats (in JS, everything is a float)
|
|
19
|
+
- smol-toml doesn't support the whole 64-bit range for integers (but does throw an appropriate error)
|
|
20
|
+
- As all numbers are floats in JS, the safe range is `2**53 - 1` <=> `-(2**53 - 1)`.
|
|
21
|
+
|
|
22
|
+
smol-toml also passes all of the tests in https://github.com/iarna/toml-spec-tests.
|
|
23
|
+
|
|
24
|
+
<details>
|
|
25
|
+
<summary>List of failed `toml-test` cases</summary>
|
|
26
|
+
|
|
27
|
+
These tests were done by modifying `primitive.ts` and make the implementation return bigints for integers. This allows
|
|
28
|
+
verifying the parser correctly intents a number to be an integer or a float.
|
|
29
|
+
|
|
30
|
+
*Ideally, this becomes an option of the library, but for now...*
|
|
31
|
+
|
|
32
|
+
The following parse tests are failing:
|
|
33
|
+
- invalid/encoding/bad-utf8-in-comment
|
|
34
|
+
- invalid/encoding/bad-utf8-in-multiline-literal
|
|
35
|
+
- invalid/encoding/bad-utf8-in-multiline
|
|
36
|
+
- invalid/encoding/bad-utf8-in-string-literal
|
|
37
|
+
- invalid/encoding/bad-utf8-in-string
|
|
38
|
+
- invalid/string/bad-codepoint
|
|
39
|
+
</details>
|
|
14
40
|
|
|
15
41
|
## Installation
|
|
16
42
|
```
|
|
@@ -19,11 +45,65 @@ smol-toml produces valid results (or errors) for all the test TOML files in http
|
|
|
19
45
|
|
|
20
46
|
## Usage
|
|
21
47
|
```js
|
|
22
|
-
import { parse } from 'smol-toml'
|
|
48
|
+
import { parse, stringify } from 'smol-toml'
|
|
23
49
|
|
|
24
50
|
const doc = '...'
|
|
25
51
|
const parsed = parse(doc)
|
|
26
52
|
console.log(parsed)
|
|
53
|
+
|
|
54
|
+
const toml = stringify(parsed)
|
|
55
|
+
console.log(toml)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
A few notes on the `stringify` function:
|
|
59
|
+
- `undefined` and `null` values on objects are ignored (does not produce a key/value).
|
|
60
|
+
- `undefined` and `null` values in arrays are **rejected**.
|
|
61
|
+
- Functions, classes and symbols are **rejected**.
|
|
62
|
+
- floats will be serialized as integers if they don't have a decimal part.
|
|
63
|
+
- `stringify(parse('a = 1.0')) === 'a = 1'`
|
|
64
|
+
- JS `Date` will be serialized as Offset Date Time
|
|
65
|
+
- Use the [`TomlDate` object](#dates) for representing other types.
|
|
66
|
+
|
|
67
|
+
### Dates
|
|
68
|
+
`smol-toml` uses an extended `Date` object to represent all types of TOML Dates. In the future, `smol-toml` will use
|
|
69
|
+
objects from the Temporal proposal, but for now we're stuck with the legacy Date object.
|
|
70
|
+
|
|
71
|
+
```js
|
|
72
|
+
import { TomlDate } from 'smol-toml'
|
|
73
|
+
|
|
74
|
+
// Offset Date Time
|
|
75
|
+
const date = new TomlDate('1979-05-27T07:32:00.000-08:00')
|
|
76
|
+
console.log(date.isDateTime(), date.isDate(), date.isTime(), date.isLocal()) // ~> true, false, false, false
|
|
77
|
+
console.log(date.toISOString()) // ~> 1979-05-27T07:32:00.000-08:00
|
|
78
|
+
|
|
79
|
+
// Local Date Time
|
|
80
|
+
const date = new TomlDate('1979-05-27T07:32:00.000')
|
|
81
|
+
console.log(date.isDateTime(), date.isDate(), date.isTime(), date.isLocal()) // ~> true, false, false, true
|
|
82
|
+
console.log(date.toISOString()) // ~> 1979-05-27T07:32:00.000
|
|
83
|
+
|
|
84
|
+
// Local Date
|
|
85
|
+
const date = new TomlDate('1979-05-27')
|
|
86
|
+
console.log(date.isDateTime(), date.isDate(), date.isTime(), date.isLocal()) // ~> false, true, false, true
|
|
87
|
+
console.log(date.toISOString()) // ~> 1979-05-27
|
|
88
|
+
|
|
89
|
+
// Local Time
|
|
90
|
+
const date = new TomlDate('07:32:00')
|
|
91
|
+
console.log(date.isDateTime(), date.isDate(), date.isTime(), date.isLocal()) // ~> false, false, true, true
|
|
92
|
+
console.log(date.toISOString()) // ~> 07:32:00.000
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
You can also wrap a native `Date` object and specify using different methods depending on the type of date you wish
|
|
96
|
+
to represent:
|
|
97
|
+
|
|
98
|
+
```js
|
|
99
|
+
import { TomlDate } from 'smol-toml'
|
|
100
|
+
|
|
101
|
+
const jsDate = new Date()
|
|
102
|
+
|
|
103
|
+
const offsetDateTime = TomlDate.wrapAsOffsetDateTime(jsDate)
|
|
104
|
+
const localDateTime = TomlDate.wrapAsLocalDateTime(jsDate)
|
|
105
|
+
const localDate = TomlDate.wrapAsLocalDate(jsDate)
|
|
106
|
+
const localTime = TomlDate.wrapAsLocalTime(jsDate)
|
|
27
107
|
```
|
|
28
108
|
|
|
29
109
|
## Performance
|
|
@@ -36,43 +116,80 @@ idea is to have a file relatively close to a real-world application.
|
|
|
36
116
|
|
|
37
117
|
The large TOML generator can be found [here](https://gist.github.com/cyyynthia/e77c744cb6494dabe37d0182506526b9)
|
|
38
118
|
|
|
39
|
-
|
|
|
40
|
-
|
|
41
|
-
| Spec example | **
|
|
42
|
-
| ~5MB test file | **
|
|
119
|
+
| **Parse** | smol-toml | @iarna/toml@3.0.0 | @ltd/j-toml | fast-toml |
|
|
120
|
+
|----------------|---------------------|-------------------|-----------------|-----------------|
|
|
121
|
+
| Spec example | **71,356.51 op/s** | 33,629.31 op/s | 16,433.86 op/s | 29,421.60 op/s |
|
|
122
|
+
| ~5MB test file | **3.8091 op/s** | *DNF* | 2.4369 op/s | 2.6078 op/s |
|
|
123
|
+
|
|
124
|
+
| **Stringify** | smol-toml | @iarna/toml@3.0.0 | @ltd/j-toml |
|
|
125
|
+
|----------------|----------------------|-------------------|----------------|
|
|
126
|
+
| Spec example | **195,191.99 op/s** | 46,583.07 op/s | 5,670.12 op/s |
|
|
127
|
+
| ~5MB test file | **14.6709 op/s** | 3.5941 op/s | 0.7856 op/s |
|
|
43
128
|
|
|
44
129
|
<details>
|
|
45
130
|
<summary>Detailed benchmark data</summary>
|
|
46
131
|
|
|
47
|
-
Tests ran using Vitest v0.31.0 on commit
|
|
132
|
+
Tests ran using Vitest v0.31.0 on commit f58cb6152e667e9cea09f31c93d90652e3b82bf5
|
|
48
133
|
|
|
49
134
|
CPU: Intel Core i7 7700K (4.2GHz)
|
|
50
135
|
|
|
51
136
|
```
|
|
52
137
|
RUN v0.31.0
|
|
53
138
|
|
|
54
|
-
✓ bench/parseSpecExample.bench.ts (4)
|
|
139
|
+
✓ bench/parseSpecExample.bench.ts (4) 2462ms
|
|
55
140
|
name hz min max mean p75 p99 p995 p999 rme samples
|
|
56
|
-
· smol-toml
|
|
57
|
-
· @iarna/toml
|
|
58
|
-
· @ltd/j-toml 16,
|
|
59
|
-
· fast-toml
|
|
60
|
-
✓ bench/parseLargeMixed.bench.ts (3)
|
|
141
|
+
· smol-toml 71,356.51 0.0132 0.2633 0.0140 0.0137 0.0219 0.0266 0.1135 ±0.37% 35679 fastest
|
|
142
|
+
· @iarna/toml 33,629.31 0.0272 0.2629 0.0297 0.0287 0.0571 0.0650 0.1593 ±0.45% 16815
|
|
143
|
+
· @ltd/j-toml 16,433.86 0.0523 1.3088 0.0608 0.0550 0.1140 0.1525 0.7348 ±1.47% 8217 slowest
|
|
144
|
+
· fast-toml 29,421.60 0.0305 0.2995 0.0340 0.0312 0.0618 0.0640 0.1553 ±0.47% 14711
|
|
145
|
+
✓ bench/parseLargeMixed.bench.ts (3) 16062ms
|
|
61
146
|
name hz min max mean p75 p99 p995 p999 rme samples
|
|
62
|
-
· smol-toml
|
|
63
|
-
· @ltd/j-toml 2.
|
|
64
|
-
· fast-toml 2.
|
|
147
|
+
· smol-toml 3.8091 239.60 287.30 262.53 274.17 287.30 287.30 287.30 ±3.66% 10 fastest
|
|
148
|
+
· @ltd/j-toml 2.4369 376.73 493.49 410.35 442.58 493.49 493.49 493.49 ±7.08% 10 slowest
|
|
149
|
+
· fast-toml 2.6078 373.88 412.79 383.47 388.62 412.79 412.79 412.79 ±2.72% 10
|
|
150
|
+
✓ bench/stringifySpecExample.bench.ts (3) 1886ms
|
|
151
|
+
name hz min max mean p75 p99 p995 p999 rme samples
|
|
152
|
+
· smol-toml 195,191.99 0.0047 0.2704 0.0051 0.0050 0.0099 0.0110 0.0152 ±0.41% 97596 fastest
|
|
153
|
+
· @iarna/toml 46,583.07 0.0197 0.2808 0.0215 0.0208 0.0448 0.0470 0.1704 ±0.47% 23292
|
|
154
|
+
· @ltd/j-toml 5,670.12 0.1613 0.5768 0.1764 0.1726 0.3036 0.3129 0.4324 ±0.56% 2836 slowest
|
|
155
|
+
✓ bench/stringifyLargeMixed.bench.ts (3) 24057ms
|
|
156
|
+
name hz min max mean p75 p99 p995 p999 rme samples
|
|
157
|
+
· smol-toml 14.6709 65.1071 79.2199 68.1623 67.1088 79.2199 79.2199 79.2199 ±5.25% 10 fastest
|
|
158
|
+
· @iarna/toml 3.5941 266.48 295.24 278.24 290.10 295.24 295.24 295.24 ±2.83% 10
|
|
159
|
+
· @ltd/j-toml 0.7856 1,254.33 1,322.05 1,272.87 1,286.82 1,322.05 1,322.05 1,322.05 ±1.37% 10 slowest
|
|
65
160
|
|
|
66
161
|
|
|
67
162
|
BENCH Summary
|
|
68
163
|
|
|
69
164
|
smol-toml - bench/parseLargeMixed.bench.ts >
|
|
70
|
-
1.
|
|
71
|
-
1.
|
|
165
|
+
1.46x faster than fast-toml
|
|
166
|
+
1.56x faster than @ltd/j-toml
|
|
72
167
|
|
|
73
168
|
smol-toml - bench/parseSpecExample.bench.ts >
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
169
|
+
2.12x faster than @iarna/toml
|
|
170
|
+
2.43x faster than fast-toml
|
|
171
|
+
4.34x faster than @ltd/j-toml
|
|
172
|
+
|
|
173
|
+
smol-toml - bench/stringifyLargeMixed.bench.ts >
|
|
174
|
+
4.00x faster than @iarna/toml
|
|
175
|
+
18.33x faster than @ltd/j-toml
|
|
176
|
+
|
|
177
|
+
smol-toml - bench/stringifySpecExample.bench.ts >
|
|
178
|
+
4.19x faster than @iarna/toml
|
|
179
|
+
34.42x faster than @ltd/j-toml
|
|
77
180
|
```
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
Additional notes:
|
|
184
|
+
|
|
185
|
+
I initially tried to benchmark `toml-nodejs`, but the 0.3.0 package is broken.
|
|
186
|
+
I initially reported this to the library author, but the author decided to
|
|
187
|
+
- a) advise to use a custom loader (via *experimental* flag) to circumvent the invalid imports.
|
|
188
|
+
- Said flag, `--experimental-specifier-resolution`, has been removed in Node v20.
|
|
189
|
+
- b) [delete the issue](https://github.com/huan231/toml-nodejs/issues/12) when pointed out links to the NodeJS
|
|
190
|
+
documentation about the flag removal and standard resolution algorithm.
|
|
191
|
+
|
|
192
|
+
For the reference anyways, `toml-nodejs` (with proper imports) is ~8x slower on both parse benchmark with:
|
|
193
|
+
- spec example: 7,543.47 op/s
|
|
194
|
+
- 5mb mixed: 0.7006 op/s
|
|
78
195
|
</details>
|
package/dist/date.d.ts
CHANGED
|
@@ -25,7 +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
|
-
export declare let DATE_TIME_RE: RegExp;
|
|
29
28
|
export default class TomlDate extends Date {
|
|
30
29
|
#private;
|
|
31
30
|
constructor(date: string | Date);
|
|
@@ -33,6 +32,7 @@ export default class TomlDate extends Date {
|
|
|
33
32
|
isLocal(): boolean;
|
|
34
33
|
isDate(): boolean;
|
|
35
34
|
isTime(): boolean;
|
|
35
|
+
isValid(): boolean;
|
|
36
36
|
toISOString(): string;
|
|
37
37
|
static wrapAsOffsetDateTime(jsDate: Date, offset?: string): TomlDate;
|
|
38
38
|
static wrapAsLocalDateTime(jsDate: Date): TomlDate;
|
package/dist/date.js
CHANGED
|
@@ -25,11 +25,11 @@
|
|
|
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
|
-
|
|
28
|
+
let DATE_TIME_RE = /^(\d{4}-\d{2}-\d{2})?[T ]?(?:(\d{2}):\d{2}:\d{2}(?:\.\d+)?)?(Z|[-+]\d{2}:\d{2})?$/i;
|
|
29
29
|
export default class TomlDate extends Date {
|
|
30
|
-
#hasDate;
|
|
31
|
-
#hasTime;
|
|
32
|
-
#offset;
|
|
30
|
+
#hasDate = false;
|
|
31
|
+
#hasTime = false;
|
|
32
|
+
#offset = null;
|
|
33
33
|
constructor(date) {
|
|
34
34
|
let hasDate = true;
|
|
35
35
|
let hasTime = true;
|
|
@@ -42,16 +42,23 @@ export default class TomlDate extends Date {
|
|
|
42
42
|
date = `0000-01-01T${date}`;
|
|
43
43
|
}
|
|
44
44
|
hasTime = !!match[2];
|
|
45
|
-
|
|
45
|
+
// Do not allow rollover hours
|
|
46
|
+
if (match[2] && +match[2] > 23) {
|
|
47
|
+
date = '';
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
offset = match[3] || null;
|
|
51
|
+
date = date.toUpperCase();
|
|
52
|
+
if (!offset)
|
|
53
|
+
date += 'Z';
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
date = '';
|
|
46
58
|
}
|
|
47
59
|
}
|
|
48
60
|
super(date);
|
|
49
|
-
if (isNaN(this.getTime())) {
|
|
50
|
-
this.#hasDate = false;
|
|
51
|
-
this.#hasTime = false;
|
|
52
|
-
this.#offset = null;
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
61
|
+
if (!isNaN(this.getTime())) {
|
|
55
62
|
this.#hasDate = hasDate;
|
|
56
63
|
this.#hasTime = hasTime;
|
|
57
64
|
this.#offset = offset;
|
|
@@ -61,7 +68,7 @@ export default class TomlDate extends Date {
|
|
|
61
68
|
return this.#hasDate && this.#hasTime;
|
|
62
69
|
}
|
|
63
70
|
isLocal() {
|
|
64
|
-
return !this.#
|
|
71
|
+
return !this.#hasDate || !this.#hasTime || !this.#offset;
|
|
65
72
|
}
|
|
66
73
|
isDate() {
|
|
67
74
|
return this.#hasDate && !this.#hasTime;
|
|
@@ -69,6 +76,9 @@ export default class TomlDate extends Date {
|
|
|
69
76
|
isTime() {
|
|
70
77
|
return this.#hasTime && !this.#hasDate;
|
|
71
78
|
}
|
|
79
|
+
isValid() {
|
|
80
|
+
return this.#hasDate || this.#hasTime;
|
|
81
|
+
}
|
|
72
82
|
toISOString() {
|
|
73
83
|
let iso = super.toISOString();
|
|
74
84
|
// Local Date
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
3
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
4
|
+
*
|
|
5
|
+
* Redistribution and use in source and binary forms, with or without
|
|
6
|
+
* modification, are permitted provided that the following conditions are met:
|
|
7
|
+
*
|
|
8
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
* list of conditions and the following disclaimer.
|
|
10
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
11
|
+
* this list of conditions and the following disclaimer in the
|
|
12
|
+
* documentation and/or other materials provided with the distribution.
|
|
13
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
14
|
+
* may be used to endorse or promote products derived from this software without
|
|
15
|
+
* specific prior written permission.
|
|
16
|
+
*
|
|
17
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
18
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
19
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
20
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
21
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
22
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
23
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
24
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
25
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
26
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
27
|
+
*/
|
|
28
|
+
import { type TomlPrimitive } from './util.js';
|
|
29
|
+
export declare function extractValue(str: string, ptr: number, end?: string): [TomlPrimitive, number];
|
package/dist/extract.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
3
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
4
|
+
*
|
|
5
|
+
* Redistribution and use in source and binary forms, with or without
|
|
6
|
+
* modification, are permitted provided that the following conditions are met:
|
|
7
|
+
*
|
|
8
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
* list of conditions and the following disclaimer.
|
|
10
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
11
|
+
* this list of conditions and the following disclaimer in the
|
|
12
|
+
* documentation and/or other materials provided with the distribution.
|
|
13
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
14
|
+
* may be used to endorse or promote products derived from this software without
|
|
15
|
+
* specific prior written permission.
|
|
16
|
+
*
|
|
17
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
18
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
19
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
20
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
21
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
22
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
23
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
24
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
25
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
26
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
27
|
+
*/
|
|
28
|
+
import { parseString, parseValue } from './primitive.js';
|
|
29
|
+
import { parseArray, parseInlineTable } from './struct.js';
|
|
30
|
+
import { indexOfNewline, skipVoid, skipUntil, skipComment, getStringEnd } from './util.js';
|
|
31
|
+
import TomlError from './error.js';
|
|
32
|
+
function sliceAndTrimEndOf(str, startPtr, endPtr, allowNewLines) {
|
|
33
|
+
let value = str.slice(startPtr, endPtr);
|
|
34
|
+
let commentIdx = value.indexOf('#');
|
|
35
|
+
if (commentIdx > -1) {
|
|
36
|
+
// The call to skipComment allows to "validate" the comment
|
|
37
|
+
// (absence of control characters)
|
|
38
|
+
skipComment(str, commentIdx);
|
|
39
|
+
value = value.slice(0, commentIdx);
|
|
40
|
+
}
|
|
41
|
+
let trimmed = value.trimEnd();
|
|
42
|
+
if (!allowNewLines) {
|
|
43
|
+
let newlineIdx = value.indexOf('\n', trimmed.length);
|
|
44
|
+
if (newlineIdx > -1) {
|
|
45
|
+
throw new TomlError('newlines are not allowed in inline tables', {
|
|
46
|
+
toml: str,
|
|
47
|
+
ptr: startPtr + newlineIdx
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return [trimmed, commentIdx];
|
|
52
|
+
}
|
|
53
|
+
export function extractValue(str, ptr, end) {
|
|
54
|
+
let c = str[ptr];
|
|
55
|
+
if (c === '[' || c === '{') {
|
|
56
|
+
let [value, endPtr] = c === '['
|
|
57
|
+
? parseArray(str, ptr)
|
|
58
|
+
: parseInlineTable(str, ptr);
|
|
59
|
+
let newPtr = skipUntil(str, endPtr, ',', end);
|
|
60
|
+
if (end === '}') {
|
|
61
|
+
let nextNewLine = indexOfNewline(str, endPtr, newPtr);
|
|
62
|
+
if (nextNewLine > -1) {
|
|
63
|
+
throw new TomlError('newlines are not allowed in inline tables', {
|
|
64
|
+
toml: str,
|
|
65
|
+
ptr: nextNewLine
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return [value, newPtr];
|
|
70
|
+
}
|
|
71
|
+
let endPtr;
|
|
72
|
+
if (c === '"' || c === "'") {
|
|
73
|
+
endPtr = getStringEnd(str, ptr);
|
|
74
|
+
return [parseString(str, ptr, endPtr), endPtr + +(!!end && str[endPtr] === ',')];
|
|
75
|
+
}
|
|
76
|
+
endPtr = skipUntil(str, ptr, ',', end);
|
|
77
|
+
let slice = sliceAndTrimEndOf(str, ptr, endPtr - (+(str[endPtr - 1] === ',')), end === ']');
|
|
78
|
+
if (!slice[0]) {
|
|
79
|
+
throw new TomlError('incomplete key-value declaration: no value specified', {
|
|
80
|
+
toml: str,
|
|
81
|
+
ptr: ptr
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
if (end && slice[1] > -1) {
|
|
85
|
+
endPtr = skipVoid(str, ptr + slice[1]);
|
|
86
|
+
endPtr += +(str[endPtr] === ',');
|
|
87
|
+
}
|
|
88
|
+
return [
|
|
89
|
+
parseValue(slice[0], str, ptr),
|
|
90
|
+
endPtr,
|
|
91
|
+
];
|
|
92
|
+
}
|
package/dist/index.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
|
-
|
|
28
|
+
export { default as TomlError } from './error.js';
|
|
29
29
|
export { default as TomlDate } from './date.js';
|
|
30
|
-
export
|
|
30
|
+
export { parse } from './parse.js';
|
|
31
|
+
export { stringify } from './stringify.js';
|
package/dist/index.js
CHANGED
|
@@ -25,66 +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
|
-
|
|
29
|
-
import { extractKeyValue } from './parse.js';
|
|
30
|
-
import { skipVoid, peekTable } from './util.js';
|
|
31
|
-
import TomlError from './error.js';
|
|
28
|
+
export { default as TomlError } from './error.js';
|
|
32
29
|
export { default as TomlDate } from './date.js';
|
|
33
|
-
export
|
|
34
|
-
|
|
35
|
-
let tbl = res;
|
|
36
|
-
let seenTables = new Set();
|
|
37
|
-
let seenValues = new Set();
|
|
38
|
-
for (let ptr = skipVoid(toml, 0); ptr < toml.length;) {
|
|
39
|
-
if (toml[ptr] === '[') {
|
|
40
|
-
let isTableArray = toml[ptr + 1] === '[';
|
|
41
|
-
let end = toml.indexOf(']', ptr);
|
|
42
|
-
if (end === -1)
|
|
43
|
-
throw new TomlError('unfinished table encountered', {
|
|
44
|
-
toml: toml,
|
|
45
|
-
ptr: ptr
|
|
46
|
-
});
|
|
47
|
-
let k = parseKey(toml, ptr += +isTableArray + 1, end++);
|
|
48
|
-
let strKey = k.join('"."');
|
|
49
|
-
if (!isTableArray && seenTables.has(strKey))
|
|
50
|
-
throw new TomlError('trying to redefine an already defined table', {
|
|
51
|
-
toml: toml,
|
|
52
|
-
ptr: ptr - 1
|
|
53
|
-
});
|
|
54
|
-
seenTables.add(strKey);
|
|
55
|
-
let r = peekTable(res, k, seenValues, true);
|
|
56
|
-
if (!r) {
|
|
57
|
-
throw new TomlError('trying to redefine an already defined value', {
|
|
58
|
-
toml: toml,
|
|
59
|
-
ptr: ptr - 1
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
let v = r[1][r[0]];
|
|
63
|
-
if (!v) {
|
|
64
|
-
r[1][r[0]] = (v = isTableArray ? [] : {});
|
|
65
|
-
}
|
|
66
|
-
else if (isTableArray && !Array.isArray(v)) {
|
|
67
|
-
throw new TomlError('trying to define an array of tables, but a table already exists for this identifier', {
|
|
68
|
-
toml: toml,
|
|
69
|
-
ptr: ptr - 2
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
tbl = v;
|
|
73
|
-
if (isTableArray)
|
|
74
|
-
v.push(tbl = {});
|
|
75
|
-
ptr = end + +isTableArray;
|
|
76
|
-
}
|
|
77
|
-
else {
|
|
78
|
-
ptr = extractKeyValue(toml, ptr, tbl, seenValues);
|
|
79
|
-
}
|
|
80
|
-
ptr = skipVoid(toml, ptr, true);
|
|
81
|
-
if (toml[ptr] && toml[ptr] !== '\n' && toml[ptr] !== '\r') {
|
|
82
|
-
throw new TomlError('each key-value declaration must be followed by an end-of-line', {
|
|
83
|
-
toml: toml,
|
|
84
|
-
ptr: ptr
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
ptr = skipVoid(toml, ptr);
|
|
88
|
-
}
|
|
89
|
-
return res;
|
|
90
|
-
}
|
|
30
|
+
export { parse } from './parse.js';
|
|
31
|
+
export { stringify } from './stringify.js';
|
package/dist/parse.d.ts
CHANGED
|
@@ -26,5 +26,4 @@
|
|
|
26
26
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
27
27
|
*/
|
|
28
28
|
import { type TomlPrimitive } from './util.js';
|
|
29
|
-
export declare function
|
|
30
|
-
export declare function extractKeyValue(str: string, ptr: number, table: Record<string, TomlPrimitive>, seen: Set<any>, isInline?: boolean): number;
|
|
29
|
+
export declare function parse(toml: string): Record<string, TomlPrimitive>;
|