diff --git a/docs/05_content_nodes.md b/docs/05_content_nodes.md
index 7fedeb5c..636ad674 100644
--- a/docs/05_content_nodes.md
+++ b/docs/05_content_nodes.md
@@ -164,13 +164,23 @@ String(doc)
#### `YAML.Document#createNode(value, options?): Node`
-To create a new node, use the `createNode(value, options?)` document method. This will recursively wrap any input with appropriate `Node` containers. Generic JS `Object` values as well as `Map` and its descendants become mappings, while arrays and other iterable objects result in sequences. With `Object`, entries that have an `undefined` value are dropped.
+To create a new node, use the `createNode(value, options?)` document method.
+This will recursively wrap any input with appropriate `Node` containers.
+Generic JS `Object` values as well as `Map` and its descendants become mappings, while arrays and other iterable objects result in sequences.
+With `Object`, entries that have an `undefined` value are dropped.
-Use `options.replacer` to apply a replacer array or function, following the [JSON implementation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#The_replacer_parameter). To specify the collection type, set `options.tag` to its identifying string, e.g. `"!!omap"`. Note that this requires the corresponding tag to be available in the document's schema. If `options.wrapScalars` is undefined or `true`, plain values are wrapped in `Scalar` objects.
+To force flow styling on a collection, use `options.flow = true`
+Use `options.replacer` to apply a replacer array or function, following the [JSON implementation][replacer].
+To specify the collection type, set `options.tag` to its identifying string, e.g. `"!!omap"`.
+Note that this requires the corresponding tag to be available in the document's schema.
-As a possible side effect, this method may add entries to the document's [`anchors`](#working-with-anchors)
+[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.
+As a possible side effect, this method may add entries to the document's [`anchors`](#working-with-anchors).
+
+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.
new YAMLMap(), new YAMLSeq(), doc.createPair(key, value)
diff --git a/src/doc/Document.ts b/src/doc/Document.ts
index d667bd74..3007d522 100644
--- a/src/doc/Document.ts
+++ b/src/doc/Document.ts
@@ -5,8 +5,10 @@ import { collectionFromPath, isEmptyPath } from '../nodes/Collection.js'
import {
DOC,
isCollection,
+ isMap,
isNode,
isScalar,
+ isSeq,
Node,
NODE_TYPE,
ParsedNode
@@ -157,7 +159,7 @@ export class Document {
*/
createNode(
value: unknown,
- { keepUndefined, onTagObj, replacer, tag }: CreateNodeOptions = {}
+ { flow, keepUndefined, onTagObj, replacer, tag }: CreateNodeOptions = {}
): Node {
if (typeof replacer === 'function')
value = replacer.call({ '': value }, '', value)
@@ -183,6 +185,7 @@ export class Document {
replacer,
schema: this.schema
}
+
const node = createNode(value, tag, ctx)
for (const alias of aliasNodes) {
// With circular references, the source node is only resolved after all of
@@ -195,6 +198,11 @@ export class Document {
this.anchors.map[name] = alias.source
}
}
+ if (flow) {
+ if (isMap(node)) node.type = Type.FLOW_MAP
+ else if (isSeq(node)) node.type = Type.FLOW_SEQ
+ }
+
return node
}
diff --git a/src/nodes/Scalar.ts b/src/nodes/Scalar.ts
index f8737274..6c7c66cb 100644
--- a/src/nodes/Scalar.ts
+++ b/src/nodes/Scalar.ts
@@ -31,6 +31,7 @@ export class Scalar extends NodeBase {
*/
declare format?: string
+ /** If `value` is a number, use this value when stringifying this node. */
declare minFractionDigits?: number
/** Set during parsing to the source string value */
diff --git a/src/options.ts b/src/options.ts
index 0732fb30..fab3e969 100644
--- a/src/options.ts
+++ b/src/options.ts
@@ -1,9 +1,10 @@
-import { LogLevelId, Type } from './constants.js'
+import type { LogLevelId } from './constants.js'
import type { Reviver } from './doc/applyReviver.js'
import type { Directives } from './doc/directives.js'
import type { Replacer } from './doc/Document.js'
import type { SchemaName } from './doc/Schema.js'
import type { Pair } from './nodes/Pair.js'
+import type { Scalar } from './nodes/Scalar.js'
import type { LineCounter } from './parse/line-counter.js'
import type { CollectionTag, ScalarTag, TagValue } from './tags/types.js'
@@ -117,6 +118,15 @@ export type SchemaOptions = {
}
export type CreateNodeOptions = {
+ /** Force the top-level collection node to use flow style. */
+ flow?: boolean
+
+ /**
+ * Keep `undefined` object values when creating mappings, rather than
+ * discarding them.
+ *
+ * Default: `false`
+ */
keepUndefined?: boolean | null
onTagObj?: (tagObj: ScalarTag | CollectionTag) => void
@@ -174,13 +184,7 @@ export type ToStringOptions = {
*
* Default: `null`
*/
- defaultKeyType?:
- | null
- | Type.BLOCK_FOLDED
- | Type.BLOCK_LITERAL
- | Type.PLAIN
- | Type.QUOTE_DOUBLE
- | Type.QUOTE_SINGLE
+ defaultKeyType?: Scalar.Type | null
/**
* The default type of string literal used to stringify values in general.
@@ -188,12 +192,7 @@ export type ToStringOptions = {
*
* Default: `'PLAIN'`
*/
- defaultStringType?:
- | Type.BLOCK_FOLDED
- | Type.BLOCK_LITERAL
- | Type.PLAIN
- | Type.QUOTE_DOUBLE
- | Type.QUOTE_SINGLE
+ defaultStringType?: Scalar.Type
/**
* Restrict double-quoted strings to use JSON-compatible syntax.
diff --git a/tests/doc/createNode.js b/tests/doc/createNode.js
index b309adfa..f11bf22f 100644
--- a/tests/doc/createNode.js
+++ b/tests/doc/createNode.js
@@ -54,11 +54,23 @@ describe('arrays', () => {
expect(s).toBeInstanceOf(YAMLSeq)
expect(s.items).toHaveLength(0)
})
+
test('createNode([true])', () => {
const s = doc.createNode([true])
expect(s).toBeInstanceOf(YAMLSeq)
expect(s.items).toMatchObject([{ value: true }])
+ doc.contents = s
+ expect(String(doc)).toBe('- true\n')
+ })
+
+ test('flow: true', () => {
+ const s = doc.createNode([true], { flow: true })
+ expect(s).toBeInstanceOf(YAMLSeq)
+ expect(s.items).toMatchObject([{ value: true }])
+ doc.contents = s
+ expect(String(doc)).toBe('[ true ]\n')
})
+
describe('[3, ["four", 5]]', () => {
const array = [3, ['four', 5]]
test('createNode(value)', () => {
@@ -89,13 +101,27 @@ describe('objects', () => {
expect(s).toBeInstanceOf(YAMLMap)
expect(s.items).toHaveLength(0)
})
+
test('createNode({ x: true })', () => {
const s = doc.createNode({ x: true })
expect(s).toBeInstanceOf(YAMLMap)
expect(s.items).toMatchObject([
{ key: { value: 'x' }, value: { value: true } }
])
+ doc.contents = s
+ expect(String(doc)).toBe('x: true\n')
+ })
+
+ test('flow: true', () => {
+ const s = doc.createNode({ x: true }, { flow: true })
+ expect(s).toBeInstanceOf(YAMLMap)
+ expect(s.items).toMatchObject([
+ { key: { value: 'x' }, value: { value: true } }
+ ])
+ doc.contents = s
+ expect(String(doc)).toBe('{ x: true }\n')
})
+
test('createNode({ x: true, y: undefined })', () => {
const s = doc.createNode({ x: true, y: undefined })
expect(s).toBeInstanceOf(YAMLMap)
@@ -103,6 +129,7 @@ describe('objects', () => {
{ type: PairType.PAIR, key: { value: 'x' }, value: { value: true } }
])
})
+
test('createNode({ x: true, y: undefined }, { keepUndefined: true })', () => {
const s = doc.createNode({ x: true, y: undefined }, { keepUndefined: true })
expect(s).toBeInstanceOf(YAMLMap)
@@ -111,6 +138,7 @@ describe('objects', () => {
{ type: PairType.PAIR, key: { value: 'y' }, value: { value: null } }
])
})
+
describe('{ x: 3, y: [4], z: { w: "five", v: 6 } }', () => {
const object = { x: 3, y: [4], z: { w: 'five', v: 6 } }
test('createNode(value)', () => {