diff --git a/src/vs/base/browser/ui/list/listView.ts b/src/vs/base/browser/ui/list/listView.ts index 416d27d34e6..002d6cca5ed 100644 --- a/src/vs/base/browser/ui/list/listView.ts +++ b/src/vs/base/browser/ui/list/listView.ts @@ -679,7 +679,7 @@ export class ListView implements ISpliceable, IDisposable { item.dragStartDisposable.dispose(); const renderer = this.renderers.get(item.templateId); - if (renderer && renderer.disposeElement) { + if (renderer && renderer.disposeElement && item.row) { renderer.disposeElement(item.element, index, item.row!.templateData, item.size); } diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index c9e4ef822d4..9e42f1ac08b 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -1421,13 +1421,24 @@ declare module 'vscode' { //#region Peng: Notebook + export enum CellKind { + Markdown = 1, + Code = 2 + } + + export enum CellOutputKind { + Text = 1, + Error = 2, + Rich = 3 + } + export interface CellStreamOutput { - output_type: 'stream'; + outputKind: CellOutputKind.Text; text: string; } export interface CellErrorOutput { - output_type: 'error'; + outputKind: CellOutputKind.Error; /** * Exception Name */ @@ -1443,16 +1454,14 @@ declare module 'vscode' { } export interface CellDisplayOutput { - // todo@peng - // eslint-disable-next-line vscode-dts-literal-or-types - output_type: 'display_data' | 'execute_result'; + outputKind: CellOutputKind.Rich; /** * { mime_type: value } * * Example: * ```json * { - * "output_type": "execute_result", + * "outputKind": vscode.CellOutputKind.Rich, * "data": { * "text/html": [ * "

Hello

" @@ -1471,9 +1480,7 @@ declare module 'vscode' { export interface NotebookCell { handle: number; language: string; - // todo@peng - // eslint-disable-next-line vscode-dts-literal-or-types - cell_type: 'markdown' | 'code'; + cellKind: CellKind; outputs: CellOutput[]; getContent(): string; } @@ -1493,16 +1500,13 @@ declare module 'vscode' { /** * Create a notebook cell. The cell is not inserted into current document when created. Extensions should insert the cell into the document by [TextDocument.cells](#TextDocument.cells) */ - // todo@peng - // eslint-disable-next-line vscode-dts-literal-or-types - createCell(content: string, language: string, type: 'markdown' | 'code', outputs: CellOutput[]): NotebookCell; + createCell(content: string, language: string, type: CellKind, outputs: CellOutput[]): NotebookCell; } export interface NotebookProvider { resolveNotebook(editor: NotebookEditor): Promise; executeCell(document: NotebookDocument, cell: NotebookCell | undefined): Promise; save(document: NotebookDocument): Promise; - latexRenderer?(value: string): Promise; } export interface NotebookOutputSelector { diff --git a/src/vs/workbench/api/browser/mainThreadNotebook.ts b/src/vs/workbench/api/browser/mainThreadNotebook.ts index 5b88cfc49e4..b8ff0879afc 100644 --- a/src/vs/workbench/api/browser/mainThreadNotebook.ts +++ b/src/vs/workbench/api/browser/mainThreadNotebook.ts @@ -9,7 +9,7 @@ import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { URI, UriComponents } from 'vs/base/common/uri'; import { INotebookService, IMainNotebookController } from 'vs/workbench/contrib/notebook/browser/notebookService'; import { Emitter, Event } from 'vs/base/common/event'; -import { ICell, IOutput, INotebook, INotebookMimeTypeSelector, NOTEBOOK_DISPLAY_ORDER, NotebookCellsSplice, NotebookCellOutputsSplice, generateCellPath } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { ICell, IOutput, INotebook, INotebookMimeTypeSelector, NOTEBOOK_DISPLAY_ORDER, NotebookCellsSplice, NotebookCellOutputsSplice, generateCellPath, CellKind } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { PieceTreeTextBufferFactory, PieceTreeTextBufferBuilder } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder'; @@ -46,14 +46,14 @@ export class MainThreadCell implements ICell { public handle: number, public source: string[], public language: string, - public cell_type: 'markdown' | 'code', + public cellKind: CellKind, outputs: IOutput[] ) { this._outputs = outputs; this.uri = URI.from({ scheme: 'vscode-notebook', authority: parent.viewType, - path: generateCellPath(cell_type, handle), + path: generateCellPath(cellKind, handle), query: parent.uri.toString() }); } @@ -131,10 +131,10 @@ export class MainThreadNotebookDocument extends Disposable implements INotebook this.activeCell = this._mapping.get(handle); } - async createRawCell(viewType: string, uri: URI, index: number, language: string, type: 'markdown' | 'code'): Promise { + async createRawCell(viewType: string, uri: URI, index: number, language: string, type: CellKind): Promise { let cell = await this._proxy.$createEmptyCell(viewType, uri, index, language, type); if (cell) { - let mainCell = new MainThreadCell(this, cell.handle, cell.source, cell.language, cell.cell_type, cell.outputs); + let mainCell = new MainThreadCell(this, cell.handle, cell.source, cell.language, cell.cellKind, cell.outputs); this._mapping.set(cell.handle, mainCell); this.cells.splice(index, 0, mainCell); @@ -178,7 +178,7 @@ export class MainThreadNotebookDocument extends Disposable implements INotebook splices.reverse().forEach(splice => { let cellDtos = splice[2]; let newCells = cellDtos.map(cell => { - let mainCell = new MainThreadCell(this, cell.handle, cell.source, cell.language, cell.cell_type, cell.outputs || []); + let mainCell = new MainThreadCell(this, cell.handle, cell.source, cell.language, cell.cellKind, cell.outputs || []); this._mapping.set(cell.handle, mainCell); let dirtyStateListener = mainCell.onDidChangeDirtyState((cellState) => { this.isDirty = this.isDirty || cellState; @@ -365,7 +365,7 @@ export class MainThreadNotebookController implements IMainNotebookController { mainthreadNotebook?.updateActiveCell(cellHandle); } - async createRawCell(uri: URI, index: number, language: string, type: 'markdown' | 'code'): Promise { + async createRawCell(uri: URI, index: number, language: string, type: CellKind): Promise { let mainthreadNotebook = this._mapping.get(URI.from(uri).toString()); return mainthreadNotebook?.createRawCell(this._viewType, uri, index, language, type); } diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 8929e1c1aed..67e71e8b7b9 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -1014,7 +1014,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I WebviewContentState: extHostTypes.WebviewContentState, UIKind: UIKind, ColorThemeKind: extHostTypes.ColorThemeKind, - TimelineItem: extHostTypes.TimelineItem + TimelineItem: extHostTypes.TimelineItem, + CellKind: extHostTypes.CellKind, + CellOutputKind: extHostTypes.CellOutputKind }; }; } diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 270199559a7..ab3a1023096 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -635,11 +635,22 @@ export interface ExtHostWebviewsShape { $backup(resource: UriComponents, viewType: string, cancellation: CancellationToken): Promise; } +export enum CellKind { + Markdown = 1, + Code = 2 +} + +export enum CellOutputKind { + Text = 1, + Error = 2, + Rich = 3 +} + export interface ICellDto { handle: number; source: string[]; language: string; - cell_type: 'markdown' | 'code'; + cellKind: CellKind; outputs: IOutput[]; } @@ -1494,7 +1505,7 @@ export interface ExtHostCommentsShape { export interface ExtHostNotebookShape { $resolveNotebook(viewType: string, uri: UriComponents): Promise; $executeNotebook(viewType: string, uri: UriComponents, cellHandle: number | undefined): Promise; - $createEmptyCell(viewType: string, uri: UriComponents, index: number, language: string, type: 'markdown' | 'code'): Promise; + $createEmptyCell(viewType: string, uri: UriComponents, index: number, language: string, type: CellKind): Promise; $deleteCell(viewType: string, uri: UriComponents, index: number): Promise; $saveNotebook(viewType: string, uri: UriComponents): Promise; $updateActiveEditor(viewType: string, uri: UriComponents): Promise; diff --git a/src/vs/workbench/api/common/extHostNotebook.ts b/src/vs/workbench/api/common/extHostNotebook.ts index 1f2aa3b1081..fbc3b3a4af4 100644 --- a/src/vs/workbench/api/common/extHostNotebook.ts +++ b/src/vs/workbench/api/common/extHostNotebook.ts @@ -5,7 +5,7 @@ import * as vscode from 'vscode'; import * as glob from 'vs/base/common/glob'; -import { ExtHostNotebookShape, IMainContext, MainThreadNotebookShape, MainContext, ICellDto, NotebookCellsSplice, NotebookCellOutputsSplice } from 'vs/workbench/api/common/extHost.protocol'; +import { ExtHostNotebookShape, IMainContext, MainThreadNotebookShape, MainContext, ICellDto, NotebookCellsSplice, NotebookCellOutputsSplice, CellKind, CellOutputKind } from 'vs/workbench/api/common/extHost.protocol'; import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; import { Disposable as VSCodeDisposable } from './extHostTypes'; import { URI, UriComponents } from 'vs/base/common/uri'; @@ -13,7 +13,7 @@ import { DisposableStore } from 'vs/base/common/lifecycle'; import { readonly } from 'vs/base/common/errors'; import { Emitter, Event } from 'vs/base/common/event'; import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors'; -import { INotebookDisplayOrder, parseCellUri, parseCellHandle, ITransformedDisplayOutputDto, IOrderedMimeType, IStreamOutput, IErrorOutput, mimeTypeSupportedByCore } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { INotebookDisplayOrder, parseCellUri, parseCellHandle, ITransformedDisplayOutputDto, IOrderedMimeType, IStreamOutput, IErrorOutput, mimeTypeSupportedByCore, IOutput } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { ISplice } from 'vs/base/common/sequence'; interface ExtHostOutputDisplayOrder { @@ -96,7 +96,7 @@ export class ExtHostCell implements vscode.NotebookCell { constructor( private _content: string, - public cell_type: 'markdown' | 'code', + public cellKind: CellKind, public language: string, outputs: any[] ) { @@ -108,7 +108,7 @@ export class ExtHostCell implements vscode.NotebookCell { return this._outputs; } - set outputs(newOutputs: any[]) { + set outputs(newOutputs: vscode.CellOutput[]) { let diffs = diff(this._outputs || [], newOutputs || [], (a) => { return this._outputMapping.has(a); }); @@ -237,10 +237,10 @@ export class ExtHostNotebookDocument implements vscode.NotebookDocument, vscode. let inserts = diff.toInsert; let cellDtos = inserts.map(cell => { - let outputs = cell.outputs; - if (outputs && outputs.length) { - outputs = outputs.map(output => { - if (output.output_type === 'display_data' || output.output_type === 'execute_result') { + let outputs: IOutput[] = []; + if (cell.outputs.length) { + outputs = cell.outputs.map(output => { + if (output.outputKind === CellOutputKind.Rich) { const ret = this.transformMimeTypes(cell, output); if (ret.orderedMimeTypes[ret.pickedMimeTypeIndex].isResolved) { @@ -248,7 +248,7 @@ export class ExtHostNotebookDocument implements vscode.NotebookDocument, vscode. } return ret; } else { - return output; + return output as IStreamOutput | IErrorOutput; } }); } @@ -257,7 +257,7 @@ export class ExtHostNotebookDocument implements vscode.NotebookDocument, vscode. handle: cell.handle, source: cell.source, language: cell.language, - cell_type: cell.cell_type, + cellKind: cell.cellKind, outputs: outputs, isDirty: false }; @@ -280,7 +280,7 @@ export class ExtHostNotebookDocument implements vscode.NotebookDocument, vscode. let outputs = diff.toInsert; let transformedOutputs = outputs.map(output => { - if (output.output_type === 'display_data' || output.output_type === 'execute_result') { + if (output.outputKind === CellOutputKind.Rich) { const ret = this.transformMimeTypes(cell, output); if (ret.orderedMimeTypes[ret.pickedMimeTypeIndex].isResolved) { @@ -373,7 +373,7 @@ export class ExtHostNotebookDocument implements vscode.NotebookDocument, vscode. }); return { - output_type: output.output_type, + outputKind: output.outputKind, data: output.data, orderedMimeTypes: orderMimeTypes, pickedMimeTypeIndex: 0 @@ -381,7 +381,7 @@ export class ExtHostNotebookDocument implements vscode.NotebookDocument, vscode. } findRichestMimeType(output: vscode.CellOutput) { - if (output.output_type === 'display_data' || output.output_type === 'execute_result') { + if (output.outputKind === CellOutputKind.Rich) { let mimeTypes = Object.keys(output.data); const sorted = mimeTypes.sort((a, b) => { @@ -517,7 +517,7 @@ export class ExtHostNotebookEditor implements vscode.NotebookEditor, vscode.Disp this._disposableStore.dispose(); } - createCell(content: string, language: string, type: 'markdown' | 'code', outputs: vscode.CellOutput[]): vscode.NotebookCell { + createCell(content: string, language: string, type: CellKind, outputs: vscode.CellOutput[]): vscode.NotebookCell { let cell = new ExtHostCell(content, type, language, outputs); return cell; } @@ -556,14 +556,6 @@ export class ExtHostNotebookOutputRenderer { let html = this.renderer.render(document, cell, output, mimeType); return html; - // return { - // output_type: 'display_data', - // data: { - // 'text/html': [ - // html - // ] - // } - // }; } } @@ -689,7 +681,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN return provider.provider.executeCell(document!, cell); } - async $createEmptyCell(viewType: string, uri: URI, index: number, language: string, type: 'markdown' | 'code'): Promise { + async $createEmptyCell(viewType: string, uri: URI, index: number, language: string, type: CellKind): Promise { let provider = this._notebookProviders.get(viewType); if (provider) { @@ -725,7 +717,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN handle: rawCell.handle, source: rawCell.source, language: rawCell.language, - cell_type: rawCell.cell_type, + cellKind: rawCell.cellKind, outputs: rawCell.outputs }; } diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index e7810d7b6a3..090404db342 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -2555,6 +2555,21 @@ export enum ColorThemeKind { //#endregion Theming +//#region Notebook + +export enum CellKind { + Markdown = 1, + Code = 2 +} + +export enum CellOutputKind { + Text = 1, + Error = 2, + Rich = 3 +} + +//#endregion + //#region Timeline @es5ClassCompat diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index eccb3200ec0..dc61a50edb4 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -9,14 +9,14 @@ import { BareFontInfo } from 'vs/editor/common/config/fontInfo'; import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/renderers/cellViewModel'; import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/output/outputRenderer'; -import { IOutput } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { IOutput, CellKind } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; export const KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED = new RawContextKey('notebookFindWidgetFocused', false); export interface INotebookEditor { viewType: string | undefined; - insertEmptyNotebookCell(cell: CellViewModel, type: 'markdown' | 'code', direction: 'above' | 'below'): Promise; + insertEmptyNotebookCell(cell: CellViewModel, type: CellKind, direction: 'above' | 'below'): Promise; deleteNotebookCell(cell: CellViewModel): void; editNotebookCell(cell: CellViewModel): void; saveNotebookCell(cell: CellViewModel): void; diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts index ccf95891b4b..154b333c82f 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts @@ -28,7 +28,7 @@ import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/output/out import { BackLayerWebView } from 'vs/workbench/contrib/notebook/browser/renderers/backLayerWebView'; import { CodeCellRenderer, MarkdownCellRenderer, NotebookCellListDelegate } from 'vs/workbench/contrib/notebook/browser/renderers/cellRenderer'; import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/renderers/cellViewModel'; -import { CELL_MARGIN, NotebookCellsSplice, IOutput, parseCellUri } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CELL_MARGIN, NotebookCellsSplice, IOutput, parseCellUri, CellKind } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { IWebviewService } from 'vs/workbench/contrib/webview/browser/webview'; import { getExtraColor } from 'vs/workbench/contrib/welcome/walkThrough/common/walkThroughUtils'; import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; @@ -345,7 +345,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor, Noteb } })); - this.list?.splice(0, this.list?.length); + this.list?.splice(0, this.list?.length || 0); this.list?.splice(0, 0, this.notebookViewModel!.viewCells); this.list?.layout(); } @@ -441,7 +441,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor, Noteb }); } - async insertEmptyNotebookCell(cell: CellViewModel, type: 'code' | 'markdown', direction: 'above' | 'below'): Promise { + async insertEmptyNotebookCell(cell: CellViewModel, type: CellKind, direction: 'above' | 'below'): Promise { const newLanguages = this.notebookViewModel!.languages; const language = newLanguages && newLanguages.length ? newLanguages[0] : 'markdown'; const index = this.notebookViewModel!.getViewCellIndex(cell); @@ -453,7 +453,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor, Noteb this.list?.splice(insertIndex, 0, [newCell]); this.list?.setFocus([insertIndex]); - if (type === 'markdown') { + if (type === CellKind.Markdown) { newCell.isEditing = true; } diff --git a/src/vs/workbench/contrib/notebook/browser/notebookRegistry.ts b/src/vs/workbench/contrib/notebook/browser/notebookRegistry.ts index a7bd33f6e32..9b3ca0ce5d2 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookRegistry.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookRegistry.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IOutputTransformContribution } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { IOutputTransformContribution, CellOutputKind } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { BrandedService, IConstructorSignature1 } from 'vs/platform/instantiation/common/instantiation'; import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; @@ -11,7 +11,7 @@ export type IOutputTransformCtor = IConstructorSignature1(id: string, types: string[], ctor: { new(editor: INotebookEditor, ...services: Services): IOutputTransformContribution }): void { - NotebookRegistryImpl.INSTANCE.registerOutputTransform(id, types, ctor); +export function registerOutputTransform(id: string, kind: CellOutputKind, ctor: { new(editor: INotebookEditor, ...services: Services): IOutputTransformContribution }): void { + NotebookRegistryImpl.INSTANCE.registerOutputTransform(id, kind, ctor); } class NotebookRegistryImpl { @@ -35,8 +35,8 @@ class NotebookRegistryImpl { this.outputTransforms = []; } - registerOutputTransform(id: string, types: string[], ctor: { new(editor: INotebookEditor, ...services: Services): IOutputTransformContribution }): void { - this.outputTransforms.push({ id: id, types: types, ctor: ctor as IOutputTransformCtor }); + registerOutputTransform(id: string, kind: CellOutputKind, ctor: { new(editor: INotebookEditor, ...services: Services): IOutputTransformContribution }): void { + this.outputTransforms.push({ id: id, kind: kind, ctor: ctor as IOutputTransformCtor }); } getNotebookOutputTransform(): IOutputTransformDescription[] { diff --git a/src/vs/workbench/contrib/notebook/browser/notebookService.ts b/src/vs/workbench/contrib/notebook/browser/notebookService.ts index 7e9d0422182..150139be8ad 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookService.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookService.ts @@ -10,7 +10,7 @@ import { notebookProviderExtensionPoint, notebookRendererExtensionPoint } from ' import { NotebookProviderInfo } 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 { INotebook, ICell, INotebookMimeTypeSelector, INotebookRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { INotebook, ICell, INotebookMimeTypeSelector, INotebookRendererInfo, CellKind } 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'; @@ -24,7 +24,7 @@ export interface IMainNotebookController { resolveNotebook(viewType: string, uri: URI): Promise; executeNotebook(viewType: string, uri: URI): Promise; updateNotebookActiveCell(uri: URI, cellHandle: number): void; - createRawCell(uri: URI, index: number, language: string, type: 'markdown' | 'code'): Promise; + createRawCell(uri: URI, index: number, language: string, type: CellKind): Promise; deleteCell(uri: URI, index: number): Promise executeNotebookActiveCell(uri: URI): void; destoryNotebookDocument(notebook: INotebook): Promise; @@ -45,7 +45,7 @@ export interface INotebookService { getContributedNotebookProviders(resource: URI): readonly NotebookProviderInfo[]; getNotebookProviderResourceRoots(): URI[]; updateNotebookActiveCell(viewType: string, resource: URI, cellHandle: number): void; - createNotebookCell(viewType: string, resource: URI, index: number, language: string, type: 'markdown' | 'code'): Promise; + createNotebookCell(viewType: string, resource: URI, index: number, language: string, type: CellKind): Promise; deleteNotebookCell(viewType: string, resource: URI, index: number): Promise; destoryNotebookDocument(viewType: string, notebook: INotebook): void; updateActiveNotebookDocument(viewType: string, resource: URI): void; @@ -244,7 +244,7 @@ export class NotebookService extends Disposable implements INotebookService { } } - async createNotebookCell(viewType: string, resource: URI, index: number, language: string, type: 'markdown' | 'code'): Promise { + async createNotebookCell(viewType: string, resource: URI, index: number, language: string, type: CellKind): Promise { let provider = this._notebookProviders.get(viewType); if (provider) { diff --git a/src/vs/workbench/contrib/notebook/browser/output/outputRenderer.ts b/src/vs/workbench/contrib/notebook/browser/output/outputRenderer.ts index 4da7d769ed7..b17d580af28 100644 --- a/src/vs/workbench/contrib/notebook/browser/output/outputRenderer.ts +++ b/src/vs/workbench/contrib/notebook/browser/output/outputRenderer.ts @@ -11,7 +11,7 @@ import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookB export class OutputRenderer { protected readonly _contributions: { [key: string]: IOutputTransformContribution; }; - protected readonly _mimeTypeMapping: { [key: string]: IOutputTransformContribution; }; + protected readonly _mimeTypeMapping: { [key: number]: IOutputTransformContribution; }; constructor( notebookEditor: INotebookEditor, @@ -26,9 +26,7 @@ export class OutputRenderer { try { const contribution = this.instantiationService.createInstance(desc.ctor, notebookEditor); this._contributions[desc.id] = contribution; - desc.types.forEach(mimeType => { - this._mimeTypeMapping[mimeType] = contribution; - }); + this._mimeTypeMapping[desc.kind] = contribution; } catch (err) { onUnexpectedError(err); } @@ -38,7 +36,7 @@ export class OutputRenderer { renderNoop(output: IOutput, container: HTMLElement): IRenderOutput { const contentNode = document.createElement('p'); - contentNode.innerText = `No renderer could be found for output. It has the following output type: ${output.output_type}`; + contentNode.innerText = `No renderer could be found for output. It has the following output type: ${output.outputKind}`; container.appendChild(contentNode); return { hasDynamicHeight: false @@ -46,7 +44,7 @@ export class OutputRenderer { } render(output: IOutput, container: HTMLElement, preferredMimeType: string | undefined): IRenderOutput { - let transform = this._mimeTypeMapping[output.output_type]; + let transform = this._mimeTypeMapping[output.outputKind]; if (transform) { return transform.render(output, container, preferredMimeType); diff --git a/src/vs/workbench/contrib/notebook/browser/output/transforms/errorTransform.ts b/src/vs/workbench/contrib/notebook/browser/output/transforms/errorTransform.ts index 9320dc659c5..f929414c655 100644 --- a/src/vs/workbench/contrib/notebook/browser/output/transforms/errorTransform.ts +++ b/src/vs/workbench/contrib/notebook/browser/output/transforms/errorTransform.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IOutputTransformContribution, IRenderOutput } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { IOutputTransformContribution, IRenderOutput, CellOutputKind } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { registerOutputTransform } from 'vs/workbench/contrib/notebook/browser/notebookRegistry'; import * as DOM from 'vs/base/browser/dom'; import { RGBA, Color } from 'vs/base/common/color'; @@ -36,7 +36,7 @@ class ErrorTransform implements IOutputTransformContribution { } } -registerOutputTransform('notebook.output.error', ['error'], ErrorTransform); +registerOutputTransform('notebook.output.error', CellOutputKind.Error, ErrorTransform); /** * @param text The content to stylize. diff --git a/src/vs/workbench/contrib/notebook/browser/output/transforms/richTransform.ts b/src/vs/workbench/contrib/notebook/browser/output/transforms/richTransform.ts index 01ddb43f8d8..1b2c163aa59 100644 --- a/src/vs/workbench/contrib/notebook/browser/output/transforms/richTransform.ts +++ b/src/vs/workbench/contrib/notebook/browser/output/transforms/richTransform.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IOutputTransformContribution, IRenderOutput } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { IOutputTransformContribution, IRenderOutput, CellOutputKind } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { registerOutputTransform } from 'vs/workbench/contrib/notebook/browser/notebookRegistry'; import * as DOM from 'vs/base/browser/dom'; import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; @@ -221,7 +221,7 @@ class RichRenderer implements IOutputTransformContribution { } } -registerOutputTransform('notebook.output.rich', ['display_data', 'execute_result'], RichRenderer); +registerOutputTransform('notebook.output.rich', CellOutputKind.Rich, RichRenderer); export function getOutputSimpleEditorOptions(): IEditorOptions { diff --git a/src/vs/workbench/contrib/notebook/browser/output/transforms/streamTransform.ts b/src/vs/workbench/contrib/notebook/browser/output/transforms/streamTransform.ts index 9e5ee10d379..813bed700e9 100644 --- a/src/vs/workbench/contrib/notebook/browser/output/transforms/streamTransform.ts +++ b/src/vs/workbench/contrib/notebook/browser/output/transforms/streamTransform.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IOutputTransformContribution, IRenderOutput } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { IOutputTransformContribution, IRenderOutput, CellOutputKind } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { registerOutputTransform } from 'vs/workbench/contrib/notebook/browser/notebookRegistry'; import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; @@ -27,4 +27,4 @@ class StreamRenderer implements IOutputTransformContribution { } } -registerOutputTransform('notebook.output.stream', ['stream'], StreamRenderer); +registerOutputTransform('notebook.output.stream', CellOutputKind.Text, StreamRenderer); diff --git a/src/vs/workbench/contrib/notebook/browser/renderers/cellRenderer.ts b/src/vs/workbench/contrib/notebook/browser/renderers/cellRenderer.ts index 034533c5784..960b776c953 100644 --- a/src/vs/workbench/contrib/notebook/browser/renderers/cellRenderer.ts +++ b/src/vs/workbench/contrib/notebook/browser/renderers/cellRenderer.ts @@ -21,7 +21,7 @@ import { CodeCell } from 'vs/workbench/contrib/notebook/browser/renderers/codeCe import { StatefullMarkdownCell } from 'vs/workbench/contrib/notebook/browser/renderers/markdownCell'; import { CellViewModel } from './cellViewModel'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; -import { EDITOR_TOP_PADDING, EDITOR_BOTTOM_PADDING } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { EDITOR_TOP_PADDING, EDITOR_BOTTOM_PADDING, CellKind } from 'vs/workbench/contrib/notebook/common/notebookCommon'; export class NotebookCellListDelegate implements IListVirtualDelegate { private _lineHeight: number; @@ -41,7 +41,7 @@ export class NotebookCellListDelegate implements IListVirtualDelegate { - await this.notebookEditor.insertEmptyNotebookCell(element, 'code', 'above'); + await this.notebookEditor.insertEmptyNotebookCell(element, CellKind.Code, 'above'); } ); actions.push(insertAbove); @@ -100,7 +100,7 @@ class AbstractCellRenderer { undefined, true, async () => { - await this.notebookEditor.insertEmptyNotebookCell(element, 'code', 'below'); + await this.notebookEditor.insertEmptyNotebookCell(element, CellKind.Code, 'below'); } ); actions.push(insertBelow); @@ -111,7 +111,7 @@ class AbstractCellRenderer { undefined, true, async () => { - await this.notebookEditor.insertEmptyNotebookCell(element, 'markdown', 'above'); + await this.notebookEditor.insertEmptyNotebookCell(element, CellKind.Markdown, 'above'); } ); actions.push(insertMarkdownAbove); @@ -122,12 +122,12 @@ class AbstractCellRenderer { undefined, true, async () => { - await this.notebookEditor.insertEmptyNotebookCell(element, 'markdown', 'below'); + await this.notebookEditor.insertEmptyNotebookCell(element, CellKind.Markdown, 'below'); } ); actions.push(insertMarkdownBelow); - if (element.cellType === 'markdown') { + if (element.cellKind === CellKind.Markdown) { const editAction = new Action( 'workbench.notebook.editCell', 'Edit Cell', diff --git a/src/vs/workbench/contrib/notebook/browser/renderers/cellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/renderers/cellViewModel.ts index 9a7b1f187da..6a5208f0bf7 100644 --- a/src/vs/workbench/contrib/notebook/browser/renderers/cellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/renderers/cellViewModel.ts @@ -14,7 +14,7 @@ import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer' import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { CellFindMatch } from 'vs/workbench/contrib/notebook/browser/notebookFindWidget'; import { MarkdownRenderer } from 'vs/workbench/contrib/notebook/browser/renderers/mdRenderer'; -import { EDITOR_BOTTOM_PADDING, EDITOR_TOP_PADDING, ICell, IOutput, NotebookCellOutputsSplice } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { EDITOR_BOTTOM_PADDING, EDITOR_TOP_PADDING, ICell, IOutput, NotebookCellOutputsSplice, CellKind } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { SearchParams } from 'vs/editor/common/model/textModelSearch'; export class CellViewModel extends Disposable { @@ -31,8 +31,8 @@ export class CellViewModel extends Disposable { protected _outputsTop: PrefixSumComputer | null = null; - get cellType() { - return this.cell.cell_type; + get cellKind() { + return this.cell.cellKind; } get lineCount() { return this.cell.source.length; @@ -151,7 +151,7 @@ export class CellViewModel extends Disposable { return false; } - if (this.cellType === 'code') { + if (this.cellKind === CellKind.Code) { if (this.outputs && this.outputs.length > 0) { // if it contains output, it will be marked as dynamic height // thus when it's being rendered, the list view will `probeHeight` @@ -167,7 +167,7 @@ export class CellViewModel extends Disposable { } getHeight(lineHeight: number) { - if (this.cellType === 'markdown') { + if (this.cellKind === CellKind.Markdown) { return 100; } else { @@ -193,7 +193,7 @@ export class CellViewModel extends Disposable { } getHTML(): HTMLElement | null { - if (this.cellType === 'markdown') { + if (this.cellKind === CellKind.Markdown) { if (this._html) { return this._html; } diff --git a/src/vs/workbench/contrib/notebook/browser/renderers/codeCell.ts b/src/vs/workbench/contrib/notebook/browser/renderers/codeCell.ts index a8f101890f3..219c367ef67 100644 --- a/src/vs/workbench/contrib/notebook/browser/renderers/codeCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/renderers/codeCell.ts @@ -8,7 +8,7 @@ import * as DOM from 'vs/base/browser/dom'; import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/renderers/cellViewModel'; import { getResizesObserver } from 'vs/workbench/contrib/notebook/browser/renderers/sizeObserver'; -import { CELL_MARGIN, IOutput, EDITOR_TOP_PADDING, EDITOR_BOTTOM_PADDING, ITransformedDisplayOutputDto, IRenderOutput } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CELL_MARGIN, IOutput, EDITOR_TOP_PADDING, EDITOR_BOTTOM_PADDING, ITransformedDisplayOutputDto, IRenderOutput, CellOutputKind } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { CellRenderTemplate, INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { raceCancellation } from 'vs/base/common/async'; import { CancellationTokenSource } from 'vs/base/common/cancellation'; @@ -211,7 +211,7 @@ export class CodeCell extends Disposable { let outputItemDiv = document.createElement('div'); let result: IRenderOutput | undefined = undefined; - if (currOutput.output_type === 'display_data' || currOutput.output_type === 'execute_result') { + if (currOutput.outputKind === CellOutputKind.Rich) { let transformedDisplayOutput = currOutput as ITransformedDisplayOutputDto; if (transformedDisplayOutput.orderedMimeTypes.length > 1) { @@ -229,7 +229,7 @@ export class CodeCell extends Disposable { if (pickedMimeTypeRenderer.isResolved) { // html - result = this.notebookEditor.getOutputRenderer().render({ output_type: 'display_data', data: { 'text/html': pickedMimeTypeRenderer.output! } } as any, outputItemDiv, 'text/html'); + result = this.notebookEditor.getOutputRenderer().render({ outputKind: CellOutputKind.Rich, data: { 'text/html': pickedMimeTypeRenderer.output! } } as any, outputItemDiv, 'text/html'); } else { result = this.notebookEditor.getOutputRenderer().render(currOutput, outputItemDiv, pickedMimeTypeRenderer.mimeType); } diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index 39e5dd6efe3..c640bb7ef16 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -10,6 +10,17 @@ import { IRelativePattern } from 'vs/base/common/glob'; import { PieceTreeTextBufferFactory } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; +export enum CellKind { + Markdown = 1, + Code = 2 +} + +export enum CellOutputKind { + Text = 1, + Error = 2, + Rich = 3 +} + export const NOTEBOOK_DISPLAY_ORDER = [ 'application/json', 'application/javascript', @@ -43,12 +54,12 @@ export interface INotebookSelectors { } export interface IStreamOutput { - output_type: 'stream'; + outputKind: CellOutputKind.Text; text: string; } export interface IErrorOutput { - output_type: 'error'; + outputKind: CellOutputKind.Error; /** * Exception Name */ @@ -64,7 +75,7 @@ export interface IErrorOutput { } export interface IDisplayOutput { - output_type: 'display_data' | 'execute_result'; + outputKind: CellOutputKind.Rich; /** * { mime_type: value } */ @@ -85,7 +96,7 @@ export interface IOrderedMimeType { } export interface ITransformedDisplayOutputDto { - output_type: 'display_data' | 'execute_result'; + outputKind: CellOutputKind.Rich; data: { [key: string]: any; } orderedMimeTypes: IOrderedMimeType[]; @@ -93,7 +104,7 @@ export interface ITransformedDisplayOutputDto { } export interface IGenericOutput { - output_type: string; + outputKind: CellOutputKind; pickedMimeType?: string; pickedRenderer?: number; transformedOutput?: { [key: string]: IDisplayOutput }; @@ -106,7 +117,7 @@ export interface ICell { handle: number; source: string[]; language: string; - cell_type: 'markdown' | 'code'; + cellKind: CellKind; outputs: IOutput[]; onDidChangeOutputs?: Event; isDirty: boolean; @@ -179,8 +190,8 @@ export function parseCellUri(resource: URI): { viewType: string, notebook: URI } return { viewType, notebook }; } -export function generateCellPath(cell_type: string, cellHandle: number): string { - return `/cell_${cellHandle}${cell_type === 'markdown' ? '.md' : ''}`; +export function generateCellPath(cellKind: CellKind, cellHandle: number): string { + return `/cell_${cellHandle}${cellKind === CellKind.Markdown ? '.md' : ''}`; } export function parseCellHandle(path: string): number | undefined { diff --git a/src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts b/src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts index f5e3efe30ab..a35c7730714 100644 --- a/src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts +++ b/src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts @@ -11,7 +11,7 @@ import { PieceTreeTextBufferFactory } from 'vs/editor/common/model/pieceTreeText import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; import { NotebookEditorModel } from 'vs/workbench/contrib/notebook/browser/notebookEditorInput'; import { NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/notebookViewModel'; -import { generateCellPath, ICell, INotebook, IOutput, NotebookCellOutputsSplice, NotebookCellsSplice } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { generateCellPath, ICell, INotebook, IOutput, NotebookCellOutputsSplice, NotebookCellsSplice, CellKind } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/renderers/cellViewModel'; class MockCell implements ICell { @@ -38,14 +38,14 @@ class MockCell implements ICell { public handle: number, public source: string[], public language: string, - public cell_type: 'markdown' | 'code', + public cellKind: CellKind, outputs: IOutput[] ) { this._outputs = outputs; this.uri = URI.from({ scheme: 'vscode-notebook', authority: viewType, - path: generateCellPath(cell_type, handle), + path: generateCellPath(cellKind, handle), query: '' }); } @@ -86,12 +86,12 @@ class MockNotebook extends Disposable implements INotebook { suite('NotebookViewModel', () => { const instantiationService = new TestInstantiationService(); - const createCellViewModel = (viewType: string, notebookHandle: number, cellhandle: number, source: string[], language: string, cell_type: 'markdown' | 'code', outputs: IOutput[]) => { - const mockCell = new MockCell(viewType, cellhandle, source, language, cell_type, outputs); + const createCellViewModel = (viewType: string, notebookHandle: number, cellhandle: number, source: string[], language: string, cellKind: CellKind, outputs: IOutput[]) => { + const mockCell = new MockCell(viewType, cellhandle, source, language, cellKind, outputs); return instantiationService.createInstance(CellViewModel, viewType, notebookHandle, mockCell, false); }; - const withNotebookDocument = (cells: [string[], string, 'markdown' | 'code', IOutput[]][], callback: (viewModel: NotebookViewModel) => void) => { + const withNotebookDocument = (cells: [string[], string, CellKind, IOutput[]][], callback: (viewModel: NotebookViewModel) => void) => { const viewType = 'notebook'; const notebook = new MockNotebook(0, viewType, URI.parse('test')); notebook.cells = cells.map((cell, index) => { @@ -117,11 +117,11 @@ suite('NotebookViewModel', () => { test('insert/delete', function () { withNotebookDocument( [ - [['var a = 1;'], 'javascript', 'code', []], - [['var b = 2;'], 'javascript', 'code', []] + [['var a = 1;'], 'javascript', CellKind.Code, []], + [['var b = 2;'], 'javascript', CellKind.Code, []] ], (viewModel) => { - const cell = createCellViewModel(viewModel.viewType, viewModel.handle, 0, ['var c = 3;'], 'javascript', 'code', []); + const cell = createCellViewModel(viewModel.viewType, viewModel.handle, 0, ['var c = 3;'], 'javascript', CellKind.Code, []); viewModel.insertCell(1, cell); assert.equal(viewModel.viewCells.length, 3); assert.equal(viewModel.notebookDocument.cells.length, 3); @@ -138,22 +138,22 @@ suite('NotebookViewModel', () => { test('index', function () { withNotebookDocument( [ - [['var a = 1;'], 'javascript', 'code', []], - [['var b = 2;'], 'javascript', 'code', []] + [['var a = 1;'], 'javascript', CellKind.Code, []], + [['var b = 2;'], 'javascript', CellKind.Code, []] ], (viewModel) => { const firstViewCell = viewModel.viewCells[0]; const lastViewCell = viewModel.viewCells[viewModel.viewCells.length - 1]; const insertIndex = viewModel.getViewCellIndex(firstViewCell) + 1; - const cell = createCellViewModel(viewModel.viewType, viewModel.handle, 3, ['var c = 3;'], 'javascript', 'code', []); + const cell = createCellViewModel(viewModel.viewType, viewModel.handle, 3, ['var c = 3;'], 'javascript', CellKind.Code, []); viewModel.insertCell(insertIndex, cell); const addedCellIndex = viewModel.getViewCellIndex(cell); viewModel.deleteCell(addedCellIndex); const secondInsertIndex = viewModel.getViewCellIndex(lastViewCell) + 1; - const cell2 = createCellViewModel(viewModel.viewType, viewModel.handle, 4, ['var d = 4;'], 'javascript', 'code', []); + const cell2 = createCellViewModel(viewModel.viewType, viewModel.handle, 4, ['var d = 4;'], 'javascript', CellKind.Code, []); viewModel.insertCell(secondInsertIndex, cell2); assert.equal(viewModel.viewCells.length, 3);