mirror of
https://github.com/Microsoft/vscode
synced 2024-08-27 13:00:58 +00:00
Safer construction of notebook html (#170987)
This commit is contained in:
parent
1d9f8c7ed5
commit
5b8361bc71
|
@ -127,16 +127,20 @@ export class OutputElement extends Disposable {
|
|||
|
||||
private _renderSearchForMimetype(viewModel: ICellOutputViewModel, mimeType: string): IInsetRenderOutput {
|
||||
const query = `@tag:notebookRenderer ${mimeType}`;
|
||||
|
||||
const p = DOM.$('p', undefined, `No renderer could be found for mimetype "${mimeType}", but one might be available on the Marketplace.`);
|
||||
const a = DOM.$('a', { href: `command:workbench.extensions.search?%22${query}%22`, class: 'monaco-button monaco-text-button', tabindex: 0, role: 'button', style: 'padding: 8px; text-decoration: none; color: rgb(255, 255, 255); background-color: rgb(14, 99, 156); max-width: 200px;' }, `Search Marketplace`);
|
||||
|
||||
return {
|
||||
type: RenderOutputType.Html,
|
||||
source: viewModel,
|
||||
htmlContent: `<p>No renderer could be found for mimetype "${mimeType}", but one might be available on the Marketplace.</p>
|
||||
<a href="command:workbench.extensions.search?%22${query}%22" class="monaco-button monaco-text-button" tabindex="0" role="button" style="padding: 8px; text-decoration: none; color: rgb(255, 255, 255); background-color: rgb(14, 99, 156); max-width: 200px;">Search Marketplace</a>`
|
||||
htmlContent: p.outerHTML + a.outerHTML,
|
||||
};
|
||||
}
|
||||
|
||||
private _renderMessage(viewModel: ICellOutputViewModel, message: string): IInsetRenderOutput {
|
||||
return { type: RenderOutputType.Html, source: viewModel, htmlContent: `<p>${message}</p>` };
|
||||
const el = DOM.$('p', undefined, message);
|
||||
return { type: RenderOutputType.Html, source: viewModel, htmlContent: el.outerHTML };
|
||||
}
|
||||
|
||||
private async pickActiveMimeTypeRenderer(notebookTextModel: NotebookTextModel, viewModel: ICellOutputViewModel) {
|
||||
|
|
|
@ -236,16 +236,20 @@ class CellOutputElement extends Disposable {
|
|||
|
||||
private _renderSearchForMimetype(viewModel: ICellOutputViewModel, mimeType: string): IInsetRenderOutput {
|
||||
const query = `@tag:notebookRenderer ${mimeType}`;
|
||||
|
||||
const p = DOM.$('p', undefined, `No renderer could be found for mimetype "${mimeType}", but one might be available on the Marketplace.`);
|
||||
const a = DOM.$('a', { href: `command:workbench.extensions.search?%22${query}%22`, class: 'monaco-button monaco-text-button', tabindex: 0, role: 'button', style: 'padding: 8px; text-decoration: none; color: rgb(255, 255, 255); background-color: rgb(14, 99, 156); max-width: 200px;' }, `Search Marketplace`);
|
||||
|
||||
return {
|
||||
type: RenderOutputType.Html,
|
||||
source: viewModel,
|
||||
htmlContent: `<p>No renderer could be found for mimetype "${mimeType}", but one might be available on the Marketplace.</p>
|
||||
<a href="command:workbench.extensions.search?%22${query}%22" class="monaco-button monaco-text-button" tabindex="0" role="button" style="padding: 8px; text-decoration: none; color: rgb(255, 255, 255); background-color: rgb(14, 99, 156); max-width: 200px;">Search Marketplace</a>`
|
||||
htmlContent: p.outerHTML + a.outerHTML
|
||||
};
|
||||
}
|
||||
|
||||
private _renderMessage(viewModel: ICellOutputViewModel, message: string): IInsetRenderOutput {
|
||||
return { type: RenderOutputType.Html, source: viewModel, htmlContent: `<p>${message}</p>` };
|
||||
const el = DOM.$('p', undefined, message);
|
||||
return { type: RenderOutputType.Html, source: viewModel, htmlContent: el.outerHTML };
|
||||
}
|
||||
|
||||
private async _attachToolbar(outputItemDiv: HTMLElement, notebookTextModel: NotebookTextModel, kernel: INotebookKernel | undefined, index: number, mimeTypes: readonly IOrderedMimeType[]) {
|
||||
|
|
|
@ -182,30 +182,6 @@ async function webviewPreloads(ctx: PreloadContext) {
|
|||
|
||||
document.body.addEventListener('click', handleInnerClick);
|
||||
|
||||
const preservedScriptAttributes: (keyof HTMLScriptElement)[] = [
|
||||
'type', 'src', 'nonce', 'noModule', 'async',
|
||||
];
|
||||
|
||||
// derived from https://github.com/jquery/jquery/blob/d0ce00cdfa680f1f0c38460bc51ea14079ae8b07/src/core/DOMEval.js
|
||||
const domEval = (container: Element) => {
|
||||
const arr = Array.from(container.getElementsByTagName('script'));
|
||||
for (let n = 0; n < arr.length; n++) {
|
||||
const node = arr[n];
|
||||
const scriptTag = document.createElement('script');
|
||||
const trustedScript = ttPolicy?.createScript(node.innerText) ?? node.innerText;
|
||||
scriptTag.text = trustedScript as string;
|
||||
for (const key of preservedScriptAttributes) {
|
||||
const val = node[key] || node.getAttribute && node.getAttribute(key);
|
||||
if (val) {
|
||||
scriptTag.setAttribute(key, val as any);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO@connor4312: should script with src not be removed?
|
||||
container.appendChild(scriptTag).parentNode!.removeChild(scriptTag);
|
||||
}
|
||||
};
|
||||
|
||||
async function loadScriptSource(url: string, originalUri: string): Promise<string> {
|
||||
const res = await fetch(url);
|
||||
const text = await res.text();
|
||||
|
@ -2312,7 +2288,6 @@ async function webviewPreloads(ctx: PreloadContext) {
|
|||
if (content.type === 0 /* RenderOutputType.Html */) {
|
||||
const trustedHtml = ttPolicy?.createHTML(content.htmlContent) ?? content.htmlContent;
|
||||
this.element.innerHTML = trustedHtml as string;
|
||||
domEval(this.element);
|
||||
} else if (preloadErrors.some(e => e instanceof Error)) {
|
||||
const errors = preloadErrors.filter((e): e is Error => e instanceof Error);
|
||||
showRenderError(`Error loading preloads`, this.element, errors);
|
||||
|
|
Loading…
Reference in a new issue