diff --git a/contrib/get_nbconvert_minfied_css.py b/contrib/get_nbconvert_minfied_css.py
new file mode 100644
index 0000000000000000000000000000000000000000..922d0a272a355854c54c14f70ca3136beaeb993d
--- /dev/null
+++ b/contrib/get_nbconvert_minfied_css.py
@@ -0,0 +1,202 @@
+# -*- coding: utf-8 -*-
+#! /usr/bin/env python3
+
+"""
+Generate minified stylesheet for ipython notebook
+"""
+
+import os
+
+REPLACE_HIGHLIGHT_WITH_CODEHILITE = False
+
+NOTEBOOK_CSS_VERSION = '4.3.0'
+CSS_URL = ("https://cdn.jupyter.org/notebook/%s/style/style.min.css"
+ % NOTEBOOK_CSS_VERSION)
+
+REQUEST_TIMEOUT = 6
+REQUEST_MAX_RETRIES = 5
+
+IPYTHON_NOTEBOOK_DECLARE_STR = """
+/*!
+*
+* IPython notebook
+*
+*/"""
+
+IPYTHON_NOTEBOOK_WEBAPP_DECLARE_STR = """
+/*!
+*
+* IPython notebook webapp
+*
+*/
+"""
+
+HIGHLIGHT_CSS_CLASS = ".highlight"
+CODEHILITE_CSS_CLASS = ".codehilite"
+PYGMENTS_STYLE = "default"
+
+HIGHLIGT_DECLARE_STR = """
+/*!
+*
+* Pygments "%s" style with "%s" css_class
+*
+*/
+""" %(PYGMENTS_STYLE,
+ CODEHILITE_CSS_CLASS
+ if REPLACE_HIGHLIGHT_WITH_CODEHILITE else HIGHLIGHT_CSS_CLASS)
+
+DEST_DIR = (
+ os.path.abspath(
+ os.path.join(
+ os.path.dirname(__file__),
+ os.path.pardir, 'relate', 'static', 'css')))
+
+CSS_DEST = os.path.join(DEST_DIR, 'ipynb.style.css')
+CSS_MINIFIED_DEST = os.path.join(DEST_DIR, 'ipynb.style.min.css')
+
+
+def retry_urlopen(request, timeout=REQUEST_TIMEOUT, n_retries=REQUEST_MAX_RETRIES):
+ from six.moves.urllib.request import urlopen
+ i = 0
+ while True:
+ try:
+ result = urlopen(request, timeout=timeout).read()
+ return result
+ except Exception as e:
+ from six.moves.urllib.error import URLError
+ from socket import timeout as TimeoutError
+ if not isinstance(e, (URLError, TimeoutError)):
+ raise e
+ if not "timed out" in str(e).lower():
+ raise e
+ i += 1
+ if i > n_retries:
+ raise e
+ print("\rRequest timed out, retry (%s/%s). " % (
+ i, n_retries), flush=True, end="")
+ import time
+ time.sleep(0.1)
+
+
+def minify_css(css_string):
+ url = 'https://cssminifier.com/raw'
+ post_fields = {'input': css_string}
+ from six.moves.urllib.parse import urlencode
+ from six.moves.urllib.request import Request
+ request = Request(url, urlencode(post_fields).encode())
+ return retry_urlopen(request)
+
+
+class GenerateCSS(object):
+ def _download(self):
+ try:
+ return retry_urlopen(CSS_URL)
+ except Exception as e:
+ if 'ssl' in str(e).lower():
+ import sys
+ try:
+ import pycurl
+ except ImportError:
+ print(
+ "Failed, try again after installing PycURL with "
+ "`pip install pycurl` to avoid outdated SSL.",
+ file=sys.stderr)
+ raise e
+ else:
+ print("Failed, trying again with PycURL to avoid "
+ "outdated SSL.",
+ file=sys.stderr)
+ return self._download_pycurl()
+ raise e
+
+ def _download_pycurl(self):
+ """Download CSS with pycurl, in case of old SSL (e.g. Python < 2.7.9)."""
+ import pycurl
+ c = pycurl.Curl()
+ c.setopt(c.URL, CSS_URL)
+ from io import BytesIO
+ buf = BytesIO()
+ c.setopt(c.WRITEDATA, buf)
+ c.perform()
+ return buf.getvalue().decode()
+
+ def process_nbconvert_css(self):
+ print("Downloading ipython notebook CSS: %s." % CSS_URL)
+ try:
+ css = self._download()
+ print("Done.")
+ return self._process_nbconvert_css(css)
+ except:
+ raise
+
+ def _process_nbconvert_css(self, css):
+ print("Processing downloaded ipython notebook CSS.")
+ try:
+ css = css.split(IPYTHON_NOTEBOOK_DECLARE_STR.encode())[1]
+ css = IPYTHON_NOTEBOOK_DECLARE_STR.encode() + css
+ except IndexError:
+ raise ValueError("Bad splitter for notebook css %s"
+ % IPYTHON_NOTEBOOK_DECLARE_STR)
+
+ print("Done.")
+ if not REPLACE_HIGHLIGHT_WITH_CODEHILITE:
+ return css
+ return css.replace(HIGHLIGHT_CSS_CLASS.encode() + b" ",
+ CODEHILITE_CSS_CLASS.encode() + b" ")
+
+ def process_highlight_style_defs(self, style=PYGMENTS_STYLE):
+ print("Processing Pygments code highlight CSS.")
+ def get_highlight_style_defs():
+ from pygments.formatters import get_formatter_by_name
+ formatter = get_formatter_by_name("html", style=style)
+ return formatter.get_style_defs()
+
+ style_defs = get_highlight_style_defs()
+ print("Done.")
+ if REPLACE_HIGHLIGHT_WITH_CODEHILITE:
+ css_class = CODEHILITE_CSS_CLASS
+ else:
+ css_class = HIGHLIGHT_CSS_CLASS
+ return (HIGHLIGT_DECLARE_STR +
+ "\n".join(["%s %s" % (css_class, line)
+ for line in style_defs.splitlines()]))
+
+ def get_assembled_css(self):
+ try:
+ nbcovert_css = self.process_nbconvert_css()
+ highlight_css = self.process_highlight_style_defs()
+ except:
+ raise
+ css = "\n".join([nbcovert_css.decode(), highlight_css])
+ print("CSS assembled.")
+ return css
+
+ def get_minified_css(self, css):
+ css = (css.replace(IPYTHON_NOTEBOOK_DECLARE_STR, "")
+ .replace(IPYTHON_NOTEBOOK_WEBAPP_DECLARE_STR, "")
+ .replace(HIGHLIGT_DECLARE_STR, "")
+ )
+ return minify_css(css)
+
+ def run(self):
+ css = self.get_assembled_css()
+ with open(CSS_DEST, 'wb') as f:
+ f.write(css.encode())
+ print("Succesfully generated %s" % CSS_DEST)
+
+ print("Minifying CSS...")
+ minified_css = self.get_minified_css(css).decode()
+ print("Done.")
+
+ with open(CSS_MINIFIED_DEST, 'wb') as f:
+ f.write(minified_css.encode())
+ print("Succesfully generated %s" % CSS_MINIFIED_DEST)
+
+
+def main():
+ g = GenerateCSS()
+ g.run()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/course/content.py b/course/content.py
index eade7a0ee1739d98318fe18b76669e2772a752d3..99328765a89cd701f10aaf6322da7e13de94c8c6 100644
--- a/course/content.py
+++ b/course/content.py
@@ -896,14 +896,35 @@ def expand_markup(
env = Environment(
loader=GitTemplateLoader(repo, commit_sha),
undefined=StrictUndefined)
+
template = env.from_string(text)
- text = template.render(**jinja_env)
+ kwargs = {}
+ if jinja_env:
+ kwargs.update(jinja_env)
+
+ from course.utils import (
+ IpythonNotebookCellsJinjaExpansionContext as IpynbContext)
+ kwargs[IpynbContext.context_name] = IpynbContext(course, repo, commit_sha)
+
+ text = template.render(**kwargs)
# }}}
return text
+def unwrap_relate_tmp_pre_tag(html_string):
+ # type: (Text) -> (Text)
+
+ from lxml.html import fromstring, tostring
+ tree = fromstring(html_string)
+
+ for node in tree.iterdescendants("pre"):
+ if "relate_tmp_pre" in node.attrib.get("class", ""):
+ node.drop_tag()
+ return tostring(tree, encoding="unicode")
+
+
def markup_to_html(
course, # type: Optional[Course]
repo, # type: Repo_ish
@@ -915,6 +936,11 @@ def markup_to_html(
jinja_env={}, # type: Dict
):
# type: (...) -> Text
+
+ disable_codehilite = bool(
+ getattr(settings,
+ "RELATE_DISABLE_CODEHILITE_MARKDOWN_EXTENSION", True))
+
if course is not None and not jinja_env:
try:
import django.core.cache as cache
@@ -922,9 +948,12 @@ def markup_to_html(
cache_key = None
else:
import hashlib
- cache_key = ("markup:v7:%s:%d:%s:%s"
- % (CACHE_KEY_ROOT, course.id, str(commit_sha),
- hashlib.md5(text.encode("utf-8")).hexdigest()))
+ cache_key = ("markup:v7:%s:%d:%s:%s%s"
+ % (CACHE_KEY_ROOT,
+ course.id, str(commit_sha),
+ hashlib.md5(text.encode("utf-8")).hexdigest(),
+ ":NOCODEHILITE" if disable_codehilite else ""
+ ))
def_cache = cache.caches["default"]
result = def_cache.get(cache_key)
@@ -949,15 +978,30 @@ def markup_to_html(
from course.mdx_mathjax import MathJaxExtension
import markdown
+
+ extensions = [
+ LinkFixerExtension(course, commit_sha, reverse_func=reverse_func),
+ MathJaxExtension(),
+ "markdown.extensions.extra",
+ ]
+
+ if not disable_codehilite:
+ # Note: no matter whether disable_codehilite, the code in
+ # the rendered ipython notebook will be highlighted.
+ # "css_class=highlight" is to ensure that, when codehilite extension
+ # is enabled, code out side of notebook uses the same html class
+ # attribute as the default highlight class (i.e., `highlight`)
+ # used by rendered ipynb notebook cells, Thus we don't need to
+ # make 2 copies of css for the highlight.
+ extensions += ["markdown.extensions.codehilite(css_class=highlight)"]
+
result = markdown.markdown(text,
- extensions=[
- LinkFixerExtension(course, commit_sha, reverse_func=reverse_func),
- MathJaxExtension(),
- "markdown.extensions.extra",
- "markdown.extensions.codehilite",
- ],
+ extensions=extensions,
output_format="html5")
+ if result.strip():
+ result = unwrap_relate_tmp_pre_tag(result)
+
assert isinstance(result, six.text_type)
if cache_key is not None:
def_cache.add(cache_key, result, None)
diff --git a/course/templates/course/jinja2/nbconvert_template.tpl b/course/templates/course/jinja2/nbconvert_template.tpl
new file mode 100644
index 0000000000000000000000000000000000000000..f040623ae182dcd75792303c0b86b022075da044
--- /dev/null
+++ b/course/templates/course/jinja2/nbconvert_template.tpl
@@ -0,0 +1,10 @@
+{%- extends 'basic.tpl' -%}
+
+{# This is to prevent code_cell being process by markdown_to_html #}
+
+{% block input %}
{{ super() }}
+{%- endblock input %}
+
+{# This is to remove the empty cells ahead of markdown_cells #}
+{% block empty_in_prompt -%}
+{%- endblock empty_in_prompt %}
\ No newline at end of file
diff --git a/course/utils.py b/course/utils.py
index 6209648783114f970cecab5494e78565367e84c5..88311ac2f8dc0d5f4cd0b5651d273919418e2f09 100644
--- a/course/utils.py
+++ b/course/utils.py
@@ -69,9 +69,13 @@ if False:
FlowSession,
FlowPageData,
)
+ from course.content import Repo_ish # noqa
# }}}
+import re
+CODE_CELL_DIV_ATTRS_RE = re.compile('()')
+
def getattr_with_fallback(aggregates, attr_name, default=None):
# type: (Iterable[Any], Text, Any) -> Any
@@ -1181,4 +1185,110 @@ def get_course_specific_language_choices():
return tuple(filtered_options)
+
+class RelateJinjaExpansionContextBase(object):
+ def __init__(self, course, repo, commit_sha):
+ # type: (Optional[Course], Repo_ish, bytes) -> None
+ self.course = course
+ self.repo = repo
+ self.commit_sha = commit_sha
+
+ @property
+ def context_name(self):
+ raise NotImplementedError()
+
+ def __call__(self, *args, **kwargs):
+ # type: (*Any, **Any) -> Text
+ raise NotImplementedError()
+
+
+# {{{ ipynb utilities
+
+class IpythonNotebookCellsJinjaExpansionContext(RelateJinjaExpansionContextBase):
+ context_name = "render_notebook_cells"
+
+ def render_notebook_cells(self, ipynb_path, indices=None, clear_output=False,
+ clear_markdown=False):
+ # type: (Text, Optional[Any], Optional[bool], Optional[bool]) -> Text
+ from course.content import get_repo_blob_data_cached
+ try:
+ ipynb_source = get_repo_blob_data_cached(self.repo, ipynb_path,
+ self.commit_sha).decode()
+
+ return self.render_notebook_from_source(
+ ipynb_source,
+ clear_output=clear_output,
+ indices=indices,
+ clear_markdown=clear_markdown,
+ )
+ except ObjectDoesNotExist:
+ raise
+
+ __call__ = render_notebook_cells # type: ignore
+
+ def render_notebook_from_source(self, ipynb_source, clear_output=False,
+ indices=None, clear_markdown=False):
+ # type: (Text, Optional[bool], Optional[Any], Optional[bool]) -> Text
+ """
+ Get HTML format of ipython notebook so as to be rendered in RELATE flow
+ pages.
+ :param ipynb_source: the :class:`text` read from a ipython notebook.
+ :param clear_output: a :class:`bool` instance, indicating whether existing
+ execution output of code cells should be removed.
+ :param indices: a :class:`list` instance, 0-based indices of notebook cells
+ which are expected to be rendered.
+ :param clear_markdown: a :class:`bool` instance, indicating whether markdown
+ cells will be ignored..
+ :return:
+ """
+ import nbformat
+ from nbformat.reader import parse_json
+ nb_source_dict = parse_json(ipynb_source)
+
+ if indices:
+ nb_source_dict.update(
+ {"cells": [nb_source_dict["cells"][idx] for idx in indices]})
+
+ if clear_markdown:
+ nb_source_dict.update(
+ {"cells": [cell for cell in nb_source_dict["cells"]
+ if cell['cell_type'] != "markdown"]})
+
+ nb_source_dict.update({"cells": nb_source_dict["cells"]})
+
+ import json
+ ipynb_source = json.dumps(nb_source_dict)
+ notebook = nbformat.reads(ipynb_source, as_version=4)
+
+ from traitlets.config import Config
+ c = Config()
+
+ # This is to prevent execution of arbitrary code from note book
+ c.ExecutePreprocessor.enabled = False
+ if clear_output:
+ c.ClearOutputPreprocessor.enabled = True
+
+ c.CSSHTMLHeaderPreprocessor.enabled = False
+ c.HighlightMagicsPreprocessor.enabled = False
+
+ import os
+ from django.conf import settings
+
+ # Place the template in course template dir
+ template_path = os.path.join(
+ settings.BASE_DIR, "course", "templates", "course", "jinja2")
+ c.TemplateExporter.template_path.append(template_path)
+
+ from nbconvert import HTMLExporter
+ html_exporter = HTMLExporter(
+ config=c,
+ template_file="nbconvert_template.tpl"
+ )
+
+ (body, resources) = html_exporter.from_notebook_node(notebook)
+
+ return body
+
+# }}}
+
# vim: foldmethod=marker
diff --git a/doc/content.rst b/doc/content.rst
index 610028a3903fbfe77aa91e335549e3d3ac8ca489..5d516a4b74ccea7c980aa64bd234bb59b1508281 100644
--- a/doc/content.rst
+++ b/doc/content.rst
@@ -319,6 +319,37 @@ The following snippet shows an interactive video viewer::
To view this video please enable JavaScript, and consider upgrading to a web browser that supports HTML5 video
+
+Ipython notebook to HTML
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+RELATE provides the functionality of rendering `Ipython Notebooks
+
`_ in course pages.
+
+.. function:: render_notebook_cells(ipynb_path, indices=None, clear_output=False,
+ clear_markdown=False)
+ Convert an ipython notebook to markdown via nbconvert
+ (see http://nbconvert.readthedocs.io).
+
+ :param ipynb_path: :class:`string`, the path of the ipython notebook in
+ the repo.
+ :param indices: :class:`list`, the indices of cells which are expected to
+ be rendered. For example, ``[1, 2, 3, 6]`` or ``range(3, -1)``. If not
+ specified, all cells will be rendered.
+ :param clear_output: :class:`bool`, indicating whether existing execution
+ output of code cells should be removed. Default: `False`.
+ :param clear_markdown: :class:`bool`, indicating whether all text cells
+ will be removed. Default: `False`.
+ :rtype: :class:`string`, rendered markdown which will be consequently
+ converted to HTML.
+
+For example, the following snippet shows the HTML version of ``test.ipynb`` in repo
+folder ``code``, with markdown (``text_cells``) and output (execution result of
+``code_cells``) removed::
+
+ {{ render_notebook_cells("code/test.ipynb", clear_markdown=True, clear_output=True) }}
+
+
Macros
^^^^^^
diff --git a/local_settings.example.py b/local_settings.example.py
index 6b3f43b440a453afe95e75780a4131cfb590e759..db3188ac6eeae274bcaa67f4d46939be2bff81c8 100644
--- a/local_settings.example.py
+++ b/local_settings.example.py
@@ -209,6 +209,11 @@ RELATE_SHOW_EDITOR_FORM = True
# }}}
+# Whether disable "markdown.extensions.codehilite" when rendering page markdown.
+# Default to True, as enable it sometimes crashes for some pages with code fences.
+# For this reason, there will be a warning when the attribute is set to False when
+# starting the server.
+#RELATE_DISABLE_CODEHILITE_MARKDOWN_EXTENSION = True
# {{{ user full_name format
diff --git a/relate/checks.py b/relate/checks.py
index dcaa5aed2d46c601b6b9179f220eb3c616ef548b..c5468932e379a305c7ac3c75411c9773d059e51d 100644
--- a/relate/checks.py
+++ b/relate/checks.py
@@ -54,6 +54,8 @@ RELATE_STARTUP_CHECKS_EXTRA = "RELATE_STARTUP_CHECKS_EXTRA"
RELATE_STARTUP_CHECKS_TAG = "start_up_check"
RELATE_STARTUP_CHECKS_EXTRA_TAG = "startup_checks_extra"
+RELATE_DISABLE_CODEHILITE_MARKDOWN_EXTENSION = (
+ "RELATE_DISABLE_CODEHILITE_MARKDOWN_EXTENSION")
class RelateCriticalCheckMessage(Critical):
@@ -349,6 +351,35 @@ def check_relate_settings(app_configs, **kwargs):
# }}}
+ # {{{ check RELATE_DISABLE_CODEHILITE_MARKDOWN_EXTENSION
+ relate_disable_codehilite_markdown_extension = getattr(
+ settings, RELATE_DISABLE_CODEHILITE_MARKDOWN_EXTENSION, None)
+ if relate_disable_codehilite_markdown_extension is not None:
+ if not isinstance(relate_disable_codehilite_markdown_extension, bool):
+ errors.append(
+ Warning(
+ msg="%(location)s is not a Boolean value: `%(value)s`, "
+ "assuming True"
+ % {"location":
+ RELATE_DISABLE_CODEHILITE_MARKDOWN_EXTENSION,
+ "value":
+ repr(relate_disable_codehilite_markdown_extension)},
+ id="relate_disable_codehilite_markdown_extension.W001"))
+ elif not relate_disable_codehilite_markdown_extension:
+ errors.append(
+ Warning(
+ msg="%(location)s is set to False "
+ "(with 'markdown.extensions.codehilite' enabled'), "
+ "noticing that some pages with code fence markdown "
+ "might get crashed"
+ % {"location":
+ RELATE_DISABLE_CODEHILITE_MARKDOWN_EXTENSION,
+ "value":
+ repr(relate_disable_codehilite_markdown_extension)},
+ id="relate_disable_codehilite_markdown_extension.W002"))
+
+ # }}}
+
# {{{ check LANGUAGES, why this is not done in django?
languages = settings.LANGUAGES
@@ -468,7 +499,7 @@ def register_startup_checks_extra():
Register extra checks provided by user.
Here we will have to raise error for Exceptions, as that can not be done
via check: all checks, including check_relate_settings, will only be
- executed after self.ready() is done.
+ executed after AppConfig.ready() is done.
"""
startup_checks_extra = getattr(settings, RELATE_STARTUP_CHECKS_EXTRA, None)
if startup_checks_extra:
diff --git a/relate/static/css/ipynb.style.css b/relate/static/css/ipynb.style.css
new file mode 100644
index 0000000000000000000000000000000000000000..79fd18630228afa2181a2870ff7ee0e65c4f8578
--- /dev/null
+++ b/relate/static/css/ipynb.style.css
@@ -0,0 +1,2257 @@
+
+/*!
+*
+* IPython notebook
+*
+*/
+/* CSS font colors for translated ANSI colors. */
+.ansibold {
+ font-weight: bold;
+}
+/* use dark versions for foreground, to improve visibility */
+.ansiblack {
+ color: black;
+}
+.ansired {
+ color: darkred;
+}
+.ansigreen {
+ color: darkgreen;
+}
+.ansiyellow {
+ color: #c4a000;
+}
+.ansiblue {
+ color: darkblue;
+}
+.ansipurple {
+ color: darkviolet;
+}
+.ansicyan {
+ color: steelblue;
+}
+.ansigray {
+ color: gray;
+}
+/* and light for background, for the same reason */
+.ansibgblack {
+ background-color: black;
+}
+.ansibgred {
+ background-color: red;
+}
+.ansibggreen {
+ background-color: green;
+}
+.ansibgyellow {
+ background-color: yellow;
+}
+.ansibgblue {
+ background-color: blue;
+}
+.ansibgpurple {
+ background-color: magenta;
+}
+.ansibgcyan {
+ background-color: cyan;
+}
+.ansibggray {
+ background-color: gray;
+}
+div.cell {
+ /* Old browsers */
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-box-align: stretch;
+ display: -moz-box;
+ -moz-box-orient: vertical;
+ -moz-box-align: stretch;
+ display: box;
+ box-orient: vertical;
+ box-align: stretch;
+ /* Modern browsers */
+ display: flex;
+ flex-direction: column;
+ align-items: stretch;
+ border-radius: 2px;
+ box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ border-width: 1px;
+ border-style: solid;
+ border-color: transparent;
+ width: 100%;
+ padding: 5px;
+ /* This acts as a spacer between cells, that is outside the border */
+ margin: 0px;
+ outline: none;
+ border-left-width: 1px;
+ padding-left: 5px;
+ background: linear-gradient(to right, transparent -40px, transparent 1px, transparent 1px, transparent 100%);
+}
+div.cell.jupyter-soft-selected {
+ border-left-color: #90CAF9;
+ border-left-color: #E3F2FD;
+ border-left-width: 1px;
+ padding-left: 5px;
+ border-right-color: #E3F2FD;
+ border-right-width: 1px;
+ background: #E3F2FD;
+}
+@media print {
+ div.cell.jupyter-soft-selected {
+ border-color: transparent;
+ }
+}
+div.cell.selected {
+ border-color: #ababab;
+ border-left-width: 0px;
+ padding-left: 6px;
+ background: linear-gradient(to right, #42A5F5 -40px, #42A5F5 5px, transparent 5px, transparent 100%);
+}
+@media print {
+ div.cell.selected {
+ border-color: transparent;
+ }
+}
+div.cell.selected.jupyter-soft-selected {
+ border-left-width: 0;
+ padding-left: 6px;
+ background: linear-gradient(to right, #42A5F5 -40px, #42A5F5 7px, #E3F2FD 7px, #E3F2FD 100%);
+}
+.edit_mode div.cell.selected {
+ border-color: #66BB6A;
+ border-left-width: 0px;
+ padding-left: 6px;
+ background: linear-gradient(to right, #66BB6A -40px, #66BB6A 5px, transparent 5px, transparent 100%);
+}
+@media print {
+ .edit_mode div.cell.selected {
+ border-color: transparent;
+ }
+}
+.prompt {
+ /* This needs to be wide enough for 3 digit prompt numbers: In[100]: */
+ min-width: 14ex;
+ /* This padding is tuned to match the padding on the CodeMirror editor. */
+ padding: 0.4em;
+ margin: 0px;
+ font-family: monospace;
+ text-align: right;
+ /* This has to match that of the the CodeMirror class line-height below */
+ line-height: 1.21429em;
+ /* Don't highlight prompt number selection */
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ /* Use default cursor */
+ cursor: default;
+}
+@media (max-width: 540px) {
+ .prompt {
+ text-align: left;
+ }
+}
+div.inner_cell {
+ min-width: 0;
+ /* Old browsers */
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-box-align: stretch;
+ display: -moz-box;
+ -moz-box-orient: vertical;
+ -moz-box-align: stretch;
+ display: box;
+ box-orient: vertical;
+ box-align: stretch;
+ /* Modern browsers */
+ display: flex;
+ flex-direction: column;
+ align-items: stretch;
+ /* Old browsers */
+ -webkit-box-flex: 1;
+ -moz-box-flex: 1;
+ box-flex: 1;
+ /* Modern browsers */
+ flex: 1;
+}
+/* input_area and input_prompt must match in top border and margin for alignment */
+div.input_area {
+ border: 1px solid #cfcfcf;
+ border-radius: 2px;
+ background: #f7f7f7;
+ line-height: 1.21429em;
+}
+/* This is needed so that empty prompt areas can collapse to zero height when there
+ is no content in the output_subarea and the prompt. The main purpose of this is
+ to make sure that empty JavaScript output_subareas have no height. */
+div.prompt:empty {
+ padding-top: 0;
+ padding-bottom: 0;
+}
+div.unrecognized_cell {
+ padding: 5px 5px 5px 0px;
+ /* Old browsers */
+ display: -webkit-box;
+ -webkit-box-orient: horizontal;
+ -webkit-box-align: stretch;
+ display: -moz-box;
+ -moz-box-orient: horizontal;
+ -moz-box-align: stretch;
+ display: box;
+ box-orient: horizontal;
+ box-align: stretch;
+ /* Modern browsers */
+ display: flex;
+ flex-direction: row;
+ align-items: stretch;
+}
+div.unrecognized_cell .inner_cell {
+ border-radius: 2px;
+ padding: 5px;
+ font-weight: bold;
+ color: red;
+ border: 1px solid #cfcfcf;
+ background: #eaeaea;
+}
+div.unrecognized_cell .inner_cell a {
+ color: inherit;
+ text-decoration: none;
+}
+div.unrecognized_cell .inner_cell a:hover {
+ color: inherit;
+ text-decoration: none;
+}
+@media (max-width: 540px) {
+ div.unrecognized_cell > div.prompt {
+ display: none;
+ }
+}
+div.code_cell {
+ /* avoid page breaking on code cells when printing */
+}
+@media print {
+ div.code_cell {
+ page-break-inside: avoid;
+ }
+}
+/* any special styling for code cells that are currently running goes here */
+div.input {
+ page-break-inside: avoid;
+ /* Old browsers */
+ display: -webkit-box;
+ -webkit-box-orient: horizontal;
+ -webkit-box-align: stretch;
+ display: -moz-box;
+ -moz-box-orient: horizontal;
+ -moz-box-align: stretch;
+ display: box;
+ box-orient: horizontal;
+ box-align: stretch;
+ /* Modern browsers */
+ display: flex;
+ flex-direction: row;
+ align-items: stretch;
+}
+@media (max-width: 540px) {
+ div.input {
+ /* Old browsers */
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-box-align: stretch;
+ display: -moz-box;
+ -moz-box-orient: vertical;
+ -moz-box-align: stretch;
+ display: box;
+ box-orient: vertical;
+ box-align: stretch;
+ /* Modern browsers */
+ display: flex;
+ flex-direction: column;
+ align-items: stretch;
+ }
+}
+/* input_area and input_prompt must match in top border and margin for alignment */
+div.input_prompt {
+ color: #303F9F;
+ border-top: 1px solid transparent;
+}
+div.input_area > div.highlight {
+ margin: 0.4em;
+ border: none;
+ padding: 0px;
+ background-color: transparent;
+}
+div.input_area > div.highlight > pre {
+ margin: 0px;
+ border: none;
+ padding: 0px;
+ background-color: transparent;
+}
+/* The following gets added to the if it is detected that the user has a
+ * monospace font with inconsistent normal/bold/italic height. See
+ * notebookmain.js. Such fonts will have keywords vertically offset with
+ * respect to the rest of the text. The user should select a better font.
+ * See: https://github.com/ipython/ipython/issues/1503
+ *
+ * .CodeMirror span {
+ * vertical-align: bottom;
+ * }
+ */
+.CodeMirror {
+ line-height: 1.21429em;
+ /* Changed from 1em to our global default */
+ font-size: 14px;
+ height: auto;
+ /* Changed to auto to autogrow */
+ background: none;
+ /* Changed from white to allow our bg to show through */
+}
+.CodeMirror-scroll {
+ /* The CodeMirror docs are a bit fuzzy on if overflow-y should be hidden or visible.*/
+ /* We have found that if it is visible, vertical scrollbars appear with font size changes.*/
+ overflow-y: hidden;
+ overflow-x: auto;
+}
+.CodeMirror-lines {
+ /* In CM2, this used to be 0.4em, but in CM3 it went to 4px. We need the em value because */
+ /* we have set a different line-height and want this to scale with that. */
+ padding: 0.4em;
+}
+.CodeMirror-linenumber {
+ padding: 0 8px 0 4px;
+}
+.CodeMirror-gutters {
+ border-bottom-left-radius: 2px;
+ border-top-left-radius: 2px;
+}
+.CodeMirror pre {
+ /* In CM3 this went to 4px from 0 in CM2. We need the 0 value because of how we size */
+ /* .CodeMirror-lines */
+ padding: 0;
+ border: 0;
+ border-radius: 0;
+}
+/*
+
+Original style from softwaremaniacs.org (c) Ivan Sagalaev
+Adapted from GitHub theme
+
+*/
+.highlight-base {
+ color: #000;
+}
+.highlight-variable {
+ color: #000;
+}
+.highlight-variable-2 {
+ color: #1a1a1a;
+}
+.highlight-variable-3 {
+ color: #333333;
+}
+.highlight-string {
+ color: #BA2121;
+}
+.highlight-comment {
+ color: #408080;
+ font-style: italic;
+}
+.highlight-number {
+ color: #080;
+}
+.highlight-atom {
+ color: #88F;
+}
+.highlight-keyword {
+ color: #008000;
+ font-weight: bold;
+}
+.highlight-builtin {
+ color: #008000;
+}
+.highlight-error {
+ color: #f00;
+}
+.highlight-operator {
+ color: #AA22FF;
+ font-weight: bold;
+}
+.highlight-meta {
+ color: #AA22FF;
+}
+/* previously not defined, copying from default codemirror */
+.highlight-def {
+ color: #00f;
+}
+.highlight-string-2 {
+ color: #f50;
+}
+.highlight-qualifier {
+ color: #555;
+}
+.highlight-bracket {
+ color: #997;
+}
+.highlight-tag {
+ color: #170;
+}
+.highlight-attribute {
+ color: #00c;
+}
+.highlight-header {
+ color: blue;
+}
+.highlight-quote {
+ color: #090;
+}
+.highlight-link {
+ color: #00c;
+}
+/* apply the same style to codemirror */
+.cm-s-ipython span.cm-keyword {
+ color: #008000;
+ font-weight: bold;
+}
+.cm-s-ipython span.cm-atom {
+ color: #88F;
+}
+.cm-s-ipython span.cm-number {
+ color: #080;
+}
+.cm-s-ipython span.cm-def {
+ color: #00f;
+}
+.cm-s-ipython span.cm-variable {
+ color: #000;
+}
+.cm-s-ipython span.cm-operator {
+ color: #AA22FF;
+ font-weight: bold;
+}
+.cm-s-ipython span.cm-variable-2 {
+ color: #1a1a1a;
+}
+.cm-s-ipython span.cm-variable-3 {
+ color: #333333;
+}
+.cm-s-ipython span.cm-comment {
+ color: #408080;
+ font-style: italic;
+}
+.cm-s-ipython span.cm-string {
+ color: #BA2121;
+}
+.cm-s-ipython span.cm-string-2 {
+ color: #f50;
+}
+.cm-s-ipython span.cm-meta {
+ color: #AA22FF;
+}
+.cm-s-ipython span.cm-qualifier {
+ color: #555;
+}
+.cm-s-ipython span.cm-builtin {
+ color: #008000;
+}
+.cm-s-ipython span.cm-bracket {
+ color: #997;
+}
+.cm-s-ipython span.cm-tag {
+ color: #170;
+}
+.cm-s-ipython span.cm-attribute {
+ color: #00c;
+}
+.cm-s-ipython span.cm-header {
+ color: blue;
+}
+.cm-s-ipython span.cm-quote {
+ color: #090;
+}
+.cm-s-ipython span.cm-link {
+ color: #00c;
+}
+.cm-s-ipython span.cm-error {
+ color: #f00;
+}
+.cm-s-ipython span.cm-tab {
+ background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAMCAYAAAAkuj5RAAAAAXNSR0IArs4c6QAAAGFJREFUSMft1LsRQFAQheHPowAKoACx3IgEKtaEHujDjORSgWTH/ZOdnZOcM/sgk/kFFWY0qV8foQwS4MKBCS3qR6ixBJvElOobYAtivseIE120FaowJPN75GMu8j/LfMwNjh4HUpwg4LUAAAAASUVORK5CYII=);
+ background-position: right;
+ background-repeat: no-repeat;
+}
+div.output_wrapper {
+ /* this position must be relative to enable descendents to be absolute within it */
+ position: relative;
+ /* Old browsers */
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-box-align: stretch;
+ display: -moz-box;
+ -moz-box-orient: vertical;
+ -moz-box-align: stretch;
+ display: box;
+ box-orient: vertical;
+ box-align: stretch;
+ /* Modern browsers */
+ display: flex;
+ flex-direction: column;
+ align-items: stretch;
+ z-index: 1;
+}
+/* class for the output area when it should be height-limited */
+div.output_scroll {
+ /* ideally, this would be max-height, but FF barfs all over that */
+ height: 24em;
+ /* FF needs this *and the wrapper* to specify full width, or it will shrinkwrap */
+ width: 100%;
+ overflow: auto;
+ border-radius: 2px;
+ -webkit-box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.8);
+ box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.8);
+ display: block;
+}
+/* output div while it is collapsed */
+div.output_collapsed {
+ margin: 0px;
+ padding: 0px;
+ /* Old browsers */
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-box-align: stretch;
+ display: -moz-box;
+ -moz-box-orient: vertical;
+ -moz-box-align: stretch;
+ display: box;
+ box-orient: vertical;
+ box-align: stretch;
+ /* Modern browsers */
+ display: flex;
+ flex-direction: column;
+ align-items: stretch;
+}
+div.out_prompt_overlay {
+ height: 100%;
+ padding: 0px 0.4em;
+ position: absolute;
+ border-radius: 2px;
+}
+div.out_prompt_overlay:hover {
+ /* use inner shadow to get border that is computed the same on WebKit/FF */
+ -webkit-box-shadow: inset 0 0 1px #000;
+ box-shadow: inset 0 0 1px #000;
+ background: rgba(240, 240, 240, 0.5);
+}
+div.output_prompt {
+ color: #D84315;
+}
+/* This class is the outer container of all output sections. */
+div.output_area {
+ padding: 0px;
+ page-break-inside: avoid;
+ /* Old browsers */
+ display: -webkit-box;
+ -webkit-box-orient: horizontal;
+ -webkit-box-align: stretch;
+ display: -moz-box;
+ -moz-box-orient: horizontal;
+ -moz-box-align: stretch;
+ display: box;
+ box-orient: horizontal;
+ box-align: stretch;
+ /* Modern browsers */
+ display: flex;
+ flex-direction: row;
+ align-items: stretch;
+}
+div.output_area .MathJax_Display {
+ text-align: left !important;
+}
+div.output_area .rendered_html table {
+ margin-left: 0;
+ margin-right: 0;
+}
+div.output_area .rendered_html img {
+ margin-left: 0;
+ margin-right: 0;
+}
+div.output_area img,
+div.output_area svg {
+ max-width: 100%;
+ height: auto;
+}
+div.output_area img.unconfined,
+div.output_area svg.unconfined {
+ max-width: none;
+}
+/* This is needed to protect the pre formating from global settings such
+ as that of bootstrap */
+.output {
+ /* Old browsers */
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-box-align: stretch;
+ display: -moz-box;
+ -moz-box-orient: vertical;
+ -moz-box-align: stretch;
+ display: box;
+ box-orient: vertical;
+ box-align: stretch;
+ /* Modern browsers */
+ display: flex;
+ flex-direction: column;
+ align-items: stretch;
+}
+@media (max-width: 540px) {
+ div.output_area {
+ /* Old browsers */
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-box-align: stretch;
+ display: -moz-box;
+ -moz-box-orient: vertical;
+ -moz-box-align: stretch;
+ display: box;
+ box-orient: vertical;
+ box-align: stretch;
+ /* Modern browsers */
+ display: flex;
+ flex-direction: column;
+ align-items: stretch;
+ }
+}
+div.output_area pre {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ vertical-align: baseline;
+ color: black;
+ background-color: transparent;
+ border-radius: 0;
+}
+/* This class is for the output subarea inside the output_area and after
+ the prompt div. */
+div.output_subarea {
+ overflow-x: auto;
+ padding: 0.4em;
+ /* Old browsers */
+ -webkit-box-flex: 1;
+ -moz-box-flex: 1;
+ box-flex: 1;
+ /* Modern browsers */
+ flex: 1;
+ max-width: calc(100% - 14ex);
+}
+div.output_scroll div.output_subarea {
+ overflow-x: visible;
+}
+/* The rest of the output_* classes are for special styling of the different
+ output types */
+/* all text output has this class: */
+div.output_text {
+ text-align: left;
+ color: #000;
+ /* This has to match that of the the CodeMirror class line-height below */
+ line-height: 1.21429em;
+}
+/* stdout/stderr are 'text' as well as 'stream', but execute_result/error are *not* streams */
+div.output_stderr {
+ background: #fdd;
+ /* very light red background for stderr */
+}
+div.output_latex {
+ text-align: left;
+}
+/* Empty output_javascript divs should have no height */
+div.output_javascript:empty {
+ padding: 0;
+}
+.js-error {
+ color: darkred;
+}
+/* raw_input styles */
+div.raw_input_container {
+ line-height: 1.21429em;
+ padding-top: 5px;
+}
+pre.raw_input_prompt {
+ /* nothing needed here. */
+}
+input.raw_input {
+ font-family: monospace;
+ font-size: inherit;
+ color: inherit;
+ width: auto;
+ /* make sure input baseline aligns with prompt */
+ vertical-align: baseline;
+ /* padding + margin = 0.5em between prompt and cursor */
+ padding: 0em 0.25em;
+ margin: 0em 0.25em;
+}
+input.raw_input:focus {
+ box-shadow: none;
+}
+p.p-space {
+ margin-bottom: 10px;
+}
+div.output_unrecognized {
+ padding: 5px;
+ font-weight: bold;
+ color: red;
+}
+div.output_unrecognized a {
+ color: inherit;
+ text-decoration: none;
+}
+div.output_unrecognized a:hover {
+ color: inherit;
+ text-decoration: none;
+}
+.rendered_html {
+ color: #000;
+ /* any extras will just be numbers: */
+}
+.rendered_html em {
+ font-style: italic;
+}
+.rendered_html strong {
+ font-weight: bold;
+}
+.rendered_html u {
+ text-decoration: underline;
+}
+.rendered_html :link {
+ text-decoration: underline;
+}
+.rendered_html :visited {
+ text-decoration: underline;
+}
+.rendered_html h1 {
+ font-size: 185.7%;
+ margin: 1.08em 0 0 0;
+ font-weight: bold;
+ line-height: 1.0;
+}
+.rendered_html h2 {
+ font-size: 157.1%;
+ margin: 1.27em 0 0 0;
+ font-weight: bold;
+ line-height: 1.0;
+}
+.rendered_html h3 {
+ font-size: 128.6%;
+ margin: 1.55em 0 0 0;
+ font-weight: bold;
+ line-height: 1.0;
+}
+.rendered_html h4 {
+ font-size: 100%;
+ margin: 2em 0 0 0;
+ font-weight: bold;
+ line-height: 1.0;
+}
+.rendered_html h5 {
+ font-size: 100%;
+ margin: 2em 0 0 0;
+ font-weight: bold;
+ line-height: 1.0;
+ font-style: italic;
+}
+.rendered_html h6 {
+ font-size: 100%;
+ margin: 2em 0 0 0;
+ font-weight: bold;
+ line-height: 1.0;
+ font-style: italic;
+}
+.rendered_html h1:first-child {
+ margin-top: 0.538em;
+}
+.rendered_html h2:first-child {
+ margin-top: 0.636em;
+}
+.rendered_html h3:first-child {
+ margin-top: 0.777em;
+}
+.rendered_html h4:first-child {
+ margin-top: 1em;
+}
+.rendered_html h5:first-child {
+ margin-top: 1em;
+}
+.rendered_html h6:first-child {
+ margin-top: 1em;
+}
+.rendered_html ul {
+ list-style: disc;
+ margin: 0em 2em;
+ padding-left: 0px;
+}
+.rendered_html ul ul {
+ list-style: square;
+ margin: 0em 2em;
+}
+.rendered_html ul ul ul {
+ list-style: circle;
+ margin: 0em 2em;
+}
+.rendered_html ol {
+ list-style: decimal;
+ margin: 0em 2em;
+ padding-left: 0px;
+}
+.rendered_html ol ol {
+ list-style: upper-alpha;
+ margin: 0em 2em;
+}
+.rendered_html ol ol ol {
+ list-style: lower-alpha;
+ margin: 0em 2em;
+}
+.rendered_html ol ol ol ol {
+ list-style: lower-roman;
+ margin: 0em 2em;
+}
+.rendered_html ol ol ol ol ol {
+ list-style: decimal;
+ margin: 0em 2em;
+}
+.rendered_html * + ul {
+ margin-top: 1em;
+}
+.rendered_html * + ol {
+ margin-top: 1em;
+}
+.rendered_html hr {
+ color: black;
+ background-color: black;
+}
+.rendered_html pre {
+ margin: 1em 2em;
+}
+.rendered_html pre,
+.rendered_html code {
+ border: 0;
+ background-color: #fff;
+ color: #000;
+ font-size: 100%;
+ padding: 0px;
+}
+.rendered_html blockquote {
+ margin: 1em 2em;
+}
+.rendered_html table {
+ margin-left: auto;
+ margin-right: auto;
+ border: 1px solid black;
+ border-collapse: collapse;
+}
+.rendered_html tr,
+.rendered_html th,
+.rendered_html td {
+ border: 1px solid black;
+ border-collapse: collapse;
+ margin: 1em 2em;
+}
+.rendered_html td,
+.rendered_html th {
+ text-align: left;
+ vertical-align: middle;
+ padding: 4px;
+}
+.rendered_html th {
+ font-weight: bold;
+}
+.rendered_html * + table {
+ margin-top: 1em;
+}
+.rendered_html p {
+ text-align: left;
+}
+.rendered_html * + p {
+ margin-top: 1em;
+}
+.rendered_html img {
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+}
+.rendered_html * + img {
+ margin-top: 1em;
+}
+.rendered_html img,
+.rendered_html svg {
+ max-width: 100%;
+ height: auto;
+}
+.rendered_html img.unconfined,
+.rendered_html svg.unconfined {
+ max-width: none;
+}
+div.text_cell {
+ /* Old browsers */
+ display: -webkit-box;
+ -webkit-box-orient: horizontal;
+ -webkit-box-align: stretch;
+ display: -moz-box;
+ -moz-box-orient: horizontal;
+ -moz-box-align: stretch;
+ display: box;
+ box-orient: horizontal;
+ box-align: stretch;
+ /* Modern browsers */
+ display: flex;
+ flex-direction: row;
+ align-items: stretch;
+}
+@media (max-width: 540px) {
+ div.text_cell > div.prompt {
+ display: none;
+ }
+}
+div.text_cell_render {
+ /*font-family: "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;*/
+ outline: none;
+ resize: none;
+ width: inherit;
+ border-style: none;
+ padding: 0.5em 0.5em 0.5em 0.4em;
+ color: #000;
+ box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+}
+a.anchor-link:link {
+ text-decoration: none;
+ padding: 0px 20px;
+ visibility: hidden;
+}
+h1:hover .anchor-link,
+h2:hover .anchor-link,
+h3:hover .anchor-link,
+h4:hover .anchor-link,
+h5:hover .anchor-link,
+h6:hover .anchor-link {
+ visibility: visible;
+}
+.text_cell.rendered .input_area {
+ display: none;
+}
+.text_cell.rendered .rendered_html {
+ overflow-x: auto;
+ overflow-y: hidden;
+}
+.text_cell.unrendered .text_cell_render {
+ display: none;
+}
+.cm-header-1,
+.cm-header-2,
+.cm-header-3,
+.cm-header-4,
+.cm-header-5,
+.cm-header-6 {
+ font-weight: bold;
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+}
+.cm-header-1 {
+ font-size: 185.7%;
+}
+.cm-header-2 {
+ font-size: 157.1%;
+}
+.cm-header-3 {
+ font-size: 128.6%;
+}
+.cm-header-4 {
+ font-size: 110%;
+}
+.cm-header-5 {
+ font-size: 100%;
+ font-style: italic;
+}
+.cm-header-6 {
+ font-size: 100%;
+ font-style: italic;
+}
+/*!
+*
+* IPython notebook webapp
+*
+*/
+@media (max-width: 767px) {
+ .notebook_app {
+ padding-left: 0px;
+ padding-right: 0px;
+ }
+}
+#ipython-main-app {
+ box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ height: 100%;
+}
+div#notebook_panel {
+ margin: 0px;
+ padding: 0px;
+ box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ height: 100%;
+}
+div#notebook {
+ font-size: 14px;
+ line-height: 20px;
+ overflow-y: hidden;
+ overflow-x: auto;
+ width: 100%;
+ /* This spaces the page away from the edge of the notebook area */
+ padding-top: 20px;
+ margin: 0px;
+ outline: none;
+ box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ min-height: 100%;
+}
+@media not print {
+ #notebook-container {
+ padding: 15px;
+ background-color: #fff;
+ min-height: 0;
+ -webkit-box-shadow: 0px 0px 12px 1px rgba(87, 87, 87, 0.2);
+ box-shadow: 0px 0px 12px 1px rgba(87, 87, 87, 0.2);
+ }
+}
+@media print {
+ #notebook-container {
+ width: 100%;
+ }
+}
+div.ui-widget-content {
+ border: 1px solid #ababab;
+ outline: none;
+}
+pre.dialog {
+ background-color: #f7f7f7;
+ border: 1px solid #ddd;
+ border-radius: 2px;
+ padding: 0.4em;
+ padding-left: 2em;
+}
+p.dialog {
+ padding: 0.2em;
+}
+/* Word-wrap output correctly. This is the CSS3 spelling, though Firefox seems
+ to not honor it correctly. Webkit browsers (Chrome, rekonq, Safari) do.
+ */
+pre,
+code,
+kbd,
+samp {
+ white-space: pre-wrap;
+}
+#fonttest {
+ font-family: monospace;
+}
+p {
+ margin-bottom: 0;
+}
+.end_space {
+ min-height: 100px;
+ transition: height .2s ease;
+}
+.notebook_app > #header {
+ -webkit-box-shadow: 0px 0px 12px 1px rgba(87, 87, 87, 0.2);
+ box-shadow: 0px 0px 12px 1px rgba(87, 87, 87, 0.2);
+}
+@media not print {
+ .notebook_app {
+ background-color: #EEE;
+ }
+}
+kbd {
+ border-style: solid;
+ border-width: 1px;
+ box-shadow: none;
+ margin: 2px;
+ padding-left: 2px;
+ padding-right: 2px;
+ padding-top: 1px;
+ padding-bottom: 1px;
+}
+/* CSS for the cell toolbar */
+.celltoolbar {
+ border: thin solid #CFCFCF;
+ border-bottom: none;
+ background: #EEE;
+ border-radius: 2px 2px 0px 0px;
+ width: 100%;
+ height: 29px;
+ padding-right: 4px;
+ /* Old browsers */
+ display: -webkit-box;
+ -webkit-box-orient: horizontal;
+ -webkit-box-align: stretch;
+ display: -moz-box;
+ -moz-box-orient: horizontal;
+ -moz-box-align: stretch;
+ display: box;
+ box-orient: horizontal;
+ box-align: stretch;
+ /* Modern browsers */
+ display: flex;
+ flex-direction: row;
+ align-items: stretch;
+ /* Old browsers */
+ -webkit-box-pack: end;
+ -moz-box-pack: end;
+ box-pack: end;
+ /* Modern browsers */
+ justify-content: flex-end;
+ display: -webkit-flex;
+}
+@media print {
+ .celltoolbar {
+ display: none;
+ }
+}
+.ctb_hideshow {
+ display: none;
+ vertical-align: bottom;
+}
+/* ctb_show is added to the ctb_hideshow div to show the cell toolbar.
+ Cell toolbars are only shown when the ctb_global_show class is also set.
+*/
+.ctb_global_show .ctb_show.ctb_hideshow {
+ display: block;
+}
+.ctb_global_show .ctb_show + .input_area,
+.ctb_global_show .ctb_show + div.text_cell_input,
+.ctb_global_show .ctb_show ~ div.text_cell_render {
+ border-top-right-radius: 0px;
+ border-top-left-radius: 0px;
+}
+.ctb_global_show .ctb_show ~ div.text_cell_render {
+ border: 1px solid #cfcfcf;
+}
+.celltoolbar {
+ font-size: 87%;
+ padding-top: 3px;
+}
+.celltoolbar select {
+ display: block;
+ width: 100%;
+ height: 32px;
+ padding: 6px 12px;
+ font-size: 13px;
+ line-height: 1.42857143;
+ color: #555555;
+ background-color: #fff;
+ background-image: none;
+ border: 1px solid #ccc;
+ border-radius: 2px;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+ -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+ transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+ height: 30px;
+ padding: 5px 10px;
+ font-size: 12px;
+ line-height: 1.5;
+ border-radius: 1px;
+ width: inherit;
+ font-size: inherit;
+ height: 22px;
+ padding: 0px;
+ display: inline-block;
+}
+.celltoolbar select:focus {
+ border-color: #66afe9;
+ outline: 0;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
+ box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
+}
+.celltoolbar select::-moz-placeholder {
+ color: #999;
+ opacity: 1;
+}
+.celltoolbar select:-ms-input-placeholder {
+ color: #999;
+}
+.celltoolbar select::-webkit-input-placeholder {
+ color: #999;
+}
+.celltoolbar select::-ms-expand {
+ border: 0;
+ background-color: transparent;
+}
+.celltoolbar select[disabled],
+.celltoolbar select[readonly],
+fieldset[disabled] .celltoolbar select {
+ background-color: #eeeeee;
+ opacity: 1;
+}
+.celltoolbar select[disabled],
+fieldset[disabled] .celltoolbar select {
+ cursor: not-allowed;
+}
+textarea.celltoolbar select {
+ height: auto;
+}
+select.celltoolbar select {
+ height: 30px;
+ line-height: 30px;
+}
+textarea.celltoolbar select,
+select[multiple].celltoolbar select {
+ height: auto;
+}
+.celltoolbar label {
+ margin-left: 5px;
+ margin-right: 5px;
+}
+.completions {
+ position: absolute;
+ z-index: 110;
+ overflow: hidden;
+ border: 1px solid #ababab;
+ border-radius: 2px;
+ -webkit-box-shadow: 0px 6px 10px -1px #adadad;
+ box-shadow: 0px 6px 10px -1px #adadad;
+ line-height: 1;
+}
+.completions select {
+ background: white;
+ outline: none;
+ border: none;
+ padding: 0px;
+ margin: 0px;
+ overflow: auto;
+ font-family: monospace;
+ font-size: 110%;
+ color: #000;
+ width: auto;
+}
+.completions select option.context {
+ color: #286090;
+}
+#kernel_logo_widget {
+ float: right !important;
+ float: right;
+}
+#kernel_logo_widget .current_kernel_logo {
+ display: none;
+ margin-top: -1px;
+ margin-bottom: -1px;
+ width: 32px;
+ height: 32px;
+}
+#menubar {
+ box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ margin-top: 1px;
+}
+#menubar .navbar {
+ border-top: 1px;
+ border-radius: 0px 0px 2px 2px;
+ margin-bottom: 0px;
+}
+#menubar .navbar-toggle {
+ float: left;
+ padding-top: 7px;
+ padding-bottom: 7px;
+ border: none;
+}
+#menubar .navbar-collapse {
+ clear: left;
+}
+.nav-wrapper {
+ border-bottom: 1px solid #e7e7e7;
+}
+i.menu-icon {
+ padding-top: 4px;
+}
+ul#help_menu li a {
+ overflow: hidden;
+ padding-right: 2.2em;
+}
+ul#help_menu li a i {
+ margin-right: -1.2em;
+}
+.dropdown-submenu {
+ position: relative;
+}
+.dropdown-submenu > .dropdown-menu {
+ top: 0;
+ left: 100%;
+ margin-top: -6px;
+ margin-left: -1px;
+}
+.dropdown-submenu:hover > .dropdown-menu {
+ display: block;
+}
+.dropdown-submenu > a:after {
+ display: inline-block;
+ font: normal normal normal 14px/1 FontAwesome;
+ font-size: inherit;
+ text-rendering: auto;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ display: block;
+ content: "\f0da";
+ float: right;
+ color: #333333;
+ margin-top: 2px;
+ margin-right: -10px;
+}
+.dropdown-submenu > a:after.pull-left {
+ margin-right: .3em;
+}
+.dropdown-submenu > a:after.pull-right {
+ margin-left: .3em;
+}
+.dropdown-submenu:hover > a:after {
+ color: #262626;
+}
+.dropdown-submenu.pull-left {
+ float: none;
+}
+.dropdown-submenu.pull-left > .dropdown-menu {
+ left: -100%;
+ margin-left: 10px;
+}
+#notification_area {
+ float: right !important;
+ float: right;
+ z-index: 10;
+}
+.indicator_area {
+ float: right !important;
+ float: right;
+ color: #777;
+ margin-left: 5px;
+ margin-right: 5px;
+ width: 11px;
+ z-index: 10;
+ text-align: center;
+ width: auto;
+}
+#kernel_indicator {
+ float: right !important;
+ float: right;
+ color: #777;
+ margin-left: 5px;
+ margin-right: 5px;
+ width: 11px;
+ z-index: 10;
+ text-align: center;
+ width: auto;
+ border-left: 1px solid;
+}
+#kernel_indicator .kernel_indicator_name {
+ padding-left: 5px;
+ padding-right: 5px;
+}
+#modal_indicator {
+ float: right !important;
+ float: right;
+ color: #777;
+ margin-left: 5px;
+ margin-right: 5px;
+ width: 11px;
+ z-index: 10;
+ text-align: center;
+ width: auto;
+}
+#readonly-indicator {
+ float: right !important;
+ float: right;
+ color: #777;
+ margin-left: 5px;
+ margin-right: 5px;
+ width: 11px;
+ z-index: 10;
+ text-align: center;
+ width: auto;
+ margin-top: 2px;
+ margin-bottom: 0px;
+ margin-left: 0px;
+ margin-right: 0px;
+ display: none;
+}
+.modal_indicator:before {
+ width: 1.28571429em;
+ text-align: center;
+}
+.edit_mode .modal_indicator:before {
+ display: inline-block;
+ font: normal normal normal 14px/1 FontAwesome;
+ font-size: inherit;
+ text-rendering: auto;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ content: "\f040";
+}
+.edit_mode .modal_indicator:before.pull-left {
+ margin-right: .3em;
+}
+.edit_mode .modal_indicator:before.pull-right {
+ margin-left: .3em;
+}
+.command_mode .modal_indicator:before {
+ display: inline-block;
+ font: normal normal normal 14px/1 FontAwesome;
+ font-size: inherit;
+ text-rendering: auto;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ content: ' ';
+}
+.command_mode .modal_indicator:before.pull-left {
+ margin-right: .3em;
+}
+.command_mode .modal_indicator:before.pull-right {
+ margin-left: .3em;
+}
+.kernel_idle_icon:before {
+ display: inline-block;
+ font: normal normal normal 14px/1 FontAwesome;
+ font-size: inherit;
+ text-rendering: auto;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ content: "\f10c";
+}
+.kernel_idle_icon:before.pull-left {
+ margin-right: .3em;
+}
+.kernel_idle_icon:before.pull-right {
+ margin-left: .3em;
+}
+.kernel_busy_icon:before {
+ display: inline-block;
+ font: normal normal normal 14px/1 FontAwesome;
+ font-size: inherit;
+ text-rendering: auto;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ content: "\f111";
+}
+.kernel_busy_icon:before.pull-left {
+ margin-right: .3em;
+}
+.kernel_busy_icon:before.pull-right {
+ margin-left: .3em;
+}
+.kernel_dead_icon:before {
+ display: inline-block;
+ font: normal normal normal 14px/1 FontAwesome;
+ font-size: inherit;
+ text-rendering: auto;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ content: "\f1e2";
+}
+.kernel_dead_icon:before.pull-left {
+ margin-right: .3em;
+}
+.kernel_dead_icon:before.pull-right {
+ margin-left: .3em;
+}
+.kernel_disconnected_icon:before {
+ display: inline-block;
+ font: normal normal normal 14px/1 FontAwesome;
+ font-size: inherit;
+ text-rendering: auto;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ content: "\f127";
+}
+.kernel_disconnected_icon:before.pull-left {
+ margin-right: .3em;
+}
+.kernel_disconnected_icon:before.pull-right {
+ margin-left: .3em;
+}
+.notification_widget {
+ color: #777;
+ z-index: 10;
+ background: rgba(240, 240, 240, 0.5);
+ margin-right: 4px;
+ color: #333;
+ background-color: #fff;
+ border-color: #ccc;
+}
+.notification_widget:focus,
+.notification_widget.focus {
+ color: #333;
+ background-color: #e6e6e6;
+ border-color: #8c8c8c;
+}
+.notification_widget:hover {
+ color: #333;
+ background-color: #e6e6e6;
+ border-color: #adadad;
+}
+.notification_widget:active,
+.notification_widget.active,
+.open > .dropdown-toggle.notification_widget {
+ color: #333;
+ background-color: #e6e6e6;
+ border-color: #adadad;
+}
+.notification_widget:active:hover,
+.notification_widget.active:hover,
+.open > .dropdown-toggle.notification_widget:hover,
+.notification_widget:active:focus,
+.notification_widget.active:focus,
+.open > .dropdown-toggle.notification_widget:focus,
+.notification_widget:active.focus,
+.notification_widget.active.focus,
+.open > .dropdown-toggle.notification_widget.focus {
+ color: #333;
+ background-color: #d4d4d4;
+ border-color: #8c8c8c;
+}
+.notification_widget:active,
+.notification_widget.active,
+.open > .dropdown-toggle.notification_widget {
+ background-image: none;
+}
+.notification_widget.disabled:hover,
+.notification_widget[disabled]:hover,
+fieldset[disabled] .notification_widget:hover,
+.notification_widget.disabled:focus,
+.notification_widget[disabled]:focus,
+fieldset[disabled] .notification_widget:focus,
+.notification_widget.disabled.focus,
+.notification_widget[disabled].focus,
+fieldset[disabled] .notification_widget.focus {
+ background-color: #fff;
+ border-color: #ccc;
+}
+.notification_widget .badge {
+ color: #fff;
+ background-color: #333;
+}
+.notification_widget.warning {
+ color: #fff;
+ background-color: #f0ad4e;
+ border-color: #eea236;
+}
+.notification_widget.warning:focus,
+.notification_widget.warning.focus {
+ color: #fff;
+ background-color: #ec971f;
+ border-color: #985f0d;
+}
+.notification_widget.warning:hover {
+ color: #fff;
+ background-color: #ec971f;
+ border-color: #d58512;
+}
+.notification_widget.warning:active,
+.notification_widget.warning.active,
+.open > .dropdown-toggle.notification_widget.warning {
+ color: #fff;
+ background-color: #ec971f;
+ border-color: #d58512;
+}
+.notification_widget.warning:active:hover,
+.notification_widget.warning.active:hover,
+.open > .dropdown-toggle.notification_widget.warning:hover,
+.notification_widget.warning:active:focus,
+.notification_widget.warning.active:focus,
+.open > .dropdown-toggle.notification_widget.warning:focus,
+.notification_widget.warning:active.focus,
+.notification_widget.warning.active.focus,
+.open > .dropdown-toggle.notification_widget.warning.focus {
+ color: #fff;
+ background-color: #d58512;
+ border-color: #985f0d;
+}
+.notification_widget.warning:active,
+.notification_widget.warning.active,
+.open > .dropdown-toggle.notification_widget.warning {
+ background-image: none;
+}
+.notification_widget.warning.disabled:hover,
+.notification_widget.warning[disabled]:hover,
+fieldset[disabled] .notification_widget.warning:hover,
+.notification_widget.warning.disabled:focus,
+.notification_widget.warning[disabled]:focus,
+fieldset[disabled] .notification_widget.warning:focus,
+.notification_widget.warning.disabled.focus,
+.notification_widget.warning[disabled].focus,
+fieldset[disabled] .notification_widget.warning.focus {
+ background-color: #f0ad4e;
+ border-color: #eea236;
+}
+.notification_widget.warning .badge {
+ color: #f0ad4e;
+ background-color: #fff;
+}
+.notification_widget.success {
+ color: #fff;
+ background-color: #5cb85c;
+ border-color: #4cae4c;
+}
+.notification_widget.success:focus,
+.notification_widget.success.focus {
+ color: #fff;
+ background-color: #449d44;
+ border-color: #255625;
+}
+.notification_widget.success:hover {
+ color: #fff;
+ background-color: #449d44;
+ border-color: #398439;
+}
+.notification_widget.success:active,
+.notification_widget.success.active,
+.open > .dropdown-toggle.notification_widget.success {
+ color: #fff;
+ background-color: #449d44;
+ border-color: #398439;
+}
+.notification_widget.success:active:hover,
+.notification_widget.success.active:hover,
+.open > .dropdown-toggle.notification_widget.success:hover,
+.notification_widget.success:active:focus,
+.notification_widget.success.active:focus,
+.open > .dropdown-toggle.notification_widget.success:focus,
+.notification_widget.success:active.focus,
+.notification_widget.success.active.focus,
+.open > .dropdown-toggle.notification_widget.success.focus {
+ color: #fff;
+ background-color: #398439;
+ border-color: #255625;
+}
+.notification_widget.success:active,
+.notification_widget.success.active,
+.open > .dropdown-toggle.notification_widget.success {
+ background-image: none;
+}
+.notification_widget.success.disabled:hover,
+.notification_widget.success[disabled]:hover,
+fieldset[disabled] .notification_widget.success:hover,
+.notification_widget.success.disabled:focus,
+.notification_widget.success[disabled]:focus,
+fieldset[disabled] .notification_widget.success:focus,
+.notification_widget.success.disabled.focus,
+.notification_widget.success[disabled].focus,
+fieldset[disabled] .notification_widget.success.focus {
+ background-color: #5cb85c;
+ border-color: #4cae4c;
+}
+.notification_widget.success .badge {
+ color: #5cb85c;
+ background-color: #fff;
+}
+.notification_widget.info {
+ color: #fff;
+ background-color: #5bc0de;
+ border-color: #46b8da;
+}
+.notification_widget.info:focus,
+.notification_widget.info.focus {
+ color: #fff;
+ background-color: #31b0d5;
+ border-color: #1b6d85;
+}
+.notification_widget.info:hover {
+ color: #fff;
+ background-color: #31b0d5;
+ border-color: #269abc;
+}
+.notification_widget.info:active,
+.notification_widget.info.active,
+.open > .dropdown-toggle.notification_widget.info {
+ color: #fff;
+ background-color: #31b0d5;
+ border-color: #269abc;
+}
+.notification_widget.info:active:hover,
+.notification_widget.info.active:hover,
+.open > .dropdown-toggle.notification_widget.info:hover,
+.notification_widget.info:active:focus,
+.notification_widget.info.active:focus,
+.open > .dropdown-toggle.notification_widget.info:focus,
+.notification_widget.info:active.focus,
+.notification_widget.info.active.focus,
+.open > .dropdown-toggle.notification_widget.info.focus {
+ color: #fff;
+ background-color: #269abc;
+ border-color: #1b6d85;
+}
+.notification_widget.info:active,
+.notification_widget.info.active,
+.open > .dropdown-toggle.notification_widget.info {
+ background-image: none;
+}
+.notification_widget.info.disabled:hover,
+.notification_widget.info[disabled]:hover,
+fieldset[disabled] .notification_widget.info:hover,
+.notification_widget.info.disabled:focus,
+.notification_widget.info[disabled]:focus,
+fieldset[disabled] .notification_widget.info:focus,
+.notification_widget.info.disabled.focus,
+.notification_widget.info[disabled].focus,
+fieldset[disabled] .notification_widget.info.focus {
+ background-color: #5bc0de;
+ border-color: #46b8da;
+}
+.notification_widget.info .badge {
+ color: #5bc0de;
+ background-color: #fff;
+}
+.notification_widget.danger {
+ color: #fff;
+ background-color: #d9534f;
+ border-color: #d43f3a;
+}
+.notification_widget.danger:focus,
+.notification_widget.danger.focus {
+ color: #fff;
+ background-color: #c9302c;
+ border-color: #761c19;
+}
+.notification_widget.danger:hover {
+ color: #fff;
+ background-color: #c9302c;
+ border-color: #ac2925;
+}
+.notification_widget.danger:active,
+.notification_widget.danger.active,
+.open > .dropdown-toggle.notification_widget.danger {
+ color: #fff;
+ background-color: #c9302c;
+ border-color: #ac2925;
+}
+.notification_widget.danger:active:hover,
+.notification_widget.danger.active:hover,
+.open > .dropdown-toggle.notification_widget.danger:hover,
+.notification_widget.danger:active:focus,
+.notification_widget.danger.active:focus,
+.open > .dropdown-toggle.notification_widget.danger:focus,
+.notification_widget.danger:active.focus,
+.notification_widget.danger.active.focus,
+.open > .dropdown-toggle.notification_widget.danger.focus {
+ color: #fff;
+ background-color: #ac2925;
+ border-color: #761c19;
+}
+.notification_widget.danger:active,
+.notification_widget.danger.active,
+.open > .dropdown-toggle.notification_widget.danger {
+ background-image: none;
+}
+.notification_widget.danger.disabled:hover,
+.notification_widget.danger[disabled]:hover,
+fieldset[disabled] .notification_widget.danger:hover,
+.notification_widget.danger.disabled:focus,
+.notification_widget.danger[disabled]:focus,
+fieldset[disabled] .notification_widget.danger:focus,
+.notification_widget.danger.disabled.focus,
+.notification_widget.danger[disabled].focus,
+fieldset[disabled] .notification_widget.danger.focus {
+ background-color: #d9534f;
+ border-color: #d43f3a;
+}
+.notification_widget.danger .badge {
+ color: #d9534f;
+ background-color: #fff;
+}
+div#pager {
+ background-color: #fff;
+ font-size: 14px;
+ line-height: 20px;
+ overflow: hidden;
+ display: none;
+ position: fixed;
+ bottom: 0px;
+ width: 100%;
+ max-height: 50%;
+ padding-top: 8px;
+ -webkit-box-shadow: 0px 0px 12px 1px rgba(87, 87, 87, 0.2);
+ box-shadow: 0px 0px 12px 1px rgba(87, 87, 87, 0.2);
+ /* Display over codemirror */
+ z-index: 100;
+ /* Hack which prevents jquery ui resizable from changing top. */
+ top: auto !important;
+}
+div#pager pre {
+ line-height: 1.21429em;
+ color: #000;
+ background-color: #f7f7f7;
+ padding: 0.4em;
+}
+div#pager #pager-button-area {
+ position: absolute;
+ top: 8px;
+ right: 20px;
+}
+div#pager #pager-contents {
+ position: relative;
+ overflow: auto;
+ width: 100%;
+ height: 100%;
+}
+div#pager #pager-contents #pager-container {
+ position: relative;
+ padding: 15px 0px;
+ box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+}
+div#pager .ui-resizable-handle {
+ top: 0px;
+ height: 8px;
+ background: #f7f7f7;
+ border-top: 1px solid #cfcfcf;
+ border-bottom: 1px solid #cfcfcf;
+ /* This injects handle bars (a short, wide = symbol) for
+ the resize handle. */
+}
+div#pager .ui-resizable-handle::after {
+ content: '';
+ top: 2px;
+ left: 50%;
+ height: 3px;
+ width: 30px;
+ margin-left: -15px;
+ position: absolute;
+ border-top: 1px solid #cfcfcf;
+}
+.quickhelp {
+ /* Old browsers */
+ display: -webkit-box;
+ -webkit-box-orient: horizontal;
+ -webkit-box-align: stretch;
+ display: -moz-box;
+ -moz-box-orient: horizontal;
+ -moz-box-align: stretch;
+ display: box;
+ box-orient: horizontal;
+ box-align: stretch;
+ /* Modern browsers */
+ display: flex;
+ flex-direction: row;
+ align-items: stretch;
+ line-height: 1.8em;
+}
+.shortcut_key {
+ display: inline-block;
+ width: 21ex;
+ text-align: right;
+ font-family: monospace;
+}
+.shortcut_descr {
+ display: inline-block;
+ /* Old browsers */
+ -webkit-box-flex: 1;
+ -moz-box-flex: 1;
+ box-flex: 1;
+ /* Modern browsers */
+ flex: 1;
+}
+span.save_widget {
+ margin-top: 6px;
+}
+span.save_widget span.filename {
+ height: 1em;
+ line-height: 1em;
+ padding: 3px;
+ margin-left: 16px;
+ border: none;
+ font-size: 146.5%;
+ border-radius: 2px;
+}
+span.save_widget span.filename:hover {
+ background-color: #e6e6e6;
+}
+span.checkpoint_status,
+span.autosave_status {
+ font-size: small;
+}
+@media (max-width: 767px) {
+ span.save_widget {
+ font-size: small;
+ }
+ span.checkpoint_status,
+ span.autosave_status {
+ display: none;
+ }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+ span.checkpoint_status {
+ display: none;
+ }
+ span.autosave_status {
+ font-size: x-small;
+ }
+}
+.toolbar {
+ padding: 0px;
+ margin-left: -5px;
+ margin-top: 2px;
+ margin-bottom: 5px;
+ box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+}
+.toolbar select,
+.toolbar label {
+ width: auto;
+ vertical-align: middle;
+ margin-right: 2px;
+ margin-bottom: 0px;
+ display: inline;
+ font-size: 92%;
+ margin-left: 0.3em;
+ margin-right: 0.3em;
+ padding: 0px;
+ padding-top: 3px;
+}
+.toolbar .btn {
+ padding: 2px 8px;
+}
+.toolbar .btn-group {
+ margin-top: 0px;
+ margin-left: 5px;
+}
+#maintoolbar {
+ margin-bottom: -3px;
+ margin-top: -8px;
+ border: 0px;
+ min-height: 27px;
+ margin-left: 0px;
+ padding-top: 11px;
+ padding-bottom: 3px;
+}
+#maintoolbar .navbar-text {
+ float: none;
+ vertical-align: middle;
+ text-align: right;
+ margin-left: 5px;
+ margin-right: 0px;
+ margin-top: 0px;
+}
+.select-xs {
+ height: 24px;
+}
+.pulse,
+.dropdown-menu > li > a.pulse,
+li.pulse > a.dropdown-toggle,
+li.pulse.open > a.dropdown-toggle {
+ background-color: #F37626;
+ color: white;
+}
+/**
+ * Primary styles
+ *
+ * Author: Jupyter Development Team
+ */
+/** WARNING IF YOU ARE EDITTING THIS FILE, if this is a .css file, It has a lot
+ * of chance of beeing generated from the ../less/[samename].less file, you can
+ * try to get back the less file by reverting somme commit in history
+ **/
+/*
+ * We'll try to get something pretty, so we
+ * have some strange css to have the scroll bar on
+ * the left with fix button on the top right of the tooltip
+ */
+@-moz-keyframes fadeOut {
+ from {
+ opacity: 1;
+ }
+ to {
+ opacity: 0;
+ }
+}
+@-webkit-keyframes fadeOut {
+ from {
+ opacity: 1;
+ }
+ to {
+ opacity: 0;
+ }
+}
+@-moz-keyframes fadeIn {
+ from {
+ opacity: 0;
+ }
+ to {
+ opacity: 1;
+ }
+}
+@-webkit-keyframes fadeIn {
+ from {
+ opacity: 0;
+ }
+ to {
+ opacity: 1;
+ }
+}
+/*properties of tooltip after "expand"*/
+.bigtooltip {
+ overflow: auto;
+ height: 200px;
+ -webkit-transition-property: height;
+ -webkit-transition-duration: 500ms;
+ -moz-transition-property: height;
+ -moz-transition-duration: 500ms;
+ transition-property: height;
+ transition-duration: 500ms;
+}
+/*properties of tooltip before "expand"*/
+.smalltooltip {
+ -webkit-transition-property: height;
+ -webkit-transition-duration: 500ms;
+ -moz-transition-property: height;
+ -moz-transition-duration: 500ms;
+ transition-property: height;
+ transition-duration: 500ms;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ height: 80px;
+}
+.tooltipbuttons {
+ position: absolute;
+ padding-right: 15px;
+ top: 0px;
+ right: 0px;
+}
+.tooltiptext {
+ /*avoid the button to overlap on some docstring*/
+ padding-right: 30px;
+}
+.ipython_tooltip {
+ max-width: 700px;
+ /*fade-in animation when inserted*/
+ -webkit-animation: fadeOut 400ms;
+ -moz-animation: fadeOut 400ms;
+ animation: fadeOut 400ms;
+ -webkit-animation: fadeIn 400ms;
+ -moz-animation: fadeIn 400ms;
+ animation: fadeIn 400ms;
+ vertical-align: middle;
+ background-color: #f7f7f7;
+ overflow: visible;
+ border: #ababab 1px solid;
+ outline: none;
+ padding: 3px;
+ margin: 0px;
+ padding-left: 7px;
+ font-family: monospace;
+ min-height: 50px;
+ -moz-box-shadow: 0px 6px 10px -1px #adadad;
+ -webkit-box-shadow: 0px 6px 10px -1px #adadad;
+ box-shadow: 0px 6px 10px -1px #adadad;
+ border-radius: 2px;
+ position: absolute;
+ z-index: 1000;
+}
+.ipython_tooltip a {
+ float: right;
+}
+.ipython_tooltip .tooltiptext pre {
+ border: 0;
+ border-radius: 0;
+ font-size: 100%;
+ background-color: #f7f7f7;
+}
+.pretooltiparrow {
+ left: 0px;
+ margin: 0px;
+ top: -16px;
+ width: 40px;
+ height: 16px;
+ overflow: hidden;
+ position: absolute;
+}
+.pretooltiparrow:before {
+ background-color: #f7f7f7;
+ border: 1px #ababab solid;
+ z-index: 11;
+ content: "";
+ position: absolute;
+ left: 15px;
+ top: 10px;
+ width: 25px;
+ height: 25px;
+ -webkit-transform: rotate(45deg);
+ -moz-transform: rotate(45deg);
+ -ms-transform: rotate(45deg);
+ -o-transform: rotate(45deg);
+}
+ul.typeahead-list i {
+ margin-left: -10px;
+ width: 18px;
+}
+ul.typeahead-list {
+ max-height: 80vh;
+ overflow: auto;
+}
+ul.typeahead-list > li > a {
+ /** Firefox bug **/
+ /* see https://github.com/jupyter/notebook/issues/559 */
+ white-space: normal;
+}
+.cmd-palette .modal-body {
+ padding: 7px;
+}
+.cmd-palette form {
+ background: white;
+}
+.cmd-palette input {
+ outline: none;
+}
+.no-shortcut {
+ display: none;
+}
+.command-shortcut:before {
+ content: "(command)";
+ padding-right: 3px;
+ color: #777777;
+}
+.edit-shortcut:before {
+ content: "(edit)";
+ padding-right: 3px;
+ color: #777777;
+}
+#find-and-replace #replace-preview .match,
+#find-and-replace #replace-preview .insert {
+ background-color: #BBDEFB;
+ border-color: #90CAF9;
+ border-style: solid;
+ border-width: 1px;
+ border-radius: 0px;
+}
+#find-and-replace #replace-preview .replace .match {
+ background-color: #FFCDD2;
+ border-color: #EF9A9A;
+ border-radius: 0px;
+}
+#find-and-replace #replace-preview .replace .insert {
+ background-color: #C8E6C9;
+ border-color: #A5D6A7;
+ border-radius: 0px;
+}
+#find-and-replace #replace-preview {
+ max-height: 60vh;
+ overflow: auto;
+}
+#find-and-replace #replace-preview pre {
+ padding: 5px 10px;
+}
+.terminal-app {
+ background: #EEE;
+}
+.terminal-app #header {
+ background: #fff;
+ -webkit-box-shadow: 0px 0px 12px 1px rgba(87, 87, 87, 0.2);
+ box-shadow: 0px 0px 12px 1px rgba(87, 87, 87, 0.2);
+}
+.terminal-app .terminal {
+ width: 100%;
+ float: left;
+ font-family: monospace;
+ color: white;
+ background: black;
+ padding: 0.4em;
+ border-radius: 2px;
+ -webkit-box-shadow: 0px 0px 12px 1px rgba(87, 87, 87, 0.4);
+ box-shadow: 0px 0px 12px 1px rgba(87, 87, 87, 0.4);
+}
+.terminal-app .terminal,
+.terminal-app .terminal dummy-screen {
+ line-height: 1em;
+ font-size: 14px;
+}
+.terminal-app .terminal .xterm-rows {
+ padding: 10px;
+}
+.terminal-app .terminal-cursor {
+ color: black;
+ background: white;
+}
+.terminal-app #terminado-container {
+ margin-top: 20px;
+}
+/*# sourceMappingURL=style.min.css.map */
+
+/*!
+*
+* Pygments "default" style with ".highlight" css_class
+*
+*/
+.highlight .hll { background-color: #ffffcc }
+.highlight .c { color: #408080; font-style: italic } /* Comment */
+.highlight .err { border: 1px solid #FF0000 } /* Error */
+.highlight .k { color: #008000; font-weight: bold } /* Keyword */
+.highlight .o { color: #666666 } /* Operator */
+.highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */
+.highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */
+.highlight .cp { color: #BC7A00 } /* Comment.Preproc */
+.highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */
+.highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */
+.highlight .cs { color: #408080; font-style: italic } /* Comment.Special */
+.highlight .gd { color: #A00000 } /* Generic.Deleted */
+.highlight .ge { font-style: italic } /* Generic.Emph */
+.highlight .gr { color: #FF0000 } /* Generic.Error */
+.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
+.highlight .gi { color: #00A000 } /* Generic.Inserted */
+.highlight .go { color: #888888 } /* Generic.Output */
+.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
+.highlight .gs { font-weight: bold } /* Generic.Strong */
+.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
+.highlight .gt { color: #0044DD } /* Generic.Traceback */
+.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
+.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
+.highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
+.highlight .kp { color: #008000 } /* Keyword.Pseudo */
+.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
+.highlight .kt { color: #B00040 } /* Keyword.Type */
+.highlight .m { color: #666666 } /* Literal.Number */
+.highlight .s { color: #BA2121 } /* Literal.String */
+.highlight .na { color: #7D9029 } /* Name.Attribute */
+.highlight .nb { color: #008000 } /* Name.Builtin */
+.highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */
+.highlight .no { color: #880000 } /* Name.Constant */
+.highlight .nd { color: #AA22FF } /* Name.Decorator */
+.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
+.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
+.highlight .nf { color: #0000FF } /* Name.Function */
+.highlight .nl { color: #A0A000 } /* Name.Label */
+.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
+.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
+.highlight .nv { color: #19177C } /* Name.Variable */
+.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
+.highlight .w { color: #bbbbbb } /* Text.Whitespace */
+.highlight .mb { color: #666666 } /* Literal.Number.Bin */
+.highlight .mf { color: #666666 } /* Literal.Number.Float */
+.highlight .mh { color: #666666 } /* Literal.Number.Hex */
+.highlight .mi { color: #666666 } /* Literal.Number.Integer */
+.highlight .mo { color: #666666 } /* Literal.Number.Oct */
+.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */
+.highlight .sc { color: #BA2121 } /* Literal.String.Char */
+.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
+.highlight .s2 { color: #BA2121 } /* Literal.String.Double */
+.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
+.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */
+.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
+.highlight .sx { color: #008000 } /* Literal.String.Other */
+.highlight .sr { color: #BB6688 } /* Literal.String.Regex */
+.highlight .s1 { color: #BA2121 } /* Literal.String.Single */
+.highlight .ss { color: #19177C } /* Literal.String.Symbol */
+.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */
+.highlight .vc { color: #19177C } /* Name.Variable.Class */
+.highlight .vg { color: #19177C } /* Name.Variable.Global */
+.highlight .vi { color: #19177C } /* Name.Variable.Instance */
+.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
\ No newline at end of file
diff --git a/relate/static/css/ipynb.style.min.css b/relate/static/css/ipynb.style.min.css
new file mode 100644
index 0000000000000000000000000000000000000000..4638dd726ce2f3b9c3a6b0c615167fad5403ec26
--- /dev/null
+++ b/relate/static/css/ipynb.style.min.css
@@ -0,0 +1 @@
+div.cell,div.inner_cell{-webkit-box-align:stretch;display:flex}.CodeMirror,.prompt,div.input_area,div.output_text{line-height:1.21429em}.cm-header-5,.cm-header-6,.highlight-comment,.rendered_html em,.rendered_html h5,.rendered_html h6{font-style:italic}.ansibold{font-weight:700}.ansiblack{color:#000}.ansired{color:#8b0000}.ansigreen{color:#006400}.ansiyellow{color:#c4a000}.ansiblue{color:#00008b}.ansipurple{color:#9400d3}.ansicyan{color:#4682b4}.ansigray{color:gray}.ansibgblack{background-color:#000}.ansibgred{background-color:red}.ansibggreen{background-color:green}.ansibgyellow{background-color:#ff0}.ansibgblue{background-color:#00f}.ansibgpurple{background-color:#ff00ff}.ansibgcyan{background-color:#0ff}.ansibggray{background-color:gray}div.cell{-webkit-box-orient:vertical;-moz-box-orient:vertical;-moz-box-align:stretch;box-orient:vertical;box-align:stretch;flex-direction:column;align-items:stretch;border-radius:2px;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;border-width:1px;border-style:solid;border-color:transparent;width:100%;padding:5px;margin:0;outline:0;background:linear-gradient(to right,transparent -40px,transparent 1px,transparent 1px,transparent 100%)}div.inner_cell,div.output_wrapper{-webkit-box-orient:vertical;-moz-box-orient:vertical}div.cell.jupyter-soft-selected{border-left-color:#E3F2FD;border-left-width:1px;padding-left:5px;border-right-color:#E3F2FD;border-right-width:1px;background:#E3F2FD}@media print{div.cell.jupyter-soft-selected{border-color:transparent}}div.cell.selected{border-color:#ababab;border-left-width:0;padding-left:6px;background:linear-gradient(to right,#42A5F5 -40px,#42A5F5 5px,transparent 5px,transparent 100%)}@media print{div.cell.selected{border-color:transparent}}div.cell.selected.jupyter-soft-selected{border-left-width:0;padding-left:6px;background:linear-gradient(to right,#42A5F5 -40px,#42A5F5 7px,#E3F2FD 7px,#E3F2FD 100%)}.edit_mode div.cell.selected{border-color:#66BB6A;border-left-width:0;padding-left:6px;background:linear-gradient(to right,#66BB6A -40px,#66BB6A 5px,transparent 5px,transparent 100%)}@media print{.edit_mode div.cell.selected{border-color:transparent}div.code_cell{page-break-inside:avoid}}.prompt{min-width:14ex;padding:.4em;margin:0;font-family:monospace;text-align:right;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:default}div.inner_cell{min-width:0;-moz-box-align:stretch;box-orient:vertical;box-align:stretch;flex-direction:column;align-items:stretch;-webkit-box-flex:1;-moz-box-flex:1;box-flex:1;flex:1}div.input_area{border:1px solid #cfcfcf;border-radius:2px;background:#f7f7f7}div.prompt:empty{padding-top:0;padding-bottom:0}div.unrecognized_cell{padding:5px 5px 5px 0;-webkit-box-orient:horizontal;-webkit-box-align:stretch;-moz-box-orient:horizontal;-moz-box-align:stretch;box-orient:horizontal;box-align:stretch;display:flex;flex-direction:row;align-items:stretch}div.unrecognized_cell .inner_cell{border-radius:2px;padding:5px;font-weight:700;color:red;border:1px solid #cfcfcf;background:#eaeaea}div.unrecognized_cell .inner_cell a,div.unrecognized_cell .inner_cell a:hover{color:inherit;text-decoration:none}@media (max-width:540px){.prompt{text-align:left}div.unrecognized_cell>div.prompt{display:none}}div.input,div.output_wrapper{-webkit-box-align:stretch;display:flex}div.input{page-break-inside:avoid;-webkit-box-orient:horizontal;-moz-box-orient:horizontal;-moz-box-align:stretch;box-orient:horizontal;box-align:stretch;flex-direction:row;align-items:stretch}@media (max-width:540px){div.input{-webkit-box-orient:vertical;-webkit-box-align:stretch;-moz-box-orient:vertical;-moz-box-align:stretch;box-orient:vertical;box-align:stretch;display:flex;flex-direction:column;align-items:stretch}}div.input_prompt{color:#303F9F;border-top:1px solid transparent}div.input_area>div.highlight{margin:.4em;border:none;padding:0;background-color:transparent}div.input_area>div.highlight>pre{margin:0;border:none;padding:0;background-color:transparent}.CodeMirror{font-size:14px;height:auto;background:0 0}.CodeMirror-scroll{overflow-y:hidden;overflow-x:auto}.CodeMirror-lines{padding:.4em}.CodeMirror-linenumber{padding:0 8px 0 4px}.CodeMirror-gutters{border-bottom-left-radius:2px;border-top-left-radius:2px}.CodeMirror pre{padding:0;border:0;border-radius:0}.highlight-base,.highlight-variable{color:#000}.highlight-variable-2{color:#1a1a1a}.highlight-variable-3{color:#333}.highlight-string{color:#BA2121}.highlight-comment{color:#408080}.highlight-number{color:#080}.highlight-atom{color:#88F}.highlight-keyword{color:green;font-weight:700}.highlight-builtin{color:green}.highlight-error{color:red}.highlight-operator{color:#A2F;font-weight:700}.highlight-meta{color:#A2F}.highlight-def{color:#00f}.highlight-string-2{color:#f50}.highlight-qualifier{color:#555}.highlight-bracket{color:#997}.highlight-tag{color:#170}.highlight-attribute{color:#00c}.highlight-header{color:#00f}.highlight-quote{color:#090}.highlight-link{color:#00c}.cm-s-ipython span.cm-keyword{color:green;font-weight:700}.cm-s-ipython span.cm-atom{color:#88F}.cm-s-ipython span.cm-number{color:#080}.cm-s-ipython span.cm-def{color:#00f}.cm-s-ipython span.cm-variable{color:#000}.cm-s-ipython span.cm-operator{color:#A2F;font-weight:700}.cm-s-ipython span.cm-variable-2{color:#1a1a1a}.cm-s-ipython span.cm-variable-3{color:#333}.cm-s-ipython span.cm-comment{color:#408080;font-style:italic}.cm-s-ipython span.cm-string{color:#BA2121}.cm-s-ipython span.cm-string-2{color:#f50}.cm-s-ipython span.cm-meta{color:#A2F}.cm-s-ipython span.cm-qualifier{color:#555}.cm-s-ipython span.cm-builtin{color:green}.cm-s-ipython span.cm-bracket{color:#997}.cm-s-ipython span.cm-tag{color:#170}.cm-s-ipython span.cm-attribute{color:#00c}.cm-s-ipython span.cm-header{color:#00f}.cm-s-ipython span.cm-quote{color:#090}.cm-s-ipython span.cm-link{color:#00c}.cm-s-ipython span.cm-error{color:red}.cm-s-ipython span.cm-tab{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAMCAYAAAAkuj5RAAAAAXNSR0IArs4c6QAAAGFJREFUSMft1LsRQFAQheHPowAKoACx3IgEKtaEHujDjORSgWTH/ZOdnZOcM/sgk/kFFWY0qV8foQwS4MKBCS3qR6ixBJvElOobYAtivseIE120FaowJPN75GMu8j/LfMwNjh4HUpwg4LUAAAAASUVORK5CYII=) right no-repeat}div.output_wrapper{position:relative;-moz-box-align:stretch;box-orient:vertical;box-align:stretch;flex-direction:column;align-items:stretch;z-index:1}div.output_area,div.output_collapsed{-webkit-box-align:stretch;display:flex}div.output_scroll{height:24em;width:100%;overflow:auto;border-radius:2px;-webkit-box-shadow:inset 0 2px 8px rgba(0,0,0,.8);box-shadow:inset 0 2px 8px rgba(0,0,0,.8);display:block}div.output_collapsed{margin:0;padding:0;-webkit-box-orient:vertical;-moz-box-orient:vertical;-moz-box-align:stretch;box-orient:vertical;box-align:stretch;flex-direction:column;align-items:stretch}div.output_area,div.text_cell{-webkit-box-orient:horizontal}div.out_prompt_overlay{height:100%;padding:0 .4em;position:absolute;border-radius:2px}div.out_prompt_overlay:hover{-webkit-box-shadow:inset 0 0 1px #000;box-shadow:inset 0 0 1px #000;background:rgba(240,240,240,.5)}div.output_prompt{color:#D84315}div.output_area{padding:0;page-break-inside:avoid;-moz-box-orient:horizontal;-moz-box-align:stretch;box-orient:horizontal;box-align:stretch;flex-direction:row;align-items:stretch}.output,div.text_cell{-webkit-box-align:stretch}div.output_area .MathJax_Display{text-align:left!important}.rendered_html p,div.output_latex,div.output_text{text-align:left}div.output_area .rendered_html img,div.output_area .rendered_html table{margin-left:0;margin-right:0}div.output_area img,div.output_area svg{max-width:100%;height:auto}div.output_area img.unconfined,div.output_area svg.unconfined{max-width:none}.output{-webkit-box-orient:vertical;-moz-box-orient:vertical;-moz-box-align:stretch;box-orient:vertical;box-align:stretch;display:flex;flex-direction:column;align-items:stretch}@media (max-width:540px){div.output_area{-webkit-box-orient:vertical;-webkit-box-align:stretch;-moz-box-orient:vertical;-moz-box-align:stretch;box-orient:vertical;box-align:stretch;display:flex;flex-direction:column;align-items:stretch}}.celltoolbar,div.text_cell{-moz-box-orient:horizontal}div.output_area pre{margin:0;padding:0;border:0;vertical-align:baseline;color:#000;background-color:transparent;border-radius:0}div.output_subarea{overflow-x:auto;padding:.4em;-webkit-box-flex:1;-moz-box-flex:1;box-flex:1;flex:1;max-width:calc(100% - 14ex)}div.output_scroll div.output_subarea{overflow-x:visible}.text_cell.rendered .rendered_html,div#notebook{overflow-y:hidden;overflow-x:auto}div.output_text{color:#000}div.output_stderr{background:#fdd}div.output_javascript:empty{padding:0}.js-error{color:#8b0000}div.raw_input_container{line-height:1.21429em;padding-top:5px}input.raw_input{font-family:monospace;font-size:inherit;color:inherit;width:auto;vertical-align:baseline;padding:0 .25em;margin:0 .25em}input.raw_input:focus{box-shadow:none}p.p-space{margin-bottom:10px}div.output_unrecognized{padding:5px;font-weight:700;color:red}div.output_unrecognized a,div.output_unrecognized a:hover{color:inherit;text-decoration:none}.rendered_html{color:#000}.rendered_html strong{font-weight:700}.rendered_html :link,.rendered_html :visited,.rendered_html u{text-decoration:underline}.rendered_html h1{font-size:185.7%;margin:1.08em 0 0;font-weight:700;line-height:1}.rendered_html h2{font-size:157.1%;margin:1.27em 0 0;font-weight:700;line-height:1}.rendered_html h3{font-size:128.6%;margin:1.55em 0 0;font-weight:700;line-height:1}.rendered_html h4,.rendered_html h5,.rendered_html h6{margin:2em 0 0;line-height:1;font-size:100%;font-weight:700}.rendered_html h1:first-child{margin-top:.538em}.rendered_html h2:first-child{margin-top:.636em}.rendered_html h3:first-child{margin-top:.777em}.rendered_html h4:first-child,.rendered_html h5:first-child,.rendered_html h6:first-child{margin-top:1em}.rendered_html ul{list-style:disc;margin:0 2em;padding-left:0}.rendered_html ul ul{list-style:square;margin:0 2em}.rendered_html ul ul ul{list-style:circle;margin:0 2em}.rendered_html ol{list-style:decimal;margin:0 2em;padding-left:0}.rendered_html ol ol{list-style:upper-alpha;margin:0 2em}.rendered_html ol ol ol{list-style:lower-alpha;margin:0 2em}.rendered_html ol ol ol ol{list-style:lower-roman;margin:0 2em}.rendered_html ol ol ol ol ol{list-style:decimal;margin:0 2em}.rendered_html *+ol,.rendered_html *+ul{margin-top:1em}.rendered_html blockquote,.rendered_html pre{margin:1em 2em}.rendered_html hr{color:#000;background-color:#000}.rendered_html code,.rendered_html pre{border:0;background-color:#fff;color:#000;font-size:100%;padding:0}.rendered_html table{margin-left:auto;margin-right:auto;border:1px solid #000;border-collapse:collapse}.rendered_html td,.rendered_html th,.rendered_html tr{border:1px solid #000;border-collapse:collapse;margin:1em 2em}.rendered_html *+img,.rendered_html *+p,.rendered_html *+table{margin-top:1em}.rendered_html td,.rendered_html th{text-align:left;vertical-align:middle;padding:4px}.rendered_html th{font-weight:700}.rendered_html img{display:block;margin-left:auto;margin-right:auto}.rendered_html img,.rendered_html svg{max-width:100%;height:auto}.rendered_html img.unconfined,.rendered_html svg.unconfined{max-width:none}div.text_cell{-moz-box-align:stretch;box-orient:horizontal;box-align:stretch;display:flex;flex-direction:row;align-items:stretch}.text_cell.rendered .input_area,.text_cell.unrendered .text_cell_render{display:none}@media (max-width:540px){div.text_cell>div.prompt{display:none}}div.text_cell_render{outline:0;resize:none;width:inherit;border-style:none;padding:.5em .5em .5em .4em;color:#000;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box}a.anchor-link:link{text-decoration:none;padding:0 20px;visibility:hidden}h1:hover .anchor-link,h2:hover .anchor-link,h3:hover .anchor-link,h4:hover .anchor-link,h5:hover .anchor-link,h6:hover .anchor-link{visibility:visible}.cm-header-1,.cm-header-2,.cm-header-3,.cm-header-4,.cm-header-5,.cm-header-6{font-weight:700;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}#fonttest,.completions select{font-family:monospace}.cm-header-1{font-size:185.7%}.cm-header-2{font-size:157.1%}.cm-header-3{font-size:128.6%}.cm-header-4{font-size:110%}.cm-header-5,.cm-header-6{font-size:100%}@media (max-width:767px){.notebook_app{padding-left:0;padding-right:0}}#ipython-main-app{box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;height:100%}div#notebook_panel{margin:0;padding:0;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;height:100%}div#notebook{font-size:14px;line-height:20px;width:100%;padding-top:20px;margin:0;outline:0;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;min-height:100%}@media not print{#notebook-container{padding:15px;background-color:#fff;min-height:0;-webkit-box-shadow:0 0 12px 1px rgba(87,87,87,.2);box-shadow:0 0 12px 1px rgba(87,87,87,.2)}}.notebook_app>#header,div#pager{-webkit-box-shadow:0 0 12px 1px rgba(87,87,87,.2)}div.ui-widget-content{border:1px solid #ababab;outline:0}pre.dialog{background-color:#f7f7f7;border:1px solid #ddd;border-radius:2px;padding:.4em .4em .4em 2em}p.dialog{padding:.2em}code,kbd,pre,samp{white-space:pre-wrap}p{margin-bottom:0}.end_space{min-height:100px;transition:height .2s ease}.notebook_app>#header{box-shadow:0 0 12px 1px rgba(87,87,87,.2)}@media not print{.notebook_app{background-color:#EEE}}kbd{border-style:solid;border-width:1px;box-shadow:none;margin:2px;padding:1px 2px}.celltoolbar{border:thin solid #CFCFCF;border-bottom:none;background:#EEE;border-radius:2px 2px 0 0;width:100%;height:29px;padding-right:4px;-webkit-box-orient:horizontal;-webkit-box-align:stretch;-moz-box-align:stretch;box-orient:horizontal;box-align:stretch;flex-direction:row;align-items:stretch;-webkit-box-pack:end;-moz-box-pack:end;box-pack:end;justify-content:flex-end;display:-webkit-flex;font-size:87%;padding-top:3px}@media print{#notebook-container{width:100%}.celltoolbar{display:none}}.ctb_hideshow{display:none;vertical-align:bottom}.ctb_global_show .ctb_show.ctb_hideshow{display:block}.ctb_global_show .ctb_show+.input_area,.ctb_global_show .ctb_show+div.text_cell_input,.ctb_global_show .ctb_show~div.text_cell_render{border-top-right-radius:0;border-top-left-radius:0}.ctb_global_show .ctb_show~div.text_cell_render{border:1px solid #cfcfcf}.celltoolbar select{color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;line-height:1.5;border-radius:1px;width:inherit;font-size:inherit;height:22px;padding:0;display:inline-block}.celltoolbar select:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.celltoolbar select::-moz-placeholder{color:#999;opacity:1}.celltoolbar select:-ms-input-placeholder{color:#999}.celltoolbar select::-webkit-input-placeholder{color:#999}.celltoolbar select::-ms-expand{border:0;background-color:transparent}.celltoolbar select[disabled],.celltoolbar select[readonly],fieldset[disabled] .celltoolbar select{background-color:#eee;opacity:1}.celltoolbar select[disabled],fieldset[disabled] .celltoolbar select{cursor:not-allowed}textarea.celltoolbar select{height:auto}select.celltoolbar select{height:30px;line-height:30px}select[multiple].celltoolbar select,textarea.celltoolbar select{height:auto}.celltoolbar label{margin-left:5px;margin-right:5px}.completions{position:absolute;z-index:110;overflow:hidden;border:1px solid #ababab;border-radius:2px;-webkit-box-shadow:0 6px 10px -1px #adadad;box-shadow:0 6px 10px -1px #adadad;line-height:1}.completions select{background:#fff;outline:0;border:none;padding:0;margin:0;overflow:auto;font-size:110%;color:#000;width:auto}.dropdown-submenu>a:after,.edit_mode .modal_indicator:before{font:normal normal normal 14px/1 FontAwesome;text-rendering:auto;-moz-osx-font-smoothing:grayscale}.completions select option.context{color:#286090}#kernel_logo_widget{float:right!important;float:right}#kernel_logo_widget .current_kernel_logo{display:none;margin-top:-1px;margin-bottom:-1px;width:32px;height:32px}#menubar{box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;margin-top:1px}#menubar .navbar{border-top:1px;border-radius:0 0 2px 2px;margin-bottom:0}#menubar .navbar-toggle{float:left;padding-top:7px;padding-bottom:7px;border:none}#menubar .navbar-collapse{clear:left}.nav-wrapper{border-bottom:1px solid #e7e7e7}i.menu-icon{padding-top:4px}ul#help_menu li a{overflow:hidden;padding-right:2.2em}ul#help_menu li a i{margin-right:-1.2em}.dropdown-submenu{position:relative}.dropdown-submenu>.dropdown-menu{top:0;left:100%;margin-top:-6px;margin-left:-1px}.dropdown-submenu:hover>.dropdown-menu{display:block}.dropdown-submenu>a:after{font-size:inherit;-webkit-font-smoothing:antialiased;display:block;content:"\f0da";float:right;color:#333;margin-top:2px;margin-right:-10px}.dropdown-submenu>a:after.pull-left{margin-right:.3em}.dropdown-submenu>a:after.pull-right{margin-left:.3em}.dropdown-submenu:hover>a:after{color:#262626}.dropdown-submenu.pull-left{float:none}.dropdown-submenu.pull-left>.dropdown-menu{left:-100%;margin-left:10px}#kernel_indicator,#modal_indicator,.indicator_area{margin-left:5px;margin-right:5px}#notification_area{float:right!important;float:right;z-index:10}.indicator_area{float:right!important;float:right;color:#777;z-index:10;text-align:center;width:auto}#kernel_indicator,#modal_indicator,#readonly-indicator{float:right!important;color:#777;width:auto;text-align:center;z-index:10}#kernel_indicator{float:right;border-left:1px solid}#kernel_indicator .kernel_indicator_name{padding-left:5px;padding-right:5px}#modal_indicator{float:right}#readonly-indicator{float:right;display:none;margin:2px 0 0}.command_mode .modal_indicator:before.pull-left,.edit_mode .modal_indicator:before.pull-left,.kernel_busy_icon:before.pull-left,.kernel_dead_icon:before.pull-left,.kernel_disconnected_icon:before.pull-left,.kernel_idle_icon:before.pull-left{margin-right:.3em}.command_mode .modal_indicator:before.pull-right,.edit_mode .modal_indicator:before.pull-right,.kernel_busy_icon:before.pull-right,.kernel_dead_icon:before.pull-right,.kernel_disconnected_icon:before.pull-right,.kernel_idle_icon:before.pull-right{margin-left:.3em}.modal_indicator:before{width:1.28571429em;text-align:center}.edit_mode .modal_indicator:before{display:inline-block;font-size:inherit;-webkit-font-smoothing:antialiased;content:"\f040"}.command_mode .modal_indicator:before,.kernel_idle_icon:before{display:inline-block;font:normal normal normal 14px/1 FontAwesome;text-rendering:auto}.command_mode .modal_indicator:before{font-size:inherit;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;content:' '}.kernel_idle_icon:before{font-size:inherit;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;content:"\f10c"}.kernel_busy_icon:before,.kernel_dead_icon:before{font:normal normal normal 14px/1 FontAwesome;display:inline-block;text-rendering:auto;-moz-osx-font-smoothing:grayscale}.kernel_busy_icon:before{font-size:inherit;-webkit-font-smoothing:antialiased;content:"\f111"}.kernel_dead_icon:before{font-size:inherit;-webkit-font-smoothing:antialiased;content:"\f1e2"}.kernel_disconnected_icon:before{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;content:"\f127"}.notification_widget{z-index:10;background:rgba(240,240,240,.5);margin-right:4px;color:#333;background-color:#fff;border-color:#ccc}.notification_widget.active,.notification_widget.danger.active,.notification_widget.danger:active,.notification_widget.info.active,.notification_widget.info:active,.notification_widget.success.active,.notification_widget.success:active,.notification_widget.warning.active,.notification_widget.warning:active,.notification_widget:active,.open>.dropdown-toggle.notification_widget,.open>.dropdown-toggle.notification_widget.danger,.open>.dropdown-toggle.notification_widget.info,.open>.dropdown-toggle.notification_widget.success,.open>.dropdown-toggle.notification_widget.warning{background-image:none}.notification_widget.focus,.notification_widget:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.notification_widget.active,.notification_widget:active,.notification_widget:hover,.open>.dropdown-toggle.notification_widget{color:#333;background-color:#e6e6e6;border-color:#adadad}.notification_widget.active.focus,.notification_widget.active:focus,.notification_widget.active:hover,.notification_widget:active.focus,.notification_widget:active:focus,.notification_widget:active:hover,.open>.dropdown-toggle.notification_widget.focus,.open>.dropdown-toggle.notification_widget:focus,.open>.dropdown-toggle.notification_widget:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.notification_widget.disabled.focus,.notification_widget.disabled:focus,.notification_widget.disabled:hover,.notification_widget[disabled].focus,.notification_widget[disabled]:focus,.notification_widget[disabled]:hover,fieldset[disabled] .notification_widget.focus,fieldset[disabled] .notification_widget:focus,fieldset[disabled] .notification_widget:hover{background-color:#fff;border-color:#ccc}.notification_widget .badge{color:#fff;background-color:#333}.notification_widget.warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.notification_widget.warning.focus,.notification_widget.warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.notification_widget.warning.active,.notification_widget.warning:active,.notification_widget.warning:hover,.open>.dropdown-toggle.notification_widget.warning{color:#fff;background-color:#ec971f;border-color:#d58512}.notification_widget.warning.active.focus,.notification_widget.warning.active:focus,.notification_widget.warning.active:hover,.notification_widget.warning:active.focus,.notification_widget.warning:active:focus,.notification_widget.warning:active:hover,.open>.dropdown-toggle.notification_widget.warning.focus,.open>.dropdown-toggle.notification_widget.warning:focus,.open>.dropdown-toggle.notification_widget.warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.notification_widget.warning.disabled.focus,.notification_widget.warning.disabled:focus,.notification_widget.warning.disabled:hover,.notification_widget.warning[disabled].focus,.notification_widget.warning[disabled]:focus,.notification_widget.warning[disabled]:hover,fieldset[disabled] .notification_widget.warning.focus,fieldset[disabled] .notification_widget.warning:focus,fieldset[disabled] .notification_widget.warning:hover{background-color:#f0ad4e;border-color:#eea236}.notification_widget.warning .badge{color:#f0ad4e;background-color:#fff}.notification_widget.success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.notification_widget.success.focus,.notification_widget.success:focus{color:#fff;background-color:#449d44;border-color:#255625}.notification_widget.success.active,.notification_widget.success:active,.notification_widget.success:hover,.open>.dropdown-toggle.notification_widget.success{color:#fff;background-color:#449d44;border-color:#398439}.notification_widget.success.active.focus,.notification_widget.success.active:focus,.notification_widget.success.active:hover,.notification_widget.success:active.focus,.notification_widget.success:active:focus,.notification_widget.success:active:hover,.open>.dropdown-toggle.notification_widget.success.focus,.open>.dropdown-toggle.notification_widget.success:focus,.open>.dropdown-toggle.notification_widget.success:hover{color:#fff;background-color:#398439;border-color:#255625}.notification_widget.success.disabled.focus,.notification_widget.success.disabled:focus,.notification_widget.success.disabled:hover,.notification_widget.success[disabled].focus,.notification_widget.success[disabled]:focus,.notification_widget.success[disabled]:hover,fieldset[disabled] .notification_widget.success.focus,fieldset[disabled] .notification_widget.success:focus,fieldset[disabled] .notification_widget.success:hover{background-color:#5cb85c;border-color:#4cae4c}.notification_widget.success .badge{color:#5cb85c;background-color:#fff}.notification_widget.info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.notification_widget.info.focus,.notification_widget.info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.notification_widget.info.active,.notification_widget.info:active,.notification_widget.info:hover,.open>.dropdown-toggle.notification_widget.info{color:#fff;background-color:#31b0d5;border-color:#269abc}.notification_widget.info.active.focus,.notification_widget.info.active:focus,.notification_widget.info.active:hover,.notification_widget.info:active.focus,.notification_widget.info:active:focus,.notification_widget.info:active:hover,.open>.dropdown-toggle.notification_widget.info.focus,.open>.dropdown-toggle.notification_widget.info:focus,.open>.dropdown-toggle.notification_widget.info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.notification_widget.info.disabled.focus,.notification_widget.info.disabled:focus,.notification_widget.info.disabled:hover,.notification_widget.info[disabled].focus,.notification_widget.info[disabled]:focus,.notification_widget.info[disabled]:hover,fieldset[disabled] .notification_widget.info.focus,fieldset[disabled] .notification_widget.info:focus,fieldset[disabled] .notification_widget.info:hover{background-color:#5bc0de;border-color:#46b8da}.notification_widget.info .badge{color:#5bc0de;background-color:#fff}.notification_widget.danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.notification_widget.danger.focus,.notification_widget.danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.notification_widget.danger.active,.notification_widget.danger:active,.notification_widget.danger:hover,.open>.dropdown-toggle.notification_widget.danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.notification_widget.danger.active.focus,.notification_widget.danger.active:focus,.notification_widget.danger.active:hover,.notification_widget.danger:active.focus,.notification_widget.danger:active:focus,.notification_widget.danger:active:hover,.open>.dropdown-toggle.notification_widget.danger.focus,.open>.dropdown-toggle.notification_widget.danger:focus,.open>.dropdown-toggle.notification_widget.danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.notification_widget.danger.disabled.focus,.notification_widget.danger.disabled:focus,.notification_widget.danger.disabled:hover,.notification_widget.danger[disabled].focus,.notification_widget.danger[disabled]:focus,.notification_widget.danger[disabled]:hover,fieldset[disabled] .notification_widget.danger.focus,fieldset[disabled] .notification_widget.danger:focus,fieldset[disabled] .notification_widget.danger:hover{background-color:#d9534f;border-color:#d43f3a}.notification_widget.danger .badge{color:#d9534f;background-color:#fff}div#pager{background-color:#fff;font-size:14px;line-height:20px;overflow:hidden;display:none;position:fixed;bottom:0;width:100%;max-height:50%;padding-top:8px;box-shadow:0 0 12px 1px rgba(87,87,87,.2);z-index:100;top:auto!important}div#pager pre{line-height:1.21429em;color:#000;background-color:#f7f7f7;padding:.4em}div#pager #pager-button-area{position:absolute;top:8px;right:20px}div#pager #pager-contents{position:relative;overflow:auto;width:100%;height:100%}div#pager #pager-contents #pager-container{position:relative;padding:15px 0;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box}div#pager .ui-resizable-handle{top:0;height:8px;background:#f7f7f7;border-top:1px solid #cfcfcf;border-bottom:1px solid #cfcfcf}div#pager .ui-resizable-handle::after{content:'';top:2px;left:50%;height:3px;width:30px;margin-left:-15px;position:absolute;border-top:1px solid #cfcfcf}.quickhelp{-webkit-box-orient:horizontal;-webkit-box-align:stretch;-moz-box-orient:horizontal;-moz-box-align:stretch;box-orient:horizontal;box-align:stretch;display:flex;flex-direction:row;align-items:stretch;line-height:1.8em}.shortcut_key{display:inline-block;width:21ex;text-align:right;font-family:monospace}.shortcut_descr{display:inline-block;-webkit-box-flex:1;-moz-box-flex:1;box-flex:1;flex:1}span.save_widget{margin-top:6px}span.save_widget span.filename{height:1em;line-height:1em;padding:3px;margin-left:16px;border:none;font-size:146.5%;border-radius:2px}span.save_widget span.filename:hover{background-color:#e6e6e6}span.autosave_status,span.checkpoint_status{font-size:small}@media (max-width:767px){span.save_widget{font-size:small}span.autosave_status,span.checkpoint_status{display:none}}@media (min-width:768px) and (max-width:991px){span.checkpoint_status{display:none}span.autosave_status{font-size:x-small}}.toolbar{padding:0;margin-left:-5px;margin-top:2px;margin-bottom:5px;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box}.toolbar label,.toolbar select{width:auto;vertical-align:middle;margin-bottom:0;display:inline;font-size:92%;margin-left:.3em;margin-right:.3em;padding:3px 0 0}.toolbar .btn{padding:2px 8px}.toolbar .btn-group{margin-top:0;margin-left:5px}#maintoolbar{margin-bottom:-3px;margin-top:-8px;border:0;min-height:27px;margin-left:0;padding-top:11px;padding-bottom:3px}#maintoolbar .navbar-text{float:none;vertical-align:middle;text-align:right;margin-left:5px;margin-right:0;margin-top:0}.select-xs{height:24px}.dropdown-menu>li>a.pulse,.pulse,li.pulse.open>a.dropdown-toggle,li.pulse>a.dropdown-toggle{background-color:#F37626;color:#fff}@-moz-keyframes fadeOut{from{opacity:1}to{opacity:0}}@-webkit-keyframes fadeOut{from{opacity:1}to{opacity:0}}@-moz-keyframes fadeIn{from{opacity:0}to{opacity:1}}@-webkit-keyframes fadeIn{from{opacity:0}to{opacity:1}}.bigtooltip{overflow:auto;height:200px;-webkit-transition-property:height;-webkit-transition-duration:.5s;-moz-transition-property:height;-moz-transition-duration:.5s;transition-property:height;transition-duration:.5s}.smalltooltip{-webkit-transition-property:height;-webkit-transition-duration:.5s;-moz-transition-property:height;-moz-transition-duration:.5s;transition-property:height;transition-duration:.5s;text-overflow:ellipsis;overflow:hidden;height:80px}.tooltipbuttons{position:absolute;padding-right:15px;top:0;right:0}.tooltiptext{padding-right:30px}.ipython_tooltip{max-width:700px;-webkit-animation:fadeIn .4s;-moz-animation:fadeIn .4s;animation:fadeIn .4s;vertical-align:middle;background-color:#f7f7f7;overflow:visible;border:1px solid #ababab;outline:0;padding:3px 3px 3px 7px;margin:0;font-family:monospace;min-height:50px;-moz-box-shadow:0 6px 10px -1px #adadad;-webkit-box-shadow:0 6px 10px -1px #adadad;box-shadow:0 6px 10px -1px #adadad;border-radius:2px;position:absolute;z-index:1000}.ipython_tooltip a{float:right}.ipython_tooltip .tooltiptext pre{border:0;border-radius:0;font-size:100%;background-color:#f7f7f7}.pretooltiparrow{left:0;margin:0;top:-16px;width:40px;height:16px;overflow:hidden;position:absolute}.pretooltiparrow:before{background-color:#f7f7f7;border:1px solid #ababab;z-index:11;content:"";position:absolute;left:15px;top:10px;width:25px;height:25px;-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg)}ul.typeahead-list i{margin-left:-10px;width:18px}ul.typeahead-list{max-height:80vh;overflow:auto}ul.typeahead-list>li>a{white-space:normal}.cmd-palette .modal-body{padding:7px}.cmd-palette form{background:#fff}.cmd-palette input{outline:0}.no-shortcut{display:none}.command-shortcut:before{content:"(command)";padding-right:3px;color:#777}.edit-shortcut:before{content:"(edit)";padding-right:3px;color:#777}#find-and-replace #replace-preview .insert,#find-and-replace #replace-preview .match{background-color:#BBDEFB;border-color:#90CAF9;border-style:solid;border-width:1px;border-radius:0}#find-and-replace #replace-preview .replace .match{background-color:#FFCDD2;border-color:#EF9A9A;border-radius:0}#find-and-replace #replace-preview .replace .insert{background-color:#C8E6C9;border-color:#A5D6A7;border-radius:0}#find-and-replace #replace-preview{max-height:60vh;overflow:auto}#find-and-replace #replace-preview pre{padding:5px 10px}.terminal-app{background:#EEE}.terminal-app #header{background:#fff;-webkit-box-shadow:0 0 12px 1px rgba(87,87,87,.2);box-shadow:0 0 12px 1px rgba(87,87,87,.2)}.terminal-app .terminal{width:100%;float:left;font-family:monospace;color:#fff;background:#000;padding:.4em;border-radius:2px;-webkit-box-shadow:0 0 12px 1px rgba(87,87,87,.4);box-shadow:0 0 12px 1px rgba(87,87,87,.4)}.terminal-app .terminal,.terminal-app .terminal dummy-screen{line-height:1em;font-size:14px}.terminal-app .terminal .xterm-rows{padding:10px}.terminal-app .terminal-cursor{color:#000;background:#fff}.terminal-app #terminado-container{margin-top:20px}.highlight .hll{background-color:#ffc}.highlight .c{color:#408080;font-style:italic}.highlight .err{border:1px solid red}.highlight .k{color:green;font-weight:700}.highlight .o{color:#666}.highlight .ch,.highlight .cm{color:#408080;font-style:italic}.highlight .cp{color:#BC7A00}.highlight .c1,.highlight .cpf,.highlight .cs{color:#408080;font-style:italic}.highlight .gd{color:#A00000}.highlight .ge{font-style:italic}.highlight .gr{color:red}.highlight .gh{color:navy;font-weight:700}.highlight .gi{color:#00A000}.highlight .go{color:#888}.highlight .gp{color:navy;font-weight:700}.highlight .gs{font-weight:700}.highlight .gu{color:purple;font-weight:700}.highlight .gt{color:#04D}.highlight .kc,.highlight .kd,.highlight .kn{color:green;font-weight:700}.highlight .kp{color:green}.highlight .kr{color:green;font-weight:700}.highlight .kt{color:#B00040}.highlight .m{color:#666}.highlight .s{color:#BA2121}.highlight .na{color:#7D9029}.highlight .nb{color:green}.highlight .nc{color:#00F;font-weight:700}.highlight .no{color:#800}.highlight .nd{color:#A2F}.highlight .ni{color:#999;font-weight:700}.highlight .ne{color:#D2413A;font-weight:700}.highlight .nf{color:#00F}.highlight .nl{color:#A0A000}.highlight .nn{color:#00F;font-weight:700}.highlight .nt{color:green;font-weight:700}.highlight .nv{color:#19177C}.highlight .ow{color:#A2F;font-weight:700}.highlight .w{color:#bbb}.highlight .mb,.highlight .mf,.highlight .mh,.highlight .mi,.highlight .mo{color:#666}.highlight .s2,.highlight .sb,.highlight .sc{color:#BA2121}.highlight .sd{color:#BA2121;font-style:italic}.highlight .se{color:#B62;font-weight:700}.highlight .sh{color:#BA2121}.highlight .si{color:#B68;font-weight:700}.highlight .sx{color:green}.highlight .sr{color:#B68}.highlight .s1{color:#BA2121}.highlight .ss{color:#19177C}.highlight .bp{color:green}.highlight .vc,.highlight .vg,.highlight .vi{color:#19177C}.highlight .il{color:#666}
\ No newline at end of file
diff --git a/relate/static/css/style.css b/relate/static/css/style.css
index d6e523a1883f6d0ffa795e97ababd6399800e18d..d5165d141743b39684b0b237ac23646f4a4c644f 100644
--- a/relate/static/css/style.css
+++ b/relate/static/css/style.css
@@ -333,4 +333,19 @@ a .sensitive {
text-decoration: none;
}
+/* if not using "markdown.extensions.codehilite" extension */
+div.cell.border-box-sizing.code_cell.rendered > div.input > div.inner_cell > div.input_area > pre {
+ margin: 0;
+}
+
+div.rendered_html div.highlight {
+ border: 1px solid #cfcfcf;
+ border-radius: 2px;
+ background: #f7f7f7;
+}
+
+div.rendered_html div.highlight > pre{
+ margin: 0.4em;
+ background-color: transparent;
+}
/* vim: set foldmethod=marker: */
diff --git a/relate/templates/base.html b/relate/templates/base.html
index 2b29df1419147c6a7b4eea7279486e5ae48ab6f1..79ecaca0c0941fea465ec25793cf71206bb6e8e0 100644
--- a/relate/templates/base.html
+++ b/relate/templates/base.html
@@ -28,7 +28,8 @@
{% endblock %}
{% block head_assets_local %}
-
+
+
{% endblock %}
{% block head_assets_form_media %}
diff --git a/requirements.txt b/requirements.txt
index ee8118169d8608af598fa1b756a3b7827e5784cd..3dc2f8e9ad884e797326ec402c9b7d914898130c 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -113,4 +113,11 @@ typing
# For unittest by mock (only required for Py2)
# mock
+# For rendering ipython notebook
+nbconvert>=5.2.1
+IPython
+
+# For parsing and edit html
+lxml
+
# vim: foldmethod=marker
diff --git a/tests/test_checks.py b/tests/test_checks.py
index 1ba2cbb450194a26f72ad4e2e329ad155e43c97d..64b39aae33938c644c3aeccbd0bf36ebae1f2b2a 100644
--- a/tests/test_checks.py
+++ b/tests/test_checks.py
@@ -675,3 +675,39 @@ class CheckRelateTemplatesDirs(CheckRelateSettingsBase):
self.assertCheckMessages(
["relate_override_templates_dirs.W001",
"relate_override_templates_dirs.W001"])
+
+
+class CheckRelateDisableCodehiliteMarkdownExtensions(CheckRelateSettingsBase):
+ VALID_CONF = None
+ VALID_CONF_NO_WARNING = True
+
+ WARNING_CONF_NOT_BOOL1 = "some string"
+ WARNING_CONF_NOT_BOOL2 = ["markdown.extensions.codehilite"]
+ WARNING_CONF_FALSE = False
+
+ @override_settings(RELATE_DISABLE_CODEHILITE_MARKDOWN_EXTENSION=VALID_CONF)
+ def test_valid_conf(self):
+ self.assertEqual(self.func(None), [])
+
+ @override_settings(
+ RELATE_DISABLE_CODEHILITE_MARKDOWN_EXTENSION=VALID_CONF_NO_WARNING)
+ def test_valid_conf_no_warning(self):
+ self.assertEqual(self.func(None), [])
+
+ @override_settings(
+ RELATE_DISABLE_CODEHILITE_MARKDOWN_EXTENSION=WARNING_CONF_NOT_BOOL1)
+ def test_warning_conf_not_bool1(self):
+ self.assertEqual([r.id for r in self.func(None)],
+ ["relate_disable_codehilite_markdown_extension.W001"])
+
+ @override_settings(
+ RELATE_DISABLE_CODEHILITE_MARKDOWN_EXTENSION=WARNING_CONF_NOT_BOOL2)
+ def test_warning_conf_not_bool2(self):
+ self.assertEqual([r.id for r in self.func(None)],
+ ["relate_disable_codehilite_markdown_extension.W001"])
+
+ @override_settings(
+ RELATE_DISABLE_CODEHILITE_MARKDOWN_EXTENSION=WARNING_CONF_FALSE)
+ def test_warning_conf_false(self):
+ self.assertEqual([r.id for r in self.func(None)],
+ ["relate_disable_codehilite_markdown_extension.W002"])
diff --git a/tests/test_content.py b/tests/test_content.py
index 907af4764920990128c32cb2de2c8b560922efca..589e9f3c87f3b3b5f296704f53dbe22e62617693 100644
--- a/tests/test_content.py
+++ b/tests/test_content.py
@@ -22,6 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
+import json
from django.test import TestCase
from tests.base_test_mixins import (
improperly_configured_cache_patch, SingleCoursePageTestMixin)
@@ -66,6 +67,323 @@ class SingleCoursePageCacheTest(SingleCoursePageTestMixin, TestCase):
self.assertEqual(resp.status_code, 200)
+# {{{ Test Nbconvert for rendering ipynb notebook
+
+QUESTION_MARKUP_FULL = """
+type: Page
+id: ipynb
+content: |
+
+ # Ipython notebook Examples
+
+ {{ render_notebook_cells("test.ipynb") }}
+"""
+
+QUESTION_MARKUP_SLICED1 = """
+type: Page
+id: ipynb
+content: |
+
+ # Ipython notebook Examples
+
+ {{ render_notebook_cells("test.ipynb", indices=[0, 1, 2]) }}
+"""
+
+QUESTION_MARKUP_SLICED2 = """
+type: Page
+id: ipynb
+content: |
+
+ # Ipython notebook Examples
+
+ {{ render_notebook_cells("test.ipynb", indices=[1, 2]) }}
+"""
+
+QUESTION_MARKUP_CLEAR_MARKDOWN = """
+type: Page
+id: ipynb
+content: |
+
+ # Ipython notebook Examples
+
+ {{ render_notebook_cells("test.ipynb", clear_markdown=True) }}
+"""
+
+QUESTION_MARKUP_CLEAR_OUTPUT = """
+type: Page
+id: ipynb
+content: |
+
+ # Ipython notebook Examples
+
+ {{ render_notebook_cells("test.ipynb", clear_output=True) }}
+"""
+
+QUESTION_MARKUP_CLEAR_ALL = """
+type: Page
+id: ipynb
+content: |
+
+ # Ipython notebook Examples
+
+ {{ render_notebook_cells("test.ipynb", clear_markdown=True, clear_output=True) }}
+"""
+
+MARKDOWN_PLACEHOLDER = "wzxhzdk"
+
+TEST_IPYNB_BYTES = json.dumps({
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# First Title of Test NoteBook"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {
+ "scrolled": True
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "This is function1\n"
+ ]
+ }
+ ],
+ "source": [
+ "def function1():\n",
+ " print(\"This is function1\")\n",
+ "\n",
+ "function1()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Second Title of Test NoteBook"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {
+ "collapsed": True
+ },
+ "outputs": [],
+ "source": [
+ "def function2():\n",
+ " print(\"This is function2\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "This is function2\n"
+ ]
+ }
+ ],
+ "source": [
+ "function2()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": None,
+ "metadata": {
+ "collapsed": True
+ },
+ "outputs": [],
+ "source": [
+ "print(`5**18`)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.5.0"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}).encode()
+
+FIRST_TITLE_TEXT = "First Title of Test NoteBook"
+SECOND_TITLE_TEXT = "Second Title of Test NoteBook"
+TEXT_CELL_HTML_CLASS = "text_cell_render"
+CODE_CELL_HTML_CLASS = "code_cell"
+CODE_CELL_IN_STR_PATTERN = 'In[%s]:
'
+CODE_CELL_PRINT_STR1 = "This is function1"
+CODE_CELL_PRINT_STR2 = "This is function2"
+
+
+def strip_nbsp(s):
+ """
+ Returns the given HTML with ' ' (introduced by nbconvert) stripped
+ """
+ from django.utils.encoding import force_text
+ return force_text(s).replace(' ', '').replace(u'\xa0', '')
+
+
+def get_nb_html_from_response(response):
+ from django.utils.safestring import mark_safe
+ return strip_nbsp(mark_safe(response.context["body"]))
+
+
+class NbconvertRenderTestMixin(SingleCoursePageSandboxTestBaseMixin):
+ def assertIsValidNbConversion(self, response): # noqa
+ self.assertNotContains(response, MARKDOWN_PLACEHOLDER)
+ self.assertNotContains(response, "```")
+ self.assertNotContains(response, "# First Title of Test NoteBook")
+ self.assertNotContains(response, "# Second Title of Test NoteBook")
+
+ def setUp(self):
+ super(NbconvertRenderTestMixin, self).setUp()
+ patcher = mock.patch("course.content.get_repo_blob_data_cached")
+ self.mock_func = patcher.start()
+ self.mock_func.return_value = TEST_IPYNB_BYTES
+ self.addCleanup(patcher.stop)
+
+
+class NbconvertRenderTest(NbconvertRenderTestMixin, TestCase):
+
+ @classmethod
+ def setUpTestData(cls): # noqa
+ super(NbconvertRenderTest, cls).setUpTestData()
+ cls.c.force_login(cls.instructor_participation.user)
+
+ def test_full_notebook_render(self):
+ resp = self.get_page_sandbox_preview_response(QUESTION_MARKUP_FULL)
+
+ self.assertIsValidNbConversion(resp)
+ self.assertContains(resp, TEXT_CELL_HTML_CLASS, count=2)
+ self.assertContains(resp, CODE_CELL_HTML_CLASS, count=4)
+ self.assertContains(resp, FIRST_TITLE_TEXT, count=1)
+ self.assertContains(resp, SECOND_TITLE_TEXT, count=1)
+ self.assertContains(resp, CODE_CELL_PRINT_STR1, count=2)
+ self.assertContains(resp, CODE_CELL_PRINT_STR2, count=2)
+
+ # backtick is properly rendered with highlight
+ # for "`5**18`". though this syntax is not allowed in PY3
+ self.assertContains(
+ resp,
+ '`5')
+
+ nb_html = get_nb_html_from_response(resp)
+ for i in range(1, 4):
+ self.assertInHTML(CODE_CELL_IN_STR_PATTERN % i, nb_html)
+
+ def test_notebook_sliced1(self):
+ resp = self.get_page_sandbox_preview_response(QUESTION_MARKUP_SLICED1)
+ self.assertIsValidNbConversion(resp)
+ self.assertContains(resp, TEXT_CELL_HTML_CLASS, count=2)
+ self.assertContains(resp, CODE_CELL_HTML_CLASS, count=1)
+ self.assertContains(resp, FIRST_TITLE_TEXT, count=1)
+ self.assertContains(resp, SECOND_TITLE_TEXT, count=1)
+ self.assertContains(resp, CODE_CELL_PRINT_STR1, count=2)
+ self.assertNotContains(resp, CODE_CELL_PRINT_STR2)
+
+ nb_html = get_nb_html_from_response(resp)
+ self.assertInHTML(CODE_CELL_IN_STR_PATTERN % 1, nb_html, count=1)
+ self.assertInHTML(CODE_CELL_IN_STR_PATTERN % 2, nb_html, count=0)
+ self.assertInHTML(CODE_CELL_IN_STR_PATTERN % 3, nb_html, count=0)
+
+ def test_notebook_sliced2(self):
+ resp = self.get_page_sandbox_preview_response(QUESTION_MARKUP_SLICED2)
+ self.assertIsValidNbConversion(resp)
+ self.assertContains(resp, TEXT_CELL_HTML_CLASS, count=1)
+ self.assertContains(resp, CODE_CELL_HTML_CLASS, count=1)
+ self.assertNotContains(resp, FIRST_TITLE_TEXT)
+ self.assertContains(resp, SECOND_TITLE_TEXT, count=1)
+ self.assertContains(resp, CODE_CELL_PRINT_STR1, count=2)
+ self.assertNotContains(resp, CODE_CELL_PRINT_STR2)
+
+ # code highlight functions (in terms of rendered ipynb notebook cells only)
+ import six
+ if six.PY3:
+ self.assertRegex(resp.context["body"], 'class="\w*\s*highlight[^\w]')
+ self.assertContains(resp, " highlight hl-ipython3")
+ self.assertContains(resp,
+ 'print'
+ '(',
+ count=1)
+
+ nb_html = get_nb_html_from_response(resp)
+ self.assertInHTML(CODE_CELL_IN_STR_PATTERN % 1, nb_html, count=1)
+ self.assertInHTML(CODE_CELL_IN_STR_PATTERN % 2, nb_html, count=0)
+ self.assertInHTML(CODE_CELL_IN_STR_PATTERN % 3, nb_html, count=0)
+
+ def test_notebook_clear_markdown(self):
+ resp = self.get_page_sandbox_preview_response(QUESTION_MARKUP_CLEAR_MARKDOWN)
+ self.assertIsValidNbConversion(resp)
+ self.assertNotContains(resp, TEXT_CELL_HTML_CLASS)
+ self.assertContains(resp, CODE_CELL_HTML_CLASS, count=4)
+ self.assertNotContains(resp, FIRST_TITLE_TEXT)
+ self.assertNotContains(resp, SECOND_TITLE_TEXT)
+
+ nb_html = get_nb_html_from_response(resp)
+ for i in range(1, 4):
+ self.assertInHTML(CODE_CELL_IN_STR_PATTERN % i, nb_html, count=1)
+
+ def test_notebook_clear_output(self):
+ resp = self.get_page_sandbox_preview_response(QUESTION_MARKUP_CLEAR_OUTPUT)
+ self.assertIsValidNbConversion(resp)
+ self.assertContains(resp, TEXT_CELL_HTML_CLASS, count=2)
+ self.assertContains(resp, CODE_CELL_HTML_CLASS, count=4)
+ self.assertContains(resp, FIRST_TITLE_TEXT, count=1)
+ self.assertContains(resp, SECOND_TITLE_TEXT, count=1)
+ self.assertContains(resp, CODE_CELL_PRINT_STR1, count=1)
+ self.assertContains(resp, CODE_CELL_PRINT_STR2, count=1)
+
+ nb_html = get_nb_html_from_response(resp)
+ for i in range(1, 4):
+ self.assertInHTML(CODE_CELL_IN_STR_PATTERN % i, nb_html, count=0)
+ self.assertInHTML(CODE_CELL_IN_STR_PATTERN % "", nb_html, count=4)
+
+ def test_notebook_clear_markdown_and_output(self):
+ resp = self.get_page_sandbox_preview_response(QUESTION_MARKUP_CLEAR_ALL)
+ self.assertIsValidNbConversion(resp)
+ self.assertNotContains(resp, TEXT_CELL_HTML_CLASS)
+ self.assertContains(resp, CODE_CELL_HTML_CLASS, count=4)
+ self.assertNotContains(resp, FIRST_TITLE_TEXT)
+ self.assertNotContains(resp, SECOND_TITLE_TEXT)
+ self.assertContains(resp, CODE_CELL_PRINT_STR1, count=1)
+ self.assertContains(resp, CODE_CELL_PRINT_STR2, count=1)
+
+ nb_html = get_nb_html_from_response(resp)
+ for i in range(1, 4):
+ self.assertInHTML(CODE_CELL_IN_STR_PATTERN % i, nb_html, count=0)
+ self.assertInHTML(CODE_CELL_IN_STR_PATTERN % "", nb_html, count=4)
+
+
+# }}}
+
+
TEST_SANDBOX_MARK_DOWN_PATTERN = r"""
type: Page
id: test_endraw