Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,15 @@ export type ToStringOptions = {
*/
indentSeq?: boolean

/**
* Whether indentation in srcToken should be preserved.
*
* For this to work, you need to have parsed the yaml document with keepSourceTokens: true
*
* Default: `false`
*/
keepIndent?: boolean

/**
* Maximum line width (set to `0` to disable folding).
*
Expand Down Expand Up @@ -387,4 +396,4 @@ export type ToStringOptions = {
* Default: `'true'`
*/
verifyAliasOrder?: boolean
}
}
3 changes: 2 additions & 1 deletion src/stringify/stringify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export function createStringifyContext(
falseStr: 'false',
flowCollectionPadding: true,
indentSeq: true,
keepIndent: false,
lineWidth: 80,
minContentWidth: 20,
nullStr: 'null',
Expand Down Expand Up @@ -175,4 +176,4 @@ export function stringify(
return isScalar(node) || str[0] === '{' || str[0] === '['
? `${props} ${str}`
: `${props}\n${ctx.indent}${str}`
}
}
18 changes: 15 additions & 3 deletions src/stringify/stringifyPair.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ export function stringifyPair(
allNullValues,
doc,
indent,
indentStep,
options: { commentString, indentSeq, simpleKeys }
options: { commentString, indentSeq, keepIndent, simpleKeys }
} = ctx

let keyComment = (isNode(key) && key.comment) || null
if (simpleKeys) {
if (keyComment) {
Expand All @@ -37,6 +37,17 @@ export function stringifyPair(
? key.type === Scalar.BLOCK_FOLDED || key.type === Scalar.BLOCK_LITERAL
: typeof key === 'object'))

let indentStep = ctx.indentStep
if (
keepIndent &&
isNode(value) &&
value.srcToken &&
'indent' in value.srcToken
) {
const diff = value.srcToken.indent - indent.length
indentStep = ' '.repeat(diff)
}

ctx = Object.assign({}, ctx, {
allNullValues: false,
implicitKey: !explicitKey && (simpleKeys || !allNullValues),
Expand Down Expand Up @@ -150,7 +161,8 @@ export function stringifyPair(
}
if (sp0 === -1 || nl0 < sp0) hasPropsLine = true
}
if (!hasPropsLine) ws = `\n${ctx.indent}`
if (!hasPropsLine && (indentStep.length > 0 || !value.flow))
ws = `\n${ctx.indent}`
}
} else if (valueStr === '' || valueStr[0] === '\n') {
ws = ''
Expand Down
122 changes: 122 additions & 0 deletions tests/doc/stringify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -871,6 +871,128 @@ describe('custom indent', () => {
})
})

describe('keepIndent: true', () => {
test('keep object indentation', () => {
const src = source`
key:
super: indented
`
const doc = YAML.parseDocument(src, { keepSourceTokens: true })
expect(doc.toString({ keepIndent: true })).toBe(src)
})

test('keep array indentation', () => {
const src = source`
key:
- name: foo
- name: bar
- name: bam
- name: baz
`
const doc = YAML.parseDocument(src, { keepSourceTokens: true })
expect(doc.toString({ keepIndent: true })).toBe(src)
})

test('keep complex indentation', () => {
const src = source`
key:
super:
- name: foo
- name: bar
- name: bam
- name: baz
metadata:
foo: why
`
const doc = YAML.parseDocument(src, { keepSourceTokens: true })
expect(doc.toString({ keepIndent: true })).toBe(src)
})

test('handles multiline seq flow on same line', () => {
const src = source`
key: [
aaaaaaaa,
bbbbbbbb,
cccccccc,
dddddddd,
eeeeeeee,
ffffffff,
gggggggg,
hhhhhhhh
]
`
const doc = YAML.parseDocument(src, { keepSourceTokens: true })
expect(doc.toString({ keepIndent: true })).toBe(src)
})
test('handles multiline flow on same line', () => {
const src = source`
key: !tag {
one: aaaaaaaa,
two: bbbbbbbb,
three: cccccccc,
four: dddddddd,
five: eeeeeeee
}
`
const doc = YAML.parseDocument(src, { keepSourceTokens: true })
expect(doc.toString({ keepIndent: true })).toBe(src)
})

test('handles multiline flow on next line', () => {
const src = source`
key:
!tag {
one: aaaaaaaa,
two: bbbbbbbb,
three: cccccccc,
four: dddddddd,
five: eeeeeeee
}
`
const doc = YAML.parseDocument(src, { keepSourceTokens: true })
expect(doc.toString({ keepIndent: true })).toBe(src)
})

test('handles multiline flow on next line', () => {
const src = source`
key:
!tag {
one: aaaaaaaa,
two: bbbbbbbb,
three: cccccccc,
four: dddddddd,
five: eeeeeeee
}
`
const doc = YAML.parseDocument(src, { keepSourceTokens: true })
expect(doc.toString({ keepIndent: true })).toBe(src)
})

test('handles explicit key map with no indent', () => {
const src = source`
foo:
? [ key ]
: !tag
- foo
- bar
`
const doc = YAML.parseDocument(src, { keepSourceTokens: true })
expect(doc.toString({ keepIndent: true })).toBe(src)
})

test('handles explicit key map with indent', () => {
const src = source`
foo:
? [ key ]
: !tag
- foo
- bar
`
const doc = YAML.parseDocument(src, { keepSourceTokens: true })
expect(doc.toString({ keepIndent: true })).toBe(src)
})
})

describe('indentSeq: false', () => {
let obj: unknown
beforeEach(() => {
Expand Down
Loading