Compare commits

..

1 Commits

Author SHA1 Message Date
Phumrapee Limpianchop 1336074d43 fix(decode): prevent false array header detection for unquoted keys c… (#314)
CI / ci (push) Waiting to run
Deploy Docs / Deploy Docs (push) Waiting to run
* fix(decode): prevent false array header detection for unquoted keys containing brackets and colons

* test(decode): pin stream parity for an unquoted bracket-colon scalar

* chore(toon): bump `@toon-format/spec` to ^3.3.2

---------

Co-authored-by: Johann Schopplich <johann@schopplich.com>
2026-07-18 21:15:25 +02:00
5 changed files with 26 additions and 6 deletions
+1 -1
View File
@@ -38,6 +38,6 @@
"test": "vitest"
},
"devDependencies": {
"@toon-format/spec": "^3.3.0"
"@toon-format/spec": "^3.3.2"
}
}
+6
View File
@@ -41,6 +41,12 @@ export function parseArrayHeaderLine(
return
}
// A header key can't contain an unquoted colon, so this is a key-value line
const firstColonIndex = findUnquotedChar(content, COLON)
if (firstColonIndex !== -1 && firstColonIndex < bracketStart) {
return
}
const bracketEnd = findUnquotedChar(content, CLOSE_BRACKET, bracketStart)
if (bracketEnd === -1) {
return
+13
View File
@@ -236,6 +236,19 @@ describe('streaming decode', () => {
expect(events).toEqual(Array.from(decodeStreamSync(lines)))
})
it('keeps an unquoted bracket-colon scalar whole, matching decodeStreamSync', async () => {
const lines = ['key: foo [2]: bar']
const events = await collect(decodeStream(asyncLines(lines)))
expect(events).toEqual([
{ type: 'startObject' },
{ type: 'key', key: 'key' },
{ type: 'primitive', value: 'foo [2]: bar' },
{ type: 'endObject' },
])
expect(events).toEqual(Array.from(decodeStreamSync(lines)))
})
it('keeps a colon-bearing value such as a URL intact', async () => {
const lines = ['a: http://x']
const events = await collect(decodeStream(asyncLines(lines)))
+5 -5
View File
@@ -138,8 +138,8 @@ importers:
packages/toon:
devDependencies:
'@toon-format/spec':
specifier: ^3.3.0
version: 3.3.0
specifier: ^3.3.2
version: 3.3.2
packages:
@@ -1187,8 +1187,8 @@ packages:
peerDependencies:
eslint: ^9.0.0 || ^10.0.0
'@toon-format/spec@3.3.0':
resolution: {integrity: sha512-uRXoLvQU8ae79hG0/0zkjI2OIC3ULWyiDVuq3gLlh6uNduEJhAUHKx00KkIwZXnVefshk1uoSpRzMtc05mE0UQ==}
'@toon-format/spec@3.3.2':
resolution: {integrity: sha512-J2TaK9EQNPW5Hp9GhBavS3u7hE2AD/AqhV7UFYQ5quOnBgEAkUMJC6BwYxVyTRT4yy0rDQGyqK7tmMbwTZuStA==}
'@tybys/wasm-util@0.10.3':
resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==}
@@ -4569,7 +4569,7 @@ snapshots:
estraverse: 5.3.0
picomatch: 4.0.5
'@toon-format/spec@3.3.0': {}
'@toon-format/spec@3.3.2': {}
'@tybys/wasm-util@0.10.3':
dependencies:
+1
View File
@@ -5,6 +5,7 @@ minimumReleaseAgeExclude:
- '@ai-sdk/xai@3.0.108'
- ai@6.0.228
- tsdown@0.22.8
- '@toon-format/spec@3.3.2'
shellEmulator: true
trustPolicy: no-downgrade