Merge pull request #130 from jpirnay/fix-kosync-upload

fix: Reestablish 1.37 kosync upload behaviour
This commit is contained in:
jpirnay
2026-04-24 15:47:05 +02:00
committed by GitHub
2 changed files with 13 additions and 22 deletions
@@ -38,12 +38,16 @@ via a KOReader contributor mapping spine items to DocFragment numbers.
Implemented in `ProgressMapper::toKOReader`.
1. Compute overall `percentage` from chapter/page.
2. If a paragraph index is available from the section cache LUT (`CrossPointPosition::hasParagraphIndex`),
generate an XPath directly: `/body/DocFragment[spineIndex + 1]/body/p[paragraphIndex]`.
3. Otherwise, attempt byte-offset estimation via `ChapterXPathIndexer::findXPathForProgress`.
4. If XPath extraction fails, fallback to synthetic chapter path:
2. Generate XPath via byte-offset estimation (`ChapterXPathIndexer::findXPathForProgress`),
producing a `…/text()[K].M` anchor proportional to intra-spine progress.
3. If XPath extraction fails, fallback to synthetic chapter path:
- `/body/DocFragment[spineIndex + 1]/body`
The paragraph LUT (see below) is intentionally **not** used for upload: snapping to the
start of `p[N]` when the user is mid-paragraph causes pulled positions to land at the
start of the paragraph (and at the start of the chapter when an opening paragraph spans
many pages). The LUT remains in use for the reverse direction.
### KOReader -> CrossPoint
Implemented in `ProgressMapper::toCrossPoint`.
+5 -18
View File
@@ -57,24 +57,11 @@ KOReaderPosition ProgressMapper::toKOReader(const std::shared_ptr<Epub>& epub, c
// Calculate overall book progress (0.0-1.0)
result.percentage = epub->calculateProgress(pos.spineIndex, intraSpineProgress);
// Generate XPath for the current position.
// When we have a paragraph index from the section LUT, target that specific <p> element
// directly — this produces a structurally precise full-ancestry path even for chapters
// where paragraphs are nested inside divs/sections. Fall back to the progress-based
// scan (which works for any content) when no paragraph index is available.
if (pos.hasParagraphIndex && pos.paragraphIndex > 0) {
// When a seek hint is set, the LUT entry's paragraphIndex equals pos.paragraphIndex
// (both describe the same page). The byte offset now points at the body-child element
// that was current at the page break, so re-parsing from there will re-encounter that
// paragraph — seed startParagraphCount with paragraphIndex-1 to avoid double counting.
const uint16_t startCount =
pos.xhtmlSeekHint > 0 && pos.paragraphIndex > 0 ? static_cast<uint16_t>(pos.paragraphIndex - 1) : 0;
result.xpath = ChapterXPathIndexer::findXPathForParagraph(epub, pos.spineIndex, pos.paragraphIndex,
pos.xhtmlSeekHint, startCount);
}
if (result.xpath.empty()) {
result.xpath = ChapterXPathIndexer::findXPathForProgress(epub, pos.spineIndex, intraSpineProgress);
}
// Generate XPath for the current position via byte-offset scan. Targeting the
// paragraph LUT entry instead would snap to the start of the paragraph the user
// is inside, which causes pulled positions to land at the start of the chapter
// when an opening paragraph spans many pages.
result.xpath = ChapterXPathIndexer::findXPathForProgress(epub, pos.spineIndex, intraSpineProgress);
if (result.xpath.empty()) {
result.xpath = generateXPath(pos.spineIndex);
}