@jupyterlab/htmlviewer 4.0.0-alpha.8 → 4.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.js +4 -1
- package/lib/index.js.map +1 -1
- package/package.json +13 -12
- package/src/index.tsx +346 -0
- package/style/base.css +1 -1
package/lib/index.js
CHANGED
|
@@ -43,7 +43,10 @@ export class HTMLViewer extends DocumentWidget {
|
|
|
43
43
|
* Create a new widget for rendering HTML.
|
|
44
44
|
*/
|
|
45
45
|
constructor(options) {
|
|
46
|
-
super(
|
|
46
|
+
super({
|
|
47
|
+
...options,
|
|
48
|
+
content: new IFrame({ sandbox: ['allow-same-origin'] })
|
|
49
|
+
});
|
|
47
50
|
this._renderPending = false;
|
|
48
51
|
this._parser = new DOMParser();
|
|
49
52
|
this._monitor = null;
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA;;;+EAG+E;AAC/E;;;GAGG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EACL,gBAAgB,EAEhB,cAAc,EAEf,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAe,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EACL,MAAM,EACN,WAAW,EACX,WAAW,EACX,aAAa,EACb,sBAAsB,EACtB,SAAS,EACV,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAW,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAO/B;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,KAAK,CACzC,2CAA2C,CAC5C,CAAC;AACF;;GAEG;AACH,MAAM,cAAc,GAAG,IAAI,CAAC;AAE5B;;GAEG;AACH,MAAM,SAAS,GAAG,eAAe,CAAC;AAElC;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,UACX,SAAQ,cAAsB;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jupyterlab/htmlviewer",
|
|
3
|
-
"version": "4.0.0-
|
|
3
|
+
"version": "4.0.0-beta.0",
|
|
4
4
|
"description": "A viewer for HTML documents.",
|
|
5
5
|
"homepage": "https://github.com/jupyterlab/jupyterlab",
|
|
6
6
|
"bugs": {
|
|
@@ -24,7 +24,8 @@
|
|
|
24
24
|
"files": [
|
|
25
25
|
"lib/**/*.{d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf}",
|
|
26
26
|
"style/**/*.{css,eot,gif,html,jpg,json,png,svg,woff2,ttf}",
|
|
27
|
-
"style/index.js"
|
|
27
|
+
"style/index.js",
|
|
28
|
+
"src/**/*.{ts,tsx}"
|
|
28
29
|
],
|
|
29
30
|
"scripts": {
|
|
30
31
|
"build": "tsc -b",
|
|
@@ -32,19 +33,19 @@
|
|
|
32
33
|
"watch": "tsc -w --listEmittedFiles"
|
|
33
34
|
},
|
|
34
35
|
"dependencies": {
|
|
35
|
-
"@jupyterlab/apputils": "^4.0.0-
|
|
36
|
-
"@jupyterlab/coreutils": "^6.0.0-
|
|
37
|
-
"@jupyterlab/docregistry": "^4.0.0-
|
|
38
|
-
"@jupyterlab/translation": "^4.0.0-
|
|
39
|
-
"@jupyterlab/ui-components": "^4.0.0-
|
|
40
|
-
"@lumino/coreutils": "^
|
|
41
|
-
"@lumino/signaling": "^
|
|
42
|
-
"@lumino/widgets": "^
|
|
43
|
-
"react": "^
|
|
36
|
+
"@jupyterlab/apputils": "^4.0.0-beta.0",
|
|
37
|
+
"@jupyterlab/coreutils": "^6.0.0-beta.0",
|
|
38
|
+
"@jupyterlab/docregistry": "^4.0.0-beta.0",
|
|
39
|
+
"@jupyterlab/translation": "^4.0.0-beta.0",
|
|
40
|
+
"@jupyterlab/ui-components": "^4.0.0-beta.0",
|
|
41
|
+
"@lumino/coreutils": "^2.0.0",
|
|
42
|
+
"@lumino/signaling": "^2.0.0",
|
|
43
|
+
"@lumino/widgets": "^2.0.0",
|
|
44
|
+
"react": "^18.2.0"
|
|
44
45
|
},
|
|
45
46
|
"devDependencies": {
|
|
46
47
|
"rimraf": "~3.0.0",
|
|
47
|
-
"typescript": "~
|
|
48
|
+
"typescript": "~5.0.2"
|
|
48
49
|
},
|
|
49
50
|
"publishConfig": {
|
|
50
51
|
"access": "public"
|
package/src/index.tsx
ADDED
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
/* -----------------------------------------------------------------------------
|
|
2
|
+
| Copyright (c) Jupyter Development Team.
|
|
3
|
+
| Distributed under the terms of the Modified BSD License.
|
|
4
|
+
|----------------------------------------------------------------------------*/
|
|
5
|
+
/**
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
* @module htmlviewer
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { IWidgetTracker } from '@jupyterlab/apputils';
|
|
11
|
+
import { ActivityMonitor } from '@jupyterlab/coreutils';
|
|
12
|
+
import {
|
|
13
|
+
ABCWidgetFactory,
|
|
14
|
+
DocumentRegistry,
|
|
15
|
+
DocumentWidget,
|
|
16
|
+
IDocumentWidget
|
|
17
|
+
} from '@jupyterlab/docregistry';
|
|
18
|
+
import { ITranslator, nullTranslator } from '@jupyterlab/translation';
|
|
19
|
+
import {
|
|
20
|
+
IFrame,
|
|
21
|
+
ReactWidget,
|
|
22
|
+
refreshIcon,
|
|
23
|
+
ToolbarButton,
|
|
24
|
+
ToolbarButtonComponent,
|
|
25
|
+
UseSignal
|
|
26
|
+
} from '@jupyterlab/ui-components';
|
|
27
|
+
import { Token } from '@lumino/coreutils';
|
|
28
|
+
import { ISignal, Signal } from '@lumino/signaling';
|
|
29
|
+
import { Widget } from '@lumino/widgets';
|
|
30
|
+
import * as React from 'react';
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* A class that tracks HTML viewer widgets.
|
|
34
|
+
*/
|
|
35
|
+
export interface IHTMLViewerTracker extends IWidgetTracker<HTMLViewer> {}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The HTML viewer tracker token.
|
|
39
|
+
*/
|
|
40
|
+
export const IHTMLViewerTracker = new Token<IHTMLViewerTracker>(
|
|
41
|
+
'@jupyterlab/htmlviewer:IHTMLViewerTracker'
|
|
42
|
+
);
|
|
43
|
+
/**
|
|
44
|
+
* The timeout to wait for change activity to have ceased before rendering.
|
|
45
|
+
*/
|
|
46
|
+
const RENDER_TIMEOUT = 1000;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* The CSS class to add to the HTMLViewer Widget.
|
|
50
|
+
*/
|
|
51
|
+
const CSS_CLASS = 'jp-HTMLViewer';
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* A viewer widget for HTML documents.
|
|
55
|
+
*
|
|
56
|
+
* #### Notes
|
|
57
|
+
* The iframed HTML document can pose a potential security risk,
|
|
58
|
+
* since it can execute Javascript, and make same-origin requests
|
|
59
|
+
* to the server, thereby executing arbitrary Javascript.
|
|
60
|
+
*
|
|
61
|
+
* Here, we sandbox the iframe so that it can't execute Javascript
|
|
62
|
+
* or launch any popups. We allow one exception: 'allow-same-origin'
|
|
63
|
+
* requests, so that local HTML documents can access CSS, images,
|
|
64
|
+
* etc from the files system.
|
|
65
|
+
*/
|
|
66
|
+
export class HTMLViewer
|
|
67
|
+
extends DocumentWidget<IFrame>
|
|
68
|
+
implements IDocumentWidget<IFrame>
|
|
69
|
+
{
|
|
70
|
+
/**
|
|
71
|
+
* Create a new widget for rendering HTML.
|
|
72
|
+
*/
|
|
73
|
+
constructor(options: DocumentWidget.IOptionsOptionalContent) {
|
|
74
|
+
super({
|
|
75
|
+
...options,
|
|
76
|
+
content: new IFrame({ sandbox: ['allow-same-origin'] })
|
|
77
|
+
});
|
|
78
|
+
this.translator = options.translator || nullTranslator;
|
|
79
|
+
this.content.addClass(CSS_CLASS);
|
|
80
|
+
|
|
81
|
+
void this.context.ready.then(() => {
|
|
82
|
+
this.update();
|
|
83
|
+
// Throttle the rendering rate of the widget.
|
|
84
|
+
this._monitor = new ActivityMonitor({
|
|
85
|
+
signal: this.context.model.contentChanged,
|
|
86
|
+
timeout: RENDER_TIMEOUT
|
|
87
|
+
});
|
|
88
|
+
this._monitor.activityStopped.connect(this.update, this);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Whether the HTML document is trusted. If trusted,
|
|
94
|
+
* it can execute Javascript in the iframe sandbox.
|
|
95
|
+
*/
|
|
96
|
+
get trusted(): boolean {
|
|
97
|
+
return this.content.sandbox.indexOf('allow-scripts') !== -1;
|
|
98
|
+
}
|
|
99
|
+
set trusted(value: boolean) {
|
|
100
|
+
if (this.trusted === value) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (value) {
|
|
104
|
+
this.content.sandbox = Private.trusted;
|
|
105
|
+
} else {
|
|
106
|
+
this.content.sandbox = Private.untrusted;
|
|
107
|
+
}
|
|
108
|
+
// eslint-disable-next-line
|
|
109
|
+
this.content.url = this.content.url; // Force a refresh.
|
|
110
|
+
this._trustedChanged.emit(value);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Emitted when the trust state of the document changes.
|
|
115
|
+
*/
|
|
116
|
+
get trustedChanged(): ISignal<this, boolean> {
|
|
117
|
+
return this._trustedChanged;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Dispose of resources held by the html viewer.
|
|
122
|
+
*/
|
|
123
|
+
dispose(): void {
|
|
124
|
+
if (this._objectUrl) {
|
|
125
|
+
try {
|
|
126
|
+
URL.revokeObjectURL(this._objectUrl);
|
|
127
|
+
} catch (error) {
|
|
128
|
+
/* no-op */
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
super.dispose();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Handle and update request.
|
|
136
|
+
*/
|
|
137
|
+
protected onUpdateRequest(): void {
|
|
138
|
+
if (this._renderPending) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
this._renderPending = true;
|
|
142
|
+
void this._renderModel().then(() => (this._renderPending = false));
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Render HTML in IFrame into this widget's node.
|
|
147
|
+
*/
|
|
148
|
+
private async _renderModel(): Promise<void> {
|
|
149
|
+
let data = this.context.model.toString();
|
|
150
|
+
data = await this._setBase(data);
|
|
151
|
+
|
|
152
|
+
// Set the new iframe url.
|
|
153
|
+
const blob = new Blob([data], { type: 'text/html' });
|
|
154
|
+
const oldUrl = this._objectUrl;
|
|
155
|
+
this._objectUrl = URL.createObjectURL(blob);
|
|
156
|
+
this.content.url = this._objectUrl;
|
|
157
|
+
|
|
158
|
+
// Release reference to any previous object url.
|
|
159
|
+
if (oldUrl) {
|
|
160
|
+
try {
|
|
161
|
+
URL.revokeObjectURL(oldUrl);
|
|
162
|
+
} catch (error) {
|
|
163
|
+
/* no-op */
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Set a <base> element in the HTML string so that the iframe
|
|
171
|
+
* can correctly dereference relative links.
|
|
172
|
+
*/
|
|
173
|
+
private async _setBase(data: string): Promise<string> {
|
|
174
|
+
const doc = this._parser.parseFromString(data, 'text/html');
|
|
175
|
+
let base = doc.querySelector('base');
|
|
176
|
+
if (!base) {
|
|
177
|
+
base = doc.createElement('base');
|
|
178
|
+
doc.head.insertBefore(base, doc.head.firstChild);
|
|
179
|
+
}
|
|
180
|
+
const path = this.context.path;
|
|
181
|
+
const baseUrl = await this.context.urlResolver.getDownloadUrl(path);
|
|
182
|
+
|
|
183
|
+
// Set the base href, plus a fake name for the url of this
|
|
184
|
+
// document. The fake name doesn't really matter, as long
|
|
185
|
+
// as the document can dereference relative links to resources
|
|
186
|
+
// (e.g. CSS and scripts).
|
|
187
|
+
base.href = baseUrl;
|
|
188
|
+
base.target = '_self';
|
|
189
|
+
return doc.documentElement.innerHTML;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
protected translator: ITranslator;
|
|
193
|
+
private _renderPending = false;
|
|
194
|
+
private _parser = new DOMParser();
|
|
195
|
+
private _monitor: ActivityMonitor<DocumentRegistry.IModel, void> | null =
|
|
196
|
+
null;
|
|
197
|
+
private _objectUrl: string = '';
|
|
198
|
+
private _trustedChanged = new Signal<this, boolean>(this);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* A widget factory for HTMLViewers.
|
|
203
|
+
*/
|
|
204
|
+
export class HTMLViewerFactory extends ABCWidgetFactory<HTMLViewer> {
|
|
205
|
+
/**
|
|
206
|
+
* Create a new widget given a context.
|
|
207
|
+
*/
|
|
208
|
+
protected createNewWidget(context: DocumentRegistry.Context): HTMLViewer {
|
|
209
|
+
return new HTMLViewer({ context });
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Default factory for toolbar items to be added after the widget is created.
|
|
214
|
+
*/
|
|
215
|
+
protected defaultToolbarFactory(
|
|
216
|
+
widget: HTMLViewer
|
|
217
|
+
): DocumentRegistry.IToolbarItem[] {
|
|
218
|
+
return [
|
|
219
|
+
// Make a refresh button for the toolbar.
|
|
220
|
+
{
|
|
221
|
+
name: 'refresh',
|
|
222
|
+
widget: ToolbarItems.createRefreshButton(widget, this.translator)
|
|
223
|
+
},
|
|
224
|
+
// Make a trust button for the toolbar.
|
|
225
|
+
{
|
|
226
|
+
name: 'trust',
|
|
227
|
+
widget: ToolbarItems.createTrustButton(widget, this.translator)
|
|
228
|
+
}
|
|
229
|
+
];
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* A namespace for toolbar items generator
|
|
235
|
+
*/
|
|
236
|
+
export namespace ToolbarItems {
|
|
237
|
+
/**
|
|
238
|
+
* Create the refresh button
|
|
239
|
+
*
|
|
240
|
+
* @param widget HTML viewer widget
|
|
241
|
+
* @param translator Application translator object
|
|
242
|
+
* @returns Toolbar item button
|
|
243
|
+
*/
|
|
244
|
+
export function createRefreshButton(
|
|
245
|
+
widget: HTMLViewer,
|
|
246
|
+
translator?: ITranslator
|
|
247
|
+
): Widget {
|
|
248
|
+
const trans = (translator ?? nullTranslator).load('jupyterlab');
|
|
249
|
+
return new ToolbarButton({
|
|
250
|
+
icon: refreshIcon,
|
|
251
|
+
onClick: async () => {
|
|
252
|
+
if (!widget.context.model.dirty) {
|
|
253
|
+
await widget.context.revert();
|
|
254
|
+
widget.update();
|
|
255
|
+
}
|
|
256
|
+
},
|
|
257
|
+
tooltip: trans.__('Rerender HTML Document')
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Create the trust button
|
|
262
|
+
*
|
|
263
|
+
* @param document HTML viewer widget
|
|
264
|
+
* @param translator Application translator object
|
|
265
|
+
* @returns Toolbar item button
|
|
266
|
+
*/
|
|
267
|
+
export function createTrustButton(
|
|
268
|
+
document: HTMLViewer,
|
|
269
|
+
translator: ITranslator
|
|
270
|
+
): Widget {
|
|
271
|
+
return ReactWidget.create(
|
|
272
|
+
<Private.TrustButtonComponent
|
|
273
|
+
htmlDocument={document}
|
|
274
|
+
translator={translator}
|
|
275
|
+
/>
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* A namespace for private data.
|
|
282
|
+
*/
|
|
283
|
+
namespace Private {
|
|
284
|
+
/**
|
|
285
|
+
* Sandbox exceptions for untrusted HTML.
|
|
286
|
+
*/
|
|
287
|
+
export const untrusted: IFrame.SandboxExceptions[] = [];
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Sandbox exceptions for trusted HTML.
|
|
291
|
+
*/
|
|
292
|
+
export const trusted: IFrame.SandboxExceptions[] = ['allow-scripts'];
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Namespace for TrustedButton.
|
|
296
|
+
*/
|
|
297
|
+
export namespace TrustButtonComponent {
|
|
298
|
+
/**
|
|
299
|
+
* Interface for TrustedButton props.
|
|
300
|
+
*/
|
|
301
|
+
export interface IProps {
|
|
302
|
+
htmlDocument: HTMLViewer;
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Language translator.
|
|
306
|
+
*/
|
|
307
|
+
translator?: ITranslator;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* React component for a trusted button.
|
|
313
|
+
*
|
|
314
|
+
* This wraps the ToolbarButtonComponent and watches for trust changes.
|
|
315
|
+
*/
|
|
316
|
+
export function TrustButtonComponent(
|
|
317
|
+
props: TrustButtonComponent.IProps
|
|
318
|
+
): JSX.Element {
|
|
319
|
+
const translator = props.translator || nullTranslator;
|
|
320
|
+
const trans = translator.load('jupyterlab');
|
|
321
|
+
return (
|
|
322
|
+
<UseSignal
|
|
323
|
+
signal={props.htmlDocument.trustedChanged}
|
|
324
|
+
initialSender={props.htmlDocument}
|
|
325
|
+
>
|
|
326
|
+
{() => (
|
|
327
|
+
<ToolbarButtonComponent
|
|
328
|
+
className=""
|
|
329
|
+
onClick={() =>
|
|
330
|
+
(props.htmlDocument.trusted = !props.htmlDocument.trusted)
|
|
331
|
+
}
|
|
332
|
+
tooltip={trans.__(`Whether the HTML file is trusted.
|
|
333
|
+
Trusting the file allows scripts to run in it,
|
|
334
|
+
which may result in security risks.
|
|
335
|
+
Only enable for files you trust.`)}
|
|
336
|
+
label={
|
|
337
|
+
props.htmlDocument.trusted
|
|
338
|
+
? trans.__('Distrust HTML')
|
|
339
|
+
: trans.__('Trust HTML')
|
|
340
|
+
}
|
|
341
|
+
/>
|
|
342
|
+
)}
|
|
343
|
+
</UseSignal>
|
|
344
|
+
);
|
|
345
|
+
}
|
|
346
|
+
}
|
package/style/base.css
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
/*
|
|
20
|
-
When drag events occur, `
|
|
20
|
+
When drag events occur, `lm-mod-override-cursor` is added to the body.
|
|
21
21
|
Because iframes steal all cursor events, the following two rules are necessary
|
|
22
22
|
to suppress pointer events while resize drags are occurring. There may be a
|
|
23
23
|
better solution to this problem.
|