fix: Handle EPUB 3 TOC to spine mapping when nav file in subdirectory

Fixes https://github.com/daveallie/crosspoint-reader/issues/264
This commit is contained in:
Dave Allie 2026-01-13 00:52:00 +11:00
parent 0165fab581
commit 93a68b9ffa
No known key found for this signature in database
GPG Key ID: F2FDDB3AD8D0276F
4 changed files with 10 additions and 5 deletions

View File

@ -167,7 +167,10 @@ bool Epub::parseTocNavFile() const {
}
const auto navSize = tempNavFile.size();
TocNavParser navParser(contentBasePath, navSize, bookMetadataCache.get());
// Note: We can't use `contentBasePath` here as the nav file may be in a different folder to the content.opf
// and the HTMLX nav file will have hrefs relative to itself
const std::string navContentBasePath = tocNavItem.substr(0, tocNavItem.find_last_of('/') + 1);
TocNavParser navParser(navContentBasePath, navSize, bookMetadataCache.get());
if (!navParser.setup()) {
Serial.printf("[%lu] [EBP] Could not setup toc nav parser\n", millis());

View File

@ -167,7 +167,7 @@ void XMLCALL ContentOpfParser::startElement(void* userData, const XML_Char* name
if (strcmp(atts[i], "id") == 0) {
itemId = atts[i + 1];
} else if (strcmp(atts[i], "href") == 0) {
href = self->baseContentPath + atts[i + 1];
href = FsHelpers::normalisePath(self->baseContentPath + atts[i + 1]);
} else if (strcmp(atts[i], "media-type") == 0) {
mediaType = atts[i + 1];
} else if (strcmp(atts[i], "properties") == 0) {
@ -243,7 +243,7 @@ void XMLCALL ContentOpfParser::startElement(void* userData, const XML_Char* name
break;
}
} else if (strcmp(atts[i], "href") == 0) {
textHref = self->baseContentPath + atts[i + 1];
textHref = FsHelpers::normalisePath(self->baseContentPath + atts[i + 1]);
}
}
if ((type == "text" || (type == "start" && !self->textReferenceHref.empty())) && (textHref.length() > 0)) {

View File

@ -1,5 +1,6 @@
#include "TocNavParser.h"
#include <FsHelpers.h>
#include <HardwareSerial.h>
#include "../BookMetadataCache.h"
@ -140,7 +141,7 @@ void XMLCALL TocNavParser::endElement(void* userData, const XML_Char* name) {
if (strcmp(name, "a") == 0 && self->state == IN_ANCHOR) {
// Create TOC entry when closing anchor tag (we have all data now)
if (!self->currentLabel.empty() && !self->currentHref.empty()) {
std::string href = self->baseContentPath + self->currentHref;
std::string href = FsHelpers::normalisePath(self->baseContentPath + self->currentHref);
std::string anchor;
const size_t pos = href.find('#');

View File

@ -1,5 +1,6 @@
#include "TocNcxParser.h"
#include <FsHelpers.h>
#include <HardwareSerial.h>
#include "../BookMetadataCache.h"
@ -159,7 +160,7 @@ void XMLCALL TocNcxParser::endElement(void* userData, const XML_Char* name) {
// This is the safest place to push the data, assuming <navLabel> always comes before <content>.
// NCX spec says navLabel comes before content.
if (!self->currentLabel.empty() && !self->currentSrc.empty()) {
std::string href = self->baseContentPath + self->currentSrc;
std::string href = FsHelpers::normalisePath(self->baseContentPath + self->currentSrc);
std::string anchor;
const size_t pos = href.find('#');