fix(sync): countTextCharsBefore multiplied the document by node depth
countTextCharsBefore started its sibling walk at the target node itself and recursed after counting the current node's subtree, so every ancestor level re-counted everything accumulated so far — a node at depth 4 in the single-document 1984 epub reported 2.38M chars before it in a 589k-char document, producing healed percentages of 4.04 (>1) and a 500 on the reading_progress percentage check constraint. Every healed progress save from a fresh client failed; only exact-context matches (no heal) stored. The walk now starts at target.PrevSibling: strictly the characters before the node, per the contract all three callers already assume (healed book offsets, CRE convert percentage, kepub offsets). Found by the real-phone validation pass: the phone's first healed submission 500ed where the emulator's had matched context exactly and never taken the heal path.
This commit is contained in:
@@ -1321,9 +1321,16 @@ func countTextChars(n *html.Node) int {
|
|||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// countTextCharsBefore counts the text characters preceding target within
|
||||||
|
// its document: preceding siblings at each ancestor level, strictly
|
||||||
|
// EXCLUDING target's own subtree (callers add the in-node offset
|
||||||
|
// separately). Starting the walk at target itself — or recursing after
|
||||||
|
// counting the current node's subtree — would re-count the accumulated
|
||||||
|
// document once per ancestor level and multiply the result by the node's
|
||||||
|
// depth.
|
||||||
func countTextCharsBefore(target *html.Node) int {
|
func countTextCharsBefore(target *html.Node) int {
|
||||||
count := 0
|
count := 0
|
||||||
for c := target; c != nil; c = c.PrevSibling {
|
for c := target.PrevSibling; c != nil; c = c.PrevSibling {
|
||||||
count += countTextChars(c)
|
count += countTextChars(c)
|
||||||
}
|
}
|
||||||
if target.Parent != nil {
|
if target.Parent != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user