Implement a comprehensive panel detection system for manga and comics
with automatic fallback chain for maximum compatibility.
Core detector (detector.js):
- PanelDetector class with in-memory caching
- Lazy-loading of OpenCV and TensorFlow.js
- Validation logic to filter poor detections
- Cache management to avoid re-detection
OpenCV edge detection (opencv.js):
- Canny edge detection for panel boundaries
- Contour finding with bounding box extraction
- Size and aspect ratio filtering
- Reading order sorting (top-to-bottom, left-to-right)
ML-based detection (coco-ssd.js):
- COCO-SSD pre-trained model integration
- Object detection for irregular panel layouts
- Rectangular filtering for panel-like regions
- Handles edge cases where edge detection fails
Grid-based fallback (grid.js):
- Lightweight 3x3 grid detection
- Empty cell detection via alpha channel analysis
- Adjacent panel merging algorithm
- Always works as final fallback
The detection pipeline tries OpenCV first (fast, accurate),
falls back to ML detection if validation fails,
and uses grid detection as ultimate baseline.
The MOBI6.init() method builds #fileposList (the map of all filepos byte-offset references, used to insert <a id="fileposXXXX"> 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. <lars@ermert.es>
If the viewer is running in an RTL context (this is not the same as the
reading direction of the Book itself), and a fixed-layout rendered view
is scaled (which is often the case), anchoring the transform to the
left breaks page positioning.
In Safari, clicking on links triggers `selectionchange`. Since we do not
move the caret when flipping through pages, when you have flipped to the
next or previous pages and click on any link, it would take you back to
the caret instead of activating the link.
Note that the bug occurs in Safari 17 but not in WebKitGTK 2.46.
Not sure if there's a way to fix this and still retain the "set anchor
to caret on click" behavior. But I guess this behavior isn't really that
essential, anyway. So removing it for now.
Fixes#44