Skip to content

Commit

Permalink
add an html override extension (jupyter-server#218)
Browse files Browse the repository at this point in the history
  • Loading branch information
Steve Silvester authored and GitHub Enterprise committed Oct 18, 2021
1 parent c6c9749 commit cb3a59a
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 1 deletion.
4 changes: 3 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ import { kernelStatusPlugin } from './status';
import { FileRadarPlugin } from './fileradar';
import { SessionExpPlugin } from './sessionexp';
import { SyntaxHighlightPlugin } from './syntax-highlight';
import { HTMLReplacementPlugin } from './overridehtml';

const plugins: JupyterFrontEndPlugin<any>[] = [
kernelStatusPlugin,
ExternalLinksPlugin,
FileRadarPlugin,
SessionExpPlugin,
SyntaxHighlightPlugin
SyntaxHighlightPlugin,
HTMLReplacementPlugin
];

export default plugins;
54 changes: 54 additions & 0 deletions src/overridehtml.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import {
JupyterFrontEnd,
JupyterFrontEndPlugin
} from '@jupyterlab/application';

import { ReadonlyPartialJSONObject } from '@lumino/coreutils';

import {
IRenderMime,
IRenderMimeRegistry,
RenderedHTML
} from '@jupyterlab/rendermime';

class CustomRenderedHTML extends RenderedHTML {
/**
* Render a mime model as html content, replacing unsupported output.
*/
render(model: IRenderMime.IMimeModel): Promise<void> {
const data = { ...model.data };
const html = data['text/html'];
// Replace html as needed.
if (html && typeof html === 'string') {
// Look for PixieDust-related content
if (html.indexOf('#twistie') !== -1 || html.indexOf('pd_save') !== -1) {
data['text/html'] =
'<h2>PixieDust is not yet supported in JupyterLab</h2>';
// Look for jQuery content
} else if (html.indexOf('$(') !== -1) {
data['text/html'] = '<h2>JQuery is not supported in JupyterLab</h2>';
}
}
return super.render({ ...model, data: data as ReadonlyPartialJSONObject });
}
}

/**
* HTML Replacement plugin.
*/
export const HTMLReplacementPlugin: JupyterFrontEndPlugin<void> = {
id: 'data_studio:html_replacement_plugin',
autoStart: true,
requires: [IRenderMimeRegistry],
activate: async (app: JupyterFrontEnd, registry: IRenderMimeRegistry) => {
console.log('JupyterLab extension "HTML Replacement" is activated!');

const factory: IRenderMime.IRendererFactory = {
safe: true,
mimeTypes: ['text/html'],
defaultRank: 50,
createRenderer: options => new CustomRenderedHTML(options)
};
registry.addFactory(factory, 50);
}
};
70 changes: 70 additions & 0 deletions test/overridehtml.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { JupyterLab } from '@jupyterlab/application';

import {
IRenderMimeRegistry,
RenderMimeRegistry,
standardRendererFactories
} from '@jupyterlab/rendermime';

import { HTMLReplacementPlugin } from '../src/overridehtml';

import { defaultSanitizer } from '@jupyterlab/apputils';

describe('html override', () => {
let app: JupyterLab;
let registry: IRenderMimeRegistry;
const sanitizer = defaultSanitizer;
const options = {
mimeType: 'text/html',
sanitizer,
resolver: null,
linkHandler: null,
latexTypesetter: null
};

beforeEach(async () => {
app = new JupyterLab();
registry = new RenderMimeRegistry({
initialFactories: standardRendererFactories
});
});

it('should replace pixiedust content', async () => {
await HTMLReplacementPlugin.activate(app, registry);
const data = { 'text/html': '$("#twistie6a9330b3").click(function()' };
const factory = registry.getFactory('text/html');
const renderer = factory!.createRenderer(options);
await renderer.renderModel(registry.createModel({ data }));
expect(renderer.node.innerHTML).toBe(
'<h2>PixieDust is not yet supported in JupyterLab</h2>'
);

data['text/html'] = '<div class="pd_save is-viewer-good" style="';
await renderer.renderModel(registry.createModel({ data }));
expect(renderer.node.innerHTML).toBe(
'<h2>PixieDust is not yet supported in JupyterLab</h2>'
);
});

it('should handle jQuery content', async () => {
await HTMLReplacementPlugin.activate(app, registry);
const data = { 'text/html': '$(foo)' };
const model = registry.createModel({ data });
const factory = registry.getFactory('text/html');
const renderer = factory!.createRenderer(options);
await renderer.renderModel(model);
expect(renderer.node.innerHTML).toBe(
'<h2>JQuery is not supported in JupyterLab</h2>'
);
});

it('should pass other content throught', async () => {
await HTMLReplacementPlugin.activate(app, registry);
const data = { 'text/html': '<h1>hello,world!</h1>' };
const model = registry.createModel({ data });
const factory = registry.getFactory('text/html');
const renderer = factory!.createRenderer(options);
await renderer.renderModel(model);
expect(renderer.node.innerHTML).toBe('<h1>hello,world!</h1>');
});
});

0 comments on commit cb3a59a

Please sign in to comment.