Skip to content

fix(decode): prevent false array header detection for unquoted keys c…#314

Open
rayriffy wants to merge 1 commit into
toon-format:mainfrom
rayriffy:fix/decoding-bracket
Open

fix(decode): prevent false array header detection for unquoted keys c…#314
rayriffy wants to merge 1 commit into
toon-format:mainfrom
rayriffy:fix/decoding-bracket

Conversation

@rayriffy

Copy link
Copy Markdown

Linked Issue

Closes #

Description

This PR fixes a bug in the decoder where standard key-value pairs were mistakenly parsed as array headers.

Previously, if the parser encountered an unquoted key or value string containing both brackets and colons (e.g., display: "(Hello) [World] this (is:test)"), it would find the first [ and assume it was parsing an array header. When it subsequently found the : later in the string, it would throw a SyntaxError: Unexpected content ... between bracket segment and colon.

This fix updates parseArrayHeaderLine to check if a colon (:) appears before the first bracket ([). If it does, the parser correctly identifies it as a key-value separator and aborts the array header parsing.

To replicate:

import { encode, decode } from './src'

const jsonSource = {
  message: "Hello [world] this is a test:"
}

const payload = encode(jsonSource)
console.log("Encoded TOON payload:")
console.log(payload)

console.log("\nDecoded object:")
console.log(decode(payload))

returns following result

❯ bun ./repro.ts  
Encoded TOON payload:
message: "Hello [world] this is a test:"

Decoded object:
12 |   /** Raw source line (including indentation) where the error was detected, if known. */
13 |   readonly source?: string
14 | 
15 |   constructor(message: string, context?: { line?: number, source?: string, cause?: unknown }) {
16 |     const prefix = context?.line !== undefined ? `Line ${context.line}: ` : ''
17 |     super(prefix + message, context?.cause !== undefined ? { cause: context.cause } : undefined)
     ^
ToonDecodeError: Line 1: Unexpected content "this is a test" between bracket segment and colon
   line: 1,
 source: "message: \"Hello [world] this is a test:\"",

      at <parse> ()
      at new ToonDecodeError (/Users/rayriffy/Git/toon/packages/toon/src/decode/errors.ts:17:5)
      at withLine (/Users/rayriffy/Git/toon/packages/toon/src/decode/errors.ts:39:17)
      at decodeKeyValueSync (/Users/rayriffy/Git/toon/packages/toon/src/decode/decoders.ts:368:14)
      at decodeStreamSync (/Users/rayriffy/Git/toon/packages/toon/src/decode/decoders.ts:299:5)
      at buildValueFromEvents (/Users/rayriffy/Git/toon/packages/toon/src/decode/event-builder.ts:60:9)
      at decodeFromLines (/Users/rayriffy/Git/toon/packages/toon/src/index.ts:146:24)

79 |   const gapStart = Math.max(bracketEnd + 1, braceEnd)
80 |   const gapBeforeColon = content.slice(gapStart, colonIndex)
81 |   if (gapBeforeColon !== '') {
82 |     if (strict) {
83 |       const trimmedGap = gapBeforeColon.trim()
84 |       throw new SyntaxError(trimmedGap === ''
                     ^
SyntaxError: Unexpected content "this is a test" between bracket segment and colon
      at parseArrayHeaderLine (/Users/rayriffy/Git/toon/packages/toon/src/decode/parser.ts:84:17)
      at withLine (/Users/rayriffy/Git/toon/packages/toon/src/decode/errors.ts:33:12)
      at decodeKeyValueSync (/Users/rayriffy/Git/toon/packages/toon/src/decode/decoders.ts:217:23)
      at decodeStreamSync (/Users/rayriffy/Git/toon/packages/toon/src/decode/decoders.ts:179:10)
      at buildValueFromEvents (/Users/rayriffy/Git/toon/packages/toon/src/decode/event-builder.ts:22:14)
      at decodeFromLines (/Users/rayriffy/Git/toon/packages/toon/src/index.ts:146:24)
      at /Users/rayriffy/Git/toon/packages/toon/repro.ts:12:13

Bun v1.3.14 (macOS arm64)

following the fix

❯ bun ./repro.ts
Encoded TOON payload:
message: "Hello [world] this is a test:"

Decoded object:
{
  message: "Hello [world] this is a test:",
}

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactoring (no functional changes)
  • Performance improvement
  • Test coverage improvement

Changes Made

  • Added a check in parseArrayHeaderLine (packages/toon/src/decode/parser.ts) to ensure array header parsing is aborted if a key-value separator (:) appears before the first bracket ([).

SPEC Compliance

  • This PR implements/fixes spec compliance
  • Spec section(s) affected: Key-Value Pair Parsing
  • Spec version: 3.3

Testing

  • All existing tests pass
  • Added new tests for changes
  • Tests cover edge cases and spec compliance

Pre-submission Checklist

  • My code follows the project's coding standards
  • I have run code formatting/linting tools
  • I have added tests that prove my fix/feature works
  • New and existing tests pass locally
  • I have updated documentation if needed
  • I have reviewed the https://github.com/toon-format/spec for relevant sections

Breaking Changes

  • No breaking changes
  • Breaking changes (describe migration path below)

Additional Context

This issue was specifically encountered when attempting to parse TOON documents with titles containing translated bracket tags and source parentheses (e.g., doujinshi/gallery metadata).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant