diff --git a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp index 046e41c0..b103fe5b 100644 --- a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp +++ b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp @@ -158,7 +158,6 @@ void ChapterHtmlSlimParser::startNewTextBlock(const BlockStyle& blockStyle) { // Merge with existing block style to accumulate CSS styling from parent block elements. // This handles cases like

text

where the // div's margin should be preserved, even though it has no direct text content. - BlockStyle incoming = blockStyle; const bool brGapPending = currentTextBlock->getBlockStyle().fromBrElement; if (brGapPending) { @@ -665,6 +664,13 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char* const auto userAlignmentBlockStyle = BlockStyle::fromCssStyle( cssStyle, emSize, static_cast(self->paragraphAlignment), self->viewportWidth); + // Block/header boundaries must flush any buffered trailing word first. + // Otherwise tags like ..."item?"

can carry the final word into the next paragraph. + if (self->partWordBufferIndex > 0 && ((matches(name, HEADER_TAGS, NUM_HEADER_TAGS)) || + (matches(name, BLOCK_TAGS, NUM_BLOCK_TAGS) && strcmp(name, "br") != 0))) { + self->flushPartWordBuffer(); + } + if (matches(name, HEADER_TAGS, NUM_HEADER_TAGS)) { self->currentCssStyle = cssStyle; auto headerBlockStyle = BlockStyle::fromCssStyle(cssStyle, emSize, CssTextAlign::Center, self->viewportWidth);