Skip to content

Commit

Permalink
Merge pull request #203 from eemeli/stream
Browse files Browse the repository at this point in the history
Refactor parsing completely
  • Loading branch information
eemeli committed Feb 13, 2021
2 parents b2b3575 + d1e59c5 commit 35d8fe7
Show file tree
Hide file tree
Showing 119 changed files with 5,193 additions and 9,093 deletions.
1 change: 1 addition & 0 deletions .eslintignore
@@ -1,6 +1,7 @@
/browser/
/dist/
/docs-slate/
/lib/
/package-lock.json
/playground/dist/
/tests/yaml-test-suite/
8 changes: 5 additions & 3 deletions .github/workflows/nodejs.yml
@@ -1,9 +1,11 @@
name: Node.js

on:
- pull_request
- push
- workflow_dispatch
pull_request:
branches: [master]
push:
branches: [master]
workflow_dispatch:

jobs:
test:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
@@ -1,4 +1,5 @@
.*
coverage/
dist/
lib/
node_modules/
5 changes: 4 additions & 1 deletion babel.config.js
Expand Up @@ -7,4 +7,7 @@ module.exports = {
}

if (process.env.NODE_ENV === 'test')
module.exports.presets = [['@babel/env', { targets: { node: 'current' } }]]
module.exports.presets = [
['@babel/env', { targets: { node: 'current' } }],
'@babel/preset-typescript'
]
185 changes: 0 additions & 185 deletions cst.d.ts

This file was deleted.

1 change: 1 addition & 0 deletions docs/03_options.md
Expand Up @@ -39,6 +39,7 @@ The `version` option value (`'1.2'` by default) may be overridden by any documen
| schema | `'core' ⎮ 'failsafe' ⎮` `'json' ⎮ 'yaml-1.1'` | The base schema to use. By default `'core'` for YAML 1.2 and `'yaml-1.1'` for earlier versions. |
| simpleKeys | `boolean` | When stringifying, require keys to be scalars and to use implicit rather than explicit notation. By default `false`. |
| sortMapEntries | `boolean ⎮` `(a, b: Pair) => number` | When stringifying, sort map entries. If `true`, sort by comparing key values with `<`. By default `false`. |
| strict | `boolean` | When parsing, do not ignore errors required by the YAML 1.2 spec, but caused by unambiguous content. By default `true`. |
| version | `'1.0' ⎮ '1.1' ⎮ '1.2'` | The YAML version used by documents without a `%YAML` directive. By default `'1.2'`. |

[exponential entity expansion attacks]: https://en.wikipedia.org/wiki/Billion_laughs_attack
Expand Down
13 changes: 9 additions & 4 deletions docs/04_documents.md
Expand Up @@ -102,7 +102,6 @@ During stringification, a document with a true-ish `version` value will include
| ------------------------------------------ | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 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. |
| listNonDefaultTags() | `string[]` | List the tags used in the document that are not in the default `tag:yaml.org,2002:` namespace. |
| parse(cst) | `Document` | Parse a CST into this document. Mostly an internal method, modifying the document according to the contents of the parsed `cst`. Calling this multiple times on a Document is not recommended. |
| setSchema(id?, customTags?) | `void` | Set the schema used by the document. `id` may either be a YAML version, or the identifier of a YAML 1.2 schema; if set, `customTags` should have the same shape as the similarly-named option. |
| setTagPrefix(handle, prefix) | `void` | Set `handle` as a shorthand string for the `prefix` tag namespace. |
Expand Down Expand Up @@ -162,7 +161,7 @@ A description of [alias and merge nodes](#alias-nodes) is included in the next s
| getNames() | `string[]` | List of all defined anchor names. |
| getNode(name: string) | `Node?` | The node associated with the anchor `name`, if set. |
| newName(prefix: string) | `string` | Find an available anchor name with the given `prefix` and a numerical suffix. |
| setAnchor(node: Node, name?: string) | `string?` | Associate an anchor with `node`. If `name` is empty, a new name will be generated. |
| setAnchor(node?: Node, name?: string) | `string?` | Associate an anchor with `node`. If `name` is empty, a new name will be generated. |

```js
const src = '[{ a: A }, { b: B }]'
Expand Down Expand Up @@ -208,8 +207,14 @@ String(doc)
// ]
```

The constructors for `Alias` and `Merge` are not directly exported by the library, as they depend on the document's anchors; instead you'll need to use **`createAlias(node, name)`** and **`createMergePair(...sources)`**. You should make sure to only add alias and merge nodes to the document after the nodes to which they refer, or the document's YAML stringification will fail.
The constructors for `Alias` and `Merge` are not directly exported by the library, as they depend on the document's anchors; instead you'll need to use **`createAlias(node, name)`** and **`createMergePair(...sources)`**.
You should make sure to only add alias and merge nodes to the document after the nodes to which they refer, or the document's YAML stringification will fail.

It is valid to have an anchor associated with a node even if it has no aliases. `yaml` will not allow you to associate the same name with more than one node, even though this is allowed by the YAML spec (all but the last instance will have numerical suffixes added). To add or reassign an anchor, use **`setAnchor(node, name)`**. The second parameter is optional, and if left out either the pre-existing anchor name of the node will be used, or a new one generated. To remove an anchor, use `setAnchor(null, name)`. The function will return the new anchor's name, or `null` if both of its arguments are `null`.
It is valid to have an anchor associated with a node even if it has no aliases.
`yaml` will not allow you to associate the same name with more than one node, even though this is allowed by the YAML spec (all but the last instance will have numerical suffixes added).
To add or reassign an anchor, use **`setAnchor(node, name)`**.
The second parameter is optional, and if left out either the pre-existing anchor name of the node will be used, or a new one generated.
To remove an anchor, use `setAnchor(null, name)`.
The function will return the new anchor's name, or `null` if both of its arguments are `null`.

While the `merge` option needs to be true to parse `Merge` nodes as such, this is not required during stringification.
2 changes: 1 addition & 1 deletion docs/06_custom_tags.md
Expand Up @@ -132,7 +132,7 @@ import {
stringifyString, // (node, ctx, ...) => string
toJS, // (value, arg, ctx) => any -- Recursively convert to plain JS
Type, // { [string]: string } -- Used as enum for node types
YAMLReferenceError, YAMLSemanticError, YAMLSyntaxError, YAMLWarning
YAMLError, YAMLParseError, YAMLWarning
} from 'yaml/util'
```

Expand Down
24 changes: 8 additions & 16 deletions docs/08_errors.md
Expand Up @@ -2,13 +2,13 @@

Nearly all errors and warnings produced by the `yaml` parser functions contain the following fields:

| Member | Type | Description |
| ------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| name | `string` | One of `YAMLReferenceError`, `YAMLSemanticError`, `YAMLSyntaxError`, or `YAMLWarning` |
| message | `string` | A human-readable description of the error |
| source | `CST Node` | The CST node at which this error or warning was encountered. Note that in particular `source.context` is likely to be a complex object and include some circular references. |
| Member | Type | Description |
| ------- | -------- | ------------------------------------------------------------------------ |
| name | `string` | Either `YAMLParseError` or `YAMLWarning` |
| message | `string` | A human-readable description of the error |
| offset | `number` | The offset in the source at which this error or warning was encountered. |

If the `prettyErrors` option is enabled, `source` is dropped from the errors and the following fields are added with summary information regarding the error's source node, if available:
If the `prettyErrors` option is enabled, the following fields are added with summary information regarding the error's source node, if available:

| Member | Type | Description |
| -------- | ----------------------------------- | --------------------------------------------------------------------------------------------- |
Expand All @@ -18,17 +18,9 @@ If the `prettyErrors` option is enabled, `source` is dropped from the errors and

In rare cases, the library may produce a more generic error. In particular, `TypeError` may occur when parsing invalid input using the `json` schema, and `ReferenceError` when the `maxAliasCount` limit is enountered.

## YAMLReferenceError
## YAMLParseError

An error resolving a tag or an anchor that is referred to in the source. It is likely that the contents of the `source` node have not been completely parsed into the document. Not used by the CST parser.

## YAMLSemanticError

An error related to the metadata of the document, or an error with limitations imposed by the YAML spec. The data contents of the document should be valid, but the metadata may be broken.

## YAMLSyntaxError

A serious parsing error; the document contents will not be complete, and the CST is likely to be rather broken.
An error encountered while parsing a source as YAML.

## YAMLWarning

Expand Down
22 changes: 5 additions & 17 deletions index.d.ts
@@ -1,4 +1,3 @@
import { CST } from './cst'
import {
AST,
Alias,
Expand All @@ -13,13 +12,7 @@ import {
} from './types'
import { Type, YAMLError, YAMLWarning } from './util'

export { AST, CST }

export function parseCST(str: string): ParsedCST

export interface ParsedCST extends Array<CST.Document> {
setOrigRanges(): boolean
}
export { AST }

/**
* Apply a visitor to an AST node or document.
Expand Down Expand Up @@ -160,7 +153,7 @@ export interface Options extends Schema.Options {
*
* Default: `"1.2"`
*/
version?: '1.0' | '1.1' | '1.2'
version?: '1.1' | '1.2'
}

/**
Expand Down Expand Up @@ -294,7 +287,7 @@ export interface CreateNodeOptions {
}

export class Document extends Collection {
cstNode?: CST.Document
// cstNode?: CST.Document
/**
* @param value - The initial value for the document, which will be wrapped
* in a Node container.
Expand Down Expand Up @@ -347,13 +340,7 @@ export class Document extends Collection {
* `Scalar` objects.
*/
createPair(key: any, value: any, options?: { wrapScalars?: boolean }): Pair
/**
* List the tags used in the document that are not in the default
* `tag:yaml.org,2002:` namespace.
*/
listNonDefaultTags(): string[]
/** Parse a CST into this document */
parse(cst: CST.Document): this

/**
* When a document is created with `new YAML.Document()`, the schema object is
* not set as it may be influenced by parsed directives; call this with no
Expand Down Expand Up @@ -394,6 +381,7 @@ export class Document extends Collection {
export namespace Document {
interface Parsed extends Document {
contents: Scalar | YAMLMap | YAMLSeq | null
range: [number, number]
/** The schema used with the document. */
schema: Schema
}
Expand Down
3 changes: 2 additions & 1 deletion jest.config.js
Expand Up @@ -31,8 +31,9 @@ switch (process.env.npm_lifecycle_event) {
module.exports = {
collectCoverageFrom: ['src/**/*.js'],
moduleNameMapper,
resolver: 'jest-ts-webcompat-resolver',
testEnvironment: 'node',
testMatch: ['**/tests/**/*.js'],
testPathIgnorePatterns,
transform: { '/(src|tests)/.*\\.js$': 'babel-jest' }
transform: { '/(src|tests)/.*\\.(js|ts)$': 'babel-jest' }
}

0 comments on commit 35d8fe7

Please sign in to comment.