@toon-format/spec 1.3.3 → 1.4.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/tests/README.md CHANGED
@@ -25,16 +25,18 @@ tests/
25
25
  │ │ ├── arrays-nested.json
26
26
  │ │ ├── arrays-objects.json
27
27
  │ │ ├── delimiters.json
28
- │ │ ├── normalization.json
29
28
  │ │ ├── whitespace.json
30
29
  │ │ └── options.json
31
30
  │ └── decode/ # Decoding tests (TOON → JSON)
32
31
  │ ├── primitives.json
32
+ │ ├── numbers.json
33
33
  │ ├── objects.json
34
34
  │ ├── arrays-primitive.json
35
35
  │ ├── arrays-tabular.json
36
36
  │ ├── arrays-nested.json
37
37
  │ ├── delimiters.json
38
+ │ ├── whitespace.json
39
+ │ ├── root-form.json
38
40
  │ ├── validation-errors.json
39
41
  │ ├── indentation-errors.json
40
42
  │ └── blank-lines.json
@@ -47,7 +49,7 @@ All test fixtures follow a standard JSON structure defined in [`fixtures.schema.
47
49
 
48
50
  ```json
49
51
  {
50
- "version": "1.3",
52
+ "version": "1.4",
51
53
  "category": "encode",
52
54
  "description": "Brief description of test category",
53
55
  "tests": [
@@ -88,13 +90,13 @@ All test fixtures follow a standard JSON structure defined in [`fixtures.schema.
88
90
  {
89
91
  "delimiter": ",",
90
92
  "indent": 2,
91
- "lengthMarker": ""
93
+ "lengthMarker": "#"
92
94
  }
93
95
  ```
94
96
 
95
- - `delimiter`: `","` (comma, default), `"\t"` (tab), or `"|"` (pipe)
97
+ - `delimiter`: `","` (comma, default), `"\t"` (tab), or `"|"` (pipe). Affects encoder output for multiline object values; decoders parse what's present
96
98
  - `indent`: Number of spaces per indentation level (default: `2`)
97
- - `lengthMarker`: `"#"` to prefix array lengths, or `""` for no marker (default: `""`)
99
+ - `lengthMarker`: Optional. Set to `"#"` to prefix array lengths (e.g., `[#3]`). Omit this property to disable length markers
98
100
 
99
101
  #### Decoding Options
100
102
 
@@ -143,30 +145,32 @@ The fixture format is language-agnostic JSON, so you can load and iterate it usi
143
145
 
144
146
  | File | Description | Spec Sections |
145
147
  |------|-------------|---------------|
146
- | `primitives.json` | String, number, boolean, null encoding and escaping | §5 |
147
- | `objects.json` | Simple objects, nested objects, key encoding | §6 |
148
- | `arrays-primitive.json` | Inline primitive arrays, empty arrays | §7.1 |
149
- | `arrays-tabular.json` | Tabular format with header and rows | §7.2 |
150
- | `arrays-nested.json` | Arrays of arrays, mixed arrays | §7.3 |
151
- | `arrays-objects.json` | Objects as list items, complex nesting | §7 |
152
- | `delimiters.json` | Tab and pipe delimiter options | §8 |
153
- | `normalization.json` | BigInt, Date, undefined, NaN, Infinity handling | §5 |
154
- | `whitespace.json` | Formatting invariants and indentation | §4 |
148
+ | `primitives.json` | String, number, boolean, null encoding and escaping | §7.1/§7.2, §2 |
149
+ | `objects.json` | Simple objects, nested objects, key encoding | §8 (keys: §7.3/§7.1) |
150
+ | `arrays-primitive.json` | Inline primitive arrays, empty arrays | §9.1 |
151
+ | `arrays-tabular.json` | Tabular format with header and rows | §9.3 |
152
+ | `arrays-nested.json` | Arrays of arrays, mixed arrays | §9.2/§9.4 |
153
+ | `arrays-objects.json` | Objects as list items, complex nesting | §9, §10 |
154
+ | `delimiters.json` | Tab and pipe delimiter options | §11 |
155
+ | `whitespace.json` | Formatting invariants and indentation | §12 |
155
156
  | `options.json` | Length marker and delimiter option combinations | §3 |
156
157
 
157
158
  ### Decoding Tests (`fixtures/decode/`)
158
159
 
159
160
  | File | Description | Spec Sections |
160
161
  |------|-------------|---------------|
161
- | `primitives.json` | Parsing primitives, unescaping, ambiguity | §5 |
162
- | `objects.json` | Parsing objects, keys, nesting | §6 |
163
- | `arrays-primitive.json` | Inline array parsing | §7.1 |
164
- | `arrays-tabular.json` | Tabular format parsing | §7.2 |
165
- | `arrays-nested.json` | Nested and mixed array parsing | §7.3 |
166
- | `delimiters.json` | Delimiter detection and parsing | §8 |
167
- | `validation-errors.json` | Syntax errors, length mismatches, malformed input | §9 |
168
- | `indentation-errors.json` | Strict mode indentation validation | §9 |
169
- | `blank-lines.json` | Blank line handling in arrays | §9 |
162
+ | `primitives.json` | Parsing primitives, unescaping, ambiguity | §4, §7.1/§7.4 |
163
+ | `numbers.json` | Number edge cases, exponent forms, leading zeros | §4 |
164
+ | `objects.json` | Parsing objects, keys, nesting | §8 (keys: §7.3/§7.1) |
165
+ | `arrays-primitive.json` | Inline array parsing | §9.1 |
166
+ | `arrays-tabular.json` | Tabular format parsing | §9.3 |
167
+ | `arrays-nested.json` | Nested and mixed array parsing | §9.2/§9.4 |
168
+ | `delimiters.json` | Delimiter detection and parsing | §11 |
169
+ | `whitespace.json` | Whitespace tolerance and token trimming | §12 |
170
+ | `root-form.json` | Root form detection (empty, single primitive) | §5 |
171
+ | `validation-errors.json` | Syntax errors, length mismatches, malformed input | §14 |
172
+ | `indentation-errors.json` | Strict mode indentation validation | §14.3, §12 |
173
+ | `blank-lines.json` | Blank line handling in arrays | §14.4, §12 |
170
174
 
171
175
  ## Validating Fixtures
172
176
 
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.3",
2
+ "version": "1.4",
3
3
  "category": "decode",
4
4
  "description": "Nested and mixed array decoding - list format, arrays of arrays, root arrays, mixed types",
5
5
  "tests": [
@@ -12,7 +12,7 @@
12
12
  { "id": 2, "name": "Second", "extra": true }
13
13
  ]
14
14
  },
15
- "specSection": "7"
15
+ "specSection": "9.4"
16
16
  },
17
17
  {
18
18
  "name": "parses list arrays with empty items",
@@ -20,7 +20,7 @@
20
20
  "expected": {
21
21
  "items": ["first", "second", {}]
22
22
  },
23
- "specSection": "7.3"
23
+ "specSection": "9.4"
24
24
  },
25
25
  {
26
26
  "name": "parses list arrays with deeply nested objects",
@@ -49,7 +49,7 @@
49
49
  { "id": 1, "nested": { "x": 1 } }
50
50
  ]
51
51
  },
52
- "specSection": "7"
52
+ "specSection": "9.4"
53
53
  },
54
54
  {
55
55
  "name": "parses nested tabular arrays as first field on hyphen line",
@@ -65,7 +65,7 @@
65
65
  }
66
66
  ]
67
67
  },
68
- "specSection": "7"
68
+ "specSection": "10"
69
69
  },
70
70
  {
71
71
  "name": "parses objects containing arrays (including empty arrays) in list format",
@@ -75,7 +75,7 @@
75
75
  { "name": "test", "data": [] }
76
76
  ]
77
77
  },
78
- "specSection": "7"
78
+ "specSection": "9.4"
79
79
  },
80
80
  {
81
81
  "name": "parses arrays of arrays within objects",
@@ -85,7 +85,7 @@
85
85
  { "matrix": [[1, 2], [3, 4]], "name": "grid" }
86
86
  ]
87
87
  },
88
- "specSection": "7"
88
+ "specSection": "9.2"
89
89
  },
90
90
  {
91
91
  "name": "parses nested arrays of primitives",
@@ -93,7 +93,7 @@
93
93
  "expected": {
94
94
  "pairs": [["a", "b"], ["c", "d"]]
95
95
  },
96
- "specSection": "7.3"
96
+ "specSection": "9.2"
97
97
  },
98
98
  {
99
99
  "name": "parses quoted strings and mixed lengths in nested arrays",
@@ -101,7 +101,7 @@
101
101
  "expected": {
102
102
  "pairs": [["a", "b"], ["c,d", "e:f", "true"]]
103
103
  },
104
- "specSection": "7.3"
104
+ "specSection": "9.2"
105
105
  },
106
106
  {
107
107
  "name": "parses empty inner arrays",
@@ -109,7 +109,7 @@
109
109
  "expected": {
110
110
  "pairs": [[], []]
111
111
  },
112
- "specSection": "7.3"
112
+ "specSection": "9.2"
113
113
  },
114
114
  {
115
115
  "name": "parses mixed-length inner arrays",
@@ -117,37 +117,37 @@
117
117
  "expected": {
118
118
  "pairs": [[1], [2, 3]]
119
119
  },
120
- "specSection": "7.3"
120
+ "specSection": "9.2"
121
121
  },
122
122
  {
123
123
  "name": "parses root arrays of primitives (inline)",
124
124
  "input": "[5]: x,y,\"true\",true,10",
125
125
  "expected": ["x", "y", "true", true, 10],
126
- "specSection": "7"
126
+ "specSection": "9.1"
127
127
  },
128
128
  {
129
129
  "name": "parses root arrays of uniform objects in tabular format",
130
130
  "input": "[2]{id}:\n 1\n 2",
131
131
  "expected": [{ "id": 1 }, { "id": 2 }],
132
- "specSection": "7.2"
132
+ "specSection": "9.3"
133
133
  },
134
134
  {
135
135
  "name": "parses root arrays of non-uniform objects in list format",
136
136
  "input": "[2]:\n - id: 1\n - id: 2\n name: Ada",
137
137
  "expected": [{ "id": 1 }, { "id": 2, "name": "Ada" }],
138
- "specSection": "7"
138
+ "specSection": "9.4"
139
139
  },
140
140
  {
141
141
  "name": "parses empty root arrays",
142
142
  "input": "[0]:",
143
143
  "expected": [],
144
- "specSection": "7"
144
+ "specSection": "9.1"
145
145
  },
146
146
  {
147
147
  "name": "parses root arrays of arrays",
148
148
  "input": "[2]:\n - [2]: 1,2\n - [0]:",
149
149
  "expected": [[1, 2], []],
150
- "specSection": "7.3"
150
+ "specSection": "9.2"
151
151
  },
152
152
  {
153
153
  "name": "parses complex mixed object with arrays and nested objects",
@@ -161,7 +161,7 @@
161
161
  "prefs": []
162
162
  }
163
163
  },
164
- "specSection": "6"
164
+ "specSection": "8"
165
165
  },
166
166
  {
167
167
  "name": "parses arrays mixing primitives, objects and strings (list format)",
@@ -169,7 +169,7 @@
169
169
  "expected": {
170
170
  "items": [1, { "a": 1 }, "text"]
171
171
  },
172
- "specSection": "7.3"
172
+ "specSection": "9.4"
173
173
  },
174
174
  {
175
175
  "name": "parses arrays mixing objects and arrays",
@@ -177,7 +177,7 @@
177
177
  "expected": {
178
178
  "items": [{ "a": 1 }, [1, 2]]
179
179
  },
180
- "specSection": "7.3"
180
+ "specSection": "9.4"
181
181
  },
182
182
  {
183
183
  "name": "parses quoted key with list array format",
@@ -188,7 +188,7 @@
188
188
  { "id": 2 }
189
189
  ]
190
190
  },
191
- "specSection": "7"
191
+ "specSection": "9.4"
192
192
  }
193
193
  ]
194
194
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.3",
2
+ "version": "1.4",
3
3
  "category": "decode",
4
4
  "description": "Primitive array decoding - inline arrays of strings, numbers, booleans, quoted strings",
5
5
  "tests": [
@@ -9,7 +9,7 @@
9
9
  "expected": {
10
10
  "tags": ["reading", "gaming", "coding"]
11
11
  },
12
- "specSection": "7.1"
12
+ "specSection": "9.1"
13
13
  },
14
14
  {
15
15
  "name": "parses number arrays inline",
@@ -17,7 +17,7 @@
17
17
  "expected": {
18
18
  "nums": [1, 2, 3]
19
19
  },
20
- "specSection": "7.1"
20
+ "specSection": "9.1"
21
21
  },
22
22
  {
23
23
  "name": "parses mixed primitive arrays inline",
@@ -25,7 +25,7 @@
25
25
  "expected": {
26
26
  "data": ["x", "y", true, 10]
27
27
  },
28
- "specSection": "7.1"
28
+ "specSection": "9.1"
29
29
  },
30
30
  {
31
31
  "name": "parses empty arrays",
@@ -33,7 +33,7 @@
33
33
  "expected": {
34
34
  "items": []
35
35
  },
36
- "specSection": "7.1"
36
+ "specSection": "9.1"
37
37
  },
38
38
  {
39
39
  "name": "parses single-item array with empty string",
@@ -41,7 +41,7 @@
41
41
  "expected": {
42
42
  "items": [""]
43
43
  },
44
- "specSection": "7.1"
44
+ "specSection": "9.1"
45
45
  },
46
46
  {
47
47
  "name": "parses multi-item array with empty string",
@@ -49,7 +49,7 @@
49
49
  "expected": {
50
50
  "items": ["a", "", "b"]
51
51
  },
52
- "specSection": "7.1"
52
+ "specSection": "9.1"
53
53
  },
54
54
  {
55
55
  "name": "parses whitespace-only strings in arrays",
@@ -57,7 +57,7 @@
57
57
  "expected": {
58
58
  "items": [" ", " "]
59
59
  },
60
- "specSection": "7.1"
60
+ "specSection": "9.1"
61
61
  },
62
62
  {
63
63
  "name": "parses strings with delimiters in arrays",
@@ -65,7 +65,7 @@
65
65
  "expected": {
66
66
  "items": ["a", "b,c", "d:e"]
67
67
  },
68
- "specSection": "7.1"
68
+ "specSection": "9.1"
69
69
  },
70
70
  {
71
71
  "name": "parses strings that look like primitives when quoted",
@@ -73,7 +73,7 @@
73
73
  "expected": {
74
74
  "items": ["x", "true", "42", "-3.14"]
75
75
  },
76
- "specSection": "7.1"
76
+ "specSection": "9.1"
77
77
  },
78
78
  {
79
79
  "name": "parses strings with structural tokens in arrays",
@@ -81,7 +81,7 @@
81
81
  "expected": {
82
82
  "items": ["[5]", "- item", "{key}"]
83
83
  },
84
- "specSection": "7.1"
84
+ "specSection": "9.1"
85
85
  },
86
86
  {
87
87
  "name": "parses quoted key with inline array",
@@ -89,7 +89,7 @@
89
89
  "expected": {
90
90
  "my-key": [1, 2, 3]
91
91
  },
92
- "specSection": "7.1"
92
+ "specSection": "9.1"
93
93
  },
94
94
  {
95
95
  "name": "parses quoted key containing brackets with inline array",
@@ -97,7 +97,7 @@
97
97
  "expected": {
98
98
  "key[test]": [1, 2, 3]
99
99
  },
100
- "specSection": "7.1"
100
+ "specSection": "9.1"
101
101
  },
102
102
  {
103
103
  "name": "parses quoted key with empty array",
@@ -105,7 +105,7 @@
105
105
  "expected": {
106
106
  "x-custom": []
107
107
  },
108
- "specSection": "7.1"
108
+ "specSection": "9.1"
109
109
  }
110
110
  ]
111
111
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.3",
2
+ "version": "1.4",
3
3
  "category": "decode",
4
4
  "description": "Tabular array decoding - parsing arrays of uniform objects with headers",
5
5
  "tests": [
@@ -12,7 +12,7 @@
12
12
  { "sku": "B2", "qty": 1, "price": 14.5 }
13
13
  ]
14
14
  },
15
- "specSection": "7.2"
15
+ "specSection": "9.3"
16
16
  },
17
17
  {
18
18
  "name": "parses nulls and quoted values in tabular rows",
@@ -23,7 +23,18 @@
23
23
  { "id": 2, "value": "test" }
24
24
  ]
25
25
  },
26
- "specSection": "7.2"
26
+ "specSection": "9.3"
27
+ },
28
+ {
29
+ "name": "parses quoted colon in tabular row as data",
30
+ "input": "items[2]{id,note}:\n 1,\"a:b\"\n 2,\"c:d\"",
31
+ "expected": {
32
+ "items": [
33
+ { "id": 1, "note": "a:b" },
34
+ { "id": 2, "note": "c:d" }
35
+ ]
36
+ },
37
+ "specSection": "9.3"
27
38
  },
28
39
  {
29
40
  "name": "parses quoted header keys in tabular arrays",
@@ -34,7 +45,7 @@
34
45
  { "order:id": 2, "full name": "Bob" }
35
46
  ]
36
47
  },
37
- "specSection": "7.2"
48
+ "specSection": "9.3"
38
49
  },
39
50
  {
40
51
  "name": "parses quoted key with tabular array format",
@@ -45,7 +56,19 @@
45
56
  { "id": 2, "name": "Bob" }
46
57
  ]
47
58
  },
48
- "specSection": "7.2"
59
+ "specSection": "9.3"
60
+ },
61
+ {
62
+ "name": "unquoted colon terminates tabular rows and starts key-value pair",
63
+ "input": "items[2]{id,name}:\n 1,Alice\n 2,Bob\ncount: 2",
64
+ "expected": {
65
+ "items": [
66
+ { "id": 1, "name": "Alice" },
67
+ { "id": 2, "name": "Bob" }
68
+ ],
69
+ "count": 2
70
+ },
71
+ "specSection": "9.3"
49
72
  }
50
73
  ]
51
74
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.3",
2
+ "version": "1.4",
3
3
  "category": "decode",
4
4
  "description": "Blank line handling - strict mode errors on blank lines inside arrays, accepts blank lines outside arrays",
5
5
  "tests": [
@@ -11,7 +11,7 @@
11
11
  "options": {
12
12
  "strict": true
13
13
  },
14
- "specSection": "9"
14
+ "specSection": "14.4"
15
15
  },
16
16
  {
17
17
  "name": "throws on blank line inside tabular array",
@@ -21,7 +21,7 @@
21
21
  "options": {
22
22
  "strict": true
23
23
  },
24
- "specSection": "9"
24
+ "specSection": "14.4"
25
25
  },
26
26
  {
27
27
  "name": "throws on multiple blank lines inside array",
@@ -31,7 +31,7 @@
31
31
  "options": {
32
32
  "strict": true
33
33
  },
34
- "specSection": "9"
34
+ "specSection": "14.4"
35
35
  },
36
36
  {
37
37
  "name": "throws on blank line with spaces inside array",
@@ -41,7 +41,7 @@
41
41
  "options": {
42
42
  "strict": true
43
43
  },
44
- "specSection": "9"
44
+ "specSection": "14.4"
45
45
  },
46
46
  {
47
47
  "name": "throws on blank line in nested list array",
@@ -51,7 +51,7 @@
51
51
  "options": {
52
52
  "strict": true
53
53
  },
54
- "specSection": "9"
54
+ "specSection": "14.4"
55
55
  },
56
56
  {
57
57
  "name": "accepts blank line between root-level fields",
@@ -63,7 +63,7 @@
63
63
  "options": {
64
64
  "strict": true
65
65
  },
66
- "specSection": "9"
66
+ "specSection": "12"
67
67
  },
68
68
  {
69
69
  "name": "accepts trailing newline at end of file",
@@ -74,7 +74,7 @@
74
74
  "options": {
75
75
  "strict": true
76
76
  },
77
- "specSection": "9"
77
+ "specSection": "12"
78
78
  },
79
79
  {
80
80
  "name": "accepts multiple trailing newlines",
@@ -85,7 +85,7 @@
85
85
  "options": {
86
86
  "strict": true
87
87
  },
88
- "specSection": "9"
88
+ "specSection": "12"
89
89
  },
90
90
  {
91
91
  "name": "accepts blank line after array ends",
@@ -97,7 +97,7 @@
97
97
  "options": {
98
98
  "strict": true
99
99
  },
100
- "specSection": "9"
100
+ "specSection": "12"
101
101
  },
102
102
  {
103
103
  "name": "accepts blank line between nested object fields",
@@ -111,7 +111,7 @@
111
111
  "options": {
112
112
  "strict": true
113
113
  },
114
- "specSection": "9"
114
+ "specSection": "12"
115
115
  },
116
116
  {
117
117
  "name": "ignores blank lines inside list array when strict=false",
@@ -122,7 +122,7 @@
122
122
  "options": {
123
123
  "strict": false
124
124
  },
125
- "specSection": "9"
125
+ "specSection": "12"
126
126
  },
127
127
  {
128
128
  "name": "ignores blank lines inside tabular array when strict=false",
@@ -136,7 +136,7 @@
136
136
  "options": {
137
137
  "strict": false
138
138
  },
139
- "specSection": "9"
139
+ "specSection": "12"
140
140
  },
141
141
  {
142
142
  "name": "ignores multiple blank lines in arrays when strict=false",
@@ -147,7 +147,7 @@
147
147
  "options": {
148
148
  "strict": false
149
149
  },
150
- "specSection": "9"
150
+ "specSection": "12"
151
151
  }
152
152
  ]
153
153
  }