From c4a1850159f28ff46e377869ce4503d0d4e45c5d Mon Sep 17 00:00:00 2001 From: Luca Ciucci Date: Thu, 15 Oct 2026 10:09:00 +0200 Subject: [PATCH] Preserve trailing newlines in quoted scalars Quoted scalars used CLIP chomping after flow folding, which truncated multiple trailing newlines to one. Chomping applies to block scalars; quoted scalars must retain the newlines produced by folding. --- src/scantoken.cpp | 2 +- test/integration/load_node_test.cpp | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/scantoken.cpp b/src/scantoken.cpp index b13d21133..dec824d89 100644 --- a/src/scantoken.cpp +++ b/src/scantoken.cpp @@ -349,7 +349,7 @@ void Scanner::ScanQuotedScalar() { params.fold = FOLD_FLOW; params.eatLeadingWhitespace = true; params.trimTrailingSpaces = false; - params.chomp = CLIP; + params.chomp = KEEP; params.onDocIndicator = THROW; // insert a potential simple key diff --git a/test/integration/load_node_test.cpp b/test/integration/load_node_test.cpp index e5f52bea6..dfd91739f 100644 --- a/test/integration/load_node_test.cpp +++ b/test/integration/load_node_test.cpp @@ -540,5 +540,26 @@ TEST(LoadNodeTest, NonUniqueMapKey) { EXPECT_THROW(Load("{a: A, b: B, a: A}"), NonUniqueMapKey); } +TEST(LoadNodeTest, PreserveTrailingNewlinesInQuotedScalars) { + for (char quote : {'\'', '"'}) { + for (std::size_t trailing = 0; trailing <= 4; ++trailing) { + SCOPED_TRACE(::testing::Message() + << "quote=" << quote << ", trailing=" << trailing); + std::string input = "value: "; + input += quote; + input += "a\n\n b"; + if (trailing > 0) { + input += std::string(trailing + 1, '\n'); + input += " "; + } + input += quote; + input += '\n'; + + EXPECT_EQ("a\nb" + std::string(trailing, '\n'), + Load(input)["value"].as()); + } + } +} + } // namespace } // namespace YAML