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 CHANGED
@@ -1,8 +1,9 @@
1
1
  # smol-toml
2
+ [![TOML 1.0.0](https://img.shields.io/badge/TOML-1.0.0-9c4221?style=flat-square)](https://toml.io/en/v1.0.0)
2
3
  [![License](https://img.shields.io/github/license/squirrelchat/smol-toml.svg?style=flat-square)](https://github.com/squirrelchat/smol-toml/blob/mistress/LICENSE)
3
4
  [![npm](https://img.shields.io/npm/v/smol-toml?style=flat-square)](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 produces valid results (or errors) for all the test TOML files in https://github.com/iarna/toml-spec-tests.
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
- | | smol-toml | @iarna/toml@3.0.0 | @ltd/j-toml | fast-toml |
40
- |----------------|---------------------|-------------------|----------------|----------------|
41
- | Spec example | **60,733.91 op/s** | 32,565.20 op/s | 16,781.03 op/s | 31,336.67 op/s |
42
- | ~5MB test file | **4.2567 op/s** | *DNF* | 2.4873 op/s | 2.5790 op/s |
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 361089f3dbc30d994494bf6ec1e8e2f135531247
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) 2466ms
139
+ ✓ bench/parseSpecExample.bench.ts (4) 2462ms
55
140
  name hz min max mean p75 p99 p995 p999 rme samples
56
- · smol-toml 60,733.91 0.0145 0.2580 0.0165 0.0152 0.0319 0.0345 0.1383 ±0.46% 30367 fastest
57
- · @iarna/toml 32,565.20 0.0268 0.3208 0.0307 0.0284 0.0580 0.0619 0.1699 ±0.54% 16283
58
- · @ltd/j-toml 16,781.03 0.0505 1.0392 0.0596 0.0540 0.1147 0.1360 0.7657 ±1.52% 8391 slowest
59
- · fast-toml 31,336.67 0.0298 0.3357 0.0319 0.0305 0.0578 0.0622 0.1580 ±0.41% 15669
60
- ✓ bench/parseLargeMixed.bench.ts (3) 15752ms
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 4.2567 225.85 257.42 234.92 242.74 257.42 257.42 257.42 ±3.35% 10 fastest
63
- · @ltd/j-toml 2.4873 382.66 441.12 402.05 416.25 441.12 441.12 441.12 ±3.40% 10 slowest
64
- · fast-toml 2.5790 377.86 409.32 387.75 392.90 409.32 409.32 409.32 ±2.07% 10
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.65x faster than fast-toml
71
- 1.71x faster than @ltd/j-toml
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
- 1.86x faster than @iarna/toml
75
- 1.94x faster than fast-toml
76
- 3.62x faster than @ltd/j-toml
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
- export let DATE_TIME_RE = /^(\d{4}-\d{2}-\d{2})?[Tt ]?(\d{2}:\d{2}:\d{2}(?:\.\d{3,})?)?(Z|[-+]\d{2}:\d{2})?$/;
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
- offset = match[3] || null;
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.#hasTime || !this.#hasTime || !this.#offset;
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];
@@ -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
- import { type TomlPrimitive } from './util.js';
28
+ export { default as TomlError } from './error.js';
29
29
  export { default as TomlDate } from './date.js';
30
- export declare function parse(toml: string): Record<string, TomlPrimitive>;
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
- import { parseKey } from './struct.js';
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 function parse(toml) {
34
- let res = {};
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 extractValue(str: string, ptr: number, end?: string): [TomlPrimitive, number];
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>;