Skip to content

Commit

Permalink
Replace doc.directivesEndMarker with doc.directives.marker & directiv…
Browse files Browse the repository at this point in the history
…es option

As cleanup, also remove the now-obsolete doc.version value

BREAKING CHANGE: To now detect if a parsed document included an explicit
doc-start marker, use `doc.directives.marker === true`. To include the
marker when stringifying, either set that value to true, or use
`doc.toString({ directives: true )`. To explicitly leave out directives
and the doc-start marker from the output, use
`doc.toString({ directives: false )`.
  • Loading branch information
eemeli committed Mar 7, 2021
1 parent 4e8d437 commit 02faa82
Show file tree
Hide file tree
Showing 10 changed files with 64 additions and 56 deletions.
31 changes: 16 additions & 15 deletions docs/03_options.md
Expand Up @@ -131,18 +131,19 @@ The `doc.toString()` method may be called with additional options to control the

Used by: `stringify()` and `doc.toString()`

| Name | Type | Default | Description |
| ------------------------------ | ------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| defaultKeyType | `Type ⎮ null` | `null` | If not `null`, overrides `defaultStringType` for implicit key values. |
| defaultStringType | `Type` | `'PLAIN'` | The default type of string literal used to stringify values. |
| doubleQuotedAsJSON | `boolean` | `false` | Restrict double-quoted strings to use JSON-compatible syntax. |
| doubleQuotedMinMultiLineLength | `number` | `40` | Minimum length for double-quoted strings to use multiple lines to represent the value. |
| falseStr | `string` | `'false'` | String representation for `false` values. |
| indent | `number` | `2` | The number of spaces to use when indenting code. Should be a strictly positive integer. |
| indentSeq | `boolean` | `true` | Whether block sequences should be indented. |
| lineWidth | `number` | `80` | Maximum line width (set to `0` to disable folding). This is a soft limit, as only double-quoted semantics allow for inserting a line break in the middle of a word. |
| minContentWidth | `number` | `20` | Minimum line width for highly-indented content (set to `0` to disable). |
| nullStr | `string` | `'null'` | String representation for `null` values. |
| simpleKeys | `boolean` | `false` | Require keys to be scalars and always use implicit rather than explicit notation. |
| singleQuote | `boolean` | `false` | Prefer 'single quote' rather than "double quote" where applicable. |
| trueStr | `string` | `'true'` | String representation for `true` values. |
| Name | Type | Default | Description |
| ------------------------------ | ---------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| defaultKeyType | `Type ⎮ null` | `null` | If not `null`, overrides `defaultStringType` for implicit key values. |
| defaultStringType | `Type` | `'PLAIN'` | The default type of string literal used to stringify values. |
| directives | `boolean ⎮ null` | `null` | Include directives in the output. If `true`, at least the document-start marker `---` is always included. If `false`, no directives or marker is ever included. If `null`, directives and marker may be included if required. |
| doubleQuotedAsJSON | `boolean` | `false` | Restrict double-quoted strings to use JSON-compatible syntax. |
| doubleQuotedMinMultiLineLength | `number` | `40` | Minimum length for double-quoted strings to use multiple lines to represent the value. |
| falseStr | `string` | `'false'` | String representation for `false` values. |
| indent | `number` | `2` | The number of spaces to use when indenting code. Should be a strictly positive integer. |
| indentSeq | `boolean` | `true` | Whether block sequences should be indented. |
| lineWidth | `number` | `80` | Maximum line width (set to `0` to disable folding). This is a soft limit, as only double-quoted semantics allow for inserting a line break in the middle of a word. |
| minContentWidth | `number` | `20` | Minimum line width for highly-indented content (set to `0` to disable). |
| nullStr | `string` | `'null'` | String representation for `null` values. |
| simpleKeys | `boolean` | `false` | Require keys to be scalars and always use implicit rather than explicit notation. |
| singleQuote | `boolean` | `false` | Prefer 'single quote' rather than "double quote" where applicable. |
| trueStr | `string` | `'true'` | String representation for `true` values. |
24 changes: 12 additions & 12 deletions docs/04_documents.md
Expand Up @@ -73,18 +73,18 @@ 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).
See [Options](#options) for more information on the last argument.

| Member | Type | Description |
| ------------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| anchors | [`Anchors`](#anchors) | Anchors associated with the document's nodes; also provides alias & merge node creators. |
| 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 directives-end 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. |
| directivesEndMarker | `boolean?` | Whether the document should always include a directives-end marker `---` at its start, even if it includes no directives. |
| errors | `Error[]` | Errors encountered during parsing. |
| schema | `Schema` | The schema used with the document. |
| tagPrefixes | `Prefix[]` | Array of prefixes; each will have a string `handle` that starts and ends with `!` and a string `prefix` that the handle will be replaced by. |
| version | `string?` | The parsed version of the source document; if true-ish, stringified output will include a `%YAML` directive. |
| warnings | `Error[]` | Warnings encountered during parsing. |
| Member | Type | Description |
| ------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| anchors | [`Anchors`](#anchors) | Anchors associated with the document's nodes; also provides alias & merge node creators. |
| 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. |
| directives | `Directives` | Document directives `%YAML` and `%TAG`, as well as the doc-start marker `---`. |
| errors | `Error[]` | Errors encountered during parsing. |
| schema | `Schema` | The schema used with the document. |
| tagPrefixes | `Prefix[]` | Array of prefixes; each will have a string `handle` that starts and ends with `!` and a string `prefix` that the handle will be replaced by. |
| version | `string?` | The parsed version of the source document; if true-ish, stringified output will include a `%YAML` directive. |
| warnings | `Error[]` | Warnings encountered during parsing. |

```js
import { Document } from 'yaml'
Expand Down
4 changes: 1 addition & 3 deletions src/compose/compose-doc.ts
Expand Up @@ -14,10 +14,8 @@ export function composeDoc(
) {
const opts = Object.assign({ directives }, options)
const doc = new Document(undefined, opts) as Document.Parsed

const props = resolveProps(doc, start, true, 'doc-start', offset, onError)
if (props.found) doc.directivesEndMarker = true

if (props.found) doc.directives.marker = true
doc.contents = value
? composeNode(doc, value, props, onError)
: composeEmptyNode(doc, offset + props.length, start, null, props, onError)
Expand Down
2 changes: 1 addition & 1 deletion src/compose/composer.ts
Expand Up @@ -76,7 +76,7 @@ export class Composer {
const dc = doc.contents
if (afterDoc) {
doc.comment = doc.comment ? `${doc.comment}\n${comment}` : comment
} else if (afterEmptyLine || doc.directivesEndMarker || !dc) {
} else if (afterEmptyLine || doc.directives.marker || !dc) {
doc.commentBefore = comment
} else if (
isCollection(dc) &&
Expand Down
30 changes: 10 additions & 20 deletions src/doc/Document.ts
Expand Up @@ -74,8 +74,6 @@ export class Document<T = unknown> {

directives: Directives

directivesEndMarker = false

/** Errors encountered during parsing. */
errors: YAMLError[] = []

Expand All @@ -98,12 +96,6 @@ export class Document<T = unknown> {

type: Type.DOCUMENT = Type.DOCUMENT

/**
* The parsed version of the source document;
* if true-ish, stringified output will include a `%YAML` directive.
*/
version?: string

/** Warnings encountered during parsing. */
warnings: YAMLWarning[] = []

Expand Down Expand Up @@ -420,15 +412,17 @@ export class Document<T = unknown> {
}

const lines = []
let hasDirectives = false
const dir = this.directives.toString(this)
if (dir) {
lines.push(dir)
hasDirectives = true
let hasDirectives = options.directives === true
if (options.directives !== false) {
const dir = this.directives.toString(this)
if (dir) {
lines.push(dir)
hasDirectives = true
} else if (this.directives.marker) hasDirectives = true
}
if (hasDirectives || this.directivesEndMarker) lines.push('---')
if (hasDirectives) lines.push('---')
if (this.commentBefore) {
if (hasDirectives || !this.directivesEndMarker) lines.unshift('')
if (lines.length !== 1) lines.unshift('')
lines.unshift(this.commentBefore.replace(/^/gm, '#'))
}

Expand All @@ -437,11 +431,7 @@ export class Document<T = unknown> {
let contentComment = null
if (this.contents) {
if (isNode(this.contents)) {
if (
this.contents.spaceBefore &&
(hasDirectives || this.directivesEndMarker)
)
lines.push('')
if (this.contents.spaceBefore && hasDirectives) lines.push('')
if (this.contents.commentBefore)
lines.push(this.contents.commentBefore.replace(/^/gm, '#'))
// top-level block scalars need to be indented if followed by a comment
Expand Down
6 changes: 6 additions & 0 deletions src/doc/directives.ts
Expand Up @@ -21,6 +21,12 @@ export class Directives {
yaml: { version: '1.1' | '1.2'; explicit?: boolean }
tags: Record<string, string>

/**
* The directives-end/doc-start marker `---`. If `null`, a marker may still be
* included in the document's stringified representation.
*/
marker: true | null = null

/**
* Used when parsing YAML 1.1, where:
* > If the document specifies no directives, it is parsed using the same
Expand Down
15 changes: 15 additions & 0 deletions src/options.ts
Expand Up @@ -194,6 +194,21 @@ export type ToStringOptions = {
*/
defaultStringType?: Scalar.Type

/**
* Include directives in the output.
*
* - If `true`, at least the document-start marker `---` is always included.
* This does not force the `%YAML` directive to be included. To do that,
* set `doc.directives.yaml.explicit = true`.
* - If `false`, no directives or marker is ever included. If using the `%TAG`
* directive, you are expected to include it manually in the stream before
* its use.
* - If `null`, directives and marker may be included if required.
*
* Default: `null`
*/
directives?: boolean | null

/**
* Restrict double-quoted strings to use JSON-compatible syntax.
*
Expand Down
2 changes: 1 addition & 1 deletion src/test-events.ts
Expand Up @@ -22,7 +22,7 @@ export function testEvents(src: string, options?: Options) {
if (error && (!error.offset || error.offset < rootStart))
throw new Error()
let docStart = '+DOC'
if (doc.directivesEndMarker) docStart += ' ---'
if (doc.directives.marker) docStart += ' ---'
else if (doc.contents && doc.contents.range[1] === doc.contents.range[0])
continue
events.push(docStart)
Expand Down
3 changes: 1 addition & 2 deletions tests/doc/comments.js
Expand Up @@ -503,9 +503,8 @@ describe('blank lines', () => {

test('before first node in document with directives', () => {
const doc = YAML.parseDocument('str\n')
doc.directivesEndMarker = true
doc.contents.spaceBefore = true
expect(String(doc)).toBe('---\n\nstr\n')
expect(doc.toString({ directives: true })).toBe('---\n\nstr\n')
})

test('between seq items', () => {
Expand Down
3 changes: 1 addition & 2 deletions tests/doc/stringify.js
Expand Up @@ -866,8 +866,7 @@ describe('Document markers in top-level scalars', () => {

test('use marker line for block scalar header', () => {
const doc = YAML.parseDocument('|\nfoo\n')
doc.directivesEndMarker = true
expect(String(doc)).toBe('--- |\nfoo\n')
expect(doc.toString({ directives: true })).toBe('--- |\nfoo\n')
})
})

Expand Down

0 comments on commit 02faa82

Please sign in to comment.