Browse Source

examples tests greeen

Eric Charles 5 years ago
parent
commit
e1526fb619
30 changed files with 915 additions and 156 deletions
  1. 4 4
      examples/app/templates/index.html
  2. 1 0
      examples/cell/main.py
  3. 8 8
      examples/cell/templates/index.html
  4. 47 20
      examples/console/main.py
  5. 59 0
      examples/console/templates/error.html
  6. 29 0
      examples/console/templates/index.html
  7. 50 23
      examples/filebrowser/main.py
  8. 59 0
      examples/filebrowser/templates/error.html
  9. 29 0
      examples/filebrowser/templates/index.html
  10. 33 18
      examples/notebook/main.py
  11. 59 0
      examples/notebook/templates/error.html
  12. 29 0
      examples/notebook/templates/index.html
  13. 40 17
      examples/terminal/main.py
  14. 59 0
      examples/terminal/templates/error.html
  15. 29 0
      examples/terminal/templates/index.html
  16. 1 1
      packages/services/examples/browser-require/index.html
  17. 40 23
      packages/services/examples/browser-require/main.py
  18. 0 0
      packages/services/examples/browser-require/static/index.js
  19. 1 1
      packages/services/examples/browser/index.html
  20. 49 20
      packages/services/examples/browser/main.py
  21. 59 0
      packages/services/examples/browser/templates/error.html
  22. 17 0
      packages/services/examples/browser/templates/index.html
  23. 0 0
      packages/services/examples/browser/tmp/bar-Copy1.txt
  24. 0 0
      packages/services/examples/browser/tmp/foo.txt
  25. 59 0
      packages/services/examples/node/templates/error.html
  26. 29 0
      packages/services/examples/node/templates/index.html
  27. 48 20
      packages/services/examples/typescript-browser-with-output/main.py
  28. 59 0
      packages/services/examples/typescript-browser-with-output/templates/error.html
  29. 17 0
      packages/services/examples/typescript-browser-with-output/templates/index.html
  30. 1 1
      yarn.lock

+ 4 - 4
examples/app/templates/index.html

@@ -10,10 +10,10 @@
     {# Set a dummy variable - we just want the side effect of the update. #}
     {% set _ = page_config_full.update(baseUrl=base_url, wsUrl=ws_url) %}
     
-      <script id="jupyter-config-data" type="application/json">
-        {{ page_config_full | tojson }}
-      </script>
-  <script src="{{page_config['fullStaticUrl'] | e}}/bundle.js" main="index"></script>
+    <script id="jupyter-config-data" type="application/json">
+      {{ page_config_full | tojson }}
+    </script>
+    <script src="{{page_config['fullStaticUrl'] | e}}/bundle.js" main="index"></script>
 
   <script type="text/javascript">
     /* Remove token from URL. */

+ 1 - 0
examples/cell/main.py

@@ -37,6 +37,7 @@ class ExampleHandler(ExtensionHandlerJinjaMixin, ExtensionHandlerMixin, JupyterH
             "appVersion": version,
             'baseUrl': self.base_url,
             'token': self.settings['token'],
+            'fullStaticUrl': ujoin(self.base_url, 'static', 'example'), 
             'frontendUrl': ujoin(self.base_url, 'example/'),
         }
         return self.write(

+ 8 - 8
examples/cell/templates/index.html

@@ -4,16 +4,16 @@
   <title>{{page_config['appName'] | e}}</title>
 </head>
 <body>
-    {# Copy so we do not modify the page_config with updates. #}
-    {% set page_config_full = page_config.copy() %}
+  {# Copy so we do not modify the page_config with updates. #}
+  {% set page_config_full = page_config.copy() %}
     
-    {# Set a dummy variable - we just want the side effect of the update. #}
-    {% set _ = page_config_full.update(baseUrl=base_url, wsUrl=ws_url) %}
+  {# Set a dummy variable - we just want the side effect of the update. #}
+  {% set _ = page_config_full.update(baseUrl=base_url, wsUrl=ws_url) %}
     
-      <script id="jupyter-config-data" type="application/json">
-        {{ page_config_full | tojson }}
-      </script>
-  <script src="{{base_url | e}}static/example/bundle.js" main="index"></script>
+  <script id="jupyter-config-data" type="application/json">
+    {{ page_config_full | tojson }}
+  </script>
+  <script src="{{page_config['fullStaticUrl'] | e}}/bundle.js" main="index"></script>
 
   <script type="text/javascript">
     /* Remove token from URL. */

+ 47 - 20
examples/console/main.py

@@ -12,42 +12,69 @@ run ``python main.py``.
 
 """
 import os
+import json
 from jinja2 import FileSystemLoader
-from notebook.base.handlers import IPythonHandler, FileFindHandler
-from notebook.notebookapp import NotebookApp
-from notebook.utils import url_path_join as ujoin
+from jupyter_server.base.handlers import JupyterHandler, FileFindHandler
+from jupyter_server.extension.handler import ExtensionHandlerMixin, ExtensionHandlerJinjaMixin
+from jupyterlab_server import LabServerApp, LabConfig
+from jupyter_server.utils import url_path_join as ujoin
 from traitlets import Unicode
 
 HERE = os.path.dirname(__file__)
 
-class ExampleHandler(IPythonHandler):
+with open(os.path.join(HERE, 'package.json')) as fid:
+    version = json.load(fid)['version']
+
+class ExampleHandler(ExtensionHandlerJinjaMixin, ExtensionHandlerMixin, JupyterHandler):
     """Handle requests between the main app page and notebook server."""
 
-    def get(self):
-        """Get the main page for the application's interface."""
-        return self.write(self.render_template('index.html',
-                                               static=self.static_url,
-                                               base_url=self.base_url,
-                                               token=self.settings['token']))
+    def initialize(self):
+        super().initialize('lab')
 
-    def get_template(self, name):
-        loader = FileSystemLoader(HERE)
-        return loader.load(self.settings['jinja2_env'], name)
+    def get(self):
+        config_data = {
+            # Use camelCase here, since that's what the lab components expect
+            "appVersion": version,
+            'baseUrl': self.base_url,
+            'token': self.settings['token'],
+            'fullStaticUrl': ujoin(self.base_url, 'static', 'example'), 
+            'frontendUrl': ujoin(self.base_url, 'example/'),
+        }
+        return self.write(
+            self.render_template(
+                'index.html',
+                static=self.static_url,
+                base_url=self.base_url,
+                token=self.settings['token'],
+                page_config=config_data
+                )
+            )
 
 
-class ExampleApp(NotebookApp):
+class ExampleApp(LabServerApp):
 
     default_url = Unicode('/example')
 
-    def init_webapp(self):
+    lab_config = LabConfig(
+        app_name = 'JupyterLab Example Console',
+        app_settings_dir = os.path.join(HERE, 'build', 'application_settings'),
+        app_url = '/example',
+        schemas_dir = os.path.join(HERE, 'build', 'schemas'),
+        static_dir = os.path.join(HERE, 'build'),
+        templates_dir = os.path.join(HERE, 'templates'),
+        themes_dir = os.path.join(HERE, 'build', 'themes'),
+        user_settings_dir = os.path.join(HERE, 'build', 'user_settings'),
+        workspaces_dir = os.path.join(HERE, 'build', 'workspaces'),
+    )
+
+    def initialize_handlers(self):
         """initialize tornado webapp and httpserver.
         """
-        super(ExampleApp, self).init_webapp()
         default_handlers = [
-            (ujoin(self.base_url, r'/example/?'), ExampleHandler),
-            (ujoin(self.base_url, r"/example/(.*)"), FileFindHandler,
-        {'path': os.path.join(HERE, 'build')})        ]
-        self.web_app.add_handlers('.*$', default_handlers)
+            (ujoin(self.serverapp.base_url, 'example'), ExampleHandler),
+        ]
+        self.serverapp.web_app.add_handlers('.*$', default_handlers)
+        super().initialize_handlers()
 
 
 if __name__ == '__main__':

+ 59 - 0
examples/console/templates/error.html

@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) Jupyter Development Team.
+Distributed under the terms of the Modified BSD License.
+-->
+<html>
+
+<head>
+  <meta charset="utf-8">
+
+  <title>{% block title %}{{page_title | e}}{% endblock %}</title>
+
+  {% block favicon %}<link rel="shortcut icon" type="image/x-icon" href="/static/base/images/favicon.ico">{% endblock %}
+
+</head>
+
+<body>
+
+{% block stylesheet %}
+<style type="text/css">
+/* disable initial hide */
+div#header, div#site {
+    display: block;
+}
+</style>
+{% endblock %}
+{% block site %}
+
+<div class="error">
+    {% block h1_error %}
+    <h1>{{status_code | e}} : {{status_message | e}}</h1>
+    {% endblock h1_error %}
+    {% block error_detail %}
+    {% if message %}
+    <p>The error was:</p>
+    <div class="traceback-wrapper">
+    <pre class="traceback">{{message | e}}</pre>
+    </div>
+    {% endif %}
+    {% endblock %}
+</header>
+
+{% endblock %}
+
+{% block script %}
+<script type='text/javascript'>
+window.onload = function () {
+  var tb = document.getElementsByClassName('traceback')[0];
+  tb.scrollTop = tb.scrollHeight;
+  {% if message %}
+  console.error("{{message | e}}")
+  {% endif %}
+};
+</script>
+{% endblock script %}
+
+</body>
+
+</html>

+ 29 - 0
examples/console/templates/index.html

@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>{{page_config['appName'] | e}}</title>
+</head>
+<body>
+  {# Copy so we do not modify the page_config with updates. #}
+  {% set page_config_full = page_config.copy() %}
+    
+  {# Set a dummy variable - we just want the side effect of the update. #}
+  {% set _ = page_config_full.update(baseUrl=base_url, wsUrl=ws_url) %}
+    
+  <script id="jupyter-config-data" type="application/json">
+    {{ page_config_full | tojson }}
+  </script>
+  <script src="{{page_config['fullStaticUrl'] | e}}/bundle.js" main="index"></script>
+
+  <script type="text/javascript">
+    /* Remove token from URL. */
+    (function () {
+      var parsedUrl = new URL(window.location.href);
+      if (parsedUrl.searchParams.get('token')) {
+        parsedUrl.searchParams.delete('token');
+        window.history.replaceState({ }, '', parsedUrl.href);
+      }
+    })();
+  </script>
+</body>
+</html>

+ 50 - 23
examples/filebrowser/main.py

@@ -12,44 +12,71 @@ run ``python main.py``.
 
 """
 import os
+import json
 from jinja2 import FileSystemLoader
-from notebook.base.handlers import IPythonHandler, FileFindHandler
-from notebook.notebookapp import NotebookApp
-from notebook.utils import url_path_join as ujoin
+from jupyter_server.base.handlers import JupyterHandler, FileFindHandler
+from jupyter_server.extension.handler import ExtensionHandlerMixin, ExtensionHandlerJinjaMixin
+from jupyterlab_server import LabServerApp, LabConfig
+from jupyter_server.utils import url_path_join as ujoin
 from traitlets import Unicode
 
 HERE = os.path.dirname(__file__)
 
-class ExampleHandler(IPythonHandler):
+with open(os.path.join(HERE, 'package.json')) as fid:
+    version = json.load(fid)['version']
+
+class ExampleHandler(ExtensionHandlerJinjaMixin, ExtensionHandlerMixin, JupyterHandler):
     """Handle requests between the main app page and notebook server."""
 
+    def initialize(self):
+        super().initialize('lab')
+
     def get(self):
         """Get the main page for the application's interface."""
-        return self.write(self.render_template('index.html',
-                                               static=self.static_url,
-                                               base_url=self.base_url,
-                                               token=self.settings['token']))
-
-    def get_template(self, name):
-        loader = FileSystemLoader(HERE)
-        return loader.load(self.settings['jinja2_env'], name)
-
-
-
-
-class ExampleApp(NotebookApp):
+        config_data = {
+            # Use camelCase here, since that's what the lab components expect
+            "appVersion": version,
+            'baseUrl': self.base_url,
+            'token': self.settings['token'],
+            'fullStaticUrl': ujoin(self.base_url, 'static', 'example'), 
+            'frontendUrl': ujoin(self.base_url, 'example/'),
+        }
+        return self.write(
+            self.render_template(
+                'index.html',
+                static=self.static_url,
+                base_url=self.base_url,
+                token=self.settings['token'],
+                page_config=config_data
+                )
+            )
+
+
+class ExampleApp(LabServerApp):
 
     default_url = Unicode('/example')
 
-    def init_webapp(self):
+    lab_config = LabConfig(
+        app_name = 'JupyterLab Example File Browser',
+        app_url = '/example',
+        static_dir = os.path.join(HERE, 'build'),
+        templates_dir = os.path.join(HERE, 'templates'),
+        app_version = version,
+        app_settings_dir = os.path.join(HERE, 'build', 'application_settings'),
+        schemas_dir = os.path.join(HERE, 'build', 'schemas'),
+        themes_dir = os.path.join(HERE, 'build', 'themes'),
+        user_settings_dir = os.path.join(HERE, 'build', 'user_settings'),
+        workspaces_dir = os.path.join(HERE, 'build', 'workspaces'),
+    )
+
+    def initialize_handlers(self):
         """initialize tornado webapp and httpserver.
         """
-        super(ExampleApp, self).init_webapp()
         default_handlers = [
-            (ujoin(self.base_url, r'/example/?'), ExampleHandler),
-            (ujoin(self.base_url, r"/example/(.*)"), FileFindHandler,
-        {'path': os.path.join(HERE, 'build')})        ]
-        self.web_app.add_handlers('.*$', default_handlers)
+            (ujoin(self.serverapp.base_url, 'example'), ExampleHandler),
+        ]
+        self.serverapp.web_app.add_handlers('.*$', default_handlers)
+        super().initialize_handlers()
 
 
 if __name__ == '__main__':

+ 59 - 0
examples/filebrowser/templates/error.html

@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) Jupyter Development Team.
+Distributed under the terms of the Modified BSD License.
+-->
+<html>
+
+<head>
+  <meta charset="utf-8">
+
+  <title>{% block title %}{{page_title | e}}{% endblock %}</title>
+
+  {% block favicon %}<link rel="shortcut icon" type="image/x-icon" href="/static/base/images/favicon.ico">{% endblock %}
+
+</head>
+
+<body>
+
+{% block stylesheet %}
+<style type="text/css">
+/* disable initial hide */
+div#header, div#site {
+    display: block;
+}
+</style>
+{% endblock %}
+{% block site %}
+
+<div class="error">
+    {% block h1_error %}
+    <h1>{{status_code | e}} : {{status_message | e}}</h1>
+    {% endblock h1_error %}
+    {% block error_detail %}
+    {% if message %}
+    <p>The error was:</p>
+    <div class="traceback-wrapper">
+    <pre class="traceback">{{message | e}}</pre>
+    </div>
+    {% endif %}
+    {% endblock %}
+</header>
+
+{% endblock %}
+
+{% block script %}
+<script type='text/javascript'>
+window.onload = function () {
+  var tb = document.getElementsByClassName('traceback')[0];
+  tb.scrollTop = tb.scrollHeight;
+  {% if message %}
+  console.error("{{message | e}}")
+  {% endif %}
+};
+</script>
+{% endblock script %}
+
+</body>
+
+</html>

+ 29 - 0
examples/filebrowser/templates/index.html

@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>{{page_config['appName'] | e}}</title>
+</head>
+<body>
+  {# Copy so we do not modify the page_config with updates. #}
+  {% set page_config_full = page_config.copy() %}
+    
+  {# Set a dummy variable - we just want the side effect of the update. #}
+  {% set _ = page_config_full.update(baseUrl=base_url, wsUrl=ws_url) %}
+    
+  <script id="jupyter-config-data" type="application/json">
+    {{ page_config_full | tojson }}
+  </script>
+  <script src="{{page_config['fullStaticUrl'] | e}}/bundle.js" main="index"></script>
+
+  <script type="text/javascript">
+    /* Remove token from URL. */
+    (function () {
+      var parsedUrl = new URL(window.location.href);
+      if (parsedUrl.searchParams.get('token')) {
+        parsedUrl.searchParams.delete('token');
+        window.history.replaceState({ }, '', parsedUrl.href);
+      }
+    })();
+  </script>
+</body>
+</html>

+ 33 - 18
examples/notebook/main.py

@@ -12,19 +12,27 @@ run ``python main.py``.
 
 """
 import os
+import json
 from jinja2 import FileSystemLoader
-from notebook.base.handlers import IPythonHandler, FileFindHandler
-from notebook.notebookapp import NotebookApp
-from notebook.utils import url_path_join as ujoin
+from jupyter_server.base.handlers import JupyterHandler, FileFindHandler
+from jupyter_server.extension.handler import ExtensionHandlerMixin, ExtensionHandlerJinjaMixin
+from jupyterlab_server import LabServerApp, LabConfig
+from jupyter_server.utils import url_path_join as ujoin
 from traitlets import Unicode
 
 HERE = os.path.dirname(__file__)
 
-class ExampleHandler(IPythonHandler):
+with open(os.path.join(HERE, 'package.json')) as fid:
+    version = json.load(fid)['version']
+
+class ExampleHandler(ExtensionHandlerJinjaMixin, ExtensionHandlerMixin, JupyterHandler):
     """
     Serve a notebook file from the filesystem in the notebook interface
     """
 
+    def initialize(self):
+        super().initialize('lab')
+
     def get(self):
         """Get the main page for the application's interface."""
         # Options set here can be read with PageConfig.getOption
@@ -33,6 +41,7 @@ class ExampleHandler(IPythonHandler):
             'baseUrl': self.base_url,
             'token': self.settings['token'],
             'notebookPath': 'test.ipynb',
+            'fullStaticUrl': ujoin(self.base_url, 'static', 'example'), 
             'frontendUrl': ujoin(self.base_url, 'example/'),
             # FIXME: Don't use a CDN here
             'mathjaxUrl': "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js",
@@ -43,30 +52,36 @@ class ExampleHandler(IPythonHandler):
                 'index.html',
                 static=self.static_url,
                 base_url=self.base_url,
-                config_data=config_data
+                token=self.settings['token'],
+                page_config=config_data
+                )
             )
-        )
-
-    def get_template(self, name):
-        loader = FileSystemLoader(HERE)
-        return loader.load(self.settings['jinja2_env'], name)
 
 
-class ExampleApp(NotebookApp):
+class ExampleApp(LabServerApp):
 
     default_url = Unicode('/example')
 
-    def init_webapp(self):
+    lab_config = LabConfig(
+        app_name = 'JupyterLab Example Notebook',
+        app_settings_dir = os.path.join(HERE, 'build', 'application_settings'),
+        app_url = '/example',
+        schemas_dir = os.path.join(HERE, 'build', 'schemas'),
+        static_dir = os.path.join(HERE, 'build'),
+        templates_dir = os.path.join(HERE, 'templates'),
+        themes_dir = os.path.join(HERE, 'build', 'themes'),
+        user_settings_dir = os.path.join(HERE, 'build', 'user_settings'),
+        workspaces_dir = os.path.join(HERE, 'build', 'workspaces'),
+    )
+
+    def initialize_handlers(self):
         """initialize tornado webapp and httpserver.
         """
-        super(ExampleApp, self).init_webapp()
-
         default_handlers = [
-            (ujoin(self.base_url, r'/example/?'), ExampleHandler),
-            (ujoin(self.base_url, r"/example/(.*)"), FileFindHandler,
-                {'path': os.path.join(HERE, 'build')})
+            (ujoin(self.serverapp.base_url, 'example'), ExampleHandler),
         ]
-        self.web_app.add_handlers('.*$', default_handlers)
+        self.serverapp.web_app.add_handlers('.*$', default_handlers)
+        super().initialize_handlers()
 
 
 if __name__ == '__main__':

+ 59 - 0
examples/notebook/templates/error.html

@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) Jupyter Development Team.
+Distributed under the terms of the Modified BSD License.
+-->
+<html>
+
+<head>
+  <meta charset="utf-8">
+
+  <title>{% block title %}{{page_title | e}}{% endblock %}</title>
+
+  {% block favicon %}<link rel="shortcut icon" type="image/x-icon" href="/static/base/images/favicon.ico">{% endblock %}
+
+</head>
+
+<body>
+
+{% block stylesheet %}
+<style type="text/css">
+/* disable initial hide */
+div#header, div#site {
+    display: block;
+}
+</style>
+{% endblock %}
+{% block site %}
+
+<div class="error">
+    {% block h1_error %}
+    <h1>{{status_code | e}} : {{status_message | e}}</h1>
+    {% endblock h1_error %}
+    {% block error_detail %}
+    {% if message %}
+    <p>The error was:</p>
+    <div class="traceback-wrapper">
+    <pre class="traceback">{{message | e}}</pre>
+    </div>
+    {% endif %}
+    {% endblock %}
+</header>
+
+{% endblock %}
+
+{% block script %}
+<script type='text/javascript'>
+window.onload = function () {
+  var tb = document.getElementsByClassName('traceback')[0];
+  tb.scrollTop = tb.scrollHeight;
+  {% if message %}
+  console.error("{{message | e}}")
+  {% endif %}
+};
+</script>
+{% endblock script %}
+
+</body>
+
+</html>

+ 29 - 0
examples/notebook/templates/index.html

@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>{{page_config['appName'] | e}}</title>
+</head>
+<body>
+  {# Copy so we do not modify the page_config with updates. #}
+  {% set page_config_full = page_config.copy() %}
+    
+  {# Set a dummy variable - we just want the side effect of the update. #}
+  {% set _ = page_config_full.update(baseUrl=base_url, wsUrl=ws_url) %}
+    
+  <script id="jupyter-config-data" type="application/json">
+    {{ page_config_full | tojson }}
+  </script>
+  <script src="{{page_config['fullStaticUrl'] | e}}/bundle.js" main="index"></script>
+
+  <script type="text/javascript">
+    /* Remove token from URL. */
+    (function () {
+      var parsedUrl = new URL(window.location.href);
+      if (parsedUrl.searchParams.get('token')) {
+        parsedUrl.searchParams.delete('token');
+        window.history.replaceState({ }, '', parsedUrl.href);
+      }
+    })();
+  </script>
+</body>
+</html>

+ 40 - 17
examples/terminal/main.py

@@ -12,46 +12,69 @@ run ``python main.py``.
 
 """
 import os
+import json
 from jinja2 import FileSystemLoader
-from notebook.base.handlers import IPythonHandler, FileFindHandler
-from notebook.notebookapp import NotebookApp
-from notebook.utils import url_path_join as ujoin
+from jupyter_server.base.handlers import JupyterHandler, FileFindHandler
+from jupyter_server.extension.handler import ExtensionHandlerMixin, ExtensionHandlerJinjaMixin
+from jupyterlab_server import LabServerApp, LabConfig
+from jupyter_server.utils import url_path_join as ujoin
 from traitlets import Unicode
 
 HERE = os.path.dirname(__file__)
 
-class ExampleHandler(IPythonHandler):
+with open(os.path.join(HERE, 'package.json')) as fid:
+    version = json.load(fid)['version']
+
+class ExampleHandler(ExtensionHandlerJinjaMixin, ExtensionHandlerMixin, JupyterHandler):
     """Handle requests between the main app page and notebook server."""
 
+    def initialize(self):
+        super().initialize('lab')
+
     def get(self):
         """Get the main page for the application's interface."""
         available = self.settings['terminals_available']
+        config_data = {
+            # Use camelCase here, since that's what the lab components expect
+            "appVersion": version,
+            'baseUrl': self.base_url,
+            'token': self.settings['token'],
+            'fullStaticUrl': ujoin(self.base_url, 'static', 'example'), 
+            'frontendUrl': ujoin(self.base_url, 'example/'),
+            'terminalsAvailable': available
+        }
         return self.write(self.render_template('index.html',
                                                static=self.static_url,
                                                base_url=self.base_url,
                                                token=self.settings['token'],
-                                               terminals_available=available))
-
-    def get_template(self, name):
-        loader = FileSystemLoader(HERE)
-        return loader.load(self.settings['jinja2_env'], name)
+                                               terminals_available=available,
+                                               page_config=config_data))
 
 
-class ExampleApp(NotebookApp):
+class ExampleApp(LabServerApp):
 
     default_url = Unicode('/example')
 
-    def init_webapp(self):
+    lab_config = LabConfig(
+        app_name = 'JupyterLab Example Console',
+        app_settings_dir = os.path.join(HERE, 'build', 'application_settings'),
+        app_url = '/example',
+        schemas_dir = os.path.join(HERE, 'build', 'schemas'),
+        static_dir = os.path.join(HERE, 'build'),
+        templates_dir = os.path.join(HERE, 'templates'),
+        themes_dir = os.path.join(HERE, 'build', 'themes'),
+        user_settings_dir = os.path.join(HERE, 'build', 'user_settings'),
+        workspaces_dir = os.path.join(HERE, 'build', 'workspaces'),
+    )
+
+    def initialize_handlers(self):
         """initialize tornado webapp and httpserver.
         """
-        super(ExampleApp, self).init_webapp()
-
         default_handlers = [
-            (ujoin(self.base_url, r'/example/?'), ExampleHandler),
-            (ujoin(self.base_url, r"/example/(.*)"), FileFindHandler,
-                {'path': os.path.join(HERE, 'build')})
+            (ujoin(self.serverapp.base_url, 'example'), ExampleHandler),
         ]
-        self.web_app.add_handlers('.*$', default_handlers)
+        self.serverapp.web_app.add_handlers('.*$', default_handlers)
+        super().initialize_handlers()
 
 
 if __name__ == '__main__':

+ 59 - 0
examples/terminal/templates/error.html

@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) Jupyter Development Team.
+Distributed under the terms of the Modified BSD License.
+-->
+<html>
+
+<head>
+  <meta charset="utf-8">
+
+  <title>{% block title %}{{page_title | e}}{% endblock %}</title>
+
+  {% block favicon %}<link rel="shortcut icon" type="image/x-icon" href="/static/base/images/favicon.ico">{% endblock %}
+
+</head>
+
+<body>
+
+{% block stylesheet %}
+<style type="text/css">
+/* disable initial hide */
+div#header, div#site {
+    display: block;
+}
+</style>
+{% endblock %}
+{% block site %}
+
+<div class="error">
+    {% block h1_error %}
+    <h1>{{status_code | e}} : {{status_message | e}}</h1>
+    {% endblock h1_error %}
+    {% block error_detail %}
+    {% if message %}
+    <p>The error was:</p>
+    <div class="traceback-wrapper">
+    <pre class="traceback">{{message | e}}</pre>
+    </div>
+    {% endif %}
+    {% endblock %}
+</header>
+
+{% endblock %}
+
+{% block script %}
+<script type='text/javascript'>
+window.onload = function () {
+  var tb = document.getElementsByClassName('traceback')[0];
+  tb.scrollTop = tb.scrollHeight;
+  {% if message %}
+  console.error("{{message | e}}")
+  {% endif %}
+};
+</script>
+{% endblock script %}
+
+</body>
+
+</html>

+ 29 - 0
examples/terminal/templates/index.html

@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>{{page_config['appName'] | e}}</title>
+</head>
+<body>
+  {# Copy so we do not modify the page_config with updates. #}
+  {% set page_config_full = page_config.copy() %}
+    
+  {# Set a dummy variable - we just want the side effect of the update. #}
+  {% set _ = page_config_full.update(baseUrl=base_url, wsUrl=ws_url) %}
+    
+  <script id="jupyter-config-data" type="application/json">
+    {{ page_config_full | tojson }}
+  </script>
+  <script src="{{page_config['fullStaticUrl'] | e}}/bundle.js" main="index"></script>
+
+  <script type="text/javascript">
+    /* Remove token from URL. */
+    (function () {
+      var parsedUrl = new URL(window.location.href);
+      if (parsedUrl.searchParams.get('token')) {
+        parsedUrl.searchParams.delete('token');
+        window.history.replaceState({ }, '', parsedUrl.href);
+      }
+    })();
+  </script>
+</body>
+</html>

+ 1 - 1
packages/services/examples/browser-require/index.html

@@ -38,6 +38,6 @@
         }
     });
     </script>
-    <script src="{{base_url | e}}example/index.js"></script>
+    <script src="{{base_url | e}}static/example/index.js"></script>
   </body>
 </html>

+ 40 - 23
packages/services/examples/browser-require/main.py

@@ -2,44 +2,61 @@
 Copyright (c) Jupyter Development Team.
 Distributed under the terms of the Modified BSD License.
 """
-from notebook.notebookapp import NotebookApp
 import os
-from jinja2 import FileSystemLoader
-from notebook.base.handlers import IPythonHandler, FileFindHandler
-from notebook.utils import url_path_join as ujoin
+from jupyter_server.base.handlers import JupyterHandler, FileFindHandler
+from jupyter_server.extension.handler import ExtensionHandlerMixin, ExtensionHandlerJinjaMixin
+from jupyterlab_server import LabServerApp, LabConfig
+from jupyter_server.utils import url_path_join as ujoin
 from traitlets import Unicode
 
 
 HERE = os.path.dirname(__file__)
-LOADER = FileSystemLoader(HERE)
 
-
-class ExampleHander(IPythonHandler):
+class ExampleHandler(ExtensionHandlerJinjaMixin, ExtensionHandlerMixin, JupyterHandler):
     """Handle requests between the main app page and notebook server."""
 
+    def initialize(self):
+        super().initialize('lab')
+
     def get(self):
         """Get the main page for the application's interface."""
-        return self.write(self.render_template('index.html',
-                                               static=self.static_url,
-                                               base_url=self.base_url,
-                                               token=self.settings['token']))
-
-    def get_template(self, name):
-        return LOADER.load(self.settings['jinja2_env'], name)
-
-
-class ExampleApp(NotebookApp):
-    """A notebook app that runs the example."""
+        config_data = {
+            # Use camelCase here, since that's what the lab components expect
+            'baseUrl': self.base_url,
+            'token': self.settings['token'],
+            'fullStaticUrl': ujoin(self.base_url, 'static', 'example'), 
+            'frontendUrl': ujoin(self.base_url, 'example/'),
+        }
+        return self.write(
+            self.render_template(
+                'index.html',
+                static=self.static_url,
+                base_url=self.base_url,
+                token=self.settings['token'],
+                page_config=config_data
+                )
+            )
+
+
+class ExampleApp(LabServerApp):
 
     default_url = Unicode('/example')
 
-    def start(self):
+    lab_config = LabConfig(
+        app_name = 'JupyterLab Example Service Browser Require',
+        app_url = '/example',
+        static_dir = os.path.join(HERE, 'static'),
+        templates_dir = os.path.join(HERE),
+    )
+
+    def initialize_handlers(self):
+        """initialize tornado webapp and httpserver.
+        """
         default_handlers = [
-            (ujoin(self.base_url, r'/example/?'), ExampleHander),
-            (ujoin(self.base_url, r'/example/(.*)'), FileFindHandler, {'path': HERE}),
+            (ujoin(self.serverapp.base_url, 'example'), ExampleHandler),
         ]
-        self.web_app.add_handlers('.*$', default_handlers)
-        super(ExampleApp, self).start()
+        self.serverapp.web_app.add_handlers('.*$', default_handlers)
+        super().initialize_handlers()
 
 
 if __name__ == '__main__':

+ 0 - 0
packages/services/examples/browser-require/index.js → packages/services/examples/browser-require/static/index.js


+ 1 - 1
packages/services/examples/browser/index.html

@@ -11,7 +11,7 @@
       {{ page_config_full | tojson }}
     </script>
   
-    <script src="{{base_url | e}}example/bundle.js"></script>
+    <script src="{{base_url | e}}static/example/bundle.js"></script>
     <pre id='output'></pre>
   </body>
 </html>

+ 49 - 20
packages/services/examples/browser/main.py

@@ -2,44 +2,73 @@
 Copyright (c) Jupyter Development Team.
 Distributed under the terms of the Modified BSD License.
 """
-from notebook.notebookapp import NotebookApp
+import os
+import json
 import os.path as osp
-from jinja2 import FileSystemLoader
-from notebook.base.handlers import IPythonHandler, FileFindHandler
-from notebook.utils import url_path_join as ujoin
+from jupyter_server.base.handlers import JupyterHandler, FileFindHandler
+from jupyter_server.extension.handler import ExtensionHandlerMixin, ExtensionHandlerJinjaMixin
+from jupyterlab_server import LabServerApp, LabConfig
+from jupyter_server.utils import url_path_join as ujoin
 from traitlets import Unicode
 
 
 HERE = osp.dirname(__file__)
-LOADER = FileSystemLoader(HERE)
 
+with open(os.path.join(HERE, 'package.json')) as fid:
+    version = json.load(fid)['version']
 
-class ExampleHander(IPythonHandler):
+class ExampleHandler(ExtensionHandlerJinjaMixin, ExtensionHandlerMixin, JupyterHandler):
     """Handle requests between the main app page and notebook server."""
 
+    def initialize(self):
+        super().initialize('lab')
+
     def get(self):
         """Get the main page for the application's interface."""
-        return self.write(self.render_template('index.html',
-                                               static=self.static_url,
-                                               base_url=self.base_url,
-                                               token=self.settings['token']))
-
-    def get_template(self, name):
-        return LOADER.load(self.settings['jinja2_env'], name)
+        config_data = {
+            # Use camelCase here, since that's what the lab components expect
+            "appVersion": version,
+            'baseUrl': self.base_url,
+            'token': self.settings['token'],
+            'fullStaticUrl': ujoin(self.base_url, 'static', 'example'), 
+            'frontendUrl': ujoin(self.base_url, 'example/'),
+        }
+        return self.write(
+            self.render_template(
+                'index.html',
+                static=self.static_url,
+                base_url=self.base_url,
+                token=self.settings['token'],
+                page_config=config_data
+                )
+            )
 
-
-class ExampleApp(NotebookApp):
+class ExampleApp(LabServerApp):
     """A notebook app that runs the example."""
 
     default_url = Unicode('/example')
 
-    def start(self):
+    lab_config = LabConfig(
+        app_name = 'JupyterLab Example Cell',
+        app_url = '/example',
+        static_dir = os.path.join(HERE, 'build'),
+        templates_dir = os.path.join(HERE, 'templates'),
+        app_version = version, 
+        app_settings_dir = os.path.join(HERE, 'build', 'application_settings'),
+        schemas_dir = os.path.join(HERE, 'build', 'schemas'),
+        themes_dir = os.path.join(HERE, 'build', 'themes'),
+        user_settings_dir = os.path.join(HERE, 'build', 'user_settings'),
+        workspaces_dir = os.path.join(HERE, 'build', 'workspaces'),
+    )
+
+    def initialize_handlers(self):
+        """initialize tornado webapp and httpserver.
+        """
         default_handlers = [
-            (ujoin(self.base_url, r'/example/?'), ExampleHander),
-            (ujoin(self.base_url, r'/example/(.*)'), FileFindHandler, {'path': osp.join(HERE, 'build')}),
+            (ujoin(self.serverapp.base_url, 'example'), ExampleHandler),
         ]
-        self.web_app.add_handlers('.*$', default_handlers)
-        super(ExampleApp, self).start()
+        self.serverapp.web_app.add_handlers('.*$', default_handlers)
+        super().initialize_handlers()
 
 
 if __name__ == '__main__':

+ 59 - 0
packages/services/examples/browser/templates/error.html

@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) Jupyter Development Team.
+Distributed under the terms of the Modified BSD License.
+-->
+<html>
+
+<head>
+  <meta charset="utf-8">
+
+  <title>{% block title %}{{page_title | e}}{% endblock %}</title>
+
+  {% block favicon %}<link rel="shortcut icon" type="image/x-icon" href="/static/base/images/favicon.ico">{% endblock %}
+
+</head>
+
+<body>
+
+{% block stylesheet %}
+<style type="text/css">
+/* disable initial hide */
+div#header, div#site {
+    display: block;
+}
+</style>
+{% endblock %}
+{% block site %}
+
+<div class="error">
+    {% block h1_error %}
+    <h1>{{status_code | e}} : {{status_message | e}}</h1>
+    {% endblock h1_error %}
+    {% block error_detail %}
+    {% if message %}
+    <p>The error was:</p>
+    <div class="traceback-wrapper">
+    <pre class="traceback">{{message | e}}</pre>
+    </div>
+    {% endif %}
+    {% endblock %}
+</header>
+
+{% endblock %}
+
+{% block script %}
+<script type='text/javascript'>
+window.onload = function () {
+  var tb = document.getElementsByClassName('traceback')[0];
+  tb.scrollTop = tb.scrollHeight;
+  {% if message %}
+  console.error("{{message | e}}")
+  {% endif %}
+};
+</script>
+{% endblock script %}
+
+</body>
+
+</html>

+ 17 - 0
packages/services/examples/browser/templates/index.html

@@ -0,0 +1,17 @@
+<!doctype html>
+<html lang="en">
+  <head>
+    <title>Jupyter Services Demo</title>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.2.0/require.js"></script>
+  </head>
+  <body>
+    {% set page_config_full = {'baseUrl': base_url} %}
+
+    <script id="jupyter-config-data" type="application/json">
+      {{ page_config_full | tojson }}
+    </script>
+  
+    <script src="{{base_url | e}}static/example/bundle.js"></script>
+    <pre id='output'></pre>
+  </body>
+</html>

+ 0 - 0
packages/services/examples/browser/tmp/bar-Copy1.txt


+ 0 - 0
packages/services/examples/browser/tmp/foo.txt


+ 59 - 0
packages/services/examples/node/templates/error.html

@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) Jupyter Development Team.
+Distributed under the terms of the Modified BSD License.
+-->
+<html>
+
+<head>
+  <meta charset="utf-8">
+
+  <title>{% block title %}{{page_title | e}}{% endblock %}</title>
+
+  {% block favicon %}<link rel="shortcut icon" type="image/x-icon" href="/static/base/images/favicon.ico">{% endblock %}
+
+</head>
+
+<body>
+
+{% block stylesheet %}
+<style type="text/css">
+/* disable initial hide */
+div#header, div#site {
+    display: block;
+}
+</style>
+{% endblock %}
+{% block site %}
+
+<div class="error">
+    {% block h1_error %}
+    <h1>{{status_code | e}} : {{status_message | e}}</h1>
+    {% endblock h1_error %}
+    {% block error_detail %}
+    {% if message %}
+    <p>The error was:</p>
+    <div class="traceback-wrapper">
+    <pre class="traceback">{{message | e}}</pre>
+    </div>
+    {% endif %}
+    {% endblock %}
+</header>
+
+{% endblock %}
+
+{% block script %}
+<script type='text/javascript'>
+window.onload = function () {
+  var tb = document.getElementsByClassName('traceback')[0];
+  tb.scrollTop = tb.scrollHeight;
+  {% if message %}
+  console.error("{{message | e}}")
+  {% endif %}
+};
+</script>
+{% endblock script %}
+
+</body>
+
+</html>

+ 29 - 0
packages/services/examples/node/templates/index.html

@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>{{page_config['appName'] | e}}</title>
+</head>
+<body>
+  {# Copy so we do not modify the page_config with updates. #}
+  {% set page_config_full = page_config.copy() %}
+    
+  {# Set a dummy variable - we just want the side effect of the update. #}
+  {% set _ = page_config_full.update(baseUrl=base_url, wsUrl=ws_url) %}
+    
+  <script id="jupyter-config-data" type="application/json">
+    {{ page_config_full | tojson }}
+  </script>
+  <script src="{{page_config['fullStaticUrl'] | e}}/bundle.js" main="index"></script>
+
+  <script type="text/javascript">
+    /* Remove token from URL. */
+    (function () {
+      var parsedUrl = new URL(window.location.href);
+      if (parsedUrl.searchParams.get('token')) {
+        parsedUrl.searchParams.delete('token');
+        window.history.replaceState({ }, '', parsedUrl.href);
+      }
+    })();
+  </script>
+</body>
+</html>

+ 48 - 20
packages/services/examples/typescript-browser-with-output/main.py

@@ -2,44 +2,72 @@
 Copyright (c) Jupyter Development Team.
 Distributed under the terms of the Modified BSD License.
 """
-from notebook.notebookapp import NotebookApp
 import os
-from jinja2 import FileSystemLoader
-from notebook.base.handlers import IPythonHandler, FileFindHandler
-from notebook.utils import url_path_join as ujoin
+import json
+from jupyter_server.base.handlers import JupyterHandler, FileFindHandler
+from jupyter_server.extension.handler import ExtensionHandlerMixin, ExtensionHandlerJinjaMixin
+from jupyterlab_server import LabServerApp, LabConfig
+from jupyter_server.utils import url_path_join as ujoin
 from traitlets import Unicode
 
 
 HERE = os.path.dirname(__file__)
-LOADER = FileSystemLoader(HERE)
 
+with open(os.path.join(HERE, 'package.json')) as fid:
+    version = json.load(fid)['version']
 
-class ExampleHander(IPythonHandler):
+class ExampleHandler(ExtensionHandlerJinjaMixin, ExtensionHandlerMixin, JupyterHandler):
     """Handle requests between the main app page and notebook server."""
 
+    def initialize(self):
+        super().initialize('lab')
+
     def get(self):
         """Get the main page for the application's interface."""
-        return self.write(self.render_template("index.html",
-            static=self.static_url, base_url=self.base_url,
-            token=self.settings['token']))
-
-    def get_template(self, name):
-        return LOADER.load(self.settings['jinja2_env'], name)
+        config_data = {
+            # Use camelCase here, since that's what the lab components expect
+            "appVersion": version,
+            'baseUrl': self.base_url,
+            'token': self.settings['token'],
+            'fullStaticUrl': ujoin(self.base_url, 'static', 'example'), 
+            'frontendUrl': ujoin(self.base_url, 'example/'),
+        }
+        return self.write(
+            self.render_template(
+                'index.html',
+                static=self.static_url,
+                base_url=self.base_url,
+                token=self.settings['token'],
+                page_config=config_data
+                )
+            )
 
 
-class ExampleApp(NotebookApp):
-    """A notebook app that runs the example."""
+class ExampleApp(LabServerApp):
 
     default_url = Unicode('/example')
 
-    def start(self):
+    lab_config = LabConfig(
+        app_name = 'JupyterLab Example Cell',
+        app_url = '/example',
+        static_dir = os.path.join(HERE, 'build'),
+        templates_dir = os.path.join(HERE, 'templates'),
+        app_version = version,
+        app_settings_dir = os.path.join(HERE, 'build', 'application_settings'),
+        schemas_dir = os.path.join(HERE, 'build', 'schemas'),
+        themes_dir = os.path.join(HERE, 'build', 'themes'),
+        user_settings_dir = os.path.join(HERE, 'build', 'user_settings'),
+        workspaces_dir = os.path.join(HERE, 'build', 'workspaces'),
+    )
+
+    def initialize_handlers(self):
+        """initialize tornado webapp and httpserver.
+        """
         default_handlers = [
-            (ujoin(self.base_url, r'/example/?'), ExampleHander),
-            (ujoin(self.base_url, r"/example/(.*)"), FileFindHandler,
-                {'path': os.path.join(HERE, 'build')}),
+            (ujoin(self.serverapp.base_url, 'example'), ExampleHandler),
         ]
-        self.web_app.add_handlers(".*$", default_handlers)
-        super(ExampleApp, self).start()
+        self.serverapp.web_app.add_handlers('.*$', default_handlers)
+        super().initialize_handlers()
 
 
 if __name__ == '__main__':

+ 59 - 0
packages/services/examples/typescript-browser-with-output/templates/error.html

@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) Jupyter Development Team.
+Distributed under the terms of the Modified BSD License.
+-->
+<html>
+
+<head>
+  <meta charset="utf-8">
+
+  <title>{% block title %}{{page_title | e}}{% endblock %}</title>
+
+  {% block favicon %}<link rel="shortcut icon" type="image/x-icon" href="/static/base/images/favicon.ico">{% endblock %}
+
+</head>
+
+<body>
+
+{% block stylesheet %}
+<style type="text/css">
+/* disable initial hide */
+div#header, div#site {
+    display: block;
+}
+</style>
+{% endblock %}
+{% block site %}
+
+<div class="error">
+    {% block h1_error %}
+    <h1>{{status_code | e}} : {{status_message | e}}</h1>
+    {% endblock h1_error %}
+    {% block error_detail %}
+    {% if message %}
+    <p>The error was:</p>
+    <div class="traceback-wrapper">
+    <pre class="traceback">{{message | e}}</pre>
+    </div>
+    {% endif %}
+    {% endblock %}
+</header>
+
+{% endblock %}
+
+{% block script %}
+<script type='text/javascript'>
+window.onload = function () {
+  var tb = document.getElementsByClassName('traceback')[0];
+  tb.scrollTop = tb.scrollHeight;
+  {% if message %}
+  console.error("{{message | e}}")
+  {% endif %}
+};
+</script>
+{% endblock script %}
+
+</body>
+
+</html>

+ 17 - 0
packages/services/examples/typescript-browser-with-output/templates/index.html

@@ -0,0 +1,17 @@
+<!doctype html>
+<html lang="en">
+  <head>
+    <title>Jupyter Services Demo</title>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.2.0/require.js"></script>
+  </head>
+  <body>
+    {% set page_config_full = {'baseUrl': base_url} %}
+
+    <script id="jupyter-config-data" type="application/json">
+      {{ page_config_full | tojson }}
+    </script>
+
+    <script src="{{base_url | e}}static/example/bundle.js"></script>
+    <span id='outputarea'></span>
+  </body>
+</html>

+ 1 - 1
yarn.lock

@@ -14466,7 +14466,7 @@ svg-url-loader@~3.0.3:
     file-loader "~4.3.0"
     loader-utils "~1.2.3"
 
-svgo@^1.2.2:
+svgo@^1.2.2, svgo@^1.3.2:
   version "1.3.2"
   resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167"
   integrity sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==