PKWJԐץAAnbhtml/__init__.py"""Save & load Jupyter notebooks as HTML""" __version__ = '0.1' PKcWJ(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') PKSyWJ͌  nbhtml/saving.tpl{%- extends 'full.tpl' -%} {%- block html_head -%} {{ super() }} {%- endblock html_head -%} {% block any_cell %} {{ super() }} {% endblock any_cell %} {% block codecell %} {{ super() }} {%- endblock codecell %} {% block markdowncell scoped %}
{{ self.empty_in_prompt() }}
{{ cell.source | markdown2html | strip_files_prefix }}
{%- endblock markdowncell %} {% block output_area_prompt %} {{ super() }} {%- if output.output_type in ('execute_result', 'display_data') -%} {%- endif -%} {% endblock output_area_prompt %} {% block error -%} {{ super() }} {%- endblock error %} PKۀWJ?mnbhtml/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;@QPnbhtml-0.1.dist-info/WHEEL1 0 RZq+D-Dv;_[*7Fp ܦpv/fݞoL(*IPK!HX6qnbhtml-0.1.dist-info/METADATAuTMS@ WTCRzL)h4i{Vj&II51'9/.(-PQl..?ʖR!x` z;rMҘzX]_eFblmy#Bۗye<`'aCn>iͯEvڇָVQy9§)'\Qww G~v;p?t$z/ւtE7˯pj3cYʭ3Cn uӳ3XQ=]8udծsC4m2e60[[z"P  8Wkps -)(r&6?Ee?$LMoċ\AS\еXa팺K~9jL/k0J U TKsYBgG qrws3BCؚXH!َ읥P]!V̅m^n[QPB/dT6ݣKh@Rf6vÁTZ)* rAcT1Ih (tlh.yn`25j8imHHاɣ]l!tNi\,w PK!HK :8Tnbhtml-0.1.dist-info/RECORDmr0@ѽ߂J.| nhPI@y~};:uGIŲ:E'I())e_ZՅ\d#+A1 P_FC<\Uبv%#;-:&8_ &ka$BdʰIyPSbD{ehrt i~!.cjDgSҊcb[oL4FU9ɵ,?/eOyS1t-;yI+ˉȐk3҈ep4=`GOwԑj96-l37 NIy?t# g({3 PKWJԐץAAnbhtml/__init__.pyPKcWJ(D qnbhtml/read.pyPKSyWJ͌   nbhtml/saving.tplPKۀWJ?mnbhtml/write.pyPK!H;@QPnbhtml-0.1.dist-info/WHEELPK!HX6qonbhtml-0.1.dist-info/METADATAPK!HK :8Tnbhtml-0.1.dist-info/RECORDPK