Show More
@@ -0,0 +1,94 b'' | |||
|
1 | %% This is the automatic preamble used by IPython. Note that it does *not* | |
|
2 | %% include a documentclass declaration, that is added at runtime to the overall | |
|
3 | %% document. | |
|
4 | ||
|
5 | \usepackage{amsmath} | |
|
6 | \usepackage{amssymb} | |
|
7 | \usepackage{graphicx} | |
|
8 | ||
|
9 | % needed for markdown enumerations to work | |
|
10 | \usepackage{enumerate} | |
|
11 | ||
|
12 | % Slightly bigger margins than the latex defaults | |
|
13 | \usepackage{geometry} | |
|
14 | \geometry{verbose,tmargin=3cm,bmargin=3cm,lmargin=2.5cm,rmargin=2.5cm} | |
|
15 | ||
|
16 | % Define a few colors for use in code, links and cell shading | |
|
17 | \usepackage{color} | |
|
18 | \definecolor{orange}{cmyk}{0,0.4,0.8,0.2} | |
|
19 | \definecolor{darkorange}{rgb}{.71,0.21,0.01} | |
|
20 | \definecolor{darkgreen}{rgb}{.12,.54,.11} | |
|
21 | \definecolor{myteal}{rgb}{.26, .44, .56} | |
|
22 | \definecolor{gray}{gray}{0.45} | |
|
23 | \definecolor{lightgray}{gray}{.95} | |
|
24 | \definecolor{mediumgray}{gray}{.8} | |
|
25 | \definecolor{inputbackground}{rgb}{.95, .95, .85} | |
|
26 | \definecolor{outputbackground}{rgb}{.95, .95, .95} | |
|
27 | \definecolor{traceback}{rgb}{1, .95, .95} | |
|
28 | ||
|
29 | % Framed environments for code cells (inputs, outputs, errors, ...). The | |
|
30 | % various uses of \unskip (or not) at the end were fine-tuned by hand, so don't | |
|
31 | % randomly change them unless you're sure of the effect it will have. | |
|
32 | \usepackage{framed} | |
|
33 | ||
|
34 | % remove extraneous vertical space in boxes | |
|
35 | \setlength\fboxsep{0pt} | |
|
36 | ||
|
37 | % codecell is the whole input+output set of blocks that a Code cell can | |
|
38 | % generate. | |
|
39 | \newenvironment{codecell}{% | |
|
40 | \def\FrameCommand{\color{mediumgray} \vrule width 1pt \hspace{5pt}}% | |
|
41 | \MakeFramed{\vspace{-0.5em}\FrameRestore}} | |
|
42 | {\unskip\endMakeFramed} | |
|
43 | ||
|
44 | \newenvironment{codeinput}{% | |
|
45 | \def\FrameCommand{\colorbox{inputbackground}}% | |
|
46 | \MakeFramed{\advance\hsize-\width \FrameRestore}} | |
|
47 | {\unskip\endMakeFramed} | |
|
48 | ||
|
49 | \newenvironment{codeoutput}{% | |
|
50 | \def\FrameCommand{\colorbox{outputbackground}}% | |
|
51 | \vspace{-1.4em} | |
|
52 | \MakeFramed{\advance\hsize-\width \FrameRestore}} | |
|
53 | {\unskip\medskip\endMakeFramed} | |
|
54 | ||
|
55 | \newenvironment{traceback}{% | |
|
56 | \def\FrameCommand{\colorbox{traceback}}% | |
|
57 | \MakeFramed{\advance\hsize-\width \FrameRestore}} | |
|
58 | {\endMakeFramed} | |
|
59 | ||
|
60 | % Use and configure listings package for nicely formatted code | |
|
61 | \usepackage{listings} | |
|
62 | \lstset{ | |
|
63 | language=python, | |
|
64 | aboveskip=\smallskipamount, | |
|
65 | belowskip=\smallskipamount, | |
|
66 | %xleftmargin=3mm, | |
|
67 | breaklines=true, | |
|
68 | basicstyle=\small \ttfamily, | |
|
69 | showstringspaces=false, | |
|
70 | keywordstyle=\color{blue}\bfseries, | |
|
71 | commentstyle=\color{myteal}, | |
|
72 | stringstyle=\color{darkgreen}, | |
|
73 | identifierstyle=\color{darkorange}, | |
|
74 | } | |
|
75 | ||
|
76 | % The hyperref package gives us a pdf with properly built | |
|
77 | % internal navigation ('pdf bookmarks' for the table of contents, | |
|
78 | % internal cross-reference links, web links for URLs, etc.) | |
|
79 | \usepackage{hyperref} | |
|
80 | \hypersetup{ | |
|
81 | breaklinks=true, % so long urls are correctly broken across lines | |
|
82 | colorlinks=true, | |
|
83 | urlcolor=blue, | |
|
84 | linkcolor=darkorange, | |
|
85 | citecolor=darkgreen, | |
|
86 | } | |
|
87 | ||
|
88 | % hardcode size of all verbatim environments to be a bit smaller | |
|
89 | \makeatletter | |
|
90 | \g@addto@macro\@verbatim\small\topsep=0.5em\partopsep=0pt | |
|
91 | \makeatother | |
|
92 | ||
|
93 | % Prevent overflowing lines due to urls and other hard-to-break entities. | |
|
94 | \sloppy |
@@ -9,23 +9,82 b' called nb_figure_NN.png. To avoid the two-step process, ipynb -> rst -> html,' | |||
|
9 | 9 | use '--format quick-html' which will do ipynb -> html, but won't look as |
|
10 | 10 | pretty. |
|
11 | 11 | """ |
|
12 | ||
|
12 | #----------------------------------------------------------------------------- | |
|
13 | # Imports | |
|
14 | #----------------------------------------------------------------------------- | |
|
15 | from __future__ import print_function | |
|
16 | ||
|
17 | # Stdlib | |
|
18 | import codecs | |
|
19 | import logging | |
|
13 | 20 | import os |
|
21 | import pprint | |
|
22 | import re | |
|
14 | 23 | import subprocess |
|
15 | 24 | import sys |
|
25 | ||
|
26 | inkscape = 'inkscape' | |
|
27 | if sys.platform == 'darwin': | |
|
28 | inkscape = '/Applications/Inkscape.app/Contents/Resources/bin/inkscape' | |
|
29 | if not os.path.exists(inkscape): | |
|
30 | inkscape = None | |
|
31 | ||
|
32 | # From IPython | |
|
16 | 33 | from IPython.external import argparse |
|
17 | 34 | from IPython.nbformat import current as nbformat |
|
18 | 35 | from IPython.utils.text import indent |
|
19 | 36 | from decorators import DocInherit |
|
20 | 37 | |
|
21 | # Cell converters | |
|
38 | #----------------------------------------------------------------------------- | |
|
39 | # Utility functions | |
|
40 | #----------------------------------------------------------------------------- | |
|
41 | ||
|
42 | def remove_fake_files_url(cell): | |
|
43 | """Remove from the cell source the /files/ pseudo-path we use. | |
|
44 | """ | |
|
45 | src = cell.source | |
|
46 | cell.source = src.replace('/files/', '') | |
|
47 | ||
|
48 | ||
|
49 | def remove_ansi(src): | |
|
50 | """Strip all ANSI color escape sequences from input string. | |
|
51 | ||
|
52 | Parameters | |
|
53 | ---------- | |
|
54 | src : string | |
|
22 | 55 |
|
|
23 | def unknown_cell(cell): | |
|
24 | """Default converter for cells of unknown type. | |
|
56 | Returns | |
|
57 | ------- | |
|
58 | string | |
|
25 | 59 | """ |
|
60 | return re.sub(r'\033\[(0|\d;\d\d)m', '', src) | |
|
26 | 61 | |
|
27 | return rst_directive('.. warning:: Unknown cell') + \ | |
|
28 | [repr(cell)] | |
|
62 | ||
|
63 | # Pandoc-dependent code | |
|
64 | def markdown2latex(src): | |
|
65 | """Convert a markdown string to LaTeX via pandoc. | |
|
66 | ||
|
67 | This function will raise an error if pandoc is not installed. | |
|
68 | ||
|
69 | Any error messages generated by pandoc are printed to stderr. | |
|
70 | ||
|
71 | Parameters | |
|
72 | ---------- | |
|
73 | src : string | |
|
74 | Input string, assumed to be valid markdown. | |
|
75 | ||
|
76 | Returns | |
|
77 | ------- | |
|
78 | out : string | |
|
79 | Output as returned by pandoc. | |
|
80 | """ | |
|
81 | p = subprocess.Popen('pandoc -f markdown -t latex'.split(), | |
|
82 | stdin=subprocess.PIPE, stdout=subprocess.PIPE) | |
|
83 | out, err = p.communicate(src) | |
|
84 | if err: | |
|
85 | print(err, file=sys.stderr) | |
|
86 | #print('*'*20+'\n', out, '\n'+'*'*20) # dbg | |
|
87 | return out | |
|
29 | 88 | |
|
30 | 89 | |
|
31 | 90 | def rst_directive(directive, text=''): |
@@ -34,8 +93,9 b" def rst_directive(directive, text=''):" | |||
|
34 | 93 | out.extend([indent(text), '']) |
|
35 | 94 | return out |
|
36 | 95 | |
|
37 | # Converters for parts of a cell. | |
|
38 | ||
|
96 | #----------------------------------------------------------------------------- | |
|
97 | # Class declarations | |
|
98 | #----------------------------------------------------------------------------- | |
|
39 | 99 | |
|
40 | 100 | class ConversionException(Exception): |
|
41 | 101 | pass |
@@ -43,29 +103,43 b' class ConversionException(Exception):' | |||
|
43 | 103 | |
|
44 | 104 | class Converter(object): |
|
45 | 105 | default_encoding = 'utf-8' |
|
46 | ||
|
106 | extension = str() | |
|
107 | figures_counter = 0 | |
|
108 | infile = str() | |
|
109 | infile_dir = str() | |
|
110 | infile_root = str() | |
|
111 | files_dir = str() | |
|
112 | with_preamble = True | |
|
113 | user_preamble = None | |
|
114 | output = str() | |
|
115 | raw_as_verbatim = False | |
|
116 | ||
|
47 | 117 | def __init__(self, infile): |
|
48 | 118 | self.infile = infile |
|
49 |
self.dir |
|
|
50 | ||
|
51 | @property | |
|
52 | def extension(self): | |
|
53 | raise ConversionException("""extension must be defined in Converter | |
|
54 | subclass""") | |
|
119 | self.infile_dir = os.path.dirname(infile) | |
|
120 | infile_root = os.path.splitext(infile)[0] | |
|
121 | files_dir = infile_root + '_files' | |
|
122 | if not os.path.isdir(files_dir): | |
|
123 | os.mkdir(files_dir) | |
|
124 | self.infile_root = infile_root | |
|
125 | self.files_dir = files_dir | |
|
55 | 126 | |
|
56 | 127 | def dispatch(self, cell_type): |
|
57 | 128 | """return cell_type dependent render method, for example render_code |
|
58 | 129 | """ |
|
59 | # XXX: unknown_cell here is RST specific - make it generic | |
|
60 | return getattr(self, 'render_' + cell_type, unknown_cell) | |
|
130 | return getattr(self, 'render_' + cell_type, self.render_unknown) | |
|
61 | 131 | |
|
62 | 132 | def convert(self): |
|
63 | 133 | lines = [] |
|
64 | 134 | lines.extend(self.optional_header()) |
|
65 |
for |
|
|
66 | conv_fn = self.dispatch(cell.cell_type) | |
|
67 | lines.extend(conv_fn(cell)) | |
|
68 | lines.append('') | |
|
135 | for worksheet in self.nb.worksheets: | |
|
136 | for cell in worksheet.cells: | |
|
137 | #print(cell.cell_type) # dbg | |
|
138 | conv_fn = self.dispatch(cell.cell_type) | |
|
139 | if cell.cell_type in ('markdown', 'raw'): | |
|
140 | remove_fake_files_url(cell) | |
|
141 | lines.extend(conv_fn(cell)) | |
|
142 | lines.append('') | |
|
69 | 143 | lines.extend(self.optional_footer()) |
|
70 | 144 | return '\n'.join(lines) |
|
71 | 145 | |
@@ -83,12 +157,13 b' class Converter(object):' | |||
|
83 | 157 | def save(self, infile=None, encoding=None): |
|
84 | 158 | "read and parse notebook into self.nb" |
|
85 | 159 | if infile is None: |
|
86 |
|
|
|
160 | outfile = os.path.basename(self.infile) | |
|
161 | outfile = os.path.splitext(outfile)[0] + '.' + self.extension | |
|
87 | 162 | if encoding is None: |
|
88 | 163 | encoding = self.default_encoding |
|
89 |
with open( |
|
|
164 | with open(outfile, 'w') as f: | |
|
90 | 165 | f.write(self.output.encode(encoding)) |
|
91 |
return |
|
|
166 | return os.path.abspath(outfile) | |
|
92 | 167 | |
|
93 | 168 | def optional_header(self): |
|
94 | 169 | return [] |
@@ -96,6 +171,28 b' class Converter(object):' | |||
|
96 | 171 | def optional_footer(self): |
|
97 | 172 | return [] |
|
98 | 173 | |
|
174 | def _new_figure(self, data, fmt): | |
|
175 | """Create a new figure file in the given format. | |
|
176 | ||
|
177 | Returns a path relative to the input file. | |
|
178 | """ | |
|
179 | figname = '%s_fig_%02i.%s' % (self.infile_root, | |
|
180 | self.figures_counter, fmt) | |
|
181 | self.figures_counter += 1 | |
|
182 | fullname = os.path.join(self.files_dir, figname) | |
|
183 | ||
|
184 | # Binary files are base64-encoded, SVG is already XML | |
|
185 | if fmt in ('png', 'jpg', 'pdf'): | |
|
186 | data = data.decode('base64') | |
|
187 | fopen = lambda fname: open(fname, 'wb') | |
|
188 | else: | |
|
189 | fopen = lambda fname: codecs.open(fname, 'wb', self.default_encoding) | |
|
190 | ||
|
191 | with fopen(fullname) as f: | |
|
192 | f.write(data) | |
|
193 | ||
|
194 | return fullname | |
|
195 | ||
|
99 | 196 | def render_heading(self, cell): |
|
100 | 197 | """convert a heading cell |
|
101 | 198 | |
@@ -114,18 +211,43 b' class Converter(object):' | |||
|
114 | 211 | Returns list.""" |
|
115 | 212 | raise NotImplementedError |
|
116 | 213 | |
|
117 |
def render_pyout(self, |
|
|
214 | def render_pyout(self, output): | |
|
118 | 215 | """convert pyout part of a code cell |
|
119 | 216 | |
|
120 | 217 | Returns list.""" |
|
121 | 218 | raise NotImplementedError |
|
122 | 219 | |
|
123 | def render_display_data(self, cell): | |
|
220 | ||
|
221 | def render_pyerr(self, output): | |
|
222 | """convert pyerr part of a code cell | |
|
223 | ||
|
224 | Returns list.""" | |
|
225 | raise NotImplementedError | |
|
226 | ||
|
227 | def _img_lines(self, img_file): | |
|
228 | """Return list of lines to include an image file.""" | |
|
229 | # Note: subclasses may choose to implement format-specific _FMT_lines | |
|
230 | # methods if they so choose (FMT in {png, svg, jpg, pdf}). | |
|
231 | raise NotImplementedError | |
|
232 | ||
|
233 | def render_display_data(self, output): | |
|
124 | 234 | """convert display data from the output of a code cell |
|
125 | 235 | |
|
126 | 236 | Returns list. |
|
127 | 237 | """ |
|
128 | raise NotImplementedError | |
|
238 | lines = [] | |
|
239 | ||
|
240 | for fmt in ['png', 'svg', 'jpg', 'pdf']: | |
|
241 | if fmt in output: | |
|
242 | img_file = self._new_figure(output[fmt], fmt) | |
|
243 | # Subclasses can have format-specific render functions (e.g., | |
|
244 | # latex has to auto-convert all SVG to PDF first). | |
|
245 | lines_fun = getattr(self, '_%s_lines' % fmt, None) | |
|
246 | if not lines_fun: | |
|
247 | lines_fun = self._img_lines | |
|
248 | lines.extend(lines_fun(img_file)) | |
|
249 | ||
|
250 | return lines | |
|
129 | 251 | |
|
130 | 252 | def render_stream(self, cell): |
|
131 | 253 | """convert stream part of a code cell |
@@ -133,16 +255,33 b' class Converter(object):' | |||
|
133 | 255 | Returns list.""" |
|
134 | 256 | raise NotImplementedError |
|
135 | 257 | |
|
136 |
def render_ |
|
|
137 |
"""convert |
|
|
258 | def render_raw(self, cell): | |
|
259 | """convert a cell with raw text | |
|
138 | 260 | |
|
139 | 261 | Returns list.""" |
|
140 | 262 | raise NotImplementedError |
|
141 | 263 | |
|
264 | def render_unknown(self, cell): | |
|
265 | """Render cells of unkown type | |
|
266 | ||
|
267 | Returns list.""" | |
|
268 | data = pprint.pformat(cell) | |
|
269 | logging.warning('Unknown cell:\n%s' % data) | |
|
270 | return self._unknown_lines(data) | |
|
271 | ||
|
272 | def _unknown_lines(self, data): | |
|
273 | """Return list of lines for an unknown cell. | |
|
274 | ||
|
275 | Parameters | |
|
276 | ---------- | |
|
277 | data : str | |
|
278 | The content of the unknown data as a single string. | |
|
279 | """ | |
|
280 | raise NotImplementedError | |
|
281 | ||
|
142 | 282 | |
|
143 | 283 | class ConverterRST(Converter): |
|
144 | 284 | extension = 'rst' |
|
145 | figures_counter = 0 | |
|
146 | 285 | heading_level = {1: '=', 2: '-', 3: '`', 4: '\'', 5: '.', 6: '~'} |
|
147 | 286 | |
|
148 | 287 | @DocInherit |
@@ -169,8 +308,11 b' class ConverterRST(Converter):' | |||
|
169 | 308 | return [cell.source] |
|
170 | 309 | |
|
171 | 310 | @DocInherit |
|
172 |
def render_ |
|
|
173 | return [cell.source] | |
|
311 | def render_raw(self, cell): | |
|
312 | if self.raw_as_verbatim: | |
|
313 | return ['::', '', indent(cell.source), ''] | |
|
314 | else: | |
|
315 | return [cell.source] | |
|
174 | 316 | |
|
175 | 317 | @DocInherit |
|
176 | 318 | def render_pyout(self, output): |
@@ -186,25 +328,15 b' class ConverterRST(Converter):' | |||
|
186 | 328 | return lines |
|
187 | 329 | |
|
188 | 330 | @DocInherit |
|
189 |
def render_ |
|
|
190 | lines = [] | |
|
191 | ||
|
192 | if 'png' in output: | |
|
193 | # XXX: make the figures notebooks specific (i.e. self.infile) so | |
|
194 | # that multiple notebook conversions don't clobber each other's | |
|
195 | # figures | |
|
196 | infile = 'nb_figure_%s.png' % self.figures_counter | |
|
197 | fullname = os.path.join(self.dirpath, infile) | |
|
198 | with open(fullname, 'w') as f: | |
|
199 | f.write(output.png.decode('base64')) | |
|
200 | ||
|
201 | self.figures_counter += 1 | |
|
202 | lines.append('.. image:: %s' % infile) | |
|
203 | lines.append('') | |
|
204 | ||
|
205 | return lines | |
|
331 | def render_pyerr(self, output): | |
|
332 | # Note: a traceback is a *list* of frames. | |
|
333 | return ['::', '', indent(remove_ansi('\n'.join(output.traceback))), ''] | |
|
206 | 334 | |
|
207 | 335 | @DocInherit |
|
336 | def _img_lines(self, img_file): | |
|
337 | return ['.. image:: %s' % img_file, ''] | |
|
338 | ||
|
339 | @DocInherit | |
|
208 | 340 | def render_stream(self, output): |
|
209 | 341 | lines = [] |
|
210 | 342 | |
@@ -213,9 +345,17 b' class ConverterRST(Converter):' | |||
|
213 | 345 | |
|
214 | 346 | return lines |
|
215 | 347 | |
|
348 | @DocInherit | |
|
349 | def _unknown_lines(self, data): | |
|
350 | return rst_directive('.. warning:: Unknown cell') + [data] | |
|
351 | ||
|
352 | ||
|
216 | 353 | class ConverterQuickHTML(Converter): |
|
217 | 354 | extension = 'html' |
|
218 | figures_counter = 0 | |
|
355 | ||
|
356 | def in_tag(self, tag, src): | |
|
357 | """Return a list of elements bracketed by the given tag""" | |
|
358 | return ['<%s>' % tag, src, '</%s>' % tag] | |
|
219 | 359 | |
|
220 | 360 | def optional_header(self): |
|
221 | 361 | # XXX: inject the IPython standard CSS into here |
@@ -259,54 +399,226 b' class ConverterQuickHTML(Converter):' | |||
|
259 | 399 | |
|
260 | 400 | @DocInherit |
|
261 | 401 | def render_markdown(self, cell): |
|
262 |
return |
|
|
402 | return self.in_tag('pre', cell.source) | |
|
263 | 403 | |
|
264 | 404 | @DocInherit |
|
265 |
def render_ |
|
|
266 | return ["<pre>"+cell.source+"</pre>"] | |
|
405 | def render_raw(self, cell): | |
|
406 | if self.raw_as_verbatim: | |
|
407 | return self.in_tag('pre', cell.source) | |
|
408 | else: | |
|
409 | return [cell.source] | |
|
267 | 410 | |
|
268 | 411 | @DocInherit |
|
269 | 412 | def render_pyout(self, output): |
|
270 |
lines = ['<tr><td><tt>Out[<b>%s</b>]:</tt></td></tr>' % |
|
|
413 | lines = ['<tr><td><tt>Out[<b>%s</b>]:</tt></td></tr>' % | |
|
414 | output.prompt_number, '<td>'] | |
|
271 | 415 | |
|
272 | 416 | # output is a dictionary like object with type as a key |
|
273 | if 'latex' in output: | |
|
274 | lines.append("<pre>") | |
|
275 |
lines.extend(indent(output |
|
|
276 | lines.append("</pre>") | |
|
417 | for out_type in ('text', 'latex'): | |
|
418 | if out_type in output: | |
|
419 | lines.extend(self.in_tag('pre', indent(output[out_type]))) | |
|
420 | ||
|
421 | return lines | |
|
422 | ||
|
423 | @DocInherit | |
|
424 | def render_pyerr(self, output): | |
|
425 | # Note: a traceback is a *list* of frames. | |
|
426 | return self.in_tag('pre', remove_ansi('\n'.join(output.traceback))) | |
|
427 | ||
|
428 | @DocInherit | |
|
429 | def _img_lines(self, img_file): | |
|
430 | return ['<img src="%s">' % img_file, ''] | |
|
431 | ||
|
432 | @DocInherit | |
|
433 | def render_stream(self, output): | |
|
434 | lines = [] | |
|
277 | 435 | |
|
278 | 436 | if 'text' in output: |
|
279 |
lines.append( |
|
|
280 | lines.extend(indent(output.text)) | |
|
281 | lines.append("</pre>") | |
|
437 | lines.append(output.text) | |
|
282 | 438 | |
|
283 | 439 | return lines |
|
284 | 440 | |
|
285 | 441 | @DocInherit |
|
286 | def render_display_data(self, output): | |
|
287 | lines = [] | |
|
442 | def _unknown_lines(self, data): | |
|
443 | return ['<h2>Warning:: Unknown cell</h2>'] + self.in_tag('pre', data) | |
|
444 | ||
|
288 | 445 | |
|
289 | if 'png' in output: | |
|
290 | infile = 'nb_figure_%s.png' % self.figures_counter | |
|
291 | fullname = os.path.join(self.dirpath, infile) | |
|
292 | with open(fullname, 'w') as f: | |
|
293 | f.write(output.png.decode('base64')) | |
|
446 | class ConverterLaTeX(Converter): | |
|
447 | """Converts a notebook to a .tex file suitable for pdflatex. | |
|
294 | 448 |
|
|
295 | self.figures_counter += 1 | |
|
296 | lines.append('<img src="%s">' % infile) | |
|
297 | lines.append('') | |
|
449 | Note: this converter *needs*: | |
|
450 | ||
|
451 | - `pandoc`: for all conversion of markdown cells. If your notebook only | |
|
452 | has Raw cells, pandoc will not be needed. | |
|
453 | ||
|
454 | - `inkscape`: if your notebook has SVG figures. These need to be | |
|
455 | converted to PDF before inclusion in the TeX file, as LaTeX doesn't | |
|
456 | understand SVG natively. | |
|
457 | ||
|
458 | You will in general obtain much better final PDF results if you configure | |
|
459 | the matplotlib backend to create SVG output with | |
|
460 | ||
|
461 | %config InlineBackend.figure_format = 'svg' | |
|
462 | ||
|
463 | (or set the equivalent flag at startup or in your configuration profile). | |
|
464 | """ | |
|
465 | extension = 'tex' | |
|
466 | documentclass = 'article' | |
|
467 | documentclass_options = '11pt,english' | |
|
468 | heading_map = {1: r'\section', | |
|
469 | 2: r'\subsection', | |
|
470 | 3: r'\subsubsection', | |
|
471 | 4: r'\paragraph', | |
|
472 | 5: r'\subparagraph', | |
|
473 | 6: r'\subparagraph'} | |
|
474 | ||
|
475 | def in_env(self, environment, lines): | |
|
476 | """Return list of environment lines for input lines | |
|
477 | ||
|
478 | Parameters | |
|
479 | ---------- | |
|
480 | env : string | |
|
481 | Name of the environment to bracket with begin/end. | |
|
482 | ||
|
483 | lines: """ | |
|
484 | out = [r'\begin{%s}' % environment] | |
|
485 | if isinstance(lines, basestring): | |
|
486 | out.append(lines) | |
|
487 | else: # list | |
|
488 | out.extend(lines) | |
|
489 | out.append(r'\end{%s}' % environment) | |
|
490 | return out | |
|
491 | ||
|
492 | def convert(self): | |
|
493 | # The main body is done by the logic in the parent class, and that's | |
|
494 | # all we need if preamble support has been turned off. | |
|
495 | body = super(ConverterLaTeX, self).convert() | |
|
496 | if not self.with_preamble: | |
|
497 | return body | |
|
498 | # But if preamble is on, then we need to construct a proper, standalone | |
|
499 | # tex file. | |
|
500 | ||
|
501 | # Tag the document at the top and set latex class | |
|
502 | final = [ r'%% This file was auto-generated by IPython, do NOT edit', | |
|
503 | r'%% Conversion from the original notebook file:', | |
|
504 | r'%% {0}'.format(self.infile), | |
|
505 | r'%%', | |
|
506 | r'\documentclass[%s]{%s}' % (self.documentclass_options, | |
|
507 | self.documentclass), | |
|
508 | '', | |
|
509 | ] | |
|
510 | # Load our own preamble, which is stored next to the main file. We | |
|
511 | # need to be careful in case the script entry point is a symlink | |
|
512 | myfile = __file__ if not os.path.islink(__file__) else \ | |
|
513 | os.readlink(__file__) | |
|
514 | with open(os.path.join(os.path.dirname(myfile), 'preamble.tex')) as f: | |
|
515 | final.append(f.read()) | |
|
516 | ||
|
517 | # Load any additional user-supplied preamble | |
|
518 | if self.user_preamble: | |
|
519 | final.extend(['', '%% Adding user preamble from file:', | |
|
520 | '%% {0}'.format(self.user_preamble), '']) | |
|
521 | with open(self.user_preamble) as f: | |
|
522 | final.append(f.read()) | |
|
523 | ||
|
524 | # Include document body | |
|
525 | final.extend([ r'\begin{document}', '', | |
|
526 | body, | |
|
527 | r'\end{document}', '']) | |
|
528 | # Retun value must be a string | |
|
529 | return '\n'.join(final) | |
|
530 | ||
|
531 | @DocInherit | |
|
532 | def render_heading(self, cell): | |
|
533 | marker = self.heading_map[cell.level] | |
|
534 | return ['%s{%s}' % (marker, cell.source) ] | |
|
535 | ||
|
536 | @DocInherit | |
|
537 | def render_code(self, cell): | |
|
538 | if not cell.input: | |
|
539 | return [] | |
|
540 | ||
|
541 | # Cell codes first carry input code, we use lstlisting for that | |
|
542 | lines = [r'\begin{codecell}'] | |
|
543 | ||
|
544 | lines.extend(self.in_env('codeinput', | |
|
545 | self.in_env('lstlisting', cell.input))) | |
|
546 | ||
|
547 | outlines = [] | |
|
548 | for output in cell.outputs: | |
|
549 | conv_fn = self.dispatch(output.output_type) | |
|
550 | outlines.extend(conv_fn(output)) | |
|
551 | ||
|
552 | # And then output of many possible types; use a frame for all of it. | |
|
553 | if outlines: | |
|
554 | lines.extend(self.in_env('codeoutput', outlines)) | |
|
555 | ||
|
556 | lines.append(r'\end{codecell}') | |
|
298 | 557 | |
|
299 | 558 | return lines |
|
300 | 559 | |
|
560 | ||
|
561 | @DocInherit | |
|
562 | def _img_lines(self, img_file): | |
|
563 | return self.in_env('center', | |
|
564 | [r'\includegraphics[width=3in]{%s}' % img_file, r'\par']) | |
|
565 | ||
|
566 | def _svg_lines(self, img_file): | |
|
567 | base_file = os.path.splitext(img_file)[0] | |
|
568 | pdf_file = base_file + '.pdf' | |
|
569 | subprocess.check_call([ inkscape, '--export-pdf=%s' % pdf_file, | |
|
570 | img_file]) | |
|
571 | return self._img_lines(pdf_file) | |
|
572 | ||
|
301 | 573 | @DocInherit |
|
302 | 574 | def render_stream(self, output): |
|
303 | 575 | lines = [] |
|
304 | 576 | |
|
305 | 577 | if 'text' in output: |
|
306 |
lines. |
|
|
578 | lines.extend(self.in_env('verbatim', output.text.strip())) | |
|
579 | ||
|
580 | return lines | |
|
581 | ||
|
582 | @DocInherit | |
|
583 | def render_markdown(self, cell): | |
|
584 | return [markdown2latex(cell.source)] | |
|
585 | ||
|
586 | @DocInherit | |
|
587 | def render_pyout(self, output): | |
|
588 | lines = [] | |
|
589 | ||
|
590 | # output is a dictionary like object with type as a key | |
|
591 | if 'latex' in output: | |
|
592 | lines.extend(output.latex) | |
|
593 | ||
|
594 | if 'text' in output: | |
|
595 | lines.extend(self.in_env('verbatim', output.text)) | |
|
307 | 596 | |
|
308 | 597 | return lines |
|
309 | 598 | |
|
599 | @DocInherit | |
|
600 | def render_pyerr(self, output): | |
|
601 | # Note: a traceback is a *list* of frames. | |
|
602 | return self.in_env('traceback', | |
|
603 | self.in_env('verbatim', | |
|
604 | remove_ansi('\n'.join(output.traceback)))) | |
|
605 | ||
|
606 | @DocInherit | |
|
607 | def render_raw(self, cell): | |
|
608 | if self.raw_as_verbatim: | |
|
609 | return self.in_env('verbatim', cell.source) | |
|
610 | else: | |
|
611 | return [cell.source] | |
|
612 | ||
|
613 | @DocInherit | |
|
614 | def _unknown_lines(self, data): | |
|
615 | return [r'{\vspace{5mm}\bf WARNING:: unknown cell:}'] + \ | |
|
616 | self.in_env('verbatim', data) | |
|
617 | ||
|
618 | #----------------------------------------------------------------------------- | |
|
619 | # Standalone conversion functions | |
|
620 | #----------------------------------------------------------------------------- | |
|
621 | ||
|
310 | 622 | def rst2simplehtml(infile): |
|
311 | 623 | """Convert a rst file to simplified html suitable for blogger. |
|
312 | 624 | |
@@ -355,7 +667,7 b' def rst2simplehtml(infile):' | |||
|
355 | 667 | |
|
356 | 668 | return newfname |
|
357 | 669 | |
|
358 | known_formats = "rst (default), html, quick-html" | |
|
670 | known_formats = "rst (default), html, quick-html, latex" | |
|
359 | 671 | |
|
360 | 672 | def main(infile, format='rst'): |
|
361 | 673 | """Convert a notebook to html in one step""" |
@@ -373,11 +685,16 b" def main(infile, format='rst'):" | |||
|
373 | 685 | elif format == 'quick-html': |
|
374 | 686 | converter = ConverterQuickHTML(infile) |
|
375 | 687 | rstfname = converter.render() |
|
688 | elif format == 'latex': | |
|
689 | converter = ConverterLaTeX(infile) | |
|
690 | latexfname = converter.render() | |
|
376 | 691 | else: |
|
377 | 692 | raise SystemExit("Unknown format '%s', " % format + |
|
378 | 693 | "known formats are: " + known_formats) |
|
379 | 694 | |
|
380 | ||
|
695 | #----------------------------------------------------------------------------- | |
|
696 | # Script main | |
|
697 | #----------------------------------------------------------------------------- | |
|
381 | 698 | |
|
382 | 699 | if __name__ == '__main__': |
|
383 | 700 | parser = argparse.ArgumentParser(description=__doc__, |
@@ -51,15 +51,12 b'' | |||
|
51 | 51 | { |
|
52 | 52 | "cell_type": "markdown", |
|
53 | 53 | "source": [ |
|
54 | "A section heading", | |
|
55 | "=================", | |
|
56 | "", | |
|
57 | 54 | "A bit of text, with *important things*:", |
|
58 | 55 | "", |
|
59 | 56 | "* and", |
|
60 | "* more", | |
|
57 | "* more that **are boldface**, as well as `verbatim`.", | |
|
61 | 58 | "", |
|
62 |
"Using |
|
|
59 | "Using markdown hyperlinks for [ipython](http://ipython.org)." | |
|
63 | 60 | ] |
|
64 | 61 | }, |
|
65 | 62 | { |
@@ -67,21 +64,21 b'' | |||
|
67 | 64 | "collapsed": false, |
|
68 | 65 | "input": [ |
|
69 | 66 | "f = figure()", |
|
70 | "plot([1])", | |
|
67 | "plot([1,2,3])", | |
|
71 | 68 | "display(f)" |
|
72 | 69 | ], |
|
73 | 70 | "language": "python", |
|
74 | 71 | "outputs": [ |
|
75 | 72 | { |
|
76 | 73 | "output_type": "display_data", |
|
77 | "png": "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\n", | |
|
74 | "png": "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\n", | |
|
78 | 75 | "text": [ |
|
79 |
"<matplotlib.figure.Figure at 0x |
|
|
76 | "<matplotlib.figure.Figure at 0x981bccc>" | |
|
80 | 77 | ] |
|
81 | 78 | }, |
|
82 | 79 | { |
|
83 | 80 | "output_type": "display_data", |
|
84 | "png": "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\n" | |
|
81 | "png": "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\n" | |
|
85 | 82 | } |
|
86 | 83 | ], |
|
87 | 84 | "prompt_number": 1 |
@@ -128,7 +125,8 b'' | |||
|
128 | 125 | "output_type": "stream", |
|
129 | 126 | "stream": "stdout", |
|
130 | 127 | "text": [ |
|
131 | "hello world" | |
|
128 | "hello world", | |
|
129 | "" | |
|
132 | 130 | ] |
|
133 | 131 | } |
|
134 | 132 | ], |
@@ -141,17 +139,70 b'' | |||
|
141 | 139 | ] |
|
142 | 140 | }, |
|
143 | 141 | { |
|
144 |
"cell_type": " |
|
|
142 | "cell_type": "raw", | |
|
145 | 143 | "source": [ |
|
146 | 144 | "plain text" |
|
147 | 145 | ] |
|
148 | 146 | }, |
|
149 | 147 | { |
|
150 | 148 | "cell_type": "code", |
|
151 |
"collapsed": |
|
|
152 |
"input": [ |
|
|
149 | "collapsed": false, | |
|
150 | "input": [ | |
|
151 | "import sys", | |
|
152 | "m = 'A message'", | |
|
153 | "print m, 'to stdout'", | |
|
154 | "print >> sys.stderr, m, 'to stderr'", | |
|
155 | "m" | |
|
156 | ], | |
|
153 | 157 | "language": "python", |
|
154 |
"outputs": [ |
|
|
158 | "outputs": [ | |
|
159 | { | |
|
160 | "output_type": "stream", | |
|
161 | "stream": "stdout", | |
|
162 | "text": [ | |
|
163 | "A message to stdout", | |
|
164 | "" | |
|
165 | ] | |
|
166 | }, | |
|
167 | { | |
|
168 | "output_type": "stream", | |
|
169 | "stream": "stderr", | |
|
170 | "text": [ | |
|
171 | "A message to stderr", | |
|
172 | "" | |
|
173 | ] | |
|
174 | }, | |
|
175 | { | |
|
176 | "output_type": "pyout", | |
|
177 | "prompt_number": 5, | |
|
178 | "text": [ | |
|
179 | "'A message'" | |
|
180 | ] | |
|
181 | } | |
|
182 | ], | |
|
183 | "prompt_number": 5 | |
|
184 | }, | |
|
185 | { | |
|
186 | "cell_type": "code", | |
|
187 | "collapsed": false, | |
|
188 | "input": [ | |
|
189 | "# a traceback", | |
|
190 | "1/0" | |
|
191 | ], | |
|
192 | "language": "python", | |
|
193 | "outputs": [ | |
|
194 | { | |
|
195 | "ename": "ZeroDivisionError", | |
|
196 | "evalue": "integer division or modulo by zero", | |
|
197 | "output_type": "pyerr", | |
|
198 | "traceback": [ | |
|
199 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[1;31mZeroDivisionError\u001b[0m Traceback (most recent call last)", | |
|
200 | "\u001b[1;32m/home/fperez/ipython/nbconvert/tests/<ipython-input-6-03412a6702b7>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;31m# a traceback\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[1;36m1\u001b[0m\u001b[1;33m/\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", | |
|
201 | "\u001b[1;31mZeroDivisionError\u001b[0m: integer division or modulo by zero" | |
|
202 | ] | |
|
203 | } | |
|
204 | ], | |
|
205 | "prompt_number": 6 | |
|
155 | 206 | } |
|
156 | 207 | ] |
|
157 | 208 | } |
General Comments 0
You need to be logged in to leave comments.
Login now