示例#1
0
    def _process(self):
        config = Config()
        config.HTMLExporter.preprocessors = [CppHighlighter]
        config.HTMLExporter.template_file = 'basic'

        with self.attachment.file.open() as f:
            notebook = nbformat.read(f, as_version=4)

        html_exporter = HTMLExporter(config=config)
        body, resources = html_exporter.from_notebook_node(notebook)
        css_code = '\n'.join(resources['inlining'].get('css', []))

        nonce = str(uuid4())
        html = render_template('previewer_jupyter:ipynb_preview.html', attachment=self.attachment,
                               html_code=body, css_code=css_code, nonce=nonce)

        response = current_app.response_class(html)
        # Use CSP to restrict access to possibly malicious scripts or inline JS
        csp_header = "script-src cdn.mathjax.org 'nonce-{}';".format(nonce)
        response.headers['Content-Security-Policy'] = csp_header
        response.headers['X-Webkit-CSP'] = csp_header
        # IE10 doesn't have proper CSP support, so we need to be more strict
        response.headers['X-Content-Security-Policy'] = "sandbox allow-same-origin;"

        return response
示例#2
0
文件: ipynb.py 项目: andredias/nikola
 def _compile_string(self, nb_json):
     """Export notebooks as HTML strings."""
     if flag is None:
         req_missing(['ipython[notebook]>=2.0.0'], 'build this site (compile ipynb)')
     c = Config(self.site.config['IPYNB_CONFIG'])
     exportHtml = HTMLExporter(config=c)
     body, _ = exportHtml.from_notebook_node(nb_json)
     return body
示例#3
0
 def _compile_string(self, nb_json):
     """Export notebooks as HTML strings."""
     self._req_missing_ipynb()
     c = Config(self.site.config['IPYNB_CONFIG'])
     c.update(get_default_jupyter_config())
     exportHtml = HTMLExporter(config=c)
     body, _ = exportHtml.from_notebook_node(nb_json)
     return body
示例#4
0
文件: ipynb.py 项目: humitos/nikola
 def _compile_string(self, nb_json):
     """Export notebooks as HTML strings."""
     self._req_missing_ipynb()
     c = Config(self.site.config['IPYNB_CONFIG'])
     c.update(get_default_jupyter_config())
     if 'template_file' not in self.site.config['IPYNB_CONFIG'].get('Exporter', {}):
         c['Exporter']['template_file'] = 'basic.tpl'  # not a typo
     exportHtml = HTMLExporter(config=c)
     body, _ = exportHtml.from_notebook_node(nb_json)
     return body
示例#5
0
文件: ipynb.py 项目: guyou/nikola
 def compile_html_string(self, source, is_two_file=True):
     """Export notebooks as HTML strings."""
     if flag is None:
         req_missing(['ipython[notebook]>=2.0.0'], 'build this site (compile ipynb)')
     c = Config(self.site.config['IPYNB_CONFIG'])
     exportHtml = HTMLExporter(config=c)
     with io.open(source, "r", encoding="utf8") as in_file:
         nb_json = nbformat.read(in_file, current_nbformat)
     (body, resources) = exportHtml.from_notebook_node(nb_json)
     return body
示例#6
0
def main(app):
    static_dir = os.path.join(app.builder.srcdir, '_static')
    target_dir = os.path.join(app.builder.srcdir, 'notebooks')
    source_dir = os.path.abspath(os.path.join(app.builder.srcdir,
                                              '..', 'notebooks'))

    rendered_dir = os.path.join(target_dir, 'rendered')

    if not os.path.exists(static_dir):
        os.makedirs(static_dir)

    if not os.path.exists(target_dir):
        os.makedirs(target_dir)

    if not os.path.exists(rendered_dir):
        os.makedirs(rendered_dir)

    nbroots = []
    nbtitles = []
    exporter = HTMLExporter(template_file='full')

    for nb_src in glob.glob(os.path.join(source_dir, '*.ipynb')):
        print("converting notebook {0}".format(nb_src))
        basedir, nbname = os.path.split(nb_src)
        nb_dest = os.path.join(target_dir, nbname)
        shutil.copyfile(nb_src, nb_dest)

        with open(nb_dest, 'r') as f:
            nb_json = nbformat.reads(f.read(), as_version = 4)

        (body, resources) = exporter.from_notebook_node(nb_json)

        root, ext = os.path.splitext(nbname)
        nb_html_dest = os.path.join(rendered_dir, root + '.html')
        with open(nb_html_dest, 'w') as f:
            f.write(body)

        nbroots.append(root)
        nbtitles.append(get_notebook_title(nb_json, root))

    for nbroot, nbtitle in zip(nbroots, nbtitles):
        with open(os.path.join(target_dir, nbroot + '.rst'), 'w') as f:
            f.write(RST_TEMPLATE.render(title=nbtitle, nbroot=nbroot))

    with open(os.path.join(target_dir, 'index.rst'), 'w') as f:
        f.write(INDEX_TEMPLATE.render(notebooks=nbroots,
                                      sphinx_tag='notebook-examples'))
示例#7
0
    def render(self):
        try:
            with open(self.file_path, 'r') as file_pointer:
                notebook = nbformat.reads(file_pointer.read(), as_version=4)
        except ValueError:
            raise exceptions.InvalidFormat('Could not read ipython notebook file.')

        exporter = HTMLExporter(config=Config({
            'HTMLExporter': {
                'template_file': 'basic',
            },
            'CSSHtmlHeaderTransformer': {
                'enabled': False,
            },
        }))
        (body, _) = exporter.from_notebook_node(notebook)
        return self.TEMPLATE.render(base=self.assets_url, body=body)
    def render(self):
        try:
            with open(self.file_path, 'r') as file_pointer:
                notebook = nbformat.reads(file_pointer.read(), as_version=4)
        except ValueError as err:
            raise exceptions.InvalidFormatError(
                'Could not read ipython notebook file. {}'.format(str(err)),
                extension=self.metadata.ext,
                download_url=str(self.metadata.download_url),
                original_exception=err,
            )

        exporter = HTMLExporter(config=Config({
            'HTMLExporter': {
                'template_file': 'basic',
            },
            'CSSHtmlHeaderTransformer': {
                'enabled': False,
            },
        }))
        (body, _) = exporter.from_notebook_node(notebook)
        return self.TEMPLATE.render(base=self.assets_url, body=body)
示例#9
0
def page_html(ntbk,
              path_media_output=None,
              name=None,
              preprocessors=None,
              execute_dir=False,
              kernel_name=None,
              clear_output=False):
    """Build the HTML for a single notebook page.

    Inputs
    ======

    ntbk : Instance of NotebookNode
        The notebook that we'll convert to a page's HTML.
    path_media_output : string | None
        If a string, the path to where images should be extracted, relative
        to wherever you will write the final HTML file. If None,
        images will be embedded in the HTML. Note that this will not actually
        write the images. To do so, use the `write_page` function.
    name : string | None
        The name of the notebook being converted. This will be used if
        `path_media_output` is noe None in order to create unique media
        file names.
    preprocessors : list of NBConvert Preprocessors | None
        Any extra preprocessors to add to the end of the preprocessor chain
        in the HTMLConverter.
    execute_dir : string | None
        Execute the notebook with a kernel started in the directory specified
        with this argument. If None, the notebook will not be executed.
    kernel_name : string
        The name of the kernel to use if we execute notebooks.
    clear_output: bool
        To remove the output from notebook

    Returns
    =======
    page : HTML document
        The input content file converted to HTML format.
    """

    if preprocessors is None:
        preprocessors = []
    elif not isinstance(preprocessors, (list, tuple)):
        preprocessors = [preprocessors]

    if name is None:
        name = "notebook"

    ########################################
    # Notebook cleaning
    _clean_markdown_cells(ntbk)

    #############################################
    # Preprocessor configuration
    c = Config()

    # Remove cell elements using tags
    c.TagRemovePreprocessor.remove_cell_tags = ("remove_cell", "removecell")
    c.TagRemovePreprocessor.remove_all_outputs_tags = ("remove_output", )
    c.TagRemovePreprocessor.remove_input_tags = ("remove_input", )

    # Remove any cells that are *only* whitespace
    c.RegexRemovePreprocessor.patterns = ["\\s*\\Z"]

    c.HTMLExporter.preprocessors = [
        "nbconvert.preprocessors.TagRemovePreprocessor",
        "nbconvert.preprocessors.RegexRemovePreprocessor",
    ]

    if clear_output:
        c.HTMLExporter.preprocessors.append(
            'nbconvert.preprocessors.ClearOutputPreprocessor')

    if path_media_output is not None:
        # So the images are written to disk
        c.HTMLExporter.preprocessors.append(
            "nbconvert.preprocessors.ExtractOutputPreprocessor")

    # Add extra preprocessors given by the user
    for preprocessor in preprocessors:
        c.HTMLExporter.preprocessors.append(preprocessor)

    # The text used as the text for anchor links.
    # The text used as the text for anchor links.
    # TEMPORATILY Set to empty since we'll use anchor.js for the links
    # Once https://github.com/jupyter/nbconvert/pull/1101 is fixed
    # set to '<i class="fas fa-link"> </i>'
    c.HTMLExporter.anchor_link_text = " "

    # Excluding input/output prompts
    c.HTMLExporter.exclude_input_prompt = True
    c.HTMLExporter.exclude_output_prompt = True

    #############################################
    # Run and convert to HTML

    # Excution of the notebook if we wish
    if execute_dir is not None:
        ntbk = run_ntbk(ntbk, execute_dir, allow_errors=True)

    # Generate HTML from our notebook using the template
    output_resources = {
        "output_files_dir": path_media_output,
        "unique_key": name
    }
    exp = HTMLExporter(template_file=PATH_TEMPLATE, config=c)
    html, resources = exp.from_notebook_node(ntbk, resources=output_resources)

    html = f"""
    <main class="jupyter-page">
    {html}
    </main>
    """
    return html, resources
示例#10
0
def notebook(preprocessor, tag, markup):
    match = FORMAT.search(markup)
    if match:
        argdict = match.groupdict()
        src = argdict['src']
        start = argdict['start']
        end = argdict['end']
        language = argdict['language']
    else:
        raise ValueError("Error processing input, "
                         "expected syntax: {0}".format(SYNTAX))

    if start:
        start = int(start)
    else:
        start = 0

    if end:
        end = int(end)
    else:
        end = None

    language_applied_highlighter = partial(custom_highlighter, language=language)

    nb_dir =  preprocessor.configs.getConfig('NOTEBOOK_DIR')
    nb_path = os.path.join('content', nb_dir, src)

    if not os.path.exists(nb_path):
        raise ValueError("File {0} could not be found".format(nb_path))

    # Create the custom notebook converter
    c = Config({'CSSHTMLHeaderTransformer':
                    {'enabled':True, 'highlight_class':'.highlight-ipynb'},
                'SubCell':
                    {'enabled':True, 'start':start, 'end':end}})

    template_file = 'basic'
    if IPYTHON_VERSION >= 3:
        if os.path.exists('pelicanhtml_3.tpl'):
            template_file = 'pelicanhtml_3'
    elif IPYTHON_VERSION == 2:
        if os.path.exists('pelicanhtml_2.tpl'):
            template_file = 'pelicanhtml_2'
    else:
        if os.path.exists('pelicanhtml_1.tpl'):
            template_file = 'pelicanhtml_1'

    if IPYTHON_VERSION >= 2:
        subcell_kwarg = dict(preprocessors=[SubCell])
    else:
        subcell_kwarg = dict(transformers=[SubCell])

    exporter = HTMLExporter(config=c,
                            template_file=template_file,
                            filters={'highlight2html': language_applied_highlighter},
                            **subcell_kwarg)

    # read and parse the notebook
    with open(nb_path, encoding="utf-8") as f:
        nb_text = f.read()
        if IPYTHON_VERSION < 3:
            nb_json = IPython.nbformat.current.reads_json(nb_text)
        else:
            try:
                nb_json = nbformat.reads(nb_text, as_version=4)
            except:
                nb_json = IPython.nbformat.reads(nb_text, as_version=4)

    (body, resources) = exporter.from_notebook_node(nb_json)

    # if we haven't already saved the header, save it here.
    if not notebook.header_saved:
        print ("\n ** Writing styles to _nb_header.html: "
               "this should be included in the theme. **\n")

        header = '\n'.join(CSS_WRAPPER.format(css_line)
                           for css_line in resources['inlining']['css'])
        header += JS_INCLUDE

        with open('_nb_header.html', 'w', encoding="utf-8") as f:
            f.write(header)
        notebook.header_saved = True

    # this will stash special characters so that they won't be transformed
    # by subsequent processes.
    body = preprocessor.configs.htmlStash.store(body, safe=True)
    return body
示例#11
0
def get_html_data(nb, resources, **kw):
    he = HTMLExporter()
    html_data, resources = he.from_notebook_node(nb, resources, **kw)
    html_data = html_data.replace('@media print', '@media xxprintxx')
    return html_data
示例#12
0
    def get(self, prepath, user, filename):
        ## filename can have a path on it
        next = "/%s/hub/%s/public/%s" % (prepath, user, filename)
        filesystem_path = "/home/%s/public_html/%s" % (user, filename)
        if os.path.isfile(filesystem_path): # download, raw, or view notebook
            command = "view"
            if len(self.get_arguments("view")) > 0:
                command = "view"
            elif len(self.get_arguments("download")) > 0:
                command = "download" 
            elif len(self.get_arguments("copy")) > 0:
                command = "copy" 
            elif len(self.get_arguments("pdf")) > 0:
                command = "pdf" 
            elif len(self.get_arguments("raw")) > 0:
                command = "raw" 
            # else:  view
            if filename.endswith(".ipynb"):
                if command in ["view", "pdf"]:
                    # first, make a notebook html:
                    #with open("/home/%s/public_html/%s" % (user, filename)) as fp:
                    #    notebook_content = fp.read()
                    if command == "view":
                        exporter = HTMLExporter(template_file='full-tabs')
                    else:
                        exporter = PDFExporter(latex_count=1)
                    
                    nb_json = nbformat.read("/home/%s/public_html/%s" % (user, filename), as_version=4)
                    #if command == "pdf":
                    #    # If pdf, remove heading numbering:
                    #    for cell in nb_json["worksheets"][0]["cells"]:
                    #        if cell["cell_type"] == "heading":
                    #            cell["source"] = re.sub("^([0-9]+\.?)+\s", "", cell["source"])
                    # where to get css, images?
                    if command == "pdf":
                        self.set_header('Content-Type', "application/pdf")
                        base_filename = os.path.basename(filename)
                        self.set_header('Content-Disposition', 'attachment; filename="%s"' % base_filename)
                    else: # render as HTML
                        # add header/footer:
                        path = "/%s/hub/%s/public" % (prepath, user)
                        parts = [(path, path)]
                        for part in filename.split("/")[:-1]:
                            path += "/" + part
                            parts.append((path, part))
                        breadcrumbs = " / ".join(map(lambda pair: '<a href="%s" target="_blank">%s</a>' % pair, parts))
                        env = {
                            "breadcrumbs": breadcrumbs,
                            "url": "https://athena.brynmawr.edu/" + next + "?download"
                        }
                        cell = new_markdown_cell(source="""<table width="100%" style="border: none;">
<tr style="border: none;">
  <td style="border: none;" width="100px">
    <img src="https://blog.jupyter.org/content/images/2015/02/jupyter-sq-text.png" width="100"/> 
  </td>
  <td style="border: none;" width="50%">
    <h2><a href="https://athena.brynmawr.edu/">Jupyter at Bryn Mawr College</a></h2>
  </td>
  <td style="border: none;">
        <a href="https://athena.brynmawr.edu/jupyter/hub/dblank/public/Jupyter%20Help.ipynb" title="Help">
            <span class="fa fa-info-circle fa-2x menu-icon"></span>
            <span class="menu-text">Help</span>
        </a>
  </td>
  <td style="border: none;">
        <a href="{url}" title="Download Notebook" download>
            <span class="fa fa-download fa-2x menu-icon"></span>
            <span class="menu-text">Download Notebook</span>
        </a>
  </td>
</tr>
<tr style="border: none;">
  <td colspan="4" style="border: none;">
      <b>Public notebooks:</b> {breadcrumbs}
  </td>
</tr>
</table>""".format(**env))
                        nb_json["cells"].insert(0, cell)
                    (body, resources) = exporter.from_notebook_node(nb_json)
                    self.write(body)
                elif command == "download": # download notebook json
                    self.download(user, filename, "text/plain")
                elif command == "copy": # copy notebook json, if logged in
                    if self.get_current_user_name():
                        self.copy_file(user, filename, self.get_current_user_name())
                    else:
                        self.write("Please <a href=\"/%s/hub/login?next=%s\">login</a> to allow copy." % (prepath, next))
                else: # raw, just get file contents
                    with open("/home/%s/public_html/%s" % (user, filename), "rb") as fp:
                        self.write(fp.read())
            else: # some other kind of file
                # FIXME: how to get all of custom stuff?
                if command == "copy":
                    if self.get_current_user_name():
                        self.copy_file(user, filename, self.get_current_user_name())
                    else:
                        self.write("Please <a href=\"/%s/hub/login?next=%s\">login</a> to allow copy." % (prepath, next))
                else: # whatever, just get or download it
                    base_filename = os.path.basename(filename)
                    base, ext = os.path.splitext(base_filename)
                    app_log.info("extension is: %s" % ext)
                    if base_filename == "custom.css":
                        file_path = "/home/%s/.ipython/profile_default/static/custom/custom.css" % user
                        self.set_header('Content-Type', "text/css")
                        with open(file_path, "rb") as fp:
                            self.write(fp.read())
                    elif ext in [".txt", ".html", ".js", ".css", ".pdf", ".gif", ".jpeg", ".jpg", ".png"]: # show in browser
                        app_log.info("mime: %s" % str(mimetypes.guess_type(filename)[0]))
                        self.set_header('Content-Type', mimetypes.guess_type(filename)[0])
                        with open("/home/%s/public_html/%s" % (user, filename), "rb") as fp:
                            self.write(fp.read())
                    else:
                        self.download(user, filename)
        else: # not a file; directory listing
            # filename can have a full path, and might be empty
            url_path = "/%s/hub/%s/public" % (prepath, user)

            ##
            path = "/%s/hub/%s/public" % (prepath, user)
            parts = [(path, path)]
            for part in filename.split("/")[:]:
                path += "/" + part
                parts.append((path, part))
            breadcrumbs = " / ".join(map(lambda pair: '<a href="%s" target="_blank">%s</a>' % pair, parts))
            ##
            # could be: images, images/, images/subdir, images/subdir/
            if not filename.endswith("/") and filename.strip() != "":
                filename += "/"
            files = glob.glob("/home/%s/public_html/%s*" % (user, filename))
            self.write("<h1>Jupyter Project at Bryn Mawr College</h1>\n")
            self.write("[<a href=\"/jupyter/hub/login\">Home</a>] ")
            if self.get_current_user_name():
                self.write("[<a href=\"/user/%(current_user)s/tree\">%(current_user)s</a>] " % {"current_user": self.get_current_user_name()})
            self.write("<p/>\n")
            self.write("<p>Public notebooks: %s </p>\n" % breadcrumbs)
            self.write("<ol>\n")
            for absolute_filename in sorted(files):
                if os.path.isdir(absolute_filename): 
                    dir_path = absolute_filename.split("/")
                    dir_name = dir_path[-1]
                    public_path = "/".join(dir_path[dir_path.index("public_html") + 1:])
                    self.write("<li><a href=\"%(url_path)s/%(public_path)s\">%(dir_name)s</a></li>\n" % {"url_path": url_path, 
                                                                                                      "dir_name": dir_name,
                                                                                                      "public_path": public_path})
                else:
                    file_path, filename = absolute_filename.rsplit("/", 1)
                    dir_path = absolute_filename.split("/")
                    public_path = "/".join(dir_path[dir_path.index("public_html") + 1:])
                    variables = {"user": user, "filename": filename, "url_path": url_path, "next": next,
                                 "public_path": public_path}
                    if filename.endswith(".ipynb"):
                        if self.get_current_user_name():
                            self.write(("<li><a href=\"%(url_path)s/%(public_path)s\">%(filename)s</a> "+
                                        #"(<a href=\"%(url_path)s/%(public_path)s?raw\">raw</a>, " +
                                        "(<a href=\"%(url_path)s/%(public_path)s?download\">download</a>" +
                                        #"<a href=\"%(url_path)s/%(public_path)s?copy\">copy</a>" +
                                        #((", <a href=\"/user/%s/notebooks/public_html/%s\">edit</a>" % (user, filename)) if self.get_current_user_name() == user else ", edit") +
                                        ")</li>\n") % variables)
                        else:
                            self.write(("<li><a href=\"%(url_path)s/%(public_path)s\">%(filename)s</a> "+
                                        #"(<a href=\"%(url_path)s/%(public_path)s?raw\">raw</a>, " +
                                        "(<a href=\"%(url_path)s/%(public_path)s?download\">download</a>)" +
                                        #"copy, edit) " +
                                        #"[<a href=\"/jupyter/hub/login?next=%(next)s\">login</a> to copy]</li>\n") % variables)
                                        "</li>\n") % variables)
                    else:
                        # some other kind of file (eg, .zip, .css):
                        self.write("<li><a href=\"%(url_path)s/%(public_path)s\">%(filename)s</a></li>\n" % variables)
            self.write("</ol>\n")
            self.write("<hr>\n")
            self.write("<p><i>Please see <a href=\"/jupyter/hub/dblank/public/Jupyter Help.ipynb\">Jupyter Help</a> for more information about this server.</i></p>\n")
示例#13
0
def notebook(preprocessor, tag, markup):
    match = FORMAT.search(markup)
    if match:
        argdict = match.groupdict()
        src = argdict["src"]
        start = argdict["start"]
        end = argdict["end"]
        language = argdict["language"]
    else:
        raise ValueError("Error processing input, " "expected syntax: {0}".format(SYNTAX))

    if start:
        start = int(start)
    else:
        start = 0

    if end:
        end = int(end)
    else:
        end = None

    language_applied_highlighter = partial(custom_highlighter, language=language)

    nb_dir = preprocessor.configs.getConfig("NOTEBOOK_DIR")
    nb_path = os.path.join("content", nb_dir, src)

    if not os.path.exists(nb_path):
        raise ValueError("File {0} could not be found".format(nb_path))

    # Create the custom notebook converter
    c = Config(
        {
            "CSSHTMLHeaderTransformer": {"enabled": True, "highlight_class": ".highlight-ipynb"},
            "SubCell": {"enabled": True, "start": start, "end": end},
        }
    )

    template_file = "basic"
    if IPYTHON_VERSION >= 3:
        if os.path.exists("pelicanhtml_3.tpl"):
            template_file = "pelicanhtml_3"
    elif IPYTHON_VERSION == 2:
        if os.path.exists("pelicanhtml_2.tpl"):
            template_file = "pelicanhtml_2"
    else:
        if os.path.exists("pelicanhtml_1.tpl"):
            template_file = "pelicanhtml_1"

    if IPYTHON_VERSION >= 2:
        subcell_kwarg = dict(preprocessors=[SubCell])
    else:
        subcell_kwarg = dict(transformers=[SubCell])

    exporter = HTMLExporter(
        config=c, template_file=template_file, filters={"highlight2html": language_applied_highlighter}, **subcell_kwarg
    )

    # read and parse the notebook
    with open(nb_path) as f:
        nb_text = f.read()
        if IPYTHON_VERSION < 3:
            nb_json = IPython.nbformat.current.reads_json(nb_text)
        else:
            try:
                nb_json = nbformat.reads(nb_text, as_version=4)
            except:
                nb_json = IPython.nbformat.reads(nb_text, as_version=4)

    (body, resources) = exporter.from_notebook_node(nb_json)

    # if we haven't already saved the header, save it here.
    if not notebook.header_saved:
        print("\n ** Writing styles to _nb_header.html: " "this should be included in the theme. **\n")

        header = "\n".join(CSS_WRAPPER.format(css_line) for css_line in resources["inlining"]["css"])
        header += JS_INCLUDE

        with open("_nb_header.html", "w") as f:
            f.write(header)
        notebook.header_saved = True

    # this will stash special characters so that they won't be transformed
    # by subsequent processes.
    body = preprocessor.configs.htmlStash.store(body, safe=True)
    return body
示例#14
0
def notebook(preprocessor, tag, markup):
    match = FORMAT.search(markup)
    if match:
        argdict = match.groupdict()
        src = argdict["src"]
        start = argdict["start"]
        end = argdict["end"]
        language = argdict["language"]
    else:
        raise ValueError("Error processing input, "
                         "expected syntax: {0}".format(SYNTAX))

    if start:
        start = int(start)
    else:
        start = 0

    if end:
        end = int(end)
    else:
        end = None

    language_applied_highlighter = partial(custom_highlighter,
                                           language=language)

    nb_dir = preprocessor.configs.getConfig("NOTEBOOK_DIR")
    nb_path = os.path.join("content", src)

    if not os.path.exists(nb_path):
        raise ValueError("File {0} could not be found".format(nb_path))

    # Create the custom notebook converter
    c = Config({
        "CSSHTMLHeaderTransformer": {
            "enabled": True,
            "highlight_class": ".highlight-ipynb",
        },
        "SubCell": {
            "enabled": True,
            "start": start,
            "end": end
        },
    })

    template_file = "basic"
    if IPYTHON_VERSION >= 3:
        if os.path.exists("pelicanhtml_3.tpl"):
            template_file = "pelicanhtml_3"
    elif IPYTHON_VERSION == 2:
        if os.path.exists("pelicanhtml_2.tpl"):
            template_file = "pelicanhtml_2"
    else:
        if os.path.exists("pelicanhtml_1.tpl"):
            template_file = "pelicanhtml_1"

    if IPYTHON_VERSION >= 2:
        subcell_kwarg = dict(preprocessors=[SubCell])
    else:
        subcell_kwarg = dict(transformers=[SubCell])

    exporter = HTMLExporter(
        config=c,
        template_file=template_file,
        filters={"highlight2html": language_applied_highlighter},
        **subcell_kwarg)

    # read and parse the notebook
    with open(nb_path, encoding="utf-8") as f:
        nb_text = f.read()
        if IPYTHON_VERSION < 3:
            nb_json = IPython.nbformat.current.reads_json(nb_text)
        else:
            try:
                nb_json = nbformat.reads(nb_text, as_version=4)
            except:
                nb_json = IPython.nbformat.reads(nb_text, as_version=4)

    (body, resources) = exporter.from_notebook_node(nb_json)

    # if we haven't already saved the header, save it here.
    if not notebook.header_saved:
        print("\n ** Writing styles to _nb_header.html: "
              "this should be included in the theme. **\n")

        header = "\n".join(
            CSS_WRAPPER.format(css_line)
            for css_line in resources["inlining"]["css"])
        header += JS_INCLUDE

        with open("_nb_header.html", "w") as f:
            f.write(header)
        notebook.header_saved = True

    # this will stash special characters so that they won't be transformed
    # by subsequent processes.
    body = preprocessor.configs.htmlStash.store(body)
    return body
示例#15
0
def notebook(preprocessor, tag, markup):
    match = FORMAT.search(markup)
    if match:
        argdict = match.groupdict()
        src = argdict['src']
        start = argdict['start']
        end = argdict['end']
        language = argdict['language']
    else:
        raise ValueError("Error processing input, "
                         "expected syntax: {0}".format(SYNTAX))

    if start:
        start = int(start)
    else:
        start = 0

    if end:
        end = int(end)
    else:
        end = None

    language_applied_highlighter = partial(custom_highlighter,
                                           language=language)

    nb_dir = preprocessor.configs.getConfig('NOTEBOOK_DIR')
    nb_path = os.path.join('content', nb_dir, src)

    if not os.path.exists(nb_path):
        raise ValueError("File {0} could not be found".format(nb_path))

    # Create the custom notebook converter
    c = Config({
        'CSSHTMLHeaderTransformer': {
            'enabled': True,
            'highlight_class': '.highlight-ipynb'
        },
        'SubCell': {
            'enabled': True,
            'start': start,
            'end': end
        }
    })

    template_file = 'basic'
    if IPYTHON_VERSION >= 3:
        if os.path.exists('pelicanhtml_3.tpl'):
            template_file = 'pelicanhtml_3'
    elif IPYTHON_VERSION == 2:
        if os.path.exists('pelicanhtml_2.tpl'):
            template_file = 'pelicanhtml_2'
    else:
        if os.path.exists('pelicanhtml_1.tpl'):
            template_file = 'pelicanhtml_1'

    if IPYTHON_VERSION >= 2:
        subcell_kwarg = dict(preprocessors=[SubCell])
    else:
        subcell_kwarg = dict(transformers=[SubCell])

    exporter = HTMLExporter(
        config=c,
        template_file=template_file,
        filters={'highlight2html': language_applied_highlighter},
        **subcell_kwarg)

    # read and parse the notebook
    with open(nb_path, encoding='utf-8') as f:
        nb_text = f.read()
        if IPYTHON_VERSION < 3:
            nb_json = IPython.nbformat.current.reads_json(nb_text)
        else:
            try:
                nb_json = nbformat.reads(nb_text, as_version=4)
            except:
                nb_json = IPython.nbformat.reads(nb_text, as_version=4)

    (body, resources) = exporter.from_notebook_node(nb_json)

    # if we haven't already saved the header, save it here.
    if not notebook.header_saved:
        print("\n ** Writing styles to _nb_header.html: "
              "this should be included in the theme. **\n")

        header = u'\n'.join(
            CSS_WRAPPER.format(css_line)
            for css_line in resources['inlining']['css'])
        header += JS_INCLUDE

        with open('_nb_header.html', 'w') as f:
            f.write(header)
        notebook.header_saved = True

    # this will stash special characters so that they won't be transformed
    # by subsequent processes.
    body = preprocessor.configs.htmlStash.store(body)
    return body
示例#16
0
def build_page(path_ntbk,
               path_html_output,
               path_media_output=None,
               execute=False,
               path_template=None,
               verbose=False,
               kernel_name=None,
               clear_output=False):
    """Build the HTML for a single notebook page.

    Inputs
    ======

    path_ntbk : string
        The path to a notebook or text file we want to convert. If a text
        file, then Jupytext will be used to convert into a notebook. This
        will also cause the notebook to be *run* (e.g. execute=True).
    path_html_output : string
        The path to the folder where the HTML will be output.
    path_media_output : string | None
        If a string, the path to where images should be extracted. If None,
        images will be embedded in the HTML.
    execute : bool
        Whether to execute the notebook before converting
    path_template : string
        A path to the template used in conversion.
    kernel_name : string
        The name of the kernel to use if we execute notebooks.
    clear_output: bool
        To remove the output from notebook
    """

    ########################################
    # Load in the notebook
    notebook_name, suff = op.splitext(op.basename(path_ntbk))

    is_raw_markdown_file = False
    if suff in ['.md', '.markdown']:
        # If it's a markdown file, we need to check whether it's a jupytext format
        with open(path_ntbk, 'r') as ff:
            lines = ff.readlines()
            yaml_lines, content = _split_yaml(lines)
            yaml = YAML().load(''.join(yaml_lines))

        if (yaml is not None) and yaml.get('jupyter', {}).get('jupytext'):
            # If we have jupytext metadata, then use it to read the markdown file
            ntbk = jpt.reads(''.join(lines), 'md')
        else:
            # Otherwise, create an empty notebook and add all of the file contents as a markdown file
            is_raw_markdown_file = True
            ntbk = nbf.v4.new_notebook()
            ntbk['cells'].append(
                nbf.v4.new_markdown_cell(source=''.join(content)))
    else:
        # If it's not markdown, we assume it's either ipynb or a jupytext format
        ntbk = jpt.read(path_ntbk)

    if _is_jupytext_file(ntbk):
        execute = True

    ########################################
    # Notebook cleaning

    # Minor edits to cells
    _clean_markdown_cells(ntbk)

    #############################################
    # Conversion to HTML
    # create a configuration object that changes the preprocessors
    c = Config()

    c.FilesWriter.build_directory = path_html_output

    # Remove cell elements using tags
    c.TagRemovePreprocessor.remove_cell_tags = ("remove_cell", "removecell")
    c.TagRemovePreprocessor.remove_all_outputs_tags = ('remove_output', )
    c.TagRemovePreprocessor.remove_input_tags = ('remove_input', )

    # Remove any cells that are *only* whitespace
    c.RegexRemovePreprocessor.patterns = ["\\s*\\Z"]

    c.HTMLExporter.preprocessors = [
        'nbconvert.preprocessors.TagRemovePreprocessor',
        'nbconvert.preprocessors.RegexRemovePreprocessor',
        # So the images are written to disk
        'nbconvert.preprocessors.ExtractOutputPreprocessor',
        # Wrap cells in Jekyll raw tags
        _RawCellPreprocessor,
    ]

    if clear_output:
        c.HTMLExporter.preprocessors.append(
            'nbconvert.preprocessors.ClearOutputPreprocessor')

    # The text used as the text for anchor links.
    # TEMPORATILY Set to empty since we'll use anchor.js for the links
    # Once https://github.com/jupyter/nbconvert/pull/1101 is fixed
    # set to '<i class="fas fa-link"> </i>'
    c.HTMLExporter.anchor_link_text = ' '

    # Excluding input/output prompts
    c.HTMLExporter.exclude_input_prompt = True
    c.HTMLExporter.exclude_output_prompt = True

    # Excution of the notebook if we wish
    if execute is True:
        ntbk = run_ntbk(ntbk, op.dirname(path_ntbk))

    # Define the path to images and then the relative path to where they'll originally be placed
    if isinstance(path_media_output, str):
        path_media_output_rel = op.relpath(path_media_output, path_html_output)

    # Generate HTML from our notebook using the template
    output_resources = {
        'output_files_dir': path_media_output_rel,
        'unique_key': notebook_name
    }
    exp = HTMLExporter(template_file=path_template, config=c)
    html, resources = exp.from_notebook_node(ntbk, resources=output_resources)
    html = '<main class="jupyter-page">\n' + html + '\n</main>\n'

    # Now write the markdown and resources
    writer = FilesWriter(config=c)
    writer.write(html, resources, notebook_name=notebook_name)

    # Add the frontmatter to the yaml file in case it's wanted
    if is_raw_markdown_file and len(yaml_lines) > 0:
        with open(op.join(path_html_output, notebook_name + '.html'),
                  'r') as ff:
            md_lines = ff.readlines()
        md_lines.insert(0, '---\n')
        for iline in yaml_lines[::-1]:
            md_lines.insert(0, iline + '\n')
        md_lines.insert(0, '---\n')
        with open(op.join(path_html_output, notebook_name + '.html'),
                  'w') as ff:
            ff.writelines(md_lines)

    if verbose:
        print("Finished writing notebook to {}".format(path_html_output))
示例#17
0
    def get(self, user, filename):
        ## filename can have a path on it
        prefix = os.environ['JUPYTERHUB_SERVICE_PREFIX']
        next = "%s/%s/%s" % (prefix, user, filename)
        filesystem_path = "/home/%s/public_html/%s" % (user, filename)
        if filename and filename.endswith(".raw.ipynb"):
            filename = filename[:-10] + ".ipynb"
            self.set_header('Content-Type', "application/json")
            with open("/home/%s/public_html/%s" % (user, filename),
                      "rb") as fp:
                self.write(fp.read())
            return
        elif os.path.isfile(
                filesystem_path):  # download, raw, or view notebook
            command = "view"
            if len(self.get_arguments("view")) > 0:
                command = "view"
            elif len(self.get_arguments("download")) > 0:
                command = "download"
            elif len(self.get_arguments("pdf")) > 0:
                command = "pdf"
            elif len(self.get_arguments("raw")) > 0:
                command = "raw"
            # else:  view
            if filename.endswith(".ipynb"):
                if command in ["view", "pdf"]:
                    if command == "view":
                        exporter = HTMLExporter(template_file='full-tabs')
                    else:
                        exporter = PDFExporter(latex_count=1)

                    nb_json = nbformat.read("/home/%s/public_html/%s" %
                                            (user, filename),
                                            as_version=4)
                    if command == "pdf":
                        self.set_header('Content-Type', "application/pdf")
                        base_filename = os.path.basename(filename)
                        self.set_header(
                            'Content-Disposition',
                            'attachment; filename="%s"' % base_filename)
                    else:  # render as HTML
                        # add header/footer:
                        path = "%s/%s" % (prefix, user)
                        parts = [(path, path)]
                        for part in filename.split("/")[:-1]:
                            path += "/" + part
                            parts.append((path, part))
                        breadcrumbs = " / ".join(
                            map(
                                lambda pair:
                                '<a href="%s" target="_blank">%s</a>' % pair,
                                parts))
                        env = {
                            "breadcrumbs": breadcrumbs,
                            "url": next + "?download",
                            "prefix": prefix,
                        }
                        cell = new_markdown_cell(
                            source="""<table width="100%" style="border: none;">
<tr style="border: none;">
  <td style="border: none;" width="100px">
    <img src="https://blog.jupyter.org/content/images/2015/02/jupyter-sq-text.png" width="100"/> 
  </td>
  <td style="border: none;" width="50%">
    <h2><a href="/">Jupyter at Bryn Mawr College</a></h2>
  </td>
  <td style="border: none;">
                        <a href="{prefix}/dblank/Jupyter%20Help.ipynb" title="Help">
            <img src="https://upload.wikimedia.org/wikipedia/commons/a/ae/High-contrast-help-browser.svg" style="border: none" width="32"></img> 
        </a>
  </td>
  <td style="border: none;">
        <a href="{url}" title="Download Notebook" download>
            <img src="https://upload.wikimedia.org/wikipedia/commons/8/8d/Download_alt_font_awesome.svg" style="border: none" width="32"></img>
        </a>
  </td>
</tr>
<tr style="border: none;">
  <td colspan="4" style="border: none;">
      <b>Public notebooks:</b> {breadcrumbs}
  </td>
</tr>
</table>""".format(**env))
                        nb_json["cells"].insert(0, cell)
                    (body, resources) = exporter.from_notebook_node(nb_json)
                    body = body.replace(
                        '<title>Notebook</title>',
                        '<title>%s</title>' % filename.split("/")[-1])
                    self.write(body)
                elif command == "download":  # download notebook json
                    self.download(user, filename, "text/plain")
                else:  # raw, just get file contents
                    self.set_header('Content-Type', "application/json")
                    with open("/home/%s/public_html/%s" % (user, filename),
                              "rb") as fp:
                        self.write(fp.read())
            else:  # some other kind of file
                # FIXME: how to get all of custom stuff?
                if True:  # whatever, just get or download it
                    base_filename = os.path.basename(filename)
                    base, ext = os.path.splitext(base_filename)
                    app_log.info("extension is: %s" % ext)
                    if base_filename == "custom.css":
                        file_path = "/home/%s/.ipython/profile_default/static/custom/custom.css" % user
                        self.set_header('Content-Type', "text/css")
                        with open(file_path, "rb") as fp:
                            self.write(fp.read())
                    elif ext in [
                            ".txt", ".html", ".js", ".css", ".pdf", ".gif",
                            ".jpeg", ".jpg", ".png"
                    ]:  # show in browser
                        app_log.info("mime: %s" %
                                     str(mimetypes.guess_type(filename)[0]))
                        self.set_header('Content-Type',
                                        mimetypes.guess_type(filename)[0])
                        with open("/home/%s/public_html/%s" % (user, filename),
                                  "rb") as fp:
                            self.write(fp.read())
                    else:
                        self.download(user, filename)
        else:  # not a file; directory listing
            # filename can have a full path, and might be empty
            url_path = "%s/%s" % (prefix, user)
            ##
            path = "%s/%s" % (prefix, user)
            parts = [(path, path)]
            for part in filename.split("/")[:]:
                path += "/" + part
                parts.append((path, part))
            breadcrumbs = " / ".join(
                map(lambda pair: '<a href="%s" target="_blank">%s</a>' % pair,
                    parts))
            ##
            # could be: images, images/, images/subdir, images/subdir/
            if not filename.endswith("/") and filename.strip() != "":
                filename += "/"
            files = glob.glob("/home/%s/public_html/%s*" % (user, filename))
            self.write("<h1>Jupyter Project at Bryn Mawr College</h1>\n")
            self.write("[<a href=\"/hub/login\">Home</a>] ")
            if self.get_current_user_name():
                self.write(
                    "[<a href=\"/user/%(current_user)s/tree\">%(current_user)s</a>] "
                    % {"current_user": self.get_current_user_name()})
            self.write("<p/>\n")
            self.write("<p>Public notebooks: %s </p>\n" % breadcrumbs)
            self.write("<ol>\n")
            for absolute_filename in sorted(files):
                if os.path.isdir(absolute_filename):
                    dir_path = absolute_filename.split("/")
                    dir_name = dir_path[-1]
                    public_path = "/".join(
                        dir_path[dir_path.index("public_html") + 1:])
                    self.write(
                        "<li><a href=\"%(url_path)s/%(public_path)s\">%(dir_name)s</a></li>\n"
                        % {
                            "url_path": url_path,
                            "dir_name": dir_name,
                            "public_path": public_path
                        })
                else:
                    file_path, filename = absolute_filename.rsplit("/", 1)
                    dir_path = absolute_filename.split("/")
                    public_path = "/".join(
                        dir_path[dir_path.index("public_html") + 1:])
                    variables = {
                        "user": user,
                        "filename": filename,
                        "url_path": url_path,
                        "next": next,
                        "public_path": public_path
                    }
                    if filename.endswith(".ipynb"):
                        if self.get_current_user_name():
                            self.write((
                                "<li><a href=\"%(url_path)s/%(public_path)s\">%(filename)s</a> "
                                +
                                "(<a href=\"%(url_path)s/%(public_path)s?download\">download</a>"
                                + ")</li>\n") % variables)
                        else:
                            self.write((
                                "<li><a href=\"%(url_path)s/%(public_path)s\">%(filename)s</a> "
                                +
                                "(<a href=\"%(url_path)s/%(public_path)s?download\">download</a>)"
                                + "</li>\n") % variables)
                    else:
                        # some other kind of file (eg, .zip, .css):
                        self.write(
                            "<li><a href=\"%(url_path)s/%(public_path)s\">%(filename)s</a></li>\n"
                            % variables)
            self.write("</ol>\n")
            self.write("<hr>\n")
            self.write(
                "<p><i>Please see <a href=\"{prefix}/dblank/Jupyter Help.ipynb\">Jupyter Help</a> for more information about this server.</i></p>\n"
                .format(prefix=prefix))
示例#18
0
def build_page(path_ntbk, path_html_output, path_media_output=None, execute=False,
               path_template=None, verbose=False, kernel_name=None):
    """Build the HTML for a single notebook page.

    Inputs
    ======

    path_ntbk : string
        The path to a notebook we want to convert.
    path_html_output : string
        The path to the folder where the HTML will be output.
    path_media_output : string | None
        If a string, the path to where images should be extracted. If None,
        images will be embedded in the HTML.
    execute : bool
        Whether to execute the notebook before converting
    path_template : string
        A path to the template used in conversion.
    kernel_name : string
        The name of the kernel to use if we execute notebooks.
    """
    ntbk = nbf.read(path_ntbk, nbf.NO_CONVERT)
    notebook_name = op.splitext(op.basename(path_ntbk))[0]

    ########################################
    # Notebook cleaning

    # Clean up the file before converting
    cleaner = NotebookCleaner(ntbk)
    cleaner.remove_cells(empty=True)
    cleaner.clear('stderr')
    ntbk = cleaner.ntbk
    _clean_notebook_cells(ntbk)

    #############################################
    # Conversion to HTML
    # create a configuration object that changes the preprocessors
    c = Config()

    c.FilesWriter.build_directory = path_html_output
    # So the images are written to disk
    c.HTMLExporter.preprocessors = ['nbconvert.preprocessors.ExtractOutputPreprocessor']

    # The text used as the text for anchor links. Set to empty since we'll use anchor.js for the links
    c.HTMLExporter.anchor_link_text = " "

    # Excluding input/output prompts
    c.HTMLExporter.exclude_input_prompt = True
    c.HTMLExporter.exclude_output_prompt = True

    if execute is True:
        if kernel_name is None:
            kernel_name = ntbk['metadata']['kernelspec']['name']

        # Excution of the notebook if we wish
        ep = ExecutePreprocessor(timeout=600, kernel_name=kernel_name)
        ep.preprocess(ntbk, {'metadata': {'path': op.dirname(path_ntbk)}})

    # Define the path to images and then the relative path to where they'll originally be placed
    if isinstance(path_media_output, str):
        path_media_output_rel = op.relpath(path_media_output, path_html_output)

    # Generate HTML from our notebook using the template

    output_resources = {'output_files_dir': path_media_output_rel, 'unique_key': notebook_name}
    exp = HTMLExporter(template_file=path_template, config=c)
    html, resources = exp.from_notebook_node(ntbk, resources=output_resources)

    # Now write the markdown and resources
    writer = FilesWriter(config=c)
    writer.write(html, resources, notebook_name=notebook_name)
    if verbose:
        print("Finished writing notebook to {}".format(path_html_output))
示例#19
0
def build_page(path_ntbk,
               path_html_output,
               path_media_output=None,
               execute=False,
               path_template=None,
               verbose=False,
               kernel_name=None):
    """Build the HTML for a single notebook page.

    Inputs
    ======

    path_ntbk : string
        The path to a notebook we want to convert.
    path_html_output : string
        The path to the folder where the HTML will be output.
    path_media_output : string | None
        If a string, the path to where images should be extracted. If None,
        images will be embedded in the HTML.
    execute : bool
        Whether to execute the notebook before converting
    path_template : string
        A path to the template used in conversion.
    kernel_name : string
        The name of the kernel to use if we execute notebooks.
    """
    ntbk = nbf.read(path_ntbk, nbf.NO_CONVERT)
    notebook_name = op.splitext(op.basename(path_ntbk))[0]

    ########################################
    # Notebook cleaning

    # Minor edits to cells
    _clean_markdown_cells(ntbk)

    #############################################
    # Conversion to HTML
    # create a configuration object that changes the preprocessors
    c = Config()

    c.FilesWriter.build_directory = path_html_output

    # Remove cell elements using tags
    c.TagRemovePreprocessor.remove_cell_tags = ("remove_cell", "removecell")
    c.TagRemovePreprocessor.remove_all_outputs_tags = ('remove_output', )
    c.TagRemovePreprocessor.remove_input_tags = ('remove_input', )

    # Remove any cells that are *only* whitespace
    c.RegexRemovePreprocessor.patterns = ["\\s*\\Z"]

    # So the images are written to disk
    c.HTMLExporter.preprocessors = [
        'nbconvert.preprocessors.TagRemovePreprocessor',
        'nbconvert.preprocessors.RegexRemovePreprocessor',
        'nbconvert.preprocessors.ExtractOutputPreprocessor',
    ]

    # The text used as the text for anchor links. Set to empty since we'll use anchor.js for the links
    c.HTMLExporter.anchor_link_text = " "

    # Excluding input/output prompts
    c.HTMLExporter.exclude_input_prompt = True
    c.HTMLExporter.exclude_output_prompt = True

    # Excution of the notebook if we wish
    if execute is True:
        ntbk = run_ntbk(ntbk, op.dirname(path_ntbk))

    # Define the path to images and then the relative path to where they'll originally be placed
    if isinstance(path_media_output, str):
        path_media_output_rel = op.relpath(path_media_output, path_html_output)

    # Generate HTML from our notebook using the template
    output_resources = {
        'output_files_dir': path_media_output_rel,
        'unique_key': notebook_name
    }
    exp = HTMLExporter(template_file=path_template, config=c)
    html, resources = exp.from_notebook_node(ntbk, resources=output_resources)

    # Now write the markdown and resources
    writer = FilesWriter(config=c)
    writer.write(html, resources, notebook_name=notebook_name)
    if verbose:
        print("Finished writing notebook to {}".format(path_html_output))
示例#20
0
    def get(self, prepath, user, filename):
        ## filename can have a path on it
        next = "/%s/hub/%s/public/%s" % (prepath, user, filename)
        filesystem_path = "/home/%s/public_html/%s" % (user, filename)
        if os.path.isfile(filesystem_path):  # download, raw, or view notebook
            command = "view"
            if len(self.get_arguments("view")) > 0:
                command = "view"
            elif len(self.get_arguments("download")) > 0:
                command = "download"
            elif len(self.get_arguments("copy")) > 0:
                command = "copy"
            elif len(self.get_arguments("pdf")) > 0:
                command = "pdf"
            elif len(self.get_arguments("raw")) > 0:
                command = "raw"
            # else:  view
            if filename.endswith(".ipynb"):
                if command in ["view", "pdf"]:
                    # first, make a notebook html:
                    #with open("/home/%s/public_html/%s" % (user, filename)) as fp:
                    #    notebook_content = fp.read()
                    if command == "view":
                        exporter = HTMLExporter(template_file='full-tabs')
                    else:
                        exporter = PDFExporter(latex_count=1)

                    nb_json = nbformat.read("/home/%s/public_html/%s" %
                                            (user, filename),
                                            as_version=4)
                    #if command == "pdf":
                    #    # If pdf, remove heading numbering:
                    #    for cell in nb_json["worksheets"][0]["cells"]:
                    #        if cell["cell_type"] == "heading":
                    #            cell["source"] = re.sub("^([0-9]+\.?)+\s", "", cell["source"])
                    # where to get css, images?
                    if command == "pdf":
                        self.set_header('Content-Type', "application/pdf")
                        base_filename = os.path.basename(filename)
                        self.set_header(
                            'Content-Disposition',
                            'attachment; filename="%s"' % base_filename)
                    else:  # render as HTML
                        # add header/footer:
                        path = "/%s/hub/%s/public" % (prepath, user)
                        parts = [(path, path)]
                        for part in filename.split("/")[:-1]:
                            path += "/" + part
                            parts.append((path, part))
                        breadcrumbs = " / ".join(
                            map(
                                lambda pair:
                                '<a href="%s" target="_blank">%s</a>' % pair,
                                parts))
                        env = {
                            "breadcrumbs":
                            breadcrumbs,
                            "url":
                            "https://athena.brynmawr.edu/" + next + "?download"
                        }
                        cell = new_markdown_cell(
                            source="""<table width="100%" style="border: none;">
<tr style="border: none;">
  <td style="border: none;" width="100px">
    <img src="https://blog.jupyter.org/content/images/2015/02/jupyter-sq-text.png" width="100"/> 
  </td>
  <td style="border: none;" width="50%">
    <h2><a href="https://athena.brynmawr.edu/">Jupyter at Bryn Mawr College</a></h2>
  </td>
  <td style="border: none;">
        <a href="https://athena.brynmawr.edu/jupyter/hub/dblank/public/Jupyter%20Help.ipynb" title="Help">
            <span class="fa fa-info-circle fa-2x menu-icon"></span>
            <span class="menu-text">Help</span>
        </a>
  </td>
  <td style="border: none;">
        <a href="{url}" title="Download Notebook" download>
            <span class="fa fa-download fa-2x menu-icon"></span>
            <span class="menu-text">Download Notebook</span>
        </a>
  </td>
</tr>
<tr style="border: none;">
  <td colspan="4" style="border: none;">
      <b>Public notebooks:</b> {breadcrumbs}
  </td>
</tr>
</table>""".format(**env))
                        nb_json["cells"].insert(0, cell)
                    (body, resources) = exporter.from_notebook_node(nb_json)
                    self.write(body)
                elif command == "download":  # download notebook json
                    self.download(user, filename, "text/plain")
                elif command == "copy":  # copy notebook json, if logged in
                    if self.get_current_user_name():
                        self.copy_file(user, filename,
                                       self.get_current_user_name())
                    else:
                        self.write(
                            "Please <a href=\"/%s/hub/login?next=%s\">login</a> to allow copy."
                            % (prepath, next))
                else:  # raw, just get file contents
                    with open("/home/%s/public_html/%s" % (user, filename),
                              "rb") as fp:
                        self.write(fp.read())
            else:  # some other kind of file
                # FIXME: how to get all of custom stuff?
                if command == "copy":
                    if self.get_current_user_name():
                        self.copy_file(user, filename,
                                       self.get_current_user_name())
                    else:
                        self.write(
                            "Please <a href=\"/%s/hub/login?next=%s\">login</a> to allow copy."
                            % (prepath, next))
                else:  # whatever, just get or download it
                    base_filename = os.path.basename(filename)
                    base, ext = os.path.splitext(base_filename)
                    app_log.info("extension is: %s" % ext)
                    if base_filename == "custom.css":
                        file_path = "/home/%s/.ipython/profile_default/static/custom/custom.css" % user
                        self.set_header('Content-Type', "text/css")
                        with open(file_path, "rb") as fp:
                            self.write(fp.read())
                    elif ext in [
                            ".txt", ".html", ".js", ".css", ".pdf", ".gif",
                            ".jpeg", ".jpg", ".png"
                    ]:  # show in browser
                        app_log.info("mime: %s" %
                                     str(mimetypes.guess_type(filename)[0]))
                        self.set_header('Content-Type',
                                        mimetypes.guess_type(filename)[0])
                        with open("/home/%s/public_html/%s" % (user, filename),
                                  "rb") as fp:
                            self.write(fp.read())
                    else:
                        self.download(user, filename)
        else:  # not a file; directory listing
            # filename can have a full path, and might be empty
            url_path = "/%s/hub/%s/public" % (prepath, user)

            ##
            path = "/%s/hub/%s/public" % (prepath, user)
            parts = [(path, path)]
            for part in filename.split("/")[:]:
                path += "/" + part
                parts.append((path, part))
            breadcrumbs = " / ".join(
                map(lambda pair: '<a href="%s" target="_blank">%s</a>' % pair,
                    parts))
            ##
            # could be: images, images/, images/subdir, images/subdir/
            if not filename.endswith("/") and filename.strip() != "":
                filename += "/"
            files = glob.glob("/home/%s/public_html/%s*" % (user, filename))
            self.write("<h1>Jupyter Project at Bryn Mawr College</h1>\n")
            self.write("[<a href=\"/jupyter/hub/login\">Home</a>] ")
            if self.get_current_user_name():
                self.write(
                    "[<a href=\"/user/%(current_user)s/tree\">%(current_user)s</a>] "
                    % {"current_user": self.get_current_user_name()})
            self.write("<p/>\n")
            self.write("<p>Public notebooks: %s </p>\n" % breadcrumbs)
            self.write("<ol>\n")
            for absolute_filename in sorted(files):
                if os.path.isdir(absolute_filename):
                    dir_path = absolute_filename.split("/")
                    dir_name = dir_path[-1]
                    public_path = "/".join(
                        dir_path[dir_path.index("public_html") + 1:])
                    self.write(
                        "<li><a href=\"%(url_path)s/%(public_path)s\">%(dir_name)s</a></li>\n"
                        % {
                            "url_path": url_path,
                            "dir_name": dir_name,
                            "public_path": public_path
                        })
                else:
                    file_path, filename = absolute_filename.rsplit("/", 1)
                    dir_path = absolute_filename.split("/")
                    public_path = "/".join(
                        dir_path[dir_path.index("public_html") + 1:])
                    variables = {
                        "user": user,
                        "filename": filename,
                        "url_path": url_path,
                        "next": next,
                        "public_path": public_path
                    }
                    if filename.endswith(".ipynb"):
                        if self.get_current_user_name():
                            self.write((
                                "<li><a href=\"%(url_path)s/%(public_path)s\">%(filename)s</a> "
                                +
                                #"(<a href=\"%(url_path)s/%(public_path)s?raw\">raw</a>, " +
                                "(<a href=\"%(url_path)s/%(public_path)s?download\">download</a>"
                                +
                                #"<a href=\"%(url_path)s/%(public_path)s?copy\">copy</a>" +
                                #((", <a href=\"/user/%s/notebooks/public_html/%s\">edit</a>" % (user, filename)) if self.get_current_user_name() == user else ", edit") +
                                ")</li>\n") % variables)
                        else:
                            self.write((
                                "<li><a href=\"%(url_path)s/%(public_path)s\">%(filename)s</a> "
                                +
                                #"(<a href=\"%(url_path)s/%(public_path)s?raw\">raw</a>, " +
                                "(<a href=\"%(url_path)s/%(public_path)s?download\">download</a>)"
                                +
                                #"copy, edit) " +
                                #"[<a href=\"/jupyter/hub/login?next=%(next)s\">login</a> to copy]</li>\n") % variables)
                                "</li>\n") % variables)
                    else:
                        # some other kind of file (eg, .zip, .css):
                        self.write(
                            "<li><a href=\"%(url_path)s/%(public_path)s\">%(filename)s</a></li>\n"
                            % variables)
            self.write("</ol>\n")
            self.write("<hr>\n")
            self.write(
                "<p><i>Please see <a href=\"/jupyter/hub/dblank/public/Jupyter Help.ipynb\">Jupyter Help</a> for more information about this server.</i></p>\n"
            )