Skip to content

Commit ae9d35d

Browse files
authored
🔧 MAINTAIN: Add feature flag for lazy loading (#35)
1 parent e18d1bf commit ae9d35d

3 files changed

Lines changed: 65 additions & 13 deletions

File tree

docs/configure.md

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ By default, Thebe encourages users to use the `thebe-button` directive to
173173
insert a thebe button into their documentation. However, you can add your own
174174
buttons wherever you wish. Simply ensure that an HTML element has this attribute:
175175

176-
```
176+
```js
177177
onclick="initThebe()"
178178
```
179179

@@ -193,7 +193,7 @@ directive:
193193
You can customize `sphinx-thebe` to use the codemirror theme of your choice.
194194
To do so, use the following configuration:
195195

196-
```
196+
```python
197197
thebe_config = {
198198
"codemirror-theme": "<cm-theme>"
199199
}
@@ -202,15 +202,27 @@ thebe_config = {
202202
See [the CodeMirror theme demo](https://codemirror.net/demo/theme.html) for a list
203203
of themes that you can use, and what they look like.
204204

205+
## Only load JS on certain pages
206+
207+
By default, `sphinx-thebe` will load the JS/CSS from `thebe` on all of your documentation's pages.
208+
Alternatively, you may load `thebe` only on pages that use the `thebe-button` directive.
209+
To do so, use the following configuration:
210+
211+
```python
212+
thebe_config = {
213+
"always_load": False
214+
}
215+
```
205216

206217
## Configuration reference
207218

208219
Here's a reference of all of the configuration values avialable to `sphinx-thebe`.
209220
Many of these eventually make their was into the `thebe` configuration. You can
210221
find a [reference for `thebe` configuration here](https://thebelab.readthedocs.io/en/latest/config_reference.html).
211222

212-
```
223+
```python
213224
thebe_config = {
225+
"always_load": bool (default True)
214226
"repository_url": "<your-repo-url>",
215227
"repository_branch": "<your-repo-branch>",
216228
"selector": "<selector-for-code-cells>",

sphinx_thebe/__init__.py

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ def st_static_path(app):
2323
def init_thebe_default_config(app, env, docnames):
2424
thebe_config = app.config.thebe_config
2525
defaults = {
26+
"always_load": True,
2627
"selector": ".thebe",
2728
"selector_input": "pre",
2829
"selector_output": ".output",
@@ -32,28 +33,41 @@ def init_thebe_default_config(app, env, docnames):
3233
thebe_config[key] = val
3334

3435

35-
def _check_if_load_thebe(doctree, config_thebe):
36+
def _bool(b):
37+
if isinstance(b, bool):
38+
return b
39+
else:
40+
return b in ["true", "True"]
41+
42+
43+
def _do_load_thebe(doctree, config_thebe):
3644
"""Decide whether to load thebe based on the page's context."""
37-
# Only load `thebe` if there is a thebe button somewhere
38-
if not doctree or (not doctree.traverse(ThebeButtonNode)):
39-
return
45+
if not doctree:
46+
return False
4047

48+
# If we aren't properly configured
4149
if not config_thebe:
4250
logger.warning("Didn't find `thebe_config` in conf.py, add to use thebe")
43-
return
51+
return False
4452

45-
return True
53+
# Only load `thebe` if there is a thebe button somewhere
54+
if doctree.traverse(ThebeButtonNode) or _bool(config_thebe.get("always_load")):
55+
return True
56+
else:
57+
return False
4658

4759

4860
def init_thebe_core(app, pagename, templatename, context, doctree):
4961
"""Load thebe assets if there's a thebe button on this page."""
5062
config_thebe = app.config["thebe_config"]
51-
if not _check_if_load_thebe(doctree, config_thebe):
63+
if not _do_load_thebe(doctree, config_thebe):
5264
return
5365

5466
# Add core libraries
5567
opts = {"async": "async"}
56-
app.add_js_file(filename=f"https://unpkg.com/thebe@{THEBE_VERSION}/lib/index.js", **opts)
68+
app.add_js_file(
69+
filename=f"https://unpkg.com/thebe@{THEBE_VERSION}/lib/index.js", **opts
70+
)
5771

5872
# Add configuration variables
5973
thebe_config = f"""
@@ -68,7 +82,7 @@ def init_thebe_core(app, pagename, templatename, context, doctree):
6882
def update_thebe_context(app, doctree, docname):
6983
"""Add thebe config nodes to this doctree."""
7084
config_thebe = app.config["thebe_config"]
71-
if not _check_if_load_thebe(doctree, config_thebe):
85+
if not _do_load_thebe(doctree, config_thebe):
7286
return
7387

7488
# Thebe configuration
@@ -208,11 +222,13 @@ def setup(app):
208222

209223
# Update the doctree with thebe-specific information if needed
210224
app.connect("doctree-resolved", update_thebe_context)
211-
# Load the JS/CSS assets for thebe if needed
225+
226+
# Load the JS/CSS assets for thebe if needed
212227
app.connect("html-page-context", init_thebe_core)
213228

214229
# configuration for this tool
215230
app.add_config_value("thebe_config", {}, "html")
231+
216232
# override=True in case Jupyter Sphinx has already been loaded
217233
app.add_directive("thebe-button", ThebeButton, override=True)
218234

tests/test_build.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class SphinxBuild:
1818
path_html = path_build.joinpath("html")
1919
path_pg_index = path_html.joinpath("index.html")
2020
path_pg_config = path_html.joinpath("configure.html")
21+
path_pg_chglg = path_html.joinpath("changelog.html")
2122
cmd_base = ["sphinx-build", ".", "_build/html", "-a", "-W"]
2223

2324
def copy(self, path=None):
@@ -68,3 +69,26 @@ def test_sphinx_thebe(file_regression, sphinx_build):
6869
launch_buttons = soup_conf.select(".thebe-launch-button")
6970
lb_text = "\n\n".join([ii.prettify() for ii in launch_buttons])
7071
file_regression.check(lb_text, basename="launch_buttons", extension=".html")
72+
73+
# Changelog has no thebe button directive, but should have the JS anyway
74+
soup_chlg = BeautifulSoup(
75+
Path(sphinx_build.path_pg_chglg).read_text(), "html.parser"
76+
)
77+
assert "https://unpkg.com/thebe" in soup_chlg.prettify()
78+
79+
80+
def test_always_load(file_regression, sphinx_build):
81+
"""Test building with thebe."""
82+
sphinx_build.copy()
83+
84+
# Basic build with defaults
85+
sphinx_build.build(cmd=["-D", "thebe_config.always_load=false"])
86+
87+
# Thebe should be loaded on a page *with* the directive and not on pages w/o it
88+
soup_ix = BeautifulSoup(Path(sphinx_build.path_pg_index).read_text(), "html.parser")
89+
assert "https://unpkg.com/thebe" in soup_ix.prettify()
90+
# Changelog has no thebe button directive, so shouldn't have JS
91+
soup_chlg = BeautifulSoup(
92+
Path(sphinx_build.path_pg_chglg).read_text(), "html.parser"
93+
)
94+
assert "https://unpkg.com/thebe" not in soup_chlg.prettify()

0 commit comments

Comments
 (0)