Skip to content

Commit a6510c9

Browse files
committed
merged upstream
2 parents 997f9ee + 9398627 commit a6510c9

File tree

5 files changed

+186
-17
lines changed

5 files changed

+186
-17
lines changed

doc/source/index.rst

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -250,11 +250,6 @@ produces:
250250

251251
print("hello, world!", file=sys.stderr)
252252

253-
.. warning::
254-
255-
Note that output written to ``stderr`` is not displayed any differently than output written
256-
to ``stdout``.
257-
258253
Controlling the execution environment
259254
-------------------------------------
260255
The execution environment can be controlled by using the ``jupyter-kernel`` directive. This directive takes
@@ -289,6 +284,30 @@ the code. If a document contains ``jupyter-kernel`` directives with ``:id:`` spe
289284
the name provided to ``:id:`` can be used to get the code for the cells belonging to the
290285
that Jupyter session.
291286

287+
Styling options
288+
---------------
289+
290+
The CSS (Cascading Style Sheet) class structure of jupyter-sphinx is the
291+
following::
292+
293+
- jupyter_container
294+
- code_cell
295+
- stderr
296+
- output
297+
298+
If a code cell is not displayed, the output is provided without the
299+
``jupyter_container``. If you want to adjust the styles, add a new stylesheet,
300+
e.g. ``custom.css``, and adjust your ``conf.py`` to load it. How you do so depends on
301+
the theme you are using.
302+
303+
Here is a sample ``custom.css`` file overriding the ``stderr`` background color:
304+
305+
.. code-block:: css
306+
307+
.jupyter_container .stderr {
308+
background-color: #7FFF00;
309+
}
310+
292311
293312
Configuration options
294313
---------------------

jupyter_sphinx/css/jupyter-sphinx.css

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/* Stylesheet for jupyter-sphinx
2+
3+
These styles mimic the Jupyter HTML styles.
4+
5+
The default CSS (Cascading Style Sheet) class structure of jupyter-sphinx
6+
is the following:
7+
8+
jupyter_container
9+
code_cell (optional)
10+
stderr (optional)
11+
output (optional)
12+
13+
If the code_cell is not displayed, then there is not a jupyter_container, and
14+
the output is provided without CSS.
15+
16+
This stylesheet attempts to override the defaults of all packaged Sphinx themes
17+
to display jupter-sphinx cells in a Jupyter-like style.
18+
19+
If you want to adjust the styles, add additional custom CSS to override these
20+
styles.
21+
22+
After a build, this stylesheet is loaded from ./_static/jupyter-sphinx.css .
23+
24+
*/
25+
26+
27+
div.jupyter_container {
28+
padding: .4em;
29+
margin: 0 0 .4em 0;
30+
background-color: #FFFF;
31+
border: 1px solid #CCC;
32+
-moz-box-shadow: 2px 2px 4px rgba(87, 87, 87, 0.2);
33+
-webkit-box-shadow: 2px 2px 4px rgba(87, 87, 87, 0.2);
34+
box-shadow: 2px 2px 4px rgba(87, 87, 87, 0.2);
35+
}
36+
.jupyter_container div.code_cell {
37+
border: 1px solid #cfcfcf;
38+
border-radius: 2px;
39+
background-color: #f7f7f7;
40+
margin: 0 0;
41+
}
42+
43+
.jupyter_container div.code_cell pre {
44+
padding: 4px;
45+
margin: 0 0;
46+
background-color: #f7f7f7;
47+
border: none;
48+
background: none;
49+
-webkit-box-shadow: none; /* for nature */
50+
-moz-box-shadow: none; /* for nature */
51+
}
52+
53+
.jupyter_container div.code_cell * {
54+
margin: 0 0;
55+
}
56+
div.jupyter_container div.highlight {
57+
background-color: #f7f7f7; /* for haiku */
58+
}
59+
div.jupyter_container * {
60+
padding: 0;
61+
margin: 0;
62+
}
63+
/* overrides for sphinx_rtd_theme */
64+
.rst-content .jupyter_container div[class^='highlight'],
65+
.document .jupyter_container div[class^='highlight'],
66+
.rst-content .jupyter_container pre.literal-block {
67+
border:none;
68+
margin: 0;
69+
padding: 0;
70+
background: none;
71+
padding: 3px;
72+
background-color: transparent;
73+
}
74+
/* restore Mathjax CSS, as it assumes a vertical margin. */
75+
.jupyter_container .MathJax_Display {
76+
margin: 1em 0em;
77+
text-align: center;
78+
}
79+
.jupyter_container .stderr {
80+
background-color: #FCC;
81+
border: none;
82+
padding: 3px;
83+
}
84+
.jupyter_container .output {
85+
border: none;
86+
}
87+
.jupyter_container div.output pre {
88+
background-color: white;
89+
background: none;
90+
padding: 4px;
91+
border: none;
92+
-webkit-box-shadow: none; /* for nature */
93+
-moz-box-shadow: none; /* for nature */
94+
}
95+
.jupyter_container .code_cell td.linenos {
96+
align: right;
97+
padding: 4px 4px 4px 8px;
98+
border-right: 1px solid #cfcfcf;
99+
color: #999;
100+
}
101+
.jupyter_container .output .highlight {
102+
background-color: #ffffff;
103+
}
104+
/* combine sequential jupyter cells,
105+
by moving sequential ones up higher on y-axis */
106+
div.jupyter_container + div.jupyter_container {
107+
margin: -.5em 0 .4em 0;
108+
}

jupyter_sphinx/execute.py

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,14 @@ def builder_inited(app):
5555
if embed_url:
5656
app.add_js_file(embed_url)
5757

58+
# add jupyter-sphinx css
59+
app.add_css_file('jupyter-sphinx.css')
5860
# Check if a thebelab config was specified
5961
if app.config.jupyter_sphinx_thebelab_config:
6062
app.add_js_file('thebelab-helper.js')
6163
app.add_css_file('thebelab.css')
6264

65+
6366
### Directives and their associated doctree nodes
6467

6568
class JupyterKernel(Directive):
@@ -411,6 +414,12 @@ def apply(self):
411414
source["highlight_args"] = {'linenostart': linenostart}
412415
linenostart += source.rawsource.count("\n") + 1
413416

417+
418+
# Add code cell CSS class
419+
for node in nodes:
420+
source = node.children[0]
421+
source.attributes["classes"] = ["code_cell"]
422+
414423
# Write certain cell outputs (e.g. images) to separate files, and
415424
# modify the metadata of the associated cells in 'notebook' to
416425
# include the path to the output file.
@@ -505,13 +514,34 @@ def cell_output_to_nodes(cell, data_priority, write_stderr, dir, thebe_config):
505514
if (
506515
output_type == 'stream'
507516
):
508-
if not write_stderr and output["name"] == "stderr":
509-
continue
510-
to_add.append(docutils.nodes.literal_block(
511-
text=output['text'],
512-
rawsource=output['text'],
513-
language='none',
514-
))
517+
if output["name"] == "stderr":
518+
if not write_stderr:
519+
continue
520+
else:
521+
# Output a container with an unhighlighted literal block for
522+
# `stderr` messages.
523+
#
524+
# Adds a "stderr" class that can be customized by the user for both
525+
# the container and the literal_block.
526+
#
527+
# Not setting "rawsource" disables Pygment hightlighting, which
528+
# would otherwise add a <div class="highlight">.
529+
530+
container = docutils.nodes.container(classes=["stderr"])
531+
container.append(docutils.nodes.literal_block(
532+
text=output['text'],
533+
rawsource='', # disables Pygment highlighting
534+
language='none',
535+
classes=["stderr"]
536+
))
537+
to_add.append(container)
538+
else:
539+
to_add.append(docutils.nodes.literal_block(
540+
text=output['text'],
541+
rawsource=output['text'],
542+
language='none',
543+
classes=["output", "stream"]
544+
))
515545
elif (
516546
output_type == 'error'
517547
):
@@ -521,6 +551,7 @@ def cell_output_to_nodes(cell, data_priority, write_stderr, dir, thebe_config):
521551
text=text,
522552
rawsource=text,
523553
language='ipythontb',
554+
classes =["output", "traceback"]
524555
))
525556
elif (
526557
output_type in ('display_data', 'execute_result')
@@ -545,19 +576,23 @@ def cell_output_to_nodes(cell, data_priority, write_stderr, dir, thebe_config):
545576
elif mime_type == 'text/html':
546577
to_add.append(docutils.nodes.raw(
547578
text=data,
548-
format='html'
579+
format='html',
580+
classes=["output", "text_html"]
581+
549582
))
550583
elif mime_type == 'text/latex':
551584
to_add.append(math_block(
552585
text=data,
553586
nowrap=False,
554587
number=None,
588+
classes=["output", "text_latex"]
555589
))
556590
elif mime_type == 'text/plain':
557591
to_add.append(docutils.nodes.literal_block(
558592
text=data,
559593
rawsource=data,
560594
language='none',
595+
classes=["output", "text_plain"]
561596
))
562597
elif mime_type == 'application/javascript':
563598
to_add.append(docutils.nodes.raw(
@@ -572,9 +607,10 @@ def cell_output_to_nodes(cell, data_priority, write_stderr, dir, thebe_config):
572607

573608

574609
def attach_outputs(output_nodes, node, thebe_config, cm_language):
610+
if not node.attributes["hide_code"]: # only add css if code is displayed
611+
node.attributes["classes"] = ["jupyter_container"]
575612
if thebe_config:
576613
source = node.children[0]
577-
578614
thebe_source = ThebeSourceNode(hide_code=node.attributes['hide_code'],
579615
code_below=node.attributes['code_below'],
580616
language=cm_language)
@@ -592,7 +628,6 @@ def attach_outputs(output_nodes, node, thebe_config, cm_language):
592628
else:
593629
if node.attributes['hide_code']:
594630
node.children = []
595-
596631
if not node.attributes['hide_output']:
597632
if node.attributes['code_below']:
598633
node.children = output_nodes + node.children
@@ -742,6 +777,11 @@ def build_finished(app, env):
742777
if app.builder.format != 'html':
743778
return
744779

780+
# Copy stylesheet
781+
src = os.path.join(os.path.dirname(__file__), 'css')
782+
dst = os.path.join(app.outdir, '_static')
783+
copy_asset(src, dst)
784+
745785
thebe_config = app.config.jupyter_sphinx_thebelab_config
746786
if not thebe_config:
747787
return
@@ -754,6 +794,7 @@ def build_finished(app, env):
754794

755795
def setup(app):
756796
# Configuration
797+
757798
app.add_config_value(
758799
'jupyter_execute_kwargs',
759800
dict(timeout=-1, allow_errors=True, store_widget_state=True),

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,5 @@
3030
'nbformat',
3131
],
3232
python_requires = '>= 3.5',
33-
package_data={'jupyter_sphinx': ['thebelab/*']},
33+
package_data={'jupyter_sphinx': ['thebelab/*', 'css/*']},
3434
)

tests/test_execute.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,8 @@ def test_stderr(doctree):
310310
tree = doctree(source)
311311
cell, = tree.traverse(JupyterCellNode)
312312
assert len(cell.children) == 2
313-
assert cell.children[1].rawsource.strip() == "hello world"
313+
assert 'stderr' in cell.children[1].attributes['classes']
314+
assert cell.children[1].astext().strip() == "hello world"
314315

315316

316317
thebe_config = "jupyter_sphinx_thebelab_config = {\"dummy\": True}"

0 commit comments

Comments
 (0)