@tehw0lf/n8n-nodes-toon 1.3.4 → 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/README.md CHANGED
@@ -318,11 +318,11 @@ Workflow: Fetch Data → JSON to TOON → Format Report → Send Email
318
318
 
319
319
  - **n8n version:** 0.200.0 or later
320
320
  - **Node.js:** 18.x or later
321
- - **TOON Specification:** v3.3
321
+ - **TOON Specification:** v4.1
322
322
 
323
323
  ## Specification Compliance
324
324
 
325
- This node implements **TOON Specification v3.3** with comprehensive coverage of all core features and major optional features.
325
+ This node implements **TOON Specification v4.1** in full: every normative requirement of Sections 1–16 for encoders and decoders, using the default options. Two additional convenience options fall outside the specification and are documented as [non-spec extensions](#non-spec-extensions) below.
326
326
 
327
327
  ### Implemented Features
328
328
 
@@ -331,17 +331,49 @@ This node implements **TOON Specification v3.3** with comprehensive coverage of
331
331
  - Indentation-based structure with configurable spacing
332
332
  - Array length declarations `[N]`
333
333
  - Tabular arrays for uniform objects `[N]{field1,field2}:`
334
+ - Nested field groups for uniform nested-object columns (§9.3): `orders[2]{id,customer{name,country},total}:`
335
+ - Keyed tabular form for objects of uniform objects (§9.5): `users[2:]{age,city}:`
336
+ - Hyphen syntax for objects as list items, including headers carried on the hyphen line (§10)
337
+ - Full-line comment lines, stripped by the decoder and never emitted by the encoder (§5.1)
334
338
  - All three delimiters: comma (default), tab, pipe
335
339
  - Deterministic string quoting and escaping
336
- - Strict mode validation with array count and width checking
340
+ - CRLF input, byte-order-mark removal, and trailing-space handling (§12)
341
+ - Strict mode validation per the §14 checklist (counts, row widths, header syntax, duplicate keys, indentation)
342
+
343
+ ### Non-Spec Extensions
344
+
345
+ ⚠️ These two options are **this node's own convenience features, not part of the TOON specification**. v4.1 treats dotted keys as ordinary literal keys with no structural meaning (§8), so output produced with key folding enabled decodes to dotted keys — not nested objects — in any conforming TOON implementation. Both default to `off`; leave them off for interoperable output.
337
346
 
338
- ✅ **Optional Features**
339
347
  - **Key Folding** (`keyFolding: "safe"`) - Collapse nested single-key objects into dotted paths (e.g., `{a: {b: {c: 1}}}` → `a.b.c: 1`)
340
348
  - **Path Expansion** (`expandPaths: "safe"`) - Expand dotted keys back into nested objects during decoding
341
349
 
342
- ### Not Implemented
350
+ ### Notes on Encoder Output
351
+
352
+ The encoder selects a form from each value's shape and position, as §1.4 requires, rather than by preference:
353
+
354
+ - Uniform arrays of objects use tabular form; objects of uniform objects use keyed tabular form.
355
+ - Primitive arrays are always inline (§9.1 defines no line-length threshold).
356
+ - Empty arrays are `key: []` in field position and `[]` at the root; the legacy `key[0]:` form is accepted on decode but never emitted.
357
+ - Field order follows the first object's key encounter order, so decoded elements of tabular and keyed tabular forms carry the header's field order (§2).
358
+
359
+ ### Documented Implementation Behavior
360
+
361
+ The specification requires implementations to document the following (§2, §3, §4, §13.2):
362
+
363
+ **Host-type normalization (§3).** Values are normalized to the JSON data model before encoding:
364
+
365
+ | Host value | Encoded as |
366
+ |---|---|
367
+ | `NaN`, `Infinity`, `-Infinity` | `null` |
368
+ | `undefined`, functions, symbols | `null` |
369
+ | Objects with a `toJSON()` method | the normalized result of `toJSON()`, applied recursively |
370
+ | `Date` | ISO 8601 string via the built-in `toJSON()` (quoted, since it contains colons) |
371
+
372
+ **Numeric domain and out-of-range policy (§4).** Numbers are IEEE-754 doubles, the JavaScript numeric domain. Decoded numeric tokens outside that domain return the nearest approximate double rather than erroring or returning a string; values beyond `Number.MAX_SAFE_INTEGER` may therefore lose precision on round-trip. Tokens are classified by the §4 number grammar, not by `Number()`, so `.5`, `1.`, `+5`, `0x10`, `Infinity`, and `NaN` all decode as strings.
373
+
374
+ **Object key order (§2).** Key order is preserved as encountered, except that tabular and keyed tabular forms reorder to the header's field order. One deviation is inherent to the JavaScript object model: **integer-like keys are hoisted** and ordered numerically ahead of string keys, so a document with keys `b`, `1`, `a` decodes to an object ordered `1`, `b`, `a`. Array order is always preserved.
343
375
 
344
- ❌ **Hyphen Syntax for List-Item Objects (§10)** - Optional YAML-style compact notation for objects in arrays. This is a purely cosmetic encoding optimization that doesn't affect functionality or data compatibility. Our implementation uses standard object indentation instead, which is equally spec-compliant and easier to maintain.
376
+ **Prototype keys (§15).** Decoded keys are installed with `Object.defineProperty`, so `__proto__`, `constructor`, and `prototype` become ordinary own data properties and decoding never mutates a prototype chain.
345
377
 
346
378
  ### Round-Trip Guarantee
347
379
 
@@ -463,7 +495,7 @@ See [`.github/workflows/security-scan.yml`](.github/workflows/security-scan.yml)
463
495
 
464
496
  ## Resources
465
497
 
466
- - **TOON Specification v3.3:** Official spec at [github.com/toon-format/spec](https://github.com/toon-format/spec) or see [SPEC.md](SPEC.md) in this repository
498
+ - **TOON Specification v4.1:** Official spec at [github.com/toon-format/spec](https://github.com/toon-format/spec) or see [SPEC.md](SPEC.md) in this repository
467
499
  - **n8n Documentation:** https://docs.n8n.io/
468
500
  - **Community Nodes Guide:** https://docs.n8n.io/integrations/community-nodes/
469
501
  - **GitHub Repository:** https://github.com/tehw0lf/n8n-nodes-toon
@@ -483,4 +515,4 @@ Contributions are welcome! Please open an issue or pull request on GitHub.
483
515
 
484
516
  ---
485
517
 
486
- **Note:** This node implements the [TOON Specification v3.3](https://github.com/toon-format/spec). See `SPEC.md` for complete format documentation or visit the official spec repository.
518
+ **Note:** This node implements the [TOON Specification v4.1](https://github.com/toon-format/spec). See `SPEC.md` for complete format documentation or visit the official spec repository.
@@ -1,20 +1,39 @@
1
1
  import type { DecoderOptions } from './types';
2
2
  export declare class ToonDecoder {
3
3
  private options;
4
+ private lines;
5
+ private pos;
6
+ private inHeaderSpan;
4
7
  constructor(options: DecoderOptions);
5
8
  decode(toonText: string): unknown;
6
9
  private parseLines;
7
- private determineRootForm;
8
- private parseArrayHeader;
9
- private parseDelimitedTokens;
10
- private parseArray;
11
- private parseTabularArray;
10
+ private withinHeaderSpan;
11
+ private checkBlankInSpan;
12
+ private depthOf;
13
+ private peek;
14
+ private parseRoot;
15
+ private checkNoTrailingContent;
16
+ private tryParseHeader;
12
17
  private parseObject;
13
- private isValidArrayHeader;
14
- private isInvalidArrayHeader;
15
- private findUnquotedColon;
16
- private findNextSiblingIndex;
17
- private parseTokenValue;
18
+ private assignKey;
19
+ private parseFieldLine;
20
+ private parseNestedScope;
21
+ private parseArrayBodyAfterHeader;
22
+ private parseArrayBody;
23
+ private parseArrayContent;
24
+ private parseTabularRows;
25
+ private materializeRow;
26
+ private parseKeyedTabular;
27
+ private parseKeyedTabularBody;
28
+ private parseListItems;
29
+ private isListItemLine;
30
+ private parseListItem;
31
+ private parseListItemRestFields;
32
+ private checkCount;
33
+ private checkWidth;
34
+ private decodeKeyToken;
35
+ private parseValueToken;
36
+ private findClosingQuote;
18
37
  private expandPaths;
19
38
  private isExpandable;
20
39
  private deepSet;