From 9a676796f728347b0127162079c13d23a0f7fee8 Mon Sep 17 00:00:00 2001 From: Larzans Date: Fri, 3 Apr 2026 18:01:12 +0200 Subject: [PATCH] Fix MOBI anchors being calculated too late (#118) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The MOBI6.init() method builds #fileposList (the map of all filepos byte-offset references, used to insert anchors into section HTML) after calling getGuide() and the TOC-section loader — both of which call createDocument() → loadText(), which caches the section HTML. Since #fileposList is still empty at that point, the cached HTML has no anchor elements. Later, when Foliate calls getElementById('filepos12345') on the cached (anchor-less) document, it returns null, so the paginator falls back to ?? 0 — i.e. scroll to position 0 = first page. For EPUB this doesn't happen because chapters are separate files; navigation loads a new section by index, not by searching for an anchor element within one section. Co-authored-by: Lars E. --- mobi.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/mobi.js b/mobi.js index 811b0d3..20c77a8 100644 --- a/mobi.js +++ b/mobi.js @@ -719,6 +719,16 @@ class MOBI6 { size: section.end - section.start, })) + // get list of all `filepos` references in the book, + // which will be used to insert anchor elements + // because only then can they be referenced in the DOM + // NOTE: must be built BEFORE getGuide()/createDocument() so that sections + // cached during init() already have anchor elements inserted. + this.#fileposList = [...new Set( + Array.from(str.matchAll(fileposRegex), m => m[1]))] + .map(filepos => ({ filepos, number: Number(filepos) })) + .sort((a, b) => a.number - b.number) + try { this.landmarks = await this.getGuide() const tocHref = this.landmarks @@ -765,14 +775,6 @@ class MOBI6 { console.warn(e) } - // get list of all `filepos` references in the book, - // which will be used to insert anchor elements - // because only then can they be referenced in the DOM - this.#fileposList = [...new Set( - Array.from(str.matchAll(fileposRegex), m => m[1]))] - .map(filepos => ({ filepos, number: Number(filepos) })) - .sort((a, b) => a.number - b.number) - this.metadata = this.mobi.getMetadata() this.getCover = this.mobi.getCover.bind(this.mobi) return this