Browse Source

#8494: add text-based image view, fix token doc

Nicholas Bollweg 4 years ago
parent
commit
8775433ebe

+ 58 - 22
packages/imageviewer-extension/src/index.ts

@@ -9,7 +9,7 @@ import {
 
 import { ICommandPalette, WidgetTracker } from '@jupyterlab/apputils';
 
-import { IDocumentWidget } from '@jupyterlab/docregistry';
+import { IDocumentWidget, DocumentRegistry } from '@jupyterlab/docregistry';
 
 import {
   ImageViewer,
@@ -41,13 +41,28 @@ namespace CommandIDs {
 /**
  * The list of file types for images.
  */
-const FILE_TYPES = ['png', 'gif', 'jpeg', 'svg', 'bmp', 'ico', 'xbm', 'tiff'];
+const FILE_TYPES = ['png', 'gif', 'jpeg', 'bmp', 'ico', 'tiff'];
 
 /**
  * The name of the factory that creates image widgets.
  */
 const FACTORY = 'Image';
 
+/**
+ * The name of the factory that creates image widgets.
+ */
+const TEXT_FACTORY = 'Image (Text)';
+
+/**
+ * The list of file types for images with optional text modes.
+ */
+const TEXT_FILE_TYPES = ['svg', 'xbm'];
+
+/**
+ * The test pattern for text file types in paths.
+ */
+const TEXT_FILE_REGEX = new RegExp(`\.(${TEXT_FILE_TYPES.join('|')})$`);
+
 /**
  * The image file handler extension.
  */
@@ -73,13 +88,47 @@ function activate(
   restorer: ILayoutRestorer | null
 ): IImageTracker {
   const namespace = 'image-widget';
+
+  function onWidgetCreated(
+    sender: any,
+    widget: IDocumentWidget<ImageViewer, DocumentRegistry.IModel>
+  ) {
+    // Notify the widget tracker if restore data needs to update.
+    widget.context.pathChanged.connect(() => {
+      void tracker.save(widget);
+    });
+    void tracker.add(widget);
+
+    const types = app.docRegistry.getFileTypesForPath(widget.context.path);
+
+    if (types.length > 0) {
+      widget.title.icon = types[0].icon!;
+      widget.title.iconClass = types[0].iconClass ?? '';
+      widget.title.iconLabel = types[0].iconLabel ?? '';
+    }
+  }
+
   const factory = new ImageViewerFactory({
     name: FACTORY,
     modelName: 'base64',
-    fileTypes: FILE_TYPES,
+    fileTypes: [...FILE_TYPES, ...TEXT_FILE_TYPES],
     defaultFor: FILE_TYPES,
     readOnly: true
   });
+
+  const textFactory = new ImageViewerFactory({
+    name: TEXT_FACTORY,
+    modelName: 'text',
+    fileTypes: TEXT_FILE_TYPES,
+    defaultFor: TEXT_FILE_TYPES,
+    readOnly: true
+  });
+
+  [factory, textFactory].forEach(factory => {
+    app.docRegistry.addWidgetFactory(factory);
+    factory.widgetCreated.connect(onWidgetCreated);
+  });
+
   const tracker = new WidgetTracker<IDocumentWidget<ImageViewer>>({
     namespace
   });
@@ -88,29 +137,16 @@ function activate(
     // Handle state restoration.
     void restorer.restore(tracker, {
       command: 'docmanager:open',
-      args: widget => ({ path: widget.context.path, factory: FACTORY }),
+      args: widget => ({
+        path: widget.context.path,
+        factory: TEXT_FILE_REGEX.test(widget.context.path)
+          ? TEXT_FACTORY
+          : FACTORY
+      }),
       name: widget => widget.context.path
     });
   }
 
-  app.docRegistry.addWidgetFactory(factory);
-
-  factory.widgetCreated.connect((sender, widget) => {
-    // Notify the widget tracker if restore data needs to update.
-    widget.context.pathChanged.connect(() => {
-      void tracker.save(widget);
-    });
-    void tracker.add(widget);
-
-    const types = app.docRegistry.getFileTypesForPath(widget.context.path);
-
-    if (types.length > 0) {
-      widget.title.icon = types[0].icon!;
-      widget.title.iconClass = types[0].iconClass ?? '';
-      widget.title.iconLabel = types[0].iconLabel ?? '';
-    }
-  });
-
   addCommands(app, tracker);
 
   if (palette) {

+ 2 - 2
packages/imageviewer/src/tokens.ts

@@ -10,14 +10,14 @@ import { Token } from '@lumino/coreutils';
 import { ImageViewer } from './widget';
 
 /**
- * A class that tracks editor widgets.
+ * A class that tracks image widgets.
  */
 export interface IImageTracker
   extends IWidgetTracker<IDocumentWidget<ImageViewer>> {}
 
 /* tslint:disable */
 /**
- * The editor tracker token.
+ * The image tracker token.
  */
 export const IImageTracker = new Token<IImageTracker>(
   '@jupyterlab/imageviewer:IImageTracker'

+ 5 - 4
packages/imageviewer/src/widget.ts

@@ -47,7 +47,6 @@ export class ImageViewer extends Widget implements Printing.IPrintable {
         return;
       }
       const contents = context.contentsModel!;
-      this._format = contents.format === 'base64' ? ';base64' : '';
       this._mimeType = contents.mimetype;
       this._render();
       context.model.contentChanged.connect(this.update, this);
@@ -179,8 +178,11 @@ export class ImageViewer extends Widget implements Printing.IPrintable {
     if (!cm) {
       return;
     }
-    const content = context.model.toString();
-    this._img.src = `data:${this._mimeType}${this._format},${content}`;
+    let content = context.model.toString();
+    if (cm.format !== 'base64') {
+      content = btoa(content);
+    }
+    this._img.src = `data:${this._mimeType};base64,${content}`;
   }
 
   /**
@@ -196,7 +198,6 @@ export class ImageViewer extends Widget implements Printing.IPrintable {
     this._img.style.filter = `invert(${this._colorinversion})`;
   }
 
-  private _format: string;
   private _mimeType: string;
   private _scale = 1;
   private _matrix = [1, 0, 0, 1];