add ablility to specify notebook cells

This commit is contained in:
Jake Vanderplas
2013-05-04 07:21:10 -07:00
parent c0e756209d
commit d5e4d179e9

View File

@@ -6,7 +6,7 @@ notebook in a blog post.
Syntax
------
{% notebook filename.ipynb %}
{% notebook filename.ipynb [ cells[start:end] ]%}
The file should be specified relative to the ``notebooks`` subdirectory of the
content directory. Optionally, this subdirectory can be specified in the
@@ -14,6 +14,9 @@ config file:
NOTEBOOK_DIR = 'notebooks'
The cells[start:end] statement is optional, and can be used to specify which
block of cells from the notebook to include.
Details
-------
Because the conversion and formatting of notebooks is rather involved, there
@@ -52,8 +55,8 @@ except ImportError:
from converters import ConverterBloggerHTML # requires nbconvert package
separate_available = False
SYNTAX = "{% notebook /path/to/notebook.ipynb %}"
FORMAT = re.compile(r"""^(?:\s+)?(?P<src>\S+)(?:\s+)?$""")
SYNTAX = "{% notebook /path/to/notebook.ipynb [ cells[start:end] ] %}"
FORMAT = re.compile(r"""^(\s+)?(?P<src>\S+)(\s+)?((cells\[)(?P<start>-?[0-9]*):(?P<end>-?[0-9]*)(\]))?(\s+)?$""")
def process_body(body):
@@ -108,16 +111,66 @@ def process_header(header):
return header.split('\n')
def strip_divs(body, start=None, end=None):
"""Strip divs from the body for partial notebook insertion
If L represents the list of parsed main divs, then this returns
the document corresponding to the divs L[start:end].
body should be a list of lines in the body of the html file.
"""
# TODO: this is a bit hackish. It would be better to add a PR to
# nbconvert which does this at the source.
DIV = re.compile('<div')
UNDIV = re.compile('</div')
# remove ipynb div
body_lines = body[1:-1]
# split divs
L = []
count = 0
div_start = 0
for i, line in enumerate(body_lines):
count += len(DIV.findall(line))
count -= len(UNDIV.findall(line))
if count == 0:
L.append(body_lines[div_start:i + 1])
div_start = i + 1
elif count < 0:
raise ValueError("parsing error: lost a tag")
if div_start != len(body_lines):
raise ValueError("parsing error: didn't find the end of the div")
body_lines = sum(L[start:end], [])
return body[:1] + body_lines + body[-1:]
@LiquidTags.register('notebook')
def notebook(preprocessor, tag, markup):
match = FORMAT.search(markup)
if match:
argdict = match.groupdict()
src = argdict['src']
start = argdict['start']
end = argdict['end']
else:
raise ValueError("Error processing input, "
"expected syntax: {0}".format(SYNTAX))
if start:
start = int(start)
else:
start = None
if end:
end = int(end)
else:
end = None
settings = preprocessor.configs.config['settings']
nb_dir = settings.get('NOTEBOOK_DIR', 'notebooks')
nb_path = os.path.join('content', nb_dir, src)
@@ -144,6 +197,8 @@ def notebook(preprocessor, tag, markup):
"this should be included in the theme.\n")
open('_nb_header.html', 'w').write('\n'.join(header_lines).encode('utf-8'))
body_lines = strip_divs(body_lines, start, end)
body = preprocessor.configs.htmlStash.store('\n'.join(body_lines),
safe=True)
return body