提交 1b3b4026 编写于 作者: R rebornix

trusted notebook metadata

上级 4d4f3660
......@@ -21,9 +21,9 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { IQuickInputService, IQuickPickItem, QuickPickInput } from 'vs/platform/quickinput/common/quickInput';
import { CATEGORIES } from 'vs/workbench/common/actions';
import { BaseCellRenderTemplate, CellEditState, CellFocusMode, EXPAND_CELL_CONTENT_COMMAND_ID, ICellViewModel, INotebookEditor, NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_EDITOR_FOCUSED, NOTEBOOK_CELL_HAS_OUTPUTS, NOTEBOOK_CELL_INPUT_COLLAPSED, NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_OUTPUT_COLLAPSED, NOTEBOOK_CELL_TYPE, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_RUNNABLE, NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_OUTPUT_FOCUSED } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { BaseCellRenderTemplate, CellEditState, CellFocusMode, EXECUTE_CELL_COMMAND_ID, EXPAND_CELL_CONTENT_COMMAND_ID, ICellViewModel, INotebookEditor, NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_EDITOR_FOCUSED, NOTEBOOK_CELL_HAS_OUTPUTS, NOTEBOOK_CELL_INPUT_COLLAPSED, NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_OUTPUT_COLLAPSED, NOTEBOOK_CELL_TYPE, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_RUNNABLE, NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_OUTPUT_FOCUSED } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
import { CellEditType, CellKind, ICellEditOperation, ICellRange, isDocumentExcludePattern, NotebookCellMetadata, NotebookCellRunState, NOTEBOOK_EDITOR_CURSOR_BEGIN_END, NOTEBOOK_EDITOR_CURSOR_BOUNDARY, TransientMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { CellEditType, CellKind, ICellEditOperation, ICellRange, isDocumentExcludePattern, NotebookCellMetadata, NotebookCellRunState, NotebookDocumentMetadata, NOTEBOOK_EDITOR_CURSOR_BEGIN_END, NOTEBOOK_EDITOR_CURSOR_BOUNDARY, TransientMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
......@@ -37,6 +37,7 @@ const NOTEBOOK_FOCUS_PREVIOUS_EDITOR = 'notebook.focusPreviousEditor';
const NOTEBOOK_FOCUS_NEXT_EDITOR = 'notebook.focusNextEditor';
const CLEAR_ALL_CELLS_OUTPUTS_COMMAND_ID = 'notebook.clearAllCellsOutputs';
const RENDER_ALL_MARKDOWN_CELLS = 'notebook.renderAllMarkdownCells';
const TRUST_NOTEBOOK = 'notebook.trust';
// Cell Commands
const INSERT_CODE_CELL_ABOVE_COMMAND_ID = 'notebook.cell.insertCodeCellAbove';
......@@ -64,7 +65,6 @@ const SPLIT_CELL_COMMAND_ID = 'notebook.cell.split';
const JOIN_CELL_ABOVE_COMMAND_ID = 'notebook.cell.joinAbove';
const JOIN_CELL_BELOW_COMMAND_ID = 'notebook.cell.joinBelow';
const EXECUTE_CELL_COMMAND_ID = 'notebook.cell.execute';
const CANCEL_CELL_COMMAND_ID = 'notebook.cell.cancelExecution';
const EXECUTE_CELL_SELECT_BELOW = 'notebook.cell.executeAndSelectBelow';
const EXECUTE_CELL_INSERT_BELOW = 'notebook.cell.executeAndInsertBelow';
......@@ -1824,6 +1824,34 @@ registerAction2(class extends ChangeNotebookCellMetadataAction {
}
});
abstract class ChangeNotebookMetadataAction extends NotebookCellAction {
async runWithContext(accessor: ServicesAccessor, context: INotebookCellActionContext): Promise<void> {
const textModel = context.notebookEditor.viewModel?.notebookDocument;
if (!textModel) {
return;
}
textModel.applyEdits(textModel.versionId, [{ editType: CellEditType.DocumentMetadata, metadata: { ...textModel.metadata, ...this.getMetadataDelta() } }], true, undefined, () => undefined, undefined);
}
abstract getMetadataDelta(): Partial<NotebookDocumentMetadata>;
}
registerAction2(class extends ChangeNotebookMetadataAction {
constructor() {
super({
id: TRUST_NOTEBOOK,
title: localize('notebook.trust', "Trust Notebook"),
});
}
getMetadataDelta(): Partial<NotebookDocumentMetadata> {
return { trusted: true };
}
});
registerAction2(class extends Action2 {
constructor() {
super({
......
......@@ -60,6 +60,7 @@ export const NOTEBOOK_CELL_OUTPUT_COLLAPSED = new RawContextKey<boolean>('notebo
// Shared commands
export const EXPAND_CELL_CONTENT_COMMAND_ID = 'notebook.cell.expandCellContent';
export const EXECUTE_CELL_COMMAND_ID = 'notebook.cell.execute';
// Kernels
......
......@@ -873,7 +873,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
private _updateForMetadata(): void {
const notebookMetadata = this.viewModel!.metadata;
this._editorEditable?.set(!!notebookMetadata?.editable);
this._editorRunnable?.set(!!notebookMetadata?.runnable);
this._editorRunnable?.set(this.viewModel!.runnable);
this._overflowContainer.classList.toggle('notebook-editor-editable', !!notebookMetadata?.editable);
this.getDomNode().classList.toggle('notebook-editor-editable', !!notebookMetadata?.editable);
......@@ -1621,7 +1621,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
}
async executeNotebook(): Promise<void> {
if (!this._notebookViewModel!.metadata.runnable) {
if (!this._notebookViewModel!.runnable) {
return;
}
......
......@@ -28,7 +28,7 @@ import { NotebookKernelProviderAssociationRegistry, NotebookViewTypesExtensionRe
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, CellKind, CellOutputKind, DisplayOrderKey, IDisplayOutput, INotebookDecorationRenderOptions, INotebookKernelInfo2, INotebookKernelProvider, INotebookRendererInfo, INotebookTextModel, IOrderedMimeType, ITransformedDisplayOutputDto, mimeTypeSupportedByCore, notebookDocumentFilterMatch, NotebookEditorPriority, NOTEBOOK_DISPLAY_ORDER, RENDERER_NOT_AVAILABLE, sortMimeTypes } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, BUILTIN_RENDERER_ID, CellKind, CellOutputKind, DisplayOrderKey, IDisplayOutput, INotebookDecorationRenderOptions, INotebookKernelInfo2, INotebookKernelProvider, INotebookRendererInfo, INotebookTextModel, IOrderedMimeType, ITransformedDisplayOutputDto, mimeTypeIsAlwaysSecure, mimeTypeSupportedByCore, notebookDocumentFilterMatch, NotebookEditorPriority, NOTEBOOK_DISPLAY_ORDER, RENDERER_NOT_AVAILABLE, 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';
......@@ -732,10 +732,10 @@ export class NotebookService extends Disposable implements INotebookService, ICu
getMimeTypeInfo(textModel: NotebookTextModel, output: ITransformedDisplayOutputDto): readonly IOrderedMimeType[] {
// TODO@rebornix no string[] casting
return this._getOrderedMimeTypes(output, textModel.metadata.displayOrder as string[] ?? []);
return this._getOrderedMimeTypes(textModel, output, textModel.metadata.displayOrder as string[] ?? []);
}
private _getOrderedMimeTypes(output: IDisplayOutput, documentDisplayOrder: string[]): IOrderedMimeType[] {
private _getOrderedMimeTypes(textModel: NotebookTextModel, output: IDisplayOutput, documentDisplayOrder: string[]): IOrderedMimeType[] {
const mimeTypes = Object.keys(output.data);
const coreDisplayOrder = this._displayOrder;
const sorted = sortMimeTypes(mimeTypes, coreDisplayOrder?.userOrder || [], documentDisplayOrder, coreDisplayOrder?.defaultOrder || []);
......@@ -751,31 +751,36 @@ export class NotebookService extends Disposable implements INotebookService, ICu
orderMimeTypes.push({
mimeType: mimeType,
rendererId: handler.id,
isTrusted: textModel.metadata.trusted
});
for (let i = 1; i < handlers.length; i++) {
orderMimeTypes.push({
mimeType: mimeType,
rendererId: handlers[i].id
rendererId: handlers[i].id,
isTrusted: textModel.metadata.trusted
});
}
if (mimeTypeSupportedByCore(mimeType)) {
orderMimeTypes.push({
mimeType: mimeType,
rendererId: BUILTIN_RENDERER_ID
rendererId: BUILTIN_RENDERER_ID,
isTrusted: mimeTypeIsAlwaysSecure(mimeType) || textModel.metadata.trusted
});
}
} else {
if (mimeTypeSupportedByCore(mimeType)) {
orderMimeTypes.push({
mimeType: mimeType,
rendererId: BUILTIN_RENDERER_ID
rendererId: BUILTIN_RENDERER_ID,
isTrusted: mimeTypeIsAlwaysSecure(mimeType) || textModel.metadata.trusted
});
} else {
orderMimeTypes.push({
mimeType: mimeType,
rendererId: RENDERER_NOT_AVAILABLE
rendererId: RENDERER_NOT_AVAILABLE,
isTrusted: textModel.metadata.trusted
});
}
}
......
......@@ -63,7 +63,8 @@ export class OutputElement extends Disposable {
const mimeTypes = this.notebookService.getMimeTypeInfo(this.notebookEditor.textModel!, this.output);
const pick = this.pickedMimeTypes.get(this.output) ?? Math.max(mimeTypes.findIndex(mimeType => mimeType.rendererId !== RENDERER_NOT_AVAILABLE), 0);
// there is at least one mimetype which is safe and can be rendered by the core
const pick = this.pickedMimeTypes.get(this.output) ?? Math.max(mimeTypes.findIndex(mimeType => mimeType.rendererId !== RENDERER_NOT_AVAILABLE && mimeType.isTrusted), 0);
if (mimeTypes.length > 1) {
outputItemDiv.style.position = 'relative';
......@@ -104,6 +105,8 @@ export class OutputElement extends Disposable {
} else {
result = this.notebookEditor.getOutputRenderer().render(this.output, innerContainer, pickedMimeTypeRenderer.mimeType, this.getNotebookUri(),);
}
this.pickedMimeTypes.set(this.output, pick);
} else {
// for text and error, there is no mimetype
const innerContainer = DOM.$('.output-inner-container');
......@@ -174,10 +177,10 @@ export class OutputElement extends Disposable {
async pickActiveMimeTypeRenderer(output: ITransformedDisplayOutputDto) {
const mimeTypes = this.notebookService.getMimeTypeInfo(this.notebookEditor.textModel!, output);
const currIndex = this.pickedMimeTypes.get(output) ?? 0;
const currIndex = this.pickedMimeTypes.get(output);
// const currIndex = output.pickedMimeTypeIndex;
const items = mimeTypes.map((mimeType, index): IMimeTypeRenderer => ({
const items = mimeTypes.filter(mimeType => mimeType.isTrusted).map((mimeType, index): IMimeTypeRenderer => ({
label: mimeType.mimeType,
id: mimeType.mimeType,
index: index,
......@@ -189,7 +192,9 @@ export class OutputElement extends Disposable {
const picker = this.quickInputService.createQuickPick();
picker.items = items;
picker.activeItems = items.filter(item => !!item.picked);
picker.placeholder = nls.localize('promptChooseMimeType.placeHolder', "Select output mimetype to render for current output");
picker.placeholder = items.length !== mimeTypes.length
? nls.localize('promptChooseMimeTypeInSecure.placeHolder', "Select mimetype to render for current output. Rich mimetypes are available only when the notebook is trusted")
: nls.localize('promptChooseMimeType.placeHolder', "Select mimetype to render for current output");
const pick = await new Promise<number | undefined>(resolve => {
picker.onDidAccept(() => {
......@@ -284,7 +289,7 @@ export class OutputContainer extends Disposable {
this.templateData.outputContainer!.style.display = 'block';
// there are outputs, we need to calcualte their sizes and trigger relayout
// @TODO@rebornix, if there is no resizable output, we should not check their height individually, which hurts the performance
const outputsToRender = this.viewCell.outputs.slice(0, Math.min(OUTPUT_COUNT_LIMIT, this.viewCell.outputs.length));
const outputsToRender = this._calcuateOutputsToRender();
for (let index = 0; index < outputsToRender.length; index++) {
const currOutput = this.viewCell.outputs[index];
......@@ -356,6 +361,43 @@ export class OutputContainer extends Disposable {
});
}
private _calcuateOutputsToRender() {
const outputs = this.viewCell.outputs.slice(0, Math.min(OUTPUT_COUNT_LIMIT, this.viewCell.outputs.length));
if (!this.notebookEditor.viewModel!.metadata.trusted) {
// not trusted
const secureOutput = outputs.filter(output => {
switch (output.outputKind) {
case CellOutputKind.Text:
return true;
case CellOutputKind.Error:
return true;
case CellOutputKind.Rich:
{
const mimeTypes = [];
for (const property in output.data) {
mimeTypes.push(property);
}
if (mimeTypes.indexOf('text/plain') >= 0
|| mimeTypes.indexOf('text/markdown') >= 0
|| mimeTypes.indexOf('application/json') >= 0
|| mimeTypes.includes('image/png')) {
return true;
}
return false;
}
default:
return false;
}
});
return secureOutput;
}
return outputs;
}
private _updateOutputs(splices: NotebookCellOutputsSplice[]) {
if (!splices.length) {
return;
......@@ -393,7 +435,7 @@ export class OutputContainer extends Disposable {
});
let prevElement: HTMLElement | undefined = undefined;
const outputsToRender = this.viewCell.outputs.slice(0, Math.min(OUTPUT_COUNT_LIMIT, this.viewCell.outputs.length));
const outputsToRender = this._calcuateOutputsToRender();
outputsToRender.reverse().forEach(output => {
if (this.outputEntries.has(output)) {
......
......@@ -414,6 +414,9 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR
const betweenCellToolbar = disposables.add(this.createBetweenCellToolbar(bottomCellContainer, disposables, contextKeyService));
const statusBar = disposables.add(this.instantiationService.createInstance(CellEditorStatusBar, editorPart));
DOM.hide(statusBar.durationContainer);
DOM.hide(statusBar.cellRunStatusContainer);
const titleMenu = disposables.add(this.cellMenus.getCellTitleMenu(contextKeyService));
const templateData: MarkdownCellRenderTemplate = {
......
......@@ -23,6 +23,7 @@ import { INotificationService } from 'vs/platform/notification/common/notificati
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { ChangeCellLanguageAction, INotebookCellActionContext } from 'vs/workbench/contrib/notebook/browser/contrib/coreActions';
import { ICellViewModel, INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { BaseCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel';
import { INotebookCellStatusBarService } from 'vs/workbench/contrib/notebook/common/notebookCellStatusBarService';
import { CellKind, CellStatusbarAlignment, INotebookCellStatusBarEntry } from 'vs/workbench/contrib/notebook/common/notebookCommon';
......@@ -339,3 +340,18 @@ export function getResizesObserver(referenceDomElement: HTMLElement | null, dime
return new ElementSizeObserver(referenceDomElement, dimension, changeCallback);
}
}
export function getExecuteCellPlaceholder(viewCell: BaseCellViewModel) {
return {
alignment: CellStatusbarAlignment.LEFT,
priority: -1,
cellResource: viewCell.uri,
command: undefined,
// text: `${keybinding?.getLabel() || 'Ctrl + Enter'} to run`,
// tooltip: `${keybinding?.getLabel() || 'Ctrl + Enter'} to run`,
text: 'Ctrl + Enter to run',
tooltip: 'Ctrl + Enter to run',
visible: true,
opacity: '0.7'
};
}
......@@ -16,10 +16,9 @@ import { CellFocusMode, CodeCellRenderTemplate, INotebookEditor } from 'vs/workb
import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel';
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { ClickTargetType } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets';
import { ClickTargetType, getExecuteCellPlaceholder } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets';
import { OutputContainer } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellOutput';
import { INotebookCellStatusBarService } from 'vs/workbench/contrib/notebook/common/notebookCellStatusBarService';
import { CellStatusbarAlignment } from 'vs/workbench/contrib/notebook/common/notebookCommon';
export class CodeCell extends Disposable {
......@@ -35,7 +34,9 @@ export class CodeCell extends Disposable {
@INotebookCellStatusBarService readonly notebookCellStatusBarService: INotebookCellStatusBarService,
@IOpenerService readonly openerService: IOpenerService,
@ITextFileService readonly textFileService: ITextFileService,
@IModeService private readonly _modeService: IModeService
@IModeService private readonly _modeService: IModeService,
// @IKeybindingService private readonly _keybindingService: IKeybindingService,
) {
super();
......@@ -218,19 +219,14 @@ export class CodeCell extends Disposable {
updateForCollapseState();
const updatePlaceholder = () => {
if (this.notebookEditor.getActiveCell() === this.viewCell && viewCell.metadata.runState === undefined && viewCell.metadata.lastRunDuration === undefined) {
if (this.notebookEditor.getActiveCell() === this.viewCell
&& viewCell.metadata.runState === undefined
&& viewCell.metadata.lastRunDuration === undefined
) {
// active cell and no run status
if (this._activeCellRunPlaceholder === null) {
this._activeCellRunPlaceholder = this.notebookCellStatusBarService.addEntry({
alignment: CellStatusbarAlignment.LEFT,
priority: -1,
cellResource: viewCell.uri,
command: undefined,
text: 'Ctrl + Enter to run',
tooltip: 'Ctrl + Enter to run',
visible: true,
opacity: '0.7'
});
// const keybinding = this._keybindingService.lookupKeybinding(EXECUTE_CELL_COMMAND_ID);
this._activeCellRunPlaceholder = this.notebookCellStatusBarService.addEntry(getExecuteCellPlaceholder(this.viewCell));
}
return;
......@@ -247,6 +243,8 @@ export class CodeCell extends Disposable {
this._register(this.viewCell.model.onDidChangeMetadata(() => {
updatePlaceholder();
}));
updatePlaceholder();
}
private viewUpdate(): void {
......
......@@ -7,7 +7,7 @@ import * as DOM from 'vs/base/browser/dom';
import { raceCancellation } from 'vs/base/common/async';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { renderCodicons } from 'vs/base/browser/codicons';
import { Disposable, DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
import { Disposable, DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
......@@ -19,7 +19,8 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { getResizesObserver } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets';
import { getExecuteCellPlaceholder, getResizesObserver } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets';
import { INotebookCellStatusBarService } from 'vs/workbench/contrib/notebook/common/notebookCellStatusBarService';
export class StatefulMarkdownCell extends Disposable {
......@@ -29,6 +30,7 @@ export class StatefulMarkdownCell extends Disposable {
private localDisposables = new DisposableStore();
private foldingState: CellFoldingState;
private _activeCellRunPlaceholder: IDisposable | null = null;
constructor(
private readonly notebookEditor: INotebookEditor,
......@@ -37,6 +39,7 @@ export class StatefulMarkdownCell extends Disposable {
private editorOptions: IEditorOptions,
private readonly renderedEditors: Map<ICellViewModel, ICodeEditor | undefined>,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@INotebookCellStatusBarService readonly notebookCellStatusBarService: INotebookCellStatusBarService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
) {
super();
......@@ -129,6 +132,31 @@ export class StatefulMarkdownCell extends Disposable {
});
this.viewUpdate();
const updatePlaceholder = () => {
if (this.notebookEditor.getActiveCell() === this.viewCell) {
// active cell and no run status
if (this._activeCellRunPlaceholder === null) {
// const keybinding = this._keybindingService.lookupKeybinding(EXECUTE_CELL_COMMAND_ID);
this._activeCellRunPlaceholder = this.notebookCellStatusBarService.addEntry(getExecuteCellPlaceholder(this.viewCell));
}
return;
}
this._activeCellRunPlaceholder?.dispose();
this._activeCellRunPlaceholder = null;
};
this._register(this.notebookEditor.onDidChangeActiveCell(() => {
updatePlaceholder();
}));
this._register(this.viewCell.model.onDidChangeMetadata(() => {
updatePlaceholder();
}));
updatePlaceholder();
}
private viewUpdate(): void {
......
......@@ -453,8 +453,8 @@ export abstract class BaseCellViewModel extends Disposable {
const editable = this.metadata?.editable ??
documentMetadata.cellEditable;
const runnable = this.metadata?.runnable ??
documentMetadata.cellRunnable;
const runnable = (this.metadata?.runnable ??
documentMetadata.cellRunnable) && !!documentMetadata.trusted;
const hasExecutionOrder = this.metadata?.hasExecutionOrder ??
documentMetadata.cellHasExecutionOrder;
......
......@@ -180,6 +180,10 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD
return this._notebook.metadata;
}
get runnable() {
return !!this._notebook.metadata?.runnable && !!this._notebook.metadata?.trusted;
}
private readonly _onDidChangeViewCells = this._register(new Emitter<INotebookViewCellsUpdateEvent>());
get onDidChangeViewCells(): Event<INotebookViewCellsUpdateEvent> { return this._onDidChangeViewCells.event; }
......
......@@ -86,7 +86,7 @@ export interface NotebookDocumentMetadata {
displayOrder?: (string | glob.IRelativePattern)[];
custom?: { [key: string]: unknown };
runState?: NotebookRunState;
trusted?: boolean;
trusted: boolean;
}
export enum NotebookCellRunState {
......@@ -185,6 +185,7 @@ export enum MimeTypeRendererResolver {
export interface IOrderedMimeType {
mimeType: string;
rendererId: string;
isTrusted: boolean;
}
export interface ITransformedDisplayOutputDto extends IDisplayOutput {
......@@ -538,6 +539,19 @@ export namespace CellUri {
}
}
export function mimeTypeIsAlwaysSecure(mimeType: string) {
if ([
'application/json',
'text/markdown',
'image/png',
'text/plain'
].indexOf(mimeType) > -1) {
return true;
}
return false;
}
export function mimeTypeSupportedByCore(mimeType: string) {
if ([
'application/json',
......
......@@ -156,7 +156,7 @@ suite('NotebookViewModel', () => {
['var e = 5;', 'javascript', CellKind.Code, [], { editable: false, runnable: false }],
],
(editor, viewModel) => {
viewModel.notebookDocument.metadata = { editable: true, runnable: true, cellRunnable: true, cellEditable: true, cellHasExecutionOrder: true };
viewModel.notebookDocument.metadata = { editable: true, runnable: true, cellRunnable: true, cellEditable: true, cellHasExecutionOrder: true, trusted: true };
const defaults = { hasExecutionOrder: true };
......@@ -190,7 +190,7 @@ suite('NotebookViewModel', () => {
...defaults
});
viewModel.notebookDocument.metadata = { editable: true, runnable: true, cellRunnable: false, cellEditable: true, cellHasExecutionOrder: true };
viewModel.notebookDocument.metadata = { editable: true, runnable: true, cellRunnable: false, cellEditable: true, cellHasExecutionOrder: true, trusted: true };
assert.deepEqual(viewModel.viewCells[0].getEvaluatedMetadata(viewModel.metadata), <NotebookCellMetadata>{
editable: true,
......@@ -222,7 +222,7 @@ suite('NotebookViewModel', () => {
...defaults
});
viewModel.notebookDocument.metadata = { editable: true, runnable: true, cellRunnable: false, cellEditable: false, cellHasExecutionOrder: true };
viewModel.notebookDocument.metadata = { editable: true, runnable: true, cellRunnable: false, cellEditable: false, cellHasExecutionOrder: true, trusted: true };
assert.deepEqual(viewModel.viewCells[0].getEvaluatedMetadata(viewModel.metadata), <NotebookCellMetadata>{
editable: false,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册