##// END OF EJS Templates
start tex template
Matthias BUSSONNIER -
Show More
@@ -1,218 +1,221 b''
1 """Base classes for the notebook conversion pipeline.
1 """Base classes for the notebook conversion pipeline.
2
2
3 This module defines Converter, from which all objects designed to implement
3 This module defines Converter, from which all objects designed to implement
4 a conversion of IPython notebooks to some other format should inherit.
4 a conversion of IPython notebooks to some other format should inherit.
5 """
5 """
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Copyright (c) 2012, the IPython Development Team.
7 # Copyright (c) 2012, the IPython Development Team.
8 #
8 #
9 # Distributed under the terms of the Modified BSD License.
9 # Distributed under the terms of the Modified BSD License.
10 #
10 #
11 # The full license is in the file COPYING.txt, distributed with this software.
11 # The full license is in the file COPYING.txt, distributed with this software.
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13
13
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17
17
18 from __future__ import print_function, absolute_import
18 from __future__ import print_function, absolute_import
19
19
20 # Stdlib imports
20 # Stdlib imports
21 import io
21 import io
22 import os
22 import os
23 import re
23 import re
24 from IPython.utils import path
24 from IPython.utils import path
25
25
26 from jinja2 import Environment, FileSystemLoader
26 from jinja2 import Environment, FileSystemLoader
27 env = Environment(
27 env = Environment(
28 loader=FileSystemLoader('./templates/'),
28 loader=FileSystemLoader('./templates/'),
29 extensions=['jinja2.ext.loopcontrols']
29 extensions=['jinja2.ext.loopcontrols']
30 )
30 )
31
31
32 texenv = Environment(
32 texenv = Environment(
33 loader=FileSystemLoader('./templates/tex/'),
33 loader=FileSystemLoader('./templates/tex/'),
34 extensions=['jinja2.ext.loopcontrols']
34 extensions=['jinja2.ext.loopcontrols']
35 )
35 )
36
36
37 # IPython imports
37 # IPython imports
38 from IPython.nbformat import current as nbformat
38 from IPython.nbformat import current as nbformat
39 from IPython.config.configurable import Configurable
39 from IPython.config.configurable import Configurable
40 from IPython.utils.traitlets import ( Unicode, Any)
40 from IPython.utils.traitlets import ( Unicode, Any)
41
41
42 # Our own imports
42 # Our own imports
43 from IPython.utils.text import indent
43 from IPython.utils.text import indent
44 from .utils import remove_ansi
44 from .utils import remove_ansi
45 from markdown import markdown
45 from markdown import markdown
46 from .utils import highlight, ansi2html
46 from .utils import highlight, ansi2html
47 from .utils import markdown2latex
47 #-----------------------------------------------------------------------------
48 #-----------------------------------------------------------------------------
48 # Class declarations
49 # Class declarations
49 #-----------------------------------------------------------------------------
50 #-----------------------------------------------------------------------------
50 def rm_fake(strng):
51 def rm_fake(strng):
51 return strng.replace('/files/', '')
52 return strng.replace('/files/', '')
52
53
53 class ConversionException(Exception):
54 class ConversionException(Exception):
54 pass
55 pass
55
56
56
57
57 def python_comment(string):
58 def python_comment(string):
58 return '# '+'\n# '.join(string.split('\n'))
59 return '# '+'\n# '.join(string.split('\n'))
59
60
60
61
61
62
62 def header_body():
63 def header_body():
63 """Return the body of the header as a list of strings."""
64 """Return the body of the header as a list of strings."""
64
65
65 from pygments.formatters import HtmlFormatter
66 from pygments.formatters import HtmlFormatter
66
67
67 header = []
68 header = []
68 static = os.path.join(path.get_ipython_package_dir(),
69 static = os.path.join(path.get_ipython_package_dir(),
69 'frontend', 'html', 'notebook', 'static',
70 'frontend', 'html', 'notebook', 'static',
70 )
71 )
71 here = os.path.split(os.path.realpath(__file__))[0]
72 here = os.path.split(os.path.realpath(__file__))[0]
72 css = os.path.join(static, 'css')
73 css = os.path.join(static, 'css')
73 for sheet in [
74 for sheet in [
74 # do we need jquery and prettify?
75 # do we need jquery and prettify?
75 # os.path.join(static, 'jquery', 'css', 'themes', 'base',
76 # os.path.join(static, 'jquery', 'css', 'themes', 'base',
76 # 'jquery-ui.min.css'),
77 # 'jquery-ui.min.css'),
77 # os.path.join(static, 'prettify', 'prettify.css'),
78 # os.path.join(static, 'prettify', 'prettify.css'),
78 os.path.join(css, 'boilerplate.css'),
79 os.path.join(css, 'boilerplate.css'),
79 os.path.join(css, 'fbm.css'),
80 os.path.join(css, 'fbm.css'),
80 os.path.join(css, 'notebook.css'),
81 os.path.join(css, 'notebook.css'),
81 os.path.join(css, 'renderedhtml.css'),
82 os.path.join(css, 'renderedhtml.css'),
82 # our overrides:
83 # our overrides:
83 os.path.join(here, '..', 'css', 'static_html.css'),
84 os.path.join(here, '..', 'css', 'static_html.css'),
84 ]:
85 ]:
85
86
86 with io.open(sheet, encoding='utf-8') as f:
87 with io.open(sheet, encoding='utf-8') as f:
87 s = f.read()
88 s = f.read()
88 header.append(s)
89 header.append(s)
89
90
90 pygments_css = HtmlFormatter().get_style_defs('.highlight')
91 pygments_css = HtmlFormatter().get_style_defs('.highlight')
91 header.append(pygments_css)
92 header.append(pygments_css)
92 return header
93 return header
93
94
94 inlining = {}
95 inlining = {}
95 inlining['css'] = header_body()
96 inlining['css'] = header_body()
96
97
97
98
98 def filter_data_type(output):
99 def filter_data_type(output):
99 for fmt in ['html', 'pdf', 'svg', 'latex', 'png', 'jpg', 'jpeg' , 'text']:
100 for fmt in ['html', 'pdf', 'svg', 'latex', 'png', 'jpg', 'jpeg' , 'text']:
100 if fmt in output:
101 if fmt in output:
101 return [fmt]
102 return [fmt]
102
103
103
104
104 env.filters['filter_data_type'] = filter_data_type
105 env.filters['filter_data_type'] = filter_data_type
105 env.filters['pycomment'] = python_comment
106 env.filters['pycomment'] = python_comment
106 env.filters['indent'] = indent
107 env.filters['indent'] = indent
107 env.filters['rm_fake'] = rm_fake
108 env.filters['rm_fake'] = rm_fake
108 env.filters['rm_ansi'] = remove_ansi
109 env.filters['rm_ansi'] = remove_ansi
109 env.filters['markdown'] = markdown
110 env.filters['markdown'] = markdown
110 env.filters['highlight'] = highlight
111 env.filters['highlight'] = highlight
111 env.filters['ansi2html'] = ansi2html
112 env.filters['ansi2html'] = ansi2html
112
113
113
114
114
115
115 LATEX_SUBS = (
116 LATEX_SUBS = (
116 (re.compile(r'\\'), r'\\textbackslash'),
117 (re.compile(r'\\'), r'\\textbackslash'),
117 (re.compile(r'([{}_#%&$])'), r'\\\1'),
118 (re.compile(r'([{}_#%&$])'), r'\\\1'),
118 (re.compile(r'~'), r'\~{}'),
119 (re.compile(r'~'), r'\~{}'),
119 (re.compile(r'\^'), r'\^{}'),
120 (re.compile(r'\^'), r'\^{}'),
120 (re.compile(r'"'), r"''"),
121 (re.compile(r'"'), r"''"),
121 (re.compile(r'\.\.\.+'), r'\\ldots'),
122 (re.compile(r'\.\.\.+'), r'\\ldots'),
122 )
123 )
123
124
124 def escape_tex(value):
125 def escape_tex(value):
125 newval = value
126 newval = value
126 for pattern, replacement in LATEX_SUBS:
127 for pattern, replacement in LATEX_SUBS:
127 newval = pattern.sub(replacement, newval)
128 newval = pattern.sub(replacement, newval)
128 return newval
129 return newval
129
130
130 texenv.block_start_string = '((*'
131 texenv.block_start_string = '((*'
131 texenv.block_end_string = '*))'
132 texenv.block_end_string = '*))'
132 texenv.variable_start_string = '((('
133 texenv.variable_start_string = '((('
133 texenv.variable_end_string = ')))'
134 texenv.variable_end_string = ')))'
134 texenv.comment_start_string = '((='
135 texenv.comment_start_string = '((='
135 texenv.comment_end_string = '=))'
136 texenv.comment_end_string = '=))'
136 texenv.filters['escape_tex'] = escape_tex
137 texenv.filters['escape_tex'] = escape_tex
137
138
138 texenv.filters['filter_data_type'] = filter_data_type
139 texenv.filters['filter_data_type'] = filter_data_type
139 texenv.filters['pycomment'] = python_comment
140 texenv.filters['pycomment'] = python_comment
140 texenv.filters['indent'] = indent
141 texenv.filters['indent'] = indent
141 texenv.filters['rm_fake'] = rm_fake
142 texenv.filters['rm_fake'] = rm_fake
142 texenv.filters['rm_ansi'] = remove_ansi
143 texenv.filters['rm_ansi'] = remove_ansi
143 texenv.filters['markdown'] = markdown
144 texenv.filters['markdown'] = markdown
144 texenv.filters['highlight'] = highlight
145 texenv.filters['highlight'] = highlight
145 texenv.filters['ansi2html'] = ansi2html
146 texenv.filters['ansi2html'] = ansi2html
147 texenv.filters['markdown2latex'] = markdown2latex
148 markdown2latex
146
149
147
150
148 def haspyout_transformer(nb,_):
151 def haspyout_transformer(nb,_):
149 print('calling...')
152 print('calling...')
150 for worksheet in nb.worksheets:
153 for worksheet in nb.worksheets:
151 print('worksheet')
154 print('worksheet')
152 for cell in worksheet.cells:
155 for cell in worksheet.cells:
153 cell.type = cell.cell_type
156 cell.type = cell.cell_type
154 cell.haspyout = False
157 cell.haspyout = False
155 for out in cell.get('outputs', []):
158 for out in cell.get('outputs', []):
156 if out.output_type == 'pyout':
159 if out.output_type == 'pyout':
157 cell.haspyout = True
160 cell.haspyout = True
158 break
161 break
159 return nb
162 return nb
160
163
161 class ConverterTemplate(Configurable):
164 class ConverterTemplate(Configurable):
162 """ A Jinja2 base converter templates"""
165 """ A Jinja2 base converter templates"""
163
166
164 display_data_priority = ['pdf', 'svg', 'png', 'jpg', 'text']
167 display_data_priority = ['pdf', 'svg', 'png', 'jpg', 'text']
165 #-------------------------------------------------------------------------
168 #-------------------------------------------------------------------------
166 # Instance-level attributes that are set in the constructor for this
169 # Instance-level attributes that are set in the constructor for this
167 # class.
170 # class.
168 #-------------------------------------------------------------------------
171 #-------------------------------------------------------------------------
169 infile = Any()
172 infile = Any()
170
173
171
174
172 infile_dir = Unicode()
175 infile_dir = Unicode()
173
176
174 def __init__(self, tplfile='fullhtml', preprocessors=[], config=None,tex_environement=False, **kw):
177 def __init__(self, tplfile='fullhtml', preprocessors=[], config=None,tex_environement=False, **kw):
175 """
178 """
176 tplfile : jinja template file to process.
179 tplfile : jinja template file to process.
177
180
178 config: the Configurable confg object to pass around
181 config: the Configurable confg object to pass around
179
182
180 preprocessors: list of function to run on ipynb json data before conversion
183 preprocessors: list of function to run on ipynb json data before conversion
181 to extract/inline file,
184 to extract/inline file,
182
185
183 """
186 """
184 self.env = texenv if tex_environement else env
187 self.env = texenv if tex_environement else env
185 self.ext = '.tplx' if tex_environement else '.tpl'
188 self.ext = '.tplx' if tex_environement else '.tpl'
186 self.template = self.env.get_template(tplfile+self.ext)
189 self.template = self.env.get_template(tplfile+self.ext)
187 self.nb = None
190 self.nb = None
188 self.preprocessors = preprocessors
191 self.preprocessors = preprocessors
189 self.preprocessors.append(haspyout_transformer)
192 self.preprocessors.append(haspyout_transformer)
190 super(ConverterTemplate, self).__init__(config=config, **kw)
193 super(ConverterTemplate, self).__init__(config=config, **kw)
191
194
192
195
193 def process(self):
196 def process(self):
194 """
197 """
195 preprocess the notebook json for easier use with the templates.
198 preprocess the notebook json for easier use with the templates.
196 will call all the `preprocessor`s in order before returning it.
199 will call all the `preprocessor`s in order before returning it.
197 """
200 """
198 nb = self.nb
201 nb = self.nb
199
202
200 for preprocessor in self.preprocessors:
203 for preprocessor in self.preprocessors:
201 nb = preprocessor(nb,{})
204 nb = preprocessor(nb,{})
202
205
203 return nb
206 return nb
204
207
205 def convert(self):
208 def convert(self):
206 """ convert the ipynb file
209 """ convert the ipynb file
207
210
208 return both the converted ipynb file and a dict containing potential
211 return both the converted ipynb file and a dict containing potential
209 other resources
212 other resources
210 """
213 """
211 return self.template.render(nb=self.process(), inlining=inlining), {}
214 return self.template.render(nb=self.process(), inlining=inlining), {}
212
215
213
216
214 def read(self, filename):
217 def read(self, filename):
215 "read and parse notebook into NotebookNode called self.nb"
218 "read and parse notebook into NotebookNode called self.nb"
216 with io.open(filename) as f:
219 with io.open(filename) as f:
217 self.nb = nbformat.read(f, 'json')
220 self.nb = nbformat.read(f, 'json')
218
221
@@ -1,56 +1,198 b''
1 ((*- extends 'null.tplx' -*))
1 ((*- extends 'null.tplx' -*))
2
2
3 ((* block in_prompt *))
3 ((* block in_prompt *))
4 # In[(((cell.prompt_number if cell.prompt_number else ' ')))]:
4 # In[(((cell.prompt_number if cell.prompt_number else ' ')))]:
5 ((* endblock in_prompt *))
5 ((* endblock in_prompt *))
6
6
7 ((* block output_prompt *))
7 ((* block output_prompt *))
8 # Out[(((cell.prompt_number)))]:((* endblock output_prompt *))
8 # Out[(((cell.prompt_number)))]:((* endblock output_prompt *))
9
9
10 ((* block input *))((( cell.input )))
10 ((* block codecell *))
11 \begin{codecell}
12 ((( super() )))
13 \end{codecell}
14 ((* endblock *))
15
16 ((* block input *))
17 \begin{codeinput}
18 \begin{lstlisting}
19 ((( cell.input )))
20 \end{lstlisting}
21 \end{codeinput}
11 ((* endblock input *))
22 ((* endblock input *))
12
23
13
24
14 ((= Those Two are for error displaying
25 ((= Those Two are for error displaying
15 even if the first one seem to do nothing,
26 even if the first one seem to do nothing,
16 it introduces a new line
27 it introduces a new line
17
28
18 =))
29 =))
19 ((* block pyerr *))((( super() )))
30 ((* block pyerr *))((( super() )))
20 ((* endblock pyerr *))
31 ((* endblock pyerr *))
21
32
22 ((* block traceback_line *))
33 ((* block traceback_line *))
23 ((( line |indent| rm_ansi )))((* endblock traceback_line *))
34 ((( line |indent| rm_ansi )))((* endblock traceback_line *))
24 ((= .... =))
35 ((= .... =))
25
36
26
37
27 ((* block pyout *))
38 ((* block pyout *))
28 ((( output.text| indent | pycomment)))
39 ((( output.text| indent | pycomment)))
29 ((* endblock pyout *))
40 ((* endblock pyout *))
30
41
31 ((* block stream *))
42 ((* block stream *))
32 ((( output.text| indent | pycomment)))
43 ((( output.text| indent | pycomment)))
33 ((* endblock stream *))
44 ((* endblock stream *))
34
45
35
46
36
47
37
48
38 ((* block display_data scoped *))
49 ((* block display_data scoped *))
39 # image file:
50 # image file:
40 ((* endblock display_data *))
51 ((* endblock display_data *))
41
52
42 ((* block markdowncell scoped *))
53 ((* block markdowncell scoped *))
43 ((( cell.source | pycomment )))
54 ((( cell.source | markdown2latex )))
44 ((* endblock markdowncell *))
55 ((* endblock markdowncell *))
45
56
46 ((* block headingcell scoped *))
57 ((* block headingcell scoped *))
47 ((( '#' * cell.level )))((( cell.source | pycomment)))
58 \section{((( cell.source)))}
48 ((* endblock headingcell *))
59 ((* endblock headingcell *))
49
60
50 ((* block rawcell scoped *))
61 ((* block rawcell scoped *))
51 ((( cell.source | pycomment )))
62 ((( cell.source | pycomment )))
52 ((* endblock rawcell *))
63 ((* endblock rawcell *))
53
64
54 ((* block unknowncell scoped *))
65 ((* block unknowncell scoped *))
55 unknown type (((cell.type)))
66 unknown type (((cell.type)))
56 ((* endblock unknowncell *))
67 ((* endblock unknowncell *))
68
69
70
71 ((* block body *))
72 \begin{document}
73 ((( super() )))
74 \end{document}
75 ((* endblock*))
76
77 ((* block header *))
78 %% This file was auto-generated by IPython.
79 %% Conversion from the original notebook file:
80 %% tests/ipynbref/Gun_Data.orig.ipynb
81 %%
82 \documentclass[11pt,english]{article}
83
84 %% This is the automatic preamble used by IPython. Note that it does *not*
85 %% include a documentclass declaration, that is added at runtime to the overall
86 %% document.
87
88 \usepackage{amsmath}
89 \usepackage{amssymb}
90 \usepackage{graphicx}
91 \usepackage{ucs}
92 \usepackage[utf8x]{inputenc}
93
94 % needed for markdown enumerations to work
95 \usepackage{enumerate}
96
97 % Slightly bigger margins than the latex defaults
98 \usepackage{geometry}
99 \geometry{verbose,tmargin=3cm,bmargin=3cm,lmargin=2.5cm,rmargin=2.5cm}
100
101 % Define a few colors for use in code, links and cell shading
102 \usepackage{color}
103 \definecolor{orange}{cmyk}{0,0.4,0.8,0.2}
104 \definecolor{darkorange}{rgb}{.71,0.21,0.01}
105 \definecolor{darkgreen}{rgb}{.12,.54,.11}
106 \definecolor{myteal}{rgb}{.26, .44, .56}
107 \definecolor{gray}{gray}{0.45}
108 \definecolor{lightgray}{gray}{.95}
109 \definecolor{mediumgray}{gray}{.8}
110 \definecolor{inputbackground}{rgb}{.95, .95, .85}
111 \definecolor{outputbackground}{rgb}{.95, .95, .95}
112 \definecolor{traceback}{rgb}{1, .95, .95}
113
114 % Framed environments for code cells (inputs, outputs, errors, ...). The
115 % various uses of \unskip (or not) at the end were fine-tuned by hand, so don't
116 % randomly change them unless you're sure of the effect it will have.
117 \usepackage{framed}
118
119 % remove extraneous vertical space in boxes
120 \setlength\fboxsep{0pt}
121
122 % codecell is the whole input+output set of blocks that a Code cell can
123 % generate.
124
125 % TODO: unfortunately, it seems that using a framed codecell environment breaks
126 % the ability of the frames inside of it to be broken across pages. This
127 % causes at least the problem of having lots of empty space at the bottom of
128 % pages as new frames are moved to the next page, and if a single frame is too
129 % long to fit on a page, will completely stop latex from compiling the
130 % document. So unless we figure out a solution to this, we'll have to instead
131 % leave the codecell env. as empty. I'm keeping the original codecell
132 % definition here (a thin vertical bar) for reference, in case we find a
133 % solution to the page break issue.
134
135 %% \newenvironment{codecell}{%
136 %% \def\FrameCommand{\color{mediumgray} \vrule width 1pt \hspace{5pt}}%
137 %% \MakeFramed{\vspace{-0.5em}}}
138 %% {\unskip\endMakeFramed}
139
140 % For now, make this a no-op...
141 \newenvironment{codecell}{}
142
143 \newenvironment{codeinput}{%
144 \def\FrameCommand{\colorbox{inputbackground}}%
145 \MakeFramed{\advance\hsize-\width \FrameRestore}}
146 {\unskip\endMakeFramed}
147
148 \newenvironment{codeoutput}{%
149 \def\FrameCommand{\colorbox{outputbackground}}%
150 \vspace{-1.4em}
151 \MakeFramed{\advance\hsize-\width \FrameRestore}}
152 {\unskip\medskip\endMakeFramed}
153
154 \newenvironment{traceback}{%
155 \def\FrameCommand{\colorbox{traceback}}%
156 \MakeFramed{\advance\hsize-\width \FrameRestore}}
157 {\endMakeFramed}
158
159 % Use and configure listings package for nicely formatted code
160 \usepackage{listingsutf8}
161 \lstset{
162 language=python,
163 inputencoding=utf8x,
164 extendedchars=\true,
165 aboveskip=\smallskipamount,
166 belowskip=\smallskipamount,
167 xleftmargin=2mm,
168 breaklines=true,
169 basicstyle=\small \ttfamily,
170 showstringspaces=false,
171 keywordstyle=\color{blue}\bfseries,
172 commentstyle=\color{myteal},
173 stringstyle=\color{darkgreen},
174 identifierstyle=\color{darkorange},
175 columns=fullflexible, % tighter character kerning, like verb
176 }
177
178 % The hyperref package gives us a pdf with properly built
179 % internal navigation ('pdf bookmarks' for the table of contents,
180 % internal cross-reference links, web links for URLs, etc.)
181 \usepackage{hyperref}
182 \hypersetup{
183 breaklinks=true, % so long urls are correctly broken across lines
184 colorlinks=true,
185 urlcolor=blue,
186 linkcolor=darkorange,
187 citecolor=darkgreen,
188 }
189
190 % hardcode size of all verbatim environments to be a bit smaller
191 \makeatletter
192 \g@addto@macro\@verbatim\small\topsep=0.5em\partopsep=0pt
193 \makeatother
194
195 % Prevent overflowing lines due to urls and other hard-to-break entities.
196 \sloppy
197
198 ((* endblock *))
General Comments 0
You need to be logged in to leave comments. Login now