From 0955c0e78f6d9a7ecd0022f729c73f9cc8c4030c Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Thu, 23 Jul 2020 14:15:42 -0700 Subject: [PATCH] notebooks: initial implementation of 'pure' output renderers (#103125) --- .../notebook/browser/extensionPoint.ts | 10 +++- .../browser/notebookPureOutputRenderer.ts | 49 +++++++++++++++++++ .../notebook/browser/notebookServiceImpl.ts | 11 +++-- .../browser/view/renderers/webviewPreloads.ts | 15 +++++- 4 files changed, 79 insertions(+), 6 deletions(-) create mode 100644 src/vs/workbench/contrib/notebook/browser/notebookPureOutputRenderer.ts diff --git a/src/vs/workbench/contrib/notebook/browser/extensionPoint.ts b/src/vs/workbench/contrib/notebook/browser/extensionPoint.ts index 1f167a7a581..c7b5c94f98d 100644 --- a/src/vs/workbench/contrib/notebook/browser/extensionPoint.ts +++ b/src/vs/workbench/contrib/notebook/browser/extensionPoint.ts @@ -27,12 +27,14 @@ namespace NotebookRendererContribution { export const viewType = 'viewType'; export const displayName = 'displayName'; export const mimeTypes = 'mimeTypes'; + export const entrypoint = 'entrypoint'; } -interface INotebookRendererContribution { +export interface INotebookRendererContribution { readonly [NotebookRendererContribution.viewType]: string; readonly [NotebookRendererContribution.displayName]: string; readonly [NotebookRendererContribution.mimeTypes]?: readonly string[]; + readonly [NotebookRendererContribution.entrypoint]?: string; } const notebookProviderContribution: IJSONSchema = { @@ -115,7 +117,11 @@ const notebookRendererContribution: IJSONSchema = { items: { type: 'string' } - } + }, + [NotebookRendererContribution.entrypoint]: { + type: 'string', + description: nls.localize('contributes.notebook.renderer.entrypoint', 'File to load in the webview to render the extension.'), + }, } } }; diff --git a/src/vs/workbench/contrib/notebook/browser/notebookPureOutputRenderer.ts b/src/vs/workbench/contrib/notebook/browser/notebookPureOutputRenderer.ts new file mode 100644 index 00000000000..c1f42f14d6c --- /dev/null +++ b/src/vs/workbench/contrib/notebook/browser/notebookPureOutputRenderer.ts @@ -0,0 +1,49 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { URI, UriComponents } from 'vs/base/common/uri'; +import { INotebookRendererInfo, IOutputRenderResponse, IOutputRenderRequest } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; +import { joinPath } from 'vs/base/common/resources'; + +/** + * A 'stub' output renderer used when the contribution has an `entrypoint` + * property. Include the entrypoint as its reload and renders an empty string. + */ +export class PureNotebookOutputRenderer implements INotebookRendererInfo { + + public readonly extensionId: ExtensionIdentifier; + public readonly extensionLocation: URI; + public readonly preloads: URI[]; + + + constructor(public readonly id: string, extension: IExtensionDescription, entrypoint: string) { + this.extensionId = extension.identifier; + this.extensionLocation = extension.extensionLocation; + this.preloads = [joinPath(extension.extensionLocation, entrypoint)]; + } + + public render(uri: URI, request: IOutputRenderRequest): Promise | undefined> { + return this.render2(uri, request); + } + + public render2(_uri: URI, request: IOutputRenderRequest): Promise | undefined> { + return Promise.resolve({ + items: request.items.map(cellInfo => ({ + key: cellInfo.key, + outputs: cellInfo.outputs.map(output => ({ + index: output.index, + outputId: output.outputId, + mimeType: output.mimeType, + handlerId: this.id, + // todo@connor4312: temp approach exploring this API: + transformedOutput: `` + })) + })) + }); + } +} diff --git a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts index 75c6bd6b1ed..09c6094701c 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts @@ -31,6 +31,7 @@ import { generateUuid } from 'vs/base/common/uuid'; import { flatten } from 'vs/base/common/arrays'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { NotebookKernelProviderAssociationRegistry, updateNotebookKernelProvideAssociationSchema, NotebookViewTypesExtensionRegistry } from 'vs/workbench/contrib/notebook/browser/notebookKernelAssociation'; +import { PureNotebookOutputRenderer } from 'vs/workbench/contrib/notebook/browser/notebookPureOutputRenderer'; function MODEL_ID(resource: URI): string { return resource.toString(); @@ -287,8 +288,12 @@ export class NotebookService extends Disposable implements INotebookService, ICu this.notebookRenderersInfoStore.add(new NotebookOutputRendererInfo({ id: notebookContribution.viewType, displayName: notebookContribution.displayName, - mimeTypes: notebookContribution.mimeTypes || [] + mimeTypes: notebookContribution.mimeTypes || [], })); + + if (notebookContribution.entrypoint) { + this._notebookRenderers.set(notebookContribution.viewType, new PureNotebookOutputRenderer(notebookContribution.viewType, extension.description, notebookContribution.entrypoint)); + } } } @@ -690,7 +695,7 @@ export class NotebookService extends Disposable implements INotebookService, ICu let orderMimeTypes: IOrderedMimeType[] = []; sorted.forEach(mimeType => { - let handlers = this.findBestMatchedRenderer(mimeType); + let handlers = this._findBestMatchedRenderer(mimeType); if (handlers.length) { const handler = handlers[0]; @@ -734,7 +739,7 @@ export class NotebookService extends Disposable implements INotebookService, ICu }; } - findBestMatchedRenderer(mimeType: string): readonly NotebookOutputRendererInfo[] { + private _findBestMatchedRenderer(mimeType: string): readonly NotebookOutputRendererInfo[] { return this.notebookRenderersInfoStore.getContributedRenderer(mimeType); } diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts index a301e99aa04..57dee431804 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts @@ -261,6 +261,8 @@ function webviewPreloads() { interface ICreateCellInfo { outputId: string; + output?: unknown; + mimeType?: string; element: HTMLElement; } @@ -374,10 +376,21 @@ function webviewPreloads() { outputNode.innerHTML = content; cellOutputContainer.appendChild(outputNode); + let pureData: { mimeType: string, output: unknown } | undefined; + const outputScript = cellOutputContainer.querySelector('script.vscode-pure-data'); + if (outputScript) { + try { pureData = JSON.parse(outputScript.innerHTML); } catch { } + } + // eval domEval(outputNode); resizeObserve(outputNode, outputId); - onDidCreateOutput.fire([data.apiNamespace, { element: outputNode, outputId }]); + onDidCreateOutput.fire([data.apiNamespace, { + element: outputNode, + output: pureData?.output, + mimeType: pureData?.mimeType, + outputId + }]); vscode.postMessage({ __vscode_notebook_message: true, -- GitLab