add notebook tag

This commit is contained in:
Jake Vanderplas
2013-05-02 22:47:52 -07:00
parent 57d62ce99f
commit 1ae1833864
5 changed files with 152 additions and 8 deletions

View File

@@ -36,7 +36,6 @@ ReTitleAlt = re.compile("""(?:"|')(?P<title>[^"']+)?(?:"|')\s+(?:"|')(?P<alt>[^"
@LiquidTags.register('img')
def img(preprocessor, tag, markup):
markup = markup.strip()
attrs = None
# Parse the markup string

View File

@@ -8,7 +8,7 @@ Syntax
------
{% include_code path/to/code [Title text] %}
The "path to code" is relative to the code path in
The "path to code" is relative to the code subdirectory of
the content directory (TODO: allow this to be set in configs).
Example
@@ -37,8 +37,6 @@ FORMAT = re.compile(r"""^(?:\s+)?(?P<src>\S+)(?:\s+)?(?:(?:lang:)(?P<lang>\S+))?
@LiquidTags.register('include_code')
def include_code(preprocessor, tag, markup):
markup = markup.strip()
title = None
lang = None
src = None
@@ -59,7 +57,7 @@ def include_code(preprocessor, tag, markup):
code_path = os.path.join('content', code_dir, src)
if not os.path.exists(code_path):
return "File {0} could not be found".format(code_path)
raise ValueError("File {0} could not be found".format(code_path))
code = open(code_path).read()

View File

@@ -9,6 +9,7 @@ Where "tag" is associated with some user-defined extension.
These result in a preprocess step within markdown that produces
either markdown or html.
"""
import warnings
import markdown
import itertools
import re
@@ -35,7 +36,7 @@ class _LiquidTagsPreprocessor(markdown.preprocessors.Preprocessor):
tag = EXTRACT_TAG.match(markup).groups()[0]
markup = EXTRACT_TAG.sub('', markup, 1)
if tag in self._tags:
liquid_tags[i] = self._tags[tag](self, tag, markup)
liquid_tags[i] = self._tags[tag](self, tag, markup.strip())
# add an empty string to liquid_tags so that chaining works
liquid_tags.append('')

148
liquid_tags/notebook.py Normal file
View File

@@ -0,0 +1,148 @@
"""
Notebook Tag
------------
This is a liquid-style tag to include a static html rendering of an IPython
notebook in a blog post.
Syntax
------
{% notebook filename.ipynb %}
The file should be specified relative to the ``notebook`` subdirectory of the
content directory. [TODO: make this configurable].
This will include the IPython notebook in the file.
Details
-------
Because the conversion and formatting of notebooks is rather involved, there
are a few extra steps required for this plugin:
- First, the plugin requires that the nbconvert package [1]_ to be in the
python path. For example, in bash, this can be set via
>$ export PYTHONPATH=/path/to/nbconvert/
- After typing "make html" when using the notebook tag, a file called
``_nb_header.html`` will be produced in the main directory. The content
of the file should be included in the header of the theme. An easy way
to accomplish this is to add the following lines within the header template
of the theme you use:
{% if IPYNB_FORMATTING %}
{{ IPYNB_FORMATTING }}
{% endif %}
and in your ``pelicanconf.py`` file, include the line:
IPYNB_FORMATTING = open('_nb_header.html').read().decode('utf-8')
[1] https://github.com/ipython/nbconvert
"""
import re
import os
from .mdx_liquid_tags import LiquidTags
from converters import ConverterBloggerHTML # part of the nbconvert package
SYNTAX = "{% notebook /path/to/notebook.ipynb %}"
FORMAT = re.compile(r"""^(?:\s+)?(?P<src>\S+)(?:\s+)?$""")
def process_body(body):
body = '\n'.join(body)
# replace the highlight tags
body = body.replace('class="highlight"', 'class="highlight-ipynb"')
# specify <pre> tags
body = body.replace('<pre', '<pre class="ipynb"')
# create a special div for notebook
body = '<div class="ipynb">\n\n' + body + "\n\n</div>"
# specialize headers
for h in '123456':
body = body.replace('<h%s' % h, '<h%s class="ipynb"' % h)
return body.split('\n')
def process_header(header):
header = '\n'.join(header)
# replace the highlight tags
header = header.replace('highlight', 'highlight-ipynb')
# specify <pre> tags
header = header.replace('html, body', '\n'.join(('pre.ipynb {',
' color: black;',
' background: #f7f7f7;',
' border: 0;',
' box-shadow: none;',
' margin-bottom: 0;',
' padding: 0;'
'}\n',
'html, body')))
# create a special div for notebook
header = header.replace('body {', 'div.ipynb {')
# specialize headers
header = header.replace('html, body,',
'\n'.join((('h1.ipynb h2.ipynb h3.ipynb '
'h4.ipynb h5.ipynb h6.ipynb {'),
'h1.ipynb h2.ipynb ... {',
' margin: 0;',
' padding: 0;',
' border: 0;',
' font-size: 100%;',
' font: inherit;',
' vertical-align: baseline;',
'}\n',
'html, body,')))
header = header.replace('html, body,',
'/*html, body,*/')
header = header.replace('h1, h2, h3, h4, h5, h6,',
'/*h1, h2, h3, h4, h5, h6,*/')
return header.split('\n')
@LiquidTags.register('notebook')
def notebook(preprocessor, tag, markup):
match = FORMAT.search(markup)
if match:
argdict = match.groupdict()
src = argdict['src']
else:
raise ValueError("Error processing input, "
"expected syntax: {0}".format(SYNTAX))
# TODO: make the notebook directory a configurable setting
nb_dir = 'notebooks'
nb_path = os.path.join('content', nb_dir, src)
url = '/{0}/{1}/{2}'.format('static', nb_dir, src)
if not os.path.exists(nb_path):
raise ValueError("File {0} could not be found".format(nb_path))
# Call the notebook converter
converter = ConverterBloggerHTML(nb_path)
converter.read()
header_lines = process_header(converter.header_body())
print ("\n *** Writing styles to _nb_header.html: "
"this should be included in the theme.\n")
open('_nb_header.html', 'w').write('\n'.join(header_lines).encode('utf-8'))
body_lines = process_body(converter.main_body('\n'))
body = preprocessor.configs.htmlStash.store('\n'.join(body_lines),
safe=True)
return body
#----------------------------------------------------------------------
# This import allows image tag to be a Pelican plugin
from liquid_tags import register

View File

@@ -35,8 +35,6 @@ VID_TYPEDICT = {'.mp4':"type='video/mp4; codecs=\"avc1.42E01E, mp4a.40.2\"'",
@LiquidTags.register('video')
def video(preprocessor, tag, markup):
markup = markup.strip()
videos = []
width = None
height = None