Skip to content

Commit 5e5470a

Browse files
authoredNov 20, 2022
feat: Use indicator line for props on block collection values of mappings (#425)
1 parent 29732f3 commit 5e5470a

File tree

3 files changed

+191
-29
lines changed

3 files changed

+191
-29
lines changed
 

‎src/stringify/stringifyPair.ts

+43-16
Original file line numberDiff line numberDiff line change
@@ -82,17 +82,16 @@ export function stringifyPair(
8282
str += lineComment(str, ctx.indent, commentString(keyComment))
8383
}
8484

85-
let vcb = ''
86-
let valueComment = null
85+
let vsb, vcb, valueComment
8786
if (isNode(value)) {
88-
if (value.spaceBefore) vcb = '\n'
89-
if (value.commentBefore) {
90-
const cs = commentString(value.commentBefore)
91-
vcb += `\n${indentComment(cs, ctx.indent)}`
92-
}
87+
vsb = !!value.spaceBefore
88+
vcb = value.commentBefore
9389
valueComment = value.comment
94-
} else if (value && typeof value === 'object') {
95-
value = doc.createNode(value)
90+
} else {
91+
vsb = false
92+
vcb = null
93+
valueComment = null
94+
if (value && typeof value === 'object') value = doc.createNode(value)
9695
}
9796
ctx.implicitKey = false
9897
if (!explicitKey && !keyComment && isScalar(value))
@@ -109,7 +108,7 @@ export function stringifyPair(
109108
!value.anchor
110109
) {
111110
// If indentSeq === false, consider '- ' as part of indentation where possible
112-
ctx.indent = ctx.indent.substr(2)
111+
ctx.indent = ctx.indent.substring(2)
113112
}
114113

115114
let valueCommentDone = false
@@ -120,13 +119,41 @@ export function stringifyPair(
120119
() => (chompKeep = true)
121120
)
122121
let ws = ' '
123-
if (vcb || keyComment) {
124-
if (valueStr === '' && !ctx.inFlow) ws = vcb === '\n' ? '\n\n' : vcb
125-
else ws = `${vcb}\n${ctx.indent}`
122+
if (keyComment || vsb || vcb) {
123+
ws = vsb ? '\n' : ''
124+
if (vcb) {
125+
const cs = commentString(vcb)
126+
ws += `\n${indentComment(cs, ctx.indent)}`
127+
}
128+
if (valueStr === '' && !ctx.inFlow) {
129+
if (ws === '\n') ws = '\n\n'
130+
} else {
131+
ws += `\n${ctx.indent}`
132+
}
126133
} else if (!explicitKey && isCollection(value)) {
127-
const flow = valueStr[0] === '[' || valueStr[0] === '{'
128-
if (!flow || valueStr.includes('\n')) ws = `\n${ctx.indent}`
129-
} else if (valueStr === '' || valueStr[0] === '\n') ws = ''
134+
const vs0 = valueStr[0]
135+
const nl0 = valueStr.indexOf('\n')
136+
const hasNewline = nl0 !== -1
137+
const flow = ctx.inFlow ?? value.flow ?? value.items.length === 0
138+
if (hasNewline || !flow) {
139+
let hasPropsLine = false
140+
if (hasNewline && (vs0 === '&' || vs0 === '!')) {
141+
let sp0 = valueStr.indexOf(' ')
142+
if (
143+
vs0 === '&' &&
144+
sp0 !== -1 &&
145+
sp0 < nl0 &&
146+
valueStr[sp0 + 1] === '!'
147+
) {
148+
sp0 = valueStr.indexOf(' ', sp0 + 1)
149+
}
150+
if (sp0 === -1 || nl0 < sp0) hasPropsLine = true
151+
}
152+
if (!hasPropsLine) ws = `\n${ctx.indent}`
153+
}
154+
} else if (valueStr === '' || valueStr[0] === '\n') {
155+
ws = ''
156+
}
130157
str += ws + valueStr
131158

132159
if (ctx.inFlow) {

‎tests/doc/stringify.js

+142-12
Original file line numberDiff line numberDiff line change
@@ -253,8 +253,7 @@ foo:
253253
const seq = [{ foo: { bar: { baz } } }, { fe: { fi: { fo: { baz } } } }]
254254
expect(YAML.stringify(seq)).toBe(`- foo:
255255
bar:
256-
baz:
257-
&a1
256+
baz: &a1
258257
a: 1
259258
- fe:
260259
fi:
@@ -364,6 +363,137 @@ z:
364363
)
365364
})
366365
})
366+
367+
describe('properties on collections in block mapping', () => {
368+
test('explicit tag on block sequence', () => {
369+
const src = source`
370+
key: !tag
371+
- one
372+
- two
373+
`
374+
const doc = YAML.parseDocument(src)
375+
expect(String(doc)).toBe(src)
376+
})
377+
test('explicit tag on block mapping', () => {
378+
const src = source`
379+
key: !tag
380+
one: 1
381+
two: 2
382+
`
383+
const doc = YAML.parseDocument(src)
384+
expect(String(doc)).toBe(src)
385+
})
386+
test('single-line comment on block sequence', () => {
387+
const src = source`
388+
key: #comment
389+
- one
390+
- two
391+
`
392+
const doc = YAML.parseDocument(src)
393+
expect(String(doc)).toBe(source`
394+
key:
395+
#comment
396+
- one
397+
- two
398+
`)
399+
})
400+
test('single-line comment and explicit tag on block sequence', () => {
401+
const src = source`
402+
key: #comment
403+
!tag
404+
- one
405+
- two
406+
`
407+
const doc = YAML.parseDocument(src)
408+
expect(String(doc)).toBe(source`
409+
key:
410+
#comment
411+
!tag
412+
- one
413+
- two
414+
`)
415+
})
416+
test('explicit tag and comment on block sequence', () => {
417+
const src = source`
418+
key: !tag
419+
#comment
420+
- one
421+
- two
422+
`
423+
const doc = YAML.parseDocument(src)
424+
expect(String(doc)).toBe(source`
425+
key:
426+
#comment
427+
!tag
428+
- one
429+
- two
430+
`)
431+
})
432+
test('anchor on block sequence', () => {
433+
const src = source`
434+
key: &anchor
435+
- one
436+
- two
437+
`
438+
const doc = YAML.parseDocument(src)
439+
expect(String(doc)).toBe(src)
440+
})
441+
test('anchor and explicit tag on block sequence', () => {
442+
const src = source`
443+
key: &anchor !tag
444+
- one
445+
- two
446+
`
447+
const doc = YAML.parseDocument(src)
448+
expect(String(doc)).toBe(src)
449+
})
450+
test('explicit tag on empty mapping', () => {
451+
const doc = new YAML.Document({ key: {} })
452+
doc.get('key').tag = '!tag'
453+
expect(String(doc)).toBe(source`
454+
key: !tag {}
455+
`)
456+
})
457+
test('explicit tag on single-line flow mapping', () => {
458+
const src = source`
459+
key: !tag { one: 1, two: 2 }
460+
`
461+
const doc = YAML.parseDocument(src)
462+
expect(String(doc)).toBe(src)
463+
})
464+
test('explicit tag on multi-line flow mapping', () => {
465+
const src = source`
466+
key: !tag {
467+
one: aaaaaaaaaa,
468+
two: bbbbbbbbbb,
469+
three: cccccccccc,
470+
four: dddddddddd,
471+
five: eeeeeeeeee
472+
}
473+
`
474+
const doc = YAML.parseDocument(src)
475+
expect(String(doc)).toBe(source`
476+
key:
477+
!tag {
478+
one: aaaaaaaaaa,
479+
two: bbbbbbbbbb,
480+
three: cccccccccc,
481+
four: dddddddddd,
482+
five: eeeeeeeeee
483+
}
484+
`)
485+
})
486+
test('explicit tag on explicit-value block sequence', () => {
487+
const src = source`
488+
? [ key ]
489+
: !tag
490+
- one
491+
- two
492+
`
493+
const doc = YAML.parseDocument(src)
494+
expect(String(doc)).toBe(src)
495+
})
496+
})
367497
})
368498

369499
test('eemeli/yaml#43: Quoting colons', () => {
@@ -702,7 +832,7 @@ describe('indentSeq: false', () => {
702832
b: 2
703833
map:
704834
seq:
705-
#sc
835+
#sc
706836
- a
707837
`)
708838
})
@@ -714,7 +844,7 @@ describe('indentSeq: false', () => {
714844
b: 2
715845
map:
716846
seq:
717-
#sc
847+
#sc
718848
- a
719849
`)
720850
})
@@ -1182,15 +1312,15 @@ describe('YAML.stringify on ast Document', () => {
11821312
})
11831313

11841314
describe('flow collection padding', () => {
1185-
const doc = new YAML.Document();
1186-
doc.contents = new YAML.YAMLSeq();
1187-
doc.contents.items = [1, 2];
1188-
doc.contents.flow = true;
1315+
const doc = new YAML.Document()
1316+
doc.contents = new YAML.YAMLSeq()
1317+
doc.contents.items = [1, 2]
1318+
doc.contents.flow = true
11891319

11901320
test('default', () => {
11911321
expect(doc.toString()).toBe('[ 1, 2 ]\n')
1192-
});
1322+
})
11931323
test('default', () => {
1194-
expect(doc.toString({flowCollectionPadding: false})).toBe('[1, 2]\n')
1195-
});
1196-
})
1324+
expect(doc.toString({ flowCollectionPadding: false })).toBe('[1, 2]\n')
1325+
})
1326+
})

‎tests/doc/types.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -778,7 +778,12 @@ date (00:00:00Z): 2002-12-14\n`)
778778
test('eemeli/yaml#78', () => {
779779
const set = new Set(['a', 'b', 'c'])
780780
const str = YAML.stringify({ set }, { version: '1.1' })
781-
expect(str).toBe(`set:\n !!set\n ? a\n ? b\n ? c\n`)
781+
expect(str).toBe(source`
782+
set: !!set
783+
? a
784+
? b
785+
? c
786+
`)
782787
})
783788
})
784789

0 commit comments

Comments
 (0)
Please sign in to comment.