Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
djangoliv authored and djangoliv committed Sep 18, 2018
1 parent 62a7768 commit 654490a
Show file tree
Hide file tree
Showing 5 changed files with 311 additions and 0 deletions.
49 changes: 49 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"name": "HTMLViewer",
"version": "0.1.0",
"description": "A JupyterLab extension.",
"keywords": [
"jupyter",
"jupyterlab",
"jupyterlab-extension"
],
"homepage": "https://github.com/my_name/myextension",
"bugs": {
"url": "https://github.com/my_name/myextension/issues"
},
"license": "BSD-3-Clause",
"author": "logilab",
"files": [
"lib/**/*.{d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf}",
"style/**/*.{css,eot,gif,html,jpg,json,png,svg,woff2,ttf}"
],
"main": "lib/index.js",
"types": "lib/index.d.ts",
"repository": {
"type": "git",
"url": "https://github.com/my_name/myextension.git"
},
"scripts": {
"build": "tsc",
"clean": "rimraf lib",
"watch": "tsc -w",
"prepare": "npm run clean && npm run build"
},
"dependencies": {
"@jupyterlab/application": "^0.18.5",
"@jupyterlab/apputils": "^0.18.4",
"@jupyterlab/docmanager": "^0.18.4",
"@jupyterlab/docregistry": "^0.18.4",
"@jupyterlab/notebook": "^0.18.4",
"@phosphor/disposable": "^1.1.2",
"@types/react": "^16.4.14",
"@types/react-dom": "^16.0.7"
},
"devDependencies": {
"rimraf": "^2.6.1",
"typescript": "~2.9.2"
},
"jupyterlab": {
"extension": true
}
}
24 changes: 24 additions & 0 deletions src/htmlviewer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { IInstanceTracker } from '@jupyterlab/apputils';

import { IDocumentWidget } from '@jupyterlab/docregistry';

import { Token } from '@phosphor/coreutils';

import { HtmlViewer } from './widget';

export * from './widget';

/**
* A class that tracks editor widgets.
*/
export interface IHtmlTracker
extends IInstanceTracker<IDocumentWidget<HtmlViewer>> {}

/* tslint:disable */
/**
* The editor tracker token.
*/
export const IHtmlTracker = new Token<IHtmlTracker>(
'@jupyterlab/htmlviewer:IHtmlTracker'
);
/* tslint:enable */
91 changes: 91 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@

import {
ILayoutRestorer,
JupyterLab,
JupyterLabPlugin
} from '@jupyterlab/application';

import { ICommandPalette, InstanceTracker } from '@jupyterlab/apputils';

import { IDocumentWidget } from '@jupyterlab/docregistry';

import {
HtmlViewer,
HtmlViewerFactory,
IHtmlTracker
} from './htmlviewer';

/**
* The list of file types for html.
*/
const FILE_TYPES = ['html', 'xhtml'];

/**
* The name of the factory that creates html widgets.
*/
const FACTORY = 'Html';

/**
* The html file handler extension.
*/
const plugin: JupyterLabPlugin<IHtmlTracker> = {
activate,
id: '@jupyterlab/htmlviewer-extension:plugin',
provides: IHtmlTracker,
requires: [ICommandPalette, ILayoutRestorer],
autoStart: true
};

/**
* Export the plugin as default.
*/
export default plugin;

/**
* Activate the html widget extension.
*/
function activate(
app: JupyterLab,
palette: ICommandPalette,
restorer: ILayoutRestorer
): IHtmlTracker {
const namespace = 'html-widget';
const factory = new HtmlViewerFactory({
name: FACTORY,
modelName: 'base64',
fileTypes: FILE_TYPES,
defaultFor: FILE_TYPES,
readOnly: true
});
const tracker = new InstanceTracker<IDocumentWidget<HtmlViewer>>({
namespace
});

// Handle state restoration.
restorer.restore(tracker, {
command: 'docmanager:open',
args: widget => ({ path: widget.context.path, factory: FACTORY }),
name: widget => widget.context.path
});

app.docRegistry.addWidgetFactory(factory);

factory.widgetCreated.connect((sender, widget) => {
// Notify the instance tracker if restore data needs to update.
widget.context.pathChanged.connect(() => {
tracker.save(widget);
});
tracker.add(widget);

const types = app.docRegistry.getFileTypesForPath(widget.context.path);

if (types.length > 0) {
widget.title.iconClass = types[0].iconClass;
widget.title.iconLabel = types[0].iconLabel;
}
});

return tracker;
}


131 changes: 131 additions & 0 deletions src/widget.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import { PathExt } from '@jupyterlab/coreutils';

import {
ABCWidgetFactory,
DocumentRegistry,
IDocumentWidget,
DocumentWidget
} from '@jupyterlab/docregistry';

import { PromiseDelegate } from '@phosphor/coreutils';

import { Message } from '@phosphor/messaging';

import { Widget } from '@phosphor/widgets';

/**
* The class name added to a htmlviewer.
*/
const HTML_CLASS = 'jp-HtmlViewer';

/**
* A widget for HTML.
*/
export class HtmlViewer extends Widget {
/**
* Construct a new html widget.
*/
constructor(context: DocumentRegistry.Context) {
super();
this.context = context;
this.node.tabIndex = -1;
this.addClass(HTML_CLASS);

this._html = document.createElement('iframe');
this._html.setAttribute('height', "100%");
this._html.setAttribute('width', "100%");
this.node.appendChild(this._html);

this._onTitleChanged();
context.pathChanged.connect(
this._onTitleChanged,
this
);

context.ready.then(() => {
if (this.isDisposed) {
return;
}
this._render();
context.model.contentChanged.connect(
this.update,
this
);
context.fileChanged.connect(
this.update,
this
);
this._ready.resolve(void 0);
});
}

/**
* The html widget's context.
*/
readonly context: DocumentRegistry.Context;

/**
* A promise that resolves when the html viewer is ready.
*/
get ready(): Promise<void> {
return this._ready.promise;
}

/**
* Handle `update-request` messages for the widget.
*/
protected onUpdateRequest(msg: Message): void {
if (this.isDisposed || !this.context.isReady) {
return;
}
this._render();
}

/**
* Handle `'activate-request'` messages.
*/
protected onActivateRequest(msg: Message): void {
this.node.focus();
}

/**
* Handle a change to the title.
*/
private _onTitleChanged(): void {
this.title.label = PathExt.basename(this.context.localPath);
}

/**
* Render the widget content.
*/
private _render(): void {
let context = this.context;
let cm = context.contentsModel;
if (!cm) {
return;
}
let url = this.node.baseURI.replace("/lab", "/files/")+ this.context.path;
this._html.setAttribute('src', url);
}

private _ready = new PromiseDelegate<void>();
private _html: HTMLElement;
}

/**
* A widget factory for html
*/
export class HtmlViewerFactory extends ABCWidgetFactory<
IDocumentWidget<HtmlViewer>
> {
/**
* Create a new widget given a context.
*/
protected createNewWidget(
context: DocumentRegistry.IContext<DocumentRegistry.IModel>
): IDocumentWidget<HtmlViewer> {
const content = new HtmlViewer(context);
const widget = new DocumentWidget({ content, context });
return widget;
}
}
16 changes: 16 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"compilerOptions": {
"declaration": true,
"lib": ["es2015", "dom"],
"module": "commonjs",
"moduleResolution": "node",
"noEmitOnError": true,
"noUnusedLocals": true,
"outDir": "./lib",
"target": "es2015",
"strict": true,
"strictNullChecks": false,
"types": []
},
"include": ["src/*"]
}

0 comments on commit 654490a

Please sign in to comment.