feat(sync): add CFI converter for CREngine XPointer to standard epubcfi
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.
This commit is contained in: