Skip to content

Commit

Permalink
Transfer search parameters from page URL to jupyterlite (#108)
Browse files Browse the repository at this point in the history
* Add directive to transfert URL search parameters from the documentation page to jupyterlite

* Add documentation on the directive

* prettier

* Add an option to transfer all the parameters

* Allow True, False or ["param1", "param2"] as options

* Adds regex to checks parameters

* Update jupyterlite_sphinx/jupyterlite_sphinx.py

Co-authored-by: martinRenou <[email protected]>

---------

Co-authored-by: martinRenou <[email protected]>
  • Loading branch information
brichet and martinRenou authored Sep 11, 2023
1 parent 83663db commit d69ce1f
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 7 deletions.
5 changes: 5 additions & 0 deletions docs/directives/jupyterlite.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,8 @@ You can also pass a Notebook file to open automatically:
:prompt: Try JupyterLite!
:prompt_color: #00aa42
```

The directive `search_params` allows to transfer some search parameters from the documentation URL to the Jupyterlite URL.\
Jupyterlite will then be able to fetch these parameters from its own URL.\
For example `:search_params: ["param1", "param2"]` will transfer the parameters *param1* and *param2*.
Use a boolean value to transfer all or none of the parameters (default to none): `:search_params: True`
24 changes: 24 additions & 0 deletions jupyterlite_sphinx/jupyterlite_sphinx.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,27 @@ window.jupyterliteShowIframe = (tryItButtonId, iframeSrc) => {
tryItButton.classList.remove('jupyterlite_sphinx_try_it_button_unclicked');
tryItButton.classList.add('jupyterlite_sphinx_try_it_button_clicked');
}

window.jupyterliteConcatSearchParams = (iframeSrc, params) => {
const baseURL = window.location.origin;
const iframeUrl = new URL(iframeSrc, baseURL);

let pageParams = new URLSearchParams(window.location.search);

if (params === true) {
params = Array.from(pageParams.keys());
} else if (params === false) {
params = [];
} else if (!Array.isArray(params)) {
console.error('The search parameters are not an array');
}

params.forEach(param => {
value = pageParams.get(param);
if (value !== null) {
iframeUrl.searchParams.append(param, value);
}
});

return iframeUrl.toString().replace(baseURL, '');
}
52 changes: 45 additions & 7 deletions jupyterlite_sphinx/jupyterlite_sphinx.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import tempfile
from warnings import warn
import glob
import re

from pathlib import Path

Expand Down Expand Up @@ -51,6 +52,7 @@ def __init__(
height="100%",
prompt=False,
prompt_color=None,
search_params=[],
**attributes,
):
super().__init__(
Expand All @@ -60,10 +62,12 @@ def __init__(
height=height,
prompt=prompt,
prompt_color=prompt_color,
search_params=search_params,
)

def html(self):
iframe_src = self["iframe_src"]
search_params = self["search_params"]

if self["prompt"]:
prompt = (
Expand All @@ -76,13 +80,24 @@ def html(self):
placeholder_id = uuid4()
container_style = f'width: {self["width"]}; height: {self["height"]};'

return (
f"<div class=\"jupyterlite_sphinx_iframe_container\" style=\"{container_style}\" onclick=window.jupyterliteShowIframe('{placeholder_id}','{iframe_src}')>"
f' <div id={placeholder_id} class="jupyterlite_sphinx_try_it_button jupyterlite_sphinx_try_it_button_unclicked" style="background-color: {prompt_color};">'
f" {prompt}"
" </div>"
"</div>"
)
return f"""
<div
class=\"jupyterlite_sphinx_iframe_container\"
style=\"{container_style}\"
onclick=\"window.jupyterliteShowIframe(
'{placeholder_id}',
window.jupyterliteConcatSearchParams('{iframe_src}', {search_params})
)\"
>
<div
id={placeholder_id}
class=\"jupyterlite_sphinx_try_it_button jupyterlite_sphinx_try_it_button_unclicked\"
style=\"background-color: {prompt_color};\"
>
{prompt}
</div>
</div>
"""

return (
f'<iframe src="{iframe_src}"'
Expand Down Expand Up @@ -196,6 +211,7 @@ class RepliteDirective(SphinxDirective):
"theme": directives.unchanged,
"prompt": directives.unchanged,
"prompt_color": directives.unchanged,
"search_params": directives.unchanged,
}

def run(self):
Expand All @@ -205,6 +221,8 @@ def run(self):
prompt = self.options.pop("prompt", False)
prompt_color = self.options.pop("prompt_color", None)

search_params = search_params_parser(self.options.pop("search_params", ""))

prefix = os.path.relpath(
os.path.join(self.env.app.srcdir, JUPYTERLITE_DIR),
os.path.dirname(self.get_source_info()[0]),
Expand All @@ -218,6 +236,7 @@ def run(self):
prompt=prompt,
prompt_color=prompt_color,
content=self.content,
search_params=search_params,
lite_options=self.options,
)
]
Expand All @@ -233,6 +252,7 @@ class _LiteDirective(SphinxDirective):
"theme": directives.unchanged,
"prompt": directives.unchanged,
"prompt_color": directives.unchanged,
"search_params": directives.unchanged,
}

def run(self):
Expand All @@ -242,6 +262,8 @@ def run(self):
prompt = self.options.pop("prompt", False)
prompt_color = self.options.pop("prompt_color", None)

search_params = search_params_parser(self.options.pop("search_params", ""))

source_location = os.path.dirname(self.get_source_info()[0])

prefix = os.path.relpath(
Expand Down Expand Up @@ -276,6 +298,7 @@ def run(self):
height=height,
prompt=prompt,
prompt_color=prompt_color,
search_params=search_params,
lite_options=self.options,
)
]
Expand Down Expand Up @@ -476,3 +499,18 @@ def setup(app):
app.add_css_file("jupyterlite_sphinx.css")

app.add_js_file("jupyterlite_sphinx.js")


def search_params_parser(search_params: str) -> str:
pattern = re.compile(r"^\[(?:\s*[\"']{1}([^=\s\,&=\?\/]+)[\"']{1}\s*\,?)+\]$")
if not search_params:
return ""
if search_params in ["True", "False"]:
return search_params.lower()
elif pattern.match(search_params):
return search_params.replace('"', "'")
else:
raise ValueError(
'The search_params directive must be either True, False or ["param1", "param2"].\n'
'The params name shouldn\'t contain any of the following characters ["\\", "\'", """, ",", "?", "=", "&", " ").'
)

0 comments on commit d69ce1f

Please sign in to comment.