Quellcode durchsuchen

Merge remote-tracking branch 'upstream/master'

A. Darian vor 9 Jahren
Ursprung
Commit
aa0efd9204

+ 1 - 2
examples/lab/index.html

@@ -3,8 +3,7 @@
 <head>
   <title>Jupyter Plugins Demo</title>
   <link href="http://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
-  <link rel="stylesheet" type="text/css" href="index.css">
-      <script id='jupyter-config-data' type="application/json">{ "baseUrl": "{{base_url}}", "wsUrl": "{{ws_url}}" }</script>
+  <script id='jupyter-config-data' type="application/json">{ "baseUrl": "{{base_url}}", "wsUrl": "{{ws_url}}" }</script>
   <script src="build/bundle.js" main="index"></script>
 </head>
 <body>

+ 9 - 8
examples/lab/src/index.ts → examples/lab/index.js

@@ -11,14 +11,15 @@ function main() {
     require('phosphide/lib/appshell/plugin'),
     require('phosphide/lib/commandregistry/plugin'),
     require('phosphide/lib/commandpalette/plugin'),
-    require('../../lib/terminal/plugin'),
-    require('../../lib/fileopener/plugin'),
-    require('../../lib/filehandler/plugin'),
-    require('../../lib/filebrowser/plugin'),
-    require('../../lib/imagehandler/plugin'),
-    require('../../lib/notebook/plugin'),
-    require('../../lib/services/plugin'),
-    require('./plugin')
+    require('phosphide/lib/shortcutmanager/plugin'),
+    require('../lib/terminal/plugin'),
+    require('../lib/fileopener/plugin'),
+    require('../lib/filehandler/plugin'),
+    require('../lib/filebrowser/plugin'),
+    require('../lib/imagehandler/plugin'),
+    require('../lib/notebook/plugin'),
+    require('../lib/services/plugin'),
+    require('../lib/application/plugin')
   ]).then(function() {
     console.log('loading finished');
   });

+ 0 - 17
examples/lab/src/tsconfig.json

@@ -1,17 +0,0 @@
-{
-  "compilerOptions": {
-    "declaration": true,
-    "noImplicitAny": true,
-    "noEmitOnError": true,
-    "module": "commonjs",
-    "target": "ES5",
-    "outDir": "../build"
-  },
-  "files": [
-    "../../typings/es6-promise.d.ts",
-    "../../typings/codemirror/codemirror.d.ts",
-    "../../typings/requirejs/requirejs.d.ts",
-    "index.ts",
-    "plugin.ts"
-  ]
-}

+ 1 - 1
examples/lab/webpack.conf.js

@@ -1,6 +1,6 @@
 
 module.exports = {
-  entry: './example/build/index.js',
+  entry: './example/index.js',
   output: {
     path: './example/build',
     filename: 'bundle.js'

BIN
jupyter-plugins-demo.gif


+ 5 - 4
package.json

@@ -1,18 +1,19 @@
 {
   "name": "jupyter-js-plugins",
-  "version": "0.2.1",
+  "version": "0.2.3",
   "description": "Plugins for JupyterLab",
   "main": "lib/index.js",
   "typings": "lib/index.d.ts",
   "dependencies": {
     "codemirror": "^5.10.0",
-    "jupyter-js-filebrowser": "^0.4.3",
+    "jupyter-js-filebrowser": "^0.4.9",
     "jupyter-js-notebook": "^0.3.2",
     "jupyter-js-services": "^0.4.1",
     "jupyter-js-terminal": "^0.1.12",
     "jupyter-js-utils": "^0.2.7",
-    "phosphide": "^0.2.0",
+    "phosphide": "^0.3.0",
     "phosphor-codemirror": "^0.0.1",
+    "phosphor-command": "^0.6.0",
     "phosphor-di": "^0.9.0",
     "phosphor-properties": "^2.0.0",
     "phosphor-tabs": "^1.0.0-rc.2"
@@ -40,7 +41,7 @@
   "scripts": {
     "clean": "rimraf docs && rimraf lib && rimraf test/build",
     "clean:example": "rimraf example/build",
-    "build:example": "tsc --project example/src && webpack --config example/webpack.conf.js",
+    "build:example": "webpack --config example/webpack.conf.js",
     "build:src": "tsc --project src && node scripts/copycss.js",
     "build:test": "tsc --project test/src && webpack --config test/webpack.conf.js",
     "build": "npm run build:src && npm run build:test",

+ 1 - 1
scripts/travis_script.sh

@@ -1,7 +1,7 @@
 #!/bin/bash
 set -e
 export DISPLAY=:99.0
-sh -e /etc/init.d/xvfb start
+sh -e /etc/init.d/xvfb start || true
 
 npm run clean
 npm run build

+ 0 - 0
examples/lab/index.css → src/application/plugin.css


+ 2 - 9
examples/lab/src/plugin.ts → src/application/plugin.ts

@@ -1,11 +1,3 @@
-// Copyright (c) Jupyter Development Team.
-// Distributed under the terms of the Modified BSD License.
-'use strict';
-
-import {
-  FileBrowserWidget
-} from 'jupyter-js-filebrowser';
-
 import {
   IAppShell, ICommandPalette, ICommandRegistry
 } from 'phosphide';
@@ -24,8 +16,9 @@ import {
 
 import {
   IFileBrowserWidget
-} from '../../lib';
+} from '../index';
 
+import './plugin.css';
 
 /**
  * Register the plugin contributions.

+ 1 - 1
src/filebrowser/plugin.css

@@ -33,7 +33,7 @@
 .jp-FileButtons-item {
   background-color: #FAFAFA;
   font-size: 16px;
-  border: 1px solid #757575;
+  border: 1px solid rgb(212,212,212);
   height: 30px;
   border-radius: 3px;
   margin-right: 3px;

+ 75 - 29
src/fileopener/plugin.ts

@@ -7,9 +7,13 @@ import {
 } from 'jupyter-js-filebrowser';
 
 import {
-  IAppShell, ICommandPalette, ICommandRegistry
+  IAppShell, ICommandPalette, ICommandRegistry, IShortcutManager
 } from 'phosphide';
 
+import {
+  SimpleCommand
+} from 'phosphor-command';
+
 import {
   Container, Token
 } from 'phosphor-di';
@@ -41,38 +45,80 @@ import {
 export
 function resolve(container: Container): Promise<void> {
   return container.resolve({
-    requires: [IAppShell, IFileOpener, IFileBrowserWidget, ICommandPalette, ICommandRegistry],
-    create: (appShell: IAppShell, opener: IFileOpener, browser: IFileBrowserWidget, palette: ICommandPalette, registry: ICommandRegistry): void => {
-      registry.add('jupyter-plugins:new:text-file', () => {
-        browser.newUntitled('file', '.txt').then(
-          contents => opener.open(contents.path)
-        );
+    requires: [IAppShell, IFileOpener, IFileBrowserWidget, ICommandPalette, ICommandRegistry, IShortcutManager],
+    create: (appShell: IAppShell, opener: IFileOpener, browser: IFileBrowserWidget, palette: ICommandPalette, registry: ICommandRegistry, shortcuts: IShortcutManager): void => {
+
+      // Create a command to add a new empty text file.
+      // This requires an id and an instance of a command object.
+      let newTextFileId = 'file-operations:new-text-file';
+      let newTextFileCommand = new SimpleCommand({
+        category: 'File Operations',
+        text: 'New Text File',
+        caption: 'Create a new text file',
+        handler: () => {
+          browser.newUntitled('file', '.txt').then(
+            contents => opener.open(contents.path)
+          );
+        }
       });
 
-      registry.add('jupyter-plugins:new:notebook', () => {
-        browser.newUntitled('notebook').then(
-          contents => opener.open(contents.path)
-        );
+      // Add the command to the command registry, shortcut manager
+      // and command palette plugins.
+      registry.add([
+        {
+          id: newTextFileId,
+          command: newTextFileCommand
+        }
+      ]);
+      shortcuts.add([
+        {
+          sequence: ['Ctrl O'],
+          selector: '*',
+          command: newTextFileId
+        }
+      ]);
+      palette.add([
+        {
+          id: newTextFileId,
+          args: void 0
+        }
+      ]);
+
+      // Add the command for a new notebook.
+      let newNotebookId = 'file-operations:new-notebook';
+      let newNotebookCommand = new SimpleCommand({
+        category: 'File Operations',
+        text: 'New Notebook',
+        caption: 'Create a new Jupyter Notebook',
+        handler: () => {
+          browser.newUntitled('notebook').then(
+            contents => opener.open(contents.path)
+          );
+        }
       });
-      let paletteItems = [{
-        id: 'jupyter-plugins:new:text-file',
-        title: 'Text File',
-        caption: ''
-      }, {
-        id: 'jupyter-plugins:new:notebook',
-        title: 'Notebook',
-        caption: ''
-      }];
-      let section = {
-        text: 'New...',
-        items: paletteItems
-      }
-      palette.add([section]);
 
-      FileBrowserWidget.widgetFactory = () => {
-        let model = browser.model;
-        let item = model.items[model.selected[0]];
-        return opener.open(item.path);
+      registry.add([
+        {
+          id: newNotebookId,
+          command: newNotebookCommand
+        }
+      ]);
+      shortcuts.add([
+        {
+          sequence: ['Ctrl Shift N'],
+          selector: '*',
+          command: newNotebookId
+        }
+      ]);
+      palette.add([
+        {
+          id: newNotebookId,
+          args: void 0
+        }
+      ]);
+
+      browser.widgetFactory = path => {
+        return opener.open(path);
       }
     }
   });

+ 20 - 15
src/imagehandler/plugin.ts

@@ -67,8 +67,8 @@ class ImageHandler extends AbstractFileHandler {
   protected createWidget(path: string): Widget {
     let ext = path.split('.').pop();
     var widget = new Widget();
-    let canvas = document.createElement('canvas');
-    widget.node.appendChild(canvas);
+    let image = document.createElement('img');
+    widget.node.appendChild(image);
     widget.node.style.overflowX = 'auto';
     widget.node.style.overflowY = 'auto';
     widget.title.text = path.split('/').pop();
@@ -76,20 +76,25 @@ class ImageHandler extends AbstractFileHandler {
   }
 
  /**
-   * Populate a widget from `IContentsModel`.
-   */
-  protected populateWidget(widget: Widget, model: IContentsModel): Promise<void> {
-    let ext = model.path.split('.').pop();
-    let uri = `data:${model.mimetype};${model.format},${model.content}`;
-    var img = new Image();
-    var canvas = widget.node.firstChild as HTMLCanvasElement;
-    img.addEventListener('load', () => {
-      canvas.width = img.naturalWidth;
-      canvas.height = img.naturalHeight;
-      let context = canvas.getContext('2d')
-      context.drawImage(img, 0, 0);
+  * Populate a widget from `IContentsModel`.
+  */
+  protected setState(widget: Widget, model: IContentsModel): Promise<void> {
+    return new Promise<void>((resolve, reject) => {
+      let img = widget.node.firstChild as HTMLImageElement;
+      img.addEventListener('load', () => {
+        resolve(void 0);
+      });
+      img.addEventListener('error', error => {
+        reject(error);
+      });
+      img.src = `data:${model.mimetype};${model.format},${model.content}`;;
     });
-    img.src = uri;
+  }
+
+  /**
+   * Get the state of the Widget, returns `undefined`.
+   */
+  protected getState(widget: Widget): Promise<IContentsModel> {
     return Promise.resolve(void 0);
   }
 }

+ 5 - 1
src/notebook/plugin.ts

@@ -80,11 +80,15 @@ class NotebookFileHandler extends AbstractFileHandler {
   }
 
 
-  protected populateWidget(widget: NotebookWidget, model: IContentsModel): Promise<void> {
+  protected setState(widget: NotebookWidget, model: IContentsModel): Promise<void> {
     let nbdata: NBData = makedata(model);
     populateNotebookModel(widget.model, nbdata);
     return Promise.resolve();
   }
+
+  protected getState(widget: NotebookWidget): Promise<IContentsModel> {
+    return Promise.resolve(void 0);
+  }
 }
 
 function makedata(a: IContentsModel): NBData {

+ 47 - 26
src/terminal/plugin.ts

@@ -7,9 +7,13 @@ import {
 } from 'jupyter-js-terminal';
 
 import {
-  IAppShell, ICommandPalette, ICommandRegistry
+  IAppShell, ICommandPalette, ICommandRegistry, IShortcutManager
 } from 'phosphide';
 
+import {
+  SimpleCommand
+} from 'phosphor-command';
+
 import {
   Container, Token
 } from 'phosphor-di';
@@ -24,33 +28,50 @@ import './plugin.css';
 export
 function resolve(container: Container): Promise<void> {
   return container.resolve({
-    requires: [IAppShell, ICommandPalette, ICommandRegistry],
-    create: (shell: IAppShell, palette: ICommandPalette, registry: ICommandRegistry) => {
-      registry.add('jupyter-plugins:new:terminal', () => {
-        let term = new TerminalWidget();
-        term.color = 'black';
-        term.background = 'white';
-        term.title.closable = true;
-        shell.addToMainArea(term);
-        let stack = term.parent;
-        if (!stack) {
-          return;
-        }
-        let tabs = stack.parent;
-        if (tabs instanceof TabPanel) {
-          tabs.currentWidget = term;
+    requires: [IAppShell, ICommandPalette, ICommandRegistry, IShortcutManager],
+    create: (shell: IAppShell, palette: ICommandPalette, registry: ICommandRegistry, shortcuts: IShortcutManager) => {
+
+      let newTerminalId = 'terminal:new';
+      let newTerminalCommand = new SimpleCommand({
+        category: 'Terminal',
+        text: 'New Terminal',
+        caption: 'Start a new terminal session',
+        handler: () => {
+          let term = new TerminalWidget();
+          term.color = 'black';
+          term.background = 'white';
+          term.title.closable = true;
+          shell.addToMainArea(term);
+          let stack = term.parent;
+          if (!stack) {
+            return;
+          }
+          let tabs = stack.parent;
+          if (tabs instanceof TabPanel) {
+            tabs.currentWidget = term;
+          }
         }
       });
-      let paletteItem = {
-        id: 'jupyter-plugins:new:terminal',
-        title: 'Terminal',
-        caption: ''
-      };
-      let section = {
-        text: 'New...',
-        items: [paletteItem]
-      }
-      palette.add([section]);
+
+      registry.add([
+        {
+          id: newTerminalId,
+          command: newTerminalCommand
+        }
+      ]);
+      shortcuts.add([
+        {
+          sequence: ['Ctrl T'],
+          selector: '*',
+          command: newTerminalId
+        }
+      ]);
+      palette.add([
+        {
+          id: newTerminalId,
+          args: void 0
+        }
+      ]);
     }
   });
 }

+ 1 - 0
src/tsconfig.json

@@ -13,6 +13,7 @@
     "../typings/requirejs/requirejs.d.ts",
     "../typings/codemirror/codemirror.d.ts",
     "index.ts",
+    "application/plugin.ts",
     "filebrowser/index.ts",
     "filebrowser/plugin.ts",
     "filehandler/plugin.ts",