npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

toon-parser

v2.1.0

Published

Safe JSON <-> TOON encoder/decoder with strict validation.

Readme

toon-parser

CI Coverage npm version npm provenance License: MIT

Safe JSON ⇆ TOON encoder/decoder with strict validation and prototype-pollution guards.

Install

npm install toon-parser

Note: this package supports both ESM and CommonJS consumers (CJS builds are available as dist/index.cjs). The package requires Node >= 18 per engines in package.json.

New in 2.1.0

  • HTML/CSV/Log/URL Support: Dedicated parsers for common formats to leverage Toon's structure.

New in 2.0.0

  • XML Support: Convert XML strings directly to TOON with xmlToToon.
  • Date Support: Automatically converts Date objects to ISO strings.

Why this library?

  • Implements the TOON v2.1 spec features most useful for JSON round-trips: tabular arrays, inline primitive arrays, nested objects/arrays, deterministic quoting.
  • Hardened for untrusted input: prototype-pollution guards, max depth/length/node caps, strict length/width enforcement, and finite-number checks.
  • No dynamic code execution; parsing uses explicit token scanning and bounded state to resist resource exhaustion.

Quick start

import { jsonToToon, toonToJson } from 'toon-parser';

const data = {
  context: { task: 'hike planning', year: 2025 },
  friends: ['ana', 'luis', 'sam'],
  hikes: [
    { id: 1, name: 'Blue Lake', distanceKm: 7.5, wasSunny: true },
    { id: 2, name: 'Ridge Overlook', distanceKm: 9.2, wasSunny: false }
  ]
};

const toon = jsonToToon(data);
// TOON text with tabular hikes array and inline primitive friends array
console.log(toon);

const roundTrip = toonToJson(toon);
console.log(roundTrip); // back to the original JSON object

API

jsonToToon(value, options?) => string

Encodes a JSON-compatible value into TOON text.

xmlToToon(xml, options?) => string

Parses an XML string and converts it to TOON text. Accepts standard JsonToToonOptions plus an xmlOptions object passed to fast-xml-parser.

import { xmlToToon } from 'toon-parser';
const toon = xmlToToon('<user id="1">Alice</user>');
// user:
//   "#text": Alice
//   "@_id": 1

htmlToToon(html, options?) => string

Parses HTML string to Toon. Uses node-html-parser.

csvToToon(csv, options?) => string

Parses CSV string. Options:

  • delimiter (default ,)
  • hasHeader (default true)

urlToToon(urlOrQs, options?) => string

Parses URL query strings to Toon object. Expands dotted/bracket notation (e.g. user[name]).

logToToon(log, options?) => string

Parses logs. Options:

  • format: 'auto' | 'clf' | 'json'

csvToJson(csv, options?) => unknown[]

Lightweight CSV to JSON helper. Throws when row widths mismatch headers or when the delimiter is not a single character.

htmlToJson(html) => { children: ... }

Parses HTML into a simplified JSON tree. Performs a minimal tag-balance check and trims whitespace-only nodes. Not intended for arbitrary HTML with scripts/styles.

xmlToJson(xml, options?) => unknown

Validates XML before parsing; returns {} for empty input and throws on malformed XML.

[!WARNING] Security Note: While fast-xml-parser v5 is generally secure by default, overriding xmlOptions can alter security properties (e.g., enabling entity expansion). Only enable such features if you trust the source XML.

Options:

  • indent (number, default 2): spaces per indentation level.
  • delimiter (, | | | \t, default ,): delimiter for inline arrays and tabular rows.
  • sortKeys (boolean, default false): sort object keys alphabetically instead of preserving encounter order.
  • maxDepth (number, default 64): maximum nesting depth (objects + arrays).
  • maxArrayLength (number, default 50_000): maximum allowed array length.
  • maxTotalNodes (number, default 250_000): cap on processed fields/items to limit resource use.
  • disallowedKeys (string[], default ["__proto__", "constructor", "prototype"]): keys rejected to prevent prototype pollution.

Throws ToonError if limits are hit or input is not encodable.

toonToJson(text, options?) => unknown

Decodes TOON text back to JSON data.

Options:

  • strict (boolean, default true): enforce declared array lengths, tabular row widths, and indentation consistency.
  • Same security options as jsonToToon: maxDepth, maxArrayLength, maxTotalNodes, disallowedKeys.

Throws ToonError with line numbers when parsing fails or security limits are exceeded.

Usage examples

Control indentation and delimiter

const toon = jsonToToon(data, { indent: 4, delimiter: '|' });

Detect and emit tabular arrays

Uniform arrays of objects with primitive values are emitted in TOON’s table form automatically:

const toon = jsonToToon({ rows: [{ a: 1, b: 'x' }, { a: 2, b: 'y' }] });
/*
rows[2]{a,b}:
  1,x
  2,y
*/

Non-uniform arrays fall back to list form with - entries.

Handling unsafe keys

Prototype-polluting keys are rejected:

toonToJson('__proto__: 1'); // throws ToonError: Disallowed key "__proto__"

You can extend the blocklist:

toonToJson('danger: 1', { disallowedKeys: ['danger'] }); // throws

Enforcing strictness

Strict mode (default) ensures array lengths match headers and tabular rows match declared widths:

toonToJson('nums[2]: 1'); // throws ToonError: length mismatch

Disable strictness if you need best-effort parsing:

const result = toonToJson('nums[2]: 1', { strict: false });
// result: { nums: [1] }

Security limits

const opts = { maxDepth: 10, maxArrayLength: 1000, maxTotalNodes: 10_000 };
jsonToToon(bigValue, opts); // throws if exceeded
toonToJson(bigToonText, opts); // throws if exceeded

Error handling

All validation/parsing errors throw ToonError. When applicable, the error message includes a line number:

try {
  toonToJson('nums[2]: 1');
} catch (err) {
  if (err instanceof ToonError) {
    console.error(err.message); // "Line 1: Inline array length mismatch..."
  }
}

Design choices

  • Tabular detection follows the spec: all elements must be objects, share identical keys, and contain only primitives.
  • String quoting follows deterministic rules (quote numeric-looking strings, leading/trailing space, colon, delimiter, backslash, brackets, control chars, or leading hyphen).
  • Finite numbers only: NaN, Infinity, and -Infinity are rejected.
  • No implicit path expansion: dotted keys stay literal (e.g., a.b remains a single key).

Project status

This library targets TOON spec v2.1 core behaviors commonly needed for JSON round-trips. It prioritizes correctness and safety over permissiveness; loosen validation via strict: false only when you fully trust the input source.***