Content server: Book details view: Make calibre://show-book and calibre://view-book URLs in the comments work

This commit is contained in:
Kovid Goyal 2025-01-09 14:56:09 +05:30
parent 5cca273ddd
commit 6d3e245ea8
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 52 additions and 6 deletions

View File

@ -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'<h3>{name}</h3>'
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)
# }}}

View File

@ -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}