mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Remove overlapping highlights when applying a new one
This commit is contained in:
parent
5af73fee86
commit
37a60e366a
@ -60,6 +60,11 @@ def unwrap(node):
|
||||
p.normalize()
|
||||
|
||||
|
||||
def unwrap_crw(crw):
|
||||
for node in document.querySelectorAll(f'span[data-calibre-range-wrapper="{crw}"]'):
|
||||
unwrap(node)
|
||||
|
||||
|
||||
def create_wrapper_function(wrapper_elem, r):
|
||||
start_node = r.startContainer
|
||||
end_node = r.endContainer
|
||||
@ -109,3 +114,33 @@ def wrap_text_in_range(style, r):
|
||||
def reset_highlight_counter():
|
||||
nonlocal wrapper_counter
|
||||
wrapper_counter = 0
|
||||
|
||||
|
||||
def is_text_node(node):
|
||||
return node.nodeType is Node.TEXT_NODE or node.nodeType is Node.CDATA_SECTION_NODE
|
||||
|
||||
|
||||
def range_wrappers_intersecting_selection(sel):
|
||||
ans = {}
|
||||
sel = sel or window.getSelection()
|
||||
if not sel:
|
||||
return ans
|
||||
r = sel.getRangeAt(0)
|
||||
if not r:
|
||||
return ans
|
||||
walker = document.createTreeWalker(r.commonAncestorContainer, NodeFilter.SHOW_ALL, None, False)
|
||||
in_selection = False
|
||||
while True:
|
||||
node = walker.nextNode()
|
||||
if not node:
|
||||
break
|
||||
if not in_selection and node is not r.startContainer:
|
||||
continue
|
||||
in_selection = True
|
||||
if node.nodeType is Node.ELEMENT_NODE and node.dataset.calibreRangeWrapper:
|
||||
ans[node.dataset.calibreRangeWrapper] = True
|
||||
elif is_text_node(node) and node.parentNode.dataset.calibreRangeWrapper:
|
||||
ans[node.parentNode.dataset.calibreRangeWrapper] = True
|
||||
if node is r.endContainer:
|
||||
break
|
||||
return Object.keys(ans)
|
||||
|
@ -11,7 +11,10 @@ from select import (
|
||||
|
||||
from fs_images import fix_fullscreen_svg_images
|
||||
from iframe_comm import IframeClient
|
||||
from range_utils import reset_highlight_counter, wrap_text_in_range
|
||||
from range_utils import (
|
||||
range_wrappers_intersecting_selection, reset_highlight_counter, unwrap_crw,
|
||||
wrap_text_in_range
|
||||
)
|
||||
from read_book.cfi import cfi_for_selection, scroll_to as scroll_to_cfi
|
||||
from read_book.extract import get_elements
|
||||
from read_book.find import reset_find_caches, select_search_result
|
||||
@ -646,12 +649,28 @@ class IframeBoss:
|
||||
elif data.type is 'set-highlight-style':
|
||||
set_selection_style(data.style)
|
||||
elif data.type is 'apply-highlight':
|
||||
sel = window.getSelection()
|
||||
text = ''
|
||||
if sel:
|
||||
text = sel.toString()
|
||||
bounds = cfi_for_selection()
|
||||
intersecting_wrappers = range_wrappers_intersecting_selection()
|
||||
annot_id = wrap_text_in_range(data.style)
|
||||
removed_highlights = {}
|
||||
if annot_id is not None:
|
||||
window.getSelection().removeAllRanges()
|
||||
sel.removeAllRanges()
|
||||
self.annot_id_uuid_map[annot_id] = data.uuid
|
||||
self.send_message('annotations', type='highlight-applied', uuid=data.uuid, ok=annot_id is not None, bounds=bounds)
|
||||
for crw in intersecting_wrappers:
|
||||
unwrap_crw(crw)
|
||||
removed_highlights[self.annot_id_uuid_map[crw]] = True
|
||||
self.send_message(
|
||||
'annotations',
|
||||
type='highlight-applied',
|
||||
uuid=data.uuid, ok=annot_id is not None,
|
||||
bounds=bounds,
|
||||
removed_highlights=Object.keys(removed_highlights),
|
||||
highlighted_text=text,
|
||||
)
|
||||
reset_find_caches()
|
||||
else:
|
||||
console.log('Ignoring annotations message to iframe with unknown type: ' + data.type)
|
||||
|
Loading…
x
Reference in New Issue
Block a user