##// END OF EJS Templates
remove trailing whitespace
Matthias BUSSONNIER -
Show More
@@ -1,654 +1,654 b''
1 # coding: utf-8
1 # coding: utf-8
2 """A tornado based IPython notebook server.
2 """A tornado based IPython notebook server.
3
3
4 Authors:
4 Authors:
5
5
6 * Brian Granger
6 * Brian Granger
7 """
7 """
8 #-----------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
9 # Copyright (C) 2008-2011 The IPython Development Team
9 # Copyright (C) 2008-2011 The IPython Development Team
10 #
10 #
11 # Distributed under the terms of the BSD License. The full license is in
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
12 # the file COPYING, distributed as part of this software.
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 # Imports
16 # Imports
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 # stdlib
19 # stdlib
20 import errno
20 import errno
21 import logging
21 import logging
22 import os
22 import os
23 import random
23 import random
24 import re
24 import re
25 import select
25 import select
26 import signal
26 import signal
27 import socket
27 import socket
28 import sys
28 import sys
29 import threading
29 import threading
30 import time
30 import time
31 import uuid
31 import uuid
32 import webbrowser
32 import webbrowser
33
33
34 # Third party
34 # Third party
35 import zmq
35 import zmq
36 from jinja2 import Environment, FileSystemLoader
36 from jinja2 import Environment, FileSystemLoader
37
37
38 # Install the pyzmq ioloop. This has to be done before anything else from
38 # Install the pyzmq ioloop. This has to be done before anything else from
39 # tornado is imported.
39 # tornado is imported.
40 from zmq.eventloop import ioloop
40 from zmq.eventloop import ioloop
41 ioloop.install()
41 ioloop.install()
42
42
43 from tornado import httpserver
43 from tornado import httpserver
44 from tornado import web
44 from tornado import web
45
45
46 # Our own libraries
46 # Our own libraries
47 from .kernelmanager import MappingKernelManager
47 from .kernelmanager import MappingKernelManager
48 from .handlers import (LoginHandler, LogoutHandler,
48 from .handlers import (LoginHandler, LogoutHandler,
49 ProjectDashboardHandler, NewHandler, NamedNotebookHandler,
49 ProjectDashboardHandler, NewHandler, NamedNotebookHandler,
50 MainKernelHandler, KernelHandler, KernelActionHandler, IOPubHandler,
50 MainKernelHandler, KernelHandler, KernelActionHandler, IOPubHandler,
51 ShellHandler, NotebookRootHandler, NotebookHandler, NotebookCopyHandler,
51 ShellHandler, NotebookRootHandler, NotebookHandler, NotebookCopyHandler,
52 RSTHandler, AuthenticatedFileHandler, PrintNotebookHandler,
52 RSTHandler, AuthenticatedFileHandler, PrintNotebookHandler,
53 MainClusterHandler, ClusterProfileHandler, ClusterActionHandler,
53 MainClusterHandler, ClusterProfileHandler, ClusterActionHandler,
54 FileFindHandler,
54 FileFindHandler,
55 )
55 )
56 from .nbmanager import NotebookManager
56 from .nbmanager import NotebookManager
57 from .filenbmanager import FileNotebookManager
57 from .filenbmanager import FileNotebookManager
58 from .clustermanager import ClusterManager
58 from .clustermanager import ClusterManager
59
59
60 from IPython.config.application import catch_config_error, boolean_flag
60 from IPython.config.application import catch_config_error, boolean_flag
61 from IPython.core.application import BaseIPythonApplication
61 from IPython.core.application import BaseIPythonApplication
62 from IPython.core.profiledir import ProfileDir
62 from IPython.core.profiledir import ProfileDir
63 from IPython.frontend.consoleapp import IPythonConsoleApp
63 from IPython.frontend.consoleapp import IPythonConsoleApp
64 from IPython.lib.kernel import swallow_argv
64 from IPython.lib.kernel import swallow_argv
65 from IPython.zmq.session import Session, default_secure
65 from IPython.zmq.session import Session, default_secure
66 from IPython.zmq.zmqshell import ZMQInteractiveShell
66 from IPython.zmq.zmqshell import ZMQInteractiveShell
67 from IPython.zmq.ipkernel import (
67 from IPython.zmq.ipkernel import (
68 flags as ipkernel_flags,
68 flags as ipkernel_flags,
69 aliases as ipkernel_aliases,
69 aliases as ipkernel_aliases,
70 IPKernelApp
70 IPKernelApp
71 )
71 )
72 from IPython.utils.importstring import import_item
72 from IPython.utils.importstring import import_item
73 from IPython.utils.traitlets import (
73 from IPython.utils.traitlets import (
74 Dict, Unicode, Integer, List, Enum, Bool,
74 Dict, Unicode, Integer, List, Enum, Bool,
75 DottedObjectName
75 DottedObjectName
76 )
76 )
77 from IPython.utils import py3compat
77 from IPython.utils import py3compat
78 from IPython.utils.path import filefind
78 from IPython.utils.path import filefind
79
79
80 #-----------------------------------------------------------------------------
80 #-----------------------------------------------------------------------------
81 # Module globals
81 # Module globals
82 #-----------------------------------------------------------------------------
82 #-----------------------------------------------------------------------------
83
83
84 _kernel_id_regex = r"(?P<kernel_id>\w+-\w+-\w+-\w+-\w+)"
84 _kernel_id_regex = r"(?P<kernel_id>\w+-\w+-\w+-\w+-\w+)"
85 _kernel_action_regex = r"(?P<action>restart|interrupt)"
85 _kernel_action_regex = r"(?P<action>restart|interrupt)"
86 _notebook_id_regex = r"(?P<notebook_id>\w+-\w+-\w+-\w+-\w+)"
86 _notebook_id_regex = r"(?P<notebook_id>\w+-\w+-\w+-\w+-\w+)"
87 _profile_regex = r"(?P<profile>[^\/]+)" # there is almost no text that is invalid
87 _profile_regex = r"(?P<profile>[^\/]+)" # there is almost no text that is invalid
88 _cluster_action_regex = r"(?P<action>start|stop)"
88 _cluster_action_regex = r"(?P<action>start|stop)"
89
89
90
90
91 LOCALHOST = '127.0.0.1'
91 LOCALHOST = '127.0.0.1'
92
92
93 _examples = """
93 _examples = """
94 ipython notebook # start the notebook
94 ipython notebook # start the notebook
95 ipython notebook --profile=sympy # use the sympy profile
95 ipython notebook --profile=sympy # use the sympy profile
96 ipython notebook --pylab=inline # pylab in inline plotting mode
96 ipython notebook --pylab=inline # pylab in inline plotting mode
97 ipython notebook --certfile=mycert.pem # use SSL/TLS certificate
97 ipython notebook --certfile=mycert.pem # use SSL/TLS certificate
98 ipython notebook --port=5555 --ip=* # Listen on port 5555, all interfaces
98 ipython notebook --port=5555 --ip=* # Listen on port 5555, all interfaces
99 """
99 """
100
100
101 #-----------------------------------------------------------------------------
101 #-----------------------------------------------------------------------------
102 # Helper functions
102 # Helper functions
103 #-----------------------------------------------------------------------------
103 #-----------------------------------------------------------------------------
104
104
105 def url_path_join(a,b):
105 def url_path_join(a,b):
106 if a.endswith('/') and b.startswith('/'):
106 if a.endswith('/') and b.startswith('/'):
107 return a[:-1]+b
107 return a[:-1]+b
108 else:
108 else:
109 return a+b
109 return a+b
110
110
111 def random_ports(port, n):
111 def random_ports(port, n):
112 """Generate a list of n random ports near the given port.
112 """Generate a list of n random ports near the given port.
113
113
114 The first 5 ports will be sequential, and the remaining n-5 will be
114 The first 5 ports will be sequential, and the remaining n-5 will be
115 randomly selected in the range [port-2*n, port+2*n].
115 randomly selected in the range [port-2*n, port+2*n].
116 """
116 """
117 for i in range(min(5, n)):
117 for i in range(min(5, n)):
118 yield port + i
118 yield port + i
119 for i in range(n-5):
119 for i in range(n-5):
120 yield port + random.randint(-2*n, 2*n)
120 yield port + random.randint(-2*n, 2*n)
121
121
122 #-----------------------------------------------------------------------------
122 #-----------------------------------------------------------------------------
123 # The Tornado web application
123 # The Tornado web application
124 #-----------------------------------------------------------------------------
124 #-----------------------------------------------------------------------------
125
125
126 class NotebookWebApplication(web.Application):
126 class NotebookWebApplication(web.Application):
127
127
128 def __init__(self, ipython_app, kernel_manager, notebook_manager,
128 def __init__(self, ipython_app, kernel_manager, notebook_manager,
129 cluster_manager, log,
129 cluster_manager, log,
130 base_project_url, settings_overrides):
130 base_project_url, settings_overrides):
131 handlers = [
131 handlers = [
132 (r"/", ProjectDashboardHandler),
132 (r"/", ProjectDashboardHandler),
133 (r"/login", LoginHandler),
133 (r"/login", LoginHandler),
134 (r"/logout", LogoutHandler),
134 (r"/logout", LogoutHandler),
135 (r"/new", NewHandler),
135 (r"/new", NewHandler),
136 (r"/%s" % _notebook_id_regex, NamedNotebookHandler),
136 (r"/%s" % _notebook_id_regex, NamedNotebookHandler),
137 (r"/%s/copy" % _notebook_id_regex, NotebookCopyHandler),
137 (r"/%s/copy" % _notebook_id_regex, NotebookCopyHandler),
138 (r"/%s/print" % _notebook_id_regex, PrintNotebookHandler),
138 (r"/%s/print" % _notebook_id_regex, PrintNotebookHandler),
139 (r"/kernels", MainKernelHandler),
139 (r"/kernels", MainKernelHandler),
140 (r"/kernels/%s" % _kernel_id_regex, KernelHandler),
140 (r"/kernels/%s" % _kernel_id_regex, KernelHandler),
141 (r"/kernels/%s/%s" % (_kernel_id_regex, _kernel_action_regex), KernelActionHandler),
141 (r"/kernels/%s/%s" % (_kernel_id_regex, _kernel_action_regex), KernelActionHandler),
142 (r"/kernels/%s/iopub" % _kernel_id_regex, IOPubHandler),
142 (r"/kernels/%s/iopub" % _kernel_id_regex, IOPubHandler),
143 (r"/kernels/%s/shell" % _kernel_id_regex, ShellHandler),
143 (r"/kernels/%s/shell" % _kernel_id_regex, ShellHandler),
144 (r"/notebooks", NotebookRootHandler),
144 (r"/notebooks", NotebookRootHandler),
145 (r"/notebooks/%s" % _notebook_id_regex, NotebookHandler),
145 (r"/notebooks/%s" % _notebook_id_regex, NotebookHandler),
146 (r"/rstservice/render", RSTHandler),
146 (r"/rstservice/render", RSTHandler),
147 (r"/files/(.*)", AuthenticatedFileHandler, {'path' : notebook_manager.notebook_dir}),
147 (r"/files/(.*)", AuthenticatedFileHandler, {'path' : notebook_manager.notebook_dir}),
148 (r"/clusters", MainClusterHandler),
148 (r"/clusters", MainClusterHandler),
149 (r"/clusters/%s/%s" % (_profile_regex, _cluster_action_regex), ClusterActionHandler),
149 (r"/clusters/%s/%s" % (_profile_regex, _cluster_action_regex), ClusterActionHandler),
150 (r"/clusters/%s" % _profile_regex, ClusterProfileHandler),
150 (r"/clusters/%s" % _profile_regex, ClusterProfileHandler),
151 ]
151 ]
152
152
153 # Python < 2.6.5 doesn't accept unicode keys in f(**kwargs), and
153 # Python < 2.6.5 doesn't accept unicode keys in f(**kwargs), and
154 # base_project_url will always be unicode, which will in turn
154 # base_project_url will always be unicode, which will in turn
155 # make the patterns unicode, and ultimately result in unicode
155 # make the patterns unicode, and ultimately result in unicode
156 # keys in kwargs to handler._execute(**kwargs) in tornado.
156 # keys in kwargs to handler._execute(**kwargs) in tornado.
157 # This enforces that base_project_url be ascii in that situation.
157 # This enforces that base_project_url be ascii in that situation.
158 #
158 #
159 # Note that the URLs these patterns check against are escaped,
159 # Note that the URLs these patterns check against are escaped,
160 # and thus guaranteed to be ASCII: 'héllo' is really 'h%C3%A9llo'.
160 # and thus guaranteed to be ASCII: 'héllo' is really 'h%C3%A9llo'.
161 base_project_url = py3compat.unicode_to_str(base_project_url, 'ascii')
161 base_project_url = py3compat.unicode_to_str(base_project_url, 'ascii')
162
162
163 settings = dict(
163 settings = dict(
164 template_path=os.path.join(os.path.dirname(__file__), "templates"),
164 template_path=os.path.join(os.path.dirname(__file__), "templates"),
165 static_path=ipython_app.static_file_path,
165 static_path=ipython_app.static_file_path,
166 static_handler_class = FileFindHandler,
166 static_handler_class = FileFindHandler,
167 static_url_prefix = url_path_join(base_project_url,'/static/'),
167 static_url_prefix = url_path_join(base_project_url,'/static/'),
168 cookie_secret=os.urandom(1024),
168 cookie_secret=os.urandom(1024),
169 login_url=url_path_join(base_project_url,'/login'),
169 login_url=url_path_join(base_project_url,'/login'),
170 cookie_name='username-%s' % uuid.uuid4(),
170 cookie_name='username-%s' % uuid.uuid4(),
171 )
171 )
172
172
173 # allow custom overrides for the tornado web app.
173 # allow custom overrides for the tornado web app.
174 settings.update(settings_overrides)
174 settings.update(settings_overrides)
175
175
176 # prepend base_project_url onto the patterns that we match
176 # prepend base_project_url onto the patterns that we match
177 new_handlers = []
177 new_handlers = []
178 for handler in handlers:
178 for handler in handlers:
179 pattern = url_path_join(base_project_url, handler[0])
179 pattern = url_path_join(base_project_url, handler[0])
180 new_handler = tuple([pattern]+list(handler[1:]))
180 new_handler = tuple([pattern]+list(handler[1:]))
181 new_handlers.append( new_handler )
181 new_handlers.append( new_handler )
182
182
183 super(NotebookWebApplication, self).__init__(new_handlers, **settings)
183 super(NotebookWebApplication, self).__init__(new_handlers, **settings)
184
184
185 self.kernel_manager = kernel_manager
185 self.kernel_manager = kernel_manager
186 self.notebook_manager = notebook_manager
186 self.notebook_manager = notebook_manager
187 self.cluster_manager = cluster_manager
187 self.cluster_manager = cluster_manager
188 self.ipython_app = ipython_app
188 self.ipython_app = ipython_app
189 self.read_only = self.ipython_app.read_only
189 self.read_only = self.ipython_app.read_only
190 self.config = self.ipython_app.config
190 self.config = self.ipython_app.config
191 self.use_less = self.ipython_app.use_less
191 self.use_less = self.ipython_app.use_less
192 self.log = log
192 self.log = log
193 self.jinja2_env = Environment(loader=FileSystemLoader(os.path.join(os.path.dirname(__file__), "templates")))
193 self.jinja2_env = Environment(loader=FileSystemLoader(os.path.join(os.path.dirname(__file__), "templates")))
194
194
195
195
196
196
197 #-----------------------------------------------------------------------------
197 #-----------------------------------------------------------------------------
198 # Aliases and Flags
198 # Aliases and Flags
199 #-----------------------------------------------------------------------------
199 #-----------------------------------------------------------------------------
200
200
201 flags = dict(ipkernel_flags)
201 flags = dict(ipkernel_flags)
202 flags['no-browser']=(
202 flags['no-browser']=(
203 {'NotebookApp' : {'open_browser' : False}},
203 {'NotebookApp' : {'open_browser' : False}},
204 "Don't open the notebook in a browser after startup."
204 "Don't open the notebook in a browser after startup."
205 )
205 )
206 flags['no-mathjax']=(
206 flags['no-mathjax']=(
207 {'NotebookApp' : {'enable_mathjax' : False}},
207 {'NotebookApp' : {'enable_mathjax' : False}},
208 """Disable MathJax
208 """Disable MathJax
209
209
210 MathJax is the javascript library IPython uses to render math/LaTeX. It is
210 MathJax is the javascript library IPython uses to render math/LaTeX. It is
211 very large, so you may want to disable it if you have a slow internet
211 very large, so you may want to disable it if you have a slow internet
212 connection, or for offline use of the notebook.
212 connection, or for offline use of the notebook.
213
213
214 When disabled, equations etc. will appear as their untransformed TeX source.
214 When disabled, equations etc. will appear as their untransformed TeX source.
215 """
215 """
216 )
216 )
217 flags['read-only'] = (
217 flags['read-only'] = (
218 {'NotebookApp' : {'read_only' : True}},
218 {'NotebookApp' : {'read_only' : True}},
219 """Allow read-only access to notebooks.
219 """Allow read-only access to notebooks.
220
220
221 When using a password to protect the notebook server, this flag
221 When using a password to protect the notebook server, this flag
222 allows unauthenticated clients to view the notebook list, and
222 allows unauthenticated clients to view the notebook list, and
223 individual notebooks, but not edit them, start kernels, or run
223 individual notebooks, but not edit them, start kernels, or run
224 code.
224 code.
225
225
226 If no password is set, the server will be entirely read-only.
226 If no password is set, the server will be entirely read-only.
227 """
227 """
228 )
228 )
229
229
230 # Add notebook manager flags
230 # Add notebook manager flags
231 flags.update(boolean_flag('script', 'FileNotebookManager.save_script',
231 flags.update(boolean_flag('script', 'FileNotebookManager.save_script',
232 'Auto-save a .py script everytime the .ipynb notebook is saved',
232 'Auto-save a .py script everytime the .ipynb notebook is saved',
233 'Do not auto-save .py scripts for every notebook'))
233 'Do not auto-save .py scripts for every notebook'))
234
234
235 # the flags that are specific to the frontend
235 # the flags that are specific to the frontend
236 # these must be scrubbed before being passed to the kernel,
236 # these must be scrubbed before being passed to the kernel,
237 # or it will raise an error on unrecognized flags
237 # or it will raise an error on unrecognized flags
238 notebook_flags = ['no-browser', 'no-mathjax', 'read-only', 'script', 'no-script']
238 notebook_flags = ['no-browser', 'no-mathjax', 'read-only', 'script', 'no-script']
239
239
240 aliases = dict(ipkernel_aliases)
240 aliases = dict(ipkernel_aliases)
241
241
242 aliases.update({
242 aliases.update({
243 'ip': 'NotebookApp.ip',
243 'ip': 'NotebookApp.ip',
244 'port': 'NotebookApp.port',
244 'port': 'NotebookApp.port',
245 'port-retries': 'NotebookApp.port_retries',
245 'port-retries': 'NotebookApp.port_retries',
246 'transport': 'KernelManager.transport',
246 'transport': 'KernelManager.transport',
247 'keyfile': 'NotebookApp.keyfile',
247 'keyfile': 'NotebookApp.keyfile',
248 'certfile': 'NotebookApp.certfile',
248 'certfile': 'NotebookApp.certfile',
249 'notebook-dir': 'NotebookManager.notebook_dir',
249 'notebook-dir': 'NotebookManager.notebook_dir',
250 'browser': 'NotebookApp.browser',
250 'browser': 'NotebookApp.browser',
251 })
251 })
252
252
253 # remove ipkernel flags that are singletons, and don't make sense in
253 # remove ipkernel flags that are singletons, and don't make sense in
254 # multi-kernel evironment:
254 # multi-kernel evironment:
255 aliases.pop('f', None)
255 aliases.pop('f', None)
256
256
257 notebook_aliases = [u'port', u'port-retries', u'ip', u'keyfile', u'certfile',
257 notebook_aliases = [u'port', u'port-retries', u'ip', u'keyfile', u'certfile',
258 u'notebook-dir']
258 u'notebook-dir']
259
259
260 #-----------------------------------------------------------------------------
260 #-----------------------------------------------------------------------------
261 # NotebookApp
261 # NotebookApp
262 #-----------------------------------------------------------------------------
262 #-----------------------------------------------------------------------------
263
263
264 class NotebookApp(BaseIPythonApplication):
264 class NotebookApp(BaseIPythonApplication):
265
265
266 name = 'ipython-notebook'
266 name = 'ipython-notebook'
267 default_config_file_name='ipython_notebook_config.py'
267 default_config_file_name='ipython_notebook_config.py'
268
268
269 description = """
269 description = """
270 The IPython HTML Notebook.
270 The IPython HTML Notebook.
271
271
272 This launches a Tornado based HTML Notebook Server that serves up an
272 This launches a Tornado based HTML Notebook Server that serves up an
273 HTML5/Javascript Notebook client.
273 HTML5/Javascript Notebook client.
274 """
274 """
275 examples = _examples
275 examples = _examples
276
276
277 classes = IPythonConsoleApp.classes + [MappingKernelManager, NotebookManager,
277 classes = IPythonConsoleApp.classes + [MappingKernelManager, NotebookManager,
278 FileNotebookManager]
278 FileNotebookManager]
279 flags = Dict(flags)
279 flags = Dict(flags)
280 aliases = Dict(aliases)
280 aliases = Dict(aliases)
281
281
282 kernel_argv = List(Unicode)
282 kernel_argv = List(Unicode)
283
283
284 log_level = Enum((0,10,20,30,40,50,'DEBUG','INFO','WARN','ERROR','CRITICAL'),
284 log_level = Enum((0,10,20,30,40,50,'DEBUG','INFO','WARN','ERROR','CRITICAL'),
285 default_value=logging.INFO,
285 default_value=logging.INFO,
286 config=True,
286 config=True,
287 help="Set the log level by value or name.")
287 help="Set the log level by value or name.")
288
288
289 # create requested profiles by default, if they don't exist:
289 # create requested profiles by default, if they don't exist:
290 auto_create = Bool(True)
290 auto_create = Bool(True)
291
291
292 # file to be opened in the notebook server
292 # file to be opened in the notebook server
293 file_to_run = Unicode('')
293 file_to_run = Unicode('')
294
294
295 # Network related information.
295 # Network related information.
296
296
297 ip = Unicode(LOCALHOST, config=True,
297 ip = Unicode(LOCALHOST, config=True,
298 help="The IP address the notebook server will listen on."
298 help="The IP address the notebook server will listen on."
299 )
299 )
300
300
301 def _ip_changed(self, name, old, new):
301 def _ip_changed(self, name, old, new):
302 if new == u'*': self.ip = u''
302 if new == u'*': self.ip = u''
303
303
304 port = Integer(8888, config=True,
304 port = Integer(8888, config=True,
305 help="The port the notebook server will listen on."
305 help="The port the notebook server will listen on."
306 )
306 )
307 port_retries = Integer(50, config=True,
307 port_retries = Integer(50, config=True,
308 help="The number of additional ports to try if the specified port is not available."
308 help="The number of additional ports to try if the specified port is not available."
309 )
309 )
310
310
311 certfile = Unicode(u'', config=True,
311 certfile = Unicode(u'', config=True,
312 help="""The full path to an SSL/TLS certificate file."""
312 help="""The full path to an SSL/TLS certificate file."""
313 )
313 )
314
314
315 keyfile = Unicode(u'', config=True,
315 keyfile = Unicode(u'', config=True,
316 help="""The full path to a private key file for usage with SSL/TLS."""
316 help="""The full path to a private key file for usage with SSL/TLS."""
317 )
317 )
318
318
319 password = Unicode(u'', config=True,
319 password = Unicode(u'', config=True,
320 help="""Hashed password to use for web authentication.
320 help="""Hashed password to use for web authentication.
321
321
322 To generate, type in a python/IPython shell:
322 To generate, type in a python/IPython shell:
323
323
324 from IPython.lib import passwd; passwd()
324 from IPython.lib import passwd; passwd()
325
325
326 The string should be of the form type:salt:hashed-password.
326 The string should be of the form type:salt:hashed-password.
327 """
327 """
328 )
328 )
329
329
330 open_browser = Bool(True, config=True,
330 open_browser = Bool(True, config=True,
331 help="""Whether to open in a browser after starting.
331 help="""Whether to open in a browser after starting.
332 The specific browser used is platform dependent and
332 The specific browser used is platform dependent and
333 determined by the python standard library `webbrowser`
333 determined by the python standard library `webbrowser`
334 module, unless it is overridden using the --browser
334 module, unless it is overridden using the --browser
335 (NotebookApp.browser) configuration option.
335 (NotebookApp.browser) configuration option.
336 """)
336 """)
337
337
338 browser = Unicode(u'', config=True,
338 browser = Unicode(u'', config=True,
339 help="""Specify what command to use to invoke a web
339 help="""Specify what command to use to invoke a web
340 browser when opening the notebook. If not specified, the
340 browser when opening the notebook. If not specified, the
341 default browser will be determined by the `webbrowser`
341 default browser will be determined by the `webbrowser`
342 standard library module, which allows setting of the
342 standard library module, which allows setting of the
343 BROWSER environment variable to override it.
343 BROWSER environment variable to override it.
344 """)
344 """)
345
345
346 read_only = Bool(False, config=True,
346 read_only = Bool(False, config=True,
347 help="Whether to prevent editing/execution of notebooks."
347 help="Whether to prevent editing/execution of notebooks."
348 )
348 )
349
349
350 use_less = Bool(False, config=True,
350 use_less = Bool(False, config=True,
351 help="""Wether to use Browser Side less-css parsing
351 help="""Wether to use Browser Side less-css parsing
352 instead of compiled css version in templates that allows
352 instead of compiled css version in templates that allows
353 it. This is mainly convenient when working on the less
353 it. This is mainly convenient when working on the less
354 file to avoid a build step, or if user want to overwrite
354 file to avoid a build step, or if user want to overwrite
355 some of the less variables without having to recompile
355 some of the less variables without having to recompile
356 everything.""")
356 everything.""")
357
357
358 webapp_settings = Dict(config=True,
358 webapp_settings = Dict(config=True,
359 help="Supply overrides for the tornado.web.Application that the "
359 help="Supply overrides for the tornado.web.Application that the "
360 "IPython notebook uses.")
360 "IPython notebook uses.")
361
361
362 enable_mathjax = Bool(True, config=True,
362 enable_mathjax = Bool(True, config=True,
363 help="""Whether to enable MathJax for typesetting math/TeX
363 help="""Whether to enable MathJax for typesetting math/TeX
364
364
365 MathJax is the javascript library IPython uses to render math/LaTeX. It is
365 MathJax is the javascript library IPython uses to render math/LaTeX. It is
366 very large, so you may want to disable it if you have a slow internet
366 very large, so you may want to disable it if you have a slow internet
367 connection, or for offline use of the notebook.
367 connection, or for offline use of the notebook.
368
368
369 When disabled, equations etc. will appear as their untransformed TeX source.
369 When disabled, equations etc. will appear as their untransformed TeX source.
370 """
370 """
371 )
371 )
372 def _enable_mathjax_changed(self, name, old, new):
372 def _enable_mathjax_changed(self, name, old, new):
373 """set mathjax url to empty if mathjax is disabled"""
373 """set mathjax url to empty if mathjax is disabled"""
374 if not new:
374 if not new:
375 self.mathjax_url = u''
375 self.mathjax_url = u''
376
376
377 base_project_url = Unicode('/', config=True,
377 base_project_url = Unicode('/', config=True,
378 help='''The base URL for the notebook server.
378 help='''The base URL for the notebook server.
379
379
380 Leading and trailing slashes can be omitted,
380 Leading and trailing slashes can be omitted,
381 and will automatically be added.
381 and will automatically be added.
382 ''')
382 ''')
383 def _base_project_url_changed(self, name, old, new):
383 def _base_project_url_changed(self, name, old, new):
384 if not new.startswith('/'):
384 if not new.startswith('/'):
385 self.base_project_url = '/'+new
385 self.base_project_url = '/'+new
386 elif not new.endswith('/'):
386 elif not new.endswith('/'):
387 self.base_project_url = new+'/'
387 self.base_project_url = new+'/'
388
388
389 base_kernel_url = Unicode('/', config=True,
389 base_kernel_url = Unicode('/', config=True,
390 help='''The base URL for the kernel server
390 help='''The base URL for the kernel server
391
391
392 Leading and trailing slashes can be omitted,
392 Leading and trailing slashes can be omitted,
393 and will automatically be added.
393 and will automatically be added.
394 ''')
394 ''')
395 def _base_kernel_url_changed(self, name, old, new):
395 def _base_kernel_url_changed(self, name, old, new):
396 if not new.startswith('/'):
396 if not new.startswith('/'):
397 self.base_kernel_url = '/'+new
397 self.base_kernel_url = '/'+new
398 elif not new.endswith('/'):
398 elif not new.endswith('/'):
399 self.base_kernel_url = new+'/'
399 self.base_kernel_url = new+'/'
400
400
401 websocket_host = Unicode("", config=True,
401 websocket_host = Unicode("", config=True,
402 help="""The hostname for the websocket server."""
402 help="""The hostname for the websocket server."""
403 )
403 )
404
404
405 extra_static_paths = List(Unicode, config=True,
405 extra_static_paths = List(Unicode, config=True,
406 help="""Extra paths to search for serving static files.
406 help="""Extra paths to search for serving static files.
407
407
408 This allows adding javascript/css to be available from the notebook server machine,
408 This allows adding javascript/css to be available from the notebook server machine,
409 or overriding individual files in the IPython"""
409 or overriding individual files in the IPython"""
410 )
410 )
411 def _extra_static_paths_default(self):
411 def _extra_static_paths_default(self):
412 return [os.path.join(self.profile_dir.location, 'static')]
412 return [os.path.join(self.profile_dir.location, 'static')]
413
413
414 @property
414 @property
415 def static_file_path(self):
415 def static_file_path(self):
416 """return extra paths + the default location"""
416 """return extra paths + the default location"""
417 return self.extra_static_paths + [os.path.join(os.path.dirname(__file__), "static")]
417 return self.extra_static_paths + [os.path.join(os.path.dirname(__file__), "static")]
418
418
419 mathjax_url = Unicode("", config=True,
419 mathjax_url = Unicode("", config=True,
420 help="""The url for MathJax.js."""
420 help="""The url for MathJax.js."""
421 )
421 )
422 def _mathjax_url_default(self):
422 def _mathjax_url_default(self):
423 if not self.enable_mathjax:
423 if not self.enable_mathjax:
424 return u''
424 return u''
425 static_url_prefix = self.webapp_settings.get("static_url_prefix",
425 static_url_prefix = self.webapp_settings.get("static_url_prefix",
426 "/static/")
426 "/static/")
427 try:
427 try:
428 mathjax = filefind(os.path.join('mathjax', 'MathJax.js'), self.static_file_path)
428 mathjax = filefind(os.path.join('mathjax', 'MathJax.js'), self.static_file_path)
429 except IOError:
429 except IOError:
430 if self.certfile:
430 if self.certfile:
431 # HTTPS: load from Rackspace CDN, because SSL certificate requires it
431 # HTTPS: load from Rackspace CDN, because SSL certificate requires it
432 base = u"https://c328740.ssl.cf1.rackcdn.com"
432 base = u"https://c328740.ssl.cf1.rackcdn.com"
433 else:
433 else:
434 base = u"http://cdn.mathjax.org"
434 base = u"http://cdn.mathjax.org"
435
435
436 url = base + u"/mathjax/latest/MathJax.js"
436 url = base + u"/mathjax/latest/MathJax.js"
437 self.log.info("Using MathJax from CDN: %s", url)
437 self.log.info("Using MathJax from CDN: %s", url)
438 return url
438 return url
439 else:
439 else:
440 self.log.info("Using local MathJax from %s" % mathjax)
440 self.log.info("Using local MathJax from %s" % mathjax)
441 return static_url_prefix+u"mathjax/MathJax.js"
441 return static_url_prefix+u"mathjax/MathJax.js"
442
442
443 def _mathjax_url_changed(self, name, old, new):
443 def _mathjax_url_changed(self, name, old, new):
444 if new and not self.enable_mathjax:
444 if new and not self.enable_mathjax:
445 # enable_mathjax=False overrides mathjax_url
445 # enable_mathjax=False overrides mathjax_url
446 self.mathjax_url = u''
446 self.mathjax_url = u''
447 else:
447 else:
448 self.log.info("Using MathJax: %s", new)
448 self.log.info("Using MathJax: %s", new)
449
449
450 notebook_manager_class = DottedObjectName('IPython.frontend.html.notebook.filenbmanager.FileNotebookManager',
450 notebook_manager_class = DottedObjectName('IPython.frontend.html.notebook.filenbmanager.FileNotebookManager',
451 config=True,
451 config=True,
452 help='The notebook manager class to use.')
452 help='The notebook manager class to use.')
453
453
454 def parse_command_line(self, argv=None):
454 def parse_command_line(self, argv=None):
455 super(NotebookApp, self).parse_command_line(argv)
455 super(NotebookApp, self).parse_command_line(argv)
456 if argv is None:
456 if argv is None:
457 argv = sys.argv[1:]
457 argv = sys.argv[1:]
458
458
459 # Scrub frontend-specific flags
459 # Scrub frontend-specific flags
460 self.kernel_argv = swallow_argv(argv, notebook_aliases, notebook_flags)
460 self.kernel_argv = swallow_argv(argv, notebook_aliases, notebook_flags)
461 # Kernel should inherit default config file from frontend
461 # Kernel should inherit default config file from frontend
462 self.kernel_argv.append("--KernelApp.parent_appname='%s'"%self.name)
462 self.kernel_argv.append("--KernelApp.parent_appname='%s'"%self.name)
463
463
464 if self.extra_args:
464 if self.extra_args:
465 f = os.path.abspath(self.extra_args[0])
465 f = os.path.abspath(self.extra_args[0])
466 if os.path.isdir(f):
466 if os.path.isdir(f):
467 nbdir = f
467 nbdir = f
468 else:
468 else:
469 self.file_to_run = f
469 self.file_to_run = f
470 nbdir = os.path.dirname(f)
470 nbdir = os.path.dirname(f)
471 self.config.NotebookManager.notebook_dir = nbdir
471 self.config.NotebookManager.notebook_dir = nbdir
472
472
473 def init_configurables(self):
473 def init_configurables(self):
474 # force Session default to be secure
474 # force Session default to be secure
475 default_secure(self.config)
475 default_secure(self.config)
476 self.kernel_manager = MappingKernelManager(
476 self.kernel_manager = MappingKernelManager(
477 config=self.config, log=self.log, kernel_argv=self.kernel_argv,
477 config=self.config, log=self.log, kernel_argv=self.kernel_argv,
478 connection_dir = self.profile_dir.security_dir,
478 connection_dir = self.profile_dir.security_dir,
479 )
479 )
480 kls = import_item(self.notebook_manager_class)
480 kls = import_item(self.notebook_manager_class)
481 self.notebook_manager = kls(config=self.config, log=self.log)
481 self.notebook_manager = kls(config=self.config, log=self.log)
482 self.notebook_manager.log_info()
482 self.notebook_manager.log_info()
483 self.notebook_manager.load_notebook_names()
483 self.notebook_manager.load_notebook_names()
484 self.cluster_manager = ClusterManager(config=self.config, log=self.log)
484 self.cluster_manager = ClusterManager(config=self.config, log=self.log)
485 self.cluster_manager.update_profiles()
485 self.cluster_manager.update_profiles()
486
486
487 def init_logging(self):
487 def init_logging(self):
488 # This prevents double log messages because tornado use a root logger that
488 # This prevents double log messages because tornado use a root logger that
489 # self.log is a child of. The logging module dipatches log messages to a log
489 # self.log is a child of. The logging module dipatches log messages to a log
490 # and all of its ancenstors until propagate is set to False.
490 # and all of its ancenstors until propagate is set to False.
491 self.log.propagate = False
491 self.log.propagate = False
492
492
493 def init_webapp(self):
493 def init_webapp(self):
494 """initialize tornado webapp and httpserver"""
494 """initialize tornado webapp and httpserver"""
495 self.web_app = NotebookWebApplication(
495 self.web_app = NotebookWebApplication(
496 self, self.kernel_manager, self.notebook_manager,
496 self, self.kernel_manager, self.notebook_manager,
497 self.cluster_manager, self.log,
497 self.cluster_manager, self.log,
498 self.base_project_url, self.webapp_settings
498 self.base_project_url, self.webapp_settings
499 )
499 )
500 if self.certfile:
500 if self.certfile:
501 ssl_options = dict(certfile=self.certfile)
501 ssl_options = dict(certfile=self.certfile)
502 if self.keyfile:
502 if self.keyfile:
503 ssl_options['keyfile'] = self.keyfile
503 ssl_options['keyfile'] = self.keyfile
504 else:
504 else:
505 ssl_options = None
505 ssl_options = None
506 self.web_app.password = self.password
506 self.web_app.password = self.password
507 self.http_server = httpserver.HTTPServer(self.web_app, ssl_options=ssl_options)
507 self.http_server = httpserver.HTTPServer(self.web_app, ssl_options=ssl_options)
508 if not self.ip:
508 if not self.ip:
509 warning = "WARNING: The notebook server is listening on all IP addresses"
509 warning = "WARNING: The notebook server is listening on all IP addresses"
510 if ssl_options is None:
510 if ssl_options is None:
511 self.log.critical(warning + " and not using encryption. This"
511 self.log.critical(warning + " and not using encryption. This"
512 "is not recommended.")
512 "is not recommended.")
513 if not self.password and not self.read_only:
513 if not self.password and not self.read_only:
514 self.log.critical(warning + "and not using authentication."
514 self.log.critical(warning + "and not using authentication."
515 "This is highly insecure and not recommended.")
515 "This is highly insecure and not recommended.")
516 success = None
516 success = None
517 for port in random_ports(self.port, self.port_retries+1):
517 for port in random_ports(self.port, self.port_retries+1):
518 try:
518 try:
519 self.http_server.listen(port, self.ip)
519 self.http_server.listen(port, self.ip)
520 except socket.error as e:
520 except socket.error as e:
521 if e.errno != errno.EADDRINUSE:
521 if e.errno != errno.EADDRINUSE:
522 raise
522 raise
523 self.log.info('The port %i is already in use, trying another random port.' % port)
523 self.log.info('The port %i is already in use, trying another random port.' % port)
524 else:
524 else:
525 self.port = port
525 self.port = port
526 success = True
526 success = True
527 break
527 break
528 if not success:
528 if not success:
529 self.log.critical('ERROR: the notebook server could not be started because '
529 self.log.critical('ERROR: the notebook server could not be started because '
530 'no available port could be found.')
530 'no available port could be found.')
531 self.exit(1)
531 self.exit(1)
532
532
533 def init_signal(self):
533 def init_signal(self):
534 # FIXME: remove this check when pyzmq dependency is >= 2.1.11
534 # FIXME: remove this check when pyzmq dependency is >= 2.1.11
535 # safely extract zmq version info:
535 # safely extract zmq version info:
536 try:
536 try:
537 zmq_v = zmq.pyzmq_version_info()
537 zmq_v = zmq.pyzmq_version_info()
538 except AttributeError:
538 except AttributeError:
539 zmq_v = [ int(n) for n in re.findall(r'\d+', zmq.__version__) ]
539 zmq_v = [ int(n) for n in re.findall(r'\d+', zmq.__version__) ]
540 if 'dev' in zmq.__version__:
540 if 'dev' in zmq.__version__:
541 zmq_v.append(999)
541 zmq_v.append(999)
542 zmq_v = tuple(zmq_v)
542 zmq_v = tuple(zmq_v)
543 if zmq_v >= (2,1,9) and not sys.platform.startswith('win'):
543 if zmq_v >= (2,1,9) and not sys.platform.startswith('win'):
544 # This won't work with 2.1.7 and
544 # This won't work with 2.1.7 and
545 # 2.1.9-10 will log ugly 'Interrupted system call' messages,
545 # 2.1.9-10 will log ugly 'Interrupted system call' messages,
546 # but it will work
546 # but it will work
547 signal.signal(signal.SIGINT, self._handle_sigint)
547 signal.signal(signal.SIGINT, self._handle_sigint)
548 signal.signal(signal.SIGTERM, self._signal_stop)
548 signal.signal(signal.SIGTERM, self._signal_stop)
549
549
550 def _handle_sigint(self, sig, frame):
550 def _handle_sigint(self, sig, frame):
551 """SIGINT handler spawns confirmation dialog"""
551 """SIGINT handler spawns confirmation dialog"""
552 # register more forceful signal handler for ^C^C case
552 # register more forceful signal handler for ^C^C case
553 signal.signal(signal.SIGINT, self._signal_stop)
553 signal.signal(signal.SIGINT, self._signal_stop)
554 # request confirmation dialog in bg thread, to avoid
554 # request confirmation dialog in bg thread, to avoid
555 # blocking the App
555 # blocking the App
556 thread = threading.Thread(target=self._confirm_exit)
556 thread = threading.Thread(target=self._confirm_exit)
557 thread.daemon = True
557 thread.daemon = True
558 thread.start()
558 thread.start()
559
559
560 def _restore_sigint_handler(self):
560 def _restore_sigint_handler(self):
561 """callback for restoring original SIGINT handler"""
561 """callback for restoring original SIGINT handler"""
562 signal.signal(signal.SIGINT, self._handle_sigint)
562 signal.signal(signal.SIGINT, self._handle_sigint)
563
563
564 def _confirm_exit(self):
564 def _confirm_exit(self):
565 """confirm shutdown on ^C
565 """confirm shutdown on ^C
566
566
567 A second ^C, or answering 'y' within 5s will cause shutdown,
567 A second ^C, or answering 'y' within 5s will cause shutdown,
568 otherwise original SIGINT handler will be restored.
568 otherwise original SIGINT handler will be restored.
569
569
570 This doesn't work on Windows.
570 This doesn't work on Windows.
571 """
571 """
572 # FIXME: remove this delay when pyzmq dependency is >= 2.1.11
572 # FIXME: remove this delay when pyzmq dependency is >= 2.1.11
573 time.sleep(0.1)
573 time.sleep(0.1)
574 sys.stdout.write("Shutdown Notebook Server (y/[n])? ")
574 sys.stdout.write("Shutdown Notebook Server (y/[n])? ")
575 sys.stdout.flush()
575 sys.stdout.flush()
576 r,w,x = select.select([sys.stdin], [], [], 5)
576 r,w,x = select.select([sys.stdin], [], [], 5)
577 if r:
577 if r:
578 line = sys.stdin.readline()
578 line = sys.stdin.readline()
579 if line.lower().startswith('y'):
579 if line.lower().startswith('y'):
580 self.log.critical("Shutdown confirmed")
580 self.log.critical("Shutdown confirmed")
581 ioloop.IOLoop.instance().stop()
581 ioloop.IOLoop.instance().stop()
582 return
582 return
583 else:
583 else:
584 print "No answer for 5s:",
584 print "No answer for 5s:",
585 print "resuming operation..."
585 print "resuming operation..."
586 # no answer, or answer is no:
586 # no answer, or answer is no:
587 # set it back to original SIGINT handler
587 # set it back to original SIGINT handler
588 # use IOLoop.add_callback because signal.signal must be called
588 # use IOLoop.add_callback because signal.signal must be called
589 # from main thread
589 # from main thread
590 ioloop.IOLoop.instance().add_callback(self._restore_sigint_handler)
590 ioloop.IOLoop.instance().add_callback(self._restore_sigint_handler)
591
591
592 def _signal_stop(self, sig, frame):
592 def _signal_stop(self, sig, frame):
593 self.log.critical("received signal %s, stopping", sig)
593 self.log.critical("received signal %s, stopping", sig)
594 ioloop.IOLoop.instance().stop()
594 ioloop.IOLoop.instance().stop()
595
595
596 @catch_config_error
596 @catch_config_error
597 def initialize(self, argv=None):
597 def initialize(self, argv=None):
598 self.init_logging()
598 self.init_logging()
599 super(NotebookApp, self).initialize(argv)
599 super(NotebookApp, self).initialize(argv)
600 self.init_configurables()
600 self.init_configurables()
601 self.init_webapp()
601 self.init_webapp()
602 self.init_signal()
602 self.init_signal()
603
603
604 def cleanup_kernels(self):
604 def cleanup_kernels(self):
605 """Shutdown all kernels.
605 """Shutdown all kernels.
606
606
607 The kernels will shutdown themselves when this process no longer exists,
607 The kernels will shutdown themselves when this process no longer exists,
608 but explicit shutdown allows the KernelManagers to cleanup the connection files.
608 but explicit shutdown allows the KernelManagers to cleanup the connection files.
609 """
609 """
610 self.log.info('Shutting down kernels')
610 self.log.info('Shutting down kernels')
611 self.kernel_manager.shutdown_all()
611 self.kernel_manager.shutdown_all()
612
612
613 def start(self):
613 def start(self):
614 ip = self.ip if self.ip else '[all ip addresses on your system]'
614 ip = self.ip if self.ip else '[all ip addresses on your system]'
615 proto = 'https' if self.certfile else 'http'
615 proto = 'https' if self.certfile else 'http'
616 info = self.log.info
616 info = self.log.info
617 info("The IPython Notebook is running at: %s://%s:%i%s" %
617 info("The IPython Notebook is running at: %s://%s:%i%s" %
618 (proto, ip, self.port,self.base_project_url) )
618 (proto, ip, self.port,self.base_project_url) )
619 info("Use Control-C to stop this server and shut down all kernels.")
619 info("Use Control-C to stop this server and shut down all kernels.")
620
620
621 if self.open_browser or self.file_to_run:
621 if self.open_browser or self.file_to_run:
622 ip = self.ip or '127.0.0.1'
622 ip = self.ip or '127.0.0.1'
623 try:
623 try:
624 browser = webbrowser.get(self.browser or None)
624 browser = webbrowser.get(self.browser or None)
625 except webbrowser.Error as e:
625 except webbrowser.Error as e:
626 self.log.warn('No web browser found: %s.' % e)
626 self.log.warn('No web browser found: %s.' % e)
627 browser = None
627 browser = None
628
628
629 if self.file_to_run:
629 if self.file_to_run:
630 name, _ = os.path.splitext(os.path.basename(self.file_to_run))
630 name, _ = os.path.splitext(os.path.basename(self.file_to_run))
631 url = self.notebook_manager.rev_mapping.get(name, '')
631 url = self.notebook_manager.rev_mapping.get(name, '')
632 else:
632 else:
633 url = ''
633 url = ''
634 if browser:
634 if browser:
635 b = lambda : browser.open("%s://%s:%i%s%s" % (proto, ip,
635 b = lambda : browser.open("%s://%s:%i%s%s" % (proto, ip,
636 self.port, self.base_project_url, url), new=2)
636 self.port, self.base_project_url, url), new=2)
637 threading.Thread(target=b).start()
637 threading.Thread(target=b).start()
638 try:
638 try:
639 ioloop.IOLoop.instance().start()
639 ioloop.IOLoop.instance().start()
640 except KeyboardInterrupt:
640 except KeyboardInterrupt:
641 info("Interrupted...")
641 info("Interrupted...")
642 finally:
642 finally:
643 self.cleanup_kernels()
643 self.cleanup_kernels()
644
644
645
645
646 #-----------------------------------------------------------------------------
646 #-----------------------------------------------------------------------------
647 # Main entry point
647 # Main entry point
648 #-----------------------------------------------------------------------------
648 #-----------------------------------------------------------------------------
649
649
650 def launch_new_instance():
650 def launch_new_instance():
651 app = NotebookApp.instance()
651 app = NotebookApp.instance()
652 app.initialize()
652 app.initialize()
653 app.start()
653 app.start()
654
654
@@ -1,7 +1,7 b''
1 Js files in this fomder from Tag 1.3.1 sha:68297d7e3850b5eedac825a202eb64f9c80ce183
1 Js files in this fomder from Tag 1.3.1 sha:68297d7e3850b5eedac825a202eb64f9c80ce183
2 from
2 from
3 https://github.com/cloudhead/less.js
3 https://github.com/cloudhead/less.js
4
4
5 /dists/less-1.3.1.js
5 /dists/less-1.3.1.js
6 /dists/less-1.3.1.min.js
6 /dists/less-1.3.1.min.js
7
7
@@ -1,97 +1,97 b''
1
1
2 /* Flexible box model classes */
2 /* Flexible box model classes */
3 /* Taken from Alex Russell http://infrequently.org/2009/08/css-3-progress/ */
3 /* Taken from Alex Russell http://infrequently.org/2009/08/css-3-progress/ */
4
4
5 .hbox {
5 .hbox {
6 display: -webkit-box;
6 display: -webkit-box;
7 -webkit-box-orient: horizontal;
7 -webkit-box-orient: horizontal;
8 -webkit-box-align: stretch;
8 -webkit-box-align: stretch;
9
9
10 display: -moz-box;
10 display: -moz-box;
11 -moz-box-orient: horizontal;
11 -moz-box-orient: horizontal;
12 -moz-box-align: stretch;
12 -moz-box-align: stretch;
13
13
14 display: box;
14 display: box;
15 box-orient: horizontal;
15 box-orient: horizontal;
16 box-align: stretch;
16 box-align: stretch;
17 }
17 }
18
18
19 .hbox > * {
19 .hbox > * {
20 -webkit-box-flex: 0;
20 -webkit-box-flex: 0;
21 -moz-box-flex: 0;
21 -moz-box-flex: 0;
22 box-flex: 0;
22 box-flex: 0;
23 }
23 }
24
24
25 .vbox {
25 .vbox {
26 display: -webkit-box;
26 display: -webkit-box;
27 -webkit-box-orient: vertical;
27 -webkit-box-orient: vertical;
28 -webkit-box-align: stretch;
28 -webkit-box-align: stretch;
29
29
30 display: -moz-box;
30 display: -moz-box;
31 -moz-box-orient: vertical;
31 -moz-box-orient: vertical;
32 -moz-box-align: stretch;
32 -moz-box-align: stretch;
33
33
34 display: box;
34 display: box;
35 box-orient: vertical;
35 box-orient: vertical;
36 box-align: stretch;
36 box-align: stretch;
37 }
37 }
38
38
39 .vbox > * {
39 .vbox > * {
40 -webkit-box-flex: 0;
40 -webkit-box-flex: 0;
41 -moz-box-flex: 0;
41 -moz-box-flex: 0;
42 box-flex: 0;
42 box-flex: 0;
43 }
43 }
44
44
45 .reverse {
45 .reverse {
46 -webkit-box-direction: reverse;
46 -webkit-box-direction: reverse;
47 -moz-box-direction: reverse;
47 -moz-box-direction: reverse;
48 box-direction: reverse;
48 box-direction: reverse;
49 }
49 }
50
50
51 .box-flex0 {
51 .box-flex0 {
52 -webkit-box-flex: 0;
52 -webkit-box-flex: 0;
53 -moz-box-flex: 0;
53 -moz-box-flex: 0;
54 box-flex: 0;
54 box-flex: 0;
55 }
55 }
56
56
57 .box-flex1, .box-flex {
57 .box-flex1, .box-flex {
58 -webkit-box-flex: 1;
58 -webkit-box-flex: 1;
59 -moz-box-flex: 1;
59 -moz-box-flex: 1;
60 box-flex: 1;
60 box-flex: 1;
61 }
61 }
62
62
63 .box-flex2 {
63 .box-flex2 {
64 -webkit-box-flex: 2;
64 -webkit-box-flex: 2;
65 -moz-box-flex: 2;
65 -moz-box-flex: 2;
66 box-flex: 2;
66 box-flex: 2;
67 }
67 }
68
68
69 .box-group1 {
69 .box-group1 {
70 -webkit-box-flex-group: 1;
70 -webkit-box-flex-group: 1;
71 -moz-box-flex-group: 1;
71 -moz-box-flex-group: 1;
72 box-flex-group: 1;
72 box-flex-group: 1;
73 }
73 }
74
74
75 .box-group2 {
75 .box-group2 {
76 -webkit-box-flex-group: 2;
76 -webkit-box-flex-group: 2;
77 -moz-box-flex-group: 2;
77 -moz-box-flex-group: 2;
78 box-flex-group: 2;
78 box-flex-group: 2;
79 }
79 }
80
80
81 .start {
81 .start {
82 -webkit-box-pack: start;
82 -webkit-box-pack: start;
83 -moz-box-pack: start;
83 -moz-box-pack: start;
84 box-pack: start;
84 box-pack: start;
85 }
85 }
86
86
87 .end {
87 .end {
88 -webkit-box-pack: end;
88 -webkit-box-pack: end;
89 -moz-box-pack: end;
89 -moz-box-pack: end;
90 box-pack: end;
90 box-pack: end;
91 }
91 }
92
92
93 .center {
93 .center {
94 -webkit-box-pack: center;
94 -webkit-box-pack: center;
95 -moz-box-pack: center;
95 -moz-box-pack: center;
96 box-pack: center;
96 box-pack: center;
97 }
97 }
@@ -1,455 +1,455 b''
1 /**
1 /**
2 * Primary styles
2 * Primary styles
3 *
3 *
4 * Author: IPython Development Team
4 * Author: IPython Development Team
5 */
5 */
6
6
7 @import "variables.less";
7 @import "variables.less";
8
8
9 body {
9 body {
10 overflow: hidden;
10 overflow: hidden;
11 background-color:@notebook_background;
11 background-color:@notebook_background;
12 }
12 }
13
13
14 blockquote {
14 blockquote {
15 border-left: 4px solid #DDD;
15 border-left: 4px solid #DDD;
16 padding: 0 15px;
16 padding: 0 15px;
17 color: #777;
17 color: #777;
18 }
18 }
19
19
20 span#save_widget {
20 span#save_widget {
21 padding: 5px;
21 padding: 5px;
22 margin: 0px 0px 0px 300px;
22 margin: 0px 0px 0px 300px;
23 display:inline-block;
23 display:inline-block;
24 }
24 }
25
25
26 span#notebook_name {
26 span#notebook_name {
27 height: 1em;
27 height: 1em;
28 line-height: 1em;
28 line-height: 1em;
29 padding: 3px;
29 padding: 3px;
30 border: none;
30 border: none;
31 font-size: 146.5%;
31 font-size: 146.5%;
32 }
32 }
33
33
34
34
35 .ui-menubar-item .ui-button .ui-button-text {
35 .ui-menubar-item .ui-button .ui-button-text {
36 padding: 0.4em 1.0em;
36 padding: 0.4em 1.0em;
37 font-size: 100%;
37 font-size: 100%;
38 }
38 }
39
39
40 .ui-menu {
40 .ui-menu {
41 -moz-box-shadow: 0px 6px 10px -1px #adadad;
41 -moz-box-shadow: 0px 6px 10px -1px #adadad;
42 -webkit-box-shadow: 0px 6px 10px -1px #adadad;
42 -webkit-box-shadow: 0px 6px 10px -1px #adadad;
43 box-shadow: 0px 6px 10px -1px #adadad;
43 box-shadow: 0px 6px 10px -1px #adadad;
44 }
44 }
45
45
46 .ui-menu .ui-menu-item a {
46 .ui-menu .ui-menu-item a {
47 border: 1px solid transparent;
47 border: 1px solid transparent;
48 padding: 2px 1.6em;
48 padding: 2px 1.6em;
49 }
49 }
50
50
51 .ui-menu .ui-menu-item a.ui-state-focus {
51 .ui-menu .ui-menu-item a.ui-state-focus {
52 margin: 0;
52 margin: 0;
53 }
53 }
54
54
55 .ui-menu hr {
55 .ui-menu hr {
56 margin: 0.3em 0;
56 margin: 0.3em 0;
57 }
57 }
58
58
59 #menubar_container {
59 #menubar_container {
60 position: relative;
60 position: relative;
61 }
61 }
62
62
63 #notification_area {
63 #notification_area {
64 position: absolute;
64 position: absolute;
65 right: 0px;
65 right: 0px;
66 top: 0px;
66 top: 0px;
67 height: 25px;
67 height: 25px;
68 padding: 3px 0px;
68 padding: 3px 0px;
69 padding-right: 3px;
69 padding-right: 3px;
70 z-index: 10;
70 z-index: 10;
71 }
71 }
72
72
73 .notification_widget{
73 .notification_widget{
74 float : right;
74 float : right;
75 right: 0px;
75 right: 0px;
76 top: 1px;
76 top: 1px;
77 height: 25px;
77 height: 25px;
78 padding: 3px 6px;
78 padding: 3px 6px;
79 z-index: 10;
79 z-index: 10;
80 }
80 }
81
81
82 .toolbar {
82 .toolbar {
83 padding: 3px 15px;
83 padding: 3px 15px;
84 border-bottom: @borderwidth @border_color solid;
84 border-bottom: @borderwidth @border_color solid;
85 }
85 }
86
86
87 #maintoolbar > select, #maintoolbar label {
87 #maintoolbar > select, #maintoolbar label {
88 height : 23px;
88 height : 23px;
89 vertical-align: top;
89 vertical-align: top;
90 margin-right:2px;
90 margin-right:2px;
91 margin-bottom:0;
91 margin-bottom:0;
92 display: inline;
92 display: inline;
93 }
93 }
94
94
95 #cell_type {
95 #cell_type {
96 font-size: 85%;
96 font-size: 85%;
97 margin-left:0.3em;
97 margin-left:0.3em;
98 margin-right:0.3em;
98 margin-right:0.3em;
99
99
100 }
100 }
101
101
102
102
103 #ipython-main-app {
103 #ipython-main-app {
104 width: 100%;
104 width: 100%;
105 position: relative;
105 position: relative;
106 }
106 }
107
107
108 span#quick_help_area {
108 span#quick_help_area {
109 position: static;
109 position: static;
110 padding: 5px 0px;
110 padding: 5px 0px;
111 margin: 0px 0px 0px 0px;
111 margin: 0px 0px 0px 0px;
112 }
112 }
113
113
114 .help_string {
114 .help_string {
115 float: right;
115 float: right;
116 width: 170px;
116 width: 170px;
117 padding: 0px 5px;
117 padding: 0px 5px;
118 text-align: left;
118 text-align: left;
119 font-size: 85%;
119 font-size: 85%;
120 }
120 }
121
121
122 .help_string_label {
122 .help_string_label {
123 float: right;
123 float: right;
124 font-size: 85%;
124 font-size: 85%;
125 }
125 }
126
126
127 div#notebook_panel {
127 div#notebook_panel {
128 margin: 0px 0px 0px 0px;
128 margin: 0px 0px 0px 0px;
129 padding: 0px;
129 padding: 0px;
130 }
130 }
131
131
132 div#notebook {
132 div#notebook {
133 overflow-y: scroll;
133 overflow-y: scroll;
134 overflow-x: auto;
134 overflow-x: auto;
135 width: 100%;
135 width: 100%;
136 /* This spaces the cell away from the edge of the notebook area */
136 /* This spaces the cell away from the edge of the notebook area */
137 padding: 5px 5px 15px 5px;
137 padding: 5px 5px 15px 5px;
138 margin: 0px;
138 margin: 0px;
139 }
139 }
140
140
141 div#pager_splitter {
141 div#pager_splitter {
142 height: 8px;
142 height: 8px;
143 }
143 }
144
144
145 #pager_container {
145 #pager_container {
146 position : relative;
146 position : relative;
147 }
147 }
148
148
149 div#pager {
149 div#pager {
150 padding: 15px;
150 padding: 15px;
151 overflow: auto;
151 overflow: auto;
152 display: none;
152 display: none;
153 }
153 }
154
154
155 div.ui-widget-content {
155 div.ui-widget-content {
156 border: 1px solid @border_color;
156 border: 1px solid @border_color;
157 outline: none;
157 outline: none;
158 }
158 }
159
159
160 .cell {
160 .cell {
161 border: 1px solid transparent;
161 border: 1px solid transparent;
162
162
163 &.selected {
163 &.selected {
164 .corner-all;
164 .corner-all;
165 background-color:@cell_selected_background;
165 background-color:@cell_selected_background;
166 border : thin @border_color solid;
166 border : thin @border_color solid;
167 }
167 }
168 }
168 }
169
169
170 div.cell {
170 div.cell {
171 width: 100%;
171 width: 100%;
172 padding: 5px 5px 5px 0px;
172 padding: 5px 5px 5px 0px;
173 /* This acts as a spacer between cells, that is outside the border */
173 /* This acts as a spacer between cells, that is outside the border */
174 margin: 2px 0px 2px 0px;
174 margin: 2px 0px 2px 0px;
175 outline: none;
175 outline: none;
176 }
176 }
177
177
178 div.code_cell {
178 div.code_cell {
179 }
179 }
180
180
181 /* any special styling for code cells that are currently running goes here */
181 /* any special styling for code cells that are currently running goes here */
182 div.code_cell.running {
182 div.code_cell.running {
183 }
183 }
184
184
185 div.prompt {
185 div.prompt {
186 /* This needs to be wide enough for 3 digit prompt numbers: In[100]: */
186 /* This needs to be wide enough for 3 digit prompt numbers: In[100]: */
187 width: 11ex;
187 width: 11ex;
188 /* This 0.4em is tuned to match the padding on the CodeMirror editor. */
188 /* This 0.4em is tuned to match the padding on the CodeMirror editor. */
189 padding: 0.4em;
189 padding: 0.4em;
190 margin: 0px;
190 margin: 0px;
191 font-family: monospace;
191 font-family: monospace;
192 text-align: right;
192 text-align: right;
193 /* This has to match that of the the CodeMirror class line-height below */
193 /* This has to match that of the the CodeMirror class line-height below */
194 line-height: 1.231;
194 line-height: 1.231;
195 }
195 }
196
196
197 div.input {
197 div.input {
198 page-break-inside: avoid;
198 page-break-inside: avoid;
199 }
199 }
200
200
201 /* input_area and input_prompt must match in top border and margin for alignment */
201 /* input_area and input_prompt must match in top border and margin for alignment */
202 div.input_area {
202 div.input_area {
203 /*color: @fontBaseColor;*/
203 /*color: @fontBaseColor;*/
204 border: 1px solid @border_color;
204 border: 1px solid @border_color;
205 .corner-all;
205 .corner-all;
206 background: @cell_background;
206 background: @cell_background;
207 }
207 }
208
208
209 div.input_prompt {
209 div.input_prompt {
210 color: navy;
210 color: navy;
211 border-top: 1px solid transparent;
211 border-top: 1px solid transparent;
212 }
212 }
213
213
214 div.output_wrapper {
214 div.output_wrapper {
215 /* This is a spacer between the input and output of each cell */
215 /* This is a spacer between the input and output of each cell */
216 margin-top: 5px;
216 margin-top: 5px;
217 margin-left: 5px;
217 margin-left: 5px;
218 /* FF needs explicit width to stretch */
218 /* FF needs explicit width to stretch */
219 width: 100%;
219 width: 100%;
220 /* this position must be relative to enable descendents to be absolute within it */
220 /* this position must be relative to enable descendents to be absolute within it */
221 position: relative;
221 position: relative;
222 }
222 }
223
223
224 /* class for the output area when it should be height-limited */
224 /* class for the output area when it should be height-limited */
225 div.output_scroll {
225 div.output_scroll {
226 /* ideally, this would be max-height, but FF barfs all over that */
226 /* ideally, this would be max-height, but FF barfs all over that */
227 height: 24em;
227 height: 24em;
228 /* FF needs this *and the wrapper* to specify full width, or it will shrinkwrap */
228 /* FF needs this *and the wrapper* to specify full width, or it will shrinkwrap */
229 width: 100%;
229 width: 100%;
230
230
231 overflow: auto;
231 overflow: auto;
232 .corner-all;
232 .corner-all;
233 box-shadow: inset 0 2px 8px rgba(0, 0, 0, .8);
233 box-shadow: inset 0 2px 8px rgba(0, 0, 0, .8);
234 }
234 }
235
235
236 /* output div while it is collapsed */
236 /* output div while it is collapsed */
237 div.output_collapsed {
237 div.output_collapsed {
238 margin-right: 5px;
238 margin-right: 5px;
239 }
239 }
240
240
241 div.out_prompt_overlay {
241 div.out_prompt_overlay {
242 height: 100%;
242 height: 100%;
243 padding: 0px;
243 padding: 0px;
244 position: absolute;
244 position: absolute;
245 .corner-all;
245 .corner-all;
246 }
246 }
247
247
248 div.out_prompt_overlay:hover {
248 div.out_prompt_overlay:hover {
249 /* use inner shadow to get border that is computed the same on WebKit/FF */
249 /* use inner shadow to get border that is computed the same on WebKit/FF */
250 box-shadow: inset 0 0 1px #000;
250 box-shadow: inset 0 0 1px #000;
251 background: rgba(240, 240, 240, 0.5);
251 background: rgba(240, 240, 240, 0.5);
252 }
252 }
253
253
254 div.output_prompt {
254 div.output_prompt {
255 color: darkred;
255 color: darkred;
256 /* 5px right shift to account for margin in parent container */
256 /* 5px right shift to account for margin in parent container */
257 margin: 0 5px 0 -5px;
257 margin: 0 5px 0 -5px;
258 }
258 }
259
259
260 /* This class is the outer container of all output sections. */
260 /* This class is the outer container of all output sections. */
261 div.output_area {
261 div.output_area {
262 padding: 0px;
262 padding: 0px;
263 page-break-inside: avoid;
263 page-break-inside: avoid;
264 }
264 }
265
265
266
266
267 /* This is needed to protect the pre formating from global settings such
267 /* This is needed to protect the pre formating from global settings such
268 as that of bootstrap */
268 as that of bootstrap */
269 div.output_area pre {
269 div.output_area pre {
270 font-family: monospace;
270 font-family: monospace;
271 margin: 0;
271 margin: 0;
272 padding: 0;
272 padding: 0;
273 border: 0;
273 border: 0;
274 font-size: 100%;
274 font-size: 100%;
275 font: inherit;
275 font: inherit;
276 vertical-align: baseline;
276 vertical-align: baseline;
277 color: black;
277 color: black;
278 background-color: white;
278 background-color: white;
279 }
279 }
280
280
281 /* This class is for the output subarea inside the output_area and after
281 /* This class is for the output subarea inside the output_area and after
282 the prompt div. */
282 the prompt div. */
283 div.output_subarea {
283 div.output_subarea {
284 padding: 0.44em 0.4em 0.4em 1px;
284 padding: 0.44em 0.4em 0.4em 1px;
285 }
285 }
286
286
287 /* The rest of the output_* classes are for special styling of the different
287 /* The rest of the output_* classes are for special styling of the different
288 output types */
288 output types */
289
289
290 /* all text output has this class: */
290 /* all text output has this class: */
291 div.output_text {
291 div.output_text {
292 text-align: left;
292 text-align: left;
293 color: @fontBaseColor;
293 color: @fontBaseColor;
294 font-family: monospace;
294 font-family: monospace;
295 /* This has to match that of the the CodeMirror class line-height below */
295 /* This has to match that of the the CodeMirror class line-height below */
296 line-height: 1.231;
296 line-height: 1.231;
297 }
297 }
298
298
299 /* stdout/stderr are 'text' as well as 'stream', but pyout/pyerr are *not* streams */
299 /* stdout/stderr are 'text' as well as 'stream', but pyout/pyerr are *not* streams */
300 div.output_stream {
300 div.output_stream {
301 padding-top: 0.0em;
301 padding-top: 0.0em;
302 padding-bottom: 0.0em;
302 padding-bottom: 0.0em;
303 }
303 }
304 div.output_stdout {
304 div.output_stdout {
305 }
305 }
306 div.output_stderr {
306 div.output_stderr {
307 background: #fdd; /* very light red background for stderr */
307 background: #fdd; /* very light red background for stderr */
308 }
308 }
309
309
310 div.output_latex {
310 div.output_latex {
311 text-align: left;
311 text-align: left;
312 }
312 }
313
313
314 div.output_html {
314 div.output_html {
315 }
315 }
316
316
317 div.output_png {
317 div.output_png {
318 }
318 }
319
319
320 div.output_jpeg {
320 div.output_jpeg {
321 }
321 }
322
322
323 div.text_cell {
323 div.text_cell {
324 padding: 5px 5px 5px 5px;
324 padding: 5px 5px 5px 5px;
325 }
325 }
326
326
327 div.text_cell_input {
327 div.text_cell_input {
328 color: @fontBaseColor;
328 color: @fontBaseColor;
329 border: 1px solid @border_color;
329 border: 1px solid @border_color;
330 .corner-all;
330 .corner-all;
331 background: @cell_background;
331 background: @cell_background;
332 }
332 }
333
333
334 div.text_cell_render {
334 div.text_cell_render {
335 /*font-family: "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;*/
335 /*font-family: "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;*/
336 outline: none;
336 outline: none;
337 resize: none;
337 resize: none;
338 width: inherit;
338 width: inherit;
339 border-style: none;
339 border-style: none;
340 padding: 5px;
340 padding: 5px;
341 color: @fontBaseColor;
341 color: @fontBaseColor;
342 }
342 }
343
343
344 /* The following gets added to the <head> if it is detected that the user has a
344 /* The following gets added to the <head> if it is detected that the user has a
345 * monospace font with inconsistent normal/bold/italic height. See
345 * monospace font with inconsistent normal/bold/italic height. See
346 * notebookmain.js. Such fonts will have keywords vertically offset with
346 * notebookmain.js. Such fonts will have keywords vertically offset with
347 * respect to the rest of the text. The user should select a better font.
347 * respect to the rest of the text. The user should select a better font.
348 * See: https://github.com/ipython/ipython/issues/1503
348 * See: https://github.com/ipython/ipython/issues/1503
349 *
349 *
350 * .CodeMirror span {
350 * .CodeMirror span {
351 * vertical-align: bottom;
351 * vertical-align: bottom;
352 * }
352 * }
353 */
353 */
354
354
355 .CodeMirror {
355 .CodeMirror {
356 line-height: 1.231; /* Changed from 1em to our global default */
356 line-height: 1.231; /* Changed from 1em to our global default */
357 }
357 }
358
358
359 .CodeMirror-scroll {
359 .CodeMirror-scroll {
360 height: auto; /* Changed to auto to autogrow */
360 height: auto; /* Changed to auto to autogrow */
361 /* The CodeMirror docs are a bit fuzzy on if overflow-y should be hidden or visible.*/
361 /* The CodeMirror docs are a bit fuzzy on if overflow-y should be hidden or visible.*/
362 /* We have found that if it is visible, vertical scrollbars appear with font size changes.*/
362 /* We have found that if it is visible, vertical scrollbars appear with font size changes.*/
363 overflow-y: hidden;
363 overflow-y: hidden;
364 overflow-x: auto; /* Changed from auto to remove scrollbar */
364 overflow-x: auto; /* Changed from auto to remove scrollbar */
365 }
365 }
366
366
367 /* CSS font colors for translated ANSI colors. */
367 /* CSS font colors for translated ANSI colors. */
368
368
369
369
370 .ansiblack {color: @fontBaseColor;}
370 .ansiblack {color: @fontBaseColor;}
371 .ansired {color: darkred;}
371 .ansired {color: darkred;}
372 .ansigreen {color: darkgreen;}
372 .ansigreen {color: darkgreen;}
373 .ansiyellow {color: brown;}
373 .ansiyellow {color: brown;}
374 .ansiblue {color: darkblue;}
374 .ansiblue {color: darkblue;}
375 .ansipurple {color: darkviolet;}
375 .ansipurple {color: darkviolet;}
376 .ansicyan {color: steelblue;}
376 .ansicyan {color: steelblue;}
377 .ansigrey {color: grey;}
377 .ansigrey {color: grey;}
378 .ansibold {font-weight: bold;}
378 .ansibold {font-weight: bold;}
379
379
380 .completions {
380 .completions {
381 position: absolute;
381 position: absolute;
382 z-index: 10;
382 z-index: 10;
383 overflow: hidden;
383 overflow: hidden;
384 border: 1px solid @border_color;
384 border: 1px solid @border_color;
385 }
385 }
386
386
387 .completions select {
387 .completions select {
388 background: white;
388 background: white;
389 outline: none;
389 outline: none;
390 border: none;
390 border: none;
391 padding: 0px;
391 padding: 0px;
392 margin: 0px;
392 margin: 0px;
393 overflow: auto;
393 overflow: auto;
394 font-family: monospace;
394 font-family: monospace;
395 }
395 }
396
396
397 option.context {
397 option.context {
398 background-color: #DEF7FF;
398 background-color: #DEF7FF;
399 }
399 }
400 option.introspection {
400 option.introspection {
401 background-color: #EBF4EB;
401 background-color: #EBF4EB;
402 }
402 }
403
403
404 /*fixed part of the completion*/
404 /*fixed part of the completion*/
405 .completions p b {
405 .completions p b {
406 font-weight:bold;
406 font-weight:bold;
407 }
407 }
408
408
409 .completions p {
409 .completions p {
410 background: #DDF;
410 background: #DDF;
411 /*outline: none;
411 /*outline: none;
412 padding: 0px;*/
412 padding: 0px;*/
413 border-bottom: black solid 1px;
413 border-bottom: black solid 1px;
414 padding: 1px;
414 padding: 1px;
415 font-family: monospace;
415 font-family: monospace;
416 }
416 }
417
417
418 pre.dialog {
418 pre.dialog {
419 background-color: @cell_background;
419 background-color: @cell_background;
420 border: 1px solid #ddd;
420 border: 1px solid #ddd;
421 .corner-all;
421 .corner-all;
422 padding: 0.4em;
422 padding: 0.4em;
423 padding-left: 2em;
423 padding-left: 2em;
424 }
424 }
425
425
426 p.dialog {
426 p.dialog {
427 padding : 0.2em;
427 padding : 0.2em;
428 }
428 }
429
429
430 .shortcut_key {
430 .shortcut_key {
431 display: inline-block;
431 display: inline-block;
432 width: 15ex;
432 width: 15ex;
433 text-align: right;
433 text-align: right;
434 font-family: monospace;
434 font-family: monospace;
435 }
435 }
436
436
437 .shortcut_descr {
437 .shortcut_descr {
438 }
438 }
439
439
440 /* Word-wrap output correctly. This is the CSS3 spelling, though Firefox seems
440 /* Word-wrap output correctly. This is the CSS3 spelling, though Firefox seems
441 to not honor it correctly. Webkit browsers (Chrome, rekonq, Safari) do.
441 to not honor it correctly. Webkit browsers (Chrome, rekonq, Safari) do.
442 */
442 */
443 pre, code, kbd, samp { white-space: pre-wrap; }
443 pre, code, kbd, samp { white-space: pre-wrap; }
444
444
445 #fonttest {
445 #fonttest {
446 font-family: monospace;
446 font-family: monospace;
447 }
447 }
448
448
449 .js-error {
449 .js-error {
450 color: darkred;
450 color: darkred;
451 }
451 }
452
452
453
453
454
454
455
455
@@ -1,68 +1,68 b''
1 .rendered_html {color: black;}
1 .rendered_html {color: black;}
2 .rendered_html em {font-style: italic;}
2 .rendered_html em {font-style: italic;}
3 .rendered_html strong {font-weight: bold;}
3 .rendered_html strong {font-weight: bold;}
4 .rendered_html u {text-decoration: underline;}
4 .rendered_html u {text-decoration: underline;}
5 .rendered_html :link { text-decoration: underline }
5 .rendered_html :link { text-decoration: underline }
6 .rendered_html :visited { text-decoration: underline }
6 .rendered_html :visited { text-decoration: underline }
7 .rendered_html h1 {font-size: 197%; margin: .65em 0; font-weight: bold;}
7 .rendered_html h1 {font-size: 197%; margin: .65em 0; font-weight: bold;}
8 .rendered_html h2 {font-size: 153.9%; margin: .75em 0; font-weight: bold;}
8 .rendered_html h2 {font-size: 153.9%; margin: .75em 0; font-weight: bold;}
9 .rendered_html h3 {font-size: 123.1%; margin: .85em 0; font-weight: bold;}
9 .rendered_html h3 {font-size: 123.1%; margin: .85em 0; font-weight: bold;}
10 .rendered_html h4 {font-size: 100% margin: 0.95em 0; font-weight: bold;}
10 .rendered_html h4 {font-size: 100% margin: 0.95em 0; font-weight: bold;}
11 .rendered_html h5 {font-size: 85%; margin: 1.5em 0; font-weight: bold;}
11 .rendered_html h5 {font-size: 85%; margin: 1.5em 0; font-weight: bold;}
12 .rendered_html h6 {font-size: 77%; margin: 1.65em 0; font-weight: bold;}
12 .rendered_html h6 {font-size: 77%; margin: 1.65em 0; font-weight: bold;}
13 .rendered_html ul {list-style:disc; margin: 1em 2em;}
13 .rendered_html ul {list-style:disc; margin: 1em 2em;}
14 .rendered_html ul ul {list-style:square; margin: 0em 2em;}
14 .rendered_html ul ul {list-style:square; margin: 0em 2em;}
15 .rendered_html ul ul ul {list-style:circle; margin-left: 0em 2em;}
15 .rendered_html ul ul ul {list-style:circle; margin-left: 0em 2em;}
16 .rendered_html ol {list-style:decimal; margin: 1em 2em;}
16 .rendered_html ol {list-style:decimal; margin: 1em 2em;}
17 .rendered_html ol ol {list-style:upper-alpha; margin: 0em 2em;}
17 .rendered_html ol ol {list-style:upper-alpha; margin: 0em 2em;}
18 .rendered_html ol ol ol {list-style:lower-alpha; margin: 0em 2em;}
18 .rendered_html ol ol ol {list-style:lower-alpha; margin: 0em 2em;}
19 .rendered_html ol ol ol ol {list-style:lower-roman; margin: 0em 2em;}
19 .rendered_html ol ol ol ol {list-style:lower-roman; margin: 0em 2em;}
20 /* any extras will just be numbers: */
20 /* any extras will just be numbers: */
21 .rendered_html ol ol ol ol ol {list-style:decimal; margin: 0em 2em;}
21 .rendered_html ol ol ol ol ol {list-style:decimal; margin: 0em 2em;}
22
22
23 .rendered_html hr {
23 .rendered_html hr {
24 color: black;
24 color: black;
25 background-color: black;
25 background-color: black;
26 }
26 }
27
27
28 .rendered_html pre {
28 .rendered_html pre {
29 margin: 1em 2em;
29 margin: 1em 2em;
30 }
30 }
31
31
32 .rendered_html blockquote {
32 .rendered_html blockquote {
33 margin: 1em 2em;
33 margin: 1em 2em;
34 }
34 }
35
35
36 .rendered_html table {
36 .rendered_html table {
37 border: 1px solid black;
37 border: 1px solid black;
38 border-collapse: collapse;
38 border-collapse: collapse;
39 margin: 1em 2em;
39 margin: 1em 2em;
40 }
40 }
41
41
42 .rendered_html td {
42 .rendered_html td {
43 border: 1px solid black;
43 border: 1px solid black;
44 text-align: left;
44 text-align: left;
45 vertical-align: middle;
45 vertical-align: middle;
46 padding: 4px;
46 padding: 4px;
47 }
47 }
48
48
49 .rendered_html th {
49 .rendered_html th {
50 border: 1px solid black;
50 border: 1px solid black;
51 text-align: left;
51 text-align: left;
52 vertical-align: middle;
52 vertical-align: middle;
53 padding: 4px;
53 padding: 4px;
54 font-weight: bold;
54 font-weight: bold;
55 }
55 }
56
56
57 .rendered_html tr {
57 .rendered_html tr {
58 border: 1px solid black;
58 border: 1px solid black;
59 }
59 }
60
60
61 .rendered_html p {
61 .rendered_html p {
62 text-align: justify;
62 text-align: justify;
63 }
63 }
64
64
65 .rendered_html p + p {
65 .rendered_html p + p {
66 margin-top: 1em;
66 margin-top: 1em;
67 }
67 }
68
68
@@ -1,159 +1,159 b''
1 /**
1 /**
2 * Primary styles
2 * Primary styles
3 *
3 *
4 * Author: IPython Development Team
4 * Author: IPython Development Team
5 */
5 */
6
6
7 /** WARNING IF YOU ARE EDITTING THIS FILE, if this is a .css file, It has a lot
7 /** WARNING IF YOU ARE EDITTING THIS FILE, if this is a .css file, It has a lot
8 * of chance of beeing generated from the ../less/[samename].less file, you can
8 * of chance of beeing generated from the ../less/[samename].less file, you can
9 * try to get back the less file by reverting somme commit in history
9 * try to get back the less file by reverting somme commit in history
10 **/
10 **/
11
11
12 /*
12 /*
13 * We'll try to get something pretty, so we
13 * We'll try to get something pretty, so we
14 * have some strange css to have the scroll bar on
14 * have some strange css to have the scroll bar on
15 * the left with fix button on the top right of the tooltip
15 * the left with fix button on the top right of the tooltip
16 */
16 */
17
17
18 // double slash comment are remove by less compilation
18 // double slash comment are remove by less compilation
19 // **
19 // **
20 // * Less mixins
20 // * Less mixins
21 // **/
21 // **/
22
22
23 // Four color of the background
23 // Four color of the background
24 @import "variables" ;
24 @import "variables" ;
25
25
26 .dropshadow(){
26 .dropshadow(){
27 -moz-box-shadow: 0px 6px 10px -1px #adadad;
27 -moz-box-shadow: 0px 6px 10px -1px #adadad;
28 -webkit-box-shadow: 0px 6px 10px -1px #adadad;
28 -webkit-box-shadow: 0px 6px 10px -1px #adadad;
29 box-shadow: 0px 6px 10px -1px #adadad;
29 box-shadow: 0px 6px 10px -1px #adadad;
30 }
30 }
31
31
32 // smoth height adaptation
32 // smoth height adaptation
33 .smoothheight(@t:1s) {
33 .smoothheight(@t:1s) {
34 -webkit-transition-property: height;
34 -webkit-transition-property: height;
35 -webkit-transition-duration: 1s;
35 -webkit-transition-duration: 1s;
36 -moz-transition-property: height;
36 -moz-transition-property: height;
37 -moz-transition-duration: 1s;
37 -moz-transition-duration: 1s;
38 transition-property: height;
38 transition-property: height;
39 transition-duration: 1s;
39 transition-duration: 1s;
40 }
40 }
41
41
42 @-moz-keyframes fadeOut {
42 @-moz-keyframes fadeOut {
43 from {opacity:1;}
43 from {opacity:1;}
44 to {opacity:0;}
44 to {opacity:0;}
45 }
45 }
46
46
47 @-webkit-keyframes fadeOut {
47 @-webkit-keyframes fadeOut {
48 from {opacity:1;}
48 from {opacity:1;}
49 to {opacity:0;}
49 to {opacity:0;}
50 }
50 }
51
51
52 //@keyframes fadeOut {
52 //@keyframes fadeOut {
53 // from {opacity:1;}
53 // from {opacity:1;}
54 // to {opacity:0;}
54 // to {opacity:0;}
55 //}
55 //}
56
56
57 @-moz-keyframes fadeIn {
57 @-moz-keyframes fadeIn {
58 from {opacity:0;}
58 from {opacity:0;}
59 to {opacity:1;}
59 to {opacity:1;}
60 }
60 }
61
61
62 @-webkit-keyframes fadeIn {
62 @-webkit-keyframes fadeIn {
63 from {opacity:0;}
63 from {opacity:0;}
64 to {opacity:1;}
64 to {opacity:1;}
65 }
65 }
66
66
67 //@keyframes fadeIn {
67 //@keyframes fadeIn {
68 // from {opacity:0;}
68 // from {opacity:0;}
69 // to {opacity:1;}
69 // to {opacity:1;}
70 //}
70 //}
71
71
72 /*properties of tooltip after "expand"*/
72 /*properties of tooltip after "expand"*/
73 .bigtooltip {
73 .bigtooltip {
74 overflow: auto;
74 overflow: auto;
75 height: 200px;
75 height: 200px;
76 .smoothheight();
76 .smoothheight();
77 }
77 }
78
78
79 /*properties of tooltip before "expand"*/
79 /*properties of tooltip before "expand"*/
80 .smalltooltip{
80 .smalltooltip{
81 .smoothheight();
81 .smoothheight();
82 text-overflow: ellipsis;
82 text-overflow: ellipsis;
83 overflow: hidden;
83 overflow: hidden;
84 height:80px;
84 height:80px;
85 }
85 }
86
86
87 .tooltipbuttons
87 .tooltipbuttons
88 {
88 {
89 position: absolute;
89 position: absolute;
90 padding-right : 15px;
90 padding-right : 15px;
91 top : 0px;
91 top : 0px;
92 right:0px;
92 right:0px;
93 }
93 }
94
94
95 .tooltiptext
95 .tooltiptext
96 {
96 {
97 /*avoid the button to overlap on some docstring*/
97 /*avoid the button to overlap on some docstring*/
98 padding-right:30px
98 padding-right:30px
99 }
99 }
100
100
101 .ipython_tooltip {
101 .ipython_tooltip {
102 max-width:700px;
102 max-width:700px;
103 /*fade-in animation when inserted*/
103 /*fade-in animation when inserted*/
104 -webkit-animation: fadeOut 800ms;
104 -webkit-animation: fadeOut 800ms;
105 -moz-animation: fadeOut 800ms;
105 -moz-animation: fadeOut 800ms;
106 animation: fadeOut 800ms;
106 animation: fadeOut 800ms;
107 -webkit-animation: fadeIn 800ms;
107 -webkit-animation: fadeIn 800ms;
108 -moz-animation: fadeIn 800ms;
108 -moz-animation: fadeIn 800ms;
109 animation: fadeIn 800ms;
109 animation: fadeIn 800ms;
110 vertical-align: middle;
110 vertical-align: middle;
111 background-color: @cell_background;
111 background-color: @cell_background;
112
112
113 overflow : visible;
113 overflow : visible;
114 border: @border_color @borderwidth solid;
114 border: @border_color @borderwidth solid;
115 outline: none;
115 outline: none;
116 padding: 3px;
116 padding: 3px;
117 margin: 0px;
117 margin: 0px;
118 padding-left:7px;
118 padding-left:7px;
119 font-family: monospace;
119 font-family: monospace;
120 min-height:50px;
120 min-height:50px;
121 position: absolute;
121 position: absolute;
122
122
123 .dropshadow;
123 .dropshadow;
124 .corner-all;
124 .corner-all;
125
125
126 a {
126 a {
127 float:right;
127 float:right;
128 }
128 }
129
129
130 }
130 }
131
131
132
132
133 .pretooltiparrow {
133 .pretooltiparrow {
134 left: 0px;
134 left: 0px;
135 margin: 0px;
135 margin: 0px;
136 top: -16px;
136 top: -16px;
137 width: 40px;
137 width: 40px;
138 height: 16px;
138 height: 16px;
139 overflow: hidden;
139 overflow: hidden;
140 position: absolute;
140 position: absolute;
141
141
142 }
142 }
143
143
144 .pretooltiparrow:before {
144 .pretooltiparrow:before {
145 background-color : @cell_background;
145 background-color : @cell_background;
146 border : @borderwidth @border_color solid;
146 border : @borderwidth @border_color solid;
147 z-index:11;
147 z-index:11;
148 content: "";
148 content: "";
149 position: absolute;
149 position: absolute;
150 left: 15px;
150 left: 15px;
151 top: 10px;
151 top: 10px;
152 width: 25px;
152 width: 25px;
153 height: 25px;
153 height: 25px;
154 @theta : 45deg;
154 @theta : 45deg;
155 -webkit-transform: rotate(@theta);
155 -webkit-transform: rotate(@theta);
156 -moz-transform: rotate(@theta);
156 -moz-transform: rotate(@theta);
157 -ms-transform: rotate(@theta);
157 -ms-transform: rotate(@theta);
158 -o-transform: rotate(@theta);
158 -o-transform: rotate(@theta);
159 }
159 }
@@ -1,17 +1,17 b''
1 @corner_radius: 3px;
1 @corner_radius: 3px;
2 @notebook_background : white;
2 @notebook_background : white;
3 @cell_selected_background: darken(@notebook_background, 2%);
3 @cell_selected_background: darken(@notebook_background, 2%);
4 @cell_background: darken(@notebook_background, 3.2%);
4 @cell_background: darken(@notebook_background, 3.2%);
5 @border_color: darken(@cell_selected_background, 10%);
5 @border_color: darken(@cell_selected_background, 10%);
6 @borderwidth : 1px;
6 @borderwidth : 1px;
7 @fontBaseColor : black;
7 @fontBaseColor : black;
8
8
9
9
10
10
11
11
12
12
13 // utilities mixins
13 // utilities mixins
14
14
15 .corner-all {
15 .corner-all {
16 border-radius:@corner_radius;
16 border-radius:@corner_radius;
17 }
17 }
General Comments 0
You need to be logged in to leave comments. Login now