Exporter used for HTML; deprecated it in favour of a .md + beautiful soup one
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Thu Jul 6 10:09:43 2017
@author: tania
"""
from os import remove, close
import re, glob, os, fnmatch
from shutil import move
from tempfile import mkstemp
from pathlib import Path
#---------------------------------------
def find_notebooks():
""" Find all the notebooks in the repo previsouly converted to
markdown"""
basePath = Path(os.getcwd())
notebooksAll = [nb for nb in glob.glob('**/*.ipynb')]
exception = str(basePath) + '/_site/*/*'
notebooks = [nb for nb in notebooksAll if not fnmatch.fnmatch(nb, exception)]
notebooks = [os.path.abspath(nb).replace('ipynb', 'md') for nb in notebooks]
return notebooks
def replace(file_path):
""" Replaces the expressions"""
fh, abs_path = mkstemp()
with open(abs_path,'w') as new_file:
with open(file_path) as source_file:
for line in source_file:
if any(s in line for s in s_repl):
line_new = robj.sub(lambda m: rdict[m.group(0)], line)
line_new2 = quoteobj.sub(lambda m: rquote[m.group(0)], line_new)
new_file.write(line_new2)
elif any(s in line for s in scope):
line_new = scopeobj.sub(lambda m: rscope[m.group(0)], line)
new_file.write(line_new)
else:
new_file.write(line)
new_file.close()
#Remove original file
remove(file_path)
#Move new file
move(abs_path, file_path)
print(f"Replaced {file_path}")
# Replacement rules: needed to parse the html properly
rdict = {'class=': 'class="', '<table>':'<table class="table-responsive table-striped>'}
s_repl = {'class=', '<table>'}
robj = re.compile('|'.join(rdict.keys()))
rquote ={'>':'">' }
quoteobj= re.compile('|'.join(rquote.keys()))
rscope = {'scope=row':'scope="row"','scope=col':'scope="col"'}
scope = {'scope=row', 'scope=col'}
scopeobj = re.compile('|'.join(rscope.keys()))
notebooks = find_notebooks()
for nb in notebooks: replace(nb)
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
@author: trallard
This code is used to generate Jekyll blogpost from Jupyter notebooks
within a main Jekyll repository. This uses the library 'nbconvert-jekyll'.
Since the templates are given in this package there is no need to specify a c
ustom template, unless you need to modify the default output. If doing so you also
need to provide a path for the templates.
"""
# Import libraries
import fnmatch
import glob
import os
from pathlib import Path
try:
from urllib.parse import quote # Py 3
except ImportError:
from urllib2 import quote # Py 2
# ---------------------------------------
def find_notebooks():
""" Find all the notebooks in the repo, but excludes those
in the _site folder, this will be default if no specific
notebook was passed for conversion """
basePath = Path(os.getcwd())
notebooksAll = [nb for nb in glob.glob('**/*.ipynb')]
exception = str(basePath) + '/_site/*/*'
notebooks = [nb for nb in notebooksAll if not fnmatch.fnmatch(nb, exception)]
return notebooks
# modify this function to point the images to a custom path
# the default for nbconvert is to create a directory {notebook_name}_files
# where the notebook is located
def jekyllpath(path):
"""
Take the filepath of an image output by the ExportOutputProcessor
and convert it into a URL we can use with Jekyll
"""
base = os.path.split(path)[1]
return path.replace("..", "{{site.url}}{{site.baseurl}}")
# ---------------------------------------
notebooks = find_notebooks()
# check if the list is empty
if not notebooks:
print("No notebook found in this repository \n")
else:
for nb in notebooks:
print(" ***** Notebook found: {} \n)".format(nb))
"""Converting notebooks now: this uses nbconvert with
a custom generated template"""
c = get_config()
c.NbConvertApp.export_format = 'markdown'
scriptsPath = os.path.join(os.getcwd(), 'scripts')
c.MarkdownExporter.template_path = [scriptsPath] # point this to the location of the jekyll template file
c.MarkdownExporter.template_file = 'jekyll'
# Uncomment if you want to pass a custom template
#c.MarkdownExporter.template_path = [scriptsPath] # point this to the location of the jekyll template file
#c.MarkdownExporter.template_file = 'jekyll_html'
# convert all notebooks found
c.NbConvertApp.notebooks = notebooks
# customise the images output directory
c.NbConvertApp.output_files_dir = '../images/notebook_images/{notebook_name}'
# c.Application.verbose_crash = True
# modify this function to point the images to a custom path
# the default for nbconvert is to create a directory {notebook_name}_files
# where the notebook is located
def jekyllpath(path):
"""
Take the filepath of an image output by the ExportOutputProcessor
and convert it into a URL we can use with Jekyll
"""
base = os.path.split(path)[1]
return path.replace("..", "{{site.url}}{{site.baseurl}}")
c.MarkdownExporter.filters = {'jekyllpath': jekyllpath}
{% extends 'markdown.tpl' %}
{# custom header for jekyll post #}
{%- block header -%}
---
layout: notebook
title: "{{resources['metadata']['name']}}"
tags:
update_date:
code_version: 1
validation_pass:
---
<br />
{%- endblock header -%}
{% block in_prompt -%}
{%- if cell.execution_count is defined -%}
{%- if resources.global_content_filter.include_input_prompt-%}
<font color ='#00bcd4'> In [{{ cell.execution_count }}]: </font>
{%- else -%}
In [ ]:
{%- endif -%}
{%- endif -%}
{%- endblock in_prompt %}
{# Images will be saved in the custom path #}
{% block data_svg %}
<img src="{{ output.metadata.filenames['image/svg+xml'] | jekyllpath }}" alt="svg" />
{% endblock data_svg %}
{% block data_png %}
<img src="{{ output.metadata.filenames['image/png'] | jekyllpath }}" alt="png"/>
{% endblock data_png %}
{% block data_jpg %}
<img src="{{ output.metadata.filenames['image/jpeg'] | jekyllpath }}" alt="jpeg" />
{% endblock data_jpg %}
{# cells containing markdown text only #}
{% block markdowncell scoped %}
{{ cell.source | wrap_text(80) }}
{% endblock markdowncell %}
{# headings #}
{% block headingcell scoped %}
{{ '#' * cell.level }} {{ cell.source | replace('\n', ' ') }}
{% endblock headingcell %}
{% block stream -%}
{% endblock stream %}
{# latex data block#}
{% block data_latex %}
{{ output.data['text/latex'] }}
{% endblock data_latex %}
{% block data_text scoped %}
{{ output.data['text/plain'] | indent }}
{% endblock data_text %}
{% block data_html scoped -%}
{{ output.data['text/html'] }}
{%- endblock data_html %}
{% block data_markdown scoped -%}
{{ output.data['text/markdown'] | markdown2html }}
{%- endblock data_markdown %}
from setuptools import setup
import os
name = 'jekyllconvert'
pkg_root = os.path.join(os.path.dirname(__file__), name)
here = os.path.dirname(__file__)
packages = []
for d, _, _ in os.walk(os.path.join(here, name)):
if os.path.exists(os.path.join(d, '__init__.py')):
packages.append(d[len(here)+1:].replace(os.path.sep, '.'))
setup_args = dict(name = name,
version = '0.2',
description = 'Package used for custom conversion from Jupyter notebook to Jekyll posts',
url = 'https://github.com/trallard/nbconvert-jekyllconvert.git',
author = 'Tania Allard',
author_email = 't.allard@sheffield.ac.uk',
description_file = 'README.md',
license = 'MIT',
entry_points ={'nbconvert.exporters': ['md_jk = jekyllconvert:JekyllExporter'],},
include_package_data=True,
packages = packages,
zip_safe=False,
install_requires = ['nbconvert'])
if __name__ == '__main__':
setup(**setup_args)
# file __init__.py
import os
import os.path
from traitlets import default, Unicode
from traitlets.config import Config
from nbconvert.filters.highlight import Highlight2HTML
from nbconvert.filters.markdown_mistune import IPythonRenderer, MarkdownWithMath
from nbconvert.exporters.html import HTMLExporter
#-----------------------------------------------------------------------------
# Classes
#-----------------------------------------------------------------------------
class JekyllExporter(HTMLExporter):
"""
My custom exporter
"""
anchor_link_text = Unicode(u'¶', help="The text used as the text for anchor links.").tag(config=True)
output_mimetype = 'text/markdown'
def _file_extension_default(self):
"""
The new file extension is `.test_ext`
"""
return '.md'
@property
def template_path(self):
"""
We want to inherit from HTML template, and have template under
`./templates/` so append it to the search path. (see next section)
"""
#return super().template_path+[os.path.join(os.path.dirname(__file__), "templates")]
module_path = os.path.join(os.path.dirname(__file__), "templates")
print(module_path)
return super().template_path + [module_path]
def _template_file_default(self):
"""
We want to use the new template we ship with our library.
"""
return 'Jekyll_template'
@property
def default_config(self):
c = Config({
'NbConvertBase': {
'display_data_priority': ['application/vnd.jupyter.widget-state+json',
'application/vnd.jupyter.widget-view+json',
'application/javascript',
'text/html',
'text/markdown',
'image/svg+xml',
'text/latex',
'image/png',
'image/jpeg',
'text/plain'
]
},
'CSSHTMLHeaderPreprocessor': {
'enabled': True
},
'HighlightMagicsPreprocessor': {
'enabled': True
}
})
c.merge(super(HTMLExporter, self).default_config)
return c