Skip to content

Commit

Permalink
feat: Use indicator line for props on block collection values of mapp…
Browse files Browse the repository at this point in the history
…ings (#425)
  • Loading branch information
eemeli committed Nov 20, 2022
1 parent 29732f3 commit 5e5470a
Show file tree
Hide file tree
Showing 3 changed files with 191 additions and 29 deletions.
59 changes: 43 additions & 16 deletions src/stringify/stringifyPair.ts
Expand Up @@ -82,17 +82,16 @@ export function stringifyPair(
str += lineComment(str, ctx.indent, commentString(keyComment))
}

let vcb = ''
let valueComment = null
let vsb, vcb, valueComment
if (isNode(value)) {
if (value.spaceBefore) vcb = '\n'
if (value.commentBefore) {
const cs = commentString(value.commentBefore)
vcb += `\n${indentComment(cs, ctx.indent)}`
}
vsb = !!value.spaceBefore
vcb = value.commentBefore
valueComment = value.comment
} else if (value && typeof value === 'object') {
value = doc.createNode(value)
} else {
vsb = false
vcb = null
valueComment = null
if (value && typeof value === 'object') value = doc.createNode(value)
}
ctx.implicitKey = false
if (!explicitKey && !keyComment && isScalar(value))
Expand All @@ -109,7 +108,7 @@ export function stringifyPair(
!value.anchor
) {
// If indentSeq === false, consider '- ' as part of indentation where possible
ctx.indent = ctx.indent.substr(2)
ctx.indent = ctx.indent.substring(2)
}

let valueCommentDone = false
Expand All @@ -120,13 +119,41 @@ export function stringifyPair(
() => (chompKeep = true)
)
let ws = ' '
if (vcb || keyComment) {
if (valueStr === '' && !ctx.inFlow) ws = vcb === '\n' ? '\n\n' : vcb
else ws = `${vcb}\n${ctx.indent}`
if (keyComment || vsb || vcb) {
ws = vsb ? '\n' : ''
if (vcb) {
const cs = commentString(vcb)
ws += `\n${indentComment(cs, ctx.indent)}`
}
if (valueStr === '' && !ctx.inFlow) {
if (ws === '\n') ws = '\n\n'
} else {
ws += `\n${ctx.indent}`
}
} else if (!explicitKey && isCollection(value)) {
const flow = valueStr[0] === '[' || valueStr[0] === '{'
if (!flow || valueStr.includes('\n')) ws = `\n${ctx.indent}`
} else if (valueStr === '' || valueStr[0] === '\n') ws = ''
const vs0 = valueStr[0]
const nl0 = valueStr.indexOf('\n')
const hasNewline = nl0 !== -1
const flow = ctx.inFlow ?? value.flow ?? value.items.length === 0
if (hasNewline || !flow) {
let hasPropsLine = false
if (hasNewline && (vs0 === '&' || vs0 === '!')) {
let sp0 = valueStr.indexOf(' ')
if (
vs0 === '&' &&
sp0 !== -1 &&
sp0 < nl0 &&
valueStr[sp0 + 1] === '!'
) {
sp0 = valueStr.indexOf(' ', sp0 + 1)
}
if (sp0 === -1 || nl0 < sp0) hasPropsLine = true
}
if (!hasPropsLine) ws = `\n${ctx.indent}`
}
} else if (valueStr === '' || valueStr[0] === '\n') {
ws = ''
}
str += ws + valueStr

if (ctx.inFlow) {
Expand Down
154 changes: 142 additions & 12 deletions tests/doc/stringify.js
Expand Up @@ -253,8 +253,7 @@ foo:
const seq = [{ foo: { bar: { baz } } }, { fe: { fi: { fo: { baz } } } }]
expect(YAML.stringify(seq)).toBe(`- foo:
bar:
baz:
&a1
baz: &a1
a: 1
- fe:
fi:
Expand Down Expand Up @@ -364,6 +363,137 @@ z:
)
})
})

describe('properties on collections in block mapping', () => {
test('explicit tag on block sequence', () => {
const src = source`
key: !tag
- one
- two
`
const doc = YAML.parseDocument(src)
expect(String(doc)).toBe(src)
})
test('explicit tag on block mapping', () => {
const src = source`
key: !tag
one: 1
two: 2
`
const doc = YAML.parseDocument(src)
expect(String(doc)).toBe(src)
})
test('single-line comment on block sequence', () => {
const src = source`
key: #comment
- one
- two
`
const doc = YAML.parseDocument(src)
expect(String(doc)).toBe(source`
key:
#comment
- one
- two
`)
})
test('single-line comment and explicit tag on block sequence', () => {
const src = source`
key: #comment
!tag
- one
- two
`
const doc = YAML.parseDocument(src)
expect(String(doc)).toBe(source`
key:
#comment
!tag
- one
- two
`)
})
test('explicit tag and comment on block sequence', () => {
const src = source`
key: !tag
#comment
- one
- two
`
const doc = YAML.parseDocument(src)
expect(String(doc)).toBe(source`
key:
#comment
!tag
- one
- two
`)
})
test('anchor on block sequence', () => {
const src = source`
key: &anchor
- one
- two
`
const doc = YAML.parseDocument(src)
expect(String(doc)).toBe(src)
})
test('anchor and explicit tag on block sequence', () => {
const src = source`
key: &anchor !tag
- one
- two
`
const doc = YAML.parseDocument(src)
expect(String(doc)).toBe(src)
})
test('explicit tag on empty mapping', () => {
const doc = new YAML.Document({ key: {} })
doc.get('key').tag = '!tag'
expect(String(doc)).toBe(source`
key: !tag {}
`)
})
test('explicit tag on single-line flow mapping', () => {
const src = source`
key: !tag { one: 1, two: 2 }
`
const doc = YAML.parseDocument(src)
expect(String(doc)).toBe(src)
})
test('explicit tag on multi-line flow mapping', () => {
const src = source`
key: !tag {
one: aaaaaaaaaa,
two: bbbbbbbbbb,
three: cccccccccc,
four: dddddddddd,
five: eeeeeeeeee
}
`
const doc = YAML.parseDocument(src)
expect(String(doc)).toBe(source`
key:
!tag {
one: aaaaaaaaaa,
two: bbbbbbbbbb,
three: cccccccccc,
four: dddddddddd,
five: eeeeeeeeee
}
`)
})
test('explicit tag on explicit-value block sequence', () => {
const src = source`
? [ key ]
: !tag
- one
- two
`
const doc = YAML.parseDocument(src)
expect(String(doc)).toBe(src)
})
})
})

test('eemeli/yaml#43: Quoting colons', () => {
Expand Down Expand Up @@ -702,7 +832,7 @@ describe('indentSeq: false', () => {
b: 2
map:
seq:
#sc
#sc
- a
`)
})
Expand All @@ -714,7 +844,7 @@ describe('indentSeq: false', () => {
b: 2
map:
seq:
#sc
#sc
- a
`)
})
Expand Down Expand Up @@ -1182,15 +1312,15 @@ describe('YAML.stringify on ast Document', () => {
})

describe('flow collection padding', () => {
const doc = new YAML.Document();
doc.contents = new YAML.YAMLSeq();
doc.contents.items = [1, 2];
doc.contents.flow = true;
const doc = new YAML.Document()
doc.contents = new YAML.YAMLSeq()
doc.contents.items = [1, 2]
doc.contents.flow = true

test('default', () => {
expect(doc.toString()).toBe('[ 1, 2 ]\n')
});
})
test('default', () => {
expect(doc.toString({flowCollectionPadding: false})).toBe('[1, 2]\n')
});
})
expect(doc.toString({ flowCollectionPadding: false })).toBe('[1, 2]\n')
})
})
7 changes: 6 additions & 1 deletion tests/doc/types.js
Expand Up @@ -778,7 +778,12 @@ date (00:00:00Z): 2002-12-14\n`)
test('eemeli/yaml#78', () => {
const set = new Set(['a', 'b', 'c'])
const str = YAML.stringify({ set }, { version: '1.1' })
expect(str).toBe(`set:\n !!set\n ? a\n ? b\n ? c\n`)
expect(str).toBe(source`
set: !!set
? a
? b
? c
`)
})
})

Expand Down

0 comments on commit 5e5470a

Please sign in to comment.