PK WJԐץA A nbhtml/__init__.py"""Save & load Jupyter notebooks as HTML""" __version__ = '0.1' PK cWJ(D nbhtml/read.pyimport json from lxml.html import parse, tostring import sys from nbformat import NotebookNode, write, from_dict from nbformat.v4 import (new_notebook, new_code_cell, new_markdown_cell, new_output) def load_output(elt): stream = elt.xpath('.//div[contains(@class, "output_stream")]') if stream: name = 'stdout' if 'output_stderr' in stream[0].classes: name = 'stderr' pre = stream[0].xpath('pre')[0] return new_output('stream', name=name, text=pre.text_content()) subarea = elt.xpath('.//div[contains(@class, "output_subarea")]')[0] if 'output_error' in subarea.classes: err_json = elt.xpath('.//pre[contains(@class, "error_json")]')[0] d = json.loads(err_json.text_content()) return new_output('error', **d) # If we've got here, output must be display_data or execute_result op_json = elt.xpath('.//pre[contains(@class, "other_output_fmts")]')[0] out = from_dict(json.loads(op_json.text_content())) if 'output_html' in subarea.classes: out.data['text/html'] = ''.join(tostring(el, encoding='unicode') for el in subarea).strip() elif 'output_text' in subarea.classes: pre = subarea.xpath('pre')[0] out.data['text/plain'] = pre.text_content() elif 'output_png' in subarea.classes: src = subarea.xpath('img')[0].get('src') assert src.startswith('data:image/png;base64,'), src[:30] out.data['image/png'] = src[len('data:image/png;base64,'):] return out def load_cell(cell_elt): if 'text_cell' in cell_elt.classes: md_elt = cell_elt.xpath('.//pre[contains(@class, "markdown_raw")]')[0] cell = new_markdown_cell(md_elt.text_content()) elif 'code_cell' in cell_elt.classes: cell = load_code_cell(cell_elt) else: raise ValueError("Unhandled cell type", cell_elt.get('class')) metadata_elt = cell_elt.getprevious() cell.metadata = from_dict(json.loads(metadata_elt.text_content())) return cell def load_code_cell(cell_elt): code_elt = cell_elt.xpath('.//div[@class="input_area"]//pre')[0] code = code_elt.text_content() if code.endswith('\n'): code = code[:-1] if code == ' ': # Empty cell gains a space in HTML conversion code = '' cell = new_code_cell(code) for output in cell_elt.xpath('.//div[@class="output_area"]'): cell.outputs.append(load_output(output)) ec = cell_elt.getnext().get('data-execution-count') cell.execution_count = json.loads(ec) return cell def load_notebook(fp): tree = parse(fp) nb = new_notebook() metadata_elt = tree.xpath('//script[@id="notebook_metadata_json"]')[0] nb.metadata = from_dict(json.loads(metadata_elt.text_content())) for cell_elt in tree.xpath('//div[starts-with(@class, "cell ")]'): nb.cells.append(load_cell(cell_elt)) return nb if __name__ == '__main__': with open(sys.argv[1]) as f: nb = load_notebook(f) write(nb, 'from_html.ipynb') print('Saved from_html.ipynb') PK SyWJ ͌ nbhtml/saving.tpl{%- extends 'full.tpl' -%} {%- block html_head -%} {{ super() }} {%- endblock html_head -%} {% block any_cell %}
{{cell.metadata | json | escape }}
{{ super() }}
{% endblock any_cell %}
{% block codecell %}
{{ super() }}
{%- endblock codecell %}
{% block markdowncell scoped %}
{{ cell.source }}
{{ self.empty_in_prompt() }}
{{ output | json_non_shown_output | escape }}
{%- endif -%}
{% endblock output_area_prompt %}
{% block error -%}
{{output | json_error_data | escape }}
{{ super() }}
{%- endblock error %}
PK ۀWJ?m nbhtml/write.pyfrom copy import deepcopy
import json
import os.path
import sys
from nbconvert.exporters import HTMLExporter
def tojson(d):
return json.dumps(d, sort_keys=True, indent=2)
def error_data(output):
output = output.copy()
del output['output_type']
return json.dumps(output, sort_keys=True)
class SavingHTMLExporter(HTMLExporter):
"""Export HTML with enough information to reconstruct the notebook.
"""
def __init__(self, **kw):
super().__init__(**kw)
self.template_path = [os.path.dirname(__file__)]
self.template_file = 'saving.tpl'
def json_non_shown_output(self, output):
"""Serialise a copy of outputs other than the one shown.
"""
output = deepcopy(output)
for fmt in self.config.NbConvertBase.display_data_priority:
if fmt in output.data:
del output.data[fmt]
break
return json.dumps(output, sort_keys=True)
def default_filters(self):
yield from super().default_filters()
yield ('json_non_shown_output', self.json_non_shown_output)
yield ('json_error_data', error_data)
yield ('json', tojson)
def convert(ipynb_file):
exp = SavingHTMLExporter()
output, resource = exp.from_filename(ipynb_file)
output_file = ipynb_file + '.html'
with open(output_file, 'w') as f:
f.write(output)
return output_file
if __name__ == '__main__':
output_file = convert(sys.argv[1])
print('Saved', output_file)
PK !H;@Q P nbhtml-0.1.dist-info/WHEEL1
0 RZq+D-Dv;_[*7Fp ܦpv/fݞoL(*IPK !HX6q nbhtml-0.1.dist-info/METADATAuTMS@WTCRzL)h4i{Vj&II51'9/.(-PQl..?ʖR!x`
z;rMҘzX]_eFblmy#Bۗye<`'aCn>iͯEvڇָVQy9§)'\QwwG~v;p?t$z/ւtE7˯pj3cYʭ3Cn
uӳ3XQ=]8udծsC4m2e60[[z"P 8Wkps
-)(r&6?Ee?$LMoċ\A S\еXa팺K~9jL/k0JU
TKsYBgG qrws3BCؚXH!َ읥P]!V̅m^n[QPB/dT6ݣKh@Rf6vÁTZ)*rAcT1Ih (tlh.yn`25j8i mHHاɣ]l!tNi\,wPK !HK:8T nbhtml-0.1.dist-info/RECORDmr0 @ѽ߂J.| nhPI@y~};:uGIŲ:E'I())e_ZՅ\d#+A1P_FC<\Uبv%#;-:&8_
&ka$BdʰIyPSbD{ehrt
i~!.cjDgSҊcb[oL4FU9ɵ, ?/eOyS1t-;yI+ˉȐk3҈ep4=`GOwԑj96-l37NIy?t#
g({3
PK WJԐץA A nbhtml/__init__.pyPK cWJ(D q nbhtml/read.pyPK SyWJ ͌ nbhtml/saving.tplPK ۀWJ?m nbhtml/write.pyPK !H;@Q P nbhtml-0.1.dist-info/WHEELPK !HX6q o nbhtml-0.1.dist-info/METADATAPK !HK:8T nbhtml-0.1.dist-info/RECORDPK