From e9e5edf9672a2396ef54810060b7446c390c30c0 Mon Sep 17 00:00:00 2001
From: Agriya Khetarpal <74401230+agriyakhetarpal@users.noreply.github.com>
Date: Wed, 7 May 2025 17:32:47 +0530
Subject: [PATCH 01/10] Add more REPL configuration options
---
jupyterlite_sphinx/jupyterlite_sphinx.py | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/jupyterlite_sphinx/jupyterlite_sphinx.py b/jupyterlite_sphinx/jupyterlite_sphinx.py
index 989a739..4d4d43f 100644
--- a/jupyterlite_sphinx/jupyterlite_sphinx.py
+++ b/jupyterlite_sphinx/jupyterlite_sphinx.py
@@ -1137,6 +1137,14 @@ def setup(app):
"replite_new_tab_button_text", "Open in a REPL", rebuild="html"
)
+ # REPL configuration options
+ app.add_config_value("replite_auto_execute", True, rebuild="html")
+ app.add_config_value("replite_clear_cells_on_execute", False, rebuild="html")
+ app.add_config_value("replite_clear_code_content_on_execute", False, rebuild="html")
+ app.add_config_value("replite_hide_code_input", False, rebuild="html")
+ app.add_config_value("replite_prompt_cell_position", "bottom", rebuild="html")
+ app.add_config_value("replite_show_banner", True, rebuild="html")
+
# Initialize NotebookLite and JupyterLite directives
app.add_node(
NotebookLiteIframe,
@@ -1186,7 +1194,6 @@ def setup(app):
man=(skip, None),
)
app.add_directive("replite", RepliteDirective)
- app.add_config_value("replite_auto_execute", True, rebuild="html")
# Initialize Voici directive and tabbed interface
app.add_node(
From d61e0fbc12369e631c15805e3886eebaaf1f510c Mon Sep 17 00:00:00 2001
From: Agriya Khetarpal <74401230+agriyakhetarpal@users.noreply.github.com>
Date: Wed, 7 May 2025 17:33:01 +0530
Subject: [PATCH 02/10] Bump to jupyterlite 0.6.0a9
---
pyproject.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyproject.toml b/pyproject.toml
index 4473438..1b38054 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -16,7 +16,7 @@ dependencies = [
"docutils",
"jupyter_server",
"jupyterlab_server",
- "jupyterlite-core >=0.2,<0.6",
+ "jupyterlite-core==0.6.0a9",
"jupytext",
"nbformat",
"sphinx>=4",
From 0dde042ebd45a21fc2c0fe6d66ec834d952352e2 Mon Sep 17 00:00:00 2001
From: Agriya Khetarpal <74401230+agriyakhetarpal@users.noreply.github.com>
Date: Wed, 7 May 2025 17:39:25 +0530
Subject: [PATCH 03/10] Add extra customisations to options_spec
---
jupyterlite_sphinx/jupyterlite_sphinx.py | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/jupyterlite_sphinx/jupyterlite_sphinx.py b/jupyterlite_sphinx/jupyterlite_sphinx.py
index 4d4d43f..59db243 100644
--- a/jupyterlite_sphinx/jupyterlite_sphinx.py
+++ b/jupyterlite_sphinx/jupyterlite_sphinx.py
@@ -405,6 +405,11 @@ class RepliteDirective(SphinxDirective):
"height": directives.unchanged,
"kernel": directives.unchanged,
"execute": directives.unchanged,
+ "clear_cells_on_execute": directives.unchanged,
+ "clear_code_content_on_execute": directives.unchanged,
+ "hide_code_input": directives.unchanged,
+ "prompt_cell_position": directives.unchanged,
+ "show_banner": directives.unchanged,
"toolbar": directives.unchanged,
"theme": directives.unchanged,
"prompt": directives.unchanged,
From 6385f7be3fb3f82869a6baa43632a36ae3d2301b Mon Sep 17 00:00:00 2001
From: Agriya Khetarpal <74401230+agriyakhetarpal@users.noreply.github.com>
Date: Wed, 7 May 2025 18:00:53 +0530
Subject: [PATCH 04/10] Some black formatting fixes
---
jupyterlite_sphinx/jupyterlite_sphinx.py | 19 ++++++++-----------
1 file changed, 8 insertions(+), 11 deletions(-)
diff --git a/jupyterlite_sphinx/jupyterlite_sphinx.py b/jupyterlite_sphinx/jupyterlite_sphinx.py
index 59db243..e5e3b41 100644
--- a/jupyterlite_sphinx/jupyterlite_sphinx.py
+++ b/jupyterlite_sphinx/jupyterlite_sphinx.py
@@ -85,7 +85,7 @@ def html(self):
)
placeholder_id = uuid4()
- container_style = f'width: {self["width"]}; height: {self["height"]};'
+ container_style = f"width: {self['width']}; height: {self['height']};"
return f"""
Date: Wed, 7 May 2025 18:10:10 +0530
Subject: [PATCH 05/10] Handle Replite directive customisations logic
---
jupyterlite_sphinx/jupyterlite_sphinx.py | 71 +++++++++++++++++++++---
1 file changed, 63 insertions(+), 8 deletions(-)
diff --git a/jupyterlite_sphinx/jupyterlite_sphinx.py b/jupyterlite_sphinx/jupyterlite_sphinx.py
index e5e3b41..9c241f3 100644
--- a/jupyterlite_sphinx/jupyterlite_sphinx.py
+++ b/jupyterlite_sphinx/jupyterlite_sphinx.py
@@ -428,14 +428,69 @@ def run(self):
search_params = search_params_parser(self.options.pop("search_params", False))
# We first check the global config, and then the per-directive
- # option. It defaults to True for backwards compatibility.
- execute = self.options.pop("execute", str(self.env.config.replite_auto_execute))
-
- if execute not in ("True", "False"):
- raise ValueError("The :execute: option must be either True or False")
-
- if execute == "False":
- self.options["execute"] = "0"
+ # options, with reasonable defaults for backwards compatibility.
+ repl_config_mappings = {
+ "execute": "execute",
+ "clear_cells_on_execute": "clearCellsOnExecute",
+ "clear_code_content_on_execute": "clearCodeContentOnExecute",
+ "hide_code_input": "hideCodeInput",
+ "show_banner": "showBanner",
+ "prompt_cell_position": "promptCellPosition",
+ }
+
+ for option in repl_config_mappings:
+ config_option = repl_config_mappings[option]
+ if option == "execute":
+ value = self.options.pop(
+ option, str(self.env.config.replite_auto_execute)
+ )
+ elif option == "clear_cells_on_execute":
+ value = self.options.pop(
+ option, str(self.env.config.replite_clear_cells_on_execute)
+ )
+ elif option == "clear_code_content_on_execute":
+ value = self.options.pop(
+ option, str(self.env.config.replite_clear_code_content_on_execute)
+ )
+ elif option == "hide_code_input":
+ value = self.options.pop(
+ option, str(self.env.config.replite_hide_code_input)
+ )
+ elif option == "show_banner":
+ value = self.options.pop(
+ option, str(self.env.config.replite_show_banner)
+ )
+ elif option == "prompt_cell_position":
+ value = self.options.pop(
+ option, str(self.env.config.replite_prompt_cell_position)
+ )
+ else:
+ err_msg = (
+ f"Unknown option {option} for Replite directive. "
+ "Please check the documentation for valid options."
+ )
+ raise ValueError(err_msg)
+
+ # Convert to URL parameter format (0/1) for all options
+ # except for prompt_cell_position
+ if option != "prompt_cell_position":
+ if value.lower() == "true":
+ self.options[config_option] = "1"
+ elif value.lower() == "false":
+ self.options[config_option] = "0"
+ else:
+ err_msg = (
+ f"The {option} option must be either True or False, not {value}"
+ )
+ raise ValueError(err_msg)
+ else:
+ # For prompt_cell_position, we need to check if the value is valid
+ if value not in ["top", "bottom", "left", "right"]:
+ err_msg = (
+ f"The {option} option must be one of: top, bottom, left, right"
+ )
+ raise ValueError(err_msg)
+ self.options[config_option] = value
content = self.content
From 8d440eb92ef748998faf51c7f02fb69724ad42a9 Mon Sep 17 00:00:00 2001
From: Agriya Khetarpal <74401230+agriyakhetarpal@users.noreply.github.com>
Date: Wed, 7 May 2025 18:10:24 +0530
Subject: [PATCH 06/10] Handle Replite tab customisations logic
---
jupyterlite_sphinx/jupyterlite_sphinx.py | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/jupyterlite_sphinx/jupyterlite_sphinx.py b/jupyterlite_sphinx/jupyterlite_sphinx.py
index 9c241f3..98a35b2 100644
--- a/jupyterlite_sphinx/jupyterlite_sphinx.py
+++ b/jupyterlite_sphinx/jupyterlite_sphinx.py
@@ -269,8 +269,27 @@ def __init__(
code = "\n".join(code_lines)
lite_options["code"] = code
+ # REPL URL parameters
if "execute" in lite_options and lite_options["execute"] == "0":
lite_options["execute"] = "0"
+ if (
+ "clearCellsOnExecute" in lite_options
+ and lite_options["clearCellsOnExecute"] == "0"
+ ):
+ lite_options["clearCellsOnExecute"] = "0"
+ if (
+ "clearCodeContentOnExecute" in lite_options
+ and lite_options["clearCodeContentOnExecute"] == "0"
+ ):
+ lite_options["clearCodeContentOnExecute"] = "0"
+ if "hideCodeInput" in lite_options and lite_options["hideCodeInput"] == "0":
+ lite_options["hideCodeInput"] = "0"
+ if "showBanner" in lite_options and lite_options["showBanner"] == "0":
+ lite_options["showBanner"] = "0"
+ if "promptCellPosition" in lite_options:
+ valid_positions = {"bottom", "top", "left", "right"}
+ if lite_options["promptCellPosition"] in valid_positions:
+ lite_options["promptCellPosition"] = lite_options["promptCellPosition"]
app_path = self.lite_app
if notebook is not None:
From 6ca0e9045b59ada146e80ca61cbc87cb6d6593c7 Mon Sep 17 00:00:00 2001
From: Agriya Khetarpal <74401230+agriyakhetarpal@users.noreply.github.com>
Date: Wed, 7 May 2025 18:19:25 +0530
Subject: [PATCH 07/10] Add docs on global REPL configuration
---
docs/configuration.md | 51 ++++++++++++++++++++++++++++++++++++++-----
1 file changed, 45 insertions(+), 6 deletions(-)
diff --git a/docs/configuration.md b/docs/configuration.md
index 3774fb9..10221c8 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -85,11 +85,50 @@ voici_new_tab_button_text = "My custom Voici button text"
You can override this text on a per-directive basis by passing the `:new_tab_button_text:` option
to the directive. Note that this is compatible only if `:new_tab:` is also provided.
-## REPL code auto-execution with the `Replite` directive
+## REPL configuration options
-It is possible to control whether code snippets in REPL environments automatically executes when loaded.
-For this, you may set `replite_auto_execute = False` globally in `conf.py` with (defaults to `True` if
-not present), or override it on a per-directive basis with `:execute: True` or `:execute: False`.
+We provide several configuration options for the Replite directive that control the behaviour and appearance of the REPL. These options can be set globally in `conf.py` and then overridden on a per-directive basis.
+
+### REPL code auto-execution
+
+```python
+# enable or disable automatic code execution when the REPL loads
+# (available in jupyterlite-core 0.5.0 and later)
+replite_auto_execute = True # default is True
+```
+
+This setting controls whether code snippets in REPL environments automatically execute when loaded. Set to `False` to disable automatic execution. You can override this on a per-directive basis with `:execute: True` or `:execute: False`.
+
+### REPL interface customisations (JupyterLite 0.6.0 and later)
+
+The following options customise how the REPL interface behaves and is presented:
+
+```python
+# clear previous cells when a new cell is executed
+replite_clear_cells_on_execute = False # default is False
+
+# clear the code content in the prompt cell after execution
+replite_clear_code_content_on_execute = False # default is False
+
+# hide input cells, showing only output
+replite_hide_code_input = False # default is False
+
+# position of the prompt cell ('bottom', 'top', 'left', or 'right')
+replite_prompt_cell_position = "bottom" # default is "bottom"
+
+# show or hide the kernel banner
+replite_show_banner = True # default is True
+```
+
+These global settings can be overridden in individual directives using the corresponding options:
+
+- `:clear_cells_on_execute: True/False`
+- `:clear_code_content_on_execute: True/False`
+- `:hide_code_input: True/False`
+- `:prompt_cell_position: bottom/top/left/right`
+- `:show_banner: True/False`
+
+For more details and visual examples of each, see the [Replite directive documentation](directives/replite.md).
## Strip particular tagged cells from IPython Notebooks
@@ -120,7 +159,7 @@ Sphinx-specific content. It can be used to remove either code cells or Markdown
For example, you can use this feature to remove the `toctree` directive from the rendered notebook
in the JupyterLite console:
-```json
+````json
{
"cells": [
{
@@ -148,7 +187,7 @@ in the JupyterLite console:
}
]
}
-```
+````
where the cell with the `toctree` directive will be removed from the rendered notebook in
the JupyterLite console.
From 21c7df50a0ca781ea4685527ce2c2d6f4f7504d6 Mon Sep 17 00:00:00 2001
From: Agriya Khetarpal <74401230+agriyakhetarpal@users.noreply.github.com>
Date: Wed, 7 May 2025 18:20:02 +0530
Subject: [PATCH 08/10] Add docs on enhanced Replite configuration
---
docs/directives/replite.md | 170 +++++++++++++++++++++++++++++++++++++
1 file changed, 170 insertions(+)
diff --git a/docs/directives/replite.md b/docs/directives/replite.md
index 26f115f..33015ed 100644
--- a/docs/directives/replite.md
+++ b/docs/directives/replite.md
@@ -157,3 +157,173 @@ global value using an additional `:new_tab_button_text:` parameter:
```
````
+
+````{tip}
+
+ ## Additional REPL interface options (JupyterLite 0.6.0+)
+
+ With `jupyterlite-core` versions 0.6.0 and later, the REPL interface comes with several additional customisation options that provide more control over the execution environment and layout:
+
+ ### Clearing cells on execute
+
+ To automatically clear the previously executed cells when a new cell is executed, use the `:clear_cells_on_execute:` option:
+
+ ```rst
+ .. replite::
+ :kernel: xeus-python
+ :clear_cells_on_execute: True
+
+ # When you execute this cell and then enter new code,
+ # this cell will disappear from the display
+ print("Hello, world!")
+ ```
+
+ ```{eval-rst}
+ .. replite::
+ :kernel: xeus-python
+ :clear_cells_on_execute: True
+
+ # When you execute this cell and then enter new code,
+ # this cell will disappear from the display
+ print("Hello, world!")
+ ```
+
+ ### Clearing code content on execute
+
+ To automatically clear the code content in the prompt cell after execution, use the `:clear_code_on_execute:` option:
+
+ ```rst
+ .. replite::
+ :kernel: xeus-python
+ :clear_code_content_on_execute: True
+
+ # After executing this cell, its content will be cleared,
+ # but the output will remain visible
+ print("The code will disappear but this output stays")
+ ```
+
+ ```{eval-rst}
+ .. replite::
+ :kernel: xeus-python
+ :clear_code_content_on_execute: True
+
+ # After executing this cell, its content will be cleared,
+ # but the output will remain visible
+ print("The code will disappear but this output stays")
+ ```
+
+ ### Hiding code input
+
+ To hide the input cells after execution, showing only the output, use the `:hide_code_input:` option:
+
+ ```rst
+ .. replite::
+ :kernel: xeus-python
+ :hide_code_input: True
+
+ # After executing this cell, the input will be hidden,
+ # but the output will remain visible
+ print("You'll see this output but not the code that generated it")
+ ```
+
+ ```{eval-rst}
+ .. replite::
+ :kernel: xeus-python
+ :hide_code_input: True
+
+ # After execution, this code will be hidden
+ # Only the output will be visible
+ print("You'll see this output but not the code that generated it")
+ ```
+
+ ### Changing prompt cell position
+
+ By default, the prompt cell is positioned at the bottom of the REPL interface. You can change this using the `:prompt_cell_position:` option, which accepts `top`, `bottom`, `left`, or `right`:
+
+ ```rst
+ .. replite::
+ :kernel: xeus-python
+ :prompt_cell_position: top
+
+ # The prompt will appear at the top of the REPL
+ print("Input above, output below")
+ ```
+
+ ```{eval-rst}
+ .. replite::
+ :kernel: xeus-python
+ :prompt_cell_position: top
+
+ # The prompt will appear at the top of the REPL
+ print("Input above, output below")
+ ```
+
+ ### Showing or hiding the kernel banner
+
+ By default, the REPL shows the kernel banner with version information. To hide this banner, use the `:show_banner:` option:
+
+ ```rst
+ .. replite::
+ :kernel: xeus-python
+ :show_banner: False
+
+ # The kernel banner won't be displayed
+ print("No banner here")
+ ```
+
+ ```{eval-rst}
+ .. replite::
+ :kernel: xeus-python
+ :show_banner: False
+
+ # The kernel banner won't be displayed
+ print("No banner here")
+ ```
+
+ ### Combining options
+ All of these options can be combined to create a customised REPL experience,
+ for example:
+
+ ```rst
+ .. replite::
+ :kernel: xeus-python
+ :prompt_cell_position: left
+ :hide_code_input: True
+ :show_banner: False
+ :height: 400px
+
+ # This will create a clean output-only display
+ # with the input cell on the left
+ import matplotlib.pyplot as plt
+ import numpy as np
+
+ x = np.linspace(0, 2 * np.pi, 200)
+ y = np.sin(x)
+
+ fig, ax = plt.subplots()
+ ax.plot(x, y)
+ plt.show()
+ ```
+
+ ```{eval-rst}
+ .. replite::
+ :kernel: xeus-python
+ :prompt_cell_position: left
+ :hide_code_input: True
+ :show_banner: False
+ :height: 400px
+
+ # This will create a clean output-only display
+ # with the input cell on the left
+ import matplotlib.pyplot as plt
+ import numpy as np
+
+ x = np.linspace(0, 2 * np.pi, 200)
+ y = np.sin(x)
+
+ fig, ax = plt.subplots()
+ ax.plot(x, y)
+ plt.show()
+ ```
+
+````
From d9dc2c99b8206d8412f5002d884b22e43ac14b06 Mon Sep 17 00:00:00 2001
From: Agriya Khetarpal <74401230+agriyakhetarpal@users.noreply.github.com>
Date: Wed, 7 May 2025 18:30:14 +0530
Subject: [PATCH 09/10] Install JupyterLite alpha in RTD deployment
---
dev-environment.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dev-environment.yml b/dev-environment.yml
index 2547bde..5c001ca 100644
--- a/dev-environment.yml
+++ b/dev-environment.yml
@@ -5,7 +5,6 @@ dependencies:
- pip
- jupyter_server
- jupyterlab_server
- - jupyterlite-core >=0.3,<0.6
- jupytext
- pydata-sphinx-theme
- micromamba=2.0.5
@@ -16,4 +15,5 @@ dependencies:
- voici
- pip:
- .
+ - jupyterlite-core ==0.6.0a9
- jupyterlite-xeus >=2.1.2
From e491d48193d2adb84c8fdee0afabcb81aa7655a6 Mon Sep 17 00:00:00 2001
From: Agriya Khetarpal <74401230+agriyakhetarpal@users.noreply.github.com>
Date: Wed, 7 May 2025 18:32:59 +0530
Subject: [PATCH 10/10] Temporarily relax jupyterlite-xeus as well
---
dev-environment.yml | 2 +-
pyproject.toml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/dev-environment.yml b/dev-environment.yml
index 5c001ca..582813c 100644
--- a/dev-environment.yml
+++ b/dev-environment.yml
@@ -16,4 +16,4 @@ dependencies:
- pip:
- .
- jupyterlite-core ==0.6.0a9
- - jupyterlite-xeus >=2.1.2
+ # - jupyterlite-xeus >=2.1.2
diff --git a/pyproject.toml b/pyproject.toml
index 1b38054..10a8f05 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -30,7 +30,7 @@ dev = [
docs = [
"myst_parser",
"pydata-sphinx-theme",
- "jupyterlite-xeus>=0.1.8,<4",
+ # "jupyterlite-xeus>=0.1.8,<4",
]
[tool.hatch.version]