@bgotink/kdl

This package contains a parser and stringifier for the KDL Document Language, a node-based, human-friendly configuration and serialization format.

The parser in this package focuses on parsing documents in a way that allows for format-preserving modifications. This is most useful when working with KDL files maintained by humans.

Try it out

Version 0.4.0-next.0 of the @bgotink/kdl package is available on this website via the console of your browser:

console.log(kdl.parse("node arg").findNodeByName("node").getArgument(0));

Install

yarn add @bgotink/kdl
# or
npm install @bgotink/kdl
# or
pnpm add @bgotink/kdl
# or ...

Usage

The examples below assume a Node.js environment. The @bgotink/kdl package works in any javascript runtime, including browsers, as long as it supports relatively modern browser standards. If you're trying to run these samples in a non-Node.js runtime, replace the import for assert with something equivalent in your runtime.

import {parse, format} from "@bgotink/kdl";
import assert from "node:assert/strict";

const doc = parse(String.raw`
	node "value" #"other value"# 2.0 4 #false \
			#null -0 {
		child; "child too"
	}
`);

doc.nodes[0].children.nodes[0].entries.push(
	parse(
		String.raw`/-lorem="ipsum" \
			dolor=#true`,
		{as: "entry"},
	),
);

assert.equal(
	format(doc),
	String.raw`
	node "value" #"other value"# 2.0 4 #false \
			#null -0 {
		child /-lorem="ipsum" \
			dolor=#true; "child too"
	}
`,
);

JSON-in-KDL (JiK)

This package exports function from @bgotink/kdl/json to parse and stringify KDL documents as JSON-in-KDL (JiK) 4.0.0. For information on the format, see the JiK 4.0.0 specification.

import {parse} from "@bgotink/kdl/json";
import assert from "node:assert/strict";

assert.deepEqual(
	parse(
		String.raw`
			- {
				prop #false
				otherProp {
					- 0
					- 2
					- 4
				}
			}
		`,
	),
	{
		prop: false,
		otherProp: [0, 2, 4],
	},
);

There are four functions:

  • parse and stringify turn text into the encoded JSON value and back. These functions are useful for encoding/decoding entire JiK files.
  • toJson and fromJson turn KDL nodes into the encoded JSON value and back. These functions give more fine-grained control over the output, and can be used for e.g. encoding/decoding a JiK node embedded in a KDL document.

(De)Serialization

The package contains utilities for (de)serialization in @bgotink/kdl/dessert.

import {parse} from "@bgotink/kdl/dessert";
import assert from "node:assert/strict";

assert.deepEqual(
	parse(
		String.raw`
			name "my-package"
			
			dependency "@bgotink/kdl" range="^0.2.0"
			dependency "prettier" range="^3" dev=#true
		`,
		(ctx) => {
			const dependencies = {};
			const devDependencies = {};

			const name = ctx.child.single.required("name", (ctx) =>
				ctx.argument.required("string"),
			);

			for (const dependency of ctx.children("dependency", (ctx) => ({
				name: ctx.argument.required("string"),
				range: ctx.property("range", "string") ?? "*",
				dev: ctx.property("dev", "boolean") ?? false,
			}))) {
				(dependency.dev ? devDependencies : dependencies)[dependency.name] =
					dependency.range;
			}

			return {name, dependencies, devDependencies};
		},
	),
	{
		name: "my-package",
		dependencies: {
			"@bgotink/kdl": "^0.2.0",
		},
		devDependencies: {
			prettier: "^3",
		},
	},
);

KDL v1

The package exports two functions from @bgotink/kdl/v1-compat to support documents written in KDL v1:

  • parse parses a KDL v1 document and transforms all linked formatting information to turn it into a valid KDL v2 document. If the resulting document is passed to format(), the resulting string will be the same document but in KDL v2 syntax. It will include all comments and formatting applied by the original document's author.
  • parseCompat parses a document that's either KDL v2 or KDL v1 and returns a valid KDL v2 document. This is a helper function that combines the regular parse function with the v1-compat parse function into a single function that supports both formats.

Quirks

This package turns KDL documents into JavaScript objects and vice versa. It is therefore limited by the JavaScript language.

Properties

Multiple properties with the same name are allowed. All duplicated will be preserved, meaning those documents will correctly round-trip. When using node.getProperty()/node.getProperties()/node.getPropertyEntry(), the last property with that name's value will be returned, effectively shadowing any earlier duplicates. Using node.getPropertyEntries()/node.entries does expose the shadowed duplicates, leaving it up to the caller to handle these. Passing the node through clearFormat() removes these shadowed duplicates.

Numbers

JavaScript stores all numbers as 64-bit IEEE 754 floating point numbers. This limits what integer values can be used safely. These limits are lower than you might expect if you're used to working in environments that have a separate 64-bit integer data type.

The original representation of parsed numbers is retained, unless clearFormat is called on the value or any entry/node/document containing the value.

License

This package is licensed under the MIT license, which can be found in LICENSE.md.

The test suite at test/upstream is part of the KDL specification and is available under the Creative Commons Attribution-ShareAlike 4.0 International License.

Parsing KDL

The parse(text[, options]) function parses a KDL document. The text can be passed in as string, Node.js buffer, TypedArray, ArrayBuffer, or DataView.

You can pass the as option to make the function parse something different from a KDL document:

import {parse, Document, Node} from "@bgotink/kdl";

assert(
	parse(
		String.raw`
			node Lorem Ipsum
		`,
	) instanceof Document,
);

assert(
	parse(
		String.raw`
			node Lorem Ipsum
		`,
		{as: "node"},
	) instanceof Node,
);

Errors

The parse function throws InvalidKdlErrors when an error occurs. The parser tries to recover from many errors so it can provide as much feedback as possible in a single run. This greatly helps when using the parser to provide feedback to the human author of a KDL document, as you can provide them with multiple mistakes in a single go instaed of showing only the first error every single time.

A single InvalidKdlError object might describe multiple actual errors in the document. The getDetails() method returns an iterator that yields every KDL error contained within the error. If the error doesn't have any more details, the getDetails() iterator only yields the error itself..

Locations

Setting the storeLocations option to true makes location information available in the getLocation function.

Two ways of tracking columns

By default the columns in error messages and in getLocation results are tracked by code point. This means that characters that span multiple code points will move the column forward quite a bit. For example: 😅 is a single code point but 🏳️‍🌈 consists of four code points.

Setting the graphemeLocations option to true instead track columns by grapheme. A grapheme is what we humans perceive as a single character. The pride flag that consists of four code points is a single grapheme.

Tracking by code points is the default for the simple reason that it seems to match how columns are tracked in editors like VS Code or Zed. There's also a 6.5x speed difference between the two methods, but even with graphemeLocations enabled the parser succeeds in parsing thousands of documents per second.

Quirks

This package turns KDL documents into JavaScript objects and vice versa. It is therefore limited by the JavaScript language.

Properties

Multiple properties with the same name are allowed. All duplicated will be preserved, meaning those documents will correctly round-trip. When using node.getProperty()/node.getProperties()/node.getPropertyEntry(), the last property with that name's value will be returned, effectively shadowing any earlier duplicates. Using node.getPropertyEntries()/node.entries does expose the shadowed duplicates, leaving it up to the caller to handle these. Passing the node through clearFormat() removes these shadowed duplicates.

Numbers

JavaScript stores all numbers as 64-bit IEEE 754 floating point numbers. This limits what integer values can be used safely. These limits are lower than you might expect if you're used to working in environments that have a separate 64-bit integer data type.

The original representation of parsed numbers is retained, unless clearFormat is called on the value or any entry/node/document containing the value.

Formatting KDL

The format(value) function turns a document, node, entry, identifier, value, or tag into a KDL string representing that value.

The KDL DOM classes contain not just their values, but also any information on whitespace and comments required to format the element. This makes this package good at manipulating KDL files maintained by humans, as it supports making modifications with as few changes to the file as possible.

import {parse, format} from "@bgotink/kdl";

const doc = parse(
	String.raw`
		node "value" #"other value"# 2.0 4 #false \
				#null -0 {
			child; "child too"
		}
	`,
);

doc.nodes[0].children.nodes[0].entries.push(
	parse(
		String.raw`/-lorem="ipsum" \
				dolor=#true`,
		{as: "entry"},
	),
);

assert.equal(
	format(doc),
	String.raw`
		node "value" #"other value"# 2.0 4 #false \
				#null -0 {
			child /-lorem="ipsum" \
				dolor=#true; "child too"
		}
	`,
);

All KDL DOM elements that wrap simple values—i.e. Value, Identifier, and Tag—have an optional representation property that declares how its value is to be formatted. This property is set for all parsed elements and ensures that formatting the element results in as few changes as possible. Take care when changing these values, as the representation is not validated when formatting the element.

// Do not do this!
import {Entry, Identifier, Node, Value, format} from "@bgotink/kdl";

const node = new Node(new Identifier("real_name"));
node.name.representation = "fake_name";

const entry = new Entry(new Value(42), new Identifier("property"));
entry.name.representation = "something_else";
entry.value.representation = "false";

assert.equal(format(node), "fake_name something_else=false");

Instances of Document, Node, Entry, and Tag, store information about whitespace. Just like the representation, these fields are not validated when formatting the DOM elements.

Reset

The clearFormat(value) function removes any and all formatting from a document, node, entry, value, identifier, or tag.

JSON-in-KDL

The @bgotink/kdl/json package export exposes functions to handle JSON-in-KDL, aka JiK. There are two families of functions:

The parse and stringify functions are built to be a drop-in replacement for the JSON.parse and JSON.stringify functions. These functions work well for managing entire JiK files.

The toJson and fromJson functions allow for more fine-grained control. There are extra options that support some none-standard JiK behaviour. Most importantly they work with a KDL Node, which makes these functions support JiK nodes embedded into regular a KDL document.

All of these functions throw an InvalidJsonInKdlError if they encounter invalid JiK content.

Compabitility with KDL v1

The parse function in this package only supports KDL v2 documents. If your program wants to be compatible with KDL v1 as well, this package exposes an extra entry point @bgotink/kdl/v1-compat.

This entry point exposes two functions: parse and parseCompat. Both functions return a Document that produces valid KDL v2 text, but they differ in what they accept.

  • parse parses a KDL v1 text
  • parseCocmpat parses KDL text that's either valid KDL v2 or KDL v1

The parseCompat function first tries to parse the text as a KDL v2 document. If that fails, it tries to parse the text as a KDL v1 document. If both parsers fail, the function throws an AggregateError that contains all errors. The function does not look for a /- kdl-version <version> hint in the text.

(De)Serialization Tools

The @bgotink/kdl/dessert package export exposes tools for helping with (de)serializing KDL nodes/documents into a more useful JavaScript structure. The basic tools don't enforce any specific programming paradigm, e.g. enforcing the use of class, but some of the higher level tools exposed do take a more opinionated approach.

The name "dessert" comes from DESerialization & SERialization Tools. Also, who doesn't like dessert?

Deserialization

There is one main deserialization function: deserialize takes a KDL node or document and a deserializer and runs the given node or document through the deserializer. A second function parse takes a KDL document text, parses it into a KDL document and then runs it through deserialize.

There are three types of deserializer:

  • A function that takes a deserialization context and returns the deserialized value,
  • An object with a deserialize function on it that takes a deserialization context and returns the deserialized value, or
  • An object with a deserializeFromNode function on it that takes a KDL node and returns the deserialized value.

A deserialization context is an object with a bunch of functions on it to help extract arguments, properties, and children from the node.

Here's an example of a deserializer using functions:

import type {DeserializationContext} from "@bgotink/kdl/dessert";

type Tree = {value: number; left?: Tree; right?: Tree};

function treeDeserializer(ctx: DeserializationContext): Tree {
	return {
		value: ctx.argument.required("number"),
		left: ctx.child.single("left", treeDeserializer),
		right: ctx.child.single("right", treeDeserializer),
	};
}

export function readTree(node: Node): Tree {
	return deserialize(node, treeDeserializer);
}

and here's that same deserializer as a class:

import type {DeserializationContext} from "@bgotink/kdl/dessert";

class Tree {
	static deserialize(ctx: DeserializationContext): Tree {
		return new Tree(
			ctx.argument.required("number"),
			ctx.child.single("left", Tree),
			ctx.child.single("right", Tree),
		);
	}

	constructor(
		readonly value: number,
		readonly left?: Tree,
		readonly right?: Tree,
	) {}
}

export function readTree(node: Node): Tree {
	return deserialize(node, Tree);
}

Both of these deserializers effortlessly turn the following KDL node into a tree structure

root 10 {
	left 5 {
		left 3
		right 2
	}
	right 5 {
		left 1
		right 4 {
			left 1
			right 3 {
				left 2
				right 1
			}
		}
	}
}

Serialization

There is one serialization function: serialize takes a node name and a serializer and creates a node with that name and runs it through the serializer. Serializers can be parameterized, allowing for serializers to be shared across multiple values.

There are three types of serializer:

  • A function that takes a serialization context,
  • An object with a serialize function on it that takes a serialization context, or
  • An object with a serializeToNode function on it that returns a KDL node.

All three of these can be parameterized.

Here's an example of a parameterized serializer for the Tree type from either of the two deserialization examples above.

function treeSerializer(ctx: SerializationContext, tree: Tree) {
	ctx.argument(tree.value);

	if (tree.left) {
		ctx.child("left", treeSerializer, tree.left);
	}
	if (tree.right) {
		ctx.child("right", treeSerializer, tree.right);
	}
}

export function writeTree(tree: Tree): Node {
	return serialize("root", treeDeserializer, tree);
}

or we could extend the Tree class from the class-based sample with a serialize method:

class Tree {
	// ... see the Tree class in the deserialize example

	serialize(ctx: SerializationContext) {
		ctx.argument(this.value);

		if (this.left) {
			ctx.child("left", this.left);
		}
		if (this.right) {
			ctx.child("right", this.right);
		}
	}
}

export function writeTree(tree: Tree): Node {
	return serialize("root", tree);
}

Preserving comments and formatting

Programs that make modifications to human-edited files might want to preserve comments and formatting when making these changes. The @bgotink/kdl/dessert API supports this by allowing programs to link an object being serialized using a serialization context with its deserialization context. This process takes two steps:

  1. Store the DeserializationContext somewhere
  2. Pass call source on the SerializationContext at the beginning of the serialize function and pass it the stored DeserializationContext

It is important this call to source happens before you make any other calls to any function on the SerializationContext. Calling it later in the serializer will cause an error.

Here's an example of what this looks like in the class-based Tree example from above:

class Tree {
	// ... see the Tree class in the deserialize and serialize examples

	// We store the DeserializationContext
	static deserialize(ctx: DeserializationContxt) {
		const tree = new Tree(
			ctx.argument.required("number"),
			ctx.child.single("left", Tree),
			ctx.child.single("right", Tree),
		);
		tree.#deserializationCtx = ctx;
		return tree;
	}

	#deserializationCtx?: DeserializationContxt;

	// ...

	serialize(ctx: SerializationContext) {
		ctx.source(this.#deserializationCtx);

		// keep the rest of the original serialize function here
	}
}

If we now pass in this tree

root 10 {
	left 5 { /- left 0; right 5 }
	right 5 { left 1; right 4 }
}

and run

function modify(node: Node): Node {
	const tree = readTree(node); // see deserialization example for this functino

	tree.right.left.value++;
	tree.right.value++;
	tree.value++;

	return writeTree(tree);
}

the resulting node will be

root 11 {
	left 5 { /- left 0; right 5 }
	right 6 { left 2; right 4 }
}

instead of creating a fresh KDL document with default formatting, which would look more like this:

root 11 {
	left 5 {
		right 5
	}
	right 6 {
		left 2
		right 4
	}
}

Deserializers and serializers that implement the deserializeFromNode and serializeToNode respectively are responsible for copying any comments and formatting from the original node being deserialized to the final serialized node.

index

Classes

Interfaces

BOM

Defined in: src/model/whitespace.d.ts:8

A Byte-Order Mark at the start of a document

Properties

text

text: string

Defined in: src/model/whitespace.d.ts:17

The BOM text, i.e. '\ufeff'.


type

type: "bom"

Defined in: src/model/whitespace.d.ts:12

A property to differentiate the different types of whitespace


EscLine

Defined in: src/model/whitespace.d.ts:55

An escaped newline

Properties

text

text: string

Defined in: src/model/whitespace.d.ts:64

The escaped newline


type

type: "line-escape"

Defined in: src/model/whitespace.d.ts:59

A property to differentiate the different types of whitespace


InlineWhitespace

Defined in: src/model/whitespace.d.ts:23

Regular plain old whitespace characters

Properties

text

text: string

Defined in: src/model/whitespace.d.ts:32

The whitespace's text


type

type: "space"

Defined in: src/model/whitespace.d.ts:27

A property to differentiate the different types of whitespace


Location

Defined in: src/parser/token.d.ts:6

A location in the source text

Properties

column

column: number

Defined in: src/parser/token.d.ts:24

Column in the line

The first character of the line is column number 1.


line

line: number

Defined in: src/parser/token.d.ts:18

Line number in the source text

The first line has number 1.


offset

offset: number

Defined in: src/parser/token.d.ts:12

Index of this location in the source text

The first character in the source text has offset 0.


MultilineComment

Defined in: src/model/whitespace.d.ts:70

A multiline comment

Properties

text

text: string

Defined in: src/model/whitespace.d.ts:79

The comment text, including the comment tokens themselves


type

type: "multiline"

Defined in: src/model/whitespace.d.ts:74

A property to differentiate the different types of whitespace


Newline

Defined in: src/model/whitespace.d.ts:40

A single newline

Note a newline can consist of multiple characters: \r\n is a single newline.

Properties

text

text: string

Defined in: src/model/whitespace.d.ts:49

The newline


type

type: "newline"

Defined in: src/model/whitespace.d.ts:44

A property to differentiate the different types of whitespace


SingleLineComment

Defined in: src/model/whitespace.d.ts:85

A single-line comment

Properties

text

text: string

Defined in: src/model/whitespace.d.ts:94

The comment's text, starting at the // and ending with a newline unless the comment ended at the end of the file


type

type: "singleline"

Defined in: src/model/whitespace.d.ts:89

A property to differentiate the different types of whitespace


SlashDashInDocument

Defined in: src/model/whitespace.d.ts:137

A slashdash comment in a document, i.e. a slashdash commented node

Properties

preface

preface: NodeSpace[]

Defined in: src/model/whitespace.d.ts:146

Any whitespace between the slashdash token and the value


type

type: "slashdash"

Defined in: src/model/whitespace.d.ts:141

A property to differentiate the different types of whitespace


value

value: Node

Defined in: src/model/whitespace.d.ts:151

The escaped value


SlashDashInNode

Defined in: src/model/whitespace.d.ts:112

A slashdash comment inside a node, i.e. a slashdash commented argument, property, or child block

Properties

preface

preface: NodeSpace[]

Defined in: src/model/whitespace.d.ts:121

Any whitespace between the slashdash token and the value


type

type: "slashdash"

Defined in: src/model/whitespace.d.ts:116

A property to differentiate the different types of whitespace


value

value: Entry | Document

Defined in: src/model/whitespace.d.ts:126

The escaped value


StoredLocation

Defined in: src/locations.js:5

Stored location of a Document, Entry, Identifier, Node, Tag, or Value.

Properties

end

end: Location

Defined in: src/locations.js:9

The location after the last character


start

start: Location

Defined in: src/locations.js:8

The location of the first character


Token

Defined in: src/parser/token.d.ts:30

A single token in the KDL text

Properties

end

end: Location

Defined in: src/parser/token.d.ts:60

The location after the last character of this token


start

start: Location

Defined in: src/parser/token.d.ts:55

The location of the first character of this token


text

text: string

Defined in: src/parser/token.d.ts:50

The text of this token

This could be computed if you have access to the source text using

sourceText.slice(token.start.offset, token.end.offset)

Type Aliases

LineSpace

LineSpace: BOM | Newline | WS | SingleLineComment

Defined in: src/model/whitespace.d.ts:107

A single plain whitespace item in a document, i.e. before/after/between nodes


NodeSpace

NodeSpace: EscLine | WS

Defined in: src/model/whitespace.d.ts:102

A single plain whitespace item inside of a node, e.g. between two arguments in a node.


Primitive

Primitive<>: string | number | boolean | null

Defined in: src/model/value.js:4

A primitive is any type that can be represented as an argument or property

Type Parameters

Type Parameter

WhitespaceInDocument

WhitespaceInDocument: (LineSpace | SlashDashInDocument)[]

Defined in: src/model/whitespace.d.ts:157

Whitespace in a document, i.e. before/after/between nodes


WhitespaceInNode

WhitespaceInNode: (NodeSpace | SlashDashInNode)[]

Defined in: src/model/whitespace.d.ts:132

Whitespace inside of a node, e.g. between two arguments in a node.

Functions

clearFormat()

clearFormat<T>(v): T

Defined in: src/clear-format.js:123

Type Parameters

Type ParameterDescription
T extends Identifier | Tag | Value | Entry | Node | Document

Parameters

ParameterTypeDescription
vT

Returns

T


format()

format(v): string

Defined in: src/format.js:201

Parameters

ParameterTypeDescription
vIdentifier | Tag | Value | Entry | Node | Document

Returns

string


getLocation()

getLocation(element): undefined | StoredLocation

Defined in: src/locations.js:26

Get location information of the given parsed element

If the element was not created by the parser, or if the parser option storeLocations was not set to true, the result will be undefined.

Parameters

ParameterTypeDescription
elementIdentifier | Tag | Value | Entry | Node | Document

Returns

undefined | StoredLocation


parse()

Call Signature

parse(text, options): Value

Defined in: src/parse.d.ts:23

Parse the given text as a value.

The text should not contain anything other than the value, i.e. no leading or trailing whitespace, no comments, no tags.

Parameters
ParameterType
textstring | ArrayBuffer | DataView | Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array
options{ as: "value"; graphemeLocations: boolean; storeLocations: boolean; }
options.as"value"
options.graphemeLocations?boolean
options.storeLocations?boolean
Returns

Value

Call Signature

parse(text, options): Identifier

Defined in: src/parse.d.ts:46

Parse the given text as a identifier.

The text should not contain anything other than the identifier, i.e. no leading or trailing whitespace, no comments, no tags.

Parameters
ParameterType
textstring | ArrayBuffer | DataView | Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array
options{ as: "identifier"; graphemeLocations: boolean; storeLocations: boolean; }
options.as"identifier"
options.graphemeLocations?boolean
options.storeLocations?boolean
Returns

Identifier

Call Signature

parse(text, options): Entry

Defined in: src/parse.d.ts:69

Parse the given text as an entry.

The text can contain extra whitespace, tags, and comments (though no slashdash comments of entire nodes)

Parameters
ParameterType
textstring | ArrayBuffer | DataView | Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array
options{ as: "entry"; graphemeLocations: boolean; storeLocations: boolean; }
options.as"entry"
options.graphemeLocations?boolean
options.storeLocations?boolean
Returns

Entry

Call Signature

parse(text, options): Node

Defined in: src/parse.d.ts:91

Parse the given text as a node.

The text can contain extra whitespace, tags, and comments.

Parameters
ParameterType
textstring | ArrayBuffer | DataView | Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array
options{ as: "node"; graphemeLocations: boolean; storeLocations: boolean; }
options.as"node"
options.graphemeLocations?boolean
options.storeLocations?boolean
Returns

Node

Call Signature

parse(text, options): LineSpace

Defined in: src/parse.d.ts:111

Parse the given text as a whitespace in a document.

Parameters
ParameterType
textstring | ArrayBuffer | DataView | Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array
options{ as: "whitespace in document"; graphemeLocations: boolean; storeLocations: boolean; }
options.as"whitespace in document"
options.graphemeLocations?boolean
options.storeLocations?boolean
Returns

LineSpace

Call Signature

parse(text, options): NodeSpace

Defined in: src/parse.d.ts:131

Parse the given text as a whitespace in a node.

Parameters
ParameterType
textstring | ArrayBuffer | DataView | Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array
options{ as: "whitespace in node"; graphemeLocations: boolean; storeLocations: boolean; }
options.as"whitespace in node"
options.graphemeLocations?boolean
options.storeLocations?boolean
Returns

NodeSpace

Call Signature

parse(text, options?): Document

Defined in: src/parse.d.ts:153

Parse the given text as a document.

The text can contain extra whitespace, tags, and comments.

Parameters
ParameterType
textstring | ArrayBuffer | DataView | Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array
options?{ as: "document"; graphemeLocations: boolean; storeLocations: boolean; }
options.as?"document"
options.graphemeLocations?boolean
options.storeLocations?boolean
Returns

Document

Class: Document

Defined in: src/model/document.js:19

A document is a collection of zero or mode Nodes

Constructors

new Document()

new Document(nodes?): Document

Defined in: src/model/document.js:50

Parameters

ParameterTypeDefault valueDescription
nodes?Node[][]

Returns

Document

Properties

nodes

nodes: Node[]

Defined in: src/model/document.js:37

The nodes in this document

Methods

appendNode()

appendNode(node): void

Defined in: src/model/document.js:76

Add the given node at the end of this document

Parameters

ParameterTypeDescription
nodeNode | Document

Returns

void


clone()

clone(options?): Document

Defined in: src/model/document.js:61

Create an identical copy of this document

Parameters

ParameterTypeDescription
options?{ shallow: boolean; }
options.shallow?booleanIf true, only clone this document and without any children

Returns

Document


findNodeByName()

findNodeByName(name): undefined | Node

Defined in: src/model/document.js:176

Return the last node in this document with the given name

This function returns the last node instead of first to be in line with how properties are defined in the KDL specification where the last property with the given name is used and the rest is shadowed.

Parameters

ParameterTypeDescription
namestring

Returns

undefined | Node


findNodesByName()

findNodesByName(name): Node[]

Defined in: src/model/document.js:162

Return all nodes with the given node name

Changes to the returned array are not reflected back onto this document itself, and updates to the document won't reflect in the returned array.

Parameters

ParameterTypeDescription
namestring

Returns

Node[]


findParameterizedNode()

findParameterizedNode(name, parameter?): undefined | Node

Defined in: src/model/document.js:197

Return the last node in this document with the given name, matching the parameter

If the parameter is undefined, this method looks for a node with any single arguments. If a parameter is passed, this method looks for a node with a single parameter, equal to the given parameter.

Parameters

ParameterTypeDescription
namestring
parameter?Primitive

Returns

undefined | Node


insertNodeAfter()

insertNodeAfter(newNode, referenceNode): void

Defined in: src/model/document.js:108

Insert the given node to the document after the referenceNode, or at the beginning if no reference is passed

Parameters

ParameterTypeDescription
newNodeNode | Document
referenceNodenull | Node

Returns

void

Throws

If the given referenceNode is not part of this document


insertNodeBefore()

insertNodeBefore(newNode, referenceNode): void

Defined in: src/model/document.js:87

Insert the given node to the document before the referenceNode, or at the end if no reference is passed

Parameters

ParameterTypeDescription
newNodeNode | Document
referenceNodenull | Node

Returns

void

Throws

If the given referenceNode is not part of this document


isEmpty()

isEmpty(): boolean

Defined in: src/model/document.js:232

Return whether the document is empty

Returns

boolean


removeNode()

removeNode(node): void

Defined in: src/model/document.js:128

Remove the given node from this document

Parameters

ParameterTypeDescription
nodeNode

Returns

void

Throws

if the given node is not in this document


removeNodesByName()

removeNodesByName(name): void

Defined in: src/model/document.js:223

Remove all nodes with the given name from this document

Parameters

ParameterTypeDescription
namestring

Returns

void


replaceNode()

replaceNode(oldNode, newNode): void

Defined in: src/model/document.js:144

Replace the old node with the new node in this document

Parameters

ParameterTypeDescription
oldNodeNode
newNodeNode | Document

Returns

void

Throws

if the oldNode is not in this document

Class: Node

Defined in: src/model/node.js:18

A node is a node name, followed by zero or more arguments and/or properties, and children

Constructors

new Node()

new Node(name, entries?, children?): Node

Defined in: src/model/node.js:109

Parameters

ParameterTypeDefault valueDescription
nameIdentifierundefined
entries?Entry[][]
children?null | Documentnull

Returns

Node

Properties

children

children: null | Document

Defined in: src/model/node.js:70

Children of the node

An empty array means the children block is present but empty, if the value is null then there is no children block.


entries

entries: Entry[]

Defined in: src/model/node.js:60

Entries of the node


name

name: Identifier

Defined in: src/model/node.js:46

The name (also known as "tag name") of this node


tag

tag: null | Tag = null

Defined in: src/model/node.js:53

Tag attached to this node, if any

Methods

addArgument()

addArgument(value, tag?, index?): void

Defined in: src/model/node.js:277

Add the given value as argument to this node

The argument is added at the given index, or at the end. This index counts towards the arguments only, i.e. if the node has five entries, three of which are arguments then inserting an argument between the second and third can be achieved by passing 2 regardless of the whether properties and arguments are interspersed or not.

Parameters

ParameterTypeDescription
valuePrimitiveThe value to insert as argument
tag?null | stringThe tag to attach to the argument, if any
index?numberThe index

Returns

void


appendNode()

appendNode(node): void

Defined in: src/model/node.js:464

Add the given node at the end of this node's children

Parameters

ParameterTypeDescription
nodeNode | Document

Returns

void


clone()

clone(options?): Node

Defined in: src/model/node.js:122

Create an identical copy of this node

Parameters

ParameterTypeDescription
options?{ shallow: boolean; }
options.shallow?booleanIf true, only copy this node but don't clone this node's children.

Returns

Node


deleteProperty()

deleteProperty(name): void

Defined in: src/model/node.js:446

Delete the property with the given name

Parameters

ParameterTypeDescription
namestring

Returns

void


findNodeByName()

findNodeByName(name): undefined | Node

Defined in: src/model/node.js:542

Return the last node in this node's children with the given name

This function returns the last node instead of first to be in line with how properties are defined in the KDL specification where the last property with the given name is used and the rest is shadowed.

Parameters

ParameterTypeDescription
namestring

Returns

undefined | Node


findNodesByName()

findNodesByName(name): Node[]

Defined in: src/model/node.js:528

Return all nodes with the given node name

Changes to the returned array are not reflected back onto this document itself, and updates to the document won't reflect in the returned array.

Parameters

ParameterTypeDescription
namestring

Returns

Node[]


findParameterizedNode()

findParameterizedNode(name, parameter?): undefined | Node

Defined in: src/model/node.js:557

Return the last node in this node's children with the given name, matching the parameter

If the parameter is undefined, this method looks for a node with any single arguments. If a parameter is passed, this method looks for a node with a single parameter, equal to the given parameter.

Parameters

ParameterTypeDescription
namestring
parameter?Primitive

Returns

undefined | Node


getArgument()

getArgument(index): undefined | Primitive

Defined in: src/model/node.js:235

Return the argument at the given index, if present

This index counts towards the arguments only, i.e. if the node has five entries, three of which are arguments then passing 1 returns the second argument, regardless of the whether properties and arguments are interspersed or not.

Parameters

ParameterTypeDescription
indexnumber

Returns

undefined | Primitive


getArgumentEntries()

getArgumentEntries(): Entry[]

Defined in: src/model/node.js:205

Return a snapshot of all arguments of this node

Changes to the returned array are not reflected back onto this node itself, and updates to the node won't reflect in the returned array.

Returns

Entry[]


getArgumentEntry()

getArgumentEntry(index): undefined | Entry

Defined in: src/model/node.js:250

Return the argument entry at the given index, if present

This index counts towards the arguments only, i.e. if the node has five entries, three of which are arguments then passing 1 returns the second argument, regardless of the whether properties and arguments are interspersed or not.

Parameters

ParameterTypeDescription
indexnumber

Returns

undefined | Entry


getArguments()

getArguments(): Primitive[]

Defined in: src/model/node.js:193

Return a snapshot of all arguments of this node

Changes to the returned array are not reflected back onto this node itself, and updates to the node won't reflect in the returned array.

Returns

Primitive[]


getName()

getName(): string

Defined in: src/model/node.js:163

Return the name of this node

Returns

string


getProperties()

getProperties(): Map<string, Primitive>

Defined in: src/model/node.js:341

Return a snapshot of all properties of this node

Changes to the returned object are not reflected back onto this node itself, and updates to the node won't reflect in the returned object.

Returns

Map<string, Primitive>


getProperty()

getProperty(name): undefined | Primitive

Defined in: src/model/node.js:396

Return the value of the property with the given name, or undefined if it doesn't exist.

Parameters

ParameterTypeDescription
namestring

Returns

undefined | Primitive


getPropertyEntries()

getPropertyEntries(): Entry[]

Defined in: src/model/node.js:358

Return a snapshot of all properties of this node

Changes to the returned array are not reflected back onto this node itself, and updates to the node won't reflect in the returned array.

Returns

Entry[]


getPropertyEntry()

getPropertyEntry(name): undefined | Entry

Defined in: src/model/node.js:407

Return the property entry with the given name, or undefined if it doesn't exist.

Parameters

ParameterTypeDescription
namestring

Returns

undefined | Entry


getPropertyEntryMap()

getPropertyEntryMap(): Map<string, Entry>

Defined in: src/model/node.js:370

Return a snapshot of all properties of this node

Changes to the returned map are not reflected back onto this node itself, and updates to the node won't reflect in the returned map.

Returns

Map<string, Entry>


getTag()

getTag(): null | string

Defined in: src/model/node.js:145

Return the tag of this node, if any

Returns

null | string


hasArgument()

hasArgument(index): boolean

Defined in: src/model/node.js:220

Return the value at the given index, if present

This index counts towards the arguments only, i.e. if the node has five entries, three of which are arguments then passing 1 returns the second argument, regardless of the whether properties and arguments are interspersed or not.

Parameters

ParameterTypeDescription
indexnumber

Returns

boolean


hasArguments()

hasArguments(): boolean

Defined in: src/model/node.js:181

Return whether this node has arguments

Returns

boolean


hasChildren()

hasChildren(): boolean

Defined in: src/model/node.js:455

Return whether this node has child nodes

Returns

boolean


hasProperties()

hasProperties(): boolean

Defined in: src/model/node.js:329

Return whether this node has properties

Returns

boolean


hasProperty()

hasProperty(name): boolean

Defined in: src/model/node.js:385

Return whether this node has the given property

Parameters

ParameterTypeDescription
namestring

Returns

boolean


insertNodeAfter()

insertNodeAfter(newNode, referenceNode): void

Defined in: src/model/node.js:486

Insert the given node to the node's children after the referenceNode, or at the beginning if no reference is passed

Parameters

ParameterTypeDescription
newNodeNode | Document
referenceNodenull | Node

Returns

void

Throws

If the given referenceNode is not part of this document


insertNodeBefore()

insertNodeBefore(newNode, referenceNode): void

Defined in: src/model/node.js:475

Insert the given node to the node's children before the referenceNode, or at the end if no reference is passed

Parameters

ParameterTypeDescription
newNodeNode | Document
referenceNodenull | Node

Returns

void

Throws

If the given referenceNode is not part of this node's children


removeArgument()

removeArgument(index): void

Defined in: src/model/node.js:309

Remove the argument at the given index

The index counts towards the arguments only, i.e. if the node has five entries, three of which are arguments then the last argument can be removed by passing 2, regardless of whether the third argument is also the third entry.

Parameters

ParameterTypeDescription
indexnumber

Returns

void


removeNode()

removeNode(node): void

Defined in: src/model/node.js:496

Remove the given node from this node's children

Parameters

ParameterTypeDescription
nodeNode

Returns

void

Throws

if the given node is not in this node's children


removeNodesByName()

removeNodesByName(name): void

Defined in: src/model/node.js:567

Remove all nodes with the given name from this document

Parameters

ParameterTypeDescription
namestring

Returns

void


replaceNode()

replaceNode(oldNode, newNode): void

Defined in: src/model/node.js:511

Replace the old node with the new node in this node's children

Parameters

ParameterTypeDescription
oldNodeNode
newNodeNode | Document

Returns

void

Throws

if the oldNode is not in this node's children


setName()

setName(name): void

Defined in: src/model/node.js:172

Set the name of this node to the given name

Parameters

ParameterTypeDescription
namestring

Returns

void


setProperty()

setProperty(name, value, tag?): void

Defined in: src/model/node.js:427

Set the given property on this node

This function updates the property entry with the given name, if it exists.

Parameters

ParameterTypeDescription
namestring
valuePrimitive
tag?null | string

Returns

void


setTag()

setTag(tag): void

Defined in: src/model/node.js:154

Set the tag of this node to the given tag

Parameters

ParameterTypeDescription
tagundefined | null | string

Returns

void


create()

static create(name): Node

Defined in: src/model/node.js:25

Create a new node with the given name

Parameters

ParameterTypeDescription
namestring

Returns

Node

Class: Entry

Defined in: src/model/entry.js:7

An entry represents either an argument or a property to a node

Constructors

new Entry()

new Entry(value, name): Entry

Defined in: src/model/entry.js:80

Parameters

ParameterTypeDescription
valueValue
namenull | Identifier

Returns

Entry

Properties

equals

equals: undefined | string

Defined in: src/model/entry.js:74

Equals sign


leading

leading: undefined | string

Defined in: src/model/entry.js:60

Leading whitespace


name

name: null | Identifier

Defined in: src/model/entry.js:46

The name of this entry if it's a property, or null if it's an argument


trailing

trailing: undefined | string

Defined in: src/model/entry.js:67

Trailing whitespace


value

value: Value

Defined in: src/model/entry.js:53

The value of this entry

Methods

clone()

clone(): Entry

Defined in: src/model/entry.js:90

Create an identical copy of this entry

Returns

Entry


getName()

getName(): null | string

Defined in: src/model/entry.js:125

Return the name of this entry, if any

Returns

null | string


getTag()

getTag(): null | string

Defined in: src/model/entry.js:106

Return the tag of this entry, if any

Returns

null | string

See

Value.prototype.getTag


getValue()

getValue(): Primitive

Defined in: src/model/entry.js:143

Return the value of this entry

Returns

Primitive


isArgument()

isArgument(): boolean

Defined in: src/model/entry.js:161

Return whether this entry is an argument

Returns

boolean


isProperty()

isProperty(): boolean

Defined in: src/model/entry.js:170

Return whether this entry is a named property

Returns

boolean


setName()

setName(name): void

Defined in: src/model/entry.js:134

Set the name of this entry to the given name

Parameters

ParameterTypeDescription
nameundefined | null | string

Returns

void


setTag()

setTag(tag): void

Defined in: src/model/entry.js:116

Set the tag of this entry to the given tag

Parameters

ParameterTypeDescription
tagundefined | null | string

Returns

void

See

Value.prototype.setTag


setValue()

setValue(value): void

Defined in: src/model/entry.js:152

Set the name of this entry to the given name

Parameters

ParameterTypeDescription
valuePrimitive

Returns

void


createArgument()

static createArgument(value): Entry

Defined in: src/model/entry.js:14

Create a new argument entry with the given value

Parameters

ParameterTypeDescription
valuePrimitive

Returns

Entry


createProperty()

static createProperty(name, value): Entry

Defined in: src/model/entry.js:25

Create a new property entry for the given key and value

Parameters

ParameterTypeDescription
namestring
valuePrimitive

Returns

Entry

Class: Tag

Defined in: src/model/tag.js:4

A tag is tied to anode or entry

Constructors

new Tag()

new Tag(name): Tag

Defined in: src/model/tag.js:51

Parameters

ParameterTypeDescription
namestring

Returns

Tag

Methods

clone()

clone(): Tag

Defined in: src/model/tag.js:95

Create an identical copy of this tag

Returns

Tag


getName()

getName(): string

Defined in: src/model/tag.js:74

Return the tag name

Returns

string


setName()

setName(name): void

Defined in: src/model/tag.js:83

Change the tag name

Parameters

ParameterTypeDescription
namestring

Returns

void

Class: Identifier

Defined in: src/model/identifier.js:4

An identifier

Constructors

new Identifier()

new Identifier(name): Identifier

Defined in: src/model/identifier.js:28

Parameters

ParameterTypeDescription
namestring

Returns

Identifier

Methods

clone()

clone(): Identifier

Defined in: src/model/identifier.js:62

Create an identical copy of this identifier

Returns

Identifier


getName()

getName(): string

Defined in: src/model/identifier.js:41

Returns the name of this identifier

Returns

string


setName()

setName(name): void

Defined in: src/model/identifier.js:50

Change the name of the identifier

Parameters

ParameterTypeDescription
namestring

Returns

void

Class: Value

Defined in: src/model/value.js:13

A value represents a primitive in KDL, i.e. a string, boolean, number, or null

Values are always tied to an entry.

Constructors

new Value()

new Value(value): Value

Defined in: src/model/value.js:51

Parameters

ParameterTypeDescription
valuePrimitive

Returns

Value

Properties

betweenTagAndValue

betweenTagAndValue: undefined | string

Defined in: src/model/value.js:46

Whitespace between the tag and the value


representation

representation: undefined | string

Defined in: src/model/value.js:31

String representation of the value

Methods

clone()

clone(): Value

Defined in: src/model/value.js:67

Create an identical copy of this value

Returns

Value


getTag()

getTag(): null | string

Defined in: src/model/value.js:101

Return the tag of this entry, if any

Returns

null | string


getValue()

getValue(): Primitive

Defined in: src/model/value.js:80

Return the value itself

Returns

Primitive


setTag()

setTag(tag): void

Defined in: src/model/value.js:110

Set the tag of this entry to the given tag

Parameters

ParameterTypeDescription
tagundefined | null | string

Returns

void


setValue()

setValue(value): void

Defined in: src/model/value.js:89

Change the value

Parameters

ParameterTypeDescription
valuePrimitive

Returns

void

Class: InvalidKdlError

Defined in: src/error.js:8

Error thrown when invalid KDL is encountered

Extends

  • Error

Constructors

new InvalidKdlError()

new InvalidKdlError(message, options?): InvalidKdlError

Defined in: src/error.js:53

Parameters

ParameterTypeDescription
messagestring
options?ErrorOptions & object

Returns

InvalidKdlError

Overrides

Error.constructor

Properties

cause?

optional cause: unknown

Defined in: node_modules/typescript/lib/lib.es2022.error.d.ts:26

Inherited from

Error.cause


end

readonly end: undefined | Location

Defined in: src/error.js:28

The location of the end of the error, if it can be tied to a single location


errors

readonly errors: undefined | InvalidKdlError[]

Defined in: src/error.js:47

Collection of more specific errors

If this property is present, then the message of this error will be something generic and the errors in this property will contain more useful information.


message

message: string

Defined in: node_modules/typescript/lib/lib.es5.d.ts:1077

Inherited from

Error.message


stack?

optional stack: string

Defined in: node_modules/typescript/lib/lib.es5.d.ts:1078

Inherited from

Error.stack


start

readonly start: undefined | Location

Defined in: src/error.js:20

The location of the start of the error, if it can be tied to a single location


token

readonly token: undefined | Token

Defined in: src/error.js:36

Token tied to the error, if it can be tied to a single token


prepareStackTrace()?

static optional prepareStackTrace: (err, stackTraces) => any

Defined in: node_modules/@types/node/globals.d.ts:143

Optional override for formatting stack traces

Parameters

ParameterType
errError
stackTracesCallSite[]

Returns

any

See

https://v8.dev/docs/stack-trace-api#customizing-stack-traces

Inherited from

Error.prepareStackTrace


stackTraceLimit

static stackTraceLimit: number

Defined in: node_modules/@types/node/globals.d.ts:145

Inherited from

Error.stackTraceLimit

Methods

getDetails()

getDetails(): Generator<InvalidKdlError, void, void>

Defined in: src/error.js:79

Returns an iterable for the details of this error

If this error contains more detailed errors, this iterable yields those detailed errors. If this error doesn't have more detailed errors, this iterable yields this error itself.

Returns

Generator<InvalidKdlError, void, void>


captureStackTrace()

static captureStackTrace(targetObject, constructorOpt?): void

Defined in: node_modules/@types/node/globals.d.ts:136

Create .stack property on a target object

Parameters

ParameterType
targetObjectobject
constructorOpt?Function

Returns

void

Inherited from

Error.captureStackTrace

json

Classes

Interfaces

FromJsonOptions

Defined in: src/json.d.ts:152

Options for the fromJson function

Extends

Properties

allowEntries?

optional allowEntries: boolean

Defined in: src/json.d.ts:166

Whether to allow literal children to be encoded into values or properties

Defaults to true. This value can be defined specifically for arrays, objects, or the root node.


allowEntriesInArrays?

optional allowEntriesInArrays: boolean

Defined in: src/json.d.ts:177

Whether to allow literal items in the array to be encoded as values on a node

If set to false, all array items will be encoded as children.

If set to true, all leading literal values of arrays will be encoded as node values instead.

The default value is the value of allowEntries, which in turn defaults to true.


allowEntriesInObjects?

optional allowEntriesInObjects: boolean

Defined in: src/json.d.ts:189

Whether to allow literal properties in the object to be encoded as property on a node

If set to false, all node properties will be encoded as children.

If set to true, all properties with literal values of objects will be encoded as node properties instead. Note that this changes the order of properties, which are assumed not to matter in JSON.

The default value is the value of allowEntries, which in turn defaults to true.


allowEntriesInRoot?

optional allowEntriesInRoot: boolean

Defined in: src/json.d.ts:199

Whether to allow literal children to be encoded as values or properties on the root node

This property only has effect if the given value is an object or an array. Literal values are always encoded as values on the root node.

The default value of this option is the value of allowEntriesInArrays or allowEntriesInObjects, depending on the type of the value.


indentation?

optional indentation: string | number

Defined in: src/json.d.ts:256

The indentation to give each nested level of node

If a string is passed, that string is used as indentation. If a number higher than zero is passed, the indentation is set to the whitespace character repeated for that number of times. If zero is passed or no indentation is given, no newlines with indentation will be inserted into the output.

Inherited from

StringifyOptions.indentation


nodeName?

optional nodeName: string

Defined in: src/json.d.ts:158

Name of the root node to create

If no name is passed, the node will be called "-".


replaceJsonValue()?

optional replaceJsonValue: (key, value, originalValue) => unknown

Defined in: src/json.d.ts:272

Replacer function called for every JSON value in the data being transformed

The replacer can return any JSON value, which will be used instead of the original value. If undefined is returned, the value will be discarded.

If the originalValue had a toJSON method, it will be called and the result will be the value parameter. In all other cases value and originalValue will be the same value.

Parameters
ParameterTypeDescription
keystring | numberThe name of the property or the index inside an array
valueunknownThe value being handled
originalValueunknownThe original value
Returns

unknown

Inherited from

StringifyOptions.replaceJsonValue


replaceKdlValue()?

optional replaceKdlValue: (key, value, jsonValue, originalJsonValue) => undefined | Entry | Node

Defined in: src/json.d.ts:290

Replacer function called for every KDL node or entry created

The replacer can return an entry or node. If an entry is returned but an entry would not be valid in the given location, it will be transformed into a node. If undefined is returned, the value will be discarded.

Parameters
ParameterTypeDescription
keystring | numberThe name of the property or the index inside an array
valueEntry | NodeThe entry or node that was created
jsonValueunknownThe JSON value that was transformed into the KDL value
originalJsonValueunknown
Returns

undefined | Entry | Node

Inherited from

StringifyOptions.replaceKdlValue


JiKReviver()<T>

Defined in: src/json.d.ts:216

Reviver function that can be passed into parse or toJson

The function is called for every JSON value while it's being serialized. These values are replaced by the return value of this function.

Type Parameters

Type Parameter
T

JiKReviver(value, key, data): undefined | T

Defined in: src/json.d.ts:223

Reviver function that can be passed into parse or toJson

The function is called for every JSON value while it's being serialized. These values are replaced by the return value of this function.

Parameters

ParameterTypeDescription
valueJsonValueThe JSON value
keystring | numberThe key of the value, empty string for the root value
data{ location: Entry | Node; }The node or entry where the value was defined
data.locationEntry | Node-

Returns

undefined | T

The value to use, if the value is undefined then the property is removed from the result


JsonObject

Defined in: src/json.d.ts:13

A JSON object

Indexable

[property: string]: JsonValue


StringifyOptions

Defined in: src/json.d.ts:248

Options for the stringify function

Extended by

Properties

indentation?

optional indentation: string | number

Defined in: src/json.d.ts:256

The indentation to give each nested level of node

If a string is passed, that string is used as indentation. If a number higher than zero is passed, the indentation is set to the whitespace character repeated for that number of times. If zero is passed or no indentation is given, no newlines with indentation will be inserted into the output.


replaceJsonValue()?

optional replaceJsonValue: (key, value, originalValue) => unknown

Defined in: src/json.d.ts:272

Replacer function called for every JSON value in the data being transformed

The replacer can return any JSON value, which will be used instead of the original value. If undefined is returned, the value will be discarded.

If the originalValue had a toJSON method, it will be called and the result will be the value parameter. In all other cases value and originalValue will be the same value.

Parameters
ParameterTypeDescription
keystring | numberThe name of the property or the index inside an array
valueunknownThe value being handled
originalValueunknownThe original value
Returns

unknown


replaceKdlValue()?

optional replaceKdlValue: (key, value, jsonValue, originalJsonValue) => undefined | Entry | Node

Defined in: src/json.d.ts:290

Replacer function called for every KDL node or entry created

The replacer can return an entry or node. If an entry is returned but an entry would not be valid in the given location, it will be transformed into a node. If undefined is returned, the value will be discarded.

Parameters
ParameterTypeDescription
keystring | numberThe name of the property or the index inside an array
valueEntry | NodeThe entry or node that was created
jsonValueunknownThe JSON value that was transformed into the KDL value
originalJsonValueunknown
Returns

undefined | Entry | Node


ToJsonOptions

Defined in: src/json.d.ts:31

Options for the toJson function

Properties

ignoreValues?

optional ignoreValues: boolean

Defined in: src/json.d.ts:62

Whether to ignore values on the root node

Turning this option on deviates from the JiK standard by ignoring all values on the root node. This makes it possible to encode parameterized nodes as JiK.

For example, every book node in the following document is a JiK node:

book "The Fellowship of the Ring" {
  author "J.R.R. Tolkien"
  publicationYear 1954
}

book "Dune" publicationYear=1965 {
  author "Frank Herbert"
}

Here's how this could be turned into an map containing all books:

const books = new Map(
  document.findNodesByName('book').map(node => [
	   node.getArgument(0),
    toJson(node, {ignoreValues: true}),
  ]),
)

ToJsonReviver<T>

Defined in: src/json.d.ts:85

Extra option to modify the return value of the toJson function

Type Parameters

Type Parameter
T

Properties

reviver

reviver: JiKReviver<T>

Defined in: src/json.d.ts:89

Reviver to use


ToJsonType<T>

Defined in: src/json.d.ts:68

Extra option for providing a type hint to the toJson function

Type Parameters

Type Parameter
T

Properties

type

type: T

Defined in: src/json.d.ts:79

Type to use for the node

Possible values are:

  • object: The node must be a valid object, and nodes that are ambiguous and could be objects or something else are assumed to be an object
  • array: The node must be a valid array, and nodes that are ambiguous and could be arrays or something else are assumed to be an array

Type Aliases

JsonValue

JsonValue: null | number | boolean | string | JsonObject | JsonValue[]

Defined in: src/json.d.ts:20

A JSON value

Functions

fromJson()

fromJson(value, options?): Node

Defined in: src/json.d.ts:208

Encode the given JSON value into a JiK node

Parameters

ParameterTypeDescription
valueJsonValueThe JSON value to encode
options?FromJsonOptions-

Returns

Node

Throws

If the given value contains cycles.


parse()

Call Signature

parse(text, reviver?): JsonValue

Defined in: src/json.d.ts:236

Parse the given JiK text to its encoded JSON value

Parameters
ParameterTypeDescription
textstringThe JiK text to parse
reviver?JiKReviver<JsonValue>-
Returns

JsonValue

Throws

If the given text is not a valid JiK document

Call Signature

parse(text, reviver): unknown

Defined in: src/json.d.ts:243

Parse the given JiK text to its encoded JSON value

Parameters
ParameterTypeDescription
textstringThe JiK text to parse
reviverJiKReviver<unknown>-
Returns

unknown

Throws

If the given text is not a valid JiK document


stringify()

Call Signature

stringify(value, options?): string

Defined in: src/json.d.ts:305

Stringify the given JSON value into JiK text

Parameters
ParameterTypeDescription
valueunknownThe JSON value to encode
options?StringifyOptionsOptional options
Returns

string

Throws

If the given JSON value contains cycles.

Call Signature

stringify(value, replacer?, indentation?): string

Defined in: src/json.d.ts:315

Stringify the given JSON value into JiK text

This function's signrature is explicitly kept similar to JSON.stringify.

Parameters
ParameterTypeDescription
valueunknownThe JSON value to encode
replacer?(key, value, originalValue) => unknown-
indentation?string | numberThe indentation to give each nested level of node, either the actual indentation string or the number of spaces
Returns

string

Throws

If the given JSON value contains cycles.


toJson()

Call Signature

toJson(nodeOrDocument, options): JsonObject

Defined in: src/json.d.ts:101

Extract the JSON value encoded into the given JiK node or document.

If passed a document, the document must contain a single node, which acts as the root of the JiK value.

Parameters
ParameterTypeDescription
nodeOrDocumentNode | DocumentA valid JiK node or a document containing a single node which is a valid JiK node
optionsToJsonOptions & ToJsonType<"object"> & object-
Returns

JsonObject

See

https://github.com/kdl-org/kdl/blob/76d5dd542a9043257bc65476c0a70b94667052a7/JSON-IN-KDL.md

Throws

If the given node is not a valid JiK node or if the given document doesn't contain exactly one node

Call Signature

toJson(nodeOrDocument, options): JsonValue[]

Defined in: src/json.d.ts:114

Extract the JSON value encoded into the given JiK node or document.

If passed a document, the document must contain a single node, which acts as the root of the JiK value.

Parameters
ParameterTypeDescription
nodeOrDocumentNode | DocumentA valid JiK node or a document containing a single node which is a valid JiK node
optionsToJsonOptions & ToJsonType<"array"> & object-
Returns

JsonValue[]

See

https://github.com/kdl-org/kdl/blob/76d5dd542a9043257bc65476c0a70b94667052a7/JSON-IN-KDL.md

Throws

If the given node is not a valid JiK node or if the given document doesn't contain exactly one node

Call Signature

toJson(nodeOrDocument, options?): JsonValue

Defined in: src/json.d.ts:127

Extract the JSON value encoded into the given JiK node or document.

If passed a document, the document must contain a single node, which acts as the root of the JiK value.

Parameters
ParameterTypeDescription
nodeOrDocumentNode | DocumentA valid JiK node or a document containing a single node which is a valid JiK node
options?ToJsonOptions & Partial<ToJsonType<string>> & Partial<ToJsonReviver<JsonValue>>-
Returns

JsonValue

See

https://github.com/kdl-org/kdl/blob/76d5dd542a9043257bc65476c0a70b94667052a7/JSON-IN-KDL.md

Throws

If the given node is not a valid JiK node or if the given document doesn't contain exactly one node

Call Signature

toJson(nodeOrDocument, options?): unknown

Defined in: src/json.d.ts:142

Extract the JSON value encoded into the given JiK node or document.

If passed a document, the document must contain a single node, which acts as the root of the JiK value.

Parameters
ParameterTypeDescription
nodeOrDocumentNode | DocumentA valid JiK node or a document containing a single node which is a valid JiK node
options?ToJsonOptions & Partial<ToJsonType<string>> & Partial<ToJsonReviver<unknown>>-
Returns

unknown

See

https://github.com/kdl-org/kdl/blob/76d5dd542a9043257bc65476c0a70b94667052a7/JSON-IN-KDL.md

Throws

If the given node is not a valid JiK node or if the given document doesn't contain exactly one node

Class: InvalidJsonInKdlError

Defined in: src/json.d.ts:6

Error thrown when encountering invalid JSON-in-KDL

Extends

  • Error

Constructors

new InvalidJsonInKdlError()

new InvalidJsonInKdlError(message): InvalidJsonInKdlError

Defined in: src/json.d.ts:7

Parameters

ParameterType
messagestring

Returns

InvalidJsonInKdlError

Overrides

Error.constructor

Properties

cause?

optional cause: unknown

Defined in: node_modules/typescript/lib/lib.es2022.error.d.ts:26

Inherited from

Error.cause


message

message: string

Defined in: node_modules/typescript/lib/lib.es5.d.ts:1077

Inherited from

Error.message


name

name: string

Defined in: node_modules/typescript/lib/lib.es5.d.ts:1076

Inherited from

Error.name


stack?

optional stack: string

Defined in: node_modules/typescript/lib/lib.es5.d.ts:1078

Inherited from

Error.stack


prepareStackTrace()?

static optional prepareStackTrace: (err, stackTraces) => any

Defined in: node_modules/@types/node/globals.d.ts:143

Optional override for formatting stack traces

Parameters

ParameterType
errError
stackTracesCallSite[]

Returns

any

See

https://v8.dev/docs/stack-trace-api#customizing-stack-traces

Inherited from

Error.prepareStackTrace


stackTraceLimit

static stackTraceLimit: number

Defined in: node_modules/@types/node/globals.d.ts:145

Inherited from

Error.stackTraceLimit

Methods

captureStackTrace()

static captureStackTrace(targetObject, constructorOpt?): void

Defined in: node_modules/@types/node/globals.d.ts:136

Create .stack property on a target object

Parameters

ParameterType
targetObjectobject
constructorOpt?Function

Returns

void

Inherited from

Error.captureStackTrace

v1-compat

Functions

parse()

parse(text, options?): Document

Defined in: src/v1-compat.js:48

Parse the given KDL v1 text and turn it into a KDL v2 document

Formatting the given document will result in a KDL v2 text equivalent to the original KDL v1 text.

Parameters

ParameterTypeDescription
textstring | ArrayBuffer | DataView | Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array
options?{ graphemeLocations: boolean; storeLocations: boolean; }
options.graphemeLocations?boolean
options.storeLocations?boolean

Returns

Document


parseAndTransform()

parseAndTransform(text): Document

Defined in: src/v1-compat.js:32

Alias for parse

Parameters

ParameterTypeDescription
textstring | ArrayBuffer | DataView | Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array

Returns

Document

Deprecated

Use parse instead


parseCompat()

parseCompat(text, options?): Document

Defined in: src/v1-compat.js:99

Parse the given KDL v1 or v2 text and return a valid KDL v2 document

Formatting the given document will result in a KDL v2 text, even if the original text was KDL v1.

This function does not respect any /- kdl-version <number> comments in the text. It always tries the most recent KDL version first and falls back to the previous version if that fails. If the text doesn't parse into a valid document under any KDL version, an AggregateError is thrown combining all errors.

Parameters

ParameterTypeDescription
textstring | ArrayBuffer | DataView | Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array
options?{ graphemeLocations: boolean; storeLocations: boolean; }
options.graphemeLocations?boolean
options.storeLocations?boolean

Returns

Document


parseWithoutFormatting()

parseWithoutFormatting(text): Document

Defined in: src/v1-compat.js:21

Alias for parse

Parameters

ParameterTypeDescription
textstring | ArrayBuffer | DataView | Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array

Returns

Document

Deprecated

Use parse instead

dessert

Classes

Interfaces

Argument()<Required, ReturnMultiple, IgnoreInvalid>

Defined in: src/dessert/deserialization/types.d.ts:79

Type Parameters

Type ParameterDefault type
Required extends booleanfalse
ReturnMultiple extends booleanfalse
IgnoreInvalid extends booleanfalse

Argument(): ArgumentReturnType<Primitive, Required, ReturnMultiple, false>

Defined in: src/dessert/deserialization/types.d.ts:87

Return the next argument, if there is a next argument

Returns

ArgumentReturnType<Primitive, Required, ReturnMultiple, false>

Argument<T>(...types): ArgumentReturnType<TypeOf<T>, Required, ReturnMultiple, IgnoreInvalid>

Defined in: src/dessert/deserialization/types.d.ts:94

Return the next argument, if there is a next argument, requiring the argument to be of the given type

Type Parameters

Type Parameter
T extends [PrimitiveType, ...PrimitiveType[]]

Parameters

ParameterType
...typesT

Returns

ArgumentReturnType<TypeOf<T>, Required, ReturnMultiple, IgnoreInvalid>

Throws

If the next argument does not match any of the given types

Properties

if

if: IgnoreInvalid extends false ? Argument<Required, ReturnMultiple, true> : never

Defined in: src/dessert/deserialization/types.d.ts:123

Return undefined instead of throwing if the next argument doesn't match the given types or enum values


required

required: Required extends false ? Argument<true, ReturnMultiple, IgnoreInvalid> : never

Defined in: src/dessert/deserialization/types.d.ts:110

Throw if there is no next argument, rather than return undefined


rest

rest: ReturnMultiple extends false ? Argument<Required, true, IgnoreInvalid> : never

Defined in: src/dessert/deserialization/types.d.ts:117

Return all remaining arguments rather than only the next argument

Methods

enum()

enum<T>(...values): ArgumentReturnType<T[number], Required, ReturnMultiple, IgnoreInvalid>

Defined in: src/dessert/deserialization/types.d.ts:103

Return the next argument, if there is a next argument, requiring the argument to be one of the given enum values

Type Parameters
Type Parameter
T extends Primitive[]
Parameters
ParameterType
...valuesT
Returns

ArgumentReturnType<T[number], Required, ReturnMultiple, IgnoreInvalid>

Throws

If the next argument does not equal any of the given values


Child()<Required, Single>

Defined in: src/dessert/deserialization/types.d.ts:228

Type Parameters

Type ParameterDefault type
Required extends booleanfalse
Single extends booleanfalse

Child<T, P>(name, deserializer, ...parameters): T | Required extends false ? undefined : never

Defined in: src/dessert/deserialization/types.d.ts:237

Returns the next child with the given name, if there is any

Type Parameters

Type Parameter
T
P extends unknown[]

Parameters

ParameterType
namestring
deserializerDeserializer<T, P>
...parametersP

Returns

T | Required extends false ? undefined : never

Throws

If the deserializer fails

Properties

required

required: Required extends false ? Child<true, Single> : never

Defined in: src/dessert/deserialization/types.d.ts:246

Throw if there is no next child with the given name, instead of returning undefined


single

single: Single extends false ? Child<Required, true> : never

Defined in: src/dessert/deserialization/types.d.ts:251

Throw if there are multiple nodes left with the given name


Children()

Defined in: src/dessert/deserialization/types.d.ts:254

Children<T, P>(name, deserializer, ...parameters): T[]

Defined in: src/dessert/deserialization/types.d.ts:260

Returns all remaining children with the given name

Type Parameters

Type Parameter
T
P extends unknown[]

Parameters

ParameterType
namestring
deserializerDeserializer<T, P>
...parametersP

Returns

T[]

Throws

If the deserializer fails

Properties

entries()

entries: <T, P>(deserializer, ...parameters) => [string, T][]

Defined in: src/dessert/deserialization/types.d.ts:278

Returns all remaining children with their name

Type Parameters
Type Parameter
T
P extends unknown[]
Parameters
ParameterType
deserializerDeserializer<T, P>
...parametersP
Returns

[string, T][]

Throws

If the deserializer fails

filtered()

filtered: <T, P>(filter, deserializer, ...parameters) => [string, T][]

Returns all remaining children with their name if that name matches the given filter

Type Parameters
Type Parameter
T
P extends unknown[]
Parameters
ParameterType
filterRegExp
deserializerDeserializer<T, P>
...parametersP
Returns

[string, T][]

Throws

If the deserializer fails

filtered.unique()

Returns all remaining children with their name if that name matches the given filter, requiring all matching names to be unique

Type Parameters
Type Parameter
T
P extends unknown[]
Parameters
ParameterType
filterRegExp
deserializerDeserializer<T, P>
...parametersP
Returns

[string, T][]

Throws

If the deserializer fails

Throws

If a duplicate name is encountered

unique()

unique: <T, P>(deserializer, ...parameters) => [string, T][]

Returns all remaining children with their name, requiring all names to be unique

Type Parameters
Type Parameter
T
P extends unknown[]
Parameters
ParameterType
deserializerDeserializer<T, P>
...parametersP
Returns

[string, T][]

Throws

If the deserializer fails

Throws

If a duplicate name is encountered

unique.filtered()

Returns all remaining children with their name if that name matches the given filter, requiring all matching names to be unique

Type Parameters
Type Parameter
T
P extends unknown[]
Parameters
ParameterType
filterRegExp
deserializerDeserializer<T, P>
...parametersP
Returns

[string, T][]

Throws

If the deserializer fails

Throws

If a duplicate name is encountered

Methods

required()

required<T, P>(name, deserializer, ...parameters): [T, ...T[]]

Defined in: src/dessert/deserialization/types.d.ts:272

Returns all remaining children with the given name, requiring at least one such child

Type Parameters
Type Parameter
T
P extends unknown[]
Parameters
ParameterType
namestring
deserializerDeserializer<T, P>
...parametersP
Returns

[T, ...T[]]

Throws

If the deserializer fails

Throws

If there are no remaining children with the given name


DeserializationContext

Defined in: src/dessert/deserialization/types.d.ts:409

Wrapper around a Node to help deserializing a single Node into a value

Properties

argument

readonly argument: Argument

Defined in: src/dessert/deserialization/types.d.ts:423

Helper to access the node's arguments


child

readonly child: Child

Defined in: src/dessert/deserialization/types.d.ts:432

Helper to access the node's children


children

readonly children: Children

Defined in: src/dessert/deserialization/types.d.ts:436

Helper to access the node's children


json

readonly json: Json

Defined in: src/dessert/deserialization/types.d.ts:441

Helper for processing the node as JSON


name

readonly name: string

Defined in: src/dessert/deserialization/types.d.ts:413

Name of the node being deserialized


property

readonly property: Property

Defined in: src/dessert/deserialization/types.d.ts:427

Helper to access the node's properties


run()

readonly run: <T, P>(deserializer, ...parameters) => T

Defined in: src/dessert/deserialization/types.d.ts:446

Run the given deserializer

Type Parameters
Type Parameter
T
P extends unknown[]
Parameters
ParameterType
deserializerDeserializerFromContext<T, P>
...parametersP
Returns

T


tag

readonly tag: null | string

Defined in: src/dessert/deserialization/types.d.ts:418

Tag of the node being deserialized


DocumentSerializationContext

Defined in: src/dessert/serialization/types.d.ts:133

Wrapper around a Document to help serializing a value or values into a Document

Properties

child()

readonly child: <P>(name, serializer, ...params) => void

Defined in: src/dessert/serialization/types.d.ts:149

Run the given serializer to create a node with the given name and add that node as child to the document being serialized

Type Parameters
Type Parameter
P extends unknown[]
Parameters
ParameterType
namestring
serializerSerializer<P>
...paramsP
Returns

void

tagged()

Run the given serializer to create a node with the given name and tag and add that node as child to the document being serialized

Type Parameters
Type Parameter
P extends unknown[]
Parameters
ParameterType
tagstring
namestring
serializerSerializer<P>
...paramsP
Returns

void


json()

readonly json: (value) => void

Defined in: src/dessert/serialization/types.d.ts:175

Serialize a JSON value

The allowed values are limited to only values that can be entirely serialized into nodes placed inside the document. For example, a string value would be added as argument but a document can't have arguments.

Parameters
ParameterType
valueJsonObject | JsonValue[]
Returns

void


run()

readonly run: <P>(serializer, ...parameters) => void

Defined in: src/dessert/serialization/types.d.ts:180

Run the given serializer

Type Parameters
Type Parameter
P extends unknown[]
Parameters
ParameterType
serializerDocumentSerializer<P>
...parametersP
Returns

void


source()

readonly source: (sourceCtx) => void

Defined in: src/dessert/serialization/types.d.ts:145

Link this serialization to a prior deserialization

Attaching a deserialization context as source to this serialization allows the serialization to keep track of metadata in the original text. For example, an effort is made to preserve formatting and comments.

Parameters
ParameterType
sourceCtxundefined | null | DeserializationContext
Returns

void


target

readonly target: "document"

Defined in: src/dessert/serialization/types.d.ts:137

Marker property that can be used to distinguish between a DocumentSerializationContext and SerializationContext.


Json()

Defined in: src/dessert/deserialization/types.d.ts:362

Json(): undefined | JsonValue

Defined in: src/dessert/deserialization/types.d.ts:371

Turn the remaining arguments, properties, and children into a JSON value

After calling this function, all remaining arguments, properties, and children of the context have been consumed. Further calls to any of the context's utilities will return undefined or throw, depending on how the utility handles an empty context.

Returns

undefined | JsonValue

Throws

If the context doesn't contain a valid JSON value

Json<T>(...types): undefined | JsonTypeOf<T>

Defined in: src/dessert/deserialization/types.d.ts:381

Turn the remaining arguments, properties, and children into a JSON value matching any of the given types

After calling this function, all remaining arguments, properties, and children of the context have been consumed. Further calls to any of the context's utilities will return undefined or throw, depending on how the utility handles an empty context.

Type Parameters

Type Parameter
T extends [JsonType, ...JsonType[]]

Parameters

ParameterType
...typesT

Returns

undefined | JsonTypeOf<T>

Throws

If the context doesn't contain a valid JSON value

Throws

If the deserialized value doesn't match any of the given types

Methods

required()
Call Signature

required(): JsonValue

Defined in: src/dessert/deserialization/types.d.ts:392

Turn the remaining arguments, properties, and children into a JSON value

After calling this function, all remaining arguments, properties, and children of the context have been consumed. Further calls to any of the context's utilities will return undefined or throw, depending on how the utility handles an empty context.

Returns

JsonValue

Throws

If the context doesn't contain a valid JSON value

Throws

If the context is empty

Call Signature

required<T>(...types): JsonTypeOf<T>

Defined in: src/dessert/deserialization/types.d.ts:403

Turn the remaining arguments, properties, and children into a JSON value matching any of the given types

After calling this function, all remaining arguments, properties, and children of the context have been consumed. Further calls to any of the context's utilities will return undefined or throw, depending on how the utility handles an empty context.

Type Parameters
Type Parameter
T extends [JsonType, ...JsonType[]]
Parameters
ParameterType
...typesT
Returns

JsonTypeOf<T>

Throws

If the context doesn't contain a valid JSON value

Throws

If the context is empty

Throws

If the deserialized value doesn't match any of the given types


Property()<Required, IgnoreInvalid>

Defined in: src/dessert/deserialization/types.d.ts:145

Type Parameters

Type ParameterDefault type
Required extends booleanfalse
IgnoreInvalid extends booleanfalse

Property(name): Primitive | Required extends false ? undefined : never

Defined in: src/dessert/deserialization/types.d.ts:152

Return the property with the given name if it exists and it hasn't been returned yet

Parameters

ParameterType
namestring

Returns

Primitive | Required extends false ? undefined : never

Property<T>(name, ...types): Required extends false ? undefined : never | IgnoreInvalid extends true ? undefined : never | TypeOf<T>

Defined in: src/dessert/deserialization/types.d.ts:159

Return the property with the given name if it exists and it hasn't been returned yet

Type Parameters

Type Parameter
T extends [PrimitiveType, ...PrimitiveType[]]

Parameters

ParameterType
namestring
...typesT

Returns

Required extends false ? undefined : never | IgnoreInvalid extends true ? undefined : never | TypeOf<T>

Throws

If the property value does not match any of the given types

Properties

if

if: IgnoreInvalid extends false ? Property<Required, true> : never

Defined in: src/dessert/deserialization/types.d.ts:187

Return undefined instead of throwing if the property doesn't match the given types or enum values


required

required: Required extends false ? Property<true, IgnoreInvalid> : never

Defined in: src/dessert/deserialization/types.d.ts:177

Throw if there is no property with the given name, rather than return undefined


rest

rest: RestProperty<Required, IgnoreInvalid>

Defined in: src/dessert/deserialization/types.d.ts:182

Return all remaining properties rather than only a single named property

Methods

enum()

enum<T>(name, ...values): Required extends false ? undefined : never | IgnoreInvalid extends true ? undefined : never | T[number]

Defined in: src/dessert/deserialization/types.d.ts:169

Return the property with the given name if it exists and it hasn't been returned yet

Type Parameters
Type Parameter
T extends Primitive[]
Parameters
ParameterType
namestring
...valuesT
Returns

Required extends false ? undefined : never | IgnoreInvalid extends true ? undefined : never | T[number]

Throws

If the property value does not equal any of the given values


RestProperty()<Required, IgnoreInvalid>

Defined in: src/dessert/deserialization/types.d.ts:190

Type Parameters

Type ParameterDefault type
Required extends booleanfalse
IgnoreInvalid extends booleanfalse

RestProperty(): Map<string, Primitive>

Defined in: src/dessert/deserialization/types.d.ts:197

Return all remaining properties

Returns

Map<string, Primitive>

RestProperty<T>(...types): Map<string, TypeOf<T>>

Defined in: src/dessert/deserialization/types.d.ts:204

Return all remaining properties

Type Parameters

Type Parameter
T extends [PrimitiveType, ...PrimitiveType[]]

Parameters

ParameterType
...typesT

Returns

Map<string, TypeOf<T>>

Throws

If any remaining property value does not match any of the given types

Properties

if

if: IgnoreInvalid extends false ? RestProperty<Required, true> : never

Defined in: src/dessert/deserialization/types.d.ts:225

Return undefined instead of throwing if the property doesn't match the given types or enum values


required

required: Required extends false ? RestProperty<true, IgnoreInvalid> : never

Defined in: src/dessert/deserialization/types.d.ts:220

Throw if there is no property with the given name, rather than return undefined

Methods

enum()

enum<T>(...values): Map<string, T[number]>

Defined in: src/dessert/deserialization/types.d.ts:213

Return all remaining properties

Type Parameters
Type Parameter
T extends Primitive[]
Parameters
ParameterType
...valuesT
Returns

Map<string, T[number]>

Throws

If any remaining property value does not equal any of the given values


SerializationContext

Defined in: src/dessert/serialization/types.d.ts:51

Wrapper around a Node to help serializing a value into a single Node

Properties

argument()

readonly argument: (value) => void

Defined in: src/dessert/serialization/types.d.ts:67

Add an argument to the serialized node

Parameters
ParameterType
valuePrimitive
Returns

void

tagged()

Add an argument with a tag to the serialized node

Parameters
ParameterType
tagstring
valuePrimitive
Returns

void


child()

readonly child: <P>(name, serializer, ...params) => void

Defined in: src/dessert/serialization/types.d.ts:96

Serialize a child node and add it to this serialized node

Run the given serializer to create a node with the given name and add that node as child to the node being serialized

Type Parameters
Type Parameter
P extends unknown[]
Parameters
ParameterType
namestring
serializerSerializer<P>
...paramsP
Returns

void

tagged()

Run the given serializer to create a node with the given name and tag and add that node as child to the node being serialized

Type Parameters
Type Parameter
P extends unknown[]
Parameters
ParameterType
tagstring
namestring
serializerSerializer<P>
...paramsP
Returns

void


json()

readonly json: (value) => void

Defined in: src/dessert/serialization/types.d.ts:119

Serialize a JSON value

Parameters
ParameterType
valueJsonValue
Returns

void


property()

readonly property: (name, value) => void

Defined in: src/dessert/serialization/types.d.ts:78

Set a property on the serialized node

If the same property was already set previously, the previous value is overwritten.

Parameters
ParameterType
namestring
valuePrimitive
Returns

void

tagged()

Set a property with a tag on the serialized node

If the same property was already set previously, the previous value is overwritten.

Parameters
ParameterType
tagstring
namestring
valuePrimitive
Returns

void


run()

readonly run: <P>(serializer, ...parameters) => void

Defined in: src/dessert/serialization/types.d.ts:124

Run the given serializer

Type Parameters
Type Parameter
P extends unknown[]
Parameters
ParameterType
serializerSerializerFromContext<P>
...parametersP
Returns

void


source()

readonly source: (sourceCtx) => void

Defined in: src/dessert/serialization/types.d.ts:63

Link this serialization to a prior deserialization

Attaching a deserialization context as source to this serialization allows the serialization to keep track of metadata in the original text. For example, an effort is made to preserve formatting and comments.

Parameters
ParameterType
sourceCtxundefined | null | DeserializationContext
Returns

void


target

readonly target: "node"

Defined in: src/dessert/serialization/types.d.ts:55

Marker property that can be used to distinguish between a DocumentSerializationContext and SerializationContext.

Type Aliases

ArgumentReturnType<T, Required, ReturnMultiple, IgnoreInvalid>

ArgumentReturnType<T, Required, ReturnMultiple, IgnoreInvalid>: ReturnMultiple extends false ? T | Required extends false ? undefined : never | IgnoreInvalid extends true ? undefined : never : Required extends true ? IgnoreInvalid extends false ? [T, ...T[]] : T[] : T[]

Defined in: src/dessert/deserialization/types.d.ts:63

Return type of the DeserializationContext's argument

The actual type depends on whether you're using ctx.argument() with or without .if, .required, and/or .rest.

Type Parameters

Type ParameterDefault type
T-
Required extends boolean-
ReturnMultiple extends boolean-
IgnoreInvalid extends booleanfalse

Deserialized<T>

Deserialized<T>: T extends Deserializer<infer V, any[]> ? V : never

Defined in: src/dessert/deserialization/types.d.ts:54

Helper type to extract the type a deserializer supports

Type Parameters

Type Parameter
T extends Deserializer<unknown, any[]>

Deserializer<T, P>

Deserializer<T, P>: DeserializerFromContext<T, P> | { deserializeFromNode: T; }

Defined in: src/dessert/deserialization/types.d.ts:44

Function or object capable of deserializing objects of type T

There are three types of deserializers:

All three variants can be parameterized. Parameters can be passed via deserialize or any of the child/children functions on a DeserializationContext

Type Parameters

Type ParameterDefault type
T-
P extends unknown[][]

Type declaration

DeserializerFromContext<T, P>

{ deserializeFromNode: T; }

deserializeFromNode()

Function that is given a Node

Parameters
ParameterType
nodeNode
...parametersP
Returns

T


DeserializerFromContext<T, P>

DeserializerFromContext<T, P>: (ctx, ...parameters) => T | { deserialize: T; }

Defined in: src/dessert/deserialization/types.d.ts:26

Function or object capable of deserializing objects of type T using a DeserializationContext

Type Parameters

Type ParameterDefault type
T-
P extends unknown[][]

Type declaration

(ctx, ...parameters) => T

Parameters

ParameterType
ctxDeserializationContext
...parametersP

Returns

T

{ deserialize: T; }

deserialize()

Function that is given a DeserializationContext

Parameters
ParameterType
ctxDeserializationContext
...parametersP
Returns

T


DocumentSerializer<P>

DocumentSerializer<P>: (ctx, ...parameters) => void | { serialize: void; }

Defined in: src/dessert/serialization/types.d.ts:41

Function or object capable of serializing a Document

There are three types of serializers:

Both types can accept parameters, in which case these parameters have to be passed when calling serialize.

Type Parameters

Type Parameter
P extends unknown[]

Type declaration

(ctx, ...parameters) => void

Parameters

ParameterType
ctxDocumentSerializationContext
...parametersP

Returns

void

{ serialize: void; }

serialize()

Function that is given a DocumentSerializationContext

Parameters
ParameterType
ctxDocumentSerializationContext
...parametersP
Returns

void


JsonType

JsonType: PrimitiveType | "object" | "array"

Defined in: src/dessert/deserialization/types.d.ts:342

String representation of the JsonValue types


JsonTypeOf<T>

JsonTypeOf<T>: object[T[number]]

Defined in: src/dessert/deserialization/types.d.ts:347

Helper type to turn JsonTypes into the corresponding JsonValue types

Type Parameters

Type Parameter
T extends JsonType[]

PrimitiveType

PrimitiveType: "boolean" | "null" | "number" | "string"

Defined in: src/dessert/deserialization/types.d.ts:7

String representation of the Primitive types


PropertyReturnType<T, Required, ReturnMultiple, IgnoreInvalid>

PropertyReturnType<T, Required, ReturnMultiple, IgnoreInvalid>: ReturnMultiple extends false ? T | Required extends false ? undefined : never | IgnoreInvalid extends true ? undefined : never : Map<string, T>

Defined in: src/dessert/deserialization/types.d.ts:133

Return type of the DeserializationContext's property

The actual type depends on whether you're using ctx.property with or without .if, .required, and/or .rest.

Type Parameters

Type ParameterDefault type
T-
Required extends boolean-
ReturnMultiple extends boolean-
IgnoreInvalid extends booleanfalse

Serializer<P>

Serializer<P>: SerializerFromContext<P> | { serializeToNode: Node; }

Defined in: src/dessert/serialization/types.d.ts:25

Function or object capable of serializing a Node

There are three types of serializers:

  • Functions that are given a SerializationContext
  • A value (usually a class instance) with a serialize function that is given a SerializationContext
  • A value (usually a class instance) with a serializeTNode function that returns a Node

All three of these types can accept parameters, in which case these parameters have to be passed when calling serialize.

Type Parameters

Type Parameter
P extends unknown[]

Type declaration

SerializerFromContext<P>

{ serializeToNode: Node; }

serializeToNode()

Function to serialize a Node of the given name

Parameters
ParameterType
namestring
...parametersP
Returns

Node


SerializerFromContext<P>

SerializerFromContext<P>: (ctx, ...parameters) => void | { serialize: void; }

Defined in: src/dessert/serialization/types.d.ts:8

Function or object capable of serializing via a SerializationContext

Type Parameters

Type Parameter
P extends unknown[]

Type declaration

(ctx, ...parameters) => void

Parameters

ParameterType
ctxSerializationContext
...parametersP

Returns

void

{ serialize: void; }

serialize()

Function that is given a SerializationContext

Parameters
ParameterType
ctxSerializationContext
...parametersP
Returns

void


TypeOf<T>

TypeOf<T>: object[T[number]]

Defined in: src/dessert/deserialization/types.d.ts:12

Helper type to turn a list of PrimitiveTypes into matching Primitive types

Type Parameters

Type Parameter
T extends PrimitiveType[]

Functions

concat()

concat(...docsAndNodes): Document

Defined in: src/dessert/serialization/public-utils.js:12

Create a document containing the given nodes in order

If documents are passed, all nodes from those documents will be inserted in order into the returned document.

Parameters

ParameterTypeDescription
...docsAndNodes(Node | Document)[]

Returns

Document


deserialize()

deserialize<T, P>(node, deserializer, ...parameters): T

Defined in: src/dessert/deserialization/deserialize.js:728

Deserialize the given Document or Node using the given deserializer.

If this function is given a Document, it will be wrapped with a nameless node (using "-" as name) without any arguments or properties.

Type Parameters

Type ParameterDefault typeDescription
T-
P extends unknown[][]

Parameters

ParameterTypeDescription
nodeNode | Document
deserializerDeserializer<T, P>
...parametersP

Returns

T


firstMatchingDeserializer()

firstMatchingDeserializer<T>(...deserializers): Deserializer<Deserialized<T[number]>>

Defined in: src/dessert/deserialization/public-utils.js:59

Create a deserializer that tries all of the given deserializers until it finds one that doesn't throw an error.

The returned deserializer throws an AggregateError if all of the given deserializers throw on a certain node.

Type Parameters

Type ParameterDescription
T extends Deserializer<unknown>[]

Parameters

ParameterTypeDescription
...deserializersT

Returns

Deserializer<Deserialized<T[number]>>


format()

format<P>(serializer, ...parameters): string

Defined in: src/dessert/serialization/serialize.js:181

Serialize a KDL document and format it to a string

Type Parameters

Type ParameterDescription
P extends unknown[]

Parameters

ParameterTypeDescription
serializerDocumentSerializer<P>
...parametersP

Returns

string


parse()

parse<T>(text, deserializer): T

Defined in: src/dessert/deserialization/deserialize.js:857

Parse the given KDL text as a document and run it through the given deserializer

The deserializer will only have access to children, as a document has no arguments or properties.

This is a small function that runs parse and then runs the resulting Document through deserialize.

Type Parameters

Type ParameterDescription
T

Parameters

ParameterTypeDescription
textstring | ArrayBuffer | DataView | Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array
deserializerDeserializer<T, []>

Returns

T


repeat()

repeat<A, T>(fn, ...args): undefined | [T, ...T[]]

Defined in: src/dessert/deserialization/public-utils.js:20

Call the given function with the given arguments until it returns undefined

This function returns all return values apart from the final undefined. If the given function returned undefined on the first call, this function returns undefined.

Type Parameters

Type ParameterDescription
A extends unknown[]
T

Parameters

ParameterTypeDescription
fn(...args) => undefined | T
...argsA

Returns

undefined | [T, ...T[]]


serialize()

Call Signature

serialize<P>(name, serializer, ...params): Node

Defined in: src/dessert/serialization/types.d.ts:193

Create a node with the given name using the given serializer

Type Parameters
Type Parameter
P extends unknown[]
Parameters
ParameterTypeDescription
namestringThe name of the node
serializerSerializer<P>Serializer to call
...paramsPParameters to pass along to the serializer
Returns

Node

Call Signature

serialize<P>(name, serializer, ...params): Document

Defined in: src/dessert/serialization/types.d.ts:208

Create a document using the given serializer

The first parameter can be null or typeof Document. Passing null is easiest, but it won't work when using TypeScript with "strictNullChecks" disabled.

Type Parameters
Type Parameter
P extends unknown[]
Parameters
ParameterTypeDescription
namenull | typeof DocumentNull or a refernece to the Document class
serializerDocumentSerializer<P>Serializer to call
...paramsPParameters to pass along to the serializer
Returns

Document

Class: KdlDeserializeError

Defined in: src/dessert/deserialization/error.js:6

Error thrown if deserialization fails

Extends

  • Error

Constructors

new KdlDeserializeError()

new KdlDeserializeError(message, options): KdlDeserializeError

Defined in: src/dessert/deserialization/error.js:21

Parameters

ParameterTypeDescription
messagestring
optionsErrorOptions & object

Returns

KdlDeserializeError

Overrides

Error.constructor

Properties

cause?

optional cause: unknown

Defined in: node_modules/typescript/lib/lib.es2022.error.d.ts:26

Inherited from

Error.cause


location

location: Entry | Node

Defined in: src/dessert/deserialization/error.js:15

Location at which the error occured


message

message: string

Defined in: node_modules/typescript/lib/lib.es5.d.ts:1077

Inherited from

Error.message


stack?

optional stack: string

Defined in: node_modules/typescript/lib/lib.es5.d.ts:1078

Inherited from

Error.stack


prepareStackTrace()?

static optional prepareStackTrace: (err, stackTraces) => any

Defined in: node_modules/@types/node/globals.d.ts:143

Optional override for formatting stack traces

Parameters

ParameterType
errError
stackTracesCallSite[]

Returns

any

See

https://v8.dev/docs/stack-trace-api#customizing-stack-traces

Inherited from

Error.prepareStackTrace


stackTraceLimit

static stackTraceLimit: number

Defined in: node_modules/@types/node/globals.d.ts:145

Inherited from

Error.stackTraceLimit

Methods

captureStackTrace()

static captureStackTrace(targetObject, constructorOpt?): void

Defined in: node_modules/@types/node/globals.d.ts:136

Create .stack property on a target object

Parameters

ParameterType
targetObjectobject
constructorOpt?Function

Returns

void

Inherited from

Error.captureStackTrace

LL(1) Parser

This package contains an LL(1) parser, i.e. the parser iterates over the tokens without having to backtrack or look ahead. The parser achieves this by using a modified version of the KDL grammar defined in the KDL spec.

The parser iterates over the text per code point or per grapheme, depending on the value of the graphemeLocations option. It then looks at the first code point of every value (graphemes can contain multiple code points) and filters out code points disallowed by the KDL spec.

The parser works in two stages. First, it turns the stream of code points (or graphemes) into a stream of tokens. Then it iterates over the token stream to result in the KDL document.

The diagrams on this page are rendered using railroad-diagrams, a lovely library by Tab Atkins Jr, who happens to be involved in KDL too!

Error handling

The tokenizer and parser can throw two kinds of errors: recoverable and non-recoverable. In fact, a recoverable error is not really thrown but rather tracked separately (in the token or in the parser context).

At the end, if both the tokenizer and parser have found no non-recoverable error, all recoverable errors are thrown in a single error object. This gives the calling code more context to what is wrong in the document, with the option to show the human who wrote the KDL document everything that's wrong in their document in one go.

Tokenizer

The first step of the parser turns the stream of code points (or graphemes) into a stream of tokens. A token is an object with the following properties:

  • type: the token type
  • text: the text of the token, this can contain multiple code points / graphemes
  • start: the location of the first code point of this token in the source text
  • end: the location of the first code point after this token in the source text
  • error: any recoverable error that occurred while processing the text for this token

The start and end locations are used when throwing errors upon encountering invalid KDL text, so these are stored even if the storeLocations option is false. These locations contain three properties: offset is the zero-indexed location of the character in the text, line and column are the one-indexed line and column positions. The offset can be used to programmatically find the token in the text, line and column are more interesting for human readers to e.g. see where in the document they've made a mistake.

Token types are stored as integer, rather than a human readable string because of two reasons. Firstly, "human readable" doesn't mean "the person running the parser understands it", so the usefulness of string types is questionable. Secondly, string comparison is slower than number comparison.

That speed bump granted by number comparison is also why the tokenizer looks at the code point's integer value to assign split the text in to tokens rather than compare string values. Regular expressions are avoided entirely.

Parser

The parser is a "recursive descent" parser. That means the starts at the top-level, e.g. parseDocument when asked to parse a document, and that function recurses into other parser functions, e.g. parseNode to parse each individual node.

document

In the KDL spec all line-space are used as line-space* so to simplify this grammar, the line-space itself takes care of the "zero or more" part.

The document non-terminal is used in node-children below, because distinguishing between node and final-node as defined in the KDL spec is impossible without unbounded look-ahead. Instead, the document non-terminal is modified to support ending on a base-node with or without node-terminator.

There's one downside to this rewritten non-terminal: It works in the LL(1) parser but I am unable to write it down in BNF or any derivative. If someone else has any idea, feel free to make the necessary changes!

node-space

The KDL spec's node-space is always used with either the + or * modifier. Instead of doing the same, the node-space in this grammar is it's own +, so it's either used plain for + or marked optional for *.

The official node-space is written as ws* escline ws* | ws+, but since node-space is only ever used with + or *, it is functionally equivalent with escline | ws.

line-space

Compared to the line-space defined in the KDL spec, this version includes its own "zero or more" operator and it inlines node-space instead of referencing the non-terminal.

slashdash

base-node

The base-node non-terminal differs quite a bit from the one described in the KDL spec in order to remove any ambiguity for our LL(1) parser.

The diagram above fails to show two things:

  • There can only be one non-slashdashed node-children block in the base-node. This is validated separately in the parser.
  • The node-prop-or-arg rule actually already checks for the existence of node-space. That result is used in parsing the base-node, instead of requiring multiple consecutive node-spaces (which would be impossible anyway since node-space is a repetition).

node

node-prop-or-arg

The node-prop-or-arg non-terminal is very different from its sibling in the KDL spec in order to remove any need for look-ahead:

  • If the first token is a tag (called type in the spec), then it must be an argument
  • If the first token is a number or a keyword, then it must be an argument
  • If the first token is a string, then we need to check if there's an equals sign.

Looking for the equals sign requires unbounded lookahead thanks to the allowed node-space between the property name and the equals sign. By changing this non-terminal so it also consumes any node-space that comes after the property or argument, we can remove the need for the look-ahead.

node-children

node-terminator

The document non-terminal supports ending on a node without node-terminator, so this non-terminal doesn't need to include EOF.

tag

escline

multiline-comment

single-line-comment

value

keyword

number

string

The parser itself is greatly simplified and very lenient when it comes to strings, with post-processing added to filter out invalid strings. All multiline quoted and raw strings are post-processed to remove leading whitespace. All quoted strings are post-processed to replace any escapes.