Skip to content

Commit

Permalink
🔧 MAINTAIN: Add feature flag for lazy loading (#35)
Browse files Browse the repository at this point in the history
  • Loading branch information
choldgraf authored Aug 25, 2021
1 parent e18d1bf commit ae9d35d
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 13 deletions.
18 changes: 15 additions & 3 deletions docs/configure.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ By default, Thebe encourages users to use the `thebe-button` directive to
insert a thebe button into their documentation. However, you can add your own
buttons wherever you wish. Simply ensure that an HTML element has this attribute:

```
```js
onclick="initThebe()"
```

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

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

## Only load JS on certain pages

By default, `sphinx-thebe` will load the JS/CSS from `thebe` on all of your documentation's pages.
Alternatively, you may load `thebe` only on pages that use the `thebe-button` directive.
To do so, use the following configuration:

```python
thebe_config = {
"always_load": False
}
```

## Configuration reference

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

```
```python
thebe_config = {
"always_load": bool (default True)
"repository_url": "<your-repo-url>",
"repository_branch": "<your-repo-branch>",
"selector": "<selector-for-code-cells>",
Expand Down
36 changes: 26 additions & 10 deletions sphinx_thebe/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ def st_static_path(app):
def init_thebe_default_config(app, env, docnames):
thebe_config = app.config.thebe_config
defaults = {
"always_load": True,
"selector": ".thebe",
"selector_input": "pre",
"selector_output": ".output",
Expand All @@ -32,28 +33,41 @@ def init_thebe_default_config(app, env, docnames):
thebe_config[key] = val


def _check_if_load_thebe(doctree, config_thebe):
def _bool(b):
if isinstance(b, bool):
return b
else:
return b in ["true", "True"]


def _do_load_thebe(doctree, config_thebe):
"""Decide whether to load thebe based on the page's context."""
# Only load `thebe` if there is a thebe button somewhere
if not doctree or (not doctree.traverse(ThebeButtonNode)):
return
if not doctree:
return False

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

return True
# Only load `thebe` if there is a thebe button somewhere
if doctree.traverse(ThebeButtonNode) or _bool(config_thebe.get("always_load")):
return True
else:
return False


def init_thebe_core(app, pagename, templatename, context, doctree):
"""Load thebe assets if there's a thebe button on this page."""
config_thebe = app.config["thebe_config"]
if not _check_if_load_thebe(doctree, config_thebe):
if not _do_load_thebe(doctree, config_thebe):
return

# Add core libraries
opts = {"async": "async"}
app.add_js_file(filename=f"https://unpkg.com/thebe@{THEBE_VERSION}/lib/index.js", **opts)
app.add_js_file(
filename=f"https://unpkg.com/thebe@{THEBE_VERSION}/lib/index.js", **opts
)

# Add configuration variables
thebe_config = f"""
Expand All @@ -68,7 +82,7 @@ def init_thebe_core(app, pagename, templatename, context, doctree):
def update_thebe_context(app, doctree, docname):
"""Add thebe config nodes to this doctree."""
config_thebe = app.config["thebe_config"]
if not _check_if_load_thebe(doctree, config_thebe):
if not _do_load_thebe(doctree, config_thebe):
return

# Thebe configuration
Expand Down Expand Up @@ -208,11 +222,13 @@ def setup(app):

# Update the doctree with thebe-specific information if needed
app.connect("doctree-resolved", update_thebe_context)
# Load the JS/CSS assets for thebe if needed

# Load the JS/CSS assets for thebe if needed
app.connect("html-page-context", init_thebe_core)

# configuration for this tool
app.add_config_value("thebe_config", {}, "html")

# override=True in case Jupyter Sphinx has already been loaded
app.add_directive("thebe-button", ThebeButton, override=True)

Expand Down
24 changes: 24 additions & 0 deletions tests/test_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class SphinxBuild:
path_html = path_build.joinpath("html")
path_pg_index = path_html.joinpath("index.html")
path_pg_config = path_html.joinpath("configure.html")
path_pg_chglg = path_html.joinpath("changelog.html")
cmd_base = ["sphinx-build", ".", "_build/html", "-a", "-W"]

def copy(self, path=None):
Expand Down Expand Up @@ -68,3 +69,26 @@ def test_sphinx_thebe(file_regression, sphinx_build):
launch_buttons = soup_conf.select(".thebe-launch-button")
lb_text = "\n\n".join([ii.prettify() for ii in launch_buttons])
file_regression.check(lb_text, basename="launch_buttons", extension=".html")

# Changelog has no thebe button directive, but should have the JS anyway
soup_chlg = BeautifulSoup(
Path(sphinx_build.path_pg_chglg).read_text(), "html.parser"
)
assert "https://unpkg.com/thebe" in soup_chlg.prettify()


def test_always_load(file_regression, sphinx_build):
"""Test building with thebe."""
sphinx_build.copy()

# Basic build with defaults
sphinx_build.build(cmd=["-D", "thebe_config.always_load=false"])

# Thebe should be loaded on a page *with* the directive and not on pages w/o it
soup_ix = BeautifulSoup(Path(sphinx_build.path_pg_index).read_text(), "html.parser")
assert "https://unpkg.com/thebe" in soup_ix.prettify()
# Changelog has no thebe button directive, so shouldn't have JS
soup_chlg = BeautifulSoup(
Path(sphinx_build.path_pg_chglg).read_text(), "html.parser"
)
assert "https://unpkg.com/thebe" not in soup_chlg.prettify()

0 comments on commit ae9d35d

Please sign in to comment.