From c8551ebca947c0fcd7a5cbd5b7b2636d4bd6925c Mon Sep 17 00:00:00 2001 From: Eemeli Aro Date: Fri, 30 Dec 2022 11:30:16 +0200 Subject: [PATCH] fix: Quote top-level map keys containing document markers (fixes #431) --- src/stringify/stringifyString.ts | 12 ++++++++---- tests/doc/stringify.js | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/stringify/stringifyString.ts b/src/stringify/stringifyString.ts index c71a848d..942b2d1a 100644 --- a/src/stringify/stringifyString.ts +++ b/src/stringify/stringifyString.ts @@ -266,7 +266,7 @@ function plainString( onChompKeep?: () => void ) { const { type, value } = item - const { actualString, implicitKey, indent, inFlow } = ctx + const { actualString, implicitKey, indent, indentStep, inFlow } = ctx if ( (implicitKey && /[\n[\]{},]/.test(value)) || (inFlow && /[[\]{},]/.test(value)) @@ -298,9 +298,13 @@ function plainString( // Where allowed & type not set explicitly, prefer block style for multiline strings return blockString(item, ctx, onComment, onChompKeep) } - if (indent === '' && containsDocumentMarker(value)) { - ctx.forceBlockIndent = true - return blockString(item, ctx, onComment, onChompKeep) + if (containsDocumentMarker(value)) { + if (indent === '') { + ctx.forceBlockIndent = true + return blockString(item, ctx, onComment, onChompKeep) + } else if (implicitKey && indent === indentStep) { + return quotedString(value, ctx) + } } const str = value.replace(/\n+/g, `$&\n${indent}`) // Verify that output will be parsed as a string, as e.g. plain numbers and diff --git a/tests/doc/stringify.js b/tests/doc/stringify.js index 2e33bfa1..b973e96f 100644 --- a/tests/doc/stringify.js +++ b/tests/doc/stringify.js @@ -1118,6 +1118,20 @@ describe('Document markers in top-level scalars', () => { }) }) +describe('Document markers in top-level map keys (eemeli/yaml#431)', () => { + test('---', () => { + const str = YAML.stringify({ '--- x': 42 }) + expect(str).toBe('"--- x": 42\n') + expect(YAML.parse(str)).toEqual({ '--- x': 42 }) + }) + + test('...', () => { + const str = YAML.stringify({ '... x': 42 }) + expect(str).toBe('"... x": 42\n') + expect(YAML.parse(str)).toEqual({ '... x': 42 }) + }) +}) + describe('undefined values', () => { test('undefined', () => { expect(YAML.stringify(undefined)).toBeUndefined()