Skip to content
Open
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
19 changes: 6 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,33 +97,24 @@ parse(file)

- [`Document`](https://eemeli.org/yaml/#documents)
- [`constructor(value, replacer?, options?)`](https://eemeli.org/yaml/#creating-documents)
- [`#contents`](https://eemeli.org/yaml/#content-nodes)
- [`#value`](https://eemeli.org/yaml/#content-nodes)
- [`#directives`](https://eemeli.org/yaml/#stream-directives)
- [`#errors`](https://eemeli.org/yaml/#errors)
- [`#warnings`](https://eemeli.org/yaml/#errors)
- [`isDocument(foo): boolean`](https://eemeli.org/yaml/#identifying-node-types)
- [`parseAllDocuments(str, options?): Document[]`](https://eemeli.org/yaml/#parsing-documents)
- [`parseDocument(str, options?): Document`](https://eemeli.org/yaml/#parsing-documents)

<!-- prettier-ignore -->
```js
import {
Document,
isDocument,
parseAllDocuments,
parseDocument
} from 'yaml'
```

### Content Nodes

- [`isAlias(foo): boolean`](https://eemeli.org/yaml/#identifying-node-types)
- [`isCollection(foo): boolean`](https://eemeli.org/yaml/#identifying-node-types)
- [`isMap(foo): boolean`](https://eemeli.org/yaml/#identifying-node-types)
- [`isNode(foo): boolean`](https://eemeli.org/yaml/#identifying-node-types)
- [`isPair(foo): boolean`](https://eemeli.org/yaml/#identifying-node-types)
- [`isScalar(foo): boolean`](https://eemeli.org/yaml/#identifying-node-types)
- [`isSeq(foo): boolean`](https://eemeli.org/yaml/#identifying-node-types)
- [`new Scalar(value)`](https://eemeli.org/yaml/#scalar-values)
- [`new YAMLMap()`](https://eemeli.org/yaml/#collections)
- [`new YAMLSeq()`](https://eemeli.org/yaml/#collections)
Expand All @@ -136,9 +127,11 @@ import {
<!-- prettier-ignore -->
```js
import {
isAlias, isCollection, isMap, isNode,
isPair, isScalar, isSeq, Scalar,
visit, visitAsync, YAMLMap, YAMLSeq
Scalar,
visit,
visitAsync,
YAMLMap,
YAMLSeq
} from 'yaml'
```

Expand Down
12 changes: 6 additions & 6 deletions docs/01_intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,14 @@ import { parse, stringify } from 'yaml'
```js
import {
Document,
isDocument,
parseAllDocuments,
parseDocument
} from 'yaml'
```

- [`Document`](#documents)
- [`constructor(value, replacer?, options?)`](#creating-documents)
- [`#contents`](#content-nodes)
- [`#value`](#content-nodes)
- [`#directives`](#stream-directives)
- [`#errors`](#errors)
- [`#warnings`](#errors)
Expand All @@ -82,13 +81,14 @@ import {
<!-- prettier-ignore -->
```js
import {
isAlias, isCollection, isMap, isNode,
isPair, isScalar, isSeq, Scalar,
visit, visitAsync, YAMLMap, YAMLSeq
Scalar,
visit,
visitAsync,
YAMLMap,
YAMLSeq
} from 'yaml'
```

- [`is*(foo): boolean`](#identifying-node-types)
- [`new Scalar(value)`](#scalar-values)
- [`new YAMLMap()`](#collections)
- [`new YAMLSeq()`](#collections)
Expand Down
41 changes: 20 additions & 21 deletions docs/04_documents.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { parseAllDocuments, parseDocument } from 'yaml'

const file = fs.readFileSync('./file.yml', 'utf8')
const doc = parseDocument(file)
doc.contents
doc.value
// YAMLMap {
// items:
// [ Pair {
Expand Down Expand Up @@ -44,9 +44,9 @@ These functions should never throw,
provided that `str` is a string and the `options` are valid.
Errors and warnings are included in the documents' `errors` and `warnings` arrays.
In particular, if `errors` is not empty
it's likely that the document's parsed `contents` are not entirely correct.
it's likely that the document's parsed `value` are not entirely correct.

The `contents` of a parsed document will always consist of `Scalar`, `Map`, `Seq` or `null` values.
The `value` of a parsed document will always consist of `Scalar`, `Map`, or `Seq` values.

#### `parseDocument(str, options = {}): Document`

Expand All @@ -69,16 +69,15 @@ See [Options](#options) for more information on the second parameter.
#### `new Document(value, replacer?, options = {})`

Creates a new document.
If `value` is defined, the document `contents` are initialised with that value, wrapped recursively in appropriate [content nodes](#content-nodes).
If `value` is `undefined`, the document's `contents` is initialised as `null`.
If defined, a `replacer` may filter or modify the initial document contents, following the same algorithm as the [JSON implementation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#The_replacer_parameter).
The document `value` is initialised with `value`, wrapped recursively in appropriate [content nodes](#content-nodes).
If defined, a `replacer` may filter or modify the initial document value, following the same algorithm as the [JSON implementation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#The_replacer_parameter).
See [Options](#options) for more information on the last argument.

| Member | Type | Description |
| ------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| commentBefore | `string?` | A comment at the very beginning of the document. If not empty, separated from the rest of the document by a blank line or the doc-start indicator when stringified. |
| comment | `string?` | A comment at the end of the document. If not empty, separated from the rest of the document by a blank line when stringified. |
| contents | [`Node`](#content-nodes) `⎮ any` | The document contents. |
| value | [`Node`](#content-nodes) `⎮ any` | The document value. |
| directives | [`Directives`](#stream-directives) | Controls for the `%YAML` and `%TAG` directives, as well as the doc-start marker `---`. |
| errors | [`Error[]`](#errors) | Errors encountered during parsing. |
| schema | `Schema` | The schema used with the document. |
Expand All @@ -99,21 +98,21 @@ String(doc)
```

The Document members are all modifiable, though it's unlikely that you'll have reason to change `errors`, `schema` or `warnings`.
In particular you may be interested in both reading and writing **`contents`**.
Although `parseDocument()` and `parseAllDocuments()` will leave it with `YAMLMap`, `YAMLSeq`, `Scalar` or `null` contents, it can be set to anything.
In particular you may be interested in both reading and writing **`value`**,
which is expected to always contain a `YAMLMap`, `YAMLSeq`, or `Scalar` value.

## Document Methods

| Method | Returns | Description |
| ------------------------------------------ | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| clone() | `Document` | Create a deep copy of this Document and its contents. Custom Node values that inherit from `Object` still refer to their original instances. |
| createAlias(node: Node, name?: string) | `Alias` | Create a new `Alias` node, adding the required anchor for `node`. If `name` is empty, a new anchor name will be generated. |
| createNode(value,&nbsp;options?) | `Node` | Recursively wrap any input with appropriate `Node` containers. See [Creating Nodes](#creating-nodes) for more information. |
| createPair(key,&nbsp;value,&nbsp;options?) | `Pair` | Recursively wrap `key` and `value` into a `Pair` object. See [Creating Nodes](#creating-nodes) for more information. |
| setSchema(version,&nbsp;options?) | `void` | Change the YAML version and schema used by the document. `version` must be either `'1.1'` or `'1.2'`; accepts all Schema options. |
| toJS(options?) | `any` | A plain JavaScript representation of the document `contents`. |
| toJSON() | `any` | A JSON representation of the document `contents`. |
| toString(options?) | `string` | A YAML representation of the document. |
| Method | Returns | Description |
| ------------------------------------------ | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| clone() | `Document` | Create a deep copy of this Document and its value. Custom Node values that inherit from `Object` still refer to their original instances. |
| createAlias(node: Node, name?: string) | `Alias` | Create a new `Alias` node, adding the required anchor for `node`. If `name` is empty, a new anchor name will be generated. |
| createNode(value,&nbsp;options?) | `Node` | Recursively wrap any input with appropriate `Node` containers. See [Creating Nodes](#creating-nodes) for more information. |
| createPair(key,&nbsp;value,&nbsp;options?) | `Pair` | Recursively wrap `key` and `value` into a `Pair` object. See [Creating Nodes](#creating-nodes) for more information. |
| setSchema(version,&nbsp;options?) | `void` | Change the YAML version and schema used by the document. `version` must be either `'1.1'` or `'1.2'`; accepts all Schema options. |
| toJS(options?) | `any` | A plain JavaScript representation of the document `value`. |
| toJSON() | `any` | A JSON representation of the document `value`. |
| toString(options?) | `string` | A YAML representation of the document. |

```js
const doc = parseDocument('a: 1\nb: [2, 3]\n')
Expand All @@ -127,7 +126,7 @@ doc.getIn(['b', 1]) // 4

In addition to the above, the document object also provides the same **accessor methods** as [collections](#collections), based on the top-level collection:
`add`, `delete`, `get`, `has`, and `set`, along with their deeper variants `addIn`, `deleteIn`, `getIn`, `hasIn`, and `setIn`.
For the `*In` methods using an empty `path` value (i.e. `null`, `undefined`, or `[]`) will refer to the document's top-level `contents`.
For the `*In` methods using an empty `path` value (i.e. `[]`) will refer to the document's top-level `value`.

#### `Document#toJS()`, `Document#toJSON()` and `Document#toString()`

Expand Down Expand Up @@ -177,5 +176,5 @@ The contents of `doc.directives.tags` are used both for the `%TAG` directives an
Each of the handles must start and end with a `!` character; `!` is by default the local tag and `!!` is used for default tags.
See the section on [custom tags](#writing-custom-tags) for more on this topic.

`doc.contents.yaml` determines if an explicit `%YAML` directive should be included in the output, and what version it should use.
`doc.directives.yaml` determines if an explicit `%YAML` directive should be included in the output, and what version it should use.
If changing the version after the document's creation, you'll probably want to use `doc.setSchema()` as it will also update the schema accordingly.
81 changes: 17 additions & 64 deletions docs/05_content_nodes.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Content Nodes

After parsing, the `contents` value of each `YAML.Document` is the root of an [Abstract Syntax Tree](https://en.wikipedia.org/wiki/Abstract_syntax_tree) of nodes representing the document (or `null` for an empty document).
After parsing, the `value` value of each `YAML.Document` is the root of an [Abstract Syntax Tree](https://en.wikipedia.org/wiki/Abstract_syntax_tree) of nodes representing the document.

Both scalar and collection values may have an `anchor` associated with them; this is rendered in the string representation with a `&` prefix, so e.g. in `foo: &aa bar`, the value `bar` has the anchor `aa`.
Anchors are used by [Alias nodes](#alias-nodes) to allow for the same value to be used in multiple places in the document.
Expand Down Expand Up @@ -41,7 +41,7 @@ class Scalar<T = unknown> extends NodeBase {
}
```

A parsed document's contents will have all of its non-object values wrapped in `Scalar` objects, which themselves may be in some hierarchy of `YAMLMap` and `YAMLSeq` collections.
A parsed document's value will have all of its non-object values wrapped in `Scalar` objects, which themselves may be in some hierarchy of `YAMLMap` and `YAMLSeq` collections.
However, this is not a requirement for the document's stringification, which is rather tolerant regarding its input values, and will use [`doc.createNode()`](#creating-nodes) when encountering an unwrapped value.

When stringifying, the node `type` will be taken into account by `!!str` and `!!binary` values, and ignored by other scalars.
Expand All @@ -50,21 +50,21 @@ On the other hand, `!!int` and `!!float` stringifiers will take `format` into ac
## Collections

```js
class Pair<K = unknown, V = unknown> {
key: K // When parsed, key and value are always
value: V // Node or null, but can be set to anything
class Pair {
key: Node
value: Node | null
}

class Collection extends NodeBase {
anchor?: string // an anchor associated with this node
flow?: boolean // use flow style when stringifying this
schema?: Schema
addIn(path: Iterable<unknown>, value: unknown): void
addIn(path: unknown[], value: unknown): void
clone(schema?: Schema): NodeBase // a deep copy of this collection
deleteIn(path: Iterable<unknown>): boolean
getIn(path: Iterable<unknown>, keepScalar?: boolean): unknown
hasIn(path: Iterable<unknown>): boolean
setIn(path: Iterable<unknown>, value: unknown): void
deleteIn(path: unknown[]): boolean
getIn(path: unknown[], keepScalar?: boolean): unknown
hasIn(path: unknown[]): boolean
setIn(path: unknown[], value: unknown): void
}

class YAMLMap<K = unknown, V = unknown> extends Collection {
Expand All @@ -87,8 +87,8 @@ class YAMLSeq<T = unknown> extends Collection {
```

Within all YAML documents, two forms of collections are supported: sequential `YAMLSeq` collections and key-value `YAMLMap` collections.
The JavaScript representations of these collections both have an `items` array, which may (`YAMLSeq`) or must (`YAMLMap`) consist of `Pair` objects that contain a `key` and a `value` of any type, including `null`.
The `items` array of a `YAMLSeq` object may contain values of any type.
The JavaScript representations of these collections both have an `items` array, which may (`YAMLSeq`) or must (`YAMLMap`) consist of `Pair` objects that contain a `key` and a `value` of any node type, or `null` for `value`.
The `items` array of a `YAMLSeq` object may contain any node values.

When stringifying collections, by default block notation will be used.
Flow notation will be selected if `flow` is `true`, the collection is within a surrounding flow collection, or if the collection is in an implicit key.
Expand Down Expand Up @@ -169,7 +169,7 @@ When nodes are constructed from JS structures (e.g. during `YAML.stringify()`),
```js
const doc = new YAML.Document(['some', 'values'])
// Document {
// contents:
// value:
// YAMLSeq {
// items:
// [ Scalar { value: 'some' },
Expand Down Expand Up @@ -209,8 +209,7 @@ For all available options, see the [CreateNode Options](#createnode-options) sec
[replacer]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#The_replacer_parameter

The primary purpose of this method is to enable attaching comments or other metadata to a value, or to otherwise exert more fine-grained control over the stringified output.
To that end, you'll need to assign its return value to the `contents` of a document (or somewhere within said contents), as the document's schema is required for YAML string output.
If you're not interested in working with such metadata, document `contents` may also include non-`Node` values at any level.
To that end, you'll need to assign its return value to the `value` of a document (or somewhere within said value), as the document's schema is required for YAML string output.

<h4 style="clear:both"><code>doc.createAlias(node, name?): Alias</code></h4>

Expand All @@ -236,12 +235,11 @@ You should make sure to only add alias nodes to the document after the nodes to
```js
import { Document, YAMLSeq } from 'yaml'

const doc = new Document(new YAMLSeq())
doc.contents.items = [
const doc = new Document([
'some values',
42,
{ including: 'objects', 3: 'a string' }
]
])
doc.add(doc.createPair(1, 'a number'))

doc.toString()
Expand Down Expand Up @@ -320,7 +318,7 @@ The return value of the visitor may be used to control the traversal:
- `number`: While iterating the items of a sequence or map, set the index of the next step.
This is useful especially if the index of the current node has changed.

If `visitor` is a single function, it will be called with all values encountered in the tree, including e.g. `null` values.
If `visitor` is a single function, it will be called with all values encountered in the tree, including `null` values.
Alternatively, separate visitor functions may be defined for each `Map`, `Pair`, `Seq`, `Alias` and `Scalar` node.
To define the same visitor function for more than one node type,
use the `Collection` (map and seq), `Value` (map, seq & scalar) and `Node` (alias, map, seq & scalar) targets.
Expand All @@ -332,51 +330,6 @@ The same as `visit()`,
but allows for visitor functions that return a promise
which resolves to one of the above-defined control values.

## Identifying Node Types

```js
import {
isAlias,
isCollection, // map or seq
isDocument,
isMap,
isNode, // alias, scalar, map or seq
isPair,
isScalar,
isSeq
} from 'yaml'

const doc = new Document({ foo: [13, 42] })
isDocument(doc) === true
isNode(doc) === false
isMap(doc.contents) === true
isNode(doc.contents) === true
isPair(doc.contents.items[0]) === true
isCollection(doc.get('foo')) === true
isScalar(doc.getIn(['foo', 1])) === true
```

#### `isAlias(x: unknown): boolean`

#### `isCollection(x: unknown): boolean`

#### `isDocument(x: unknown): boolean`

#### `isMap(x: unknown): boolean`

#### `isNode(x: unknown): boolean`

#### `isPair(x: unknown): boolean`

#### `isScalar(x: unknown): boolean`

#### `isSeq(x: unknown): boolean`

To find out what you've got, a family of custom type guard functions is provided.
These should be preferred over other methods such as `instanceof` checks, as they'll work even if the nodes have been created by a different instance of the library.

Internally, node identification uses property symbols that are set on instances during their construction.

## Comments and Blank Lines

```js
Expand Down
Loading
Loading