Skip to content

Commit 9792e22

Browse files
authored
Merge pull request #129 from steppi/custom-css
Improve TryExamples customization
2 parents 661eafc + 0691b0c commit 9792e22

File tree

5 files changed

+225
-218
lines changed

5 files changed

+225
-218
lines changed

docs/_static/try_examples.css

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
.try_examples_button {
2+
background-color: #f7dc1e;
3+
border: none;
4+
padding: 5px 10px;
5+
border-radius: 15px;
6+
font-family: vibur;
7+
font-size: larger;
8+
box-shadow: 0 2px 5px rgba(108,108,108,0.2);
9+
}
10+
11+
.try_examples_button:hover {
12+
background-color: #fff221;
13+
transform: scale(1.02);
14+
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
15+
cursor: pointer;
16+
}
17+
18+
.try_examples_button_container {
19+
display: flex;
20+
justify-content: flex-end;
21+
}

docs/conf.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,7 @@
2828
]
2929
}
3030

31+
html_static_path = ["_static"]
32+
html_css_files = ["try_examples.css"]
33+
3134
suppress_warnings = ["myst.xref_missing"]

docs/directives/try_examples.md

Lines changed: 149 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,28 @@
11
# TryExamples directive
22

33
`jupyterlite-sphinx` provides the experimental `try_examples` directive which allows
4-
docstring examples sections written in [doctestformat](https://docs.python.org/3/library/doctest.html) to be swapped with an embedded classic Notebook at the push of a button.
4+
docstring examples sections written in [doctest format](https://docs.python.org/3/library/doctest.html) to be swapped with an embedded classic Notebook at the push of a button.
5+
6+
Below is an example of the directive in use. The button has been styled with custom
7+
css as explained in the configuration section below. Without custom css, the button will
8+
be plain and unadorned.
59

610

711
```rst
812
Examples
913
--------
1014
.. try_examples::
11-
:button_css:
12-
background-color: #f7dc1e;
13-
border: none;
14-
padding: 5px 10px;
15-
border-radius: 15px;
16-
font-family: vibur;
17-
font-size: x-large;
18-
box-shadow: 0 2px 5px rgba(108,108,108,0.2);
19-
:button_hover_css:
20-
background-color: #fff221;
21-
transform: scale(1.02);
22-
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
23-
cursor: pointer;
24-
:button_horizontal_position: right
25-
:button_vertical_position: top
26-
:button_text: Try it in a classic notebook!
27-
:min_height: 200px
28-
2915
3016
Doctest examples sections are parsed and converted to notebooks. Blocks of text
31-
like this become markdown cells. Codeblocks begin with `>>>`. Contiguous blocks
17+
like this become markdown cells. Codeblocks begin with ``>>>``. Contiguous blocks
3218
of code are combined into a single code cell.
3319
3420
>>> x = 2
3521
>>> y = 2
3622
>>> x + y
3723
4
3824
39-
`...` is used to continue multiline statements.
25+
``...`` is used to continue multiline statements.
4026
4127
>>> def f(x, y):
4228
... return x + y
@@ -54,28 +40,13 @@ Examples
5440
markdown format.
5541
```
5642

43+
and here is how this looks and works when rendered.
44+
5745

5846
```{eval-rst}
5947
Examples
6048
--------
6149
.. try_examples::
62-
:button_css:
63-
background-color: #f7dc1e;
64-
border: none;
65-
padding: 5px 10px;
66-
border-radius: 15px;
67-
font-family: vibur;
68-
font-size: x-large;
69-
box-shadow: 0 2px 5px rgba(108,108,108,0.2);
70-
:button_hover_css:
71-
background-color: #fff221;
72-
transform: scale(1.02);
73-
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
74-
cursor: pointer;
75-
:button_horizontal_position: right
76-
:button_vertical_position: top
77-
:button_text: Try it in a classic notebook!
78-
:min_height: 200px
7950
8051
Doctest examples sections are parsed and converted to notebooks. Blocks of text
8152
like this become markdown cells. Codeblocks begin with `>>>`. Contiguous blocks
@@ -104,75 +75,144 @@ Examples
10475
markdown format.
10576
```
10677

78+
By default, the height of the embedded notebook's iframe container is calculated to match the height of the rendered doctest examples so that it takes up the same amount of space on the
79+
page.
80+
10781
## Configuration
10882

109-
The button's text, position, and style can be configured to match your page design. The
110-
text can be configured with the option `:button_text:`. The options `:button_css:` and
111-
`:button_hover_css:` take lists of css properties as in the example above, and
112-
apply them to the button. `:button_horizontal_position:` can be one of `left`, `right`, or
113-
`center` and `:button_vertical_position:` can be one of `top` or `bottom`. The position
114-
is with respect to the rendered examples block / embedded notebook
115-
(depending on which is active).
83+
The position and style of the button can be customized to match your documentation's
84+
design by adding custom css as explained in Sphinx's documentation [here](https://docs.readthedocs.io/en/stable/guides/adding-custom-css.html#how-to-add-custom-css-or-javascript-to-sphinx-documentation). The buttons have class `try_examples_button`. The buttons are placed within
85+
containers with class `try_examples_button_container`, which can be selected to adjust the
86+
positioning of the button. The css for the example above is
87+
88+
```css
89+
90+
.try_examples_button {
91+
color: white;
92+
background-color: #0054a6;
93+
border: none;
94+
padding: 5px 10px;
95+
border-radius: 10px;
96+
margin-bottom: 5px;
97+
box-shadow: 0 2px 5px rgba(108,108,108,0.2);
98+
}
99+
100+
.try_examples_button:hover {
101+
background-color: #0066cc;
102+
transform: scale(1.02);
103+
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
104+
cursor: pointer;
105+
}
106+
107+
.try_examples_button_container {
108+
display: flex;
109+
justify-content: flex-end;
110+
}
111+
```
116112

117-
The height of the embedded notebook's iframe container is calculated to match the height
118-
of the rendered doctest examples so that it takes up the same amount of space on the
119-
page. The `:min_height:` option can be used to ensure that the embedded notebook will not
120-
be unuseably small for very short examples blocks, though its use can cause the contents
121-
of the page to shift when the button is pressed.
122113

123-
the `:theme:` option available for other `jupyterlite-sphinx` directives is also
124-
available.
114+
The `try_examples` directive has options
115+
* `:height:` To set a specific value for the height of the [iframe](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe) containing the embeddednotebook.
116+
* `:button_text` To customize the text of the button that replaces the rendered examples with an embedded notebook.
117+
* `:theme:` This works the same as for the other JupyterLite-Sphinx directives.
118+
* `:example_class:` An html class to attach to the outer container for the rendered
119+
examples content and embedded notebook. This can be used in a custom css file to allow
120+
for more precise customization, eg. different button styles across different examples.
125121

126-
If you are using [sphinx.ext.autodoc](https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html) with [numpydoc](https://numpydoc.readthedocs.io/en/latest/format.html) or [sphinx.ext.napoleon](https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html), you
127-
can set the option
122+
Here's an example with some options set
123+
124+
```rst
125+
.. try_examples::
126+
:button_text: Try it in your browser!
127+
:height: 400px
128+
129+
The button text has changed and the height now exceeds the size of the content.
130+
131+
>>> x = 2
132+
>>> y = 2
133+
>>> x + y
134+
4
135+
136+
```
137+
138+
and here is the result
139+
140+
```{eval-rst}
141+
.. try_examples::
142+
:button_text: Try it in your browser!
143+
:height: 400px
144+
145+
The button text has changed and the height now exceeds the size of the content.
146+
147+
>>> x = 2
148+
>>> y = 2
149+
>>> x + y
150+
4
128151
129-
```python
130-
global_enable_try_examples = True
131152
```
132153

133-
in your sphinx `conf.py` in order to automatically insert the `try_examples` directive
134-
in examples sections during the `"autodoc-process-docstring"` event. Configuration values
135-
can be set globally for the inserted `try_examples` directives by setting the config values
136-
`try_examples_global_button_css`, etc. as below. All valid config values are supported
137-
by prepending `try_examples_global_`.
154+
155+
### Global Configuration
156+
157+
For projects with a large number of existing doctest examples, it would be tedious to add
158+
the `try_examples` directive manually to each docstring example. If you are using [sphinx.ext.autodoc](https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html) with either [numpydoc](https://numpydoc.readthedocs.io/en/latest/format.html) or [sphinx.ext.napoleon](https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html), you
159+
can set the option.
138160

139161
```python
140162
global_enable_try_examples = True
141-
try_examples_global_button_css = """
142-
color: white;
143-
background-color: #0054a6;
144-
border: none;
145-
padding: 5px 10px;
146-
border-radius: 5px;
147-
cursor: pointer;
148-
"""
149-
try_examples_global_button_hover_css = """
150-
background-color: #0066cc;
151-
transform: scale(1.02);
152-
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
153-
"""
154-
155-
try_examples_global_button_text = "Try it in your browser!"
156-
try_examples_global_min_height = "200px"
157163
```
158164

165+
in your sphinx `conf.py` in order to automatically insert the `try_examples` directive
166+
in examples sections during the `"autodoc-process-docstring"` event. This works by
167+
identifying section headings. An examples section includes all of the content beneath
168+
an examples heading, and up to either the next heading or the end of the docstring if
169+
there are no further headings. One of `numpydoc` or `sphinx.ext.napoleon` is required
170+
because these map the section headers to a standardized format.
171+
159172
If an examples section already contains a `try_examples` directive, no additional
160173
directives will be inserted, allowing for specific cases to be separately configured
161-
if needed. Adding the comment `..! disable_try_examples` as the first non-empty line under
174+
if needed. Adding the comment
175+
176+
177+
```rst
178+
..! disable_try_examples`
179+
```
180+
181+
as the first non-empty line under
162182
the section header for an examples section will prevent a directive from being inserted,
163183
allowing for specification of examples sections which should not be made interactive.
164184

165-
## Other considerations
166-
If you are using the `TryExamples` directive in your documentation, you'll need to ensure
167-
that the version of the package installed in the Jupyterlite kernel you are using
168-
matches that of the version you are documenting.
169185

170-
## Configuration without rebuilding
186+
The button text and theme can be set globally with the config variables
187+
`try_examples_global_button_text`, and `try_examples_global_theme`.
188+
189+
```python
190+
global_enable_try_examples = True
191+
try_examples_global_button_text = "Try it in your browser!"
192+
try_examples_global_height = "200px"
193+
```
194+
195+
There is no option to set a global specific height because the proper height
196+
should depend on the size of the examples content. Again, the default height of
197+
the embedded notebook's iframe container matches the height of the associated
198+
rendered doctest example so that it takes up the same amount of space on the
199+
page. For very small examples this may lead to an unusably small notebook. It's possible
200+
to set a global minimum height in the `try_examples.json` configuration file described
201+
below.
202+
203+
### try_examples.json configuration file.
204+
205+
Users may place a configuration file `try_examples.json` in the source root of
206+
their documentation. This configuration file will be copied to the build root of
207+
the deployed documentation. Changes to the configuration file in the build root
208+
will be respected without rebuilding the documentation, allowing for runtime
209+
configuration.
171210

172-
The `TryExamples` directive supports disabling interactive examples without rebuilding
173-
the documentation. This can be helpful for projects requiring substantial documentation
174-
build time. Users may add a json config file entitled `.try_examples.json` to the root
175-
directory of the build directory for the deployed documentation. The format is a list of
211+
The current options are
212+
213+
#### "ignore_patterns"
214+
215+
The format is a list of
176216
[JavaScript Regex patterns](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions) attached to the key `"ignore_patterns"` like below.
177217

178218
```json
@@ -184,23 +224,38 @@ directory of the build directory for the deployed documentation. The format is a
184224
`TryExamples` buttons will be hidden in url pathnames matching at least one of these
185225
patterns, effectively disabling the interactive documentation. In the provided example:
186226

187-
* The pattern `".*latest/.*" disables interactive examples for urls for the documentation
227+
* The pattern `"^/latest/.*"` disables interactive examples for urls for the documentation
188228
for the latest version of the package, which may be useful if this documentation is
189229
for a development version for which a corresponding package build is not available
190230
in a Jupyterlite kernel.
191231

192-
* The pattern `".*stable/reference/generated/example.html"` targets a particular url
232+
* The pattern `"^/stable/reference/generated/example.html"` targets a particular url
193233
in the documentation for the latest stable release.
194234

195235
Note that these patterns should match the [pathname](https://developer.mozilla.org/en-US/docs/Web/API/Location/pathname) of the url, not the full url. This is the path portion of
196236
the url. For instance, the pathname of https://jupyterlite-sphinx.readthedocs.io/en/latest/directives/try_examples.html is `/en/latest/directives/try_examples.html`.
197237

238+
Again, the configuration file can be added or edited within the deployed documentation,
239+
allowing for disabling or enabling examples without rebuilding the documentation.
198240

199-
A default configuration file can be specified in `conf.py` with the option
200-
`try_examples_default_runtime_config`.
241+
#### "global_min_height"
242+
To avoid having unusably small notebooks for very small examples due to the default of
243+
having the embedded notebooks' iframe containers take the same amount of space as the
244+
rendered content they replace, users can set a global minimum height in
245+
`try_examples.json`.
201246

202-
```python
203-
try_examples_default_runtime_config = {
204-
"ignore_patterns": ["^/latest/.*", "^/stable/reference/generated/example.html"]
247+
```json
248+
{
249+
"global_min_height": "400px"
205250
}
206251
```
252+
253+
This allows the minimum height to be set or changed without rebuilding the docs. This
254+
configuration value will be ignored when a specific height is supplied as an option to
255+
`.. try_examples::`.
256+
257+
258+
## Other considerations
259+
If you are using the `TryExamples` directive in your documentation, you'll need to ensure
260+
that the version of the package installed in the Jupyterlite kernel you are using
261+
matches that of the version you are documenting.

0 commit comments

Comments
 (0)