refactor(sync): rewrite extractSurroundingText to use block-parent text collection
Instead of reading only from the single resolved text node (which produces a tiny window when the position is inside <em> or other inline elements), extractSurroundingText now: 1. Finds the block-level parent (e.g. <p>) of the resolved text node 2. Collects all text within that block, transparently crossing inline formatting elements via collectInlineText 3. Computes the global offset of the original text node within the concatenated block text 4. Extracts the [offset-window : offset+window] slice This gives a full context window regardless of inline element boundaries, enabling accurate text bridging between EPUB and KEPUB documents even when reading positions fall inside <em>, <strong>, <span class="koboSpan">, etc. Falls back to single-node extraction when no block parent is found (e.g. orphan text nodes in tests).
This commit is contained in:
@@ -208,23 +208,54 @@ func extractSurroundingText(textNode *html.Node, offset int, window int) string
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
text := textNode.Data
|
block := findBlockParent(textNode)
|
||||||
runes := []rune(text)
|
if block == nil {
|
||||||
|
text := textNode.Data
|
||||||
|
runes := []rune(text)
|
||||||
|
start := offset - window
|
||||||
|
if start < 0 {
|
||||||
|
start = 0
|
||||||
|
}
|
||||||
|
end := offset + window
|
||||||
|
if end > len(runes) {
|
||||||
|
end = len(runes)
|
||||||
|
}
|
||||||
|
if start >= end {
|
||||||
|
return normalizeWhitespace(text)
|
||||||
|
}
|
||||||
|
return normalizeWhitespace(string(runes[start:end]))
|
||||||
|
}
|
||||||
|
|
||||||
start := offset - window
|
segments := collectInlineText(block)
|
||||||
|
|
||||||
|
globalOffset := 0
|
||||||
|
for _, seg := range segments {
|
||||||
|
if seg.node == textNode {
|
||||||
|
globalOffset += offset
|
||||||
|
break
|
||||||
|
}
|
||||||
|
globalOffset += len(seg.runes)
|
||||||
|
}
|
||||||
|
|
||||||
|
var allRunes []rune
|
||||||
|
for _, seg := range segments {
|
||||||
|
allRunes = append(allRunes, seg.runes...)
|
||||||
|
}
|
||||||
|
|
||||||
|
start := globalOffset - window
|
||||||
if start < 0 {
|
if start < 0 {
|
||||||
start = 0
|
start = 0
|
||||||
}
|
}
|
||||||
end := offset + window
|
end := globalOffset + window
|
||||||
if end > len(runes) {
|
if end > len(allRunes) {
|
||||||
end = len(runes)
|
end = len(allRunes)
|
||||||
}
|
}
|
||||||
|
|
||||||
if start >= end {
|
if start >= end {
|
||||||
return normalizeWhitespace(text)
|
return normalizeWhitespace(string(allRunes))
|
||||||
}
|
}
|
||||||
|
|
||||||
return normalizeWhitespace(string(runes[start:end]))
|
return normalizeWhitespace(string(allRunes[start:end]))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *KEPUBCFIConverter) ComputeKEPUBPercentage(kepubCFI string) (float64, error) {
|
func (k *KEPUBCFIConverter) ComputeKEPUBPercentage(kepubCFI string) (float64, error) {
|
||||||
|
|||||||
Reference in New Issue
Block a user