mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Back to loading mathjax via blob urls
Fucking stupid Content Security Policy
This commit is contained in:
parent
8d27d68dff
commit
bd99a17186
58
src/calibre/gui2/viewer2/mathjax.py
Normal file
58
src/calibre/gui2/viewer2/mathjax.py
Normal file
@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env python2
|
||||
# vim:fileencoding=utf-8
|
||||
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
|
||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
|
||||
PATCHED_MATHJAX = '''
|
||||
|
||||
function postprocess_mathjax(link_uid) {
|
||||
Array.prototype.forEach.call(document.getElementsByTagName('a'), function(a) {
|
||||
var href = a.getAttribute('href');
|
||||
if (href && href.startsWith('#')) {
|
||||
a.setAttribute('href', 'javascript: void(0)')
|
||||
a.setAttribute('data-' + link_uid, JSON.stringify({'frag':href.slice(1)}))
|
||||
}
|
||||
});
|
||||
document.documentElement.dispatchEvent(new CustomEvent("calibre-mathjax-init-done"));
|
||||
}
|
||||
|
||||
function monkeypatch(mathjax_files) {
|
||||
var orig = window.MathJax.Ajax.fileURL.bind(window.MathJax.Ajax);
|
||||
|
||||
window.MathJax.Ajax.fileURL = function(mathjax_name) {
|
||||
var ans = orig(mathjax_name);
|
||||
var name = ans.replace(/^\\//g, '');
|
||||
if (name.startsWith('../fonts')) name = name.slice(3);
|
||||
ans = mathjax_files[name];
|
||||
if (!ans) ans = '';
|
||||
if (typeof ans !== 'string') {
|
||||
mathjax_files[name] = window.URL.createObjectURL(ans);
|
||||
ans = mathjax_files[name];
|
||||
}
|
||||
if (ans === name && !name.startsWith('blob:')) {
|
||||
if (ans.endsWith('.eot') || ans.endsWith('.otf')) return '';
|
||||
console.log('WARNING: Failed to resolve MathJax file: ' + mathjax_name);
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
window.MathJax.Ajax.fileRev = function(mathjax_name) { return ''; }
|
||||
}
|
||||
|
||||
function init_mathjax(link_uid, mathjax_files) {
|
||||
monkeypatch(mathjax_files);
|
||||
window.MathJax.Hub.Register.StartupHook("End", postprocess_mathjax.bind(this, link_uid))
|
||||
}
|
||||
|
||||
document.documentElement.addEventListener("calibre-mathjax-init", function(ev) {
|
||||
|
||||
window.MathJax = ev.detail.MathJax;
|
||||
window.MathJax.AuthorInit = init_mathjax.bind(this, ev.detail.link_uid, ev.detail.mathjax_files);
|
||||
|
||||
__SRC__
|
||||
});
|
||||
'''
|
||||
|
||||
|
||||
def monkeypatch_mathjax(src):
|
||||
return PATCHED_MATHJAX.replace('__SRC__', src, 1)
|
@ -62,7 +62,7 @@ class UrlSchemeHandler(QWebEngineUrlSchemeHandler):
|
||||
|
||||
def __init__(self, parent=None):
|
||||
QWebEngineUrlSchemeHandler.__init__(self, parent)
|
||||
self.mathjax_tdir = None
|
||||
self.mathjax_tdir = self.mathjax_manifest = None
|
||||
|
||||
def requestStarted(self, rq):
|
||||
if bytes(rq.requestMethod()) != b'GET':
|
||||
@ -99,16 +99,28 @@ class UrlSchemeHandler(QWebEngineUrlSchemeHandler):
|
||||
data = b'[' + manifest + b',' + metadata + b']'
|
||||
self.send_reply(rq, mime_type, data)
|
||||
elif name.startswith('mathjax/'):
|
||||
if self.mathjax_tdir is None:
|
||||
from calibre.srv.books import get_mathjax_manifest
|
||||
self.mathjax_tdir = PersistentTemporaryDirectory(prefix='v2mjx-')
|
||||
get_mathjax_manifest(self.mathjax_tdir)
|
||||
|
||||
from calibre.gui2.viewer2.mathjax import monkeypatch_mathjax
|
||||
if name == 'mathjax/manifest.json':
|
||||
if self.mathjax_tdir is None:
|
||||
import json
|
||||
from calibre.srv.books import get_mathjax_manifest
|
||||
self.mathjax_tdir = PersistentTemporaryDirectory(prefix='v2mjx-')
|
||||
self.mathjax_manifest = json.dumps(get_mathjax_manifest(self.mathjax_tdir)['files'])
|
||||
self.send_reply(rq, 'application/json', self.mathjax_manifest)
|
||||
return
|
||||
path = os.path.abspath(os.path.join(self.mathjax_tdir, name))
|
||||
if path.startswith(self.mathjax_tdir):
|
||||
mt = guess_type(name)
|
||||
with lopen(path, 'rb') as f:
|
||||
raw = f.read()
|
||||
try:
|
||||
with lopen(path, 'rb') as f:
|
||||
raw = f.read()
|
||||
except EnvironmentError as err:
|
||||
prints("Failed to get mathjax file: {} with error: {}".format(name, err))
|
||||
rq.fail(rq.RequestFailed)
|
||||
return
|
||||
if 'MathJax.js' in name:
|
||||
raw = monkeypatch_mathjax(raw.decode('utf-8')).encode('utf-8')
|
||||
|
||||
self.send_reply(rq, mt, raw)
|
||||
|
||||
def send_reply(self, rq, mime_type, data):
|
||||
|
@ -15,6 +15,7 @@ def get_url(mathjax_files, name):
|
||||
ans = mathjax_files[name] = window.URL.createObjectURL(ans)
|
||||
return ans
|
||||
|
||||
|
||||
def monkeypatch(mathjax_files):
|
||||
StyleString = window.MathJax.Ajax.StyleString.bind(window.MathJax.Ajax)
|
||||
|
||||
@ -72,7 +73,18 @@ def apply_mathjax(mathjax_files, link_uid, proceed):
|
||||
script = E.script(type='text/javascript')
|
||||
document.head.appendChild(script)
|
||||
if runtime.is_standalone_viewer:
|
||||
script.src = f'{runtime.FAKE_PROTOCOL}://{runtime.FAKE_HOST}/mathjax/MathJax.js'
|
||||
script.onload = def():
|
||||
ev = new CustomEvent("calibre-mathjax-init", {
|
||||
'detail': {
|
||||
'MathJax': m,
|
||||
'link_uid': link_uid,
|
||||
'mathjax_files': mathjax_files,
|
||||
}
|
||||
})
|
||||
document.documentElement.dispatchEvent(ev)
|
||||
document.documentElement.addEventListener("calibre-mathjax-init-done", def(ev):
|
||||
proceed()
|
||||
)
|
||||
else:
|
||||
m.AuthorInit = init_mathjax.bind(this, mathjax_files, link_uid, proceed)
|
||||
script.src = get_url(mathjax_files, 'MathJax.js')
|
||||
script.src = get_url(mathjax_files, 'MathJax.js')
|
||||
|
@ -168,7 +168,7 @@ class View:
|
||||
'human_scroll': self.on_human_scroll,
|
||||
}
|
||||
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.iframe_wrapper = IframeWrapper(handlers, document.getElementById(iframe_id), entry_point, _('Bootstrapping book reader...'), runtime.FAKE_PROTOCOL, runtime.FAKE_HOST)
|
||||
self.search_overlay = SearchOverlay(self)
|
||||
self.content_popup_overlay = ContentPopupOverlay(self)
|
||||
self.overlay = Overlay(self)
|
||||
|
@ -59,9 +59,57 @@ def get_file(book, name, proceed):
|
||||
xhr.responseType = 'blob'
|
||||
xhr.send()
|
||||
|
||||
def mathjax_file_received(name, proceed, end_type, xhr, ev):
|
||||
if end_type is 'abort':
|
||||
return
|
||||
if end_type is not 'load':
|
||||
show_error(_('Failed to load MathJax file'), _(
|
||||
'Could not load the file: {} with error: {}').format(name, xhr.error_html))
|
||||
return
|
||||
if not xhr.responseType or xhr.responseType is 'text':
|
||||
result = xhr.responseText
|
||||
else if xhr.responseType is 'blob' or xhr.responseType is 'json':
|
||||
result = xhr.response
|
||||
else:
|
||||
show_error(_('Failed to load MathJax file'), _(
|
||||
'Could not load the file: {} unknown response type: {}')
|
||||
.format(name, xhr.responseType))
|
||||
return
|
||||
if name is 'manifest.json':
|
||||
get_mathjax_files.manifest = result
|
||||
get_mathjax_files_stage2.files_to_get = list(Object.keys(result))
|
||||
get_mathjax_files_stage2.file_data = {}
|
||||
get_mathjax_files_stage2(proceed)
|
||||
return
|
||||
|
||||
get_mathjax_files_stage2.file_data[name] = result
|
||||
get_mathjax_files_stage2.files_to_get.remove(name)
|
||||
if not get_mathjax_files_stage2.files_to_get.length:
|
||||
proceed(get_mathjax_files_stage2.file_data)
|
||||
|
||||
def get_mathjax_manifest(proceed):
|
||||
xhr = ajax('mathjax/manifest.json', mathjax_file_received.bind(None, 'manifest.json', proceed), ok_code=0)
|
||||
xhr.responseType = 'json'
|
||||
xhr.send()
|
||||
|
||||
|
||||
def get_mathjax_files_stage2(proceed):
|
||||
if not get_mathjax_files_stage2.files_to_get.length:
|
||||
proceed(get_mathjax_files_stage2.file_data)
|
||||
return
|
||||
for filename in get_mathjax_files_stage2.files_to_get:
|
||||
xhr = ajax(f'mathjax/{filename}', mathjax_file_received.bind(None, filename, proceed), ok_code=0)
|
||||
xhr.responseType = 'blob'
|
||||
xhr.send()
|
||||
|
||||
|
||||
|
||||
def get_mathjax_files(proceed):
|
||||
proceed({})
|
||||
if not get_mathjax_files.manifest:
|
||||
get_mathjax_manifest(proceed)
|
||||
else:
|
||||
get_mathjax_files_stage2(proceed)
|
||||
|
||||
|
||||
|
||||
def update_url_state(replace):
|
||||
|
Loading…
x
Reference in New Issue
Block a user