Skip to content

Commit

Permalink
Merge pull request #147 from eemeli/indent
Browse files Browse the repository at this point in the history
Add options to control indentation
  • Loading branch information
eemeli authored Apr 17, 2020
2 parents 91b6dd6 + 9ff4430 commit e209c94
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 12 deletions.
2 changes: 2 additions & 0 deletions docs/03_options.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ The `version` option value (`'1.2'` by default) may be overridden by any documen
| --------------- | --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| anchorPrefix | `string` | Default prefix for anchors. By default `'a'`, resulting in anchors `a1`, `a2`, etc. |
| customTags | `Tag[] ⎮ function` | Array of [additional tags](#custom-data-types) to include in the schema |
| indent | `number` | The number of spaces to use when indenting code. By default `2`. |
| indentSeq | `boolean` | Whether block sequences should be indented. By default `true`. |
| keepBlobsInJSON | `boolean` | Allow non-JSON JavaScript objects to remain in the `toJSON` output. Relevant with the YAML 1.1 `!!timestamp` and `!!binary` tags as well as BigInts. By default `true`. |
| keepCstNodes | `boolean` | Include references in the AST to each node's corresponding CST node. By default `false`. |
| keepNodeTypes | `boolean` | Store the original node type when parsing documents. By default `true`. |
Expand Down
12 changes: 12 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,18 @@ export interface Options extends Schema.Options {
* Default: `'a'`, resulting in anchors `a1`, `a2`, etc.
*/
anchorPrefix?: string
/**
* The number of spaces to use when indenting code.
*
* Default: `2`
*/
indent?: number
/**
* Whether block sequences should be indented.
*
* Default: `true`
*/
indentSeq?: boolean
/**
* Allow non-JSON JavaScript objects to remain in the `toJSON` output.
* Relevant with the YAML 1.1 `!!timestamp` and `!!binary` tags as well as BigInts.
Expand Down
2 changes: 1 addition & 1 deletion playground
16 changes: 14 additions & 2 deletions src/Document.js
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,13 @@ export class Document {
const keep =
keepBlobsInJSON &&
(typeof arg !== 'string' || !(this.contents instanceof Scalar))
const ctx = { doc: this, keep, mapAsMap: keep && !!mapAsMap, maxAliasCount }
const ctx = {
doc: this,
indentStep: ' ',
keep,
mapAsMap: keep && !!mapAsMap,
maxAliasCount
}
const anchorNames = Object.keys(this.anchors.map)
if (anchorNames.length > 0)
ctx.anchors = anchorNames.map(name => ({
Expand All @@ -558,6 +564,11 @@ export class Document {
toString() {
if (this.errors.length > 0)
throw new Error('Document with errors cannot be stringified')
const indentSize = this.options.indent
if (!Number.isInteger(indentSize) || indentSize <= 0) {
const s = JSON.stringify(indentSize)
throw new Error(`"indent" option must be a positive integer, not ${s}`)
}
this.setSchema()
const lines = []
let hasDirectives = false
Expand Down Expand Up @@ -585,7 +596,8 @@ export class Document {
const ctx = {
anchors: {},
doc: this,
indent: ''
indent: '',
indentStep: ' '.repeat(indentSize)
}
let chompKeep = false
let contentComment = null
Expand Down
2 changes: 2 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import { warn } from './warnings'
const defaultOptions = {
anchorPrefix: 'a',
customTags: null,
indent: 2,
indentSeq: true,
keepCstNodes: false,
keepNodeTypes: true,
keepBlobsInJSON: true,
Expand Down
12 changes: 6 additions & 6 deletions src/schema/Collection.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { addComment } from '../addComment'
import { Type } from '../constants'
import { Node } from './Node'
import { Pair } from './Pair'
import { Scalar } from './Scalar'

function collectionFromPath(schema, path, value) {
Expand Down Expand Up @@ -66,7 +66,7 @@ export class Collection extends Node {

hasAllNullValues() {
return this.items.every(node => {
if (!(node instanceof Pair)) return false
if (!node || node.type !== 'PAIR') return false
const n = node.value
return (
n == null ||
Expand Down Expand Up @@ -112,10 +112,10 @@ export class Collection extends Node {
onComment,
onChompKeep
) {
const { doc, indent } = ctx
const { doc, indent, indentStep } = ctx
const inFlow =
(this.type && this.type.substr(0, 4) === 'FLOW') || ctx.inFlow
if (inFlow) itemIndent += ' '
this.type === Type.FLOW_MAP || this.type === Type.FLOW_SEQ || ctx.inFlow
if (inFlow) itemIndent += indentStep
const allNullValues = isMap && this.hasAllNullValues()
ctx = Object.assign({}, ctx, {
allNullValues,
Expand Down Expand Up @@ -176,7 +176,7 @@ export class Collection extends Node {
) {
str = start
for (const s of strings) {
str += s ? `\n ${indent}${s}` : '\n'
str += s ? `\n${indentStep}${indent}${s}` : '\n'
}
str += `\n${indent}${end}`
} else {
Expand Down
21 changes: 18 additions & 3 deletions src/schema/Pair.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { toJSON } from '../toJSON'
import { Collection } from './Collection'
import { Node } from './Node'
import { Scalar } from './Scalar'
import { YAMLSeq } from './Seq'

const stringifyKey = (key, jsKey, ctx) => {
if (jsKey === null) return ''
Expand All @@ -15,6 +16,7 @@ const stringifyKey = (key, jsKey, ctx) => {
anchors: {},
doc: ctx.doc,
indent: '',
indentStep: ctx.indentStep,
inFlow: true,
inStringifyKey: true
})
Expand Down Expand Up @@ -64,7 +66,7 @@ export class Pair extends Node {

toString(ctx, onComment, onChompKeep) {
if (!ctx || !ctx.doc) return JSON.stringify(this)
const { simpleKeys } = ctx.doc.options
const { indent: indentSize, indentSeq, simpleKeys } = ctx.doc.options
let { key, value } = this
let keyComment = key instanceof Node && key.comment
if (simpleKeys) {
Expand All @@ -83,10 +85,10 @@ export class Pair extends Node {
key instanceof Collection ||
key.type === Type.BLOCK_FOLDED ||
key.type === Type.BLOCK_LITERAL)
const { doc, indent } = ctx
const { doc, indent, indentStep } = ctx
ctx = Object.assign({}, ctx, {
implicitKey: !explicitKey,
indent: indent + ' '
indent: indent + indentStep
})
let chompKeep = false
let str = doc.schema.stringify(
Expand Down Expand Up @@ -125,6 +127,19 @@ export class Pair extends Node {
if (!explicitKey && !this.comment && value instanceof Scalar)
ctx.indentAtStart = str.length + 1
chompKeep = false
if (
!indentSeq &&
indentSize >= 2 &&
!ctx.inFlow &&
!explicitKey &&
value instanceof YAMLSeq &&
value.type !== Type.FLOW_SEQ &&
!value.tag &&
!doc.anchors.getName(value)
) {
// If indentSeq === false, consider '- ' as part of indentation where possible
ctx.indent = ctx.indent.substr(2)
}
const valueStr = doc.schema.stringify(
value,
ctx,
Expand Down
100 changes: 100 additions & 0 deletions tests/doc/stringify.js
Original file line number Diff line number Diff line change
Expand Up @@ -522,3 +522,103 @@ describe('sortMapEntries', () => {
expect(String(doc)).toBe('a: 1\nb: 2\nbb: 4\nc: 3\n')
})
})

describe('custom indent', () => {
let obj
beforeEach(() => {
const seq = YAML.createNode(['a'])
seq.commentBefore = 'sc'
const map = YAML.createNode({ foo: 'bar', seq })
map.commentBefore = 'mc'
obj = { array: [{ a: 1, b: 2 }], map }
})

test('indent: 0', () => {
expect(() => YAML.stringify(obj, { indent: 0 })).toThrow(
/must be a positive integer/
)
})

test('indent: 1', () => {
expect(YAML.stringify(obj, { indent: 1 })).toBe(
source`
array:
- a: 1
b: 2
map:
#mc
foo: bar
seq:
#sc
- a
` + '\n'
)
})

test('indent: 4', () => {
expect(YAML.stringify(obj, { indent: 4 })).toBe(
source`
array:
- a: 1
b: 2
map:
#mc
foo: bar
seq:
#sc
- a
` + '\n'
)
})
})

describe('indentSeq: false', () => {
let obj
beforeEach(() => {
const seq = YAML.createNode(['a'])
seq.commentBefore = 'sc'
obj = { array: [{ a: 1, b: 2 }], map: { seq } }
})

test('indent: 1', () => {
expect(YAML.stringify(obj, { indent: 1, indentSeq: false })).toBe(
source`
array:
- a: 1
b: 2
map:
seq:
#sc
- a
` + '\n'
)
})

test('indent: 2', () => {
expect(YAML.stringify(obj, { indent: 2, indentSeq: false })).toBe(
source`
array:
- a: 1
b: 2
map:
seq:
#sc
- a
` + '\n'
)
})

test('indent: 4', () => {
expect(YAML.stringify(obj, { indent: 4, indentSeq: false })).toBe(
source`
array:
- a: 1
b: 2
map:
seq:
#sc
- a
` + '\n'
)
})
})

0 comments on commit e209c94

Please sign in to comment.