Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,56 @@ All notable changes to the TOON specification will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [4.0] - 2026-01-15

### Added

- **XML Construct Support** (Β§22-28): TOON now natively supports XML constructs in a unified syntax:
- **Namespaces** (Β§23): Declare namespaces using `xmlns` and `xmlns:prefix` keys, consistent with XML namespace declaration syntax
- **Attributes** (Β§24): Represent XML attributes as nested key-value pairs within element objects
- **Repeated Elements** (Β§25): Use standard array syntax `key[N]:` for repeated XML elements, with support for interleaved elements using list form
- **Mixed Content** (Β§26): Represent mixed content (text and elements interleaved) using arrays where strings are text nodes and objects are elements
- **CDATA and Text Content** (Β§27): Handle CDATA sections, entity references, and whitespace normalization
- **XML Encoding/Decoding** (Β§28): Complete rules for converting between XML and TOON formats
- **Extended Syntax Features** (Β§4.1):
- Namespace declarations via `xmlns` and `xmlns:prefix` keys
- Empty field names in tabular headers to represent text content (Β§26.4)
- Array-based syntax for elements with both attributes and text content (Β§24.3)
- **XML-Related Terms** (Β§1.10): Added terminology for namespace prefixes, qualified names (QName), attributes, and mixed content
- **XML Data Model** (Β§2.2): Extended data model to support XML infoset constructs
- **XML Normalization** (Β§3.1): Rules for normalizing XML documents to TOON format
- **Extended Syntax Errors** (Β§14.6): Strict-mode validation for undefined namespace prefixes
- **XML Interoperability** (Β§17.4): Mapping guide for XML to TOON conversion
- **XML Examples** (Appendix H): Comprehensive examples demonstrating XML constructs in TOON
- **Encoder Options** (Β§13, Β§28.3):
- `preserveNamespaces` (boolean, default: true): Preserve namespace prefixes when encoding
- **Decoder Options** (Β§28.4):
- Attribute values are always coerced to strings when decoding to XML (numeric and boolean values converted to string representations)
- **Grammar Extensions** (Β§6): ABNF grammar updated to support namespace prefixes in keys (`ns-prefix` production)
- **Key Encoding** (Β§7.3): Keys may include namespace prefixes following pattern `^([A-Za-z_][A-Za-z0-9_]*:)?[A-Za-z_][A-Za-z0-9_.]*$`
- **Media Type Registration** (Β§18.1): Added optional `mode` parameter (`json` or `xml`) to `text/toon` media type (auto-detection applies if absent)

### Changed

- **Abstract** (Β§Abstract): Updated to reflect unified JSON and XML support
- **Purpose and Scope** (Β§Introduction): Expanded to include XML document serialization use cases
- **Data Model** (Β§2): Restructured into JSON Data Model (Β§2.1) and XML Data Model (Β§2.2)
- **Type Terms** (Β§1.6): Updated object and array definitions to support XML constructs
- **Conformance Checklists** (Β§13): Added XML-related requirements for encoders, decoders, and validators
- **Strict Mode Errors** (Β§14): Added extended syntax error validation (undefined namespace prefixes)
- **IANA Considerations** (Β§18): Updated media type registration to include XML mode

### Removed

- None (backward compatible with v3.0)

### Notes

- XML comments, processing instructions, and DOCTYPE declarations are not supported and are dropped during XML-to-TOON encoding
- The default namespace applies to unprefixed element names but NOT to unprefixed attribute names (per XML Namespaces specification)
- Built-in namespaces (`xml` and `xmlns`) are predefined and MUST NOT be redeclared
- All XML support is additive and does not break existing JSON functionality

## [3.0] - 2025-11-24

### Breaking Changes
Expand Down
1,059 changes: 1,034 additions & 25 deletions SPEC.md

Large diffs are not rendered by default.

49 changes: 49 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,34 @@ Complete, valid TOON files demonstrating core features:
- Decoder option `expandPaths="safe"` reconstructs nested structure
- Spec: Β§13.4 Path Expansion

### XML Constructs (v4.0+)

- [`valid/xml-namespaces.toon`](valid/xml-namespaces.toon) - Namespaced document
- Demonstrates `xmlns` and `xmlns:prefix` namespace declarations
- Shows qualified names with namespace prefixes
- Spec: Β§23 Namespaces

- [`valid/xml-attributes.toon`](valid/xml-attributes.toon) - XML attributes
- Demonstrates attributes as nested key-value pairs
- Shows attributes with and without namespace prefixes
- Shows elements with attributes and text content using arrays
- Spec: Β§24 Attributes

- [`valid/xml-repeated-elements.toon`](valid/xml-repeated-elements.toon) - Interleaved repeated elements
- Demonstrates interleaved elements of different types (XML-specific feature)
- Shows how order is preserved when elements are mixed (not representable in JSON)
- Spec: Β§25.4 Preserving Order with Interleaved Elements

- [`valid/xml-mixed-content.toon`](valid/xml-mixed-content.toon) - Mixed content
- Demonstrates mixed content with text nodes and elements
- Shows arrays where strings are text nodes and objects are elements
- Spec: Β§26 Mixed Content

- [`valid/xml-xhtml.toon`](valid/xml-xhtml.toon) - XHTML example
- Complete XHTML document with namespaces and attributes
- Demonstrates complex XML document structure
- Spec: Β§22-28 XML Constructs

## Invalid Examples

Examples that intentionally violate TOON syntax rules:
Expand Down Expand Up @@ -119,6 +147,11 @@ Examples that intentionally violate TOON syntax rules:
- MUST error in strict mode
- Spec: Β§6 Header Syntax (delimiter equality requirement)

- [`invalid/xml-undefined-namespace.toon`](invalid/xml-undefined-namespace.toon) - Undefined namespace prefix (v4.0+)
- Uses prefix `ex` without corresponding `xmlns:ex` declaration
- MUST error in strict mode
- Spec: Β§14.6 Extended Syntax Errors, Β§23 Namespaces

## Conversions

Side-by-side JSON ↔ TOON examples showing equivalent representations:
Expand All @@ -140,6 +173,22 @@ Side-by-side JSON ↔ TOON examples showing equivalent representations:
- Shows practical use case for serializing API responses while preserving deterministic structure
- `expandPaths="safe"` is not required for this file (no folded keys)

- [`conversions/xml-catalog.json`](conversions/xml-catalog.json) + [`conversions/xml-catalog.toon`](conversions/xml-catalog.toon) (v4.0+)
- Library catalog with repeated book elements
- Demonstrates tabular format for uniform repeated XML elements
- Shows attributes and text content in XML structure
- Spec: Β§25 Repeated Elements

- [`conversions/xml-rss.json`](conversions/xml-rss.json) + [`conversions/xml-rss.toon`](conversions/xml-rss.toon) (v4.0+)
- RSS feed example with attributes and repeated items
- Demonstrates tabular format for RSS item arrays
- Spec: Β§25 Repeated Elements

- [`conversions/xml-interleaved.json`](conversions/xml-interleaved.json) + [`conversions/xml-interleaved.toon`](conversions/xml-interleaved.toon) (v4.0+)
- Interleaved repeated elements of different types
- Demonstrates list form for preserving element order
- Spec: Β§25.4 Preserving Order with Interleaved Elements

## Using These Examples

These examples are useful for:
Expand Down
21 changes: 21 additions & 0 deletions examples/conversions/xml-catalog.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"library": {
"book": [
{
"id": 1,
"title": "1984",
"author": "George Orwell"
},
{
"id": 2,
"title": "Brave New World",
"author": "Aldous Huxley"
},
{
"id": 3,
"title": "Fahrenheit 451",
"author": "Ray Bradbury"
}
]
}
}
5 changes: 5 additions & 0 deletions examples/conversions/xml-catalog.toon
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
library:
book[3]{id,title,author}:
1,1984,George Orwell
2,Brave New World,Aldous Huxley
3,Fahrenheit 451,Ray Bradbury
19 changes: 19 additions & 0 deletions examples/conversions/xml-interleaved.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"root": [
{
"a": "first"
},
{
"b": "second"
},
{
"a": "third"
},
{
"c": "fourth"
},
{
"b": "fifth"
}
]
}
6 changes: 6 additions & 0 deletions examples/conversions/xml-interleaved.toon
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
root:
- a: first
- b: second
- a: third
- c: fourth
- b: fifth
19 changes: 19 additions & 0 deletions examples/conversions/xml-rss.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"rss": {
"version": "2.0",
"channel": {
"title": "Example Feed",
"link": "http://example.com",
"item": [
{
"title": "First Post",
"link": "http://example.com/1"
},
{
"title": "Second Post",
"link": "http://example.com/2"
}
]
}
}
}
8 changes: 8 additions & 0 deletions examples/conversions/xml-rss.toon
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
rss:
version: 2.0
channel:
title: Example Feed
link: "http://example.com"
item[2]{title,link}:
First Post,"http://example.com/1"
Second Post,"http://example.com/2"
2 changes: 2 additions & 0 deletions examples/invalid/xml-undefined-namespace.toon
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
root:
ex:child: value
10 changes: 10 additions & 0 deletions examples/valid/xml-attributes.toon
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
element:
id: 123
class: container primary
"data-value": "quoted: value"

a:
- xmlns:xlink: "http://www.w3.org/1999/xlink"
- xlink:href: "http://example.com"
- xlink:title: Example Link
- Click here
14 changes: 14 additions & 0 deletions examples/valid/xml-mixed-content.toon
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
article:
p[2]:
- [5]:
- "This is "
- em: emphasized
- " and "
- strong: bold
- " text."
- [3]:
- "Another "
- a:
- href: "http://example.com"
- link
- " here."
9 changes: 9 additions & 0 deletions examples/valid/xml-namespaces.toon
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
soap:Envelope:
xmlns:soap: "http://schemas.xmlsoap.org/soap/envelope/"
xmlns:m: "http://example.com/messages"
soap:Header:
m:Auth:
token: abc123
soap:Body:
m:GetUser:
m:id: 42
5 changes: 5 additions & 0 deletions examples/valid/xml-repeated-elements.toon
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
root:
- a: first
- b: second
- a: third
- b: fourth
16 changes: 16 additions & 0 deletions examples/valid/xml-xhtml.toon
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
html:
xmlns: "http://www.w3.org/1999/xhtml"
lang: en
head:
title: Page Title
meta:
charset: UTF-8
body:
class: main
h1: Hello World
p[3]:
- "Welcome to "
- a:
- href: /
- our site
- .
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@toon-format/spec",
"type": "module",
"version": "3.0.1",
"version": "4.0.0",
"packageManager": "pnpm@10.19.0",
"description": "Official specification for Token-Oriented Object Notation (TOON)",
"author": "Johann Schopplich <hello@johannschopplich.com>",
Expand Down
8 changes: 6 additions & 2 deletions tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ tests/
β”‚ β”‚ β”œβ”€β”€ delimiters.json
β”‚ β”‚ β”œβ”€β”€ whitespace.json
β”‚ β”‚ β”œβ”€β”€ options.json
β”‚ β”‚ └── key-folding.json
β”‚ β”‚ β”œβ”€β”€ key-folding.json
β”‚ β”‚ └── xml-constructs.json
β”‚ └── decode/ # Decoding tests (TOON β†’ JSON)
β”‚ β”œβ”€β”€ primitives.json
β”‚ β”œβ”€β”€ numbers.json
Expand All @@ -41,7 +42,8 @@ tests/
β”‚ β”œβ”€β”€ validation-errors.json
β”‚ β”œβ”€β”€ indentation-errors.json
β”‚ β”œβ”€β”€ blank-lines.json
β”‚ └── path-expansion.json
β”‚ β”œβ”€β”€ path-expansion.json
β”‚ └── xml-constructs.json
└── README.md # This file
```

Expand Down Expand Up @@ -160,6 +162,7 @@ The fixture format is language-agnostic JSON, so you can load and iterate it usi
| `delimiters.json` | Tab and pipe delimiter options | Β§11 |
| `whitespace.json` | Formatting invariants and indentation | Β§12 |
| `key-folding.json` | Key folding with safe mode, depth control, collision avoidance | Β§13.4 |
| `xml-constructs.json` | XML constructs: namespaces, attributes, repeated elements, mixed content | Β§22-28 |

### Decoding Tests (`fixtures/decode/`)

Expand All @@ -178,6 +181,7 @@ The fixture format is language-agnostic JSON, so you can load and iterate it usi
| `indentation-errors.json` | Strict mode indentation validation | Β§14.3, Β§12 |
| `blank-lines.json` | Blank line handling in arrays | Β§14.4, Β§12 |
| `path-expansion.json` | Path expansion with safe mode, deep merge, strict-mode conflicts | Β§13.4, Β§14.5 |
| `xml-constructs.json` | XML constructs: namespaces, attributes, repeated elements, mixed content, undefined prefix errors | Β§22-28, Β§14.6 |

## Validating Fixtures

Expand Down
Loading