mirror of
https://github.com/daveallie/crosspoint-reader.git
synced 2026-02-04 14:47:37 +03:00
fix: Handle EPUB 3 TOC to spine mapping when nav file in subdirectory (#332)
## Summary - Nav file in EPUB 3 file is a HTML file with relative hrefs - If this file exists anywhere but in the same location as the content.opf file, navigating in the book will fail - Bump the book cache version to rebuild potentially broken books ## Additional Context - Fixes https://github.com/daveallie/crosspoint-reader/issues/264 --- ### AI Usage While CrossPoint doesn't have restrictions on AI tools in contributing, please be transparent about their usage as it helps set the right context for reviewers. Did you use AI tools to help write this code? - [ ] Yes - [ ] Partially - [x] No
This commit is contained in:
parent
0165fab581
commit
8f3df7e10e
@ -167,7 +167,10 @@ bool Epub::parseTocNavFile() const {
|
|||||||
}
|
}
|
||||||
const auto navSize = tempNavFile.size();
|
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()) {
|
if (!navParser.setup()) {
|
||||||
Serial.printf("[%lu] [EBP] Could not setup toc nav parser\n", millis());
|
Serial.printf("[%lu] [EBP] Could not setup toc nav parser\n", millis());
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
#include "FsHelpers.h"
|
#include "FsHelpers.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
constexpr uint8_t BOOK_CACHE_VERSION = 3;
|
constexpr uint8_t BOOK_CACHE_VERSION = 4;
|
||||||
constexpr char bookBinFile[] = "/book.bin";
|
constexpr char bookBinFile[] = "/book.bin";
|
||||||
constexpr char tmpSpineBinFile[] = "/spine.bin.tmp";
|
constexpr char tmpSpineBinFile[] = "/spine.bin.tmp";
|
||||||
constexpr char tmpTocBinFile[] = "/toc.bin.tmp";
|
constexpr char tmpTocBinFile[] = "/toc.bin.tmp";
|
||||||
|
|||||||
@ -167,7 +167,7 @@ void XMLCALL ContentOpfParser::startElement(void* userData, const XML_Char* name
|
|||||||
if (strcmp(atts[i], "id") == 0) {
|
if (strcmp(atts[i], "id") == 0) {
|
||||||
itemId = atts[i + 1];
|
itemId = atts[i + 1];
|
||||||
} else if (strcmp(atts[i], "href") == 0) {
|
} 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) {
|
} else if (strcmp(atts[i], "media-type") == 0) {
|
||||||
mediaType = atts[i + 1];
|
mediaType = atts[i + 1];
|
||||||
} else if (strcmp(atts[i], "properties") == 0) {
|
} else if (strcmp(atts[i], "properties") == 0) {
|
||||||
@ -243,7 +243,7 @@ void XMLCALL ContentOpfParser::startElement(void* userData, const XML_Char* name
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (strcmp(atts[i], "href") == 0) {
|
} 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)) {
|
if ((type == "text" || (type == "start" && !self->textReferenceHref.empty())) && (textHref.length() > 0)) {
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
#include "TocNavParser.h"
|
#include "TocNavParser.h"
|
||||||
|
|
||||||
|
#include <FsHelpers.h>
|
||||||
#include <HardwareSerial.h>
|
#include <HardwareSerial.h>
|
||||||
|
|
||||||
#include "../BookMetadataCache.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) {
|
if (strcmp(name, "a") == 0 && self->state == IN_ANCHOR) {
|
||||||
// Create TOC entry when closing anchor tag (we have all data now)
|
// Create TOC entry when closing anchor tag (we have all data now)
|
||||||
if (!self->currentLabel.empty() && !self->currentHref.empty()) {
|
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;
|
std::string anchor;
|
||||||
|
|
||||||
const size_t pos = href.find('#');
|
const size_t pos = href.find('#');
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
#include "TocNcxParser.h"
|
#include "TocNcxParser.h"
|
||||||
|
|
||||||
|
#include <FsHelpers.h>
|
||||||
#include <HardwareSerial.h>
|
#include <HardwareSerial.h>
|
||||||
|
|
||||||
#include "../BookMetadataCache.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>.
|
// This is the safest place to push the data, assuming <navLabel> always comes before <content>.
|
||||||
// NCX spec says navLabel comes before content.
|
// NCX spec says navLabel comes before content.
|
||||||
if (!self->currentLabel.empty() && !self->currentSrc.empty()) {
|
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;
|
std::string anchor;
|
||||||
|
|
||||||
const size_t pos = href.find('#');
|
const size_t pos = href.find('#');
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user