Skip to content

Commit 9398627

Browse files
authored
Merge pull request #87 from seanpue/std_err_in_div
added css insertion to improve display
2 parents 68c281a + 330f95b commit 9398627

File tree

7 files changed

+161
-26
lines changed

7 files changed

+161
-26
lines changed

doc/source/_static/custom.css

Lines changed: 0 additions & 7 deletions
This file was deleted.

doc/source/conf.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,3 @@
4141
"repo": "jupyter/jupyter-sphinx",
4242
},
4343
}
44-
html_static_path = ["_static/custom.css"] # css overrides for Alabaster theme

doc/source/index.rst

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -251,13 +251,6 @@ produces:
251251

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

254-
.. note::
255-
To adjust the CSS of the ``stderr`` stream, use the ``stderr`` class. If you are using
256-
the default Sphinx theme, for example, add the following
257-
`custom CSS <https://alabaster.readthedocs.io/en/latest/customization.html#custom-stylesheet>`_:
258-
``.stderr {background-color: #FCC}``
259-
260-
261254
Controlling the execution environment
262255
-------------------------------------
263256
The execution environment can be controlled by using the ``jupyter-kernel`` directive. This directive takes
@@ -292,6 +285,30 @@ the code. If a document contains ``jupyter-kernel`` directives with ``:id:`` spe
292285
the name provided to ``:id:`` can be used to get the code for the cells belonging to the
293286
that Jupyter session.
294287

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

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: 28 additions & 9 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):
@@ -131,6 +134,8 @@ class JupyterCell(Directive):
131134
If provided, the cell output will not be displayed in the output.
132135
code-below : bool
133136
If provided, the code will be shown below the cell output.
137+
linenos : bool
138+
If provided, the code will be shown with line numbers.
134139
raises : comma separated list of exception types
135140
If provided, a comma-separated list of exception type names that
136141
the cell may raise. If one of the listed execption types is raised
@@ -400,6 +405,12 @@ def apply(self):
400405
source = node.children[0]
401406
source["linenos"] = True
402407

408+
409+
# Add code cell CSS class
410+
for node in nodes:
411+
source = node.children[0]
412+
source.attributes["classes"] = ["code_cell"]
413+
403414
# Write certain cell outputs (e.g. images) to separate files, and
404415
# modify the metadata of the associated cells in 'notebook' to
405416
# include the path to the output file.
@@ -504,26 +515,23 @@ def cell_output_to_nodes(cell, data_priority, write_stderr, dir, thebe_config):
504515
# Adds a "stderr" class that can be customized by the user for both
505516
# the container and the literal_block.
506517
#
507-
# Also adds "error" as a base class, which is a fairly common
508-
# class in Sphinx themes. It should result in differentiation
509-
# from stdout in most Sphinx themes.
510-
#
511518
# Not setting "rawsource" disables Pygment hightlighting, which
512519
# would otherwise add a <div class="highlight">.
513520

514-
container = docutils.nodes.container(classes=["error", "stderr"])
521+
container = docutils.nodes.container(classes=["stderr"])
515522
container.append(docutils.nodes.literal_block(
516523
text=output['text'],
517524
rawsource='', # disables Pygment highlighting
518525
language='none',
519-
classes=["error", "stderr"]
526+
classes=["stderr"]
520527
))
521528
to_add.append(container)
522529
else:
523530
to_add.append(docutils.nodes.literal_block(
524531
text=output['text'],
525532
rawsource=output['text'],
526533
language='none',
534+
classes=["output", "stream"]
527535
))
528536
elif (
529537
output_type == 'error'
@@ -534,6 +542,7 @@ def cell_output_to_nodes(cell, data_priority, write_stderr, dir, thebe_config):
534542
text=text,
535543
rawsource=text,
536544
language='ipythontb',
545+
classes =["output", "traceback"]
537546
))
538547
elif (
539548
output_type in ('display_data', 'execute_result')
@@ -558,19 +567,23 @@ def cell_output_to_nodes(cell, data_priority, write_stderr, dir, thebe_config):
558567
elif mime_type == 'text/html':
559568
to_add.append(docutils.nodes.raw(
560569
text=data,
561-
format='html'
570+
format='html',
571+
classes=["output", "text_html"]
572+
562573
))
563574
elif mime_type == 'text/latex':
564575
to_add.append(math_block(
565576
text=data,
566577
nowrap=False,
567578
number=None,
579+
classes=["output", "text_latex"]
568580
))
569581
elif mime_type == 'text/plain':
570582
to_add.append(docutils.nodes.literal_block(
571583
text=data,
572584
rawsource=data,
573585
language='none',
586+
classes=["output", "text_plain"]
574587
))
575588
elif mime_type == 'application/javascript':
576589
to_add.append(docutils.nodes.raw(
@@ -585,9 +598,10 @@ def cell_output_to_nodes(cell, data_priority, write_stderr, dir, thebe_config):
585598

586599

587600
def attach_outputs(output_nodes, node, thebe_config, cm_language):
601+
if not node.attributes["hide_code"]: # only add css if code is displayed
602+
node.attributes["classes"] = ["jupyter_container"]
588603
if thebe_config:
589604
source = node.children[0]
590-
591605
thebe_source = ThebeSourceNode(hide_code=node.attributes['hide_code'],
592606
code_below=node.attributes['code_below'],
593607
language=cm_language)
@@ -605,7 +619,6 @@ def attach_outputs(output_nodes, node, thebe_config, cm_language):
605619
else:
606620
if node.attributes['hide_code']:
607621
node.children = []
608-
609622
if not node.attributes['hide_output']:
610623
if node.attributes['code_below']:
611624
node.children = output_nodes + node.children
@@ -755,6 +768,11 @@ def build_finished(app, env):
755768
if app.builder.format != 'html':
756769
return
757770

771+
# Copy stylesheet
772+
src = os.path.join(os.path.dirname(__file__), 'css')
773+
dst = os.path.join(app.outdir, '_static')
774+
copy_asset(src, dst)
775+
758776
thebe_config = app.config.jupyter_sphinx_thebelab_config
759777
if not thebe_config:
760778
return
@@ -767,6 +785,7 @@ def build_finished(app, env):
767785

768786
def setup(app):
769787
# Configuration
788+
770789
app.add_config_value(
771790
'jupyter_execute_kwargs',
772791
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: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,6 @@ def test_stderr(doctree):
268268
cell, = tree.traverse(JupyterCellNode)
269269
assert len(cell.children) == 2
270270
assert 'stderr' in cell.children[1].attributes['classes']
271-
assert 'error' in cell.children[1].attributes['classes']
272271
assert cell.children[1].astext().strip() == "hello world"
273272

274273

0 commit comments

Comments
 (0)