Introduce ordered list support
This commit is contained in:
@@ -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<float>(self->renderer.getFontAscenderSize(self->fontId));
|
const float emSize = static_cast<float>(self->renderer.getFontAscenderSize(self->fontId));
|
||||||
const auto userAlignmentBlockStyle = BlockStyle::fromCssStyle(
|
const auto userAlignmentBlockStyle = BlockStyle::fromCssStyle(
|
||||||
cssStyle, emSize, static_cast<CssTextAlign>(self->paragraphAlignment), self->viewportWidth);
|
cssStyle, emSize, static_cast<CssTextAlign>(self->paragraphAlignment), self->viewportWidth);
|
||||||
@@ -581,7 +587,14 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char*
|
|||||||
self->updateEffectiveInlineStyle();
|
self->updateEffectiveInlineStyle();
|
||||||
|
|
||||||
if (strcmp(name, "li") == 0) {
|
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)) {
|
} 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;
|
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
|
// Closing a footnote link — create entry from collected text and href
|
||||||
if (self->insideFootnoteLink && self->depth == self->footnoteLinkDepth) {
|
if (self->insideFootnoteLink && self->depth == self->footnoteLinkDepth) {
|
||||||
if (self->currentFootnoteLinkText[0] != '\0' && self->currentFootnoteLinkHref[0] != '\0') {
|
if (self->currentFootnoteLinkText[0] != '\0' && self->currentFootnoteLinkHref[0] != '\0') {
|
||||||
|
|||||||
@@ -70,6 +70,14 @@ class ChapterHtmlSlimParser {
|
|||||||
int tableRowIndex = 0;
|
int tableRowIndex = 0;
|
||||||
int tableColIndex = 0;
|
int tableColIndex = 0;
|
||||||
|
|
||||||
|
// List nesting tracking for ul/ol markers
|
||||||
|
struct ListEntry {
|
||||||
|
int depth;
|
||||||
|
bool isOrdered;
|
||||||
|
int counter;
|
||||||
|
};
|
||||||
|
std::vector<ListEntry> listStack;
|
||||||
|
|
||||||
// Anchor-to-page mapping: tracks which page each HTML id attribute lands on
|
// Anchor-to-page mapping: tracks which page each HTML id attribute lands on
|
||||||
int completedPageCount = 0;
|
int completedPageCount = 0;
|
||||||
std::vector<std::pair<std::string, uint16_t>> anchorData;
|
std::vector<std::pair<std::string, uint16_t>> anchorData;
|
||||||
|
|||||||
Reference in New Issue
Block a user