Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/ast/from_events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ interface MappingFrame {

type Frame = DocumentFrame | SequenceFrame | MappingFrame

/** @category AST */
interface FromEventsOptions {
source: string
schema: Schema
Expand Down Expand Up @@ -161,6 +162,7 @@ function addNode (state: FromEventsState, node: Node) {
}
}

/** @category AST */
function eventsToAst (events: Event[], options: FromEventsOptions): Document[] {
const state: FromEventsState = {
source: options.source,
Expand Down
2 changes: 2 additions & 0 deletions src/ast/from_js.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
type MappingNode
} from './nodes.ts'

/** @category AST */
interface FromJsOptions {
noRefs?: boolean
skipInvalid?: boolean
Expand Down Expand Up @@ -151,6 +152,7 @@ function build (state: FromJsState, object: unknown): Node | typeof INVALID {

// A JS value is one YAML document. An unrepresentable root becomes an empty
// document, which the presenter renders as an empty string.
/** @category AST */
function jsToAst (input: unknown, schema: Schema, options: FromJsOptions = {}): Document[] {
const state: FromJsState = {
representTypes: buildRepresentTypes(schema),
Expand Down
8 changes: 8 additions & 0 deletions src/ast/nodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import { type DocumentDirective } from '../parser/events.ts'

/** @category Nodes */
class Style {
tagged = false
flow = false
Expand All @@ -13,6 +14,7 @@ class Style {
folded = false
}

/** @category Nodes */
interface NodeBase {
// YAML tag. Untagged nodes carry the semantic resolved tag; tagged nodes carry
// the printable/verbatim tag spelling.
Expand All @@ -27,32 +29,38 @@ interface NodeBase {
blankBefore?: number
}

/** @category Nodes */
interface ScalarNode extends NodeBase {
kind: 'scalar'
value: string
}

/** @category Nodes */
interface SequenceNode extends NodeBase {
kind: 'sequence'
items: Node[]
}

/** @category Nodes */
interface MappingNode extends NodeBase {
kind: 'mapping'
items: Array<{ key: Node, value: Node }>
}

/** @category Nodes */
interface AliasNode extends NodeBase {
kind: 'alias'
// The anchor name this alias points at (`*name`).
anchor: string
}

/** @category Nodes */
type Node = ScalarNode | SequenceNode | MappingNode | AliasNode

// The layer above `Node`: each document wraps one content node plus its own
// markers/directives. Not a member of `Node` — the fields differ. Document
// directives are ordered presentation data.
/** @category Nodes */
interface Document {
contents: Node | null // null = empty document
explicitStart?: boolean // print '---'
Expand Down
2 changes: 2 additions & 0 deletions src/ast/presenter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ ESCAPE_SEQUENCES[0xA0] = '\\_'
ESCAPE_SEQUENCES[0x2028] = '\\L'
ESCAPE_SEQUENCES[0x2029] = '\\P'

/** @category AST */
interface PresenterOptions {
schema: Schema
indent?: number
Expand Down Expand Up @@ -976,6 +977,7 @@ function writeDocumentDirectives (doc: Document) {
}

// Documents → text, including the trailing newline.
/** @category AST */
function present (documents: Document[], options: PresenterOptions): string {
const state = createPresenterState(options)
let result = ''
Expand Down
5 changes: 5 additions & 0 deletions src/ast/visit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,24 @@ import {

// Returned by a visitor to control the walk; anything else (incl. `undefined`)
// descends as usual.
/** @category other */
const VISIT_BREAK = Symbol('visit:break') // stop the whole traversal
/** @category other */
const VISIT_SKIP = Symbol('visit:skip') // don't descend into this node's children

type VisitControl = typeof VISIT_BREAK | typeof VISIT_SKIP | undefined | void

// Traversal-derived position of the current node. Kept off the node itself: a
// node may sit in several places (alias/dedup reuse), so depth/role belong to
// the walk, not the node. `parent.kind` + `isKey` pin the exact slot.
/** @category AST */
interface VisitContext {
depth: number // 0 = document content root
parent: Node | null // enclosing sequence/mapping, null at the root
isKey: boolean // node sits in a mapping key position
}

/** @category AST */
type Visitor = (node: Node, ctx: VisitContext) => VisitControl

// Returns `true` once `VISIT_BREAK` was seen, so callers can unwind the walk.
Expand Down Expand Up @@ -51,6 +55,7 @@ function visitNode (node: Node, visitor: Visitor, ctx: VisitContext): boolean {
}

// Walk every node in the documents, calling `visitor` once per node (pre-order).
/** @category AST */
function visit (documents: Document[], visitor: Visitor): void {
for (const doc of documents) {
if (doc.contents && visitNode(doc.contents, visitor, { depth: 0, parent: null, isKey: false })) return
Expand Down
2 changes: 2 additions & 0 deletions src/parser/constructor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ interface Anchor {
isValueFinal: boolean
}

/** @category Events */
interface ConstructorOptions {
source: string
filename?: string
Expand Down Expand Up @@ -352,6 +353,7 @@ function storeAnchor (
return null
}

/** @category Events */
function constructFromEvents (events: Event[], options: ConstructorOptions): unknown[] {
const state: ConstructorState = {
...DEFAULT_CONSTRUCTOR_OPTIONS,
Expand Down
24 changes: 24 additions & 0 deletions src/parser/events.ts
Original file line number Diff line number Diff line change
@@ -1,51 +1,70 @@
/** @category other */
const EVENT_DOCUMENT = 1
/** @category other */
const EVENT_SEQUENCE = 2
/** @category other */
const EVENT_MAPPING = 3
/** @category other */
const EVENT_SCALAR = 4
/** @category other */
const EVENT_ALIAS = 5
/** @category other */
const EVENT_POP = 6

type EventType =
typeof EVENT_DOCUMENT | typeof EVENT_SEQUENCE | typeof EVENT_MAPPING |
typeof EVENT_SCALAR | typeof EVENT_ALIAS | typeof EVENT_POP

/** @category Nodes */
const SCALAR_STYLE_PLAIN = 1
/** @category Nodes */
const SCALAR_STYLE_SINGLE_QUOTED = 2
/** @category Nodes */
const SCALAR_STYLE_DOUBLE_QUOTED = 3
/** @category Nodes */
const SCALAR_STYLE_LITERAL_BLOCK = 4
/** @category Nodes */
const SCALAR_STYLE_FOLDED_BLOCK = 5

type ScalarStyle =
typeof SCALAR_STYLE_PLAIN | typeof SCALAR_STYLE_SINGLE_QUOTED |
typeof SCALAR_STYLE_DOUBLE_QUOTED | typeof SCALAR_STYLE_LITERAL_BLOCK |
typeof SCALAR_STYLE_FOLDED_BLOCK

/** @category Nodes */
const COLLECTION_STYLE_BLOCK = 1
/** @category Nodes */
const COLLECTION_STYLE_FLOW = 2

type CollectionStyle =
typeof COLLECTION_STYLE_BLOCK | typeof COLLECTION_STYLE_FLOW

/** @category Nodes */
const CHOMPING_CLIP = 1
/** @category Nodes */
const CHOMPING_STRIP = 2
/** @category Nodes */
const CHOMPING_KEEP = 3

type Chomping =
typeof CHOMPING_CLIP | typeof CHOMPING_STRIP | typeof CHOMPING_KEEP

/** @category other */
type DocumentDirective =
{ kind: 'yaml', version: string } |
{ kind: 'tag', handle: string, prefix: string }

type TagHandlers = Record<string, string>

/** @category Events */
interface DocumentEvent {
type: typeof EVENT_DOCUMENT
explicitStart: boolean
explicitEnd: boolean
directives: DocumentDirective[]
}

/** @category Events */
interface SequenceEvent {
type: typeof EVENT_SEQUENCE
start: number
Expand All @@ -56,6 +75,7 @@ interface SequenceEvent {
style: CollectionStyle
}

/** @category Events */
interface MappingEvent {
type: typeof EVENT_MAPPING
start: number
Expand All @@ -66,6 +86,7 @@ interface MappingEvent {
style: CollectionStyle
}

/** @category Events */
interface ScalarEvent {
type: typeof EVENT_SCALAR
valueStart: number
Expand All @@ -80,16 +101,19 @@ interface ScalarEvent {
fast: boolean
}

/** @category Events */
interface AliasEvent {
type: typeof EVENT_ALIAS
anchorStart: number
anchorEnd: number
}

/** @category Events */
interface PopEvent {
type: typeof EVENT_POP
}

/** @category Events */
type Event =
DocumentEvent |
SequenceEvent |
Expand Down
2 changes: 2 additions & 0 deletions src/parser/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ interface ParserSnapshot {
eventsLength: number
}

/** @category Events */
interface ParserOptions {
filename?: string
maxDepth?: number
Expand Down Expand Up @@ -1423,6 +1424,7 @@ function readDocument (state: ParserState) {
}
}

/** @category Events */
function parseEvents (input: string, options: ParserOptions): Event[] {
const length = input.length
const state: ParserState = {
Expand Down
1 change: 1 addition & 0 deletions src/parser/parser_scalar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ function getBlockValue (
return result
}

/** @category Events */
function getScalarValue (input: string, scalar: ScalarEvent): string {
if (scalar.valueStart === NO_RANGE) return ''

Expand Down
5 changes: 5 additions & 0 deletions src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ function compileTags (tags: readonly TagDefinition[]) {
return result
}

/** @category Schema */
class Schema {
readonly tags: readonly TagDefinition[]
readonly implicitScalarTags: readonly ScalarTagDefinition[]
Expand Down Expand Up @@ -165,12 +166,14 @@ class Schema {
}
}

/** @category Schema */
const FAILSAFE_SCHEMA = new Schema([
strTag,
seqTag,
mapTag
])

/** @category Schema */
const JSON_SCHEMA = new Schema([
...FAILSAFE_SCHEMA.tags,
nullJsonTag,
Expand All @@ -179,6 +182,7 @@ const JSON_SCHEMA = new Schema([
floatJsonTag
])

/** @category Schema */
const CORE_SCHEMA = new Schema([
...FAILSAFE_SCHEMA.tags,
nullCoreTag,
Expand All @@ -187,6 +191,7 @@ const CORE_SCHEMA = new Schema([
floatCoreTag
])

/** @category Schema */
const YAML11_SCHEMA = new Schema([
...FAILSAFE_SCHEMA.tags,
nullYaml11Tag,
Expand Down
Loading