Browse Source

Merge pull request #3399 from blink1073/isolated-metadata

Handle isolated metadata
Brian E. Granger 7 years ago
parent
commit
3f582ab636

+ 1 - 0
packages/outputarea/package.json

@@ -34,6 +34,7 @@
     "@jupyterlab/coreutils": "^0.13.0",
     "@jupyterlab/coreutils": "^0.13.0",
     "@jupyterlab/observables": "^0.2.0",
     "@jupyterlab/observables": "^0.2.0",
     "@jupyterlab/rendermime": "^0.13.0",
     "@jupyterlab/rendermime": "^0.13.0",
+    "@jupyterlab/rendermime-interfaces": "^0.4.3",
     "@jupyterlab/services": "^0.52.0",
     "@jupyterlab/services": "^0.52.0",
     "@phosphor/algorithm": "^1.1.2",
     "@phosphor/algorithm": "^1.1.2",
     "@phosphor/coreutils": "^1.3.0",
     "@phosphor/coreutils": "^1.3.0",

+ 83 - 2
packages/outputarea/src/widget.ts

@@ -2,7 +2,7 @@
 // Distributed under the terms of the Modified BSD License.
 // Distributed under the terms of the Modified BSD License.
 
 
 import {
 import {
-  JSONObject
+  JSONObject, ReadonlyJSONObject
 } from '@phosphor/coreutils';
 } from '@phosphor/coreutils';
 
 
 import {
 import {
@@ -30,9 +30,13 @@ import {
 } from '@jupyterlab/coreutils';
 } from '@jupyterlab/coreutils';
 
 
 import {
 import {
-  IOutputModel, RenderMimeRegistry
+ IOutputModel, RenderMimeRegistry
 } from '@jupyterlab/rendermime';
 } from '@jupyterlab/rendermime';
 
 
+import {
+  IRenderMime
+} from '@jupyterlab/rendermime-interfaces';
+
 import {
 import {
   Kernel, KernelMessage
   Kernel, KernelMessage
 } from '@jupyterlab/services';
 } from '@jupyterlab/services';
@@ -348,7 +352,21 @@ class OutputArea extends Widget {
       model.data, !model.trusted
       model.data, !model.trusted
     );
     );
     if (mimeType) {
     if (mimeType) {
+      let metadata = model.metadata;
+      let mimeMd = metadata[mimeType] as ReadonlyJSONObject;
+      let isolated = false;
+      // mime-specific higher priority
+      if (mimeMd && mimeMd['isolated'] !== undefined) {
+        isolated = mimeMd['isolated'] as boolean;
+      } else {
+        // fallback on global
+        isolated = metadata['isolated'] as boolean;
+      }
+
       let output = this.rendermime.createRenderer(mimeType);
       let output = this.rendermime.createRenderer(mimeType);
+      if (isolated === true) {
+        output = new Private.IsolatedRenderer(output);
+      }
       output.renderModel(model);
       output.renderModel(model);
       output.addClass(OUTPUT_AREA_OUTPUT_CLASS);
       output.addClass(OUTPUT_AREA_OUTPUT_CLASS);
       panel.addWidget(output);
       panel.addWidget(output);
@@ -708,4 +726,67 @@ namespace Private {
     node.appendChild(input);
     node.appendChild(input);
     return node;
     return node;
   }
   }
+
+  /**
+   * A renderer for IFrame data.
+   */
+  export
+  class IsolatedRenderer extends Widget implements IRenderMime.IRenderer {
+    /**
+     * Create an isolated renderer.
+     */
+    constructor(wrapped: IRenderMime.IRenderer) {
+      super({ node: document.createElement('iframe') });
+      this.addClass('jp-mod-isolated');
+
+      this._wrapped = wrapped;
+
+      // Once the iframe is loaded, the subarea is dynamically inserted
+      let iframe = this.node as HTMLIFrameElement;
+
+      iframe.frameBorder = '0';
+      iframe.scrolling = 'auto';
+
+      iframe.addEventListener('load', () => {
+        // Workaround needed by Firefox, to properly render svg inside
+        // iframes, see https://stackoverflow.com/questions/10177190/
+        // svg-dynamically-added-to-iframe-does-not-render-correctly
+        iframe.contentDocument.open();
+
+        // Insert the subarea into the iframe
+        // We must directly write the html. At this point, subarea doesn't
+        // contain any user content.
+        iframe.contentDocument.write(this._wrapped.node.innerHTML);
+
+        iframe.contentDocument.close();
+
+        let body = iframe.contentDocument.body;
+
+        // Adjust the iframe height automatically
+        iframe.style.height = body.scrollHeight + 'px';
+      });
+    }
+
+    /**
+     * Render a mime model.
+     *
+     * @param model - The mime model to render.
+     *
+     * @returns A promise which resolves when rendering is complete.
+     *
+     * #### Notes
+     * This method may be called multiple times during the lifetime
+     * of the widget to update it if and when new data is available.
+     */
+    renderModel(model: IRenderMime.IMimeModel): Promise<void> {
+      return this._wrapped.renderModel(model).then(() => {
+        let win = (this.node as HTMLIFrameElement).contentWindow;
+        if (win) {
+          win.location.reload();
+        }
+      });
+    }
+
+    private _wrapped: IRenderMime.IRenderer;
+  }
 }
 }

+ 30 - 0
packages/outputarea/style/index.css

@@ -56,6 +56,36 @@
 }
 }
 
 
 
 
+/**
+ * Isolated output.
+ */
+ .jp-OutputArea-output.jp-mod-isolated {
+  width: 100%;
+  display: block;
+}
+
+
+/*
+When drag events occur, `p-mod-override-cursor` is added to the body.
+Because iframes steal all cursor events, the following two rules are necessary
+to suppress pointer events while resize drags are occuring. There may be a
+better solution to this problem.
+*/
+body.p-mod-override-cursor .jp-OutputArea-output.jp-mod-isolated {
+  position: relative;
+}
+
+body.p-mod-override-cursor .jp-OutputArea-output.jp-mod-isolated:before {
+  content: '';
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  background: transparent;
+}
+
+
 /* pre */
 /* pre */
 
 
 .jp-OutputArea-output pre {
 .jp-OutputArea-output pre {

+ 1 - 1
test/package.json

@@ -8,7 +8,7 @@
     "coverage": "webpack --config webpack-cov.conf.js && python run-test.py karma-cov.conf.js",
     "coverage": "webpack --config webpack-cov.conf.js && python run-test.py karma-cov.conf.js",
     "test": "jlpm run test:firefox",
     "test": "jlpm run test:firefox",
     "test:chrome": "python run-test.py --browsers=Chrome karma.conf.js",
     "test:chrome": "python run-test.py --browsers=Chrome karma.conf.js",
-    "test:debug": "python run-test.py  --browsers=Chrome --singleRun=false --debug=true karma.conf.js",
+    "test:debug": "python run-test.py  --browsers=Chrome --singleRun=false --debug=true --browserNoActivityTimeout=10000000 karma.conf.js",
     "test:firefox": "python run-test.py --browsers=Firefox karma.conf.js",
     "test:firefox": "python run-test.py --browsers=Firefox karma.conf.js",
     "test:ie": "python run-test.py  --browsers=IE karma.conf.js",
     "test:ie": "python run-test.py  --browsers=IE karma.conf.js",
     "watch": "jlpm run clean && tsc && run-p watch:*",
     "watch": "jlpm run clean && tsc && run-p watch:*",