smol-toml 0.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/LICENSE +24 -0
- package/README.md +70 -0
- package/dist/error.d.ts +38 -0
- package/dist/error.js +63 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +90 -0
- package/dist/parse.d.ts +29 -0
- package/dist/parse.js +137 -0
- package/dist/primitive.d.ts +29 -0
- package/dist/primitive.js +164 -0
- package/dist/struct.d.ts +30 -0
- package/dist/struct.js +155 -0
- package/dist/util.d.ts +31 -0
- package/dist/util.js +91 -0
- package/package.json +43 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
2
|
+
|
|
3
|
+
Redistribution and use in source and binary forms, with or without
|
|
4
|
+
modification, are permitted provided that the following conditions are met:
|
|
5
|
+
|
|
6
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
7
|
+
list of conditions and the following disclaimer.
|
|
8
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
9
|
+
this list of conditions and the following disclaimer in the
|
|
10
|
+
documentation and/or other materials provided with the distribution.
|
|
11
|
+
3. Neither the name of the copyright holder nor the names of its contributors
|
|
12
|
+
may be used to endorse or promote products derived from this software without
|
|
13
|
+
specific prior written permission.
|
|
14
|
+
|
|
15
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
16
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
17
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
18
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
19
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
20
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
21
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
22
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
23
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
24
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/README.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# smol-toml
|
|
2
|
+
[](https://github.com/squirrelchat/smol-toml/blob/mistress/LICENSE)
|
|
3
|
+
[](https://npm.im/smol-toml)
|
|
4
|
+
|
|
5
|
+
A small, fast, and correct TOML parser. smol-toml is (almost) fully spec-compliant with TOML v1.0.0.
|
|
6
|
+
|
|
7
|
+
Why yet another TOML parser? Well, the ecosystem of TOML parsers in JavaScript is quite underwhelming, most likely due
|
|
8
|
+
to a lack of interest. With most parsers being outdated, unmaintained, non-compliant, or a combination of these, a new
|
|
9
|
+
parser didn't feel too out of place.
|
|
10
|
+
|
|
11
|
+
*[insert xkcd 927]*
|
|
12
|
+
|
|
13
|
+
smol-toml only fails to comply with the spec in 2 (minor) ways:
|
|
14
|
+
- comments are not validated (absence of control characters)
|
|
15
|
+
- integers can only be between -9_007_199_254_740_991 and 9_007_199_254_740_991 instead of the recommended full 64-bit range
|
|
16
|
+
- integers outside of this range do raise an error, complying with the specification on this regard
|
|
17
|
+
|
|
18
|
+
Otherwise, smol-toml produces valid results (or errors) for all the test TOML files in https://github.com/iarna/toml-spec-tests
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
```
|
|
22
|
+
[pnpm | yarn | npm] i smol-toml
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
```js
|
|
27
|
+
import { parse } from 'smol-toml'
|
|
28
|
+
|
|
29
|
+
const doc = '...'
|
|
30
|
+
const parsed = parse(doc)
|
|
31
|
+
console.log(parsed)
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Performance
|
|
35
|
+
A note on these performance numbers: in some highly synthetic tests, other parsers such as `fast-toml` greatly
|
|
36
|
+
outperform other parsers, mostly due to their lack of compliance with the spec. For example, to parse a string,
|
|
37
|
+
`fast-toml` skips the entire string while `smol-toml` does validate the string, costing a fair chair of performance.
|
|
38
|
+
|
|
39
|
+
The ~5MB test file used for benchmark here is filled with random data which attempts to be close-ish to reality. The
|
|
40
|
+
idea is to have a file relatively close to a real-world application.
|
|
41
|
+
|
|
42
|
+
The large TOML generator can be found [here](https://gist.github.com/cyyynthia/e77c744cb6494dabe37d0182506526b9)
|
|
43
|
+
|
|
44
|
+
| | smol-toml | @iarna/toml@3.0.0 | @ltd/j-toml | fast-toml |
|
|
45
|
+
|----------------|---------------------|-------------------|----------------|----------------|
|
|
46
|
+
| Spec example | **37,009.05 op/s** | 29,203.53 op/s | 16,225.50 op/s | 23,886.25 op/s |
|
|
47
|
+
| ~5MB test file | **4.6007 op/s** | *DNF* | 2.4919 op/s | 2.5952 op/s |
|
|
48
|
+
|
|
49
|
+
<details>
|
|
50
|
+
<summary>Detailed benchmark data</summary>
|
|
51
|
+
|
|
52
|
+
Tests ran using Vitest v0.31.0 on commit bd69ffb52920ee6f2843356dff3325fc2e868821
|
|
53
|
+
|
|
54
|
+
CPU: Intel Core i7 7700K (4.2GHz)
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
✓ bench/parse.bench.ts (7) 17780ms
|
|
58
|
+
✓ TOML spec example (4) 17778ms
|
|
59
|
+
name hz min max mean p75 p99 p995 p999 rme samples
|
|
60
|
+
· smol-toml 37,009.05 0.0231 4.1194 0.0270 0.0260 0.0445 0.0500 0.0622 ±2.88% 18505 fastest
|
|
61
|
+
· @iarna/toml 29,203.53 0.0308 2.1478 0.0342 0.0325 0.0687 0.0714 0.2747 ±1.08% 14602
|
|
62
|
+
· @ltd/j-toml 16,225.50 0.0519 2.8481 0.0616 0.0545 0.1015 0.1193 1.9987 ±3.20% 8113 slowest
|
|
63
|
+
· fast-toml 23,886.25 0.0366 1.7331 0.0419 0.0391 0.0758 0.0818 1.1500 ±1.84% 11944
|
|
64
|
+
✓ 5MB of TOML (all structures) (3) 17268ms
|
|
65
|
+
name hz min max mean p75 p99 p995 p999 rme samples
|
|
66
|
+
· smol-toml 4.6007 208.19 238.94 217.36 229.56 238.94 238.94 238.94 ±4.10% 10 fastest
|
|
67
|
+
· @ltd/j-toml 2.4919 379.85 428.13 401.31 416.64 428.13 428.13 428.13 ±2.82% 10 slowest
|
|
68
|
+
· fast-toml 2.5952 375.28 416.15 385.33 393.15 416.15 416.15 416.15 ±2.60% 10
|
|
69
|
+
```
|
|
70
|
+
</details>
|
package/dist/error.d.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
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
|
+
type TomlErrorOptions = ErrorOptions & {
|
|
29
|
+
toml: string;
|
|
30
|
+
ptr: number;
|
|
31
|
+
};
|
|
32
|
+
export default class TomlError extends Error {
|
|
33
|
+
line: number;
|
|
34
|
+
column: number;
|
|
35
|
+
codeblock: string;
|
|
36
|
+
constructor(message: string, options: TomlErrorOptions);
|
|
37
|
+
}
|
|
38
|
+
export {};
|
package/dist/error.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
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
|
+
function getLineColFromPtr(string, ptr) {
|
|
29
|
+
let lines = string.slice(0, ptr).split(/\r\n|\n|\r/g);
|
|
30
|
+
return [lines.length, lines.pop().length + 1];
|
|
31
|
+
}
|
|
32
|
+
function makeCodeBlock(string, line, column) {
|
|
33
|
+
let lines = string.split(/\r\n|\n|\r/g);
|
|
34
|
+
let codeblock = '';
|
|
35
|
+
let numberLen = (Math.log10(line + 1) | 0) + 1;
|
|
36
|
+
for (let i = line - 1; i <= line + 1; i++) {
|
|
37
|
+
let l = lines[i - 1];
|
|
38
|
+
if (!l)
|
|
39
|
+
continue;
|
|
40
|
+
codeblock += i.toString().padEnd(numberLen, ' ');
|
|
41
|
+
codeblock += ': ';
|
|
42
|
+
codeblock += l;
|
|
43
|
+
codeblock += '\n';
|
|
44
|
+
if (i === line) {
|
|
45
|
+
codeblock += ' '.repeat(numberLen + column + 2);
|
|
46
|
+
codeblock += '^\n';
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return codeblock;
|
|
50
|
+
}
|
|
51
|
+
export default class TomlError extends Error {
|
|
52
|
+
line;
|
|
53
|
+
column;
|
|
54
|
+
codeblock;
|
|
55
|
+
constructor(message, options) {
|
|
56
|
+
const [line, column] = getLineColFromPtr(options.toml, options.ptr);
|
|
57
|
+
const codeblock = makeCodeBlock(options.toml, line, column);
|
|
58
|
+
super(`Invalid TOML document: ${message}\n\n${codeblock}`, options);
|
|
59
|
+
this.line = line;
|
|
60
|
+
this.column = column;
|
|
61
|
+
this.codeblock = codeblock;
|
|
62
|
+
}
|
|
63
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
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
|
+
export declare function parse(toml: string): {};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
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 { parseKey } from './struct.js';
|
|
29
|
+
import { extractKeyValue } from './parse.js';
|
|
30
|
+
import { skipVoid, peekTable } from './util.js';
|
|
31
|
+
import TomlError from './error.js';
|
|
32
|
+
export function parse(toml) {
|
|
33
|
+
let res = {};
|
|
34
|
+
let tbl = res;
|
|
35
|
+
let seenTables = new Set();
|
|
36
|
+
let seenValues = new Set();
|
|
37
|
+
toml = toml.trim();
|
|
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
|
+
}
|
package/dist/parse.d.ts
ADDED
|
@@ -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
|
+
export declare function extractValue(str: string, ptr: number, end?: string): [any, number];
|
|
29
|
+
export declare function extractKeyValue(str: string, ptr: number, table: Record<string, any>, seen: Set<any>, isInline?: boolean): number;
|
package/dist/parse.js
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
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 { parseKey, parseArray, parseInlineTable } from './struct.js';
|
|
30
|
+
import { peekTable, indexOfNewline, skipUntil, skipVoid } from './util.js';
|
|
31
|
+
import TomlError from './error.js';
|
|
32
|
+
function getStringEnd(str, seek) {
|
|
33
|
+
let first = str[seek];
|
|
34
|
+
let target = first === str[seek + 1] && str[seek + 1] === str[seek + 2]
|
|
35
|
+
? str.slice(seek, seek + 3)
|
|
36
|
+
: first;
|
|
37
|
+
seek += target.length - 1;
|
|
38
|
+
do
|
|
39
|
+
seek = str.indexOf(target, ++seek);
|
|
40
|
+
while (seek > -1 && first !== "'" && str[seek - 1] === '\\' && str[seek - 2] !== '\\');
|
|
41
|
+
seek += target.length;
|
|
42
|
+
if (target.length > 1) {
|
|
43
|
+
if (str[seek] === first)
|
|
44
|
+
seek++;
|
|
45
|
+
if (str[seek] === first)
|
|
46
|
+
seek++;
|
|
47
|
+
}
|
|
48
|
+
return seek;
|
|
49
|
+
}
|
|
50
|
+
function sliceAndTrimEndOf(str, startPtr, endPtr, allowNewLines) {
|
|
51
|
+
let value = str.slice(startPtr, endPtr);
|
|
52
|
+
let newlineIdx;
|
|
53
|
+
let commentIdx = value.indexOf('#');
|
|
54
|
+
if (commentIdx > -1) {
|
|
55
|
+
value = value.slice(0, commentIdx);
|
|
56
|
+
}
|
|
57
|
+
let trimmed = value.trimEnd();
|
|
58
|
+
if (!allowNewLines) {
|
|
59
|
+
let s = '\n';
|
|
60
|
+
newlineIdx = value.lastIndexOf('\n');
|
|
61
|
+
if (newlineIdx < 0)
|
|
62
|
+
newlineIdx = value.lastIndexOf(s = '\r');
|
|
63
|
+
if (trimmed.lastIndexOf(s) !== newlineIdx) {
|
|
64
|
+
throw new TomlError('newlines are not allowed in inline tables', {
|
|
65
|
+
toml: str,
|
|
66
|
+
ptr: startPtr + newlineIdx
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return trimmed;
|
|
71
|
+
}
|
|
72
|
+
export function extractValue(str, ptr, end) {
|
|
73
|
+
let c = str[ptr], offset;
|
|
74
|
+
if (c === '[' || c === '{') {
|
|
75
|
+
let [value, endPtr] = c === '['
|
|
76
|
+
? parseArray(str, ptr)
|
|
77
|
+
: parseInlineTable(str, ptr);
|
|
78
|
+
let newPtr = skipUntil(str, endPtr, end);
|
|
79
|
+
if (end === '}') {
|
|
80
|
+
let nextNewLine = indexOfNewline(str, endPtr, newPtr);
|
|
81
|
+
if (nextNewLine > -1) {
|
|
82
|
+
throw new TomlError('newlines are not allowed in inline tables', {
|
|
83
|
+
toml: str,
|
|
84
|
+
ptr: nextNewLine
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return [value, newPtr];
|
|
89
|
+
}
|
|
90
|
+
let endPtr;
|
|
91
|
+
if (c === '"' || c === "'") {
|
|
92
|
+
endPtr = getStringEnd(str, ptr);
|
|
93
|
+
offset = !!end && str[endPtr] === ',';
|
|
94
|
+
return [parseString(str, ptr, endPtr), endPtr + +offset];
|
|
95
|
+
}
|
|
96
|
+
endPtr = skipUntil(str, ptr, end);
|
|
97
|
+
let valStr = sliceAndTrimEndOf(str, ptr, endPtr - (+(str[endPtr - 1] === ',')), end === ']');
|
|
98
|
+
if (!valStr) {
|
|
99
|
+
throw new TomlError('incomplete key-value declaration: no value specified', {
|
|
100
|
+
toml: str,
|
|
101
|
+
ptr: ptr
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
return [
|
|
105
|
+
parseValue(valStr, str, ptr),
|
|
106
|
+
endPtr
|
|
107
|
+
];
|
|
108
|
+
}
|
|
109
|
+
export function extractKeyValue(str, ptr, table, seen, isInline) {
|
|
110
|
+
let equalIdx = str.indexOf('=', ptr);
|
|
111
|
+
if (equalIdx < 0) {
|
|
112
|
+
throw new TomlError('incomplete key-value declaration: no equals sign after the key', {
|
|
113
|
+
toml: str,
|
|
114
|
+
ptr: ptr
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
// KEY
|
|
118
|
+
let t = peekTable(table, parseKey(str, ptr, equalIdx), seen);
|
|
119
|
+
if (!t) {
|
|
120
|
+
throw new TomlError('trying to redefine an already defined value', {
|
|
121
|
+
toml: str,
|
|
122
|
+
ptr: ptr
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
// VALUE
|
|
126
|
+
ptr = skipVoid(str, equalIdx + 1, true, true);
|
|
127
|
+
if (str[ptr] === '\n' || str[ptr] === '\r') {
|
|
128
|
+
throw new TomlError('newlines are not allowed in key-value declarations', {
|
|
129
|
+
toml: str,
|
|
130
|
+
ptr: ptr
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
let e = extractValue(str, ptr, isInline ? '}' : void 0);
|
|
134
|
+
t[1][t[0]] = e[0];
|
|
135
|
+
seen.add(e[0]);
|
|
136
|
+
return e[1];
|
|
137
|
+
}
|
|
@@ -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
|
+
export declare function parseString(str: string, ptr?: number, endPtr?: number): string;
|
|
29
|
+
export declare function parseValue(value: string, toml: string, ptr: number): boolean | number | Date;
|
|
@@ -0,0 +1,164 @@
|
|
|
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 { skipVoid } from './util.js';
|
|
29
|
+
import TomlError from './error.js';
|
|
30
|
+
let NUM_REGEX = /^(0x|0b|0o|[+-])?[0-9a-f_]+(\.[0-9a-f_]+)?([e][+-]?[0-9a-f_]+)?$/i;
|
|
31
|
+
let INT_REGEX = /^(0x|0b|0o|[+-])?[0-9a-f]+$/;
|
|
32
|
+
let LEADING_ZERO = /^[+-]?0\d+/;
|
|
33
|
+
let ESCAPE_REGEX = /^[0-9a-f]{4,8}$/i;
|
|
34
|
+
let ESC_MAP = {
|
|
35
|
+
b: '\b',
|
|
36
|
+
t: '\t',
|
|
37
|
+
n: '\n',
|
|
38
|
+
f: '\f',
|
|
39
|
+
r: '\r',
|
|
40
|
+
'"': '"',
|
|
41
|
+
'\\': '\\',
|
|
42
|
+
};
|
|
43
|
+
let VALUES_MAP = {
|
|
44
|
+
true: true,
|
|
45
|
+
false: false,
|
|
46
|
+
inf: Infinity,
|
|
47
|
+
'+inf': Infinity,
|
|
48
|
+
'-inf': -Infinity,
|
|
49
|
+
nan: NaN,
|
|
50
|
+
'+nan': NaN,
|
|
51
|
+
'-nan': NaN,
|
|
52
|
+
'-0': 0,
|
|
53
|
+
};
|
|
54
|
+
export function parseString(str, ptr = 0, endPtr = str.length) {
|
|
55
|
+
let isLiteral = str[ptr] === "'";
|
|
56
|
+
let isMultiline = str[ptr++] === str[ptr] && str[ptr] === str[ptr + 1];
|
|
57
|
+
if (isMultiline) {
|
|
58
|
+
endPtr -= 2;
|
|
59
|
+
if (str[ptr += 2] === '\r')
|
|
60
|
+
ptr++;
|
|
61
|
+
if (str[ptr] === '\n')
|
|
62
|
+
ptr++;
|
|
63
|
+
}
|
|
64
|
+
let tmp = 0;
|
|
65
|
+
let isEscape;
|
|
66
|
+
let parsed = '';
|
|
67
|
+
let sliceStart = ptr;
|
|
68
|
+
while (ptr < endPtr - 1) {
|
|
69
|
+
let c = str[ptr++];
|
|
70
|
+
if (!isMultiline && (c === '\n' || c === '\r')) {
|
|
71
|
+
throw new TomlError('newlines are not allowed in strings', {
|
|
72
|
+
toml: str,
|
|
73
|
+
ptr: ptr - 1
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
if (c < '\t' || c === '\x0b' || c === '\x0c' || c === '\x7f' || (c > '\x0d' && c < '\x20')) {
|
|
77
|
+
throw new TomlError('control characters are not allowed in strings', {
|
|
78
|
+
toml: str,
|
|
79
|
+
ptr: ptr - 1
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
if (isEscape) {
|
|
83
|
+
isEscape = false;
|
|
84
|
+
if (c === 'u' || c === 'U') {
|
|
85
|
+
// Unicode escape
|
|
86
|
+
let code = str.slice(ptr, (ptr += (c === 'u' ? 4 : 8)));
|
|
87
|
+
if (!ESCAPE_REGEX.test(code)) {
|
|
88
|
+
throw new TomlError('invalid unicode escape', {
|
|
89
|
+
toml: str,
|
|
90
|
+
ptr: tmp
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
parsed += String.fromCodePoint(+`0x${code}`);
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
throw new TomlError('invalid unicode escape', {
|
|
98
|
+
toml: str,
|
|
99
|
+
ptr: tmp
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
else if (isMultiline && (c === '\n' || c === ' ' || c === '\t' || c === '\r')) {
|
|
104
|
+
// Multiline escape
|
|
105
|
+
ptr = skipVoid(str, ptr - 1, true);
|
|
106
|
+
if (str[ptr] !== '\n' && str[ptr] !== '\r') {
|
|
107
|
+
throw new TomlError('invalid escape: only line-ending whitespace may be escaped', {
|
|
108
|
+
toml: str,
|
|
109
|
+
ptr: tmp
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
ptr = skipVoid(str, ptr);
|
|
113
|
+
}
|
|
114
|
+
else if (c in ESC_MAP) {
|
|
115
|
+
// Classic escape
|
|
116
|
+
parsed += ESC_MAP[c];
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
throw new TomlError('unrecognized escape sequence', {
|
|
120
|
+
toml: str,
|
|
121
|
+
ptr: tmp
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
sliceStart = ptr;
|
|
125
|
+
}
|
|
126
|
+
else if (!isLiteral && c === '\\') {
|
|
127
|
+
tmp = ptr - 1;
|
|
128
|
+
isEscape = true;
|
|
129
|
+
parsed += str.slice(sliceStart, tmp);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return parsed + str.slice(sliceStart, endPtr - 1);
|
|
133
|
+
}
|
|
134
|
+
export function parseValue(value, toml, ptr) {
|
|
135
|
+
if (Object.hasOwn(VALUES_MAP, value))
|
|
136
|
+
return VALUES_MAP[value];
|
|
137
|
+
// Numbers
|
|
138
|
+
if (NUM_REGEX.test(value)) {
|
|
139
|
+
if (LEADING_ZERO.test(value)) {
|
|
140
|
+
throw new TomlError('leading zeroes are not allowed', {
|
|
141
|
+
toml: toml,
|
|
142
|
+
ptr: ptr
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
value = value.replace(/_/g, '');
|
|
146
|
+
let numeric = +value;
|
|
147
|
+
if (INT_REGEX.test(value) && !Number.isSafeInteger(numeric)) {
|
|
148
|
+
throw new TomlError('integer value cannot be represented losslessly', {
|
|
149
|
+
toml: toml,
|
|
150
|
+
ptr: ptr
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
return numeric;
|
|
154
|
+
}
|
|
155
|
+
// Date
|
|
156
|
+
let date = new Date(value.includes('-') ? value : `0000-01-01T${value}`);
|
|
157
|
+
if (isNaN(date.getTime())) {
|
|
158
|
+
throw new TomlError('invalid value', {
|
|
159
|
+
toml: toml,
|
|
160
|
+
ptr: ptr
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
return date;
|
|
164
|
+
}
|
package/dist/struct.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
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
|
+
export declare function parseKey(str: string, startPtr?: number, endPtr?: number): string[];
|
|
29
|
+
export declare function parseInlineTable(str: string, ptr: number): [Record<string, any>, number];
|
|
30
|
+
export declare function parseArray(str: string, ptr: number): [any[], number];
|
package/dist/struct.js
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
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 } from './primitive.js';
|
|
29
|
+
import { extractValue, extractKeyValue } from './parse.js';
|
|
30
|
+
import { indexOfNewline } from './util.js';
|
|
31
|
+
import TomlError from './error.js';
|
|
32
|
+
let KEY_PART_RE = /^[a-zA-Z0-9-_ \t]+$/;
|
|
33
|
+
export function parseKey(str, startPtr = 0, endPtr = str.length) {
|
|
34
|
+
let ptr;
|
|
35
|
+
let dot = -1;
|
|
36
|
+
let parsed = [];
|
|
37
|
+
let key = str.slice(startPtr, endPtr);
|
|
38
|
+
do {
|
|
39
|
+
let c = key[ptr = ++dot];
|
|
40
|
+
// If it's whitespace, ignore
|
|
41
|
+
if (c !== ' ' && c !== '\t') {
|
|
42
|
+
// If it's a string
|
|
43
|
+
if (c === '"' || c === "'") {
|
|
44
|
+
let eos = key.indexOf(c, ptr + 1) + 1;
|
|
45
|
+
if (!eos) {
|
|
46
|
+
throw new TomlError('unfinished string encountered', {
|
|
47
|
+
toml: str,
|
|
48
|
+
ptr: ptr
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
dot = key.indexOf('.', eos);
|
|
52
|
+
let end = key.slice(eos, dot < 0 ? void 0 : dot);
|
|
53
|
+
let newLine = indexOfNewline(end);
|
|
54
|
+
if (newLine > -1) {
|
|
55
|
+
throw new TomlError('newlines are not allowed in keys', {
|
|
56
|
+
toml: str,
|
|
57
|
+
ptr: ptr + dot + newLine
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
if (end.trimStart()) {
|
|
61
|
+
throw new TomlError('found extra tokens after the string part', {
|
|
62
|
+
toml: str,
|
|
63
|
+
ptr: eos
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
parsed.push(parseString(key, ptr, eos));
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
// Normal raw key part consumption and validation
|
|
70
|
+
dot = key.indexOf('.', ptr);
|
|
71
|
+
let part = key.slice(ptr, dot < 0 ? void 0 : dot);
|
|
72
|
+
if (!KEY_PART_RE.test(part)) {
|
|
73
|
+
throw new TomlError('only letter, numbers, dashes and underscores are allowed in keys', {
|
|
74
|
+
toml: str,
|
|
75
|
+
ptr: ptr
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
parsed.push(part.trimEnd());
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// Until there's no more dot
|
|
82
|
+
} while (dot + 1);
|
|
83
|
+
return parsed;
|
|
84
|
+
}
|
|
85
|
+
export function parseInlineTable(str, ptr) {
|
|
86
|
+
let res = {};
|
|
87
|
+
let seen = new Set();
|
|
88
|
+
let c;
|
|
89
|
+
let comma = 0;
|
|
90
|
+
ptr++;
|
|
91
|
+
while ((c = str[ptr++]) !== '}' && c) {
|
|
92
|
+
if (c === '\n' || c === '\r') {
|
|
93
|
+
throw new TomlError('newlines are not allowed in inline tables', {
|
|
94
|
+
toml: str,
|
|
95
|
+
ptr: ptr - 1
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
else if (c === '#') {
|
|
99
|
+
throw new TomlError('inline tables cannot contain comments', {
|
|
100
|
+
toml: str,
|
|
101
|
+
ptr: ptr - 1
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
else if (c === ',') {
|
|
105
|
+
throw new TomlError('expected key-value, found comma', {
|
|
106
|
+
toml: str,
|
|
107
|
+
ptr: ptr - 1
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
else if (c !== ' ' && c !== '\t') {
|
|
111
|
+
ptr = extractKeyValue(str, ptr - 1, res, seen, true);
|
|
112
|
+
comma = str[ptr - 1] === ',' ? ptr - 1 : 0;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (comma) {
|
|
116
|
+
throw new TomlError('trailing commas are not allowed in inline tables', {
|
|
117
|
+
toml: str,
|
|
118
|
+
ptr: comma
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
if (!c) {
|
|
122
|
+
throw new TomlError('unfinished table encountered', {
|
|
123
|
+
toml: str,
|
|
124
|
+
ptr: ptr
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
return [res, ptr];
|
|
128
|
+
}
|
|
129
|
+
export function parseArray(str, ptr) {
|
|
130
|
+
let res = [];
|
|
131
|
+
let c;
|
|
132
|
+
ptr++;
|
|
133
|
+
while ((c = str[ptr++]) !== ']' && c) {
|
|
134
|
+
if (c === ',') {
|
|
135
|
+
throw new TomlError('expected value, found comma', {
|
|
136
|
+
toml: str,
|
|
137
|
+
ptr: ptr - 1
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
else if (c === '#')
|
|
141
|
+
ptr = indexOfNewline(str, ptr);
|
|
142
|
+
else if (c !== ' ' && c !== '\t' && c !== '\n' && c !== '\r') {
|
|
143
|
+
let e = extractValue(str, ptr - 1, ']');
|
|
144
|
+
res.push(e[0]);
|
|
145
|
+
ptr = e[1];
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
if (!c) {
|
|
149
|
+
throw new TomlError('unfinished array encountered', {
|
|
150
|
+
toml: str,
|
|
151
|
+
ptr: ptr
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
return [res, ptr];
|
|
155
|
+
}
|
package/dist/util.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
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
|
+
export declare function indexOfNewline(str: string, start?: number, end?: number): number;
|
|
29
|
+
export declare function skipVoid(str: string, ptr: number, banNewLines?: boolean, banComments?: boolean): number;
|
|
30
|
+
export declare function skipUntil(str: string, ptr: number, end?: string): number;
|
|
31
|
+
export declare function peekTable(table: Record<string, any>, key: string[], seen: Set<any>, allowSuper?: boolean): [string, Record<string, any>] | null;
|
package/dist/util.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
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 TomlError from './error.js';
|
|
29
|
+
export function indexOfNewline(str, start = 0, end = str.length) {
|
|
30
|
+
for (let i = start; i < end; i++) {
|
|
31
|
+
if (str[i] === '\n' || str[i] === '\r')
|
|
32
|
+
return i;
|
|
33
|
+
}
|
|
34
|
+
return -1;
|
|
35
|
+
}
|
|
36
|
+
export function skipVoid(str, ptr, banNewLines, banComments) {
|
|
37
|
+
let c;
|
|
38
|
+
while ((c = str[ptr]) === ' ' || c === '\t' || (!banNewLines && (c === '\n' || c === '\r')))
|
|
39
|
+
ptr++;
|
|
40
|
+
if (banComments || c !== '#')
|
|
41
|
+
return ptr;
|
|
42
|
+
ptr = indexOfNewline(str, ptr);
|
|
43
|
+
return ptr < 0 ? str.length : skipVoid(str, ptr, banNewLines);
|
|
44
|
+
}
|
|
45
|
+
export function skipUntil(str, ptr, end) {
|
|
46
|
+
if (!end) {
|
|
47
|
+
ptr = indexOfNewline(str, ptr);
|
|
48
|
+
return ptr < 0 ? str.length : ptr;
|
|
49
|
+
}
|
|
50
|
+
let nextEnd = str.indexOf(end, ptr);
|
|
51
|
+
if (nextEnd < 0) {
|
|
52
|
+
// TODO: point to start of structure instead?
|
|
53
|
+
throw new TomlError('cannot find end of structure', {
|
|
54
|
+
toml: str,
|
|
55
|
+
ptr: ptr
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
let nextSep = str.indexOf(',', ptr) + 1;
|
|
59
|
+
return !nextSep || nextEnd < nextSep ? nextEnd : nextSep;
|
|
60
|
+
}
|
|
61
|
+
let DESCRIPTOR = { enumerable: true, configurable: true, writable: true };
|
|
62
|
+
export function peekTable(table, key, seen, allowSuper) {
|
|
63
|
+
let k = '';
|
|
64
|
+
let v;
|
|
65
|
+
let hasOwn;
|
|
66
|
+
let hadOwn;
|
|
67
|
+
for (let i = 0; i < key.length; i++) {
|
|
68
|
+
if (i) {
|
|
69
|
+
if (!(hadOwn = hasOwn)) {
|
|
70
|
+
if (k === '__proto__')
|
|
71
|
+
Object.defineProperty(table, k, DESCRIPTOR);
|
|
72
|
+
table[k] = {};
|
|
73
|
+
}
|
|
74
|
+
table = table[k];
|
|
75
|
+
if (Array.isArray(table))
|
|
76
|
+
table = table[table.length - 1];
|
|
77
|
+
}
|
|
78
|
+
k = key[i];
|
|
79
|
+
hasOwn = Object.hasOwn(table, k);
|
|
80
|
+
v = hasOwn ? table[k] : void 0;
|
|
81
|
+
if (v !== void 0 && (typeof v !== 'object' || seen.has(v))) {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (hasOwn && (!allowSuper || (hadOwn && !Array.isArray(v)))) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
if (!hasOwn && k === '__proto__')
|
|
89
|
+
Object.defineProperty(table, k, DESCRIPTOR);
|
|
90
|
+
return [k, table];
|
|
91
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "smol-toml",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"keywords": [ "toml", "parser" ],
|
|
5
|
+
"description": "A small, fast, and correct TOML parser",
|
|
6
|
+
"repository": "git@github.com:squirrelchat/smol-toml.git",
|
|
7
|
+
"author": "Cynthia <cyyynthia@borkenware.com>",
|
|
8
|
+
"license": "BSD-3-Clause",
|
|
9
|
+
"type": "module",
|
|
10
|
+
"engines": {
|
|
11
|
+
"node": ">= 18",
|
|
12
|
+
"pnpm": ">= 7.24"
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc",
|
|
16
|
+
"test": "vitest",
|
|
17
|
+
"test-ui": "vitest --ui",
|
|
18
|
+
"bench": "vitest bench"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@iarna/toml": "3.0.0",
|
|
22
|
+
"@ltd/j-toml": "^1.38.0",
|
|
23
|
+
"@tsconfig/esm": "^1.0.3",
|
|
24
|
+
"@tsconfig/node-lts": "^18.12.1",
|
|
25
|
+
"@tsconfig/strictest": "^2.0.1",
|
|
26
|
+
"@types/node": "^20.1.0",
|
|
27
|
+
"@vitest/ui": "^0.31.0",
|
|
28
|
+
"fast-toml": "^0.5.4",
|
|
29
|
+
"typescript": "^5.0.4",
|
|
30
|
+
"vitest": "^0.31.0"
|
|
31
|
+
},
|
|
32
|
+
"exports": {
|
|
33
|
+
".": {
|
|
34
|
+
"default": "./dist/index.js",
|
|
35
|
+
"types": "./dist/index.d.ts"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"files": [
|
|
39
|
+
"README.md",
|
|
40
|
+
"LICENSE",
|
|
41
|
+
"dist"
|
|
42
|
+
]
|
|
43
|
+
}
|