Implements ConvertCREToStandard which converts CREngine XPointers (e.g. /body/DocFragment[6]/body/div/p[47]/text().2399) to standard epubcfi format (e.g. epubcfi(/6/12!/4/2[id]/4/1:7)). Key components: - indexChildNodes: faithful port of foliate-js's epubcfi.js algorithm for computing CFI-compatible child node indices including virtual positions, null positions between adjacent elements, and text chunks - preprocessXHTML: converts XHTML self-closing tags (e.g. <a id="x"/>) to open/close pairs so Go's HTML parser produces the same DOM as the browser's XHTML parser - buildCFI: walks up from a text node to body, computing CFI indices at each level using indexChildNodes - findTextInNode: regex-based whitespace-flexible text search for context_text fallback positioning - convertByPercentageOffset: estimates position via book-wide character counts when no context_text is available - ConvertCREToStandard: orchestrates text search → percentage fallback Supports CREngine XPointer format, CREngine fragment ID format (#_doc_fragment_N_anchor), and includes round-trip test coverage for 1984 and Crime and Punishment EPUBs.
38 lines
999 B
Go
38 lines
999 B
Go
package sync
|
|
|
|
import "testing"
|
|
|
|
func TestDebugHess(t *testing.T) {
|
|
epubPath := "/home/nymusicman/Code/bookhoard/William L Hess/Crushing the Great Serpent_ Did God (42)/Crushing the Great Serpent_ Did - William L Hess.epub"
|
|
c := NewCFIConverter(epubPath)
|
|
|
|
xp, err := ParseCREXPointer("/body/DocFragment[5]/body/div[3]/p[28]/text().500")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Logf("FragmentIndex: %d, CharOffset: %d", xp.FragmentIndex, xp.CharOffset)
|
|
|
|
doc, href, err := c.getContentDoc(xp.FragmentIndex)
|
|
if err != nil {
|
|
t.Fatalf("getContentDoc error: %v", err)
|
|
}
|
|
t.Logf("href: %s", href)
|
|
|
|
body := findBody(doc)
|
|
if body == nil {
|
|
t.Fatal("no body")
|
|
}
|
|
|
|
totalChars := countTextChars(body)
|
|
t.Logf("total chars in doc: %d", totalChars)
|
|
|
|
target, foundOffset := findNodeAtCharOffset(body, 500)
|
|
if target == nil {
|
|
t.Fatal("target is nil")
|
|
}
|
|
t.Logf("foundOffset: %d target: <%s>", foundOffset, target.Data)
|
|
|
|
cfi, err := buildCFI(5, target, 0)
|
|
t.Logf("cfi: %q err: %v", cfi, err)
|
|
}
|