Skip to content

Commit 2edefe2

Browse files
committed
Add keepIndent option to toString
1 parent 1dbf1c7 commit 2edefe2

4 files changed

Lines changed: 185 additions & 6 deletions

File tree

src/options.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,15 @@ export type ToStringOptions = {
329329
*/
330330
indentSeq?: boolean
331331

332+
/**
333+
* Whether indentation in srcToken should be preserved.
334+
*
335+
* For this to work, you need to have parsed the yaml document with keepSourceTokens: true
336+
*
337+
* Default: `false`
338+
*/
339+
keepIndent?: boolean
340+
332341
/**
333342
* Maximum line width (set to `0` to disable folding).
334343
*
@@ -387,4 +396,4 @@ export type ToStringOptions = {
387396
* Default: `'true'`
388397
*/
389398
verifyAliasOrder?: boolean
390-
}
399+
}

src/stringify/stringify.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export function createStringifyContext(
5050
falseStr: 'false',
5151
flowCollectionPadding: true,
5252
indentSeq: true,
53+
keepIndent: false,
5354
lineWidth: 80,
5455
minContentWidth: 20,
5556
nullStr: 'null',
@@ -175,4 +176,4 @@ export function stringify(
175176
return isScalar(node) || str[0] === '{' || str[0] === '['
176177
? `${props} ${str}`
177178
: `${props}\n${ctx.indent}${str}`
178-
}
179+
}

src/stringify/stringifyPair.ts

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ export function stringifyPair(
1515
allNullValues,
1616
doc,
1717
indent,
18-
indentStep,
19-
options: { commentString, indentSeq, simpleKeys }
18+
options: { commentString, indentSeq, keepIndent, simpleKeys }
2019
} = ctx
20+
2121
let keyComment = (isNode(key) && key.comment) || null
2222
if (simpleKeys) {
2323
if (keyComment) {
@@ -37,6 +37,24 @@ export function stringifyPair(
3737
? key.type === Scalar.BLOCK_FOLDED || key.type === Scalar.BLOCK_LITERAL
3838
: typeof key === 'object'))
3939

40+
let indentStep = ctx.indentStep
41+
if (
42+
keepIndent &&
43+
isNode(key) &&
44+
isNode(value) &&
45+
key.srcToken &&
46+
value.srcToken &&
47+
'indent' in key.srcToken &&
48+
'indent' in value.srcToken
49+
) {
50+
let diff = value.srcToken.indent - indent.length
51+
52+
// all elements other than YAMLSeq in block form must be indented to be valid YAML.
53+
if (diff > 0 || (isSeq(value) && !value.flow)) {
54+
indentStep = ' '.repeat(diff)
55+
}
56+
}
57+
4058
ctx = Object.assign({}, ctx, {
4159
allNullValues: false,
4260
implicitKey: !explicitKey && (simpleKeys || !allNullValues),
@@ -166,4 +184,4 @@ export function stringifyPair(
166184
}
167185

168186
return str
169-
}
187+
}

tests/doc/stringify.ts

Lines changed: 152 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -871,6 +871,157 @@ describe('custom indent', () => {
871871
})
872872
})
873873

874+
describe('keepIndent: true', () => {
875+
test('keep object indentation', () => {
876+
const src = source`
877+
key:
878+
super: indented
879+
`
880+
const doc = YAML.parseDocument(src, { keepSourceTokens: true })
881+
expect(doc.toString({ keepIndent: true })).toBe(src)
882+
})
883+
884+
test('keep array indentation', () => {
885+
const src = source`
886+
key:
887+
- name: foo
888+
- name: bar
889+
- name: bam
890+
- name: baz
891+
`
892+
const doc = YAML.parseDocument(src, { keepSourceTokens: true })
893+
expect(doc.toString({ keepIndent: true })).toBe(src)
894+
})
895+
896+
test('keep complex indentation', () => {
897+
const src = source`
898+
key:
899+
super:
900+
- name: foo
901+
- name: bar
902+
- name: bam
903+
- name: baz
904+
metadata:
905+
foo: why
906+
`
907+
const doc = YAML.parseDocument(src, { keepSourceTokens: true })
908+
expect(doc.toString({ keepIndent: true })).toBe(src)
909+
})
910+
911+
test('handles multiline seq flow on same line', () => {
912+
const doc = YAML.parseDocument(
913+
source`
914+
key: [
915+
aaaaaaaa,
916+
bbbbbbbb,
917+
cccccccc,
918+
dddddddd,
919+
eeeeeeee,
920+
ffffffff,
921+
gggggggg,
922+
hhhhhhhh,
923+
]
924+
`,
925+
{ keepSourceTokens: true }
926+
)
927+
expect(doc.toString({ keepIndent: true })).toBe(
928+
source`
929+
key:
930+
[
931+
aaaaaaaa,
932+
bbbbbbbb,
933+
cccccccc,
934+
dddddddd,
935+
eeeeeeee,
936+
ffffffff,
937+
gggggggg,
938+
hhhhhhhh
939+
]
940+
`
941+
)
942+
})
943+
test('handles multiline flow on same line', () => {
944+
const doc = YAML.parseDocument(
945+
source`
946+
key: !tag {
947+
one: aaaaaaaa,
948+
two: bbbbbbbb,
949+
three: cccccccc,
950+
four: dddddddd,
951+
five: eeeeeeee
952+
}
953+
`,
954+
{ keepSourceTokens: true }
955+
)
956+
expect(doc.toString({ keepIndent: true })).toBe(
957+
source`
958+
key:
959+
!tag {
960+
one: aaaaaaaa,
961+
two: bbbbbbbb,
962+
three: cccccccc,
963+
four: dddddddd,
964+
five: eeeeeeee
965+
}
966+
`
967+
)
968+
})
969+
970+
test('handles multiline flow on next line', () => {
971+
const src = source`
972+
key:
973+
!tag {
974+
one: aaaaaaaa,
975+
two: bbbbbbbb,
976+
three: cccccccc,
977+
four: dddddddd,
978+
five: eeeeeeee
979+
}
980+
`
981+
const doc = YAML.parseDocument(src, { keepSourceTokens: true })
982+
expect(doc.toString({ keepIndent: true })).toBe(src)
983+
})
984+
985+
test('handles multiline flow on next line', () => {
986+
const src = source`
987+
key:
988+
!tag {
989+
one: aaaaaaaa,
990+
two: bbbbbbbb,
991+
three: cccccccc,
992+
four: dddddddd,
993+
five: eeeeeeee
994+
}
995+
`
996+
const doc = YAML.parseDocument(src, { keepSourceTokens: true })
997+
expect(doc.toString({ keepIndent: true })).toBe(src)
998+
})
999+
1000+
test('handles explicit key map with no indent', () => {
1001+
const src = source`
1002+
foo:
1003+
? [ key ]
1004+
: !tag
1005+
- foo
1006+
- bar
1007+
`
1008+
const doc = YAML.parseDocument(src, { keepSourceTokens: true })
1009+
expect(doc.toString({ keepIndent: true })).toBe(src)
1010+
})
1011+
1012+
test('handles explicit key map with indent', () => {
1013+
const src = source`
1014+
foo:
1015+
? [ key ]
1016+
: !tag
1017+
- foo
1018+
- bar
1019+
`
1020+
const doc = YAML.parseDocument(src, { keepSourceTokens: true })
1021+
expect(doc.toString({ keepIndent: true })).toBe(src)
1022+
})
1023+
})
1024+
8741025
describe('indentSeq: false', () => {
8751026
let obj: unknown
8761027
beforeEach(() => {
@@ -1451,4 +1602,4 @@ describe('flow collection padding', () => {
14511602
test('default', () => {
14521603
expect(doc.toString({ flowCollectionPadding: false })).toBe('[1, 2]\n')
14531604
})
1454-
})
1605+
})

0 commit comments

Comments
 (0)