diff --git a/cpp/parser/GumboNormalizer.c b/cpp/parser/GumboNormalizer.c index 53c14d4c2..232131a80 100644 --- a/cpp/parser/GumboNormalizer.c +++ b/cpp/parser/GumboNormalizer.c @@ -598,7 +598,11 @@ static void flatten_bq_node(GumboNode *node, buffer_t *ib, buffer_t *out) { return; } if (is_br_node(node)) { - flush_inline_p(ib, out, NULL); + // Emit the canonical
so it is not silently dropped. + // With buffered inline content it just terminates the current paragraph. + if (!flush_inline_p(ib, out, NULL)) { + buffer_append_str(out, "
"); + } return; } if (is_block_producing(node) || is_blockquote_node(node)) { diff --git a/cpp/tests/GumboParserTest.cpp b/cpp/tests/GumboParserTest.cpp index 0a978260a..a0ec32bc8 100644 --- a/cpp/tests/GumboParserTest.cpp +++ b/cpp/tests/GumboParserTest.cpp @@ -401,7 +401,7 @@ TEST(GumboParserTest, DivRemappings) { "hello

hi
"), "

what do you think of this craziness

another one " - "hello

hi

"); + "hello


hi

"); } TEST(GumboParserTest, ListFlattening) { @@ -508,6 +508,13 @@ TEST(GumboParserTest, BrRemappings) { "href='https://google.com'>Net

"), "

Asdasdasd



Sent with Net

"); + // A
between blockquote paragraphs is preserved. + EXPECT_EQ( + GumboParser::normalizeHtml( + "

this is a pretty short blockquote.


This is " + "a line after an empty line.

"), + "

this is a pretty short blockquote.


This is a " + "line after an empty line.

"); } // Preserve text alignment @@ -581,9 +588,10 @@ TEST(GumboParserTest, InterBlockWhitespace) { EXPECT_EQ(GumboParser::normalizeHtml( "

Asdasd

\n\n

Asdasd

\n\n

Asdasda

"), "

Asdasd

Asdasd

Asdasda

"); - EXPECT_EQ(GumboParser::normalizeHtml( - "\n

Asdasd

\n

Asdasd

\n

Asdasda

\n"), - "

Asdasd

Asdasd

Asdasda

"); + EXPECT_EQ( + GumboParser::normalizeHtml( + "\n

Asdasd

\n

Asdasd

\n

Asdasda

\n"), + "

Asdasd

Asdasd

Asdasda

"); EXPECT_EQ(GumboParser::normalizeHtml("

Asdasd

Asdasd

"), "

Asdasd

Asdasd

"); diff --git a/src/web/__tests__/htmlNormalizer.test.ts b/src/web/__tests__/htmlNormalizer.test.ts index 0d9a628a6..a129e72c5 100644 --- a/src/web/__tests__/htmlNormalizer.test.ts +++ b/src/web/__tests__/htmlNormalizer.test.ts @@ -359,7 +359,7 @@ describe('htmlNormalizer', () => { ], [ '
what do you think of this craziness
  • another one hello

    hi
', - '

what do you think of this craziness

another one hello

hi

', + '

what do you think of this craziness

another one hello


hi

', ], ])('%s → %s', (input, expected) => { expect(normalizeHtml(input)).toBe(expected); @@ -477,6 +477,16 @@ describe('htmlNormalizer', () => { '

Asdasdasd



Sent with Net

' ); }); + + test('
between blockquote paragraphs is preserved', () => { + expect( + normalizeHtml( + '

this is a pretty short blockquote.


This is a line after an empty line.

' + ) + ).toBe( + '

this is a pretty short blockquote.


This is a line after an empty line.

' + ); + }); }); describe('character escaping', () => { diff --git a/src/web/normalization/htmlNormalizer.ts b/src/web/normalization/htmlNormalizer.ts index 3150fc964..4b2c0d34a 100644 --- a/src/web/normalization/htmlNormalizer.ts +++ b/src/web/normalization/htmlNormalizer.ts @@ -401,7 +401,11 @@ function flattenBqNode( } if (!isElement(node)) return; if (isBrNode(node)) { - flushInlineP(ib, out); + // Emit the canonical
so it is not silently dropped. + // With buffered inline content it just terminates the current paragraph. + if (!flushInlineP(ib, out)) { + out.buf += '
'; + } return; } if (isBlockProducing(node) || isBlockquoteNode(node)) {