diff --git a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp
index 368a4c60..50ceb86f 100644
--- a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp
+++ b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp
@@ -554,6 +554,12 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char*
}
}
+ // Track ul/ol nesting so li markers can be numbered or bulleted accordingly
+ if (strcmp(name, "ul") == 0 || strcmp(name, "ol") == 0) {
+ self->listStack.push_back({self->depth, strcmp(name, "ol") == 0, 0});
+ // fall through to depth increment
+ }
+
const float emSize = static_cast(self->renderer.getFontAscenderSize(self->fontId));
const auto userAlignmentBlockStyle = BlockStyle::fromCssStyle(
cssStyle, emSize, static_cast(self->paragraphAlignment), self->viewportWidth);
@@ -581,7 +587,14 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char*
self->updateEffectiveInlineStyle();
if (strcmp(name, "li") == 0) {
- self->currentTextBlock->addWord("\xe2\x80\xa2", EpdFontFamily::REGULAR);
+ char marker[12];
+ if (!self->listStack.empty() && self->listStack.back().isOrdered) {
+ self->listStack.back().counter += 1;
+ snprintf(marker, sizeof(marker), "%d.", self->listStack.back().counter);
+ } else {
+ strncpy(marker, "\xe2\x80\xa2", sizeof(marker));
+ }
+ self->currentTextBlock->addWord(marker, EpdFontFamily::REGULAR);
}
}
} else if (matches(name, UNDERLINE_TAGS, NUM_UNDERLINE_TAGS)) {
@@ -893,6 +906,11 @@ void XMLCALL ChapterHtmlSlimParser::endElement(void* userData, const XML_Char* n
self->depth -= 1;
+ // Pop list entries whose ul/ol is now out of scope
+ while (!self->listStack.empty() && self->listStack.back().depth >= self->depth) {
+ self->listStack.pop_back();
+ }
+
// Closing a footnote link — create entry from collected text and href
if (self->insideFootnoteLink && self->depth == self->footnoteLinkDepth) {
if (self->currentFootnoteLinkText[0] != '\0' && self->currentFootnoteLinkHref[0] != '\0') {
diff --git a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.h b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.h
index 1cc0ea39..dec13ca0 100644
--- a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.h
+++ b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.h
@@ -70,6 +70,14 @@ class ChapterHtmlSlimParser {
int tableRowIndex = 0;
int tableColIndex = 0;
+ // List nesting tracking for ul/ol markers
+ struct ListEntry {
+ int depth;
+ bool isOrdered;
+ int counter;
+ };
+ std::vector listStack;
+
// Anchor-to-page mapping: tracks which page each HTML id attribute lands on
int completedPageCount = 0;
std::vector> anchorData;