/** * TypeScript type definitions for links-notation * * This module provides TypeScript type definitions for the Links Notation parser. * Links Notation is a format for representing relationships between entities. */ /** * Represents a link with an optional identifier and values. * * A Link can represent: * - A simple reference: `new Link('id')` * - A link with values: `new Link('id', [new Link('child1'), new Link('child2')])` * - A link without an id: `new Link(null, [...])` */ export class Link { /** * Optional identifier for the link */ id: string | null; /** * Array of child links/values */ values: Link[]; /** * Create a new Link * @param id - Optional identifier for the link * @param values - Optional array of nested links * @throws {TypeError} If values is not an array or null */ constructor(id?: string | null, values?: Link[] | null); /** * Convert link to string representation * @returns String representation of the link */ toString(): string; /** * Get formatted string of all values * @returns Space-separated string of values */ getValuesString(): string; /** * Simplify the link structure by unwrapping single-value containers * @returns Simplified link */ simplify(): Link; /** * Combine this link with another link * @param other - The link to combine with * @returns Combined link */ combine(other: Link): Link; /** * Convert to string using either just ID or full format * @returns String representation */ toLinkOrIdString(): string; /** * Check equality with another Link * @param other - Object to compare with * @returns True if links are equal */ equals(other: any): boolean; /** * Format the link as a string * @param lessParentheses - If true, omit parentheses where safe; or a FormatOptions/FormatConfig object * @param isCompoundValue - If true, this is a value in a compound link * @returns Formatted string */ format( lessParentheses?: boolean | FormatOptions | FormatConfig, isCompoundValue?: boolean ): string; /** * Check if a string needs to be wrapped in parentheses * @param str - The string to check * @returns True if parentheses are needed */ needsParentheses(str: string): boolean; /** * Get string representation of a value * @param value - The value to stringify * @returns String representation */ static getValueString(value: Link): string; /** * Escape a reference string by adding quotes if necessary * @param reference - The reference to escape * @returns Escaped reference */ static escapeReference( reference: string, options?: EscapeReferenceOptions ): string; /** Decode one escaped reference. Link IDs returned by a parser are already decoded. */ static unescapeReference(reference: string): string; } export interface EscapeReferenceOptions { /** Leave ordinary single-space prose unquoted for use on document lines. */ minimal?: boolean; } /** Escape a reference. Minimal mode doubles enclosing quotes; default formatting uses n-quotes. */ export function escapeReference( reference: string, options?: EscapeReferenceOptions ): string; /** Decode a complete escaped reference, including n-quotes and versioned literals. */ export function unescapeReference(reference: string): string; /** * Parser options for configuring the parser behavior */ /** * How deep links may nest when nothing says otherwise (64). The same limit * applies in every Links Notation implementation. */ export const DEFAULT_MAX_DEPTH: number; export interface ParserOptions { /** * Maximum input size in bytes (default: 10MB) */ maxInputSize?: number; /** * How deep links may nest: every parenthesized group and every indentation * level is one level. A document nested deeper is refused with a ParseError * whose maxDepth is set (default: 64) */ maxDepth?: number; /** * If false, read `#` as an ordinary character instead of the start of a * comment (default: true) */ comments?: boolean; } /** * Parser for Links Notation format * * The Parser class converts Links Notation strings into Link objects. */ export class Parser { /** * Maximum input size in bytes */ maxInputSize: number; /** * Maximum nesting depth */ maxDepth: number; /** * Whether `#` starts a comment that runs to the end of its line */ comments: boolean; /** * Create a new Parser instance * @param options - Parser options */ constructor(options?: ParserOptions); /** * Parse Lino notation text into Link objects * @param input - The Lino notation text to parse * @returns Array of parsed Link objects * @throws {ParseError} If the text does not parse */ parse(input: string): Link[]; /** Read the indentation tree without expanding it into path combinations. */ parseGroups(input: string): IndentedGroup[]; } /** A parsed line and the immediately indented lines below it. */ export interface IndentedGroup extends LinksGroup { element: Link; children: IndentedGroup[]; } export interface IndentedDocumentOptions extends ParserOptions { /** Multiple children become an array (default) or text joined with newlines. */ multipleValues?: 'array' | 'join'; } /** * Read parent/children text. Repeated parents accumulate children in order. * No children yields [], one yields a string, multiple yield an array by default. * Named links with values and grandchildren are rejected. */ export function parseIndentedDocument( input: string, options?: IndentedDocumentOptions ): Map; /** * Write minimally quoted text with two-space indentation and a final newline. * Multiline strings remain one encoded reference; array entries become children. */ export function formatIndentedDocument( entries: ReadonlyMap ): string; /** Options for incremental parsing. */ export interface StreamParserOptions extends ParserOptions { /** Canonical parser instance to use for completed records. */ parser?: Parser; /** Largest unresolved record retained in memory (default: 10MB). */ maxBufferSize?: number; /** Retain emitted links for end() and drain() (default: true). */ collect?: boolean; } /** Position immediately after the last character written. */ export interface StreamPosition { offset: number; line: number; column: number; buffered: number; } /** Canonical parse error translated to coordinates in the complete stream. */ export class StreamParseError extends Error { cause: Error; offset: number; line: number; column: number; found: string | null; lineText: string; snippet: string; } /** * Incrementally emits complete top-level Links Notation records. Its listener * methods mirror Node.js EventEmitter without depending on Node built-ins. */ export class StreamParser { parser: Parser; comments: boolean; maxBufferSize: number; collect: boolean; constructor(options?: StreamParserOptions); /** Feed a chunk and return links made complete by it. */ write(chunk: string): Link[]; /** Finish the stream, optionally after consuming one final chunk. */ end(chunk?: string): Link[]; /** Return and forget retained links. */ drain(): Link[]; /** Reuse this parser while preserving its options and listeners. */ reset(): this; /** Return the absolute stream position and unresolved buffer size. */ position(): StreamPosition; on(event: 'link', listener: (link: Link) => void): this; on(event: 'end', listener: (links: Link[]) => void): this; on(event: 'error', listener: (error: Error) => void): this; once(event: 'link', listener: (link: Link) => void): this; once(event: 'end', listener: (links: Link[]) => void): this; once(event: 'error', listener: (error: Error) => void): this; off(event: string, listener: (...arguments_: any[]) => void): this; addListener(event: string, listener: (...arguments_: any[]) => void): this; removeListener(event: string, listener: (...arguments_: any[]) => void): this; prependListener( event: string, listener: (...arguments_: any[]) => void ): this; prependOnceListener( event: string, listener: (...arguments_: any[]) => void ): this; removeAllListeners(event?: string): this; emit(event: string, ...arguments_: any[]): boolean; listeners(event: string): Array<(...arguments_: any[]) => void>; listenerCount(event: string): number; eventNames(): string[]; /** Lazily parse a synchronous iterable of chunks. */ static parse( chunks: Iterable, options?: StreamParserOptions ): IterableIterator; /** Lazily parse an asynchronous iterable of chunks. */ static parseAsync( chunks: AsyncIterable | Iterable, options?: StreamParserOptions ): AsyncIterableIterator; } /** * Blank out every comment in a document, keeping its length so that every * character stays at the offset it was written at. * @param document - The document to read * @returns The document, of the same length, without its comments */ export function stripComments(document: string): string; /** * The position a parse stopped at, as the generated parser reports it */ export interface ParseErrorLocation { start: { offset: number; line: number; column: number }; end: { offset: number; line: number; column: number }; } /** * The error thrown when a document does not parse * * The message says where the document stopped making sense and quotes the * offending line with a caret under it. */ export class ParseError extends Error { /** * Offset of the offending position from the start of the document */ offset: number; /** * Line the offending position is on, counted from 1 */ line: number; /** * Column the offending position is at, counted from 1 */ column: number; /** * The character found instead, or null at the end of the document */ found: string | null; /** * The offending line, as written, without its line ending */ lineText: string; /** * The offending line with a caret under the offending column */ snippet: string; /** * The position the generated parser reported */ location: ParseErrorLocation; /** * The deepest nesting allowed, when the document is nested deeper than * that; null for any other error */ maxDepth: number | null; } /** * Options for formatting links */ export interface FormatOptionsConfig { /** * If true, omit parentheses where safe (default: false) */ lessParentheses?: boolean; /** * Maximum line length before auto-indenting (default: 80) */ maxLineLength?: number; /** * If true, indent lines exceeding maxLineLength (default: false) */ indentLongLines?: boolean; /** * Maximum number of references before auto-indenting (default: null) */ maxInlineRefs?: number | null; /** * If true, group consecutive links with same ID (default: false) */ groupConsecutive?: boolean; /** * String to use for indentation (default: " ") */ indentString?: string; /** * If true, prefer inline format when under thresholds (default: true) */ preferInline?: boolean; } /** * FormatOptions for Lino notation formatting. * * Provides configuration options for controlling how Link objects are formatted. */ export class FormatOptions { /** * If true, omit parentheses where safe */ lessParentheses: boolean; /** * Maximum line length before auto-indenting */ maxLineLength: number; /** * If true, indent lines exceeding maxLineLength */ indentLongLines: boolean; /** * Maximum number of references before auto-indenting */ maxInlineRefs: number | null; /** * If true, group consecutive links with same ID */ groupConsecutive: boolean; /** * String to use for indentation */ indentString: string; /** * If true, prefer inline format when under thresholds */ preferInline: boolean; /** * Create a new FormatOptions instance * @param options - Configuration options */ constructor(options?: FormatOptionsConfig); /** * Check if line should be indented based on length * @param line - The line to check * @returns True if line should be indented based on length threshold */ shouldIndentByLength(line: string): boolean; /** * Check if link should be indented based on reference count * @param refCount - Number of references in the link * @returns True if link should be indented based on reference count threshold */ shouldIndentByRefCount(refCount: number): boolean; } /** * FormatConfig is an alias for FormatOptions to maintain API consistency * with the Python implementation. * * This is an alias for FormatOptions to maintain API consistency across languages. * Python uses 'FormatConfig', so this export provides the same name for JavaScript. */ export class FormatConfig extends FormatOptions { /** * Create a new FormatConfig instance * @param options - Configuration options */ constructor(options?: FormatOptionsConfig); } /** * Container for grouping related links */ export class LinksGroup { /** * The element associated with this group */ element: any; /** * Child groups or links */ children: (LinksGroup | Link)[]; /** * Create a new LinksGroup * @param element - The element for this group * @param children - Optional array of child groups or links */ constructor(element: any, children?: (LinksGroup | Link)[]); /** * Convert the group to a flat list * @returns Flattened list of elements */ toList(): any[]; /** * Convert the group to a string representation * @returns String representation of the group */ toString(): string; } /** * Format an array of links as a string * @param links - Array of links to format * @param lessParentheses - If true, omit parentheses where safe; or a FormatOptions/FormatConfig object * @returns Formatted string with each link on a new line */ export function formatLinks( links: Link[], lessParentheses?: boolean | FormatOptions | FormatConfig ): string; /** Binary links notation v1: bigint preserves unsigned 64-bit references. */ export class External { value: bigint; constructor(value: bigint | number); } export class ArityRange { min: bigint; max: bigint | null; constructor(min?: bigint | number, max?: bigint | number | null); contains(length: bigint | number): boolean; readonly fixed: boolean; static parse(text: string): ArityRange; } export interface BinaryLimits { maxLinks: number; maxReferences: number; maxNodes: number; maxStringBytes: number; maxDepth: number; } export class DecodeLimits implements BinaryLimits { maxLinks: number; maxReferences: number; maxNodes: number; maxStringBytes: number; maxDepth: number; constructor(values?: Partial); static unlimited(): DecodeLimits; } export class BinaryLinoOptions { externalReferences: boolean; arity: ArityRange; packedWidths: boolean; constructor( externalReferences?: boolean, arity?: ArityRange, packedWidths?: boolean ); static ofPacket(packet: LinksPacket): BinaryLinoOptions; } export type PacketReference = bigint | number | External; export type AddressedLink = [bigint | number, PacketReference[]]; export class Section { gap: bigint; arity: ArityRange; width: number; links: PacketReference[][]; constructor( gap: bigint | number, arity: ArityRange, width: number, links: PacketReference[][] ); } export class PacketReader { bytes: Uint8Array; offset: number; constructor(bytes: Uint8Array, offset?: number); read(limits?: DecodeLimits): LinksPacket | null; } export class LinksPacket { externalReferences: boolean; sections: Section[]; constructor(externalReferences?: boolean, sections?: Section[]); links(): [bigint, (bigint | External)[]][]; validate(limits?: DecodeLimits): this; toBytes(limits?: DecodeLimits): Uint8Array; static fromBytes(bytes: Uint8Array, limits?: DecodeLimits): LinksPacket; static parseLinks(text: string): [bigint, (bigint | External)[]][]; static pack( externalReferences: boolean, links: AddressedLink[], packedWidths?: boolean ): LinksPacket; } export class BinaryLinoCodec { options: BinaryLinoOptions; limits: DecodeLimits; constructor(options?: BinaryLinoOptions, limits?: DecodeLimits); encodePacket(document: Link[]): LinksPacket; encode(document: Link[]): Uint8Array; decodePacket(packet: LinksPacket): Link[]; decode(bytes: Uint8Array): Link[]; parseDocument(text: string, parser?: Parser): Link[]; formatDocument(document: Link[]): string; encodeText(text: string, parser?: Parser): Uint8Array; decodeText(bytes: Uint8Array): string; } export function formatBinaryDocument(document: Link[]): string; export function formatBinaryReference(reference: string): string; /** Encode exact Unicode as a version 1 UTF-8 hex literal (~1{...}). Throws on unpaired surrogates. */ export function encodeReferenceLiteral(text: string): string; /** Decode a complete literal. Throws on malformed hex, UTF-8, or unsupported versions. */ export function decodeReferenceLiteral(literal: string): string;