Skip to content

Commit

Permalink
feat: Add collectionStyle option (#343)
Browse files Browse the repository at this point in the history
  • Loading branch information
eemeli authored Dec 28, 2021
1 parent 181dcd8 commit 6e00711
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 6 deletions.
1 change: 1 addition & 0 deletions docs/03_options.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ Used by: `stringify()` and `doc.toString()`
| Name | Type | Default | Description |
| ------------------------------ | -------------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| blockQuote | `boolean ⎮ 'folded' ⎮ 'literal'` | `true` | Use block quote styles for scalar values where applicable. Set to `false` to disable block quotes completely. |
| collectionStyle | `'any' ⎮ 'block' ⎮ 'flow'` | `'any'` | Enforce `'block'` or `'flow'` style on maps and sequences. By default, allows each collection to set its own `flow: boolean` property. |
| commentString | `(comment: string) => string` | | Output should be valid for the current schema. By default, empty comment lines are left empty, lines consisting of a single space are replaced by `#`, and all other lines are prefixed with a `#`. |
| 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. |
Expand Down
9 changes: 9 additions & 0 deletions src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,15 @@ export type ToStringOptions = {
*/
blockQuote?: boolean | 'folded' | 'literal'

/**
* Enforce `'block'` or `'flow'` style on maps and sequences.
* Empty collections will always be stringified as `{}` or `[]`.
*
* Default: `'any'`, allowing each node to set its style separately
* with its `flow: boolean` (default `false`) property.
*/
collectionStyle?: 'any' | 'block' | 'flow'

/**
* Comment stringifier.
* Output should be valid for the current schema.
Expand Down
19 changes: 17 additions & 2 deletions src/stringify/stringify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ export type StringifyContext = {
indent: string
indentStep: string
indentAtStart?: number
inFlow?: boolean
inFlow: boolean | null
inStringifyKey?: boolean
options: Readonly<Required<Omit<ToStringOptions, 'indent'>>>
options: Readonly<
Required<Omit<ToStringOptions, 'collectionStyle' | 'indent'>>
>
}

export function createStringifyContext(
Expand Down Expand Up @@ -56,11 +58,24 @@ export function createStringifyContext(
options
)

let inFlow: boolean | null
switch (opt.collectionStyle) {
case 'block':
inFlow = false
break
case 'flow':
inFlow = true
break
default:
inFlow = null
}

return {
anchors: new Set(),
doc,
indent: '',
indentStep: typeof opt.indent === 'number' ? ' '.repeat(opt.indent) : ' ',
inFlow,
options: opt
}
}
Expand Down
6 changes: 2 additions & 4 deletions src/stringify/stringifyCollection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,8 @@ export function stringifyCollection(
ctx: StringifyContext,
options: StringifyCollectionOptions
) {
const stringify =
collection.flow || ctx.inFlow
? stringifyFlowCollection
: stringifyBlockCollection
const flow = ctx.inFlow ?? collection.flow
const stringify = flow ? stringifyFlowCollection : stringifyBlockCollection
return stringify(collection, ctx, options)
}

Expand Down
53 changes: 53 additions & 0 deletions tests/doc/stringify.js
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,59 @@ describe('indentSeq: false', () => {
})
})

describe('collectionStyle', () => {
test('collectionStyle: undefined', () => {
const doc = new YAML.Document({ foo: ['bar'] })
expect(doc.toString()).toBe('foo:\n - bar\n')

doc.contents.flow = false
doc.get('foo').flow = true
expect(doc.toString()).toBe('foo: [ bar ]\n')

doc.contents.flow = true
doc.get('foo').flow = false
expect(doc.toString()).toBe('{ foo: [ bar ] }\n')
})

test("collectionStyle: 'any'", () => {
const doc = new YAML.Document({ foo: ['bar'] })
expect(doc.toString({ collectionStyle: 'any' })).toBe('foo:\n - bar\n')

doc.contents.flow = false
doc.get('foo').flow = true
expect(doc.toString({ collectionStyle: 'any' })).toBe('foo: [ bar ]\n')

doc.contents.flow = true
doc.get('foo').flow = false
expect(doc.toString({ collectionStyle: 'any' })).toBe('{ foo: [ bar ] }\n')
})

test("collectionStyle: 'block'", () => {
const doc = new YAML.Document({ foo: ['bar'] })
expect(doc.toString({ collectionStyle: 'block' })).toBe('foo:\n - bar\n')

doc.contents.flow = false
doc.get('foo').flow = true
expect(doc.toString({ collectionStyle: 'block' })).toBe('foo:\n - bar\n')

doc.contents.flow = true
doc.get('foo').flow = false
expect(doc.toString({ collectionStyle: 'block' })).toBe('foo:\n - bar\n')
})

test("collectionStyle: 'flow'", () => {
const doc = new YAML.Document({ foo: ['bar'] })
expect(doc.toString({ collectionStyle: 'flow' })).toBe('{ foo: [ bar ] }\n')

doc.get('foo').flow = true
expect(doc.toString({ collectionStyle: 'flow' })).toBe('{ foo: [ bar ] }\n')

doc.contents.flow = true
doc.get('foo').flow = false
expect(doc.toString({ collectionStyle: 'flow' })).toBe('{ foo: [ bar ] }\n')
})
})

describe('Scalar options', () => {
describe('defaultStringType & defaultKeyType', () => {
test('PLAIN, PLAIN', () => {
Expand Down

0 comments on commit 6e00711

Please sign in to comment.