mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
E-book viewer: Handle links to missing internal files with an error popup rather than becoming non-functional
This commit is contained in:
parent
c0f15325ed
commit
9d81359d8a
@ -13,7 +13,7 @@ from itertools import count
|
||||
|
||||
from lxml.etree import Comment
|
||||
|
||||
from calibre import detect_ncpus, force_unicode, prepare_string_for_xml
|
||||
from calibre import detect_ncpus, prepare_string_for_xml
|
||||
from calibre.customize.ui import plugin_for_input_format
|
||||
from calibre.ebooks.oeb.base import EPUB, OEB_DOCS, OEB_STYLES, OPF, SMIL, XHTML, XHTML_NS, XLINK, rewrite_links, urlunquote
|
||||
from calibre.ebooks.oeb.base import XPath as _XPath
|
||||
@ -33,7 +33,7 @@ from polyglot.binary import as_base64_unicode as encode_component
|
||||
from polyglot.binary import from_base64_bytes
|
||||
from polyglot.binary import from_base64_unicode as decode_component
|
||||
from polyglot.builtins import as_bytes
|
||||
from polyglot.urllib import quote, urlparse
|
||||
from polyglot.urllib import urlparse
|
||||
|
||||
try:
|
||||
from calibre_extensions.speedup import get_num_of_significant_chars
|
||||
@ -98,9 +98,7 @@ def create_link_replacer(container, link_uid, changed):
|
||||
frag = urlunquote(frag)
|
||||
url = resource_template.format(encode_url(name, frag))
|
||||
else:
|
||||
if isinstance(name, str):
|
||||
name = name.encode('utf-8')
|
||||
url = 'missing:' + force_unicode(quote(name), 'utf-8')
|
||||
url = 'missing:' + name
|
||||
changed.add(base)
|
||||
return url
|
||||
|
||||
@ -475,14 +473,18 @@ def transform_html(container, name, virtualize_resources, link_uid, link_to_map,
|
||||
href = link_replacer(name, href)
|
||||
elif attr in a.attrib:
|
||||
a.set(attr, 'javascript:void(0)')
|
||||
if href and href.startswith(link_uid):
|
||||
a.set(attr, 'javascript:void(0)')
|
||||
parts = href.split('|')
|
||||
if len(parts) > 1:
|
||||
parts = decode_url(parts[1])
|
||||
lname, lfrag = parts[0], parts[1]
|
||||
link_to_map.setdefault(lname, {}).setdefault(lfrag or '', set()).add(name)
|
||||
a.set('data-' + link_uid, json.dumps({'name':lname, 'frag':lfrag}, ensure_ascii=False))
|
||||
if href:
|
||||
if href.startswith(link_uid):
|
||||
a.set(attr, 'javascript:void(0)')
|
||||
parts = href.split('|')
|
||||
if len(parts) > 1:
|
||||
parts = decode_url(parts[1])
|
||||
lname, lfrag = parts[0], parts[1]
|
||||
link_to_map.setdefault(lname, {}).setdefault(lfrag or '', set()).add(name)
|
||||
a.set('data-' + link_uid, json.dumps({'name':lname, 'frag':lfrag}, ensure_ascii=False))
|
||||
elif href.startswith('missing:'):
|
||||
a.set(attr, 'javascript:void(0)')
|
||||
a.set('data-' + link_uid, json.dumps({'name':href[len('missing:'):], 'frag':'', 'missing': True}, ensure_ascii=False))
|
||||
|
||||
for a in link_xpath(root):
|
||||
handle_link(a)
|
||||
@ -519,8 +521,12 @@ def virtualize_html(container, name, link_uid, link_to_map, virtualized_names):
|
||||
link_to_map.setdefault(lname, {}).setdefault(lfrag or '', set()).add(name)
|
||||
a.set('data-' + link_uid, json.dumps({'name':lname, 'frag':lfrag}, ensure_ascii=False))
|
||||
elif href:
|
||||
a.set('target', '_blank')
|
||||
a.set('rel', 'noopener noreferrer')
|
||||
if href.startswith('missing:'):
|
||||
a.set(attr, 'javascript:void(0)')
|
||||
a.set('data-' + link_uid, json.dumps({'name':href[len('missing:'):], 'frag':'', 'missing': True}, ensure_ascii=False))
|
||||
else:
|
||||
a.set('target', '_blank')
|
||||
a.set('rel', 'noopener noreferrer')
|
||||
elif attr in a.attrib:
|
||||
a.set(attr, 'javascript:void(0)')
|
||||
|
||||
@ -978,7 +984,7 @@ def develop(max_workers=1, wait_for_input=True):
|
||||
with TemporaryDirectory() as tdir:
|
||||
render(
|
||||
path, tdir, serialize_metadata=True,
|
||||
extract_annotations=True, virtualize_resources=True, max_workers=max_workers
|
||||
extract_annotations=True, virtualize_resources=False, max_workers=max_workers
|
||||
)
|
||||
print('Extracted to:', tdir)
|
||||
if wait_for_input:
|
||||
|
@ -745,7 +745,10 @@ class IframeBoss:
|
||||
except:
|
||||
print('WARNING: Failed to parse link data {}, ignoring'.format(evt.currentTarget?.getAttribute?(self.link_attr)))
|
||||
return
|
||||
self.activate_link(data.name, data.frag, evt.currentTarget)
|
||||
if data.missing:
|
||||
self.send_message('link_to_missing_activated', name=data.name)
|
||||
else:
|
||||
self.activate_link(data.name, data.frag, evt.currentTarget)
|
||||
|
||||
def activate_link(self, name, frag, target_elem):
|
||||
if not name:
|
||||
|
@ -254,6 +254,7 @@ class View:
|
||||
'report_cfi': self.on_report_cfi,
|
||||
'request_size': self.on_request_size,
|
||||
'scroll_to_anchor': self.on_scroll_to_anchor,
|
||||
'link_to_missing_activated': self.on_link_to_missing_activated,
|
||||
'selectionchange': self.on_selection_change,
|
||||
'update_selection_position': self.update_selection_position,
|
||||
'columns_per_screen_changed': self.on_columns_per_screen_changed,
|
||||
@ -1122,6 +1123,9 @@ class View:
|
||||
frag = item.frag or ''
|
||||
self.show_name(name, initial_position={'type':'pagelist_ref', 'anchor':frag, 'replace_history':False})
|
||||
|
||||
def on_link_to_missing_activated(self, data):
|
||||
ui_operations.show_error(_('Invalid link'), _('This link points to the file {} which does not exist in the book').format(data.name))
|
||||
|
||||
def on_scroll_to_anchor(self, data):
|
||||
self.show_name(data.name, initial_position={'type':'anchor', 'anchor':data.frag, 'replace_history':False})
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user