diff --git a/CHANGES.rst b/CHANGES.rst
index 79d6d3e..26f9179 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -1,3 +1,14 @@
+Release 4.0.0 (24/01/2023)
+==========================
+
+* Enforcing `subresource integrity`_ (SRI) checks breaks loading rendered
+ documentation from local filesystem (``file:///`` URIs).
+ SRI checks may now be configured by the boolean configuration option
+ ``jquery_use_sri``, which defaults to ``False``.
+ See `sphinx_rtd_theme#1420`_ for further details.
+
+.. _sphinx_rtd_theme#1420: https://github.com/readthedocs/sphinx_rtd_theme/issues/1420
+
Release 3.0.0 (03/11/2022)
==========================
diff --git a/README.rst b/README.rst
index 7e955b6..50e365a 100644
--- a/README.rst
+++ b/README.rst
@@ -19,3 +19,27 @@ To use it, add ``sphinxcontrib.jquery`` as a Sphinx extension:
"sphinxcontrib.jquery",
]
...
+
+
+Configuration
+-------------
+
+.. As this is a README, we restrict the directives we use to those which GitHub
+ renders correctly. This means that we cannot use ``versionadded``,
+ ``confval``, ``warning``, or other similar directives.
+ We use a reStructuredText definition list to emulate the ``confval``
+ rendering.
+ We use inline **bold** syntax as a poor-man's ``.. warning::`` directive.
+
+``jquery_use_sri``
+ A boolean value controlling whether to enable `subresource integrity`_ (SRI)
+ checks for JavaScript files that this extension loads.
+
+ The default is ``False``.
+
+ **Warning**: Enabling SRI checks may break documentation when loaded from
+ local filesystem (``file:///`` URIs).
+
+ *New in version 4.0.*
+
+ .. _subresource integrity: https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity
diff --git a/sphinxcontrib/jquery/__init__.py b/sphinxcontrib/jquery/__init__.py
index f38224f..3ac504a 100644
--- a/sphinxcontrib/jquery/__init__.py
+++ b/sphinxcontrib/jquery/__init__.py
@@ -3,8 +3,8 @@
import sphinx
-__version__ = "3.0.0"
-version_info = (3, 0, 0)
+__version__ = "4.0.0"
+version_info = (4, 0, 0)
_ROOT_DIR = path.abspath(path.dirname(__file__))
_FILES = (
@@ -19,18 +19,33 @@
)
-def setup(app):
+def add_js_files(app, config):
jquery_installed = getattr(app, "_sphinxcontrib_jquery_installed", False)
+
if sphinx.version_info[:2] >= (6, 0) and not jquery_installed:
makedirs(path.join(app.outdir, '_static'), exist_ok=True)
for (filename, integrity) in _FILES:
- app.add_js_file(filename, integrity=integrity, priority=100)
+ # The default is not to enable subresource integrity checks, as it
+ # does not trigger the hash check but instead blocks the request
+ # when viewing documentation locally through the ``file://`` URIs.
+ if config.jquery_use_sri:
+ app.add_js_file(filename, priority=100, integrity=integrity)
+ else:
+ app.add_js_file(filename, priority=100)
shutil.copyfile(
path.join(_ROOT_DIR, filename),
path.join(app.outdir, '_static', filename)
)
app._sphinxcontrib_jquery_installed = True
+
+def setup(app):
+ # Configuration value for enabling `subresource integrity`__ (SRI) checks
+ # __ https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity
+ app.add_config_value("jquery_use_sri", default=False, rebuild="html", types=(bool,))
+
+ app.connect('config-inited', add_js_files)
+
return {
"parallel_read_safe": True,
"parallel_write_safe": True,
diff --git a/tests/test_jquery_installed.py b/tests/test_jquery_installed.py
index 92e9fdc..38e05e6 100644
--- a/tests/test_jquery_installed.py
+++ b/tests/test_jquery_installed.py
@@ -31,8 +31,8 @@ def inner(**kwargs):
@pytest.mark.skipif(sphinx.version_info[:2] < (6, 0),
reason="Requires Sphinx 6.0 or greater")
-def test_jquery_installed_sphinx_ge_60(blank_app):
- out_dir = blank_app(confoverrides={"extensions": ["sphinxcontrib.jquery"]})
+def test_jquery_installed_sphinx_ge_60_use_sri(blank_app):
+ out_dir = blank_app(confoverrides={"extensions": ["sphinxcontrib.jquery"], "jquery_use_sri": True})
text = out_dir.joinpath("index.html").read_text(encoding="utf-8")
assert ('') in text
+ assert ('') in text
+
+ static_dir = out_dir / '_static'
+ assert static_dir.joinpath('jquery.js').is_file()
+ assert static_dir.joinpath('_sphinx_javascript_frameworks_compat.js').is_file()
+
+
@pytest.mark.skipif(sphinx.version_info[:2] >= (6, 0),
reason="Requires Sphinx older than 6.0")
def test_jquery_installed_sphinx_lt_60(blank_app):