diff --git a/extensions/vscode-notebook-tests/package.json b/extensions/vscode-notebook-tests/package.json
index 4ed7605f894cf..3479ad57701f5 100644
--- a/extensions/vscode-notebook-tests/package.json
+++ b/extensions/vscode-notebook-tests/package.json
@@ -64,6 +64,7 @@
{
"viewType": "notebookCoreTestRenderer",
"displayName": "Notebook Core Test Renderer",
+ "entrypoint": "./src/customRenderer.js",
"mimeTypes": [
"text/custom"
]
diff --git a/extensions/vscode-notebook-tests/src/customRenderer.js b/extensions/vscode-notebook-tests/src/customRenderer.js
index 75e2ec1eb7ad4..f23538e38a765 100644
--- a/extensions/vscode-notebook-tests/src/customRenderer.js
+++ b/extensions/vscode-notebook-tests/src/customRenderer.js
@@ -11,3 +11,11 @@ vscode.postMessage({
firstMessage: true
}
});
+
+const notebook = acquireNotebookRendererApi('notebookCoreTestRenderer');
+
+notebook.onDidCreateOutput(({ element, mimeType }) => {
+ const div = document.createElement('div');
+ div.innerText = `Hello ${mimeType}!`;
+ element.appendChild(div);
+});
diff --git a/extensions/vscode-notebook-tests/src/notebookTestMain.ts b/extensions/vscode-notebook-tests/src/notebookTestMain.ts
index c8ea3282c2cce..df7ace2781fce 100644
--- a/extensions/vscode-notebook-tests/src/notebookTestMain.ts
+++ b/extensions/vscode-notebook-tests/src/notebookTestMain.ts
@@ -4,7 +4,6 @@
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
-import * as path from 'path';
import { smokeTestActivate } from './notebookSmokeTestMain';
export function activate(context: vscode.ExtensionContext): any {
@@ -117,16 +116,4 @@ export function activate(context: vscode.ExtensionContext): any {
},
cancelCellExecution: async (_document: vscode.NotebookDocument, _cell: vscode.NotebookCell) => { }
}));
-
- const preloadUri = vscode.Uri.file(path.resolve(__dirname, '../src/customRenderer.js'));
- context.subscriptions.push(vscode.notebook.registerNotebookOutputRenderer('notebookCoreTestRenderer', {
- mimeTypes: [
- 'text/custom'
- ]
- }, {
- preloads: [preloadUri],
- render(_document: vscode.NotebookDocument, _request: vscode.NotebookRenderRequest): string {
- return '
test
';
- }
- }));
}
diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts
index 68c62e7af199a..56deff3da9d69 100644
--- a/src/vs/vscode.proposed.d.ts
+++ b/src/vs/vscode.proposed.d.ts
@@ -1436,31 +1436,6 @@ declare module 'vscode' {
outputId: string;
}
- export interface NotebookOutputRenderer {
- /**
- *
- * @returns HTML fragment. We can probably return `CellOutput` instead of string ?
- *
- */
- render(document: NotebookDocument, request: NotebookRenderRequest): string;
-
- /**
- * Call before HTML from the renderer is executed, and will be called for
- * every editor associated with notebook documents where the renderer
- * is or was used.
- *
- * The communication object will only send and receive messages to the
- * render API, retrieved via `acquireNotebookRendererApi`, acquired with
- * this specific renderer's ID.
- *
- * If you need to keep an association between the communication object
- * and the document for use in the `render()` method, you can use a WeakMap.
- */
- resolveNotebook?(document: NotebookDocument, communication: NotebookCommunication): void;
-
- readonly preloads?: Uri[];
- }
-
export interface NotebookCellsChangeData {
readonly start: number;
readonly deletedCount: number;
@@ -1679,12 +1654,6 @@ declare module 'vscode' {
kernel: NotebookKernel
): Disposable;
- export function registerNotebookOutputRenderer(
- id: string,
- outputSelector: NotebookOutputSelector,
- renderer: NotebookOutputRenderer
- ): Disposable;
-
export const onDidOpenNotebookDocument: Event;
export const onDidCloseNotebookDocument: Event;
export const onDidSaveNotebookDocument: Event;
diff --git a/src/vs/workbench/api/browser/mainThreadNotebook.ts b/src/vs/workbench/api/browser/mainThreadNotebook.ts
index 7fdf21501fff3..d616a3ba79339 100644
--- a/src/vs/workbench/api/browser/mainThreadNotebook.ts
+++ b/src/vs/workbench/api/browser/mainThreadNotebook.ts
@@ -9,7 +9,7 @@ import { MainContext, MainThreadNotebookShape, NotebookExtensionDescription, IEx
import { Disposable, IDisposable, combinedDisposable, DisposableStore } from 'vs/base/common/lifecycle';
import { URI, UriComponents } from 'vs/base/common/uri';
import { INotebookService, IMainNotebookController } from 'vs/workbench/contrib/notebook/common/notebookService';
-import { INotebookMimeTypeSelector, NOTEBOOK_DISPLAY_ORDER, NotebookCellOutputsSplice, NotebookDocumentMetadata, NotebookCellMetadata, ICellEditOperation, ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, CellEditType, CellKind, INotebookKernelInfo, INotebookKernelInfoDto, IEditor, INotebookRendererInfo, IOutputRenderRequest, IOutputRenderResponse, INotebookDocumentFilter } from 'vs/workbench/contrib/notebook/common/notebookCommon';
+import { NOTEBOOK_DISPLAY_ORDER, NotebookCellOutputsSplice, NotebookDocumentMetadata, NotebookCellMetadata, ICellEditOperation, ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, CellEditType, CellKind, INotebookKernelInfo, INotebookKernelInfoDto, IEditor, INotebookDocumentFilter } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
@@ -171,7 +171,6 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
private readonly _notebookProviders = new Map();
private readonly _notebookKernels = new Map();
private readonly _notebookKernelProviders = new Map, provider: IDisposable }>();
- private readonly _notebookRenderers = new Map();
private readonly _proxy: ExtHostNotebookShape;
private _toDisposeOnEditorRemove = new Map();
private _currentState?: DocumentAndEditorState;
@@ -191,10 +190,10 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
this.registerListeners();
}
- async $tryApplyEdits(viewType: string, resource: UriComponents, modelVersionId: number, edits: ICellEditOperation[], renderers: number[]): Promise {
+ async $tryApplyEdits(viewType: string, resource: UriComponents, modelVersionId: number, edits: ICellEditOperation[]): Promise {
const textModel = this._notebookService.getNotebookTextModel(URI.from(resource));
if (textModel) {
- await this._notebookService.transformEditsOutputs(textModel, edits);
+ this._notebookService.transformEditsOutputs(textModel, edits);
return textModel.$applyEdit(modelVersionId, edits, true);
}
@@ -414,22 +413,6 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
// }
}
- async $registerNotebookRenderer(extension: NotebookExtensionDescription, type: string, selectors: INotebookMimeTypeSelector, preloads: UriComponents[]): Promise {
- const staticContribution = this._notebookService.getContributedNotebookOutputRenderers(type);
-
- if (!staticContribution) {
- throw new Error(`Notebook renderer for '${type}' is not statically registered.`);
- }
-
- const renderer = new MainThreadNotebookRenderer(this._proxy, type, staticContribution.displayName, extension.id, URI.revive(extension.location), selectors, preloads.map(uri => URI.revive(uri)));
- this._notebookRenderers.set(type, renderer);
- this._notebookService.registerNotebookRenderer(type, renderer);
- }
-
- async $unregisterNotebookRenderer(id: string): Promise {
- this._notebookService.unregisterNotebookRenderer(id);
- }
-
async $registerNotebookProvider(_extension: NotebookExtensionDescription, _viewType: string, _supportBackup: boolean, _kernel: INotebookKernelInfoDto | undefined): Promise {
const controller: IMainNotebookController = {
kernel: _kernel,
@@ -448,7 +431,7 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
{ editType: CellEditType.Insert, index: 0, cells: data.cells }
];
- await this._notebookService.transformEditsOutputs(mainthreadTextModel, edits);
+ this._notebookService.transformEditsOutputs(mainthreadTextModel, edits);
await new Promise(resolve => {
DOM.scheduleAtNextAnimationFrame(() => {
const ret = mainthreadTextModel!.$applyEdit(mainthreadTextModel!.versionId, edits, true);
@@ -609,12 +592,12 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
textModel?.updateNotebookCellMetadata(handle, metadata);
}
- async $spliceNotebookCellOutputs(viewType: string, resource: UriComponents, cellHandle: number, splices: NotebookCellOutputsSplice[], renderers: number[]): Promise {
+ async $spliceNotebookCellOutputs(viewType: string, resource: UriComponents, cellHandle: number, splices: NotebookCellOutputsSplice[]): Promise {
this.logService.debug('MainThreadNotebooks#spliceNotebookCellOutputs', resource.path, cellHandle);
const textModel = this._notebookService.getNotebookTextModel(URI.from(resource));
if (textModel) {
- await this._notebookService.transformSpliceOutputs(textModel, splices);
+ this._notebookService.transformSpliceOutputs(textModel, splices);
textModel.$spliceNotebookCellOutputs(cellHandle, splices);
}
}
@@ -675,25 +658,3 @@ export class MainThreadNotebookKernel implements INotebookKernelInfo {
return this._proxy.$executeNotebook2(this.id, viewType, uri, handle);
}
}
-
-export class MainThreadNotebookRenderer implements INotebookRendererInfo {
- constructor(
- private readonly _proxy: ExtHostNotebookShape,
- readonly id: string,
- public displayName: string,
- readonly extensionId: ExtensionIdentifier,
- readonly extensionLocation: URI,
- readonly selectors: INotebookMimeTypeSelector,
- readonly preloads: URI[],
- ) {
-
- }
-
- render(uri: URI, request: IOutputRenderRequest): Promise | undefined> {
- return this._proxy.$renderOutputs(uri, this.id, request);
- }
-
- render2(uri: URI, request: IOutputRenderRequest): Promise | undefined> {
- return this._proxy.$renderOutputs2(uri, this.id, request);
- }
-}
diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts
index f697d498e35a2..bc0abb74b0e00 100644
--- a/src/vs/workbench/api/common/extHost.api.impl.ts
+++ b/src/vs/workbench/api/common/extHost.api.impl.ts
@@ -948,10 +948,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
checkProposedApiEnabled(extension);
return extHostNotebook.registerNotebookKernelProvider(extension, selector, provider);
},
- registerNotebookOutputRenderer: (type: string, outputFilter: vscode.NotebookOutputSelector, renderer: vscode.NotebookOutputRenderer) => {
- checkProposedApiEnabled(extension);
- return extHostNotebook.registerNotebookOutputRenderer(type, extension, outputFilter, renderer);
- },
get activeNotebookEditor(): vscode.NotebookEditor | undefined {
checkProposedApiEnabled(extension);
return extHostNotebook.activeNotebookEditor;
diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts
index 512dbb8d5bcde..8c1da7bb19470 100644
--- a/src/vs/workbench/api/common/extHost.protocol.ts
+++ b/src/vs/workbench/api/common/extHost.protocol.ts
@@ -51,7 +51,7 @@ import { TunnelDto } from 'vs/workbench/api/common/extHostTunnelService';
import { TunnelOptions } from 'vs/platform/remote/common/tunnel';
import { Timeline, TimelineChangeEvent, TimelineOptions, TimelineProviderDescriptor, InternalTimelineOptions } from 'vs/workbench/contrib/timeline/common/timeline';
import { revive } from 'vs/base/common/marshalling';
-import { INotebookMimeTypeSelector, IProcessedOutput, INotebookDisplayOrder, NotebookCellMetadata, NotebookDocumentMetadata, ICellEditOperation, NotebookCellsChangedEvent, NotebookDataDto, INotebookKernelInfoDto, IMainCellDto, IOutputRenderRequest, IOutputRenderResponse, INotebookDocumentFilter, INotebookKernelInfoDto2 } from 'vs/workbench/contrib/notebook/common/notebookCommon';
+import { IProcessedOutput, INotebookDisplayOrder, NotebookCellMetadata, NotebookDocumentMetadata, ICellEditOperation, NotebookCellsChangedEvent, NotebookDataDto, INotebookKernelInfoDto, IMainCellDto, INotebookDocumentFilter, INotebookKernelInfoDto2 } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { CallHierarchyItem } from 'vs/workbench/contrib/callHierarchy/common/callHierarchy';
import { Dto } from 'vs/base/common/types';
import { ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable';
@@ -701,8 +701,6 @@ export interface MainThreadNotebookShape extends IDisposable {
$registerNotebookProvider(extension: NotebookExtensionDescription, viewType: string, supportBackup: boolean, kernelInfoDto: INotebookKernelInfoDto | undefined): Promise;
$onNotebookChange(viewType: string, resource: UriComponents): Promise;
$unregisterNotebookProvider(viewType: string): Promise;
- $registerNotebookRenderer(extension: NotebookExtensionDescription, type: string, selectors: INotebookMimeTypeSelector, preloads: UriComponents[]): Promise;
- $unregisterNotebookRenderer(id: string): Promise;
$registerNotebookKernel(extension: NotebookExtensionDescription, id: string, label: string, selectors: (string | IRelativePattern)[], preloads: UriComponents[]): Promise;
$registerNotebookKernelProvider(extension: NotebookExtensionDescription, handle: number, documentFilter: INotebookDocumentFilter): Promise;
$unregisterNotebookKernelProvider(handle: number): Promise;
@@ -712,7 +710,7 @@ export interface MainThreadNotebookShape extends IDisposable {
$updateNotebookLanguages(viewType: string, resource: UriComponents, languages: string[]): Promise;
$updateNotebookMetadata(viewType: string, resource: UriComponents, metadata: NotebookDocumentMetadata): Promise;
$updateNotebookCellMetadata(viewType: string, resource: UriComponents, handle: number, metadata: NotebookCellMetadata | undefined): Promise;
- $spliceNotebookCellOutputs(viewType: string, resource: UriComponents, cellHandle: number, splices: NotebookCellOutputsSplice[], renderers: number[]): Promise;
+ $spliceNotebookCellOutputs(viewType: string, resource: UriComponents, cellHandle: number, splices: NotebookCellOutputsSplice[]): Promise;
$postMessage(editorId: string, forRendererId: string | undefined, value: any): Promise;
$onDidEdit(resource: UriComponents, viewType: string, editId: number, label: string | undefined): void;
@@ -1628,8 +1626,6 @@ export interface ExtHostNotebookShape {
$backup(viewType: string, uri: UriComponents, cancellation: CancellationToken): Promise;
$acceptDisplayOrder(displayOrder: INotebookDisplayOrder): void;
$acceptNotebookActiveKernelChange(event: { uri: UriComponents, providerHandle: number | undefined, kernelId: string | undefined }): void;
- $renderOutputs(uriComponents: UriComponents, id: string, request: IOutputRenderRequest): Promise | undefined>;
- $renderOutputs2(uriComponents: UriComponents, id: string, request: IOutputRenderRequest): Promise | undefined>;
$onDidReceiveMessage(editorId: string, rendererId: string | undefined, message: unknown): void;
$acceptModelChanged(uriComponents: UriComponents, event: NotebookCellsChangedEvent): void;
$acceptModelSaved(uriComponents: UriComponents): void;
diff --git a/src/vs/workbench/api/common/extHostNotebook.ts b/src/vs/workbench/api/common/extHostNotebook.ts
index a3528ff00c9d4..6055d791a8d9c 100644
--- a/src/vs/workbench/api/common/extHostNotebook.ts
+++ b/src/vs/workbench/api/common/extHostNotebook.ts
@@ -22,7 +22,7 @@ import { IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePa
import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters';
import * as extHostTypes from 'vs/workbench/api/common/extHostTypes';
import { asWebviewUri, WebviewInitData } from 'vs/workbench/api/common/shared/webview';
-import { CellEditType, CellOutputKind, diff, ICellDeleteEdit, ICellEditOperation, ICellInsertEdit, IMainCellDto, INotebookDisplayOrder, INotebookEditData, INotebookKernelInfoDto2, IOutputRenderRequest, IOutputRenderResponse, IOutputRenderResponseCellInfo, IOutputRenderResponseOutputInfo, IProcessedOutput, IRawOutput, NotebookCellMetadata, NotebookCellsChangedEvent, NotebookCellsChangeType, NotebookCellsSplice2, NotebookDataDto, notebookDocumentMetadataDefaults } from 'vs/workbench/contrib/notebook/common/notebookCommon';
+import { CellEditType, CellOutputKind, diff, ICellDeleteEdit, ICellEditOperation, ICellInsertEdit, IMainCellDto, INotebookDisplayOrder, INotebookEditData, INotebookKernelInfoDto2, IProcessedOutput, IRawOutput, NotebookCellMetadata, NotebookCellsChangedEvent, NotebookCellsChangeType, NotebookCellsSplice2, NotebookDataDto, notebookDocumentMetadataDefaults } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import * as vscode from 'vscode';
import { Cache } from './cache';
import { ResourceMap } from 'vs/base/common/map';
@@ -469,13 +469,12 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
}
async eventuallyUpdateCellOutputs(cell: ExtHostCell, diffs: ISplice[]) {
- const renderers = new Set();
const outputDtos: NotebookCellOutputsSplice[] = diffs.map(diff => {
const outputs = diff.toInsert;
return [diff.start, diff.deleteCount, outputs];
});
- await this._proxy.$spliceNotebookCellOutputs(this.viewType, this.uri, cell.handle, outputDtos, Array.from(renderers));
+ await this._proxy.$spliceNotebookCellOutputs(this.viewType, this.uri, cell.handle, outputDtos);
this._emitter.emitCellOutputsChange({
document: this,
cells: [cell]
@@ -725,44 +724,8 @@ export class ExtHostNotebookEditor extends Disposable implements vscode.Notebook
}
}
-export class ExtHostNotebookOutputRenderer {
- private static _handlePool: number = 0;
- private resolvedComms = new WeakSet();
- readonly handle = ExtHostNotebookOutputRenderer._handlePool++;
-
- constructor(
- public type: string,
- public filter: vscode.NotebookOutputSelector,
- public renderer: vscode.NotebookOutputRenderer
- ) {
-
- }
-
- matches(mimeType: string): boolean {
- if (this.filter.mimeTypes) {
- if (this.filter.mimeTypes.indexOf(mimeType) >= 0) {
- return true;
- }
- }
- return false;
- }
-
- resolveNotebook(document: ExtHostNotebookDocument, comm: ExtHostWebviewCommWrapper) {
- if (!this.resolvedComms.has(comm) && this.renderer.resolveNotebook) {
- this.renderer.resolveNotebook(document, comm.getRendererComm(this.type));
- this.resolvedComms.add(comm);
- }
- }
-
- render(document: ExtHostNotebookDocument, output: vscode.CellDisplayOutput, outputId: string, mimeType: string): string {
- const html = this.renderer.render(document, { output, outputId, mimeType });
-
- return html;
- }
-}
export interface ExtHostNotebookOutputRenderingHandler {
outputDisplayOrder: INotebookDisplayOrder | undefined;
- findBestMatchedRenderer(mimeType: string): ExtHostNotebookOutputRenderer[];
}
export class ExtHostNotebookKernelProviderAdapter extends Disposable {
@@ -887,8 +850,6 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
private readonly _unInitializedDocuments = new ResourceMap();
private readonly _editors = new Map();
private readonly _webviewComm = new Map();
- private readonly _notebookOutputRenderers = new Map();
- private readonly _renderersUsedInNotebooks = new WeakMap>();
private readonly _onDidChangeNotebookCells = new Emitter();
readonly onDidChangeNotebookCells = this._onDidChangeNotebookCells.event;
private readonly _onDidChangeCellOutputs = new Emitter();
@@ -958,108 +919,6 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
});
}
- registerNotebookOutputRenderer(
- type: string,
- extension: IExtensionDescription,
- filter: vscode.NotebookOutputSelector,
- renderer: vscode.NotebookOutputRenderer
- ): vscode.Disposable {
- if (this._notebookOutputRenderers.has(type)) {
- throw new Error(`Notebook renderer for '${type}' already registered`);
- }
-
- const extHostRenderer = new ExtHostNotebookOutputRenderer(type, filter, renderer);
- this._notebookOutputRenderers.set(extHostRenderer.type, extHostRenderer);
- this._proxy.$registerNotebookRenderer({ id: extension.identifier, location: extension.extensionLocation, description: extension.description }, type, filter, renderer.preloads || []);
- return new extHostTypes.Disposable(() => {
- this._notebookOutputRenderers.delete(extHostRenderer.type);
- this._proxy.$unregisterNotebookRenderer(extHostRenderer.type);
- });
- }
-
- async $renderOutputs(uriComponents: UriComponents, id: string, request: IOutputRenderRequest): Promise | undefined> {
- if (!this._notebookOutputRenderers.has(id)) {
- throw new Error(`Notebook renderer for '${id}' is not registered`);
- }
-
- const document = this._documents.get(URI.revive(uriComponents));
-
- if (!document) {
- return;
- }
-
- const renderer = this._notebookOutputRenderers.get(id)!;
- this.provideCommToNotebookRenderers(document, renderer);
-
- const cellsResponse: IOutputRenderResponseCellInfo[] = request.items.map(cellInfo => {
- const cell = document.getCell2(cellInfo.key)!;
- const outputResponse: IOutputRenderResponseOutputInfo[] = cellInfo.outputs.map(output => {
- return {
- index: output.index,
- outputId: output.outputId,
- mimeType: output.mimeType,
- handlerId: id,
- transformedOutput: renderer.render(document, cell.outputs[output.index] as vscode.CellDisplayOutput, output.outputId, output.mimeType)
- };
- });
-
- return {
- key: cellInfo.key,
- outputs: outputResponse
- };
- });
-
- return { items: cellsResponse };
- }
-
- /**
- * The request carry the raw data for outputs so we don't look up in the existing document
- */
- async $renderOutputs2(uriComponents: UriComponents, id: string, request: IOutputRenderRequest): Promise | undefined> {
- if (!this._notebookOutputRenderers.has(id)) {
- throw new Error(`Notebook renderer for '${id}' is not registered`);
- }
-
- const document = this._documents.get(URI.revive(uriComponents));
-
- if (!document) {
- return;
- }
-
- const renderer = this._notebookOutputRenderers.get(id)!;
- this.provideCommToNotebookRenderers(document, renderer);
-
- const cellsResponse: IOutputRenderResponseCellInfo[] = request.items.map(cellInfo => {
- const outputResponse: IOutputRenderResponseOutputInfo[] = cellInfo.outputs.map(output => {
- return {
- index: output.index,
- outputId: output.outputId,
- mimeType: output.mimeType,
- handlerId: id,
- transformedOutput: renderer.render(document, output.output! as vscode.CellDisplayOutput, output.outputId, output.mimeType)
- };
- });
-
- return {
- key: cellInfo.key,
- outputs: outputResponse
- };
- });
-
- return { items: cellsResponse };
- }
-
- findBestMatchedRenderer(mimeType: string): ExtHostNotebookOutputRenderer[] {
- const matches: ExtHostNotebookOutputRenderer[] = [];
- for (const renderer of this._notebookOutputRenderers) {
- if (renderer[1].matches(mimeType)) {
- matches.push(renderer[1]);
- }
- }
-
- return matches;
- }
-
registerNotebookContentProvider(
extension: IExtensionDescription,
viewType: string,
@@ -1234,26 +1093,6 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
await provider.provider.resolveNotebook(document, webComm.contentProviderComm);
}
- private provideCommToNotebookRenderers(document: ExtHostNotebookDocument, renderer: ExtHostNotebookOutputRenderer) {
- let alreadyRegistered = this._renderersUsedInNotebooks.get(document);
- if (!alreadyRegistered) {
- alreadyRegistered = new Set();
- this._renderersUsedInNotebooks.set(document, alreadyRegistered);
- }
-
- if (alreadyRegistered.has(renderer)) {
- return;
- }
-
- alreadyRegistered.add(renderer);
- for (const editorId of this._editors.keys()) {
- const comm = this._webviewComm.get(editorId);
- if (comm) {
- renderer.resolveNotebook(document, comm);
- }
- }
- }
-
async $executeNotebookByAttachedKernel(viewType: string, uri: UriComponents, cellHandle: number | undefined): Promise {
const document = this._documents.get(URI.revive(uri));
@@ -1502,11 +1341,6 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
}
this._editors.get(editorId)?.editor.dispose();
-
- for (const renderer of this._renderersUsedInNotebooks.get(document) ?? []) {
- renderer.resolveNotebook(document, webComm);
- }
-
this._editors.set(editorId, { editor });
}
diff --git a/src/vs/workbench/contrib/notebook/browser/extensionPoint.ts b/src/vs/workbench/contrib/notebook/browser/extensionPoint.ts
index c7b5c94f98dbf..a2945c71589f1 100644
--- a/src/vs/workbench/contrib/notebook/browser/extensionPoint.ts
+++ b/src/vs/workbench/contrib/notebook/browser/extensionPoint.ts
@@ -34,7 +34,7 @@ export interface INotebookRendererContribution {
readonly [NotebookRendererContribution.viewType]: string;
readonly [NotebookRendererContribution.displayName]: string;
readonly [NotebookRendererContribution.mimeTypes]?: readonly string[];
- readonly [NotebookRendererContribution.entrypoint]?: string;
+ readonly [NotebookRendererContribution.entrypoint]: string;
}
const notebookProviderContribution: IJSONSchema = {
@@ -101,6 +101,7 @@ const notebookRendererContribution: IJSONSchema = {
NotebookRendererContribution.viewType,
NotebookRendererContribution.displayName,
NotebookRendererContribution.mimeTypes,
+ NotebookRendererContribution.entrypoint,
],
properties: {
[NotebookRendererContribution.viewType]: {
diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts
index 8374805c4c40f..005d6077e0792 100644
--- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts
+++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts
@@ -22,7 +22,7 @@ import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/outpu
import { RunStateRenderer, TimerRenderer } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer';
import { CellViewModel, IModelDecorationsChangeAccessor, NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
-import { CellKind, IProcessedOutput, IRenderOutput, NotebookCellMetadata, NotebookDocumentMetadata, INotebookKernelInfo, IEditor, INotebookKernelInfo2 } from 'vs/workbench/contrib/notebook/common/notebookCommon';
+import { CellKind, IProcessedOutput, IRenderOutput, NotebookCellMetadata, NotebookDocumentMetadata, INotebookKernelInfo, IEditor, INotebookKernelInfo2, IInsetRenderOutput } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { Webview } from 'vs/workbench/contrib/webview/browser/webview';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
import { IMenu } from 'vs/platform/actions/common/actions';
@@ -334,7 +334,7 @@ export interface INotebookEditor extends IEditor {
/**
* Render the output in webview layer
*/
- createInset(cell: ICellViewModel, output: IProcessedOutput, shadowContent: string, offset: number): Promise;
+ createInset(cell: ICellViewModel, output: IInsetRenderOutput, offset: number): Promise;
/**
* Remove the output from the webview layer
@@ -557,6 +557,11 @@ export interface IOutputTransformContribution {
*/
dispose(): void;
+ /**
+ * Returns contents to place in the webview inset, or the {@link IRenderNoOutput}.
+ * This call is allowed to have side effects, such as placing output
+ * directly into the container element.
+ */
render(output: IProcessedOutput, container: HTMLElement, preferredMimeType: string | undefined): IRenderOutput;
}
diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts
index 378c52ad7c959..cff062ae1b18d 100644
--- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts
+++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts
@@ -36,7 +36,7 @@ import { CodeCellRenderer, MarkdownCellRenderer, NotebookCellListDelegate, ListT
import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel';
import { NotebookEventDispatcher, NotebookLayoutChangedEvent } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher';
import { CellViewModel, IModelDecorationsChangeAccessor, INotebookEditorViewState, NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
-import { CellKind, IProcessedOutput, INotebookKernelInfo, INotebookKernelInfoDto, INotebookKernelInfo2, NotebookRunState, NotebookCellRunState } from 'vs/workbench/contrib/notebook/common/notebookCommon';
+import { CellKind, IProcessedOutput, INotebookKernelInfo, INotebookKernelInfoDto, INotebookKernelInfo2, NotebookRunState, NotebookCellRunState, IInsetRenderOutput } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
import { Webview } from 'vs/workbench/contrib/webview/browser/webview';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
@@ -845,10 +845,6 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
}
}));
- if (this.viewModel && this.viewModel!.renderers.size) {
- this._webview?.updateRendererPreloads(this.viewModel!.renderers);
- }
-
this._webviewResolved = true;
resolve(this._webview!);
@@ -894,11 +890,6 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
}
}
- if (this.viewModel.renderers.size) {
- await this._resolveWebview();
- this._webview?.updateRendererPreloads(this.viewModel.renderers);
- }
-
this._localStore.add(this._list!.onWillScroll(e => {
if (!this._webviewResolved) {
return;
@@ -1571,23 +1562,21 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
this._list?.triggerScrollFromMouseWheelEvent(event);
}
- async createInset(cell: CodeCellViewModel, output: IProcessedOutput, shadowContent: string, offset: number) {
+ async createInset(cell: CodeCellViewModel, output: IInsetRenderOutput, offset: number) {
if (!this._webview) {
return;
}
await this._resolveWebview();
- const preloads = this._notebookViewModel!.renderers;
-
- if (!this._webview!.insetMapping.has(output)) {
+ if (!this._webview!.insetMapping.has(output.source)) {
const cellTop = this._list?.getAbsoluteTopOfElement(cell) || 0;
- await this._webview!.createInset(cell, output, cellTop, offset, shadowContent, preloads);
+ await this._webview!.createInset(cell, output, cellTop, offset);
} else {
const cellTop = this._list?.getAbsoluteTopOfElement(cell) || 0;
const scrollTop = this._list?.scrollTop || 0;
- this._webview!.updateViewScrollTop(-scrollTop, true, [{ cell: cell, output: output, cellTop: cellTop }]);
+ this._webview!.updateViewScrollTop(-scrollTop, true, [{ cell, output: output.source, cellTop }]);
}
}
diff --git a/src/vs/workbench/contrib/notebook/browser/notebookPureOutputRenderer.ts b/src/vs/workbench/contrib/notebook/browser/notebookPureOutputRenderer.ts
deleted file mode 100644
index af6c59fc4ed98..0000000000000
--- a/src/vs/workbench/contrib/notebook/browser/notebookPureOutputRenderer.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-/*---------------------------------------------------------------------------------------------
- * 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, public readonly displayName: 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 bec8d69a0b38b..7e0fb78f8aa05 100644
--- a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts
+++ b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts
@@ -3,39 +3,37 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
-import * as nls from 'vs/nls';
-import { Disposable, IDisposable, DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
-import { URI, UriComponents } from 'vs/base/common/uri';
-import { notebookProviderExtensionPoint, notebookRendererExtensionPoint, INotebookEditorContribution } from 'vs/workbench/contrib/notebook/browser/extensionPoint';
-import { NotebookProviderInfo, NotebookEditorDescriptor } from 'vs/workbench/contrib/notebook/common/notebookProvider';
-import { NotebookExtensionDescription } from 'vs/workbench/api/common/extHost.protocol';
-import { Emitter, Event } from 'vs/base/common/event';
-import { INotebookTextModel, INotebookRendererInfo, INotebookKernelInfo, CellOutputKind, ITransformedDisplayOutputDto, IDisplayOutput, ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, NOTEBOOK_DISPLAY_ORDER, sortMimeTypes, IOrderedMimeType, mimeTypeSupportedByCore, IOutputRenderRequestOutputInfo, IOutputRenderRequestCellInfo, NotebookCellOutputsSplice, ICellEditOperation, CellEditType, ICellInsertEdit, IOutputRenderResponse, IProcessedOutput, BUILTIN_RENDERER_ID, NotebookEditorPriority, INotebookKernelProvider, notebookDocumentFilterMatch, INotebookKernelInfo2, CellUri } from 'vs/workbench/contrib/notebook/common/notebookCommon';
-import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
-import { NotebookOutputRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookOutputRenderer';
-import { Iterable } from 'vs/base/common/iterator';
-import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
+import { flatten } from 'vs/base/common/arrays';
import { CancellationToken } from 'vs/base/common/cancellation';
-import { IEditorService, ICustomEditorViewTypesHandler, ICustomEditorInfo } from 'vs/workbench/services/editor/common/editorService';
-import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
-import { INotebookService, IMainNotebookController } from 'vs/workbench/contrib/notebook/common/notebookService';
+import { Emitter, Event } from 'vs/base/common/event';
import * as glob from 'vs/base/common/glob';
+import { Iterable } from 'vs/base/common/iterator';
+import { Disposable, DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { basename } from 'vs/base/common/path';
-import { getActiveNotebookEditor, INotebookEditor, NotebookEditorOptions } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
-import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
-import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
-import { Memento } from 'vs/workbench/common/memento';
-import { StorageScope, IStorageService } from 'vs/platform/storage/common/storage';
-import { IExtensionPointUser } from 'vs/workbench/services/extensions/common/extensionsRegistry';
-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';
+import { URI } from 'vs/base/common/uri';
import { RedoCommand, UndoCommand } from 'vs/editor/browser/editorExtensions';
import { CopyAction, CutAction, PasteAction } from 'vs/editor/contrib/clipboard/clipboard';
+import * as nls from 'vs/nls';
+import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
+import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
+import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
+import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
+import { NotebookExtensionDescription } from 'vs/workbench/api/common/extHost.protocol';
+import { Memento } from 'vs/workbench/common/memento';
+import { INotebookEditorContribution, notebookProviderExtensionPoint, notebookRendererExtensionPoint } from 'vs/workbench/contrib/notebook/browser/extensionPoint';
+import { getActiveNotebookEditor, INotebookEditor, NotebookEditorOptions } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
+import { NotebookKernelProviderAssociationRegistry, NotebookViewTypesExtensionRegistry, updateNotebookKernelProvideAssociationSchema } from 'vs/workbench/contrib/notebook/browser/notebookKernelAssociation';
import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
+import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
+import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
+import { ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, BUILTIN_RENDERER_ID, CellEditType, CellOutputKind, CellUri, ICellEditOperation, IDisplayOutput, INotebookKernelInfo, INotebookKernelInfo2, INotebookKernelProvider, INotebookRendererInfo, INotebookTextModel, IOrderedMimeType, ITransformedDisplayOutputDto, mimeTypeSupportedByCore, NotebookCellOutputsSplice, notebookDocumentFilterMatch, NotebookEditorPriority, NOTEBOOK_DISPLAY_ORDER, sortMimeTypes } from 'vs/workbench/contrib/notebook/common/notebookCommon';
+import { NotebookOutputRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookOutputRenderer';
+import { NotebookEditorDescriptor, NotebookProviderInfo } from 'vs/workbench/contrib/notebook/common/notebookProvider';
+import { IMainNotebookController, INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
+import { ICustomEditorInfo, ICustomEditorViewTypesHandler, IEditorService } from 'vs/workbench/services/editor/common/editorService';
+import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
+import { IExtensionPointUser } from 'vs/workbench/services/extensions/common/extensionsRegistry';
function MODEL_ID(resource: URI): string {
return resource.toString();
@@ -234,7 +232,6 @@ export class NotebookService extends Disposable implements INotebookService, ICu
declare readonly _serviceBrand: undefined;
static mainthreadNotebookDocumentHandle: number = 0;
private readonly _notebookProviders = new Map();
- private readonly _notebookRenderers = new Map();
private readonly _notebookKernels = new Map();
notebookProviderInfoStore: NotebookProviderInfoStore;
notebookRenderersInfoStore: NotebookOutputRendererInfoStore = new NotebookOutputRendererInfoStore();
@@ -291,15 +288,18 @@ export class NotebookService extends Disposable implements INotebookService, ICu
for (const extension of renderers) {
for (const notebookContribution of extension.value) {
+ if (!notebookContribution.entrypoint) { // avoid crashing
+ console.error(`Cannot register renderer for ${extension.description.identifier.value} since it did not have an entrypoint. This is now required: https://github.com/microsoft/vscode/issues/102644`);
+ continue;
+ }
+
this.notebookRenderersInfoStore.add(new NotebookOutputRendererInfo({
id: notebookContribution.viewType,
+ extension: extension.description,
+ entrypoint: notebookContribution.entrypoint,
displayName: notebookContribution.displayName,
mimeTypes: notebookContribution.mimeTypes || [],
}));
-
- if (notebookContribution.entrypoint) {
- this._notebookRenderers.set(notebookContribution.viewType, new PureNotebookOutputRenderer(notebookContribution.viewType, notebookContribution.displayName, extension.description, notebookContribution.entrypoint));
- }
}
}
@@ -553,19 +553,6 @@ export class NotebookService extends Disposable implements INotebookService, ICu
this._onDidChangeViewTypes.fire();
}
- registerNotebookRenderer(id: string, renderer: INotebookRendererInfo) {
- this._notebookRenderers.set(id, renderer);
- const staticInfo = this.notebookRenderersInfoStore.get(id);
-
- if (staticInfo) {
-
- }
- }
-
- unregisterNotebookRenderer(id: string) {
- this._notebookRenderers.delete(id);
- }
-
registerNotebookKernel(notebook: INotebookKernelInfo): void {
this._notebookKernels.set(notebook.id, notebook);
this._onDidChangeKernels.fire();
@@ -664,9 +651,7 @@ export class NotebookService extends Disposable implements INotebookService, ICu
}
getRendererInfo(id: string): INotebookRendererInfo | undefined {
- const renderer = this._notebookRenderers.get(id);
-
- return renderer;
+ return this.notebookRenderersInfoStore.get(id);
}
async resolveNotebook(viewType: string, uri: URI, forceReload: boolean, editorId?: string, backupId?: string): Promise {
@@ -719,55 +704,11 @@ export class NotebookService extends Disposable implements INotebookService, ICu
return this._models.get(modelId)?.model;
}
- private async _fillInTransformedOutputs(
- renderers: Set,
- requestItems: IOutputRenderRequestCellInfo[],
- renderFunc: (rendererId: string, items: IOutputRenderRequestCellInfo[]) => Promise | undefined>,
- lookUp: (key: T) => { outputs: IProcessedOutput[] }
- ) {
- for (const id of renderers) {
- const requestsPerRenderer: IOutputRenderRequestCellInfo[] = requestItems.map(req => {
- return {
- key: req.key,
- outputs: req.outputs.filter(output => output.handlerId === id)
- };
- });
-
- const response = await renderFunc(id, requestsPerRenderer);
-
- // mix the response with existing outputs, which will replace the picked transformed mimetype with resolved result
- if (response) {
- response.items.forEach(cellInfo => {
- const cell = lookUp(cellInfo.key)!;
- cellInfo.outputs.forEach(outputInfo => {
- const output = cell.outputs[outputInfo.index];
- if (output.outputKind === CellOutputKind.Rich && output.orderedMimeTypes && output.orderedMimeTypes.length) {
- output.orderedMimeTypes[0] = {
- mimeType: outputInfo.mimeType,
- isResolved: true,
- rendererId: outputInfo.handlerId,
- output: outputInfo.transformedOutput
- };
- }
- });
- });
- }
- }
- }
-
- async transformTextModelOutputs(textModel: NotebookTextModel) {
- const renderers = new Set();
-
- const cellMapping: Map = new Map();
-
- const requestItems: IOutputRenderRequestCellInfo[] = [];
+ private async transformTextModelOutputs(textModel: NotebookTextModel) {
for (let i = 0; i < textModel.cells.length; i++) {
const cell = textModel.cells[i];
- cellMapping.set(cell.uri.fragment, cell);
- const outputs = cell.outputs;
- const outputRequest: IOutputRenderRequestOutputInfo[] = [];
- outputs.forEach((output, index) => {
+ cell.outputs.forEach((output) => {
if (output.outputKind === CellOutputKind.Rich) {
// TODO no string[] casting
const ret = this._transformMimeTypes(output, output.outputId, textModel.metadata.displayOrder as string[] || []);
@@ -775,125 +716,43 @@ export class NotebookService extends Disposable implements INotebookService, ICu
const pickedMimeTypeIndex = ret.pickedMimeTypeIndex!;
output.pickedMimeTypeIndex = pickedMimeTypeIndex;
output.orderedMimeTypes = orderedMimeTypes;
-
- if (orderedMimeTypes[pickedMimeTypeIndex!].rendererId && orderedMimeTypes[pickedMimeTypeIndex].rendererId !== BUILTIN_RENDERER_ID) {
- outputRequest.push({ index, handlerId: orderedMimeTypes[pickedMimeTypeIndex].rendererId!, mimeType: orderedMimeTypes[pickedMimeTypeIndex].mimeType, outputId: output.outputId });
- renderers.add(orderedMimeTypes[pickedMimeTypeIndex].rendererId!);
- }
}
});
-
- requestItems.push({ key: cell.uri, outputs: outputRequest });
}
-
- await this._fillInTransformedOutputs(renderers, requestItems, async (rendererId, items) => {
- return await this._notebookRenderers.get(rendererId)?.render(textModel.uri, { items: items });
- }, (key: UriComponents) => { return cellMapping.get(URI.revive(key).fragment)!; });
-
- textModel.updateRenderers([...renderers]);
}
- async transformEditsOutputs(textModel: NotebookTextModel, edits: ICellEditOperation[]) {
- const renderers = new Set();
- const requestItems: IOutputRenderRequestCellInfo<[number, number]>[] = [];
-
- edits.forEach((edit, editIndex) => {
+ transformEditsOutputs(textModel: NotebookTextModel, edits: ICellEditOperation[]) {
+ edits.forEach((edit) => {
if (edit.editType === CellEditType.Insert) {
- edit.cells.forEach((cell, cellIndex) => {
+ edit.cells.forEach((cell) => {
const outputs = cell.outputs;
- const outputRequest: IOutputRenderRequestOutputInfo[] = [];
- outputs.map((output, index) => {
+ outputs.map((output) => {
if (output.outputKind === CellOutputKind.Rich) {
const ret = this._transformMimeTypes(output, output.outputId, textModel.metadata.displayOrder as string[] || []);
const orderedMimeTypes = ret.orderedMimeTypes!;
const pickedMimeTypeIndex = ret.pickedMimeTypeIndex!;
output.pickedMimeTypeIndex = pickedMimeTypeIndex;
output.orderedMimeTypes = orderedMimeTypes;
-
- if (orderedMimeTypes[pickedMimeTypeIndex!].rendererId && orderedMimeTypes[pickedMimeTypeIndex].rendererId !== BUILTIN_RENDERER_ID) {
- outputRequest.push({ index, handlerId: orderedMimeTypes[pickedMimeTypeIndex].rendererId!, mimeType: orderedMimeTypes[pickedMimeTypeIndex].mimeType, output: output, outputId: output.outputId });
- renderers.add(orderedMimeTypes[pickedMimeTypeIndex].rendererId!);
- }
}
});
-
- requestItems.push({ key: [editIndex, cellIndex], outputs: outputRequest });
});
}
});
-
- await this._fillInTransformedOutputs<[number, number]>(renderers, requestItems, async (rendererId, items) => {
- return await this._notebookRenderers.get(rendererId)?.render2<[number, number]>(textModel.uri, { items: items });
- }, (key: [number, number]) => {
- return (edits[key[0]] as ICellInsertEdit).cells[key[1]];
- });
-
- textModel.updateRenderers([...renderers]);
}
- async transformSpliceOutputs(textModel: NotebookTextModel, splices: NotebookCellOutputsSplice[]) {
- const renderers = new Set();
- const requestItems: IOutputRenderRequestCellInfo[] = [];
-
- splices.forEach((splice, spliceIndex) => {
+ transformSpliceOutputs(textModel: NotebookTextModel, splices: NotebookCellOutputsSplice[]) {
+ splices.forEach((splice) => {
const outputs = splice[2];
- const outputRequest: IOutputRenderRequestOutputInfo[] = [];
- outputs.map((output, index) => {
+ outputs.map((output) => {
if (output.outputKind === CellOutputKind.Rich) {
const ret = this._transformMimeTypes(output, output.outputId, textModel.metadata.displayOrder as string[] || []);
const orderedMimeTypes = ret.orderedMimeTypes!;
const pickedMimeTypeIndex = ret.pickedMimeTypeIndex!;
output.pickedMimeTypeIndex = pickedMimeTypeIndex;
output.orderedMimeTypes = orderedMimeTypes;
-
- if (orderedMimeTypes[pickedMimeTypeIndex!].rendererId && orderedMimeTypes[pickedMimeTypeIndex].rendererId !== BUILTIN_RENDERER_ID) {
- outputRequest.push({ index, handlerId: orderedMimeTypes[pickedMimeTypeIndex].rendererId!, mimeType: orderedMimeTypes[pickedMimeTypeIndex].mimeType, output: output, outputId: output.outputId });
- renderers.add(orderedMimeTypes[pickedMimeTypeIndex].rendererId!);
- }
}
});
- requestItems.push({ key: spliceIndex, outputs: outputRequest });
});
-
- await this._fillInTransformedOutputs(renderers, requestItems, async (rendererId, items) => {
- return await this._notebookRenderers.get(rendererId)?.render2(textModel.uri, { items: items });
- }, (key: number) => {
- return { outputs: splices[key][2] };
- });
-
- textModel.updateRenderers([...renderers]);
- }
-
- async transformSingleOutput(textModel: NotebookTextModel, output: IProcessedOutput, rendererId: string, mimeType: string): Promise {
- const items = [
- {
- key: 0,
- outputs: [
- {
- index: 0,
- outputId: generateUuid(),
- handlerId: rendererId,
- mimeType: mimeType,
- output: output
- }
- ]
- }
- ];
- const response = await this._notebookRenderers.get(rendererId)?.render2(textModel.uri, { items: items });
-
- if (response) {
- textModel.updateRenderers([rendererId]);
- const outputInfo = response.items[0].outputs[0];
-
- return {
- mimeType: outputInfo.mimeType,
- isResolved: true,
- rendererId: outputInfo.handlerId,
- output: outputInfo.transformedOutput
- };
- }
-
- return;
}
private _transformMimeTypes(output: IDisplayOutput, outputId: string, documentDisplayOrder: string[]): ITransformedDisplayOutputDto {
@@ -911,14 +770,12 @@ export class NotebookService extends Disposable implements INotebookService, ICu
orderMimeTypes.push({
mimeType: mimeType,
- isResolved: false,
rendererId: handler.id,
});
for (let i = 1; i < handlers.length; i++) {
orderMimeTypes.push({
mimeType: mimeType,
- isResolved: false,
rendererId: handlers[i].id
});
}
@@ -926,14 +783,12 @@ export class NotebookService extends Disposable implements INotebookService, ICu
if (mimeTypeSupportedByCore(mimeType)) {
orderMimeTypes.push({
mimeType: mimeType,
- isResolved: false,
rendererId: BUILTIN_RENDERER_ID
});
}
} else {
orderMimeTypes.push({
mimeType: mimeType,
- isResolved: false,
rendererId: BUILTIN_RENDERER_ID
});
}
diff --git a/src/vs/workbench/contrib/notebook/browser/view/output/outputRenderer.ts b/src/vs/workbench/contrib/notebook/browser/view/output/outputRenderer.ts
index 7e988c861426b..56114e323a516 100644
--- a/src/vs/workbench/contrib/notebook/browser/view/output/outputRenderer.ts
+++ b/src/vs/workbench/contrib/notebook/browser/view/output/outputRenderer.ts
@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
-import { IProcessedOutput, IRenderOutput } from 'vs/workbench/contrib/notebook/common/notebookCommon';
+import { IProcessedOutput, IRenderOutput, RenderOutputType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { NotebookRegistry } from 'vs/workbench/contrib/notebook/browser/notebookRegistry';
import { onUnexpectedError } from 'vs/base/common/errors';
import { INotebookEditor, IOutputTransformContribution } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
@@ -38,9 +38,7 @@ export class OutputRenderer {
contentNode.innerText = `No renderer could be found for output. It has the following output type: ${output.outputKind}`;
container.appendChild(contentNode);
- return {
- hasDynamicHeight: false
- };
+ return { type: RenderOutputType.None, hasDynamicHeight: false };
}
render(output: IProcessedOutput, container: HTMLElement, preferredMimeType: string | undefined): IRenderOutput {
diff --git a/src/vs/workbench/contrib/notebook/browser/view/output/transforms/errorTransform.ts b/src/vs/workbench/contrib/notebook/browser/view/output/transforms/errorTransform.ts
index 7998129daa4c6..9e0c4ba423093 100644
--- a/src/vs/workbench/contrib/notebook/browser/view/output/transforms/errorTransform.ts
+++ b/src/vs/workbench/contrib/notebook/browser/view/output/transforms/errorTransform.ts
@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
-import { IRenderOutput, CellOutputKind, IErrorOutput } from 'vs/workbench/contrib/notebook/common/notebookCommon';
+import { IRenderOutput, CellOutputKind, IErrorOutput, RenderOutputType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { NotebookRegistry } from 'vs/workbench/contrib/notebook/browser/notebookRegistry';
import * as DOM from 'vs/base/browser/dom';
import { RGBA, Color } from 'vs/base/common/color';
@@ -36,9 +36,7 @@ class ErrorTransform implements IOutputTransformContribution {
}
container.appendChild(traceback);
DOM.addClasses(container, 'error');
- return {
- hasDynamicHeight: false
- };
+ return { type: RenderOutputType.None, hasDynamicHeight: false };
}
dispose(): void {
diff --git a/src/vs/workbench/contrib/notebook/browser/view/output/transforms/richTransform.ts b/src/vs/workbench/contrib/notebook/browser/view/output/transforms/richTransform.ts
index 73a1fd4af7e01..76ffcc3f35280 100644
--- a/src/vs/workbench/contrib/notebook/browser/view/output/transforms/richTransform.ts
+++ b/src/vs/workbench/contrib/notebook/browser/view/output/transforms/richTransform.ts
@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
-import { IRenderOutput, CellOutputKind, ITransformedDisplayOutputDto } from 'vs/workbench/contrib/notebook/common/notebookCommon';
+import { IRenderOutput, CellOutputKind, ITransformedDisplayOutputDto, RenderOutputType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { NotebookRegistry } from 'vs/workbench/contrib/notebook/browser/notebookRegistry';
import * as DOM from 'vs/base/browser/dom';
import { INotebookEditor, IOutputTransformContribution } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
@@ -46,10 +46,7 @@ class RichRenderer implements IOutputTransformContribution {
const contentNode = document.createElement('p');
contentNode.innerText = `No data could be found for output.`;
container.appendChild(contentNode);
-
- return {
- hasDynamicHeight: false
- };
+ return { type: RenderOutputType.None, hasDynamicHeight: false };
}
if (!preferredMimeType || !this._richMimeTypeRenderers.has(preferredMimeType)) {
@@ -68,17 +65,14 @@ class RichRenderer implements IOutputTransformContribution {
}
container.appendChild(contentNode);
-
- return {
- hasDynamicHeight: false
- };
+ return { type: RenderOutputType.None, hasDynamicHeight: false };
}
const renderer = this._richMimeTypeRenderers.get(preferredMimeType);
return renderer!(output, container);
}
- renderJSON(output: ITransformedDisplayOutputDto, container: HTMLElement) {
+ renderJSON(output: ITransformedDisplayOutputDto, container: HTMLElement): IRenderOutput {
const data = output.data['application/json'];
const str = JSON.stringify(data, null, '\t');
@@ -108,12 +102,10 @@ class RichRenderer implements IOutputTransformContribution {
container.style.height = `${height + 16}px`;
- return {
- hasDynamicHeight: true
- };
+ return { type: RenderOutputType.None, hasDynamicHeight: true };
}
- renderCode(output: ITransformedDisplayOutputDto, container: HTMLElement) {
+ renderCode(output: ITransformedDisplayOutputDto, container: HTMLElement): IRenderOutput {
const data = output.data['text/x-javascript'];
const str = (isArray(data) ? data.join('') : data) as string;
@@ -143,87 +135,81 @@ class RichRenderer implements IOutputTransformContribution {
container.style.height = `${height + 16}px`;
- return {
- hasDynamicHeight: true
- };
+ return { type: RenderOutputType.None, hasDynamicHeight: true };
}
- renderJavaScript(output: ITransformedDisplayOutputDto, container: HTMLElement) {
+ renderJavaScript(output: ITransformedDisplayOutputDto, container: HTMLElement): IRenderOutput {
const data = output.data['application/javascript'];
const str = isArray(data) ? data.join('') : data;
const scriptVal = ``;
return {
- shadowContent: scriptVal,
+ type: RenderOutputType.Html,
+ source: output,
+ htmlContent: scriptVal,
hasDynamicHeight: false
};
}
- renderHTML(output: ITransformedDisplayOutputDto, container: HTMLElement) {
+ renderHTML(output: ITransformedDisplayOutputDto, container: HTMLElement): IRenderOutput {
const data = output.data['text/html'];
const str = (isArray(data) ? data.join('') : data) as string;
return {
- shadowContent: str,
+ type: RenderOutputType.Html,
+ source: output,
+ htmlContent: str,
hasDynamicHeight: false
};
-
}
- renderSVG(output: ITransformedDisplayOutputDto, container: HTMLElement) {
+ renderSVG(output: ITransformedDisplayOutputDto, container: HTMLElement): IRenderOutput {
const data = output.data['image/svg+xml'];
const str = (isArray(data) ? data.join('') : data) as string;
return {
- shadowContent: str,
+ type: RenderOutputType.Html,
+ source: output,
+ htmlContent: str,
hasDynamicHeight: false
};
}
- renderMarkdown(output: ITransformedDisplayOutputDto, container: HTMLElement) {
+ renderMarkdown(output: ITransformedDisplayOutputDto, container: HTMLElement): IRenderOutput {
const data = output.data['text/markdown'];
const str = (isArray(data) ? data.join('') : data) as string;
const mdOutput = document.createElement('div');
mdOutput.appendChild(this._mdRenderer.render({ value: str, isTrusted: true, supportThemeIcons: true }).element);
container.appendChild(mdOutput);
- return {
- hasDynamicHeight: true
- };
+ return { type: RenderOutputType.None, hasDynamicHeight: true };
}
- renderPNG(output: ITransformedDisplayOutputDto, container: HTMLElement) {
+ renderPNG(output: ITransformedDisplayOutputDto, container: HTMLElement): IRenderOutput {
const image = document.createElement('img');
image.src = `data:image/png;base64,${output.data['image/png']}`;
const display = document.createElement('div');
DOM.addClasses(display, 'display');
display.appendChild(image);
container.appendChild(display);
- return {
- hasDynamicHeight: true
- };
-
+ return { type: RenderOutputType.None, hasDynamicHeight: true };
}
- renderJPEG(output: ITransformedDisplayOutputDto, container: HTMLElement) {
+ renderJPEG(output: ITransformedDisplayOutputDto, container: HTMLElement): IRenderOutput {
const image = document.createElement('img');
image.src = `data:image/jpeg;base64,${output.data['image/jpeg']}`;
const display = document.createElement('div');
DOM.addClasses(display, 'display');
display.appendChild(image);
container.appendChild(display);
- return {
- hasDynamicHeight: true
- };
+ return { type: RenderOutputType.None, hasDynamicHeight: true };
}
- renderPlainText(output: ITransformedDisplayOutputDto, container: HTMLElement) {
+ renderPlainText(output: ITransformedDisplayOutputDto, container: HTMLElement): IRenderOutput {
const data = output.data['text/plain'];
const str = (isArray(data) ? data.join('') : data) as string;
const contentNode = DOM.$('.output-plaintext');
contentNode.appendChild(handleANSIOutput(str, this.themeService));
container.appendChild(contentNode);
- return {
- hasDynamicHeight: false
- };
+ return { type: RenderOutputType.None, hasDynamicHeight: false };
}
dispose(): void {
diff --git a/src/vs/workbench/contrib/notebook/browser/view/output/transforms/streamTransform.ts b/src/vs/workbench/contrib/notebook/browser/view/output/transforms/streamTransform.ts
index b3d7698c233dc..65f1826f750de 100644
--- a/src/vs/workbench/contrib/notebook/browser/view/output/transforms/streamTransform.ts
+++ b/src/vs/workbench/contrib/notebook/browser/view/output/transforms/streamTransform.ts
@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as DOM from 'vs/base/browser/dom';
-import { IRenderOutput, CellOutputKind, IStreamOutput } from 'vs/workbench/contrib/notebook/common/notebookCommon';
+import { IRenderOutput, CellOutputKind, IStreamOutput, RenderOutputType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { NotebookRegistry } from 'vs/workbench/contrib/notebook/browser/notebookRegistry';
import { INotebookEditor, IOutputTransformContribution } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
@@ -18,10 +18,7 @@ class StreamRenderer implements IOutputTransformContribution {
const contentNode = DOM.$('.output-stream');
contentNode.innerText = output.text;
container.appendChild(contentNode);
- return {
- hasDynamicHeight: false
- };
-
+ return { type: RenderOutputType.None, hasDynamicHeight: false };
}
dispose(): void {
diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts
index 7f37bd88b208a..3a0eab9dda2c2 100644
--- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts
+++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts
@@ -16,7 +16,7 @@ import { IOpenerService, matchesScheme } from 'vs/platform/opener/common/opener'
import { CELL_MARGIN, CELL_RUN_GUTTER, CODE_CELL_LEFT_MARGIN, CELL_OUTPUT_PADDING } from 'vs/workbench/contrib/notebook/browser/constants';
import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel';
-import { CellOutputKind, IProcessedOutput } from 'vs/workbench/contrib/notebook/common/notebookCommon';
+import { CellOutputKind, IDisplayOutput, IInsetRenderOutput, INotebookRendererInfo, IProcessedOutput, ITransformedDisplayOutputDto, RenderOutputType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
import { IWebviewService, WebviewElement, WebviewContentPurpose } from 'vs/workbench/contrib/webview/browser/webview';
import { asWebviewUri } from 'vs/workbench/contrib/webview/common/webviewUri';
@@ -88,12 +88,14 @@ export interface IClearMessage {
export interface ICreationRequestMessage {
type: 'html';
- content: string;
+ content:
+ | { type: RenderOutputType.Html; htmlContent: string }
+ | { type: RenderOutputType.Extension; output: IDisplayOutput; mimeType: string };
cellId: string;
outputId: string;
top: number;
left: number;
- requiredPreloads: IPreloadResource[];
+ requiredPreloads: ReadonlyArray;
initiallyHidden?: boolean;
apiNamespace?: string | undefined;
}
@@ -200,7 +202,7 @@ export type AnyMessage = FromWebviewMessage | ToWebviewMessage;
interface ICachedInset {
outputId: string;
cell: CodeCellViewModel;
- preloads: ReadonlySet;
+ renderer?: INotebookRendererInfo;
cachedCreation: ICreationRequestMessage;
}
@@ -224,11 +226,11 @@ export class BackLayerWebView extends Disposable {
insetMapping: Map = new Map();
hiddenInsetMapping: Set = new Set();
reversedInsetMapping: Map = new Map();
- preloadsCache: Map = new Map();
localResourceRootsCache: URI[] | undefined = undefined;
rendererRootsCache: URI[] = [];
kernelRootsCache: URI[] = [];
private readonly _onMessage = this._register(new Emitter());
+ private readonly _preloadsCache = new Set();
public readonly onMessage: Event = this._onMessage.event;
private _loaded!: Promise;
private _initalized?: Promise;
@@ -425,9 +427,17 @@ ${loaderJs}
return;
}
- this.preloadsCache.clear();
+ let renderers = new Set();
+ for (const inset of this.insetMapping.values()) {
+ if (inset.renderer) {
+ renderers.add(inset.renderer);
+ }
+ }
+
+ this._preloadsCache.clear();
+ this.updateRendererPreloads(renderers);
+
for (const [output, inset] of this.insetMapping.entries()) {
- this.updateRendererPreloads(inset.preloads);
this._sendMessageToWebview({ ...inset.cachedCreation, initiallyHidden: this.hiddenInsetMapping.has(output) });
}
}));
@@ -622,19 +632,18 @@ ${loaderJs}
});
}
- async createInset(cell: CodeCellViewModel, output: IProcessedOutput, cellTop: number, offset: number, shadowContent: string, preloads: Set) {
+ async createInset(cell: CodeCellViewModel, content: IInsetRenderOutput, cellTop: number, offset: number) {
if (this._disposed) {
return;
}
- const requiredPreloads = await this.updateRendererPreloads(preloads);
const initialTop = cellTop + offset;
- if (this.insetMapping.has(output)) {
- const outputCache = this.insetMapping.get(output);
+ if (this.insetMapping.has(content.source)) {
+ const outputCache = this.insetMapping.get(content.source);
if (outputCache) {
- this.hiddenInsetMapping.delete(output);
+ this.hiddenInsetMapping.delete(content.source);
this._sendMessageToWebview({
type: 'showOutput',
cellId: outputCache.cell.id,
@@ -645,30 +654,49 @@ ${loaderJs}
}
}
- const outputId = output.outputKind === CellOutputKind.Rich ? output.outputId : UUID.generateUuid();
- let apiNamespace: string | undefined;
- if (output.outputKind === CellOutputKind.Rich && output.pickedMimeTypeIndex !== undefined) {
- const pickedMimeTypeRenderer = output.orderedMimeTypes?.[output.pickedMimeTypeIndex];
- if (pickedMimeTypeRenderer?.rendererId) {
- apiNamespace = this.notebookService.getRendererInfo(pickedMimeTypeRenderer.rendererId)?.id;
- }
- }
-
- const message: ICreationRequestMessage = {
+ const messageBase = {
type: 'html',
- content: shadowContent,
cellId: cell.id,
- apiNamespace,
- outputId: outputId,
top: initialTop,
- requiredPreloads,
- left: 0
- };
+ left: 0,
+ requiredPreloads: [],
+ } as const;
+
+ let message: ICreationRequestMessage;
+ let renderer: INotebookRendererInfo | undefined;
+ if (content.type === RenderOutputType.Extension) {
+ const output = content.source as ITransformedDisplayOutputDto;
+ renderer = content.renderer;
+ message = {
+ ...messageBase,
+ outputId: output.outputId,
+ apiNamespace: content.renderer.id,
+ requiredPreloads: await this.updateRendererPreloads([content.renderer]),
+ content: {
+ type: RenderOutputType.Extension,
+ mimeType: content.mimeType,
+ output: {
+ outputKind: CellOutputKind.Rich,
+ metadata: output.metadata,
+ data: output.data,
+ },
+ },
+ };
+ } else {
+ message = {
+ ...messageBase,
+ outputId: UUID.generateUuid(),
+ content: {
+ type: content.type,
+ htmlContent: content.htmlContent,
+ }
+ };
+ }
this._sendMessageToWebview(message);
- this.insetMapping.set(output, { outputId: outputId, cell: cell, preloads, cachedCreation: message });
- this.hiddenInsetMapping.delete(output);
- this.reversedInsetMapping.set(outputId, output);
+ this.insetMapping.set(content.source, { outputId: message.outputId, cell, renderer, cachedCreation: message });
+ this.hiddenInsetMapping.delete(content.source);
+ this.reversedInsetMapping.set(message.outputId, content.source);
}
removeInset(output: IProcessedOutput) {
@@ -774,9 +802,9 @@ ${loaderJs}
});
preloads.forEach(e => {
- if (!this.preloadsCache.has(e.toString())) {
+ if (!this._preloadsCache.has(e.toString())) {
resources.push({ uri: e.toString() });
- this.preloadsCache.set(e.toString(), true);
+ this._preloadsCache.add(e.toString());
}
});
@@ -788,7 +816,7 @@ ${loaderJs}
this._updatePreloads(resources, 'kernel');
}
- async updateRendererPreloads(preloads: ReadonlySet) {
+ async updateRendererPreloads(renderers: Iterable) {
if (this._disposed) {
return [];
}
@@ -798,28 +826,21 @@ ${loaderJs}
const requiredPreloads: IPreloadResource[] = [];
const resources: IPreloadResource[] = [];
const extensionLocations: URI[] = [];
- preloads.forEach(preload => {
- const rendererInfo = this.notebookService.getRendererInfo(preload);
-
- if (rendererInfo) {
- const preloadResources = rendererInfo.preloads.map(preloadResource => {
- if (this.environmentService.isExtensionDevelopment && (preloadResource.scheme === 'http' || preloadResource.scheme === 'https')) {
- return preloadResource;
- }
- return asWebviewUri(this.workbenchEnvironmentService, this.id, preloadResource);
- });
- extensionLocations.push(rendererInfo.extensionLocation);
- preloadResources.forEach(e => {
- const resource: IPreloadResource = { uri: e.toString() };
- requiredPreloads.push(resource);
-
- if (!this.preloadsCache.has(e.toString())) {
- resources.push(resource);
- this.preloadsCache.set(e.toString(), true);
- }
- });
- }
- });
+ for (const rendererInfo of renderers) {
+ const preloads = [rendererInfo.entrypoint, ...rendererInfo.preloads]
+ .map(preload => asWebviewUri(this.workbenchEnvironmentService, this.id, preload));
+ extensionLocations.push(rendererInfo.extensionLocation);
+
+ preloads.forEach(e => {
+ const resource: IPreloadResource = { uri: e.toString() };
+ requiredPreloads.push(resource);
+
+ if (!this._preloadsCache.has(e.toString())) {
+ resources.push(resource);
+ this._preloadsCache.add(e.toString());
+ }
+ });
+ }
if (!resources.length) {
return requiredPreloads;
@@ -855,7 +876,7 @@ ${loaderJs}
}
clearPreloadsCache() {
- this.preloadsCache.clear();
+ this._preloadsCache.clear();
}
dispose() {
diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts
index ef7e8c202a176..03b24d3ca060b 100644
--- a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts
+++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts
@@ -15,7 +15,7 @@ import { CellFocusMode, CodeCellRenderTemplate, INotebookEditor } from 'vs/workb
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
import { getResizesObserver } from 'vs/workbench/contrib/notebook/browser/view/renderers/sizeObserver';
import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel';
-import { CellOutputKind, IProcessedOutput, IRenderOutput, ITransformedDisplayOutputDto, BUILTIN_RENDERER_ID } from 'vs/workbench/contrib/notebook/common/notebookCommon';
+import { CellOutputKind, IProcessedOutput, IRenderOutput, ITransformedDisplayOutputDto, BUILTIN_RENDERER_ID, RenderOutputType, outputHasDynamicHeight } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode } from 'vs/base/common/keyCodes';
import { IDimension } from 'vs/editor/common/editorCommon';
@@ -322,7 +322,7 @@ export class CodeCell extends Disposable {
const renderedOutput = this.outputElements.get(currOutput);
if (renderedOutput) {
- if (renderedOutput.renderResult.shadowContent) {
+ if (renderedOutput.renderResult.type !== RenderOutputType.None) {
// Show inset in webview, or render output that isn't rendered
this.renderOutput(currOutput, index, undefined);
} else {
@@ -408,9 +408,10 @@ export class CodeCell extends Disposable {
}
);
+ // for contents for which we don't observe for dynamic height, update them manually
this.viewCell.outputs.forEach((o, i) => {
const renderedOutput = this.outputElements.get(o);
- if (renderedOutput && !renderedOutput.renderResult.hasDynamicHeight && !renderedOutput.renderResult.shadowContent) {
+ if (renderedOutput && renderedOutput.renderResult.type === RenderOutputType.None && !renderedOutput.renderResult.hasDynamicHeight) {
this.viewCell.updateOutputHeight(i, renderedOutput.element.clientHeight);
}
});
@@ -469,9 +470,12 @@ export class CodeCell extends Disposable {
const innerContainer = DOM.$('.output-inner-container');
DOM.append(outputItemDiv, innerContainer);
- if (pickedMimeTypeRenderer.isResolved) {
- // html
- result = this.notebookEditor.getOutputRenderer().render({ outputId: currOutput.outputId, outputKind: CellOutputKind.Rich, data: { 'text/html': pickedMimeTypeRenderer.output! } }, innerContainer, 'text/html');
+
+ if (pickedMimeTypeRenderer.rendererId !== BUILTIN_RENDERER_ID) {
+ const renderer = this.notebookService.getRendererInfo(pickedMimeTypeRenderer.rendererId);
+ result = renderer
+ ? { type: RenderOutputType.Extension, renderer, source: currOutput, mimeType: pickedMimeTypeRenderer.mimeType }
+ : this.notebookEditor.getOutputRenderer().render(currOutput, innerContainer, pickedMimeTypeRenderer.mimeType);
} else {
result = this.notebookEditor.getOutputRenderer().render(currOutput, innerContainer, pickedMimeTypeRenderer.mimeType);
}
@@ -496,18 +500,16 @@ export class CodeCell extends Disposable {
this.templateData.outputContainer?.appendChild(outputItemDiv);
}
- if (result.shadowContent) {
+ if (result.type !== RenderOutputType.None) {
this.viewCell.selfSizeMonitoring = true;
- this.notebookEditor.createInset(this.viewCell, currOutput, result.shadowContent, this.viewCell.getOutputOffset(index));
+ this.notebookEditor.createInset(this.viewCell, result, this.viewCell.getOutputOffset(index));
} else {
DOM.addClass(outputItemDiv, 'foreground');
DOM.addClass(outputItemDiv, 'output-element');
outputItemDiv.style.position = 'absolute';
}
- const hasDynamicHeight = result.hasDynamicHeight;
-
- if (hasDynamicHeight) {
+ if (outputHasDynamicHeight(result)) {
this.viewCell.selfSizeMonitoring = true;
const clientHeight = outputItemDiv.clientHeight;
@@ -535,18 +537,12 @@ export class CodeCell extends Disposable {
elementSizeObserver.startObserving();
this.outputResizeListeners.get(currOutput)!.add(elementSizeObserver);
this.viewCell.updateOutputHeight(index, clientHeight);
- } else {
- if (result.shadowContent) {
- // webview
- // noop
- } else {
- // static output
- const clientHeight = Math.ceil(outputItemDiv.clientHeight);
- this.viewCell.updateOutputHeight(index, clientHeight);
+ } else if (result.type !== RenderOutputType.None) { // no-op if it's a webview
+ const clientHeight = Math.ceil(outputItemDiv.clientHeight);
+ this.viewCell.updateOutputHeight(index, clientHeight);
- const top = this.viewCell.getOutputOffsetInContainer(index);
- outputItemDiv.style.top = `${top}px`;
- }
+ const top = this.viewCell.getOutputOffsetInContainer(index);
+ outputItemDiv.style.top = `${top}px`;
}
}
@@ -605,17 +601,6 @@ export class CodeCell extends Disposable {
}
output.pickedMimeTypeIndex = pick;
-
- if (!output.orderedMimeTypes![pick].isResolved && output.orderedMimeTypes![pick].rendererId !== BUILTIN_RENDERER_ID) {
- // since it's not build in renderer and not resolved yet
- // let's see if we can activate the extension and then render
- // await this.notebookService.transformSpliceOutputs(this.notebookEditor.textModel!, [[0, 0, output]])
- const outputRet = await this.notebookService.transformSingleOutput(this.notebookEditor.textModel!, output, output.orderedMimeTypes![pick].rendererId!, output.orderedMimeTypes![pick].mimeType);
- if (outputRet) {
- output.orderedMimeTypes![pick] = outputRet;
- }
- }
-
this.renderOutput(output, index, nextElement);
this.relayoutCell();
}
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 622c1104e976f..9caa12e52b73c 100644
--- a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts
+++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts
@@ -6,6 +6,7 @@
import type { Event } from 'vs/base/common/event';
import type { IDisposable } from 'vs/base/common/lifecycle';
import { ToWebviewMessage } from 'vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView';
+import { RenderOutputType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
// !! IMPORTANT !! everything must be in-line within the webviewPreloads
// function. Imports are not allowed. This is stringifies and injected into
@@ -373,24 +374,21 @@ function webviewPreloads() {
addMouseoverListeners(outputNode, outputId);
const content = data.content;
- 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 { }
+ if (content.type === RenderOutputType.Html) {
+ outputNode.innerHTML = content.htmlContent;
+ cellOutputContainer.appendChild(outputNode);
+ domEval(outputNode);
+ } else {
+ onDidCreateOutput.fire([data.apiNamespace, {
+ element: outputNode,
+ output: content.output,
+ mimeType: content.mimeType,
+ outputId
+ }]);
+ cellOutputContainer.appendChild(outputNode);
}
- // eval
- domEval(outputNode);
resizeObserve(outputNode, outputId);
- onDidCreateOutput.fire([data.apiNamespace, {
- element: outputNode,
- output: pureData?.output,
- mimeType: pureData?.mimeType,
- outputId
- }]);
vscode.postMessage({
__vscode_notebook_message: true,
diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts
index b04c3e18ed5e2..3c26621a68207 100644
--- a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts
+++ b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts
@@ -170,10 +170,6 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD
return this._notebook;
}
- get renderers() {
- return this._notebook!.renderers;
- }
-
get handle() {
return this._notebook.handle;
}
diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts
index d48a7968a42e2..920d34f6f7016 100644
--- a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts
+++ b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts
@@ -136,7 +136,6 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
cells: NotebookCellTextModel[];
languages: string[] = [];
metadata: NotebookDocumentMetadata = notebookDocumentMetadataDefaults;
- renderers = new Set();
private _isUntitled: boolean | undefined = undefined;
private _versionId = 0;
@@ -369,12 +368,6 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
}
}
- updateRenderers(renderers: string[]) {
- renderers.forEach(render => {
- this.renderers.add(render);
- });
- }
-
insertTemplateCell(cell: NotebookCellTextModel) {
if (this.cells.length > 0 || this._isUntitled !== undefined) {
return;
diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts
index 319c8fd913009..68b34d4a5d3cf 100644
--- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts
+++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts
@@ -114,11 +114,12 @@ export interface INotebookMimeTypeSelector {
export interface INotebookRendererInfo {
id: string;
displayName: string;
+ entrypoint: URI;
+ preloads: ReadonlyArray;
+ extensionLocation: URI;
extensionId: ExtensionIdentifier;
- extensionLocation: URI,
- preloads: URI[],
- render(uri: URI, request: IOutputRenderRequest): Promise | undefined>;
- render2(uri: URI, request: IOutputRenderRequest): Promise | undefined>;
+
+ matches(mimeType: string): boolean;
}
export interface INotebookKernelInfo {
@@ -190,9 +191,7 @@ export enum MimeTypeRendererResolver {
export interface IOrderedMimeType {
mimeType: string;
- isResolved: boolean;
- rendererId?: string;
- output?: string;
+ rendererId: string;
}
export interface ITransformedDisplayOutputDto {
@@ -280,17 +279,41 @@ export interface INotebookTextModel {
readonly versionId: number;
languages: string[];
cells: ICell[];
- renderers: Set;
onDidChangeCells?: Event<{ synchronous: boolean, splices: NotebookCellTextModelSplice[] }>;
onDidChangeContent: Event;
onWillDispose(listener: () => void): IDisposable;
}
-export interface IRenderOutput {
- shadowContent?: string;
+export const enum RenderOutputType {
+ None,
+ Html,
+ Extension
+}
+
+export interface IRenderNoOutput {
+ type: RenderOutputType.None;
hasDynamicHeight: boolean;
}
+export interface IRenderPlainHtmlOutput {
+ type: RenderOutputType.Html;
+ source: IProcessedOutput;
+ htmlContent: string;
+ hasDynamicHeight: boolean;
+}
+
+export interface IRenderOutputViaExtension {
+ type: RenderOutputType.Extension;
+ source: IProcessedOutput;
+ mimeType: string;
+ renderer: INotebookRendererInfo;
+}
+
+export type IInsetRenderOutput = IRenderPlainHtmlOutput | IRenderOutputViaExtension;
+export type IRenderOutput = IRenderNoOutput | IInsetRenderOutput;
+
+export const outputHasDynamicHeight = (o: IRenderOutput) => o.type === RenderOutputType.Extension || o.hasDynamicHeight;
+
export type NotebookCellTextModelSplice = [
number /* start */,
number,
diff --git a/src/vs/workbench/contrib/notebook/common/notebookOutputRenderer.ts b/src/vs/workbench/contrib/notebook/common/notebookOutputRenderer.ts
index b22c64145eb25..4ac836f1f9d8b 100644
--- a/src/vs/workbench/contrib/notebook/common/notebookOutputRenderer.ts
+++ b/src/vs/workbench/contrib/notebook/common/notebookOutputRenderer.ts
@@ -4,31 +4,42 @@
*--------------------------------------------------------------------------------------------*/
import * as glob from 'vs/base/common/glob';
+import { joinPath } from 'vs/base/common/resources';
+import { URI } from 'vs/base/common/uri';
+import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
+import { INotebookRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookCommon';
-export class NotebookOutputRendererInfo {
+export class NotebookOutputRendererInfo implements INotebookRendererInfo {
readonly id: string;
+ readonly entrypoint: URI;
readonly displayName: string;
- readonly mimeTypes: readonly string[];
- readonly mimeTypeGlobs: glob.ParsedPattern[];
+ readonly extensionLocation: URI;
+ readonly extensionId: ExtensionIdentifier;
+ // todo: re-add preloads in pure renderer API
+ readonly preloads: ReadonlyArray = [];
+
+ private readonly mimeTypes: readonly string[];
+ private readonly mimeTypeGlobs: glob.ParsedPattern[];
constructor(descriptor: {
readonly id: string;
readonly displayName: string;
+ readonly entrypoint: string;
readonly mimeTypes: readonly string[];
+ readonly extension: IExtensionDescription;
}) {
this.id = descriptor.id;
+ this.extensionId = descriptor.extension.identifier;
+ this.extensionLocation = descriptor.extension.extensionLocation;
+ this.entrypoint = joinPath(this.extensionLocation, descriptor.entrypoint);
this.displayName = descriptor.displayName;
this.mimeTypes = descriptor.mimeTypes;
this.mimeTypeGlobs = this.mimeTypes.map(pattern => glob.parse(pattern));
}
matches(mimeType: string) {
- const matched = this.mimeTypeGlobs.find(pattern => pattern(mimeType));
- if (matched) {
- return true;
- }
-
- return this.mimeTypes.find(pattern => pattern === mimeType);
+ return this.mimeTypeGlobs.some(pattern => pattern(mimeType))
+ || this.mimeTypes.some(pattern => pattern === mimeType);
}
}
diff --git a/src/vs/workbench/contrib/notebook/common/notebookService.ts b/src/vs/workbench/contrib/notebook/common/notebookService.ts
index 87fad7fb36428..1eb32840394c9 100644
--- a/src/vs/workbench/contrib/notebook/common/notebookService.ts
+++ b/src/vs/workbench/contrib/notebook/common/notebookService.ts
@@ -10,7 +10,7 @@ import { NotebookExtensionDescription } from 'vs/workbench/api/common/extHost.pr
import { Event } from 'vs/base/common/event';
import {
INotebookTextModel, INotebookRendererInfo, INotebookKernelInfo, INotebookKernelInfoDto,
- IEditor, ICellEditOperation, NotebookCellOutputsSplice, IOrderedMimeType, IProcessedOutput, INotebookKernelProvider, INotebookKernelInfo2
+ IEditor, ICellEditOperation, NotebookCellOutputsSplice, INotebookKernelProvider, INotebookKernelInfo2
} from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
import { CancellationToken } from 'vs/base/common/cancellation';
@@ -52,11 +52,8 @@ export interface INotebookService {
onDidChangeNotebookActiveKernel: Event<{ uri: URI, providerHandle: number | undefined, kernelId: string | undefined }>;
registerNotebookController(viewType: string, extensionData: NotebookExtensionDescription, controller: IMainNotebookController): void;
unregisterNotebookProvider(viewType: string): void;
- registerNotebookRenderer(id: string, renderer: INotebookRendererInfo): void;
- unregisterNotebookRenderer(id: string): void;
- transformEditsOutputs(textModel: NotebookTextModel, edits: ICellEditOperation[]): Promise;
- transformSpliceOutputs(textModel: NotebookTextModel, splices: NotebookCellOutputsSplice[]): Promise;
- transformSingleOutput(textModel: NotebookTextModel, output: IProcessedOutput, rendererId: string, mimeType: string): Promise;
+ transformEditsOutputs(textModel: NotebookTextModel, edits: ICellEditOperation[]): void;
+ transformSpliceOutputs(textModel: NotebookTextModel, splices: NotebookCellOutputsSplice[]): void;
registerNotebookKernel(kernel: INotebookKernelInfo): void;
unregisterNotebookKernel(id: string): void;
registerNotebookKernelProvider(provider: INotebookKernelProvider): IDisposable;
diff --git a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts
index 463c36e60c31f..98d72f689d329 100644
--- a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts
+++ b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts
@@ -18,7 +18,7 @@ import { NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/v
import { CellViewModel, IModelDecorationsChangeAccessor, NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
-import { CellKind, CellUri, INotebookEditorModel, IProcessedOutput, NotebookCellMetadata, INotebookKernelInfo } from 'vs/workbench/contrib/notebook/common/notebookCommon';
+import { CellKind, CellUri, INotebookEditorModel, IProcessedOutput, NotebookCellMetadata, INotebookKernelInfo, IInsetRenderOutput } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { Webview } from 'vs/workbench/contrib/webview/browser/webview';
import { ICompositeCodeEditor, IEditor } from 'vs/editor/common/editorCommon';
import { NotImplementedError } from 'vs/base/common/errors';
@@ -259,7 +259,7 @@ export class TestNotebookEditor implements INotebookEditor {
// throw new Error('Method not implemented.');
return;
}
- createInset(cell: CellViewModel, output: IProcessedOutput, shadowContent: string, offset: number): Promise {
+ createInset(cell: CellViewModel, output: IInsetRenderOutput, offset: number): Promise {
return Promise.resolve();
}
removeInset(output: IProcessedOutput): void {