JavaScript parser and stringifier for YAML documents with complete YAML 1.1 and 1.2 support
Extensible schema system with YAML 1.1 and 1.2 support, custom tag definitions, and comprehensive configuration options for parsing, stringifying, and document handling. This provides complete control over YAML processing behavior and output formatting.
The Schema class manages YAML type definitions, tag handlers, and version-specific behaviors.
class Schema {
/** Schema name identifier */
name: string;
/** Supported YAML version */
version: '1.1' | '1.2' | 'next';
/** Schema tags collection */
tags: readonly Tag[];
/**
* Create schema with options
* @param options - Schema configuration options
*/
constructor(options: SchemaOptions);
/**
* Create deep clone of schema
* @returns Cloned schema instance
*/
clone(): Schema;
/**
* Get tag by name or class
* @param name - Tag name or constructor
* @returns Tag definition or undefined
*/
getTag(name: string | { new(...args: any[]): any }): Tag | undefined;
}
interface SchemaOptions {
/** YAML version to support */
version?: '1.1' | '1.2' | 'next';
/** Built-in schema to extend */
schema?: 'core' | 'failsafe' | 'json' | 'yaml-1.1';
/** Additional custom tags */
customTags?: (TagId | Tag)[];
/** Map entry sorting function */
sortMapEntries?: boolean | ((a: Pair, b: Pair) => number);
/** Merge key handling */
merge?: boolean;
/** Resolve unknown tags */
resolveUnknownTags?: boolean;
}Usage Examples:
import { Schema, parseDocument, stringify } from "yaml";
// Create custom schema
const customSchema = new Schema({
version: '1.2',
schema: 'core',
customTags: [
{
tag: '!date',
resolve: (str) => new Date(str),
stringify: (date) => date.toISOString().split('T')[0]
},
{
tag: '!env',
resolve: (str) => process.env[str] || '',
stringify: (value) => `\${${value}}`
}
],
sortMapEntries: true
});
// Use schema in parsing
const doc = parseDocument(`
created: !date 2023-12-01
api_key: !env API_KEY
config:
timeout: 30
retries: 3
`, { schema: customSchema });
console.log(doc.toJS());
// Result: { created: Date(2023-12-01), api_key: 'actual-env-value', config: {...} }
// Clone and modify schema
const extendedSchema = customSchema.clone();
// Add more custom tags to extendedSchemaThe library provides several built-in schemas for different YAML specifications and use cases.
// Built-in schema types
type BuiltinSchema = 'core' | 'failsafe' | 'json' | 'yaml-1.1';
/**
* Get built-in schema by name
* - 'failsafe': Basic YAML types only (strings, sequences, mappings)
* - 'json': JSON-compatible types (null, boolean, number, string, array, object)
* - 'core': YAML 1.2 core schema with common types
* - 'yaml-1.1': YAML 1.1 schema with extended types
*/Usage Examples:
import { parseDocument, stringify } from "yaml";
// JSON-compatible parsing
const jsonDoc = parseDocument(`
number: 42
boolean: true
null_value: null
array: [1, 2, 3]
object: {key: value}
`, { schema: 'json' });
// YAML 1.1 with extended types
const yaml11Doc = parseDocument(`
timestamp: 2023-12-01 10:30:00
binary: !!binary |
R0lGODlhDAAMAIQAAP//9/X17unM
octal: 0o755
set: !!set
? item1
? item2
? item3
ordered_map: !!omap
- key1: value1
- key2: value2
`, { schema: 'yaml-1.1' });
// Core schema (default for YAML 1.2)
const coreDoc = parseDocument(`
string: hello world
integer: 42
float: 3.14159
boolean: true
null_value: null
timestamp: 2023-12-01T10:30:00Z
`, { schema: 'core' });Comprehensive options for controlling YAML parsing behavior.
interface ParseOptions {
/** Keep CST (Concrete Syntax Tree) nodes in parsed output */
keepCstNodes?: boolean;
/** Keep node type information in output */
keepNodeTypes?: boolean;
/** Keep Uint8Array instances in JSON output instead of converting */
keepBlobsInJSON?: boolean;
/** Maximum number of alias nodes to resolve (prevents circular references) */
maxAliasCount?: number;
/** Add line/column position info to error messages */
prettyErrors?: boolean;
/** Line position tracker for error reporting */
lineCounter?: LineCounter | boolean;
/** Log level for parsing messages */
logLevel?: LogLevelId;
/** Enable strict parsing mode */
strict?: boolean;
/** Unique key requirement in mappings */
uniqueKeys?: boolean;
/** Version of YAML specification to follow */
version?: '1.1' | '1.2' | 'next';
}Options for document-level configuration and behavior.
interface DocumentOptions {
/** Anchor prefix for generated anchors */
anchorPrefix?: string;
/** Keep undefined values in output */
keepUndefined?: boolean;
/** Log level for document operations */
logLevel?: LogLevelId;
/** Document version */
version?: '1.1' | '1.2' | 'next';
/** Enable merge key support (<<) */
merge?: boolean;
/** Transform document before conversion */
reviver?: Reviver;
/** Transform document during creation */
replacer?: Replacer;
/** Schema to use for document */
schema?: BuiltinSchema;
/** Custom tags to include */
customTags?: (TagId | Tag)[];
/** Sort map entries */
sortMapEntries?: boolean | ((a: Pair, b: Pair) => number);
/** Convert maps with numeric keys to arrays */
mapAsMap?: boolean;
/** Maximum key length allowed */
maxAliasCount?: number;
}
type Reviver = (this: unknown, key: unknown, value: unknown) => unknown;
type Replacer = (this: unknown, key: string, value: unknown) => unknown | Array<string | number>;Extensive formatting options for controlling YAML string output.
interface ToStringOptions {
/** Use block quote style for multiline strings */
blockQuote?: boolean | 'folded' | 'literal';
/** Default type for object keys */
defaultKeyType?: Scalar.Type | null;
/** Default string representation type */
defaultStringType?: Scalar.Type;
/** Include document directives (%YAML, %TAG) */
directives?: boolean | null;
/** Number of spaces for indentation */
indent?: number;
/** Use block style for sequences */
indentSeq?: boolean | null;
/** Maximum line width before folding */
lineWidth?: number;
/** Minimum content width for single-line collections */
minContentWidth?: number;
/** String representation for null values */
nullStr?: string;
/** Use single quotes by default for strings */
singleQuote?: boolean | null;
/** Document end marker */
docEnd?: boolean;
/** Document start marker */
docStart?: boolean;
/** Comments to preserve */
commentString?: (comment: string) => string;
/** Force explicit keys for flow maps */
flowCollectionPadding?: boolean;
/** Fold options for long lines */
foldOptions?: FoldOptions;
}
interface FoldOptions {
/** Characters that must not be at line end */
lineWidth?: number;
/** Minimum content width */
minContentWidth?: number;
/** Handle content with indicators */
indicatorWidth?: number;
}Usage Examples:
import { stringify, parseDocument } from "yaml";
const data = {
title: "Configuration File",
description: "This is a very long description that should be folded across multiple lines when converted to YAML format for better readability",
servers: [
{ name: "server1", host: "192.168.1.100", port: 8080 },
{ name: "server2", host: "192.168.1.101", port: 8080 }
],
settings: {
timeout: 30,
debug: true,
feature_flags: ["auth", "logging", "monitoring"]
}
};
// Basic formatting
const basic = stringify(data);
// Custom formatting options
const formatted = stringify(data, {
indent: 4, // 4-space indentation
lineWidth: 80, // Maximum line width
blockQuote: 'folded', // Fold long strings
singleQuote: true, // Use single quotes
defaultStringType: 'QUOTE_SINGLE',
indentSeq: false, // Sequences at same level as parent
directives: true, // Include YAML directives
docStart: true, // Include document start marker
nullStr: '~' // Represent null as ~
});
console.log(formatted);
// Output:
// %YAML 1.2
// ---
// title: 'Configuration File'
// description: >-
// This is a very long description that should be folded across multiple
// lines when converted to YAML format for better readability
// servers:
// - name: 'server1'
// host: '192.168.1.100'
// port: 8080
// - name: 'server2'
// host: '192.168.1.101'
// port: 8080
// settings:
// timeout: 30
// debug: true
// feature_flags: ['auth', 'logging', 'monitoring']Options for converting YAML to JavaScript objects.
interface ToJSOptions {
/** Reviver function for transforming values */
reviver?: Reviver;
/** Convert Map objects to plain objects */
mapAsMap?: boolean;
/** Maximum alias count during resolution */
maxAliasCount?: number;
/** Keep original node objects */
keepScalar?: boolean;
/** Callback for handling unknown tags */
onAnchor?: (value: unknown, count: number) => void;
/** Called when resolving unknown tags */
onTaggedValue?: (value: unknown) => unknown;
}Options for creating AST nodes from JavaScript values.
interface CreateNodeOptions {
/** Anchor prefix for generated anchors */
anchorPrefix?: string;
/** Keep undefined values */
keepUndefined?: boolean;
/** Use flow style for collections */
flow?: boolean;
/** Map key comparison function */
compareKeys?: (a: unknown, b: unknown) => number;
/** Sort map entries */
sortMapEntries?: boolean | ((a: Pair, b: Pair) => number);
/** Tag name for the created node */
tag?: string;
/** Wrap scalars in Scalar objects */
wrapScalars?: boolean;
}Usage Examples:
import { parseDocument, stringify } from "yaml";
// Advanced parsing configuration
const doc = parseDocument(yamlSource, {
// Parsing options
prettyErrors: true,
lineCounter: true,
maxAliasCount: 100,
keepCstNodes: false,
// Document options
version: '1.2',
schema: 'core',
merge: true,
sortMapEntries: true,
keepUndefined: false,
// Schema options
customTags: [
{
tag: '!include',
resolve: (str) => require('fs').readFileSync(str, 'utf8')
}
]
});
// Advanced stringification
const yamlString = stringify(data, {
// String options
indent: 2,
lineWidth: 120,
blockQuote: 'literal',
singleQuote: false,
directives: true,
docStart: true,
docEnd: true,
// Document options
version: '1.2',
sortMapEntries: (a, b) => a.key < b.key ? -1 : 1,
// Creation options
flow: false,
anchorPrefix: 'ref'
});
// JavaScript conversion with options
const jsData = doc.toJS({
reviver: (key, value) => {
// Transform dates
if (typeof value === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(value)) {
return new Date(value);
}
return value;
},
mapAsMap: false,
maxAliasCount: 50
});Define custom YAML tags for specialized data types and processing.
interface Tag {
/** Tag name (e.g., '!!str', '!custom') */
tag: string;
/** Function to resolve tag value from string */
resolve?: (str: string, onError?: (msg: string) => void) => any;
/** Function to stringify value back to YAML */
stringify?: (item: any, ctx?: StringifyContext, onComment?: () => void, onChompKeep?: () => void) => string;
/** Test if value should use this tag */
identify?: (value: any) => boolean;
/** Default type for scalars */
default?: boolean;
/** Tag class (for collection tags) */
class?: 'scalar' | 'seq' | 'map';
/** Format hint */
format?: string;
/** Test function for string format */
test?: RegExp | ((str: string) => boolean);
}
type TagId =
| 'binary' | 'bool' | 'float' | 'int' | 'null' | 'omap' | 'pairs'
| 'set' | 'str' | 'timestamp' | 'yaml';Usage Examples:
import { parseDocument, stringify, Schema } from "yaml";
// Define custom tags
const customTags = [
// Custom date tag
{
tag: '!date',
test: /^\d{4}-\d{2}-\d{2}$/,
resolve: (str) => new Date(str + 'T00:00:00Z'),
stringify: (date) => date.toISOString().split('T')[0]
},
// Environment variable tag
{
tag: '!env',
resolve: (str) => process.env[str] || '',
stringify: (value) => `\${${value}}`
},
// Base64 encoded data
{
tag: '!base64',
resolve: (str) => Buffer.from(str, 'base64'),
stringify: (buffer) => buffer.toString('base64')
}
];
// Use custom tags
const doc = parseDocument(`
created: !date 2023-12-01
api_key: !env API_SECRET_KEY
logo: !base64 iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==
`, { customTags });
console.log(doc.toJS());
// Result: {
// created: Date('2023-12-01T00:00:00.000Z'),
// api_key: 'actual-secret-value',
// logo: Buffer<...>
// }
// Stringify with custom tags
const output = stringify({
created: new Date('2023-12-01'),
data: Buffer.from('hello world', 'utf8')
}, { customTags });
console.log(output);
// created: !date 2023-12-01
// data: !base64 aGVsbG8gd29ybGQ=Install with Tessl CLI
npx tessl i tessl/npm-yaml