diff --git a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp index 79ae15fb..4b11f6e3 100644 --- a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp +++ b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp @@ -976,7 +976,15 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char* } if (strcmp(name, "ul") == 0 || strcmp(name, "ol") == 0) { - self->listStack.push_back({self->depth, name[0] == 'o', 0}); + int startCounter = 0; + if (name[0] == 'o') { + const char* startAttr = getAttribute(atts, "start"); + if (startAttr) { + int v = atoi(startAttr); + if (v > 0) startCounter = v - 1; // counter is pre-incremented on each
  • + } + } + self->listStack.push_back({self->depth, name[0] == 'o', startCounter}); } const float emSize = static_cast(self->renderer.getFontAscenderSize(self->fontId)); @@ -1050,14 +1058,21 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char* self->updateEffectiveInlineStyle(); if (strcmp(name, "li") == 0) { - 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 { - strcpy(marker, "\xe2\x80\xa2"); + if (!self->listStack.empty()) { + char marker[12]; + if (self->listStack.back().isOrdered) { + const char* valueAttr = getAttribute(atts, "value"); + if (valueAttr) { + int v = atoi(valueAttr); + if (v > 0) self->listStack.back().counter = v - 1; + } + self->listStack.back().counter += 1; + snprintf(marker, sizeof(marker), "%d.", self->listStack.back().counter); + } else { + strcpy(marker, "\xe2\x80\xa2"); + } + self->currentTextBlock->addWord(marker, EpdFontFamily::REGULAR); } - self->currentTextBlock->addWord(marker, EpdFontFamily::REGULAR); } else if (strcmp(name, "pre") == 0) { // Record depth so characterData can treat \n as a hard line break inside
    .
             // depth has not been incremented yet here; it will be after startElement returns.
    diff --git a/scripts/generate_test_epub.py b/scripts/generate_test_epub.py
    index 76c199a5..1b12e1ff 100644
    --- a/scripts/generate_test_epub.py
    +++ b/scripts/generate_test_epub.py
    @@ -1016,6 +1016,7 @@ def main():
     
  • pre with inline code element
  • horizontal rules between paragraphs
  • superscript and subscript rendering
  • +
  • list rendering: ul, ol, nested, start/value attributes, bare li
  • """, ), @@ -1086,6 +1087,88 @@ greet("World");

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.


    End of horizontal rule tests.

    +""", + ), + [], + ), + ( + "6. Lists", + make_chapter( + "List Rendering Tests", + """ +

    Unordered list (bullets)

    + + +

    Ordered list (numbers 1, 2, 3)

    +
      +
    1. One
    2. +
    3. Two
    4. +
    5. Three
    6. +
    + +

    Ordered list with start="5" (should begin at 5)

    +
      +
    1. Five
    2. +
    3. Six
    4. +
    5. Seven
    6. +
    + +

    Ordered list with li value override (should show 1, 2, 5, 6)

    +
      +
    1. One
    2. +
    3. Two
    4. +
    5. Five
    6. +
    7. Six
    8. +
    + +

    Nested lists

    + + +

    Nested ordered lists (outer 1,2 / inner 1,2,3)

    +
      +
    1. Chapter one +
        +
      1. Section A
      2. +
      3. Section B
      4. +
      5. Section C
      6. +
      +
    2. +
    3. Chapter two +
        +
      1. Section A
      2. +
      3. Section B
      4. +
      +
    4. +
    + +

    Bare li outside any list (no bullet should appear)

    +

    The line below is a bare <li> with no enclosing <ul> or <ol>. No bullet or number should appear before it.

    +
  • This bare li should have no marker
  • +

    Normal paragraph resumed.

    + +

    List with inline formatting

    + """, ), [], diff --git a/test/epubs/test_text_rendering.epub b/test/epubs/test_text_rendering.epub index 74be4b31..95673e00 100644 Binary files a/test/epubs/test_text_rendering.epub and b/test/epubs/test_text_rendering.epub differ