|
| 1 | +import sys |
| 2 | +import os.path |
| 3 | +import re |
| 4 | +import time |
| 5 | +from docutils import io, nodes, statemachine, utils |
| 6 | +from docutils.error_reporting import ErrorString |
| 7 | +from docutils.parsers.rst import Directive, convert_directive_function |
| 8 | +from docutils.parsers.rst import directives, roles, states |
| 9 | +from docutils.parsers.rst.roles import set_classes |
| 10 | +from docutils.transforms import misc |
| 11 | + |
| 12 | +from nbconvert import ConverterHTML |
| 13 | + |
| 14 | + |
| 15 | +class Notebook(Directive): |
| 16 | + """ |
| 17 | + Use nbconvert to insert a notebook into the environment. |
| 18 | + This is based on the Raw directive in docutils |
| 19 | + """ |
| 20 | + required_arguments = 1 |
| 21 | + optional_arguments = 0 |
| 22 | + final_argument_whitespace = True |
| 23 | + option_spec = {} |
| 24 | + has_content = False |
| 25 | + |
| 26 | + def run(self): |
| 27 | + # check if raw html is supported |
| 28 | + if not self.state.document.settings.raw_enabled: |
| 29 | + raise self.warning('"%s" directive disabled.' % self.name) |
| 30 | + |
| 31 | + # set up encoding |
| 32 | + attributes = {'format': 'html'} |
| 33 | + encoding = self.options.get( |
| 34 | + 'encoding', self.state.document.settings.input_encoding) |
| 35 | + e_handler = self.state.document.settings.input_encoding_error_handler |
| 36 | + |
| 37 | + # get path to notebook |
| 38 | + source_dir = os.path.dirname( |
| 39 | + os.path.abspath(self.state.document.current_source)) |
| 40 | + nb_path = os.path.normpath(os.path.join(source_dir, |
| 41 | + self.arguments[0])) |
| 42 | + nb_path = utils.relative_path(None, nb_path) |
| 43 | + |
| 44 | + # convert notebook to html |
| 45 | + converter = ConverterHTML(nb_path) |
| 46 | + converter.read() |
| 47 | + |
| 48 | + # add HTML5 scoped attribute to header style tags |
| 49 | + header = map(lambda s: s.replace('<style', '<style scoped="scoped"'), |
| 50 | + converter.header_body()) |
| 51 | + |
| 52 | + # concatenate raw html lines |
| 53 | + lines = ['<div class="ipynotebook">'] |
| 54 | + lines.extend(header) |
| 55 | + lines.extend(converter.main_body()) |
| 56 | + lines.append('</div>') |
| 57 | + text = '\n'.join(lines) |
| 58 | + |
| 59 | + # add dependency |
| 60 | + self.state.document.settings.record_dependencies.add(nb_path) |
| 61 | + attributes['source'] = nb_path |
| 62 | + |
| 63 | + # create notebook node |
| 64 | + nb_node = notebook('', text, **attributes) |
| 65 | + (nb_node.source, nb_node.line) = \ |
| 66 | + self.state_machine.get_source_and_line(self.lineno) |
| 67 | + |
| 68 | + return [nb_node] |
| 69 | + |
| 70 | + |
| 71 | +class notebook(nodes.raw): |
| 72 | + pass |
| 73 | + |
| 74 | + |
| 75 | +def visit_notebook_node(self, node): |
| 76 | + self.visit_raw(node) |
| 77 | + |
| 78 | + |
| 79 | +def depart_notebook_node(self, node): |
| 80 | + self.depart_raw(node) |
| 81 | + |
| 82 | + |
| 83 | +def setup(app): |
| 84 | + app.add_node(notebook, |
| 85 | + html=(visit_notebook_node, depart_notebook_node)) |
| 86 | + |
| 87 | + app.add_directive('notebook', Notebook) |
0 commit comments