@jupyterlab/rendermime 4.1.0-alpha.2 → 4.1.0-alpha.3
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/factories.d.ts +4 -0
- package/lib/factories.js +11 -5
- package/lib/factories.js.map +1 -1
- package/lib/registry.d.ts +8 -0
- package/lib/registry.js +45 -1
- package/lib/registry.js.map +1 -1
- package/lib/renderers.d.ts +42 -0
- package/lib/renderers.js +267 -73
- package/lib/renderers.js.map +1 -1
- package/lib/widgets.d.ts +4 -0
- package/lib/widgets.js +16 -0
- package/lib/widgets.js.map +1 -1
- package/package.json +11 -11
- package/src/factories.ts +12 -5
- package/src/registry.ts +48 -1
- package/src/renderers.ts +398 -81
- package/src/widgets.ts +18 -0
- package/style/base.css +7 -7
package/lib/factories.d.ts
CHANGED
|
@@ -19,6 +19,10 @@ export declare const markdownRendererFactory: IRenderMime.IRendererFactory;
|
|
|
19
19
|
* A mime renderer factory for svg.
|
|
20
20
|
*/
|
|
21
21
|
export declare const svgRendererFactory: IRenderMime.IRendererFactory;
|
|
22
|
+
/**
|
|
23
|
+
* A mime renderer factory for rendering stderr outputs
|
|
24
|
+
*/
|
|
25
|
+
export declare const errorRendererFactory: IRenderMime.IRendererFactory;
|
|
22
26
|
/**
|
|
23
27
|
* A mime renderer factory for plain and jupyter console text data.
|
|
24
28
|
*/
|
package/lib/factories.js
CHANGED
|
@@ -50,16 +50,21 @@ export const svgRendererFactory = {
|
|
|
50
50
|
defaultRank: 80,
|
|
51
51
|
createRenderer: options => new widgets.RenderedSVG(options)
|
|
52
52
|
};
|
|
53
|
+
/**
|
|
54
|
+
* A mime renderer factory for rendering stderr outputs
|
|
55
|
+
*/
|
|
56
|
+
export const errorRendererFactory = {
|
|
57
|
+
safe: true,
|
|
58
|
+
mimeTypes: ['application/vnd.jupyter.stderr'],
|
|
59
|
+
defaultRank: 110,
|
|
60
|
+
createRenderer: options => new widgets.RenderedError(options)
|
|
61
|
+
};
|
|
53
62
|
/**
|
|
54
63
|
* A mime renderer factory for plain and jupyter console text data.
|
|
55
64
|
*/
|
|
56
65
|
export const textRendererFactory = {
|
|
57
66
|
safe: true,
|
|
58
|
-
mimeTypes: [
|
|
59
|
-
'text/plain',
|
|
60
|
-
'application/vnd.jupyter.stdout',
|
|
61
|
-
'application/vnd.jupyter.stderr'
|
|
62
|
-
],
|
|
67
|
+
mimeTypes: ['text/plain', 'application/vnd.jupyter.stdout'],
|
|
63
68
|
defaultRank: 120,
|
|
64
69
|
createRenderer: options => new widgets.RenderedText(options)
|
|
65
70
|
};
|
|
@@ -82,6 +87,7 @@ export const standardRendererFactories = [
|
|
|
82
87
|
svgRendererFactory,
|
|
83
88
|
imageRendererFactory,
|
|
84
89
|
javaScriptRendererFactory,
|
|
90
|
+
errorRendererFactory,
|
|
85
91
|
textRendererFactory
|
|
86
92
|
];
|
|
87
93
|
//# sourceMappingURL=factories.js.map
|
package/lib/factories.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factories.js","sourceRoot":"","sources":["../src/factories.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,OAAO,MAAM,WAAW,CAAC;AAErC;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAiC;IAC/D,IAAI,EAAE,IAAI;IACV,SAAS,EAAE,CAAC,WAAW,CAAC;IACxB,WAAW,EAAE,EAAE;IACf,cAAc,EAAE,OAAO,CAAC,EAAE,CAAC,IAAI,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC;CAC7D,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAiC;IAChE,IAAI,EAAE,IAAI;IACV,SAAS,EAAE;QACT,WAAW;QACX,WAAW;QACX,YAAY;QACZ,WAAW;QACX,YAAY;KACb;IACD,WAAW,EAAE,EAAE;IACf,cAAc,EAAE,OAAO,CAAC,EAAE,CAAC,IAAI,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC;CAC9D,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAiC;IAChE,IAAI,EAAE,IAAI;IACV,SAAS,EAAE,CAAC,YAAY,CAAC;IACzB,WAAW,EAAE,EAAE;IACf,cAAc,EAAE,OAAO,CAAC,EAAE,CAAC,IAAI,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC;CAC9D,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAiC;IACnE,IAAI,EAAE,IAAI;IACV,SAAS,EAAE,CAAC,eAAe,CAAC;IAC5B,WAAW,EAAE,EAAE;IACf,cAAc,EAAE,OAAO,CAAC,EAAE,CAAC,IAAI,OAAO,CAAC,gBAAgB,CAAC,OAAO,CAAC;CACjE,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAiC;IAC9D,IAAI,EAAE,KAAK;IACX,SAAS,EAAE,CAAC,eAAe,CAAC;IAC5B,WAAW,EAAE,EAAE;IACf,cAAc,EAAE,OAAO,CAAC,EAAE,CAAC,IAAI,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC;CAC5D,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAiC;IAC/D,IAAI,EAAE,IAAI;IACV,SAAS,EAAE
|
|
1
|
+
{"version":3,"file":"factories.js","sourceRoot":"","sources":["../src/factories.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,OAAO,MAAM,WAAW,CAAC;AAErC;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAiC;IAC/D,IAAI,EAAE,IAAI;IACV,SAAS,EAAE,CAAC,WAAW,CAAC;IACxB,WAAW,EAAE,EAAE;IACf,cAAc,EAAE,OAAO,CAAC,EAAE,CAAC,IAAI,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC;CAC7D,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAiC;IAChE,IAAI,EAAE,IAAI;IACV,SAAS,EAAE;QACT,WAAW;QACX,WAAW;QACX,YAAY;QACZ,WAAW;QACX,YAAY;KACb;IACD,WAAW,EAAE,EAAE;IACf,cAAc,EAAE,OAAO,CAAC,EAAE,CAAC,IAAI,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC;CAC9D,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAiC;IAChE,IAAI,EAAE,IAAI;IACV,SAAS,EAAE,CAAC,YAAY,CAAC;IACzB,WAAW,EAAE,EAAE;IACf,cAAc,EAAE,OAAO,CAAC,EAAE,CAAC,IAAI,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC;CAC9D,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAiC;IACnE,IAAI,EAAE,IAAI;IACV,SAAS,EAAE,CAAC,eAAe,CAAC;IAC5B,WAAW,EAAE,EAAE;IACf,cAAc,EAAE,OAAO,CAAC,EAAE,CAAC,IAAI,OAAO,CAAC,gBAAgB,CAAC,OAAO,CAAC;CACjE,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAiC;IAC9D,IAAI,EAAE,KAAK;IACX,SAAS,EAAE,CAAC,eAAe,CAAC;IAC5B,WAAW,EAAE,EAAE;IACf,cAAc,EAAE,OAAO,CAAC,EAAE,CAAC,IAAI,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC;CAC5D,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAiC;IAChE,IAAI,EAAE,IAAI;IACV,SAAS,EAAE,CAAC,gCAAgC,CAAC;IAC7C,WAAW,EAAE,GAAG;IAChB,cAAc,EAAE,OAAO,CAAC,EAAE,CAAC,IAAI,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC;CAC9D,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAiC;IAC/D,IAAI,EAAE,IAAI;IACV,SAAS,EAAE,CAAC,YAAY,EAAE,gCAAgC,CAAC;IAC3D,WAAW,EAAE,GAAG;IAChB,cAAc,EAAE,OAAO,CAAC,EAAE,CAAC,IAAI,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC;CAC7D,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAiC;IACrE,IAAI,EAAE,KAAK;IACX,SAAS,EAAE,CAAC,iBAAiB,EAAE,wBAAwB,CAAC;IACxD,WAAW,EAAE,GAAG;IAChB,cAAc,EAAE,OAAO,CAAC,EAAE,CAAC,IAAI,OAAO,CAAC,kBAAkB,CAAC,OAAO,CAAC;CACnE,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,yBAAyB,GACpC;IACE,mBAAmB;IACnB,uBAAuB;IACvB,oBAAoB;IACpB,kBAAkB;IAClB,oBAAoB;IACpB,yBAAyB;IACzB,oBAAoB;IACpB,mBAAmB;CACpB,CAAC"}
|
package/lib/registry.d.ts
CHANGED
|
@@ -218,6 +218,14 @@ export declare namespace RenderMimeRegistry {
|
|
|
218
218
|
* manager.
|
|
219
219
|
*/
|
|
220
220
|
isLocal(url: string): boolean;
|
|
221
|
+
/**
|
|
222
|
+
* Resolve a path from Jupyter kernel to a path:
|
|
223
|
+
* - relative to `root_dir` (preferrably) this is in jupyter-server scope,
|
|
224
|
+
* - path understood and known by kernel (if such a path exists).
|
|
225
|
+
* Returns `null` if there is no file matching provided path in neither
|
|
226
|
+
* kernel nor jupyter-server contents manager.
|
|
227
|
+
*/
|
|
228
|
+
resolvePath(path: string): Promise<IRenderMime.IResolvedLocation | null>;
|
|
221
229
|
/**
|
|
222
230
|
* Whether the URL can be decoded using `decodeURI`.
|
|
223
231
|
*/
|
package/lib/registry.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
| Distributed under the terms of the Modified BSD License.
|
|
4
4
|
|----------------------------------------------------------------------------*/
|
|
5
5
|
import { Sanitizer } from '@jupyterlab/apputils';
|
|
6
|
-
import { PathExt, URLExt } from '@jupyterlab/coreutils';
|
|
6
|
+
import { PageConfig, PathExt, URLExt } from '@jupyterlab/coreutils';
|
|
7
7
|
import { nullTranslator } from '@jupyterlab/translation';
|
|
8
8
|
import { MimeModel } from './mimemodel';
|
|
9
9
|
/**
|
|
@@ -281,6 +281,50 @@ export class RenderMimeRegistry {
|
|
|
281
281
|
}
|
|
282
282
|
return URLExt.isLocal(url) || !!this._contents.driveName(decodeURI(url));
|
|
283
283
|
}
|
|
284
|
+
/**
|
|
285
|
+
* Resolve a path from Jupyter kernel to a path:
|
|
286
|
+
* - relative to `root_dir` (preferrably) this is in jupyter-server scope,
|
|
287
|
+
* - path understood and known by kernel (if such a path exists).
|
|
288
|
+
* Returns `null` if there is no file matching provided path in neither
|
|
289
|
+
* kernel nor jupyter-server contents manager.
|
|
290
|
+
*/
|
|
291
|
+
async resolvePath(path) {
|
|
292
|
+
// TODO: a clean implementation would be server-side and depends on:
|
|
293
|
+
// https://github.com/jupyter-server/jupyter_server/issues/1280
|
|
294
|
+
const rootDir = PageConfig.getOption('rootUri').replace('file://', '');
|
|
295
|
+
// Workaround: expand `~` path using root dir (if it matches).
|
|
296
|
+
if (path.startsWith('~/') && rootDir.startsWith('/home/')) {
|
|
297
|
+
// For now we assume that kernel is in root dir.
|
|
298
|
+
path = rootDir.split('/').slice(0, 3).join('/') + path.substring(1);
|
|
299
|
+
}
|
|
300
|
+
if (path.startsWith(rootDir) || path.startsWith('./')) {
|
|
301
|
+
try {
|
|
302
|
+
const relativePath = path.replace(rootDir, '');
|
|
303
|
+
// If file exists on the server we have guessed right
|
|
304
|
+
const response = await this._contents.get(relativePath, {
|
|
305
|
+
content: false
|
|
306
|
+
});
|
|
307
|
+
return {
|
|
308
|
+
path: response.path,
|
|
309
|
+
scope: 'server'
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
catch (error) {
|
|
313
|
+
// The file seems like should be on the server but is not.
|
|
314
|
+
console.warn(`Could not resolve location of ${path} on server`);
|
|
315
|
+
return null;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
// The file is not accessible from jupyter-server but maybe it is
|
|
319
|
+
// available from DAP `source`; we assume the path is available
|
|
320
|
+
// from kernel because currently we have no way of checking this
|
|
321
|
+
// without introducing a cycle (unless we were to set the debugger
|
|
322
|
+
// service instance on the resolver later).
|
|
323
|
+
return {
|
|
324
|
+
path: path,
|
|
325
|
+
scope: 'kernel'
|
|
326
|
+
};
|
|
327
|
+
}
|
|
284
328
|
/**
|
|
285
329
|
* Whether the URL can be decoded using `decodeURI`.
|
|
286
330
|
*/
|
package/lib/registry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;+EAG+E;AAC/E,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}
|
package/lib/renderers.d.ts
CHANGED
|
@@ -271,3 +271,45 @@ export declare namespace renderText {
|
|
|
271
271
|
translator?: ITranslator;
|
|
272
272
|
}
|
|
273
273
|
}
|
|
274
|
+
/**
|
|
275
|
+
* Render error into a host node.
|
|
276
|
+
*
|
|
277
|
+
* @param options - The options for rendering.
|
|
278
|
+
*
|
|
279
|
+
* @returns A promise which resolves when rendering is complete.
|
|
280
|
+
*/
|
|
281
|
+
export declare function renderError(options: renderError.IRenderOptions): Promise<void>;
|
|
282
|
+
/**
|
|
283
|
+
* The namespace for the `renderError` function statics.
|
|
284
|
+
*/
|
|
285
|
+
export declare namespace renderError {
|
|
286
|
+
/**
|
|
287
|
+
* The options for the `renderError` function.
|
|
288
|
+
*/
|
|
289
|
+
interface IRenderOptions {
|
|
290
|
+
/**
|
|
291
|
+
* The host node for the error content.
|
|
292
|
+
*/
|
|
293
|
+
host: HTMLElement;
|
|
294
|
+
/**
|
|
295
|
+
* The html sanitizer for untrusted source.
|
|
296
|
+
*/
|
|
297
|
+
sanitizer: IRenderMime.ISanitizer;
|
|
298
|
+
/**
|
|
299
|
+
* The source error to render.
|
|
300
|
+
*/
|
|
301
|
+
source: string;
|
|
302
|
+
/**
|
|
303
|
+
* An optional url resolver.
|
|
304
|
+
*/
|
|
305
|
+
resolver: IRenderMime.IResolver | null;
|
|
306
|
+
/**
|
|
307
|
+
* An optional link handler.
|
|
308
|
+
*/
|
|
309
|
+
linkHandler: IRenderMime.ILinkHandler | null;
|
|
310
|
+
/**
|
|
311
|
+
* The application language translator.
|
|
312
|
+
*/
|
|
313
|
+
translator?: ITranslator;
|
|
314
|
+
}
|
|
315
|
+
}
|
package/lib/renderers.js
CHANGED
|
@@ -218,46 +218,118 @@ export function renderSVG(options) {
|
|
|
218
218
|
}
|
|
219
219
|
return Promise.resolve();
|
|
220
220
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
*
|
|
224
|
-
* @param content - The text content of a node.
|
|
225
|
-
*
|
|
226
|
-
* @returns A list of text nodes and anchor elements.
|
|
227
|
-
*/
|
|
228
|
-
function autolink(content) {
|
|
221
|
+
var ILinker;
|
|
222
|
+
(function (ILinker) {
|
|
229
223
|
// Taken from Visual Studio Code:
|
|
230
224
|
// https://github.com/microsoft/vscode/blob/9f709d170b06e991502153f281ec3c012add2e42/src/vs/workbench/contrib/debug/browser/linkDetector.ts#L17-L18
|
|
231
225
|
const controlCodes = '\\u0000-\\u0020\\u007f-\\u009f';
|
|
232
|
-
|
|
226
|
+
ILinker.webLinkRegex = new RegExp('(?<path>(?:[a-zA-Z][a-zA-Z0-9+.-]{2,}:\\/\\/|data:|www\\.)[^\\s' +
|
|
233
227
|
controlCodes +
|
|
234
228
|
'"]{2,}[^\\s' +
|
|
235
229
|
controlCodes +
|
|
236
|
-
'"\'(){}\\[\\],:;.!?]', 'ug');
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
230
|
+
'"\'(){}\\[\\],:;.!?])', 'ug');
|
|
231
|
+
// Taken from Visual Studio Code:
|
|
232
|
+
// https://github.com/microsoft/vscode/blob/3e407526a1e2ff22cacb69c7e353e81a12f41029/extensions/notebook-renderers/src/linkify.ts#L9
|
|
233
|
+
const winAbsPathRegex = /(?:[a-zA-Z]:(?:(?:\\|\/)[\w\.-]*)+)/;
|
|
234
|
+
const winRelPathRegex = /(?:(?:\~|\.)(?:(?:\\|\/)[\w\.-]*)+)/;
|
|
235
|
+
const winPathRegex = new RegExp(`(${winAbsPathRegex.source}|${winRelPathRegex.source})`);
|
|
236
|
+
const posixPathRegex = /((?:\~|\.)?(?:\/[\w\.-]*)+)/;
|
|
237
|
+
const lineColumnRegex = /(?:(?:\:|", line )(?<line>[\d]+))?(?:\:(?<column>[\d]+))?/;
|
|
238
|
+
// TODO: this ought to come from kernel (browser may be on a different OS).
|
|
239
|
+
const isWindows = navigator.userAgent.indexOf('Windows') >= 0;
|
|
240
|
+
ILinker.pathLinkRegex = new RegExp(`(?<path>${isWindows ? winPathRegex.source : posixPathRegex.source})${lineColumnRegex.source}`, 'g');
|
|
241
|
+
})(ILinker || (ILinker = {}));
|
|
242
|
+
/**
|
|
243
|
+
* Linker for web URLs.
|
|
244
|
+
*/
|
|
245
|
+
class WebLinker {
|
|
246
|
+
constructor() {
|
|
247
|
+
this.regex = ILinker.webLinkRegex;
|
|
248
|
+
}
|
|
249
|
+
createAnchor(url, label) {
|
|
250
|
+
const anchor = document.createElement('a');
|
|
251
|
+
anchor.href = url.startsWith('www.') ? 'https://' + url : url;
|
|
252
|
+
anchor.rel = 'noopener';
|
|
253
|
+
anchor.target = '_blank';
|
|
254
|
+
anchor.appendChild(document.createTextNode(label));
|
|
255
|
+
return anchor;
|
|
256
|
+
}
|
|
257
|
+
processPath(url) {
|
|
245
258
|
// Special case when the URL ends with ">" or "<"
|
|
246
259
|
const lastChars = url.slice(-1);
|
|
247
260
|
const endsWithGtLt = ['>', '<'].indexOf(lastChars) !== -1;
|
|
248
261
|
const len = endsWithGtLt ? url.length - 1 : url.length;
|
|
249
|
-
const anchor = document.createElement('a');
|
|
250
262
|
url = url.slice(0, len);
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
263
|
+
return url;
|
|
264
|
+
}
|
|
265
|
+
processLabel(url) {
|
|
266
|
+
return this.processPath(url);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Linker for path URIs.
|
|
271
|
+
*/
|
|
272
|
+
class PathLinker {
|
|
273
|
+
constructor() {
|
|
274
|
+
this.regex = ILinker.pathLinkRegex;
|
|
257
275
|
}
|
|
258
|
-
|
|
259
|
-
|
|
276
|
+
createAnchor(path, label, locators) {
|
|
277
|
+
const anchor = document.createElement('a');
|
|
278
|
+
// Store the path in dataset.
|
|
279
|
+
// Do not set `href` - at this point we do not know if the path is valid and
|
|
280
|
+
// accessible for application (and we want rendering those as links).
|
|
281
|
+
anchor.dataset.path = path;
|
|
282
|
+
// Store line using RFC 5147 fragment locator for text/plain files.
|
|
283
|
+
// It could be expanded to other formats, e.g. based on file extension.
|
|
284
|
+
const line = parseInt(locators['line'], 10);
|
|
285
|
+
let locator = !isNaN(line) ? `line=${line - 1}` : '';
|
|
286
|
+
anchor.dataset.locator = locator;
|
|
287
|
+
anchor.appendChild(document.createTextNode(label));
|
|
288
|
+
return anchor;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
function autolink(content, options) {
|
|
292
|
+
const linkers = [];
|
|
293
|
+
if (options.checkWeb) {
|
|
294
|
+
linkers.push(new WebLinker());
|
|
295
|
+
}
|
|
296
|
+
if (options.checkPaths) {
|
|
297
|
+
linkers.push(new PathLinker());
|
|
260
298
|
}
|
|
299
|
+
const nodes = [];
|
|
300
|
+
// There are two ways to implement competitive regexes:
|
|
301
|
+
// - two heads (which would need to resolve overlaps), or
|
|
302
|
+
// - (simpler) divide and recurse (implemented below)
|
|
303
|
+
const linkify = (content, regexIndex) => {
|
|
304
|
+
if (regexIndex >= linkers.length) {
|
|
305
|
+
nodes.push(document.createTextNode(content));
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
const linker = linkers[regexIndex];
|
|
309
|
+
let match;
|
|
310
|
+
let currentIndex = 0;
|
|
311
|
+
const regex = linker.regex;
|
|
312
|
+
// Reset regex
|
|
313
|
+
regex.lastIndex = 0;
|
|
314
|
+
while (null != (match = regex.exec(content))) {
|
|
315
|
+
const stringBeforeMatch = content.substring(currentIndex, match.index);
|
|
316
|
+
if (stringBeforeMatch) {
|
|
317
|
+
linkify(stringBeforeMatch, regexIndex + 1);
|
|
318
|
+
}
|
|
319
|
+
const { path, ...locators } = match.groups;
|
|
320
|
+
const value = linker.processPath ? linker.processPath(path) : path;
|
|
321
|
+
const label = linker.processLabel
|
|
322
|
+
? linker.processLabel(match[0])
|
|
323
|
+
: match[0];
|
|
324
|
+
nodes.push(linker.createAnchor(value, label, locators));
|
|
325
|
+
currentIndex = match.index + label.length;
|
|
326
|
+
}
|
|
327
|
+
const stringAfterMatches = content.substring(currentIndex);
|
|
328
|
+
if (stringAfterMatches) {
|
|
329
|
+
linkify(stringAfterMatches, regexIndex + 1);
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
linkify(content, 0);
|
|
261
333
|
return nodes;
|
|
262
334
|
}
|
|
263
335
|
/**
|
|
@@ -379,66 +451,126 @@ export function renderText(options) {
|
|
|
379
451
|
allowedTags: ['span']
|
|
380
452
|
});
|
|
381
453
|
// Set the sanitized content for the host node.
|
|
382
|
-
const ret = document.createElement('pre');
|
|
383
454
|
const pre = document.createElement('pre');
|
|
384
455
|
pre.innerHTML = content;
|
|
385
456
|
const preTextContent = pre.textContent;
|
|
457
|
+
let ret;
|
|
386
458
|
if (preTextContent) {
|
|
387
459
|
// Note: only text nodes and span elements should be present after sanitization in the `<pre>` element.
|
|
388
460
|
const linkedNodes = ((_b = (_a = sanitizer.getAutolink) === null || _a === void 0 ? void 0 : _a.call(sanitizer)) !== null && _b !== void 0 ? _b : true)
|
|
389
|
-
? autolink(preTextContent
|
|
461
|
+
? autolink(preTextContent, {
|
|
462
|
+
checkWeb: true,
|
|
463
|
+
checkPaths: false
|
|
464
|
+
})
|
|
390
465
|
: [document.createTextNode(content)];
|
|
391
|
-
let inAnchorElement = false;
|
|
392
|
-
const combinedNodes = [];
|
|
393
466
|
const preNodes = Array.from(pre.childNodes);
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
467
|
+
ret = mergeNodes(preNodes, linkedNodes);
|
|
468
|
+
}
|
|
469
|
+
else {
|
|
470
|
+
ret = document.createElement('pre');
|
|
471
|
+
}
|
|
472
|
+
host.appendChild(ret);
|
|
473
|
+
// Return the rendered promise.
|
|
474
|
+
return Promise.resolve(undefined);
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* Render error into a host node.
|
|
478
|
+
*
|
|
479
|
+
* @param options - The options for rendering.
|
|
480
|
+
*
|
|
481
|
+
* @returns A promise which resolves when rendering is complete.
|
|
482
|
+
*/
|
|
483
|
+
export function renderError(options) {
|
|
484
|
+
var _a, _b;
|
|
485
|
+
// Unpack the options.
|
|
486
|
+
const { host, linkHandler, sanitizer, resolver, source } = options;
|
|
487
|
+
// Create the HTML content.
|
|
488
|
+
const content = sanitizer.sanitize(Private.ansiSpan(source), {
|
|
489
|
+
allowedTags: ['span']
|
|
490
|
+
});
|
|
491
|
+
// Set the sanitized content for the host node.
|
|
492
|
+
const pre = document.createElement('pre');
|
|
493
|
+
pre.innerHTML = content;
|
|
494
|
+
const preTextContent = pre.textContent;
|
|
495
|
+
let ret;
|
|
496
|
+
if (preTextContent) {
|
|
497
|
+
// Note: only text nodes and span elements should be present after sanitization in the `<pre>` element.
|
|
498
|
+
const linkedNodes = ((_b = (_a = sanitizer.getAutolink) === null || _a === void 0 ? void 0 : _a.call(sanitizer)) !== null && _b !== void 0 ? _b : true)
|
|
499
|
+
? autolink(preTextContent, {
|
|
500
|
+
checkWeb: true,
|
|
501
|
+
checkPaths: true
|
|
502
|
+
})
|
|
503
|
+
: [document.createTextNode(content)];
|
|
504
|
+
const preNodes = Array.from(pre.childNodes);
|
|
505
|
+
ret = mergeNodes(preNodes, linkedNodes);
|
|
506
|
+
}
|
|
507
|
+
else {
|
|
508
|
+
ret = document.createElement('pre');
|
|
509
|
+
}
|
|
510
|
+
host.appendChild(ret);
|
|
511
|
+
// Patch the paths if a resolver is available.
|
|
512
|
+
let promise;
|
|
513
|
+
if (resolver) {
|
|
514
|
+
promise = Private.handlePaths(host, resolver, linkHandler);
|
|
515
|
+
}
|
|
516
|
+
else {
|
|
517
|
+
promise = Promise.resolve(undefined);
|
|
518
|
+
}
|
|
519
|
+
// Return the rendered promise.
|
|
520
|
+
return promise;
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Merge `<span>` nodes from a `<pre>` element with `<a>` nodes from linker.
|
|
524
|
+
*/
|
|
525
|
+
function mergeNodes(preNodes, linkedNodes) {
|
|
526
|
+
const ret = document.createElement('pre');
|
|
527
|
+
let inAnchorElement = false;
|
|
528
|
+
const combinedNodes = [];
|
|
529
|
+
for (let nodes of alignedNodes(preNodes, linkedNodes)) {
|
|
530
|
+
if (!nodes[0]) {
|
|
531
|
+
combinedNodes.push(nodes[1]);
|
|
532
|
+
inAnchorElement = nodes[1].nodeType !== Node.TEXT_NODE;
|
|
533
|
+
continue;
|
|
534
|
+
}
|
|
535
|
+
else if (!nodes[1]) {
|
|
536
|
+
combinedNodes.push(nodes[0]);
|
|
537
|
+
inAnchorElement = false;
|
|
538
|
+
continue;
|
|
539
|
+
}
|
|
540
|
+
let [preNode, linkNode] = nodes;
|
|
541
|
+
const lastCombined = combinedNodes[combinedNodes.length - 1];
|
|
542
|
+
// If we are already in an anchor element and the anchor element did not change,
|
|
543
|
+
// we should insert the node from <pre> which is either Text node or coloured span Element
|
|
544
|
+
// into the anchor content as a child
|
|
545
|
+
if (inAnchorElement &&
|
|
546
|
+
linkNode.href ===
|
|
547
|
+
lastCombined.href) {
|
|
548
|
+
lastCombined.appendChild(preNode);
|
|
549
|
+
}
|
|
550
|
+
else {
|
|
551
|
+
// the `linkNode` is either Text or AnchorElement;
|
|
552
|
+
const isAnchor = linkNode.nodeType !== Node.TEXT_NODE;
|
|
553
|
+
// if we are NOT about to start an anchor element, just add the pre Node
|
|
554
|
+
if (!isAnchor) {
|
|
555
|
+
combinedNodes.push(preNode);
|
|
402
556
|
inAnchorElement = false;
|
|
403
|
-
continue;
|
|
404
|
-
}
|
|
405
|
-
let [preNode, linkNode] = nodes;
|
|
406
|
-
const lastCombined = combinedNodes[combinedNodes.length - 1];
|
|
407
|
-
// If we are already in an anchor element and the anchor element did not change,
|
|
408
|
-
// we should insert the node from <pre> which is either Text node or coloured span Element
|
|
409
|
-
// into the anchor content as a child
|
|
410
|
-
if (inAnchorElement &&
|
|
411
|
-
linkNode.href ===
|
|
412
|
-
lastCombined.href) {
|
|
413
|
-
lastCombined.appendChild(preNode);
|
|
414
557
|
}
|
|
415
558
|
else {
|
|
416
|
-
// the `linkNode`
|
|
417
|
-
|
|
418
|
-
//
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
else {
|
|
424
|
-
// otherwise start a new anchor; the contents of the `linkNode` and `preNode` should be the same,
|
|
425
|
-
// so we just put the neatly formatted `preNode` inside the anchor node (`linkNode`)
|
|
426
|
-
// and append that to combined nodes.
|
|
427
|
-
linkNode.textContent = '';
|
|
428
|
-
linkNode.appendChild(preNode);
|
|
429
|
-
combinedNodes.push(linkNode);
|
|
430
|
-
inAnchorElement = true;
|
|
431
|
-
}
|
|
559
|
+
// otherwise start a new anchor; the contents of the `linkNode` and `preNode` should be the same,
|
|
560
|
+
// so we just put the neatly formatted `preNode` inside the anchor node (`linkNode`)
|
|
561
|
+
// and append that to combined nodes.
|
|
562
|
+
linkNode.textContent = '';
|
|
563
|
+
linkNode.appendChild(preNode);
|
|
564
|
+
combinedNodes.push(linkNode);
|
|
565
|
+
inAnchorElement = true;
|
|
432
566
|
}
|
|
433
567
|
}
|
|
434
|
-
// Do not reuse `pre` element. Clearing out previous children is too slow...
|
|
435
|
-
for (const child of combinedNodes) {
|
|
436
|
-
ret.appendChild(child);
|
|
437
|
-
}
|
|
438
568
|
}
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
569
|
+
// Do not reuse `pre` element. Clearing out previous children is too slow...
|
|
570
|
+
for (const child of combinedNodes) {
|
|
571
|
+
ret.appendChild(child);
|
|
572
|
+
}
|
|
573
|
+
return ret;
|
|
442
574
|
}
|
|
443
575
|
/**
|
|
444
576
|
* The namespace for module implementation details.
|
|
@@ -545,6 +677,25 @@ var Private;
|
|
|
545
677
|
return Promise.all(promises).then(() => undefined);
|
|
546
678
|
}
|
|
547
679
|
Private.handleUrls = handleUrls;
|
|
680
|
+
/**
|
|
681
|
+
* Resolve the paths in `<a>` elements `data` attributes.
|
|
682
|
+
*
|
|
683
|
+
* @param node - The head html element.
|
|
684
|
+
*
|
|
685
|
+
* @param resolver - A url resolver.
|
|
686
|
+
*
|
|
687
|
+
* @param linkHandler - An optional link handler for nodes.
|
|
688
|
+
*
|
|
689
|
+
* @returns a promise fulfilled when the relative urls have been resolved.
|
|
690
|
+
*/
|
|
691
|
+
async function handlePaths(node, resolver, linkHandler) {
|
|
692
|
+
// Handle anchor elements.
|
|
693
|
+
const anchors = node.getElementsByTagName('a');
|
|
694
|
+
for (let i = 0; i < anchors.length; i++) {
|
|
695
|
+
await handlePathAnchor(anchors[i], resolver, linkHandler);
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
Private.handlePaths = handlePaths;
|
|
548
699
|
/**
|
|
549
700
|
* Apply ids to headers.
|
|
550
701
|
*/
|
|
@@ -641,6 +792,49 @@ var Private;
|
|
|
641
792
|
anchor.href = '';
|
|
642
793
|
});
|
|
643
794
|
}
|
|
795
|
+
/**
|
|
796
|
+
* Handle an anchor node.
|
|
797
|
+
*/
|
|
798
|
+
async function handlePathAnchor(anchor, resolver, linkHandler) {
|
|
799
|
+
let path = anchor.dataset.path || '';
|
|
800
|
+
let locator = anchor.dataset.locator ? '#' + anchor.dataset.locator : '';
|
|
801
|
+
delete anchor.dataset.path;
|
|
802
|
+
delete anchor.dataset.locator;
|
|
803
|
+
const isLocal = resolver.isLocal
|
|
804
|
+
? resolver.isLocal(path)
|
|
805
|
+
: URLExt.isLocal(path);
|
|
806
|
+
// Bail if:
|
|
807
|
+
// - it is not a file-like url,
|
|
808
|
+
// - the resolver does not support paths
|
|
809
|
+
// - there is no link handler, or if it does not support paths
|
|
810
|
+
if (!path ||
|
|
811
|
+
!isLocal ||
|
|
812
|
+
!resolver.resolvePath ||
|
|
813
|
+
!linkHandler ||
|
|
814
|
+
!linkHandler.handlePath) {
|
|
815
|
+
anchor.replaceWith(...anchor.childNodes);
|
|
816
|
+
return Promise.resolve(undefined);
|
|
817
|
+
}
|
|
818
|
+
try {
|
|
819
|
+
// Find given path
|
|
820
|
+
const resolution = await resolver.resolvePath(path);
|
|
821
|
+
if (!resolution) {
|
|
822
|
+
// Bail if the file does not exist
|
|
823
|
+
console.log('Path resolution bailing: does not exist');
|
|
824
|
+
return Promise.resolve(undefined);
|
|
825
|
+
}
|
|
826
|
+
// Handle the click override.
|
|
827
|
+
linkHandler.handlePath(anchor, resolution.path, resolution.scope, locator);
|
|
828
|
+
// Set the visible anchor.
|
|
829
|
+
anchor.href = resolution.path + locator;
|
|
830
|
+
}
|
|
831
|
+
catch (err) {
|
|
832
|
+
// If there was an error getting the url,
|
|
833
|
+
// just make it an empty link.
|
|
834
|
+
console.warn('Path anchor error:', err);
|
|
835
|
+
anchor.href = '#linking-failed-see-console';
|
|
836
|
+
}
|
|
837
|
+
}
|
|
644
838
|
const ANSI_COLORS = [
|
|
645
839
|
'ansi-black',
|
|
646
840
|
'ansi-red',
|