diff --git a/src/calibre/utils/rapydscript.py b/src/calibre/utils/rapydscript.py
index a5df1cf63c..6e469151f3 100644
--- a/src/calibre/utils/rapydscript.py
+++ b/src/calibre/utils/rapydscript.py
@@ -17,7 +17,9 @@ from io import BytesIO
from threading import Thread, local
from calibre import force_unicode
-from calibre.constants import __appname__, __version__, cache_dir
+from calibre.constants import (
+ FAKE_HOST, FAKE_PROTOCOL, __appname__, __version__, cache_dir
+)
from calibre.utils.filenames import atomic_rename
from calibre.utils.terminal import ANSIStream
from duktape import Context, JSError, to_python
@@ -226,7 +228,10 @@ def compile_viewer():
rapydscript_dir = os.path.join(base, 'src', 'pyj')
fname = os.path.join(rapydscript_dir, 'viewer-main.pyj')
with lopen(fname, 'rb') as f:
- js = compile_fast(f.read(), fname, js_version=6).replace('__SPECIAL_TITLE__', special_title, 1)
+ js = compile_fast(f.read(), fname, js_version=6).replace(
+ '__SPECIAL_TITLE__', special_title, 1).replace(
+ '__FAKE_PROTOCOL__', FAKE_PROTOCOL, 1).replace(
+ '__FAKE_HOST__', FAKE_HOST, 1)
base = os.path.join(base, 'resources')
atomic_write(base, 'viewer.js', js)
diff --git a/src/pyj/iframe_comm.pyj b/src/pyj/iframe_comm.pyj
index fb6b341760..39fcfa456d 100644
--- a/src/pyj/iframe_comm.pyj
+++ b/src/pyj/iframe_comm.pyj
@@ -81,13 +81,16 @@ class IframeWrapper:
def create_srcdoc(self):
r = /__([A-Z][A-Z_0-9]*[A-Z0-9])__/g
- data = {
- 'BS': self.bootstrap_text,
- 'SCRIPT': iframe_js(),
- 'FONT': get_font_family(),
- 'ENTRY_POINT': self.entry_point,
- }
- self.iframe.srcdoc = LOADING_DOC.replace(r, def(match, field): return data[field];)
+ if self.entry_point:
+ data = {
+ 'BS': self.bootstrap_text,
+ 'SCRIPT': iframe_js(),
+ 'FONT': get_font_family(),
+ 'ENTRY_POINT': self.entry_point,
+ }
+ self.iframe.srcdoc = LOADING_DOC.replace(r, def(match, field): return data[field];)
+ else:
+ self.iframe.srcdoc = '
\xa0
'
self.srcdoc_created = True
def init(self):
diff --git a/src/pyj/read_book/globals.pyj b/src/pyj/read_book/globals.pyj
index e2dfcba5f1..2a59096a72 100644
--- a/src/pyj/read_book/globals.pyj
+++ b/src/pyj/read_book/globals.pyj
@@ -60,3 +60,16 @@ register_callback(def():
scheme = default_color_schemes[key]
scheme.name = gt(scheme.name)
)
+
+runtime = {
+ 'is_standalone_viewer': False
+}
+
+
+ui_operations = {
+ 'get_file': None,
+ 'get_mathjax_files': None,
+ 'update_url_state': None,
+ 'update_last_read_time': None,
+ 'show_error': None,
+}
diff --git a/src/pyj/read_book/resources.pyj b/src/pyj/read_book/resources.pyj
index 6c9e4868e0..a5f0d5cee0 100644
--- a/src/pyj/read_book/resources.pyj
+++ b/src/pyj/read_book/resources.pyj
@@ -6,6 +6,7 @@ from elementmaker import E
from encodings import base64decode, utf8_decode
from dom import clear
+from read_book.globals import ui_operations
JSON_XHTML_MIMETYPE = 'application/calibre+xhtml+json'
@@ -19,7 +20,7 @@ def decode_url(x):
def create_link_pat(book):
return RegExp(book.manifest.link_uid + r'\|([^|]+)\|', 'g')
-def load_resources(db, book, root_name, previous_resources, proceed):
+def load_resources(book, root_name, previous_resources, proceed):
ans = Object.create(None)
pending_resources = v'[root_name]'
link_pat = create_link_pat(book)
@@ -29,7 +30,7 @@ def load_resources(db, book, root_name, previous_resources, proceed):
for k in previous_resources:
v'delete previous_resources[k]'
if book.manifest.files[root_name].has_maths:
- return load_mathjax(db, book, ans, proceed)
+ return load_mathjax(book, ans, proceed)
return proceed(ans)
name = pending_resources.shift()
if ans[name]:
@@ -39,7 +40,7 @@ def load_resources(db, book, root_name, previous_resources, proceed):
if jstype(data[0]) is 'string':
find_virtualized_resources(data[0])
return setTimeout(do_one, 0)
- db.get_file(book, name, got_one)
+ ui_operations.get_file(book, name, got_one)
def got_one(data, name, mimetype):
if False and name is book.manifest.title_page_name:
@@ -68,9 +69,9 @@ def load_resources(db, book, root_name, previous_resources, proceed):
mathjax_data = None
-def load_mathjax(db, book, resource_data, proceed):
+def load_mathjax(book, resource_data, proceed):
if mathjax_data is None:
- db.get_mathjax_files(def(data):
+ ui_operations.get_mathjax_files(def(data):
nonlocal mathjax_data
mathjax_data = data
resource_data['..mathjax-files..'] = data
diff --git a/src/pyj/read_book/search.pyj b/src/pyj/read_book/search.pyj
index a36957bd95..d02567e2ae 100644
--- a/src/pyj/read_book/search.pyj
+++ b/src/pyj/read_book/search.pyj
@@ -1,13 +1,15 @@
# vim:fileencoding=utf-8
# License: GPL v3 Copyright: 2017, Kovid Goyal
-from __python__ import hash_literals, bound_methods
+from __python__ import bound_methods, hash_literals
+from elementmaker import E
+from gettext import gettext as _
+
+from book_list.theme import get_color
from complete import create_search_bar
from dom import add_extra_css, build_rule, svgicon
from keycodes import get_key
-from elementmaker import E
-from gettext import gettext as _
-from book_list.theme import get_color
+from read_book.globals import ui_operations
from read_book.resources import text_from_serialized_html
CLASS_NAME = 'book-search-container'
@@ -84,7 +86,7 @@ def find_in_serialized_html(data, text):
return haystack.toLowerCase().indexOf(text) > -1
-def find_in_spine(names, book, db, text, proceed):
+def find_in_spine(names, book, text, proceed):
text = text.toLowerCase()
def got_one(data, name, mimetype):
@@ -96,7 +98,7 @@ def find_in_spine(names, book, db, text, proceed):
def do_one():
name = names.shift()
if name:
- db.get_file(book, name, got_one)
+ ui_operations.get_file(book, name, got_one)
else:
proceed(None)
diff --git a/src/pyj/read_book/ui.pyj b/src/pyj/read_book/ui.pyj
index ebdb8d4086..009b3e85eb 100644
--- a/src/pyj/read_book/ui.pyj
+++ b/src/pyj/read_book/ui.pyj
@@ -9,14 +9,13 @@ from gettext import gettext as _
from ajax import ajax
from book_list.constants import read_book_container_id
-from book_list.library_data import (
- current_library_id, library_data
-)
+from book_list.library_data import current_library_id, library_data
+from book_list.router import home, push_state, read_book_mode, update_window_title
from book_list.ui import show_panel
-from book_list.router import update_window_title, home
from dom import clear
from modals import create_simple_dialog_markup, error_dialog
from read_book.db import get_db
+from read_book.globals import ui_operations
from read_book.view import View
from utils import debounce, human_readable
from widgets import create_button
@@ -53,9 +52,14 @@ class ReadUI:
container.appendChild(E.div(
id=self.display_id, style='display:none',
))
- self.view = View(container.lastChild, self)
+ self.view = View(container.lastChild)
window.addEventListener('resize', debounce(self.on_resize.bind(self), 250))
self.db = get_db(self.db_initialized.bind(self), self.show_error.bind(self))
+ ui_operations.get_file = self.db.get_file
+ ui_operations.get_mathjax_files = self.db.get_mathjax_files
+ ui_operations.update_url_state = self.update_url_state.bind(self)
+ ui_operations.update_last_read_time = self.db.update_last_read_time
+ ui_operations.show_error = self.show_error.bind(self)
def on_resize(self):
self.view.on_resize()
@@ -448,3 +452,6 @@ class ReadUI:
self.view.goto_bookpos(current_query.bookpos)
else:
self.load_book(current_query.library_id, int(current_query.book_id), current_query.fmt, library_data.metadata[current_query.book_id])
+
+ def update_url_state(self, replace):
+ push_state(self.url_data, replace=replace, mode=read_book_mode)
diff --git a/src/pyj/read_book/view.pyj b/src/pyj/read_book/view.pyj
index a24e01a618..b37c2673ff 100644
--- a/src/pyj/read_book/view.pyj
+++ b/src/pyj/read_book/view.pyj
@@ -9,13 +9,14 @@ import read_book.iframe # noqa
from ajax import ajax_send
from book_list.book_details import CLASS_NAME as BD_CLASS_NAME, render_metadata
from book_list.globals import get_session_data
-from book_list.router import push_state, read_book_mode
from book_list.theme import get_color
from dom import add_extra_css, build_rule, clear, set_css, svgicon, unique_id
from iframe_comm import IframeWrapper
from modals import error_dialog, warning_dialog
from read_book.content_popup import ContentPopupOverlay
-from read_book.globals import current_book, set_current_spine_item
+from read_book.globals import (
+ current_book, runtime, set_current_spine_item, ui_operations
+)
from read_book.goto import get_next_section
from read_book.overlay import Overlay
from read_book.prefs.colors import resolve_color_scheme
@@ -115,8 +116,7 @@ def margin_elem(sd, which, id, onclick):
class View:
- def __init__(self, container, ui):
- self.ui = ui
+ def __init__(self, container):
self.timers = Timers()
self.loaded_resources = {}
self.current_progress_frac = self.current_file_progress_frac = 0
@@ -167,7 +167,8 @@ class View:
'print': self.on_print,
'human_scroll': self.on_human_scroll,
}
- self.iframe_wrapper = IframeWrapper(handlers, document.getElementById(iframe_id), 'read_book.iframe', _('Bootstrapping book reader...'))
+ entry_point = None if runtime.is_standalone_viewer else 'read_book.iframe'
+ self.iframe_wrapper = IframeWrapper(handlers, document.getElementById(iframe_id), entry_point, _('Bootstrapping book reader...'))
self.search_overlay = SearchOverlay(self)
self.content_popup_overlay = ContentPopupOverlay(self)
self.overlay = Overlay(self)
@@ -245,7 +246,7 @@ class View:
for items in item_groups:
for i in items:
names.push(spine[i])
- find_in_spine(names, self.book, self.ui.db, data.text, def(found_in):
+ find_in_spine(names, self.book, data.text, def(found_in):
if found_in:
self.show_name(found_in, initial_position={'type':'search', 'search_data':data, 'replace_history':True})
else:
@@ -322,7 +323,7 @@ class View:
self.show_spine_item_stage2(data)
def on_iframe_error(self, data):
- self.ui.show_error((data.title or _('There was an error processing the book')), data.msg, data.details)
+ ui_operations.show_error((data.title or _('There was an error processing the book')), data.msg, data.details)
def get_color_scheme(self, apply_to_margins):
ans = resolve_color_scheme()
@@ -376,7 +377,8 @@ class View:
self.content_popup_overlay.loaded_resources = {}
self.timers.start_book(book)
self.book = current_book.book = book
- self.ui.db.update_last_read_time(book)
+ if ui_operations.update_last_read_time:
+ ui_operations.update_last_read_time(book)
pos = {'replace_history':True}
unkey = username_key(get_interface_data().username)
name = book.manifest.spine[0]
@@ -431,7 +433,7 @@ class View:
def cb(resource_data):
self.loaded_resources = resource_data
done_callback(resource_data)
- load_resources(self.ui.db, self.book, name, self.loaded_resources, cb)
+ load_resources(self.book, name, self.loaded_resources, cb)
def goto_doc_boundary(self, start):
name = self.book.manifest.spine[0 if start else self.book.manifest.spine.length - 1]
@@ -495,13 +497,14 @@ class View:
# See https://bugs.chromium.org/p/chromium/issues/detail?id=404315
return
self.currently_showing.bookpos = data.cfi
- push_state(self.ui.url_data, replace=data.replace_history, mode=read_book_mode)
+ ui_operations.update_url_state(data.replace_history)
username = get_interface_data().username
unkey = username_key(username)
if not self.book.last_read_position:
self.book.last_read_position = {}
self.book.last_read_position[unkey] = data.cfi
- self.ui.db.update_last_read_time(self.book)
+ if ui_operations.update_last_read_time:
+ ui_operations.update_last_read_time(self.book)
lrd = {'device':get_device_uuid(), 'cfi':data.cfi, 'pos_frac':data.progress_frac}
self.current_progress_frac = data.progress_frac
self.current_file_progress_frac = data.file_progress_frac
diff --git a/src/pyj/viewer-main.pyj b/src/pyj/viewer-main.pyj
index 5d277a5e3a..df72d6fd8e 100644
--- a/src/pyj/viewer-main.pyj
+++ b/src/pyj/viewer-main.pyj
@@ -2,4 +2,17 @@
# License: GPL v3 Copyright: 2018, Kovid Goyal
from __python__ import bound_methods, hash_literals
-print('11111111111111', document.location.href)
+
+from elementmaker import E
+from read_book.globals import runtime
+
+def container_div(id):
+ return E.div(id=id, style='margin: 0; padding: 0; display: none')
+
+runtime.is_standalone_viewer = True
+if window is window.top:
+ # main
+ document.body.appendChild(E.iframe(srcdoc="hello"))
+else:
+ # iframe
+ pass
diff --git a/src/pyj/viewer/__init__.pyj b/src/pyj/viewer/__init__.pyj
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/src/pyj/viewer/constants.pyj b/src/pyj/viewer/constants.pyj
new file mode 100644
index 0000000000..aaabf5aefe
--- /dev/null
+++ b/src/pyj/viewer/constants.pyj
@@ -0,0 +1,7 @@
+# vim:fileencoding=utf-8
+# License: GPL v3 Copyright: 2018, Kovid Goyal
+from __python__ import bound_methods, hash_literals
+
+
+FAKE_PROTOCOL = '__FAKE_PROTOCOL__'
+FAKE_HOST = '__FAKE_HOST__'