From 6be0a9136dca077864782d1ad3b53a2cbb35748e Mon Sep 17 00:00:00 2001 From: Eemeli Aro Date: Tue, 19 Nov 2024 12:41:54 +0200 Subject: [PATCH] fix: Default to literal block scalar if folded would overflow (fixes #585) --- src/stringify/stringifyString.ts | 42 +++++++++++++++++++------------- tests/doc/foldFlowLines.ts | 10 ++++++++ 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/src/stringify/stringifyString.ts b/src/stringify/stringifyString.ts index 401143cd..b21dedd2 100644 --- a/src/stringify/stringifyString.ts +++ b/src/stringify/stringifyString.ts @@ -246,29 +246,37 @@ function blockString( } const indentSize = indent ? '2' : '1' // root is at -1 - let header = - (literal ? '|' : '>') + (startWithSpace ? indentSize : '') + chomp + // Leading | or > is added later + let header = (startWithSpace ? indentSize : '') + chomp if (comment) { header += ' ' + commentString(comment.replace(/ ?[\r\n]+/g, ' ')) if (onComment) onComment() } - if (literal) { - value = value.replace(/\n+/g, `$&${indent}`) - return `${header}\n${indent}${start}${value}${end}` + if (!literal) { + const foldedValue = value + .replace(/\n+/g, '\n$&') + .replace(/(?:^|\n)([\t ].*)(?:([\n\t ]*)\n(?![\n\t ]))?/g, '$1$2') // more-indented lines aren't folded + // ^ more-ind. ^ empty ^ capture next empty lines only at end of indent + .replace(/\n+/g, `$&${indent}`) + let literalFallback = false + const foldOptions = getFoldOptions(ctx, true) + if (blockQuote !== 'folded' && type !== Scalar.BLOCK_FOLDED) { + foldOptions.onOverflow = () => { + literalFallback = true + } + } + const body = foldFlowLines( + `${start}${foldedValue}${end}`, + indent, + FOLD_BLOCK, + foldOptions + ) + if (!literalFallback) return `>${header}\n${indent}${body}` } - value = value - .replace(/\n+/g, '\n$&') - .replace(/(?:^|\n)([\t ].*)(?:([\n\t ]*)\n(?![\n\t ]))?/g, '$1$2') // more-indented lines aren't folded - // ^ more-ind. ^ empty ^ capture next empty lines only at end of indent - .replace(/\n+/g, `$&${indent}`) - const body = foldFlowLines( - `${start}${value}${end}`, - indent, - FOLD_BLOCK, - getFoldOptions(ctx, true) - ) - return `${header}\n${indent}${body}` + + value = value.replace(/\n+/g, `$&${indent}`) + return `|${header}\n${indent}${start}${value}${end}` } function plainString( diff --git a/tests/doc/foldFlowLines.ts b/tests/doc/foldFlowLines.ts index 7b4e4485..6c225dab 100644 --- a/tests/doc/foldFlowLines.ts +++ b/tests/doc/foldFlowLines.ts @@ -272,6 +272,16 @@ describe('block scalar', () => { } `) }) + + test('block scalar with very long lines (#585)', () => { + const str = ('a'.repeat(30) + '\n').repeat(3) + expect(YAML.stringify(str, { lineWidth: 20 })).toBe(source` + | + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + `) + }) }) describe('end-to-end', () => {