##// END OF EJS Templates
Split exporter into base and latex.
Jonathan Frederic -
Show More
@@ -0,0 +1,295 b''
1
2 """Latex exporter for the notebook conversion pipeline.
3
4 This module defines Exporter, a highly configurable converter
5 that uses Jinja2 to export notebook files into different format.
6
7 You can register both pre-transformers that will act on the notebook format
8 befor conversion and jinja filter that would then be availlable in the templates
9 """
10
11 #-----------------------------------------------------------------------------
12 # Copyright (c) 2013, the IPython Development Team.
13 #
14 # Distributed under the terms of the Modified BSD License.
15 #
16 # The full license is in the file COPYING.txt, distributed with this software.
17 #-----------------------------------------------------------------------------
18
19 #-----------------------------------------------------------------------------
20 # Imports
21 #-----------------------------------------------------------------------------
22 from .utils import highlight2latex #TODO
23
24 from .transformers.latex import LatexTransformer, rm_math_space #TODO: rm_math_space from filters
25
26 #Try to import the Sphinx exporter. If the user doesn't have Sphinx isntalled
27 #on his/her machine, fail silently.
28 try:
29 from .sphinx_transformer import (SphinxTransformer) #TODO
30 except ImportError:
31 SphinxTransformer = None
32
33 #-----------------------------------------------------------------------------
34 # Globals and constants
35 #-----------------------------------------------------------------------------
36
37 #Latex Jinja2 constants
38 LATEX_TEMPLATE_PATH = "/../templates/tex/"
39 LATEX_TEMPLATE_SKELETON_PATH = "/../templates/tex/skeleton/"
40 LATEX_TEMPLATE_EXTENSION = ".tplx"
41
42 #Special Jinja2 syntax that will not conflict when exporting latex.
43 LATEX_JINJA_COMMENT_BLOCK = ["((=", "=))"]
44 LATEX_JINJA_VARIABLE_BLOCK = ["(((", ")))"]
45 LATEX_JINJA_LOGIC_BLOCK = ["((*", "*))"]
46
47 #Latex substitutions for escaping latex.
48 LATEX_SUBS = (
49 (re.compile(r'\\'), r'\\textbackslash'),
50 (re.compile(r'([{}_#%&$])'), r'\\\1'),
51 (re.compile(r'~'), r'\~{}'),
52 (re.compile(r'\^'), r'\^{}'),
53 (re.compile(r'"'), r"''"),
54 (re.compile(r'\.\.\.+'), r'\\ldots'),
55 )
56
57 #-----------------------------------------------------------------------------
58 # Classes and functions
59 #-----------------------------------------------------------------------------
60 class LatexExporter(Configurable):
61 """ A Jinja2 base converter templates
62
63 Preprocess the ipynb files, feed it throug jinja templates,
64 and spit an converted files and a data object with other data
65 should be mostly configurable
66 """
67
68 #Processors that process the input data prior to the export, set in the
69 #constructor for this class.
70 preprocessors = []
71
72 def __init__(self, preprocessors={}, jinja_filters={}, config=None, export_format, **kw):
73 """ Init a new converter.
74
75 config: the Configurable config object to pass around.
76
77 preprocessors: dict of **availlable** key/value function to run on
78 ipynb json data before conversion to extract/inline file.
79 See `transformer.py` and `ConfigurableTransformers`
80
81 set the order in which the transformers should apply
82 with the `pre_transformer_order` trait of this class
83
84 transformers registerd by this key will take precedence on
85 default one.
86
87 jinja_filters: dict of supplementary jinja filter that should be made
88 availlable in template. If those are of Configurable Class type,
89 they will be instanciated with the config object as argument.
90
91 user defined filter will overwrite the one availlable by default.
92 """
93
94 #Merge default config options with user specific override options.
95 default_config = self._get_default_options()
96 if not config == None:
97 default_config._merge(config)
98 config = default_config
99
100 #Call the base class constructor
101 super(Exporter, self).__init__(config=config, **kw)
102
103 #Create a Latex environment if the user is exporting latex.
104 if self.tex_environement:
105 self.ext = LATEX_TEMPLATE_EXTENSION
106 self.env = Environment(
107 loader=FileSystemLoader([
108 os.path.dirname(os.path.realpath(__file__)) + LATEX_TEMPLATE_PATH,
109 os.path.dirname(os.path.realpath(__file__)) + LATEX_TEMPLATE_SKELETON_PATH,
110 ]),
111 extensions=JINJA_EXTENSIONS
112 )
113
114 #Set special Jinja2 syntax that will not conflict with latex.
115 self.env.block_start_string = LATEX_JINJA_LOGIC_BLOCK[0]
116 self.env.block_end_string = LATEX_JINJA_LOGIC_BLOCK[1]
117 self.env.variable_start_string = LATEX_JINJA_VARIABLE_BLOCK[0]
118 self.env.variable_end_string = LATEX_JINJA_VARIABLE_BLOCK[1]
119 self.env.comment_start_string = LATEX_JINJA_COMMENT_BLOCK[0]
120 self.env.comment_end_string = LATEX_JINJA_COMMENT_BLOCK[1]
121
122 else: #Standard environment
123 self.ext = TEMPLATE_EXTENSION
124 self.env = Environment(
125 loader=FileSystemLoader([
126 os.path.dirname(os.path.realpath(__file__)) + TEMPLATE_PATH,
127 os.path.dirname(os.path.realpath(__file__)) + TEMPLATE_SKELETON_PATH,
128 ]),
129 extensions=JINJA_EXTENSIONS
130 )
131
132 for name in self.pre_transformer_order:
133 # get the user-defined transformer first
134 transformer = preprocessors.get(name, getattr(trans, name, None))
135 if isinstance(transformer, MetaHasTraits):
136 transformer = transformer(config=config)
137 self.preprocessors.append(transformer)
138
139 #For compatibility, TODO: remove later.
140 self.preprocessors.append(trans.coalesce_streams)
141 self.preprocessors.append(trans.ExtractFigureTransformer(config=config))
142 self.preprocessors.append(trans.RevealHelpTransformer(config=config))
143 self.preprocessors.append(trans.CSSHtmlHeaderTransformer(config=config))
144 self.preprocessors.append(LatexTransformer(config=config))
145
146 #Only load the sphinx transformer if the file reference worked
147 #(Sphinx dependencies exist on the user's machine.)
148 if SphinxTransformer:
149 self.preprocessors.append(SphinxTransformer(config=config))
150
151 #Add filters to the Jinja2 environment
152 self.env.filters['filter_data_type'] = DataTypeFilter(config=config)
153 self.env.filters['pycomment'] = _python_comment
154 self.env.filters['indent'] = indent
155 self.env.filters['rm_fake'] = _rm_fake
156 self.env.filters['rm_ansi'] = remove_ansi
157 self.env.filters['markdown'] = markdown
158 self.env.filters['ansi2html'] = ansi2html
159 self.env.filters['markdown2latex'] = markdown_utils.markdown2latex
160 self.env.filters['markdown2rst'] = markdown_utils.markdown2rst
161 self.env.filters['get_lines'] = get_lines
162 self.env.filters['wrap'] = strings.wrap
163 self.env.filters['rm_dollars'] = strings.strip_dollars
164 self.env.filters['rm_math_space'] = rm_math_space
165 self.env.filters['highlight2html'] = highlight
166 self.env.filters['highlight2latex'] = highlight2latex
167
168 #Latex specific filters
169 if self.tex_environement:
170 self.env.filters['escape_tex'] = _escape_tex
171 self.env.filters['highlight'] = highlight2latex
172 else:
173 self.env.filters['highlight'] = highlight
174
175 #Load user filters. Overwrite existing filters if need be.
176 for key, user_filter in jinja_filters.iteritems():
177 if isinstance(user_filter, MetaHasTraits):
178 self.env.filters[key] = user_filter(config=config)
179 else:
180 self.env.filters[key] = user_filter
181
182 #Load the template file.
183 self.template = self.env.get_template(self.template_file+self.ext)
184
185
186 def export(self, nb):
187 """Export notebook object
188
189 nb: Notebook object to export.
190
191 Returns both the converted ipynb file and a dict containing the
192 resources created along the way via the transformers and Jinja2
193 processing.
194 """
195
196 nb, resources = self._preprocess(nb)
197 return self.template.render(nb=nb, resources=resources), resources
198
199
200 def from_filename(self, filename):
201 """Read and export a notebook from a filename
202
203 filename: Filename of the notebook file to export.
204
205 Returns both the converted ipynb file and a dict containing the
206 resources created along the way via the transformers and Jinja2
207 processing.
208 """
209 with io.open(filename) as f:
210 return self.export(nbformat.read(f, 'json'))
211
212
213 def from_file(self, file_stream):
214 """Read and export a notebook from a filename
215
216 file_stream: File handle of file that contains notebook data.
217
218 Returns both the converted ipynb file and a dict containing the
219 resources created along the way via the transformers and Jinja2
220 processing.
221 """
222
223 return self.export(nbformat.read(file_stream, 'json'))
224
225
226 def _preprocess(self, nb):
227 """ Preprocess the notebook using the transformers specific
228 for the current export format.
229
230 nb: Notebook to preprocess
231 """
232
233 #Dict of 'resources' that can be filled by the preprocessors.
234 resources = {}
235
236 #Run each transformer on the notebook. Carry the output along
237 #to each transformer
238 for transformer in self.preprocessors:
239 nb, resources = transformer(nb, resources)
240 return nb, resources
241
242
243 def _get_default_options(self, export_format):
244 """ Load the default options for built in formats.
245
246 export_format: Format being exported to.
247 """
248
249 c = get_config()
250
251 #Set default data extraction priorities.
252 c.GlobalConfigurable.display_data_priority =['svg', 'png', 'latex', 'jpg', 'jpeg','text']
253 c.ExtractFigureTransformer.display_data_priority=['svg', 'png', 'latex', 'jpg', 'jpeg','text']
254 c.ConverterTemplate.display_data_priority= ['svg', 'png', 'latex', 'jpg', 'jpeg','text']
255
256 #For most (or all cases), the template file name matches the format name.
257 c.ConverterTemplate.template_file = export_format
258
259 if export_format == "basichtml" or "fullhtml" or "reveal":
260 c.CSSHtmlHeaderTransformer.enabled=True
261 if export_format == 'reveal'
262 c.NbconvertApp.fileext='reveal.html'
263 else:
264 c.NbconvertApp.fileext='html'
265
266 elif export_format == "latex_sphinx_howto" or export_format == "latex_sphinx_manual":
267
268 #Turn on latex environment
269 c.ConverterTemplate.tex_environement=True
270
271 #Standard latex extension
272 c.NbconvertApp.fileext='tex'
273
274 #Prioritize latex extraction for latex exports.
275 c.GlobalConfigurable.display_data_priority =['latex', 'svg', 'png', 'jpg', 'jpeg' , 'text']
276 c.ExtractFigureTransformer.display_data_priority=['latex', 'svg', 'png', 'jpg', 'jpeg']
277 c.ExtractFigureTransformer.extra_ext_map={'svg':'pdf'}
278 c.ExtractFigureTransformer.enabled=True
279
280 # Enable latex transformers (make markdown2latex work with math $.)
281 c.LatexTransformer.enabled=True
282 c.SphinxTransformer.enabled = True
283
284 elif export_format == 'markdown':
285 c.NbconvertApp.fileext='md'
286 c.ExtractFigureTransformer.enabled=True
287
288 elif export_format == 'python':
289 c.NbconvertApp.fileext='py'
290
291
292 elif export_format == 'rst':
293 c.NbconvertApp.fileext='rst'
294 c.ExtractFigureTransformer.enabled=True
295 return c No newline at end of file
1 NO CONTENT: file renamed from api/exporter.py to api/base.py
NO CONTENT: file renamed from api/exporter.py to api/base.py
1 NO CONTENT: file renamed from api/exceptions.py to utils/exceptions.py
NO CONTENT: file renamed from api/exceptions.py to utils/exceptions.py
General Comments 0
You need to be logged in to leave comments. Login now