##// END OF EJS Templates
Merge pull request #3863 from damianavila/speaker_notes...
Matthias Bussonnier -
r12197:4565b731 merge
parent child Browse files
Show More
@@ -1,320 +1,322 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 """NBConvert is a utility for conversion of .ipynb files.
2 """NBConvert is a utility for conversion of .ipynb files.
3
3
4 Command-line interface for the NbConvert conversion utility.
4 Command-line interface for the NbConvert conversion utility.
5 """
5 """
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 #Copyright (c) 2013, the IPython Development Team.
7 #Copyright (c) 2013, 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 # Stdlib imports
18 # Stdlib imports
19 from __future__ import print_function
19 from __future__ import print_function
20
20
21 import logging
21 import logging
22 import sys
22 import sys
23 import os
23 import os
24 import glob
24 import glob
25
25
26 # From IPython
26 # From IPython
27 from IPython.core.application import BaseIPythonApplication, base_aliases, base_flags
27 from IPython.core.application import BaseIPythonApplication, base_aliases, base_flags
28 from IPython.config import catch_config_error, Configurable
28 from IPython.config import catch_config_error, Configurable
29 from IPython.utils.traitlets import (
29 from IPython.utils.traitlets import (
30 Unicode, List, Instance, DottedObjectName, Type, CaselessStrEnum,
30 Unicode, List, Instance, DottedObjectName, Type, CaselessStrEnum,
31 )
31 )
32 from IPython.utils.importstring import import_item
32 from IPython.utils.importstring import import_item
33 from IPython.utils.text import dedent
33 from IPython.utils.text import dedent
34
34
35 from .exporters.export import get_export_names, exporter_map
35 from .exporters.export import get_export_names, exporter_map
36 from IPython.nbconvert import exporters, transformers, writers, post_processors
36 from IPython.nbconvert import exporters, transformers, writers, post_processors
37 from .utils.base import NbConvertBase
37 from .utils.base import NbConvertBase
38 from .utils.exceptions import ConversionException
38 from .utils.exceptions import ConversionException
39
39
40 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
41 #Classes and functions
41 #Classes and functions
42 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
43
43
44 class DottedOrNone(DottedObjectName):
44 class DottedOrNone(DottedObjectName):
45 """
45 """
46 A string holding a valid dotted object name in Python, such as A.b3._c
46 A string holding a valid dotted object name in Python, such as A.b3._c
47 Also allows for None type."""
47 Also allows for None type."""
48
48
49 default_value = u''
49 default_value = u''
50
50
51 def validate(self, obj, value):
51 def validate(self, obj, value):
52 if value is not None and len(value) > 0:
52 if value is not None and len(value) > 0:
53 return super(DottedOrNone, self).validate(obj, value)
53 return super(DottedOrNone, self).validate(obj, value)
54 else:
54 else:
55 return value
55 return value
56
56
57 nbconvert_aliases = {}
57 nbconvert_aliases = {}
58 nbconvert_aliases.update(base_aliases)
58 nbconvert_aliases.update(base_aliases)
59 nbconvert_aliases.update({
59 nbconvert_aliases.update({
60 'to' : 'NbConvertApp.export_format',
60 'to' : 'NbConvertApp.export_format',
61 'template' : 'Exporter.template_file',
61 'template' : 'Exporter.template_file',
62 'writer' : 'NbConvertApp.writer_class',
62 'writer' : 'NbConvertApp.writer_class',
63 'post': 'NbConvertApp.post_processor_class',
63 'post': 'NbConvertApp.post_processor_class',
64 'output': 'NbConvertApp.output_base'
64 'output': 'NbConvertApp.output_base',
65 'offline-slides': 'RevealHelpTransformer.url_prefix',
66 'slide-notes': 'RevealHelpTransformer.speaker_notes'
65 })
67 })
66
68
67 nbconvert_flags = {}
69 nbconvert_flags = {}
68 nbconvert_flags.update(base_flags)
70 nbconvert_flags.update(base_flags)
69 nbconvert_flags.update({
71 nbconvert_flags.update({
70 'stdout' : (
72 'stdout' : (
71 {'NbConvertApp' : {'writer_class' : "StdoutWriter"}},
73 {'NbConvertApp' : {'writer_class' : "StdoutWriter"}},
72 "Write notebook output to stdout instead of files."
74 "Write notebook output to stdout instead of files."
73 )
75 )
74 })
76 })
75
77
76
78
77 class NbConvertApp(BaseIPythonApplication):
79 class NbConvertApp(BaseIPythonApplication):
78 """Application used to convert to and from notebook file type (*.ipynb)"""
80 """Application used to convert to and from notebook file type (*.ipynb)"""
79
81
80 name = 'ipython-nbconvert'
82 name = 'ipython-nbconvert'
81 aliases = nbconvert_aliases
83 aliases = nbconvert_aliases
82 flags = nbconvert_flags
84 flags = nbconvert_flags
83
85
84 def _log_level_default(self):
86 def _log_level_default(self):
85 return logging.INFO
87 return logging.INFO
86
88
87 def _classes_default(self):
89 def _classes_default(self):
88 classes = [NbConvertBase]
90 classes = [NbConvertBase]
89 for pkg in (exporters, transformers, writers):
91 for pkg in (exporters, transformers, writers):
90 for name in dir(pkg):
92 for name in dir(pkg):
91 cls = getattr(pkg, name)
93 cls = getattr(pkg, name)
92 if isinstance(cls, type) and issubclass(cls, Configurable):
94 if isinstance(cls, type) and issubclass(cls, Configurable):
93 classes.append(cls)
95 classes.append(cls)
94 return classes
96 return classes
95
97
96 description = Unicode(
98 description = Unicode(
97 u"""This application is used to convert notebook files (*.ipynb)
99 u"""This application is used to convert notebook files (*.ipynb)
98 to various other formats.
100 to various other formats.
99
101
100 WARNING: THE COMMANDLINE INTERFACE MAY CHANGE IN FUTURE RELEASES.""")
102 WARNING: THE COMMANDLINE INTERFACE MAY CHANGE IN FUTURE RELEASES.""")
101
103
102 output_base = Unicode('', config=True, help='''overwrite base name use for output files.
104 output_base = Unicode('', config=True, help='''overwrite base name use for output files.
103 can only be use when converting one notebook at a time.
105 can only be use when converting one notebook at a time.
104 ''')
106 ''')
105
107
106 examples = Unicode(u"""
108 examples = Unicode(u"""
107 The simplest way to use nbconvert is
109 The simplest way to use nbconvert is
108
110
109 > ipython nbconvert mynotebook.ipynb
111 > ipython nbconvert mynotebook.ipynb
110
112
111 which will convert mynotebook.ipynb to the default format (probably HTML).
113 which will convert mynotebook.ipynb to the default format (probably HTML).
112
114
113 You can specify the export format with `--to`.
115 You can specify the export format with `--to`.
114 Options include {0}
116 Options include {0}
115
117
116 > ipython nbconvert --to latex mynotebook.ipnynb
118 > ipython nbconvert --to latex mynotebook.ipnynb
117
119
118 Both HTML and LaTeX support multiple output templates. LaTeX includes
120 Both HTML and LaTeX support multiple output templates. LaTeX includes
119 'basic', 'book', and 'article'. HTML includes 'basic' and 'full'. You
121 'basic', 'book', and 'article'. HTML includes 'basic' and 'full'. You
120 can specify the flavor of the format used.
122 can specify the flavor of the format used.
121
123
122 > ipython nbconvert --to html --template basic mynotebook.ipynb
124 > ipython nbconvert --to html --template basic mynotebook.ipynb
123
125
124 You can also pipe the output to stdout, rather than a file
126 You can also pipe the output to stdout, rather than a file
125
127
126 > ipython nbconvert mynotebook.ipynb --stdout
128 > ipython nbconvert mynotebook.ipynb --stdout
127
129
128 A post-processor can be used to compile a PDF
130 A post-processor can be used to compile a PDF
129
131
130 > ipython nbconvert mynotebook.ipynb --to latex --post PDF
132 > ipython nbconvert mynotebook.ipynb --to latex --post PDF
131
133
132 You can get (and serve) a Reveal.js-powered slideshow
134 You can get (and serve) a Reveal.js-powered slideshow
133
135
134 > ipython nbconvert myslides.ipynb --to slides --post serve
136 > ipython nbconvert myslides.ipynb --to slides --post serve
135
137
136 Multiple notebooks can be given at the command line in a couple of
138 Multiple notebooks can be given at the command line in a couple of
137 different ways:
139 different ways:
138
140
139 > ipython nbconvert notebook*.ipynb
141 > ipython nbconvert notebook*.ipynb
140 > ipython nbconvert notebook1.ipynb notebook2.ipynb
142 > ipython nbconvert notebook1.ipynb notebook2.ipynb
141
143
142 or you can specify the notebooks list in a config file, containing::
144 or you can specify the notebooks list in a config file, containing::
143
145
144 c.NbConvertApp.notebooks = ["my_notebook.ipynb"]
146 c.NbConvertApp.notebooks = ["my_notebook.ipynb"]
145
147
146 > ipython nbconvert --config mycfg.py
148 > ipython nbconvert --config mycfg.py
147 """.format(get_export_names()))
149 """.format(get_export_names()))
148
150
149 # Writer specific variables
151 # Writer specific variables
150 writer = Instance('IPython.nbconvert.writers.base.WriterBase',
152 writer = Instance('IPython.nbconvert.writers.base.WriterBase',
151 help="""Instance of the writer class used to write the
153 help="""Instance of the writer class used to write the
152 results of the conversion.""")
154 results of the conversion.""")
153 writer_class = DottedObjectName('FilesWriter', config=True,
155 writer_class = DottedObjectName('FilesWriter', config=True,
154 help="""Writer class used to write the
156 help="""Writer class used to write the
155 results of the conversion""")
157 results of the conversion""")
156 writer_aliases = {'fileswriter': 'IPython.nbconvert.writers.files.FilesWriter',
158 writer_aliases = {'fileswriter': 'IPython.nbconvert.writers.files.FilesWriter',
157 'debugwriter': 'IPython.nbconvert.writers.debug.DebugWriter',
159 'debugwriter': 'IPython.nbconvert.writers.debug.DebugWriter',
158 'stdoutwriter': 'IPython.nbconvert.writers.stdout.StdoutWriter'}
160 'stdoutwriter': 'IPython.nbconvert.writers.stdout.StdoutWriter'}
159 writer_factory = Type()
161 writer_factory = Type()
160
162
161 def _writer_class_changed(self, name, old, new):
163 def _writer_class_changed(self, name, old, new):
162 if new.lower() in self.writer_aliases:
164 if new.lower() in self.writer_aliases:
163 new = self.writer_aliases[new.lower()]
165 new = self.writer_aliases[new.lower()]
164 self.writer_factory = import_item(new)
166 self.writer_factory = import_item(new)
165
167
166 # Post-processor specific variables
168 # Post-processor specific variables
167 post_processor = Instance('IPython.nbconvert.post_processors.base.PostProcessorBase',
169 post_processor = Instance('IPython.nbconvert.post_processors.base.PostProcessorBase',
168 help="""Instance of the PostProcessor class used to write the
170 help="""Instance of the PostProcessor class used to write the
169 results of the conversion.""")
171 results of the conversion.""")
170
172
171 post_processor_class = DottedOrNone(config=True,
173 post_processor_class = DottedOrNone(config=True,
172 help="""PostProcessor class used to write the
174 help="""PostProcessor class used to write the
173 results of the conversion""")
175 results of the conversion""")
174 post_processor_aliases = {'pdf': 'IPython.nbconvert.post_processors.pdf.PDFPostProcessor',
176 post_processor_aliases = {'pdf': 'IPython.nbconvert.post_processors.pdf.PDFPostProcessor',
175 'serve': 'IPython.nbconvert.post_processors.serve.ServePostProcessor'}
177 'serve': 'IPython.nbconvert.post_processors.serve.ServePostProcessor'}
176 post_processor_factory = Type()
178 post_processor_factory = Type()
177
179
178 def _post_processor_class_changed(self, name, old, new):
180 def _post_processor_class_changed(self, name, old, new):
179 if new.lower() in self.post_processor_aliases:
181 if new.lower() in self.post_processor_aliases:
180 new = self.post_processor_aliases[new.lower()]
182 new = self.post_processor_aliases[new.lower()]
181 if new:
183 if new:
182 self.post_processor_factory = import_item(new)
184 self.post_processor_factory = import_item(new)
183
185
184
186
185 # Other configurable variables
187 # Other configurable variables
186 export_format = CaselessStrEnum(get_export_names(),
188 export_format = CaselessStrEnum(get_export_names(),
187 default_value="html",
189 default_value="html",
188 config=True,
190 config=True,
189 help="""The export format to be used."""
191 help="""The export format to be used."""
190 )
192 )
191
193
192 notebooks = List([], config=True, help="""List of notebooks to convert.
194 notebooks = List([], config=True, help="""List of notebooks to convert.
193 Wildcards are supported.
195 Wildcards are supported.
194 Filenames passed positionally will be added to the list.
196 Filenames passed positionally will be added to the list.
195 """)
197 """)
196
198
197 @catch_config_error
199 @catch_config_error
198 def initialize(self, argv=None):
200 def initialize(self, argv=None):
199 super(NbConvertApp, self).initialize(argv)
201 super(NbConvertApp, self).initialize(argv)
200 self.init_syspath()
202 self.init_syspath()
201 self.init_notebooks()
203 self.init_notebooks()
202 self.init_writer()
204 self.init_writer()
203 self.init_post_processor()
205 self.init_post_processor()
204
206
205
207
206
208
207 def init_syspath(self):
209 def init_syspath(self):
208 """
210 """
209 Add the cwd to the sys.path ($PYTHONPATH)
211 Add the cwd to the sys.path ($PYTHONPATH)
210 """
212 """
211 sys.path.insert(0, os.getcwd())
213 sys.path.insert(0, os.getcwd())
212
214
213
215
214 def init_notebooks(self):
216 def init_notebooks(self):
215 """Construct the list of notebooks.
217 """Construct the list of notebooks.
216 If notebooks are passed on the command-line,
218 If notebooks are passed on the command-line,
217 they override notebooks specified in config files.
219 they override notebooks specified in config files.
218 Glob each notebook to replace notebook patterns with filenames.
220 Glob each notebook to replace notebook patterns with filenames.
219 """
221 """
220
222
221 # Specifying notebooks on the command-line overrides (rather than adds)
223 # Specifying notebooks on the command-line overrides (rather than adds)
222 # the notebook list
224 # the notebook list
223 if self.extra_args:
225 if self.extra_args:
224 patterns = self.extra_args
226 patterns = self.extra_args
225 else:
227 else:
226 patterns = self.notebooks
228 patterns = self.notebooks
227
229
228 # Use glob to replace all the notebook patterns with filenames.
230 # Use glob to replace all the notebook patterns with filenames.
229 filenames = []
231 filenames = []
230 for pattern in patterns:
232 for pattern in patterns:
231
233
232 # Use glob to find matching filenames. Allow the user to convert
234 # Use glob to find matching filenames. Allow the user to convert
233 # notebooks without having to type the extension.
235 # notebooks without having to type the extension.
234 globbed_files = glob.glob(pattern)
236 globbed_files = glob.glob(pattern)
235 globbed_files.extend(glob.glob(pattern + '.ipynb'))
237 globbed_files.extend(glob.glob(pattern + '.ipynb'))
236 if not globbed_files:
238 if not globbed_files:
237 self.log.warn("pattern %r matched no files", pattern)
239 self.log.warn("pattern %r matched no files", pattern)
238
240
239 for filename in globbed_files:
241 for filename in globbed_files:
240 if not filename in filenames:
242 if not filename in filenames:
241 filenames.append(filename)
243 filenames.append(filename)
242 self.notebooks = filenames
244 self.notebooks = filenames
243
245
244 def init_writer(self):
246 def init_writer(self):
245 """
247 """
246 Initialize the writer (which is stateless)
248 Initialize the writer (which is stateless)
247 """
249 """
248 self._writer_class_changed(None, self.writer_class, self.writer_class)
250 self._writer_class_changed(None, self.writer_class, self.writer_class)
249 self.writer = self.writer_factory(parent=self)
251 self.writer = self.writer_factory(parent=self)
250
252
251 def init_post_processor(self):
253 def init_post_processor(self):
252 """
254 """
253 Initialize the post_processor (which is stateless)
255 Initialize the post_processor (which is stateless)
254 """
256 """
255 self._post_processor_class_changed(None, self.post_processor_class,
257 self._post_processor_class_changed(None, self.post_processor_class,
256 self.post_processor_class)
258 self.post_processor_class)
257 if self.post_processor_factory:
259 if self.post_processor_factory:
258 self.post_processor = self.post_processor_factory(parent=self)
260 self.post_processor = self.post_processor_factory(parent=self)
259
261
260 def start(self):
262 def start(self):
261 """
263 """
262 Ran after initialization completed
264 Ran after initialization completed
263 """
265 """
264 super(NbConvertApp, self).start()
266 super(NbConvertApp, self).start()
265 self.convert_notebooks()
267 self.convert_notebooks()
266
268
267 def convert_notebooks(self):
269 def convert_notebooks(self):
268 """
270 """
269 Convert the notebooks in the self.notebook traitlet
271 Convert the notebooks in the self.notebook traitlet
270 """
272 """
271 # Export each notebook
273 # Export each notebook
272 conversion_success = 0
274 conversion_success = 0
273
275
274 if self.output_base != '' and len(self.notebooks) > 1:
276 if self.output_base != '' and len(self.notebooks) > 1:
275 self.log.error(
277 self.log.error(
276 """UsageError: --output flag or `NbConvertApp.output_base` config option
278 """UsageError: --output flag or `NbConvertApp.output_base` config option
277 cannot be used when converting multiple notebooks.
279 cannot be used when converting multiple notebooks.
278 """)
280 """)
279 self.exit(1)
281 self.exit(1)
280
282
281 exporter = exporter_map[self.export_format](config=self.config)
283 exporter = exporter_map[self.export_format](config=self.config)
282
284
283 for notebook_filename in self.notebooks:
285 for notebook_filename in self.notebooks:
284 self.log.info("Converting notebook %s to %s", notebook_filename, self.export_format)
286 self.log.info("Converting notebook %s to %s", notebook_filename, self.export_format)
285
287
286 # Get a unique key for the notebook and set it in the resources object.
288 # Get a unique key for the notebook and set it in the resources object.
287 basename = os.path.basename(notebook_filename)
289 basename = os.path.basename(notebook_filename)
288 notebook_name = basename[:basename.rfind('.')]
290 notebook_name = basename[:basename.rfind('.')]
289 if self.output_base:
291 if self.output_base:
290 notebook_name = self.output_base
292 notebook_name = self.output_base
291 resources = {}
293 resources = {}
292 resources['unique_key'] = notebook_name
294 resources['unique_key'] = notebook_name
293 resources['output_files_dir'] = '%s_files' % notebook_name
295 resources['output_files_dir'] = '%s_files' % notebook_name
294 self.log.info("Support files will be in %s", os.path.join(resources['output_files_dir'], ''))
296 self.log.info("Support files will be in %s", os.path.join(resources['output_files_dir'], ''))
295
297
296 # Try to export
298 # Try to export
297 try:
299 try:
298 output, resources = exporter.from_filename(notebook_filename, resources=resources)
300 output, resources = exporter.from_filename(notebook_filename, resources=resources)
299 except ConversionException as e:
301 except ConversionException as e:
300 self.log.error("Error while converting '%s'", notebook_filename,
302 self.log.error("Error while converting '%s'", notebook_filename,
301 exc_info=True)
303 exc_info=True)
302 self.exit(1)
304 self.exit(1)
303 else:
305 else:
304 write_resultes = self.writer.write(output, resources, notebook_name=notebook_name)
306 write_resultes = self.writer.write(output, resources, notebook_name=notebook_name)
305
307
306 #Post-process if post processor has been defined.
308 #Post-process if post processor has been defined.
307 if hasattr(self, 'post_processor') and self.post_processor:
309 if hasattr(self, 'post_processor') and self.post_processor:
308 self.post_processor(write_resultes)
310 self.post_processor(write_resultes)
309 conversion_success += 1
311 conversion_success += 1
310
312
311 # If nothing was converted successfully, help the user.
313 # If nothing was converted successfully, help the user.
312 if conversion_success == 0:
314 if conversion_success == 0:
313 self.print_help()
315 self.print_help()
314 sys.exit(-1)
316 sys.exit(-1)
315
317
316 #-----------------------------------------------------------------------------
318 #-----------------------------------------------------------------------------
317 # Main entry point
319 # Main entry point
318 #-----------------------------------------------------------------------------
320 #-----------------------------------------------------------------------------
319
321
320 launch_new_instance = NbConvertApp.launch_instance
322 launch_new_instance = NbConvertApp.launch_instance
@@ -1,185 +1,185 b''
1 {%- extends 'reveal_internals/slides.tpl' -%}
1 {%- extends 'reveal_internals/slides.tpl' -%}
2
2
3
3
4 {% block header %}
4 {% block header %}
5 <!DOCTYPE html>
5 <!DOCTYPE html>
6 <html>
6 <html>
7 <head>
7 <head>
8
8
9 <meta charset="utf-8" />
9 <meta charset="utf-8" />
10 <meta http-equiv="X-UA-Compatible" content="chrome=1">
10 <meta http-equiv="X-UA-Compatible" content="chrome=1">
11
11
12 <meta name="apple-mobile-web-app-capable" content="yes" />
12 <meta name="apple-mobile-web-app-capable" content="yes" />
13 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
13 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
14
14
15 <!-- General and theme style sheets -->
15 <!-- General and theme style sheets -->
16 <link rel="stylesheet" href="{{resources.reveal.url_prefix}}/css/reveal.css">
16 <link rel="stylesheet" href="{{resources.reveal.url_prefix}}/css/reveal.css">
17 <link rel="stylesheet" href="{{resources.reveal.url_prefix}}/css/theme/simple.css" id="theme">
17 <link rel="stylesheet" href="{{resources.reveal.url_prefix}}/css/theme/simple.css" id="theme">
18
18
19 <!-- For syntax highlighting -->
19 <!-- For syntax highlighting -->
20 <link rel="stylesheet" href="{{resources.reveal.url_prefix}}/lib/css/zenburn.css">
20 <link rel="stylesheet" href="{{resources.reveal.url_prefix}}/lib/css/zenburn.css">
21
21
22 <!-- If the query includes 'print-pdf', use the PDF print sheet -->
22 <!-- If the query includes 'print-pdf', use the PDF print sheet -->
23 <script>
23 <script>
24 document.write( '<link rel="stylesheet" href="{{resources.reveal.url_prefix}}/css/print/' + ( window.location.search.match( /print-pdf/gi ) ? 'pdf' : 'paper' ) + '.css" type="text/css" media="print">' );
24 document.write( '<link rel="stylesheet" href="{{resources.reveal.url_prefix}}/css/print/' + ( window.location.search.match( /print-pdf/gi ) ? 'pdf' : 'paper' ) + '.css" type="text/css" media="print">' );
25 </script>
25 </script>
26
26
27 <!--[if lt IE 9]>
27 <!--[if lt IE 9]>
28 <script src="{{resources.reveal.url_prefix}}/lib/js/html5shiv.js"></script>
28 <script src="{{resources.reveal.url_prefix}}/lib/js/html5shiv.js"></script>
29 <![endif]-->
29 <![endif]-->
30
30
31 {% for css in resources.inlining.css -%}
31 {% for css in resources.inlining.css -%}
32 <style type="text/css">
32 <style type="text/css">
33 {{ css }}
33 {{ css }}
34 </style>
34 </style>
35 {% endfor %}
35 {% endfor %}
36
36
37 <style type="text/css">
37 <style type="text/css">
38 /* Overrides of notebook CSS for static HTML export */
38 /* Overrides of notebook CSS for static HTML export */
39 .reveal {
39 .reveal {
40 font-size: 20px;
40 font-size: 20px;
41 overflow-y: auto;
41 overflow-y: auto;
42 overflow-x: hidden;
42 overflow-x: hidden;
43 }
43 }
44 .reveal pre {
44 .reveal pre {
45 width: 95%;
45 width: 95%;
46 padding: 0.4em;
46 padding: 0.4em;
47 margin: 0px;
47 margin: 0px;
48 font-family: monospace, sans-serif;
48 font-family: monospace, sans-serif;
49 font-size: 80%;
49 font-size: 80%;
50 box-shadow: 0px 0px 0px rgba(0, 0, 0, 0);
50 box-shadow: 0px 0px 0px rgba(0, 0, 0, 0);
51 }
51 }
52 .reveal section img {
52 .reveal section img {
53 border: 0px solid black;
53 border: 0px solid black;
54 box-shadow: 0 0 10px rgba(0, 0, 0, 0);
54 box-shadow: 0 0 10px rgba(0, 0, 0, 0);
55 }
55 }
56 .reveal .slides {
56 .reveal .slides {
57 text-align: left;
57 text-align: left;
58 }
58 }
59 .reveal.fade {
59 .reveal.fade {
60 opacity: 1;
60 opacity: 1;
61 }
61 }
62 div.input_area {
62 div.input_area {
63 padding: 0.06em;
63 padding: 0.06em;
64 }
64 }
65 div.code_cell {
65 div.code_cell {
66 background-color: transparent;
66 background-color: transparent;
67 }
67 }
68 div.prompt {
68 div.prompt {
69 width: 11ex;
69 width: 11ex;
70 padding: 0.4em;
70 padding: 0.4em;
71 margin: 0px;
71 margin: 0px;
72 font-family: monospace, sans-serif;
72 font-family: monospace, sans-serif;
73 font-size: 80%;
73 font-size: 80%;
74 text-align: right;
74 text-align: right;
75 }
75 }
76 div.output_area pre {
76 div.output_area pre {
77 font-family: monospace, sans-serif;
77 font-family: monospace, sans-serif;
78 font-size: 80%;
78 font-size: 80%;
79 }
79 }
80 div.output_prompt {
80 div.output_prompt {
81 /* 5px right shift to account for margin in parent container */
81 /* 5px right shift to account for margin in parent container */
82 margin: 5px 5px 0 0;
82 margin: 5px 5px 0 0;
83 }
83 }
84 .rendered_html p {
84 .rendered_html p {
85 text-align: inherit;
85 text-align: inherit;
86 }
86 }
87 </style>
87 </style>
88
88
89 <!-- Custom stylesheet, it must be in the same directory as the html file -->
89 <!-- Custom stylesheet, it must be in the same directory as the html file -->
90 <link rel="stylesheet" href="custom.css">
90 <link rel="stylesheet" href="custom.css">
91
91
92 </head>
92 </head>
93 {% endblock header%}
93 {% endblock header%}
94
94
95
95
96 {% block body %}
96 {% block body %}
97 <body>
97 <body>
98 <div class="reveal">
98 <div class="reveal">
99 <div class="slides">
99 <div class="slides">
100 {{ super() }}
100 {{ super() }}
101 </div>
101 </div>
102 </div>
102 </div>
103
103
104 <!--
104 <!--
105 Uncomment the following block and the addthis_widget.js (see below inside dependencies)
105 Uncomment the following block and the addthis_widget.js (see below inside dependencies)
106 to get enable social buttons.
106 to get enable social buttons.
107 -->
107 -->
108
108
109 <!--
109 <!--
110 <div class="addthis_toolbox addthis_floating_style addthis_32x32_style" style="left:20px;top:20px;">
110 <div class="addthis_toolbox addthis_floating_style addthis_32x32_style" style="left:20px;top:20px;">
111 <a class="addthis_button_twitter"></a>
111 <a class="addthis_button_twitter"></a>
112 <a class="addthis_button_google_plusone_share"></a>
112 <a class="addthis_button_google_plusone_share"></a>
113 <a class="addthis_button_linkedin"></a>
113 <a class="addthis_button_linkedin"></a>
114 <a class="addthis_button_facebook"></a>
114 <a class="addthis_button_facebook"></a>
115 <a class="addthis_button_more"></a>
115 <a class="addthis_button_more"></a>
116 </div>
116 </div>
117 -->
117 -->
118
118
119 <script src="{{resources.reveal.url_prefix}}/lib/js/head.min.js"></script>
119 <script src="{{resources.reveal.url_prefix}}/lib/js/head.min.js"></script>
120
120
121 <script src="{{resources.reveal.url_prefix}}/js/reveal.js"></script>
121 <script src="{{resources.reveal.url_prefix}}/js/reveal.js"></script>
122
122
123 <script>
123 <script>
124
124
125 // Full list of configuration options available here: https://github.com/hakimel/reveal.js#configuration
125 // Full list of configuration options available here: https://github.com/hakimel/reveal.js#configuration
126 Reveal.initialize({
126 Reveal.initialize({
127 controls: true,
127 controls: true,
128 progress: true,
128 progress: true,
129 history: true,
129 history: true,
130
130
131 theme: Reveal.getQueryHash().theme, // available themes are in /css/theme
131 theme: Reveal.getQueryHash().theme, // available themes are in /css/theme
132 transition: Reveal.getQueryHash().transition || 'linear', // default/cube/page/concave/zoom/linear/none
132 transition: Reveal.getQueryHash().transition || 'linear', // default/cube/page/concave/zoom/linear/none
133
133
134 // Optional libraries used to extend on reveal.js
134 // Optional libraries used to extend on reveal.js
135 dependencies: [
135 dependencies: [
136 { src: "{{resources.reveal.url_prefix}}/lib/js/classList.js", condition: function() { return !document.body.classList; } },
136 { src: "{{resources.reveal.url_prefix}}/lib/js/classList.js", condition: function() { return !document.body.classList; } },
137 { src: "{{resources.reveal.url_prefix}}/plugin/highlight/highlight.js", async: true, callback: function() { hljs.initHighlightingOnLoad(); } },
137 { src: "{{resources.reveal.url_prefix}}/plugin/highlight/highlight.js", async: true, callback: function() { hljs.initHighlightingOnLoad(); } },
138 { src: "{{resources.reveal.url_prefix}}/plugin/notes/notes.js", async: true, condition: function() { return !!document.body.classList; } }
138 { src: "{{resources.reveal.notes_prefix}}/plugin/notes/notes.js", async: true, condition: function() { return !!document.body.classList; } }
139 // { src: 'http://s7.addthis.com/js/300/addthis_widget.js', async: true},
139 // { src: 'http://s7.addthis.com/js/300/addthis_widget.js', async: true},
140 ]
140 ]
141 });
141 });
142 </script>
142 </script>
143
143
144 <!-- MathJax configuration -->
144 <!-- MathJax configuration -->
145 <script type="text/x-mathjax-config">
145 <script type="text/x-mathjax-config">
146 MathJax.Hub.Config({
146 MathJax.Hub.Config({
147 tex2jax: {
147 tex2jax: {
148 inlineMath: [ ['$','$'], ["\\(","\\)"] ],
148 inlineMath: [ ['$','$'], ["\\(","\\)"] ],
149 displayMath: [ ['$$','$$'], ["\\[","\\]"] ]
149 displayMath: [ ['$$','$$'], ["\\[","\\]"] ]
150 },
150 },
151 displayAlign: 'left', // Change this to 'center' to center equations.
151 displayAlign: 'left', // Change this to 'center' to center equations.
152 "HTML-CSS": {
152 "HTML-CSS": {
153 styles: {'.MathJax_Display': {"margin": 0}}
153 styles: {'.MathJax_Display': {"margin": 0}}
154 }
154 }
155 });
155 });
156 </script>
156 </script>
157 <!-- End of mathjax configuration -->
157 <!-- End of mathjax configuration -->
158
158
159 <script>
159 <script>
160 // We wait for the onload function to load MathJax after the page is completely loaded.
160 // We wait for the onload function to load MathJax after the page is completely loaded.
161 // MathJax is loaded 1 unit of time after the page is ready.
161 // MathJax is loaded 1 unit of time after the page is ready.
162 // This hack prevent problems when you load multiple js files (i.e. social button from addthis).
162 // This hack prevent problems when you load multiple js files (i.e. social button from addthis).
163 //
163 //
164 window.onload = function () {
164 window.onload = function () {
165 setTimeout(function () {
165 setTimeout(function () {
166 var script = document.createElement("script");
166 var script = document.createElement("script");
167 script.type = "text/javascript";
167 script.type = "text/javascript";
168 script.src = "https://c328740.ssl.cf1.rackcdn.com/mathjax/latest/MathJax.js?config=TeX-AMS_HTML";
168 script.src = "https://c328740.ssl.cf1.rackcdn.com/mathjax/latest/MathJax.js?config=TeX-AMS_HTML";
169 document.getElementsByTagName("head")[0].appendChild(script);
169 document.getElementsByTagName("head")[0].appendChild(script);
170 },1)
170 },1)
171 }
171 }
172 </script>
172 </script>
173
173
174 <script>
174 <script>
175 Reveal.addEventListener( 'slidechanged', function( event ) {
175 Reveal.addEventListener( 'slidechanged', function( event ) {
176 MathJax.Hub.Rerender(event.currentSlide);
176 MathJax.Hub.Rerender(event.currentSlide);
177 });
177 });
178 </script>
178 </script>
179
179
180 </body>
180 </body>
181 {% endblock body %}
181 {% endblock body %}
182
182
183 {% block footer %}
183 {% block footer %}
184 </html>
184 </html>
185 {% endblock footer %} No newline at end of file
185 {% endblock footer %}
@@ -1,61 +1,94 b''
1 """Module that pre-processes the notebook for export via Reveal.
1 """Module that pre-processes the notebook for export via Reveal.
2 """
2 """
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2013, the IPython Development Team.
4 # Copyright (c) 2013, the IPython Development Team.
5 #
5 #
6 # Distributed under the terms of the Modified BSD License.
6 # Distributed under the terms of the Modified BSD License.
7 #
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 import os
16 import urllib2
17
15 from .base import Transformer
18 from .base import Transformer
16 from IPython.utils.traitlets import Unicode
19 from IPython.utils.traitlets import Unicode, Bool
17
20
18 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
19 # Classes and functions
22 # Classes and functions
20 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
21
24
22 class RevealHelpTransformer(Transformer):
25 class RevealHelpTransformer(Transformer):
23
26
24 url_prefix = Unicode('//cdn.jsdelivr.net/reveal.js/2.4.0',
27 url_prefix = Unicode('//cdn.jsdelivr.net/reveal.js/2.4.0',
25 config=True,
28 config=True,
26 help="""If you want to use a local reveal.js library,
29 help="""If you want to use a local reveal.js library,
27 use 'url_prefix':'reveal.js' in your config object.""")
30 use 'url_prefix':'reveal.js' in your config object.""")
28
31
32 speaker_notes = Bool(False,
33 config=True,
34 help="""If you want to use the speaker notes
35 set this to True.""")
36
29 def call(self, nb, resources):
37 def call(self, nb, resources):
30 """
38 """
31 Called once to 'transform' contents of the notebook.
39 Called once to 'transform' contents of the notebook.
32
40
33 Parameters
41 Parameters
34 ----------
42 ----------
35 nb : NotebookNode
43 nb : NotebookNode
36 Notebook being converted
44 Notebook being converted
37 resources : dictionary
45 resources : dictionary
38 Additional resources used in the conversion process. Allows
46 Additional resources used in the conversion process. Allows
39 transformers to pass variables into the Jinja engine.
47 transformers to pass variables into the Jinja engine.
40 """
48 """
41
49
42 for worksheet in nb.worksheets :
50 for worksheet in nb.worksheets :
43 for index, cell in enumerate(worksheet.cells):
51 for index, cell in enumerate(worksheet.cells):
44
52
45 #Make sure the cell has slideshow metadata.
53 #Make sure the cell has slideshow metadata.
46 cell.metadata.align_type = cell.get('metadata', {}).get('slideshow', {}).get('align_type', 'Left')
54 cell.metadata.align_type = cell.get('metadata', {}).get('slideshow', {}).get('align_type', 'Left')
47 cell.metadata.slide_type = cell.get('metadata', {}).get('slideshow', {}).get('slide_type', '-')
55 cell.metadata.slide_type = cell.get('metadata', {}).get('slideshow', {}).get('slide_type', '-')
48
56
49 #Get the slide type. If type is start of subslide or slide,
57 #Get the slide type. If type is start of subslide or slide,
50 #end the last subslide/slide.
58 #end the last subslide/slide.
51 if cell.metadata.slide_type in ['slide']:
59 if cell.metadata.slide_type in ['slide']:
52 worksheet.cells[index - 1].metadata.slide_helper = 'slide_end'
60 worksheet.cells[index - 1].metadata.slide_helper = 'slide_end'
53 if cell.metadata.slide_type in ['subslide']:
61 if cell.metadata.slide_type in ['subslide']:
54 worksheet.cells[index - 1].metadata.slide_helper = 'subslide_end'
62 worksheet.cells[index - 1].metadata.slide_helper = 'subslide_end'
55
63
56
64
57 if not isinstance(resources['reveal'], dict):
65 if not isinstance(resources['reveal'], dict):
58 resources['reveal'] = {}
66 resources['reveal'] = {}
59 resources['reveal']['url_prefix'] = self.url_prefix
67 resources['reveal']['url_prefix'] = self.url_prefix
68 resources['reveal']['notes_prefix'] = self.url_prefix
69
70 cdn = 'http://cdn.jsdelivr.net/reveal.js/2.4.0'
71 local = 'local'
72 html_path = 'plugin/notes/notes.html'
73 js_path = 'plugin/notes/notes.js'
74
75 html_infile = os.path.join(cdn, html_path)
76 js_infile = os.path.join(cdn, js_path)
77 html_outfile = os.path.join(local, html_path)
78 js_outfile = os.path.join(local, js_path)
79
80 if self.speaker_notes:
81 if 'outputs' not in resources:
82 resources['outputs'] = {}
83 resources['outputs'][html_outfile] = self.notes_helper(html_infile)
84 resources['outputs'][js_outfile] = self.notes_helper(js_infile)
85 resources['reveal']['notes_prefix'] = local
60
86
61 return nb, resources
87 return nb, resources
88
89 def notes_helper(self, infile):
90 """Helper function to get the content from an url."""
91
92 content = urllib2.urlopen(infile).read()
93
94 return content
@@ -1,212 +1,217 b''
1 .. _nbconvert:
1 .. _nbconvert:
2
2
3 Converting notebooks to other formats
3 Converting notebooks to other formats
4 =====================================
4 =====================================
5
5
6 Newly added in the 1.0 release of IPython is the ``nbconvert`` tool, which
6 Newly added in the 1.0 release of IPython is the ``nbconvert`` tool, which
7 allows you to convert an ``.ipynb`` notebook document file into various static
7 allows you to convert an ``.ipynb`` notebook document file into various static
8 formats.
8 formats.
9
9
10 Currently, ``nbconvert`` is provided as a command line tool, run as a script
10 Currently, ``nbconvert`` is provided as a command line tool, run as a script
11 using IPython. A direct export capability from within the
11 using IPython. A direct export capability from within the
12 IPython Notebook web app is planned.
12 IPython Notebook web app is planned.
13
13
14 The command-line syntax to run the ``nbconvert`` script is::
14 The command-line syntax to run the ``nbconvert`` script is::
15
15
16 $ ipython nbconvert --to FORMAT notebook.ipynb
16 $ ipython nbconvert --to FORMAT notebook.ipynb
17
17
18 This will convert the IPython document file ``notebook.ipynb`` into the output
18 This will convert the IPython document file ``notebook.ipynb`` into the output
19 format given by the ``FORMAT`` string.
19 format given by the ``FORMAT`` string.
20
20
21 The default output format is html, for which the ``--to`` argument may be
21 The default output format is html, for which the ``--to`` argument may be
22 omitted::
22 omitted::
23
23
24 $ ipython nbconvert notebook.ipynb
24 $ ipython nbconvert notebook.ipynb
25
25
26 IPython provides a few templates for some output formats, and these can be
26 IPython provides a few templates for some output formats, and these can be
27 specified via an additional ``--template`` argument.
27 specified via an additional ``--template`` argument.
28
28
29 The currently supported export formats are:
29 The currently supported export formats are:
30
30
31 * ``--to html``
31 * ``--to html``
32
32
33 - ``--template full`` (default)
33 - ``--template full`` (default)
34
34
35 A full static HTML render of the notebook.
35 A full static HTML render of the notebook.
36 This looks very similar to the interactive view.
36 This looks very similar to the interactive view.
37
37
38 - ``--template basic``
38 - ``--template basic``
39
39
40 Simplified HTML, useful for embedding in webpages, blogs, etc.
40 Simplified HTML, useful for embedding in webpages, blogs, etc.
41 This excludes HTML headers.
41 This excludes HTML headers.
42
42
43 * ``--to latex``
43 * ``--to latex``
44
44
45 Latex export. This generates ``NOTEBOOK_NAME.tex`` file,
45 Latex export. This generates ``NOTEBOOK_NAME.tex`` file,
46 ready for export. You can automatically run latex on it to generate a PDF
46 ready for export. You can automatically run latex on it to generate a PDF
47 by adding ``--post PDF``.
47 by adding ``--post PDF``.
48
48
49 - ``--template article`` (default)
49 - ``--template article`` (default)
50
50
51 Latex article, derived from Sphinx's howto template.
51 Latex article, derived from Sphinx's howto template.
52
52
53 - ``--template book``
53 - ``--template book``
54
54
55 Latex book, derived from Sphinx's manual template.
55 Latex book, derived from Sphinx's manual template.
56
56
57 - ``--template basic``
57 - ``--template basic``
58
58
59 Very basic latex output - mainly meant as a starting point for custom templates.
59 Very basic latex output - mainly meant as a starting point for custom templates.
60
60
61 * ``--to slides``
61 * ``--to slides``
62
62
63 This generates a Reveal.js HTML slideshow.
63 This generates a Reveal.js HTML slideshow.
64 It must be served by an HTTP server. The easiest way to get this is to add
64 It must be served by an HTTP server. The easiest way to get this is to add
65 ``--post serve`` on the command-line.
65 ``--post serve`` on the command-line.
66 If you want to use the speaker notes plugin, just add
67 ``--slide-notes=True`` on the command-line.
68 For low connectivity environments, you can use a local copy of the reveal.js library,
69 just add ``--offline-slides=reveal.js`` on the command-line, and do not forget to move
70 your downloaded ``reveal.js`` library to the same folder where your slides are located.
66
71
67 * ``--to markdown``
72 * ``--to markdown``
68
73
69 Simple markdown output. Markdown cells are unaffected,
74 Simple markdown output. Markdown cells are unaffected,
70 and code cells are placed in triple-backtick (```````) blocks.
75 and code cells are placed in triple-backtick (```````) blocks.
71
76
72 * ``--to rst``
77 * ``--to rst``
73
78
74 Basic reStructuredText output. Useful as a starting point for embedding notebooks
79 Basic reStructuredText output. Useful as a starting point for embedding notebooks
75 in Sphinx docs.
80 in Sphinx docs.
76
81
77 * ``--to python``
82 * ``--to python``
78
83
79 Convert a notebook to an executable Python script.
84 Convert a notebook to an executable Python script.
80 This is the simplest way to get a Python script out of a notebook.
85 This is the simplest way to get a Python script out of a notebook.
81 If there were any magics in the notebook, this may only be executable from
86 If there were any magics in the notebook, this may only be executable from
82 an IPython session.
87 an IPython session.
83
88
84 .. note::
89 .. note::
85
90
86 nbconvert uses pandoc_ to convert between various markup languages,
91 nbconvert uses pandoc_ to convert between various markup languages,
87 so pandoc is a dependency of most nbconvert transforms,
92 so pandoc is a dependency of most nbconvert transforms,
88 excluding Markdown and Python.
93 excluding Markdown and Python.
89
94
90 .. _pandoc: http://johnmacfarlane.net/pandoc/
95 .. _pandoc: http://johnmacfarlane.net/pandoc/
91
96
92 The output file created by ``nbconvert`` will have the same base name as
97 The output file created by ``nbconvert`` will have the same base name as
93 the notebook and will be placed in the current working directory. Any
98 the notebook and will be placed in the current working directory. Any
94 supporting files (graphics, etc) will be placed in a new directory with the
99 supporting files (graphics, etc) will be placed in a new directory with the
95 same base name as the notebook, suffixed with ``_files``::
100 same base name as the notebook, suffixed with ``_files``::
96
101
97 $ ipython nbconvert notebook.ipynb
102 $ ipython nbconvert notebook.ipynb
98 $ ls
103 $ ls
99 notebook.ipynb notebook.html notebook_files/
104 notebook.ipynb notebook.html notebook_files/
100
105
101 For simple single-file output, such as html, markdown, etc.,
106 For simple single-file output, such as html, markdown, etc.,
102 the output may be sent to standard output with::
107 the output may be sent to standard output with::
103
108
104 $ ipython nbconvert --to markdown notebook.ipynb --stdout
109 $ ipython nbconvert --to markdown notebook.ipynb --stdout
105
110
106 Multiple notebooks can be specified from the command line::
111 Multiple notebooks can be specified from the command line::
107
112
108 $ ipython nbconvert notebook*.ipynb
113 $ ipython nbconvert notebook*.ipynb
109 $ ipython nbconvert notebook1.ipynb notebook2.ipynb
114 $ ipython nbconvert notebook1.ipynb notebook2.ipynb
110
115
111 or via a list in a configuration file, say ``mycfg.py``, containing the text::
116 or via a list in a configuration file, say ``mycfg.py``, containing the text::
112
117
113 c = get_config()
118 c = get_config()
114 c.NbConvertApp.notebooks = ["notebook1.ipynb", "notebook2.ipynb"]
119 c.NbConvertApp.notebooks = ["notebook1.ipynb", "notebook2.ipynb"]
115
120
116 and using the command::
121 and using the command::
117
122
118 $ ipython nbconvert --config mycfg.py
123 $ ipython nbconvert --config mycfg.py
119
124
120
125
121 .. _notebook_format:
126 .. _notebook_format:
122
127
123 Notebook JSON file format
128 Notebook JSON file format
124 -------------------------
129 -------------------------
125
130
126 Notebook documents are JSON files with an ``.ipynb`` extension, formatted
131 Notebook documents are JSON files with an ``.ipynb`` extension, formatted
127 as legibly as possible with minimal extra indentation and cell content broken
132 as legibly as possible with minimal extra indentation and cell content broken
128 across lines to make them reasonably friendly to use in version-control
133 across lines to make them reasonably friendly to use in version-control
129 workflows. You should be very careful if you ever manually edit this JSON
134 workflows. You should be very careful if you ever manually edit this JSON
130 data, as it is extremely easy to corrupt its internal structure and make the
135 data, as it is extremely easy to corrupt its internal structure and make the
131 file impossible to load. In general, you should consider the notebook as a
136 file impossible to load. In general, you should consider the notebook as a
132 file meant only to be edited by the IPython Notebook app itself, not for
137 file meant only to be edited by the IPython Notebook app itself, not for
133 hand-editing.
138 hand-editing.
134
139
135 .. note::
140 .. note::
136
141
137 Binary data such as figures are also saved directly in the JSON file.
142 Binary data such as figures are also saved directly in the JSON file.
138 This provides convenient single-file portability, but means that the
143 This provides convenient single-file portability, but means that the
139 files can be large; a ``diff`` of binary data is also not very
144 files can be large; a ``diff`` of binary data is also not very
140 meaningful. Since the binary blobs are encoded in a single line, they
145 meaningful. Since the binary blobs are encoded in a single line, they
141 affect only one line of the ``diff`` output, but they are typically very
146 affect only one line of the ``diff`` output, but they are typically very
142 long lines. You can use the ``Cell | All Output | Clear`` menu option to
147 long lines. You can use the ``Cell | All Output | Clear`` menu option to
143 remove all output from a notebook prior to committing it to version
148 remove all output from a notebook prior to committing it to version
144 control, if this is a concern.
149 control, if this is a concern.
145
150
146 The notebook server can also generate a pure Python version of your notebook,
151 The notebook server can also generate a pure Python version of your notebook,
147 using the ``File | Download as`` menu option. The resulting ``.py`` file will
152 using the ``File | Download as`` menu option. The resulting ``.py`` file will
148 contain all the code cells from your notebook verbatim, and all Markdown cells
153 contain all the code cells from your notebook verbatim, and all Markdown cells
149 prepended with a comment marker. The separation between code and Markdown
154 prepended with a comment marker. The separation between code and Markdown
150 cells is indicated with special comments and there is a header indicating the
155 cells is indicated with special comments and there is a header indicating the
151 format version. All output is removed when exporting to Python.
156 format version. All output is removed when exporting to Python.
152
157
153 As an example, consider a simple notebook called ``simple.ipynb`` which
158 As an example, consider a simple notebook called ``simple.ipynb`` which
154 contains one Markdown cell, with the content ``The simplest notebook.``, one
159 contains one Markdown cell, with the content ``The simplest notebook.``, one
155 code input cell with the content ``print "Hello, IPython!"``, and the
160 code input cell with the content ``print "Hello, IPython!"``, and the
156 corresponding output.
161 corresponding output.
157
162
158 The contents of the notebook document ``simple.ipynb`` is the following JSON
163 The contents of the notebook document ``simple.ipynb`` is the following JSON
159 container::
164 container::
160
165
161 {
166 {
162 "metadata": {
167 "metadata": {
163 "name": "simple"
168 "name": "simple"
164 },
169 },
165 "nbformat": 3,
170 "nbformat": 3,
166 "nbformat_minor": 0,
171 "nbformat_minor": 0,
167 "worksheets": [
172 "worksheets": [
168 {
173 {
169 "cells": [
174 "cells": [
170 {
175 {
171 "cell_type": "markdown",
176 "cell_type": "markdown",
172 "metadata": {},
177 "metadata": {},
173 "source": "The simplest notebook."
178 "source": "The simplest notebook."
174 },
179 },
175 {
180 {
176 "cell_type": "code",
181 "cell_type": "code",
177 "collapsed": false,
182 "collapsed": false,
178 "input": "print \"Hello, IPython\"",
183 "input": "print \"Hello, IPython\"",
179 "language": "python",
184 "language": "python",
180 "metadata": {},
185 "metadata": {},
181 "outputs": [
186 "outputs": [
182 {
187 {
183 "output_type": "stream",
188 "output_type": "stream",
184 "stream": "stdout",
189 "stream": "stdout",
185 "text": "Hello, IPython\n"
190 "text": "Hello, IPython\n"
186 }
191 }
187 ],
192 ],
188 "prompt_number": 1
193 "prompt_number": 1
189 }
194 }
190 ],
195 ],
191 "metadata": {}
196 "metadata": {}
192 }
197 }
193 ]
198 ]
194 }
199 }
195
200
196
201
197 The corresponding Python script is::
202 The corresponding Python script is::
198
203
199 # -*- coding: utf-8 -*-
204 # -*- coding: utf-8 -*-
200 # <nbformat>3.0</nbformat>
205 # <nbformat>3.0</nbformat>
201
206
202 # <markdowncell>
207 # <markdowncell>
203
208
204 # The simplest notebook.
209 # The simplest notebook.
205
210
206 # <codecell>
211 # <codecell>
207
212
208 print "Hello, IPython"
213 print "Hello, IPython"
209
214
210 Note that indeed the output of the code cell, which is present in the JSON
215 Note that indeed the output of the code cell, which is present in the JSON
211 container, has been removed in the ``.py`` script.
216 container, has been removed in the ``.py`` script.
212
217
General Comments 0
You need to be logged in to leave comments. Login now