From 7d36d71efd8ae841fd9507631bc5a66fc7fe239d Mon Sep 17 00:00:00 2001 From: Evan Fenner Date: Mon, 12 Jan 2026 14:05:42 -0700 Subject: [PATCH] feat: Add [Table omitted] placeholder for tables in EPUB chapters Instead of silently dropping table content, display an italicized '[Table omitted]' message where tables appear in EPUBs. This provides better feedback to readers about omitted content. Co-Authored-By: Warp --- .../Epub/parsers/ChapterHtmlSlimParser.cpp | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp index b96d28f8..5bca4d79 100644 --- a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp +++ b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp @@ -25,7 +25,7 @@ constexpr int NUM_ITALIC_TAGS = sizeof(ITALIC_TAGS) / sizeof(ITALIC_TAGS[0]); const char* IMAGE_TAGS[] = {"img"}; constexpr int NUM_IMAGE_TAGS = sizeof(IMAGE_TAGS) / sizeof(IMAGE_TAGS[0]); -const char* SKIP_TAGS[] = {"head", "table"}; +const char* SKIP_TAGS[] = {"head"}; constexpr int NUM_SKIP_TAGS = sizeof(SKIP_TAGS) / sizeof(SKIP_TAGS[0]); bool isWhitespace(const char c) { return c == ' ' || c == '\r' || c == '\n' || c == '\t'; } @@ -63,6 +63,27 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char* return; } + // Special handling for tables - show placeholder text instead of dropping silently + if (strcmp(name, "table") == 0) { + // Flush any partial word + if (self->partWordBufferIndex > 0 && self->currentTextBlock) { + self->partWordBuffer[self->partWordBufferIndex] = '\0'; + self->currentTextBlock->addWord(self->partWordBuffer, EpdFontFamily::REGULAR); + self->partWordBufferIndex = 0; + } + + // Add placeholder text + self->startNewTextBlock((TextBlock::Style)self->paragraphAlignment); + if (self->currentTextBlock) { + self->currentTextBlock->addWord("[Table omitted]", EpdFontFamily::ITALIC); + } + + // Skip table contents + self->skipUntilDepth = self->depth; + self->depth += 1; + return; + } + if (matches(name, IMAGE_TAGS, NUM_IMAGE_TAGS)) { // TODO: Start processing image tags self->skipUntilDepth = self->depth;