diff --git a/IPython/html/notebookapp.py b/IPython/html/notebookapp.py
index 955f6df6b..e5d2298bf 100644
--- a/IPython/html/notebookapp.py
+++ b/IPython/html/notebookapp.py
@@ -85,7 +85,7 @@ from IPython.utils.traitlets import (
DottedObjectName
)
from IPython.utils import py3compat
-from IPython.utils.path import filefind
+from IPython.utils.path import filefind, get_ipython_dir
from .utils import url_path_join
@@ -170,6 +170,7 @@ class NotebookWebApplication(web.Application):
cluster_manager=cluster_manager,
# IPython stuff
+ nbextensions_path = ipython_app.nbextensions_path,
mathjax_url=ipython_app.mathjax_url,
config=ipython_app.config,
use_less=ipython_app.use_less,
@@ -193,6 +194,7 @@ class NotebookWebApplication(web.Application):
handlers.extend(load_handlers('services.clusters.handlers'))
handlers.extend([
(r"/files/(.*)", AuthenticatedFileHandler, {'path' : settings['notebook_manager'].notebook_dir}),
+ (r"/nbextensions/(.*)", FileFindHandler, {'path' : settings['nbextensions_path']}),
])
# prepend base_project_url onto the patterns that we match
new_handlers = []
@@ -432,6 +434,12 @@ class NotebookApp(BaseIPythonApplication):
def static_file_path(self):
"""return extra paths + the default location"""
return self.extra_static_paths + [DEFAULT_STATIC_FILES_PATH]
+
+ nbextensions_path = List(Unicode, config=True,
+ help="""paths for Javascript extensions. By default, this is just IPYTHONDIR/nbextensions"""
+ )
+ def _nbextensions_path_default(self):
+ return [os.path.join(get_ipython_dir(), 'nbextensions')]
mathjax_url = Unicode("", config=True,
help="""The url for MathJax.js."""
@@ -442,21 +450,32 @@ class NotebookApp(BaseIPythonApplication):
static_url_prefix = self.webapp_settings.get("static_url_prefix",
url_path_join(self.base_project_url, "static")
)
- try:
- mathjax = filefind(os.path.join('mathjax', 'MathJax.js'), self.static_file_path)
- except IOError:
- if self.certfile:
- # HTTPS: load from Rackspace CDN, because SSL certificate requires it
- base = u"https://c328740.ssl.cf1.rackcdn.com"
+
+ # try local mathjax, either in nbextensions/mathjax or static/mathjax
+ for (url_prefix, search_path) in [
+ (url_path_join(self.base_project_url, "nbextensions"), self.nbextensions_path),
+ (static_url_prefix, self.static_file_path),
+ ]:
+ self.log.debug("searching for local mathjax in %s", search_path)
+ try:
+ mathjax = filefind(os.path.join('mathjax', 'MathJax.js'), search_path)
+ except IOError:
+ continue
else:
- base = u"http://cdn.mathjax.org"
-
- url = base + u"/mathjax/latest/MathJax.js"
- self.log.info("Using MathJax from CDN: %s", url)
- return url
+ url = url_path_join(url_prefix, u"mathjax/MathJax.js")
+ self.log.info("Serving local MathJax from %s at %s", mathjax, url)
+ return url
+
+ # no local mathjax, serve from CDN
+ if self.certfile:
+ # HTTPS: load from Rackspace CDN, because SSL certificate requires it
+ host = u"https://c328740.ssl.cf1.rackcdn.com"
else:
- self.log.info("Using local MathJax from %s" % mathjax)
- return url_path_join(static_url_prefix, u"mathjax/MathJax.js")
+ host = u"http://cdn.mathjax.org"
+
+ url = host + u"/mathjax/latest/MathJax.js"
+ self.log.info("Using MathJax from CDN: %s", url)
+ return url
def _mathjax_url_changed(self, name, old, new):
if new and not self.enable_mathjax:
@@ -521,9 +540,9 @@ class NotebookApp(BaseIPythonApplication):
def init_webapp(self):
"""initialize tornado webapp and httpserver"""
self.web_app = NotebookWebApplication(
- self, self.kernel_manager, self.notebook_manager,
+ self, self.kernel_manager, self.notebook_manager,
self.cluster_manager, self.log,
- self.base_project_url, self.webapp_settings
+ self.base_project_url, self.webapp_settings,
)
if self.certfile:
ssl_options = dict(certfile=self.certfile)