diff --git a/config.yaml b/config.yaml index d70988db..8084753d 100644 --- a/config.yaml +++ b/config.yaml @@ -40,3 +40,7 @@ redirect_to_exact: true # locales: # - en # - ru + +# Uncomment to inject extra scripts into replayed pages (place scripts under static/ or your alternate static_dir location) +# inject_scripts: +# - ruffle/ruffle.js diff --git a/docs/manual/configuring.rst b/docs/manual/configuring.rst index ff8bf32b..3680a19f 100644 --- a/docs/manual/configuring.rst +++ b/docs/manual/configuring.rst @@ -655,3 +655,30 @@ By default, SSL-Certificates of websites are not verified. To enable verificatio ``ca_cert_dir`` can optionally point to a directory containing the CA certificates that you trust. Most linux distributions provide CA certificates via a package called ``ca-certificates``. If omitted, the default system CA used by Python is used. + +Injecting Scripts +----------------- + +Extra JavaScript files can be injected into replayed pages. This can be useful for emulating removed browser features +or applying compatibility tweaks. + +For example, to emulate Flash Player using `Ruffle `_, create a subdirectory named ``static/ruffle`` +and unzip the `Ruffle self-hosted package `_ into it. Then add the following +configuration:: + + inject_scripts: + - ruffle/ruffle.js + +Note: Paths listed under ``inject_scripts`` are relative to the ``static_dir`` directory (default ``static/``). + +Injected scripts can also be configured per collection:: + + inject_scripts: + - all.js + - other.js + + collections: + mycoll: + inject_scripts: + - all.js # static/all.js + - _/mycoll/tweaks.js # collections/mycoll/static/tweaks.js \ No newline at end of file diff --git a/pywb/apps/rewriterapp.py b/pywb/apps/rewriterapp.py index cae36ed7..dab7d3f4 100644 --- a/pywb/apps/rewriterapp.py +++ b/pywb/apps/rewriterapp.py @@ -536,7 +536,8 @@ def render_content(self, wb_url, kwargs, environ): replay_mod=self.replay_mod, metadata=kwargs.get('metadata', {}), ui=kwargs.get('ui', {}), - config=self.config)) + config=self.config, + inject_scripts=self.get_inject_scripts(kwargs))) cookie_rewriter = None if self.cookie_tracker and cookie_key: @@ -926,6 +927,14 @@ def get_top_frame_params(self, wb_url, kwargs): 'ui': kwargs.get('ui', {}) } + def get_inject_scripts(self, kwargs): + coll = kwargs.get('coll') + coll_config = self.config.get('collections', {}).get(coll, {}) + # ignore special collections like live or all + if isinstance(coll_config, str): + coll_config = {} + return coll_config.get('inject_scripts', self.config.get('inject_scripts', [])) + def handle_custom_response(self, environ, wb_url, full_prefix, host_prefix, kwargs): if self.is_framed_replay(wb_url): extra_params = self.get_top_frame_params(wb_url, kwargs) @@ -936,6 +945,7 @@ def handle_custom_response(self, environ, wb_url, full_prefix, host_prefix, kwar self.frame_mod, self.replay_mod, self.client_side_replay, + self.get_inject_scripts(kwargs), coll=kwargs.get("coll"), extra_params=extra_params) diff --git a/pywb/rewrite/templateview.py b/pywb/rewrite/templateview.py index d21b3f29..4becd880 100644 --- a/pywb/rewrite/templateview.py +++ b/pywb/rewrite/templateview.py @@ -389,6 +389,7 @@ def get_top_frame(self, wb_url, frame_mod, replay_mod, client_side_replay, + inject_scripts, coll='', extra_params=None): """ @@ -429,7 +430,8 @@ def get_top_frame(self, wb_url, 'timestamp': timestamp, 'url': wb_url.get_url(), - 'sw_prefix': env.get('pywb.app_prefix', '') + 'sw_prefix': env.get('pywb.app_prefix', ''), + 'inject_scripts': inject_scripts, } if extra_params: diff --git a/pywb/static/loadWabac.js b/pywb/static/loadWabac.js index 94b2330f..c48f5fb4 100644 --- a/pywb/static/loadWabac.js +++ b/pywb/static/loadWabac.js @@ -1,6 +1,6 @@ class WabacReplay { - constructor(prefix, url, ts, staticPrefix, coll, swScopePrefix) { + constructor(prefix, url, ts, staticPrefix, coll, swScopePrefix, injectScripts) { this.prefix = prefix; this.url = url; this.ts = ts; @@ -8,6 +8,7 @@ class WabacReplay this.collName = coll; this.isRoot = coll === "$root"; this.swScope = swScopePrefix; + this.injectScripts = injectScripts; this.adblockUrl = undefined; this.queryParams = {"replayPrefix": ""}; @@ -54,6 +55,7 @@ class WabacReplay archiveMod: "ir_", adblockUrl: this.adblockUrl, noPostToGet: true, + injectScripts: this.injectScripts.map(src => "../" + src), }, }; diff --git a/pywb/templates/frame_insert.html b/pywb/templates/frame_insert.html index f0d2a393..3e75d9f3 100644 --- a/pywb/templates/frame_insert.html +++ b/pywb/templates/frame_insert.html @@ -55,7 +55,7 @@ if (navigator.serviceWorker) { {% if client_side_replay %} - window.cframe = new WabacReplay("{{ wb_prefix }}", "{{ url }}", "{{ timestamp }}", "{{ static_prefix }}", "{{ coll }}", "{{ sw_prefix }}"); + window.cframe = new WabacReplay("{{ wb_prefix }}", "{{ url }}", "{{ timestamp }}", "{{ static_prefix }}", "{{ coll }}", "{{ sw_prefix }}", {{ inject_scripts | tojson }}); window.cframe.init(); {% else %} navigator.serviceWorker.getRegistration("{{ sw_prefix }}").then(reg => { if (reg) reg.unregister() }); diff --git a/pywb/templates/head_insert.html b/pywb/templates/head_insert.html index 460b1c8e..11cf0f1e 100644 --- a/pywb/templates/head_insert.html +++ b/pywb/templates/head_insert.html @@ -54,6 +54,10 @@ {% endif %} +{% for script in inject_scripts %} + +{% endfor %} + {% if config.enable_flash_video_rewrite or config.transclusions_version == 1 %} diff --git a/tests/config_test.yaml b/tests/config_test.yaml index 5671069d..5ce2328e 100644 --- a/tests/config_test.yaml +++ b/tests/config_test.yaml @@ -41,3 +41,6 @@ enable_memento: true # enable new transclusion system transclusions_version: 2 + +inject_scripts: + - inject.js diff --git a/tests/test_integration.py b/tests/test_integration.py index e131ab3c..fd0c3ff9 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -118,6 +118,7 @@ def test_replay_content(self, fmod): assert '"20140127171238"' in resp.text, resp.text assert 'wombat.js' in resp.text assert 'transclusions.js' in resp.text + assert 'inject.js' in resp.text assert '_WBWombatInit' in resp.text, resp.text assert 'wbinfo.enable_auto_fetch = false;' in resp.text assert '/pywb/20140127171238{0}/http://www.iana.org/time-zones"'.format(fmod) in resp.text