From 1e59aa6d5d3009e626cd4ee997975e41e72ea652 Mon Sep 17 00:00:00 2001 From: Jonas Diemer Date: Mon, 29 Dec 2025 14:51:33 +0100 Subject: [PATCH] Added logic to parse the guide section of the Content Opf. --- lib/Epub/Epub/parsers/ContentOpfParser.cpp | 41 ++++++++++++++++++++++ lib/Epub/Epub/parsers/ContentOpfParser.h | 1 + 2 files changed, 42 insertions(+) diff --git a/lib/Epub/Epub/parsers/ContentOpfParser.cpp b/lib/Epub/Epub/parsers/ContentOpfParser.cpp index a62b2d0a..85604d2e 100644 --- a/lib/Epub/Epub/parsers/ContentOpfParser.cpp +++ b/lib/Epub/Epub/parsers/ContentOpfParser.cpp @@ -122,6 +122,18 @@ void XMLCALL ContentOpfParser::startElement(void* userData, const XML_Char* name return; } + if (self->state == IN_PACKAGE && (strcmp(name, "guide") == 0 || strcmp(name, "opf:guide") == 0)) { + self->state = IN_GUIDE; + // TODO Remove print + Serial.printf("[%lu] [COF] Entering guide state.\n", millis()); + if (!FsHelpers::openFileForRead("COF", self->cachePath + itemCacheFile, self->tempItemStore)) { + Serial.printf( + "[%lu] [COF] Couldn't open temp items file for reading. This is probably going to be a fatal error.\n", + millis()); + } + return; + } + if (self->state == IN_METADATA && (strcmp(name, "meta") == 0 || strcmp(name, "opf:meta") == 0)) { bool isCover = false; std::string coverItemId; @@ -200,6 +212,29 @@ void XMLCALL ContentOpfParser::startElement(void* userData, const XML_Char* name return; } } + // parse the guide + if (self->state == IN_GUIDE && (strcmp(name, "reference") == 0 || strcmp(name, "opf:reference") == 0)) { + std::string type; + std::string textHref; + for (int i = 0; atts[i]; i += 2) { + if (strcmp(atts[i], "type") == 0) { + type = atts[i + 1]; + if (type == "text") { + continue; + } else { + Serial.printf("[%lu] [COF] Skipping non-text reference in guide: %s\n", millis(), type.c_str()); + break; + } + } else if (strcmp(atts[i], "href") == 0) { + textHref = atts[i + 1]; + } + } + if ((type == "text") && (textHref.length() > 0)) { + Serial.printf("[%lu] [COF] Found text reference in guide: %s.\n", millis(), textHref.c_str()); + // TODO: now this has to become the chapter we display + } + return; + } } void XMLCALL ContentOpfParser::characterData(void* userData, const XML_Char* s, const int len) { @@ -221,6 +256,12 @@ void XMLCALL ContentOpfParser::endElement(void* userData, const XML_Char* name) return; } + if (self->state == IN_GUIDE && (strcmp(name, "guide") == 0 || strcmp(name, "opf:guide") == 0)) { + self->state = IN_PACKAGE; + self->tempItemStore.close(); + return; + } + if (self->state == IN_MANIFEST && (strcmp(name, "manifest") == 0 || strcmp(name, "opf:manifest") == 0)) { self->state = IN_PACKAGE; self->tempItemStore.close(); diff --git a/lib/Epub/Epub/parsers/ContentOpfParser.h b/lib/Epub/Epub/parsers/ContentOpfParser.h index 5415de67..252ebee1 100644 --- a/lib/Epub/Epub/parsers/ContentOpfParser.h +++ b/lib/Epub/Epub/parsers/ContentOpfParser.h @@ -14,6 +14,7 @@ class ContentOpfParser final : public Print { IN_BOOK_TITLE, IN_MANIFEST, IN_SPINE, + IN_GUIDE, }; const std::string& cachePath;