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 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
+ [![License](https://img.shields.io/github/license/squirrelchat/smol-toml.svg?style=flat-square)](https://github.com/squirrelchat/smol-toml/blob/mistress/LICENSE)
3
+ [![npm](https://img.shields.io/npm/v/smol-toml?style=flat-square)](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>
@@ -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
+ }
@@ -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
+ }
@@ -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
+ }
@@ -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
+ }