From 87eeac2326b8a843fba8a42252df64b1fa3b2b8a Mon Sep 17 00:00:00 2001 From: dajiaohuang Date: Wed, 28 Oct 2026 07:23:26 +0800 Subject: [PATCH 1/2] Preserve empty lines between consecutive br elements --- Source/HtmlRenderer/Core/Parse/DomParser.cs | 4 ++-- .../HtmlRenderingRegressionTests.cs | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Source/HtmlRenderer/Core/Parse/DomParser.cs b/Source/HtmlRenderer/Core/Parse/DomParser.cs index 7ffb57384..6d88b916a 100644 --- a/Source/HtmlRenderer/Core/Parse/DomParser.cs +++ b/Source/HtmlRenderer/Core/Parse/DomParser.cs @@ -1174,10 +1174,10 @@ private static void CorrectLineBreaksBlocks(CssBox box) if (!box.IsBrElement) return; var previousSibling = DomUtils.GetPreviousSibling(box); - if (previousSibling == null || previousSibling.IsBlock) + if (previousSibling == null || previousSibling.IsBlock || previousSibling.IsBrElement) { var nextSibling = DomUtils.GetFollowingSiblings(box, b => b.IsInline && !b.IsBrElement, true).FirstOrDefault(); - if (nextSibling == null) + if (nextSibling == null || previousSibling?.IsBrElement == true) { box.Text = "\n"; box.ParseToWords(); diff --git a/Source/Test/HtmlRenderer.IntegrationTest/HtmlRenderingRegressionTests.cs b/Source/Test/HtmlRenderer.IntegrationTest/HtmlRenderingRegressionTests.cs index 842c5dc1b..05d58bd36 100644 --- a/Source/Test/HtmlRenderer.IntegrationTest/HtmlRenderingRegressionTests.cs +++ b/Source/Test/HtmlRenderer.IntegrationTest/HtmlRenderingRegressionTests.cs @@ -22,6 +22,19 @@ public sealed class HtmlRenderingRegressionTests private static bool _samplesLoaded; + [TestMethod] + public async Task Render_ConsecutiveBreaks_LeaveAnEmptyLine() + { + EnsureSamplesLoaded(); + + using var oneBreak = await RenderSample("first
second"); + using var consecutiveBreaks = await RenderSample("first

second"); + + Assert.IsTrue( + consecutiveBreaks.Height > oneBreak.Height, + $"Consecutive
elements should add an empty line. One break: {oneBreak.Height}px; two breaks: {consecutiveBreaks.Height}px."); + } + [DoNotParallelize] [TestMethod] [DynamicData(nameof(GetSamples), DynamicDataDisplayName = nameof(GetSampleDisplayName))] From a85b17348c3c90aebba1bf04d872beb2b312a036 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20D=C3=BCrrenberger?= Date: Mon, 9 Nov 2026 09:57:06 +0100 Subject: [PATCH 2/2] Treat
as inline and end the line after a line break - Keep
in the surrounding inline run instead of splitting it into its own block - Start the new line with the word after a line break, so a trailing
adds no line and a leading one does - Ignore line breaks when summing the max-content width of a line - Drop the newline right after a
,  or