diff --git a/src/pyj/book_list/book_details.pyj b/src/pyj/book_list/book_details.pyj index adfa0aadf6..b681fe3b98 100644 --- a/src/pyj/book_list/book_details.pyj +++ b/src/pyj/book_list/book_details.pyj @@ -14,7 +14,7 @@ from book_list.library_data import ( current_virtual_library, download_url, library_data, load_status, set_book_metadata, download_data_file_url ) -from book_list.router import back, home, open_book, report_a_load_failure, show_note +from book_list.router import back, home, open_book, report_a_load_failure, show_note, open_book_url_in_library from book_list.theme import ( color_scheme, get_color, get_color_as_rgba, get_font_size ) @@ -155,6 +155,49 @@ def add_stars_to(stars, val, allow_half_stars): if window?: window.addEventListener('resize', debounce(adjust_all_iframes, 250)) + +def replace_calibre_links_to_books(html): + parser = v'new DOMParser()' + dom = parser.parseFromString(html, 'text/html') + changed = False + dom.body.querySelectorAll('a[href]').forEach(def (link): + nonlocal changed + if not link.href: + return + if link.href.startswith('calibre://'): + url = v'new URL(link.href, window.location.origin)' + if url.hostname is not 'show-book' and url.hostname is not 'view-book': + return + path = url.pathname + parts = str.split(path, '/') + lib, book_id = parts[1], parts[2] + try: + book_id = int(book_id) + except: + return + if lib.startswith('_hex_-'): + lib = lib[6:] + v'const uint8Array = new Uint8Array(lib.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));' + v'lib = new TextDecoder("utf-8").decode(uint8Array);' + if url.hostname is 'show-book': + new_href = query_as_href({'book_id': book_id + '', 'library_id': lib}, 'book_details') + else: + fmt = parts[3] + extra_query = {} + url.searchParams.forEach(def(val, key): + extra_query[key] = val + ) + new_href = open_book_url_in_library(lib, book_id, fmt, extra_query) + if url.search: + new_href + link.href = new_href + changed = True + ) + if not changed: + return html + return v'new XMLSerializer().serializeToString(dom);' + + def adjusting_sandboxed_html(html, extra_css): color = get_color_as_rgba('window-foreground') css = f'\n\n:root {{ color-scheme: {color_scheme()} }}\n\nhtml, body {{ overflow: hidden; color: rgba({color[0]}, {color[1]}, {color[2]}, {color[3]}) }}' @@ -445,7 +488,7 @@ def render_metadata(mi, table, book_id, iframe_css): # {{{ name = fm.name or field all_html += f'

{name}

' all_html += comment - iframe = adjusting_sandboxed_html(all_html, iframe_css) + iframe = adjusting_sandboxed_html(replace_calibre_links_to_books(all_html), iframe_css) iframe.style.marginTop = '2ex' table.parentNode.appendChild(iframe) # }}} diff --git a/src/pyj/book_list/router.pyj b/src/pyj/book_list/router.pyj index d976375f47..df2e2c5f4d 100644 --- a/src/pyj/book_list/router.pyj +++ b/src/pyj/book_list/router.pyj @@ -76,17 +76,20 @@ def open_book(book_id, fmt, library_id=None, replace=False, extra_query=None): push_state(q, replace=replace, mode=read_book_mode) -def open_book_url(book_id, fmt, extra_query): - lid = current_library_id() +def open_book_url_in_library(library_id, book_id, fmt, extra_query): ans = absolute_path('') q = {'book_id':book_id, 'fmt':fmt, 'mode': read_book_mode} - if lid: - q.library_id = lid + if library_id: + q.library_id = library_id if extra_query: Object.assign(q, extra_query) return ans + encode_query(q, '#') +def open_book_url(book_id, fmt, extra_query): + return open_book_url_in_library(current_library_id(), book_id, fmt, extra_query) + + def show_note(field, item_id, item_value, replace=False, library_id=None, close_action='back', panel='show_note'): lid = library_id or current_library_id() q = {'field': field, 'item':item_value + '', 'item_id': (item_id or '')+ '', 'panel': panel}