From e74bd387e4ac807d1d20be2f28bf71e296f69970 Mon Sep 17 00:00:00 2001 From: Raphael Fakhri <153192858+RaphaelFakhri@users.noreply.github.com> Date: Wed, 21 Oct 2026 07:49:09 +0000 Subject: [PATCH] fix: normalizer adding empty list items for whitespace around blocks --- cpp/parser/GumboNormalizer.c | 6 +++++- cpp/tests/GumboParserTest.cpp | 7 +++++++ src/web/__tests__/htmlNormalizer.test.ts | 6 ++++++ src/web/normalization/htmlNormalizer.ts | 7 ++++++- 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/cpp/parser/GumboNormalizer.c b/cpp/parser/GumboNormalizer.c index 5a6210f15..562a745f1 100644 --- a/cpp/parser/GumboNormalizer.c +++ b/cpp/parser/GumboNormalizer.c @@ -638,8 +638,12 @@ static void flatten_li_node(GumboNode *node, buffer_t *ib, buffer_t *out, li_ctx_t *ctx); static void flush_li_buffer(buffer_t *ib, buffer_t *out, li_ctx_t *ctx) { - if (ib->len == 0) + /* Whitespace around blocks inside an
  • (e.g. `
  • \n

    a

    \n
  • `) + * is layout noise, not an extra list item. */ + if (is_whitespace_only(ib->data, ib->len)) { + buffer_clear(ib); return; + } buffer_append_str(out, "el, "li", out); buffer_append_str(out, ">"); diff --git a/cpp/tests/GumboParserTest.cpp b/cpp/tests/GumboParserTest.cpp index ff06232c9..07c6c4af9 100644 --- a/cpp/tests/GumboParserTest.cpp +++ b/cpp/tests/GumboParserTest.cpp @@ -607,6 +607,13 @@ TEST(GumboParserTest, InterBlockWhitespace) { EXPECT_EQ(GumboParser::normalizeHtml("

    Asdasd

    Asdasd

    "), "

    Asdasd

    Asdasd

    "); + // Whitespace around blocks inside a list item must not add empty items. + EXPECT_EQ(GumboParser::normalizeHtml( + ""), + ""); + EXPECT_EQ(GumboParser::normalizeHtml("
    1. a

      b

    "), + "
    1. a
    2. b
    "); + // Significant inline content between blocks is still wrapped in

    . EXPECT_EQ(GumboParser::normalizeHtml("

    a

    hello

    b

    "), "

    a

    hello

    b

    "); diff --git a/src/web/__tests__/htmlNormalizer.test.ts b/src/web/__tests__/htmlNormalizer.test.ts index 04547a2de..8501ea353 100644 --- a/src/web/__tests__/htmlNormalizer.test.ts +++ b/src/web/__tests__/htmlNormalizer.test.ts @@ -616,6 +616,12 @@ describe('htmlNormalizer', () => { '

    Asdasd

    Asdasd

    Asdasda

    ', ], ['

    Asdasd

    Asdasd

    ', '

    Asdasd

    Asdasd

    '], + // Whitespace around blocks inside a list item must not add empty items. + [ + '', + '', + ], + ['
    1. a

      b

    ', '
    1. a
    2. b
    '], // Significant inline content between blocks is still wrapped in

    . ['

    a

    hello

    b

    ', '

    a

    hello

    b

    '], // Spaces inside text / between inlines must be preserved. diff --git a/src/web/normalization/htmlNormalizer.ts b/src/web/normalization/htmlNormalizer.ts index 35e6ef8a2..bb4f96090 100644 --- a/src/web/normalization/htmlNormalizer.ts +++ b/src/web/normalization/htmlNormalizer.ts @@ -432,7 +432,12 @@ function flushLiBuffer( out: { buf: string }, ctx: LiCtx ): void { - if (ib.buf.length === 0) return; + // Whitespace around blocks inside an
  • (e.g. `
  • \n

    a

    \n
  • `) + // is layout noise, not an extra list item. + if (isWhitespaceOnly(ib.buf)) { + ib.buf = ''; + return; + } out.buf += ``; out.buf += emitStylesOpen(ctx.styles); out.buf += ib.buf;