mirror of
https://github.com/daveallie/crosspoint-reader.git
synced 2026-02-05 07:07:38 +03:00
## Summary * **What is the goal of this PR?** Add EPUB 3 support by implementing native navigation document (nav.xhtml) parsing with NCX fallback, addressing issue Fixes: #143. * **What changes are included?** - New `TocNavParser` for parsing EPUB 3 HTML5 navigation documents (`<nav epub:type="toc">`) - Detection of nav documents via `properties="nav"` attribute in OPF manifest - Fallback logic: try EPUB 3 nav first, fall back to NCX (EPUB 2) if unavailable - Graceful degradation: books without any TOC now load with a warning instead of failing ## Additional Context * The implementation follows the existing streaming XML parser pattern using Expat to minimize RAM usage on the ESP32-C3 * EPUB 3 books that include both nav.xhtml and toc.ncx will prefer the nav document (per EPUB 3 spec recommendation) * No breaking changes - existing EPUB 2 books continue to work as before * Tested on examples from https://idpf.github.io/epub3-samples/30/samples.html
48 lines
1.4 KiB
C++
48 lines
1.4 KiB
C++
#pragma once
|
|
#include <Print.h>
|
|
#include <expat.h>
|
|
|
|
#include <string>
|
|
|
|
class BookMetadataCache;
|
|
|
|
// Parser for EPUB 3 nav.xhtml navigation documents
|
|
// Parses HTML5 nav elements with epub:type="toc" to extract table of contents
|
|
class TocNavParser final : public Print {
|
|
enum ParserState {
|
|
START,
|
|
IN_HTML,
|
|
IN_BODY,
|
|
IN_NAV_TOC, // Inside <nav epub:type="toc">
|
|
IN_OL, // Inside <ol>
|
|
IN_LI, // Inside <li>
|
|
IN_ANCHOR, // Inside <a>
|
|
};
|
|
|
|
const std::string& baseContentPath;
|
|
size_t remainingSize;
|
|
XML_Parser parser = nullptr;
|
|
ParserState state = START;
|
|
BookMetadataCache* cache;
|
|
|
|
// Track nesting depth for <ol> elements to determine TOC depth
|
|
uint8_t olDepth = 0;
|
|
// Current entry data being collected
|
|
std::string currentLabel;
|
|
std::string currentHref;
|
|
|
|
static void startElement(void* userData, const XML_Char* name, const XML_Char** atts);
|
|
static void characterData(void* userData, const XML_Char* s, int len);
|
|
static void endElement(void* userData, const XML_Char* name);
|
|
|
|
public:
|
|
explicit TocNavParser(const std::string& baseContentPath, const size_t xmlSize, BookMetadataCache* cache)
|
|
: baseContentPath(baseContentPath), remainingSize(xmlSize), cache(cache) {}
|
|
~TocNavParser() override;
|
|
|
|
bool setup();
|
|
|
|
size_t write(uint8_t) override;
|
|
size_t write(const uint8_t* buffer, size_t size) override;
|
|
};
|