Merge the notebookMarkupRenderer contribution point into the renderers contribition point

For #123540
This commit is contained in:
Matt Bierner 2021-05-12 13:27:58 -07:00
parent 09bd849661
commit 11a8c4b4bc
No known key found for this signature in database
GPG Key ID: 099C331567E11888
9 changed files with 47 additions and 162 deletions

View File

@ -40,7 +40,7 @@
}
},
"contributes": {
"notebookMarkupRenderers": [
"notebookOutputRenderer": [
{
"id": "markdownItRenderer",
"displayName": "Markdown it renderer",

View File

@ -21,18 +21,28 @@
}
},
"contributes": {
"notebookMarkupRenderers": [
"notebookOutputRenderer": [
{
"id": "markdownItRenderer-katex",
"displayName": "Markdown it katex renderer",
"entrypoint": "./notebook-out/katex.js",
"dependsOn": "markdownItRenderer"
"mimeTypes": [
"text/markdown"
],
"dependencies": [
"markdownItRenderer"
]
},
{
"id": "markdownItRenderer-emoji",
"displayName": "Markdown it emoji renderer",
"entrypoint": "./notebook-out/emoji.js",
"dependsOn": "markdownItRenderer"
"mimeTypes": [
"text/markdown"
],
"dependencies": [
"markdownItRenderer"
]
}
]
},

View File

@ -42,22 +42,6 @@ export interface INotebookRendererContribution {
readonly [NotebookRendererContribution.optionalDependencies]: readonly string[];
}
enum NotebookMarkupRendererContribution {
id = 'id',
displayName = 'displayName',
entrypoint = 'entrypoint',
dependsOn = 'dependsOn',
mimeTypes = 'mimeTypes',
}
export interface INotebookMarkupRendererContribution {
readonly [NotebookMarkupRendererContribution.id]?: string;
readonly [NotebookMarkupRendererContribution.displayName]: string;
readonly [NotebookMarkupRendererContribution.entrypoint]: string;
readonly [NotebookMarkupRendererContribution.dependsOn]: string | undefined;
readonly [NotebookMarkupRendererContribution.mimeTypes]: string[] | undefined;
}
const notebookProviderContribution: IJSONSchema = {
description: nls.localize('contributes.notebook.provider', 'Contributes notebook document provider.'),
type: 'array',
@ -164,42 +148,6 @@ const notebookRendererContribution: IJSONSchema = {
}
}
};
const notebookMarkupRendererContribution: IJSONSchema = {
description: nls.localize('contributes.notebook.markdownRenderer', 'Contributes a renderer for markdown cells in notebooks.'),
type: 'array',
defaultSnippets: [{ body: [{ id: '', displayName: '', entrypoint: '' }] }],
items: {
type: 'object',
required: [
NotebookMarkupRendererContribution.id,
NotebookMarkupRendererContribution.displayName,
NotebookMarkupRendererContribution.entrypoint,
],
properties: {
[NotebookMarkupRendererContribution.id]: {
type: 'string',
description: nls.localize('contributes.notebook.markdownRenderer.id', 'Unique identifier of the notebook markdown renderer.'),
},
[NotebookMarkupRendererContribution.displayName]: {
type: 'string',
description: nls.localize('contributes.notebook.markdownRenderer.displayName', 'Human readable name of the notebook markdown renderer.'),
},
[NotebookMarkupRendererContribution.entrypoint]: {
type: 'string',
description: nls.localize('contributes.notebook.markdownRenderer.entrypoint', 'File to load in the webview to render the extension.'),
},
[NotebookMarkupRendererContribution.mimeTypes]: {
type: 'array',
items: { type: 'string' },
description: nls.localize('contributes.notebook.markdownRenderer.mimeTypes', 'The mime type that the renderer handles.'),
},
[NotebookMarkupRendererContribution.dependsOn]: {
type: 'string',
description: nls.localize('contributes.notebook.markdownRenderer.dependsOn', 'If specified, this renderer augments another renderer instead of providing full rendering.'),
},
}
}
};
export const notebooksExtensionPoint2 = ExtensionsRegistry.registerExtensionPoint<INotebookEditorContribution[]>(
{
@ -218,9 +166,3 @@ export const notebookRendererExtensionPoint = ExtensionsRegistry.registerExtensi
extensionPoint: 'notebookOutputRenderer',
jsonSchema: notebookRendererContribution
});
export const notebookMarkupRendererExtensionPoint = ExtensionsRegistry.registerExtensionPoint<INotebookMarkupRendererContribution[]>(
{
extensionPoint: 'notebookMarkupRenderers',
jsonSchema: notebookMarkupRendererContribution
});

View File

@ -27,14 +27,13 @@ import { NotebookExtensionDescription } from 'vs/workbench/api/common/extHost.pr
import { IEditorInput } from 'vs/workbench/common/editor';
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
import { Memento } from 'vs/workbench/common/memento';
import { INotebookEditorContribution, notebookMarkupRendererExtensionPoint, notebooksExtensionPoint, notebookRendererExtensionPoint, notebooksExtensionPoint2 } from 'vs/workbench/contrib/notebook/browser/extensionPoint';
import { INotebookEditorContribution, notebooksExtensionPoint, notebookRendererExtensionPoint, notebooksExtensionPoint2 } from 'vs/workbench/contrib/notebook/browser/extensionPoint';
import { NotebookEditorOptions, updateEditorTopPadding } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { NotebookDiffEditorInput } from 'vs/workbench/contrib/notebook/browser/notebookDiffEditorInput';
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, CellUri, DisplayOrderKey, INotebookExclusiveDocumentFilter, INotebookMarkupRendererInfo, INotebookContributionData, INotebookRendererInfo, INotebookTextModel, IOrderedMimeType, IOutputDto, mimeTypeIsAlwaysSecure, mimeTypeSupportedByCore, NotebookDataDto, NotebookEditorPriority, NotebookRendererMatch, NotebookTextDiffEditorPreview, RENDERER_NOT_AVAILABLE, sortMimeTypes, TransientOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, BUILTIN_RENDERER_ID, CellUri, DisplayOrderKey, INotebookExclusiveDocumentFilter, INotebookContributionData, INotebookRendererInfo, INotebookTextModel, IOrderedMimeType, IOutputDto, mimeTypeIsAlwaysSecure, mimeTypeSupportedByCore, NotebookDataDto, NotebookEditorPriority, NotebookRendererMatch, NotebookTextDiffEditorPreview, RENDERER_NOT_AVAILABLE, sortMimeTypes, TransientOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { NotebookEditorInput } from 'vs/workbench/contrib/notebook/common/notebookEditorInput';
import { NotebookMarkupRendererInfo as NotebookMarkupRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookMarkdownRenderer';
import { NotebookOutputRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookOutputRenderer';
import { NotebookEditorDescriptor, NotebookProviderInfo } from 'vs/workbench/contrib/notebook/common/notebookProvider';
import { ComplexNotebookProviderInfo, INotebookContentProvider, INotebookSerializer, INotebookService, SimpleNotebookProviderInfo } from 'vs/workbench/contrib/notebook/common/notebookService';
@ -250,6 +249,10 @@ export class NotebookOutputRendererInfoStore {
return this.contributedRenderers.get(rendererId);
}
getAll(): NotebookOutputRendererInfo[] {
return Array.from(this.contributedRenderers.values());
}
add(info: NotebookOutputRendererInfo): void {
if (this.contributedRenderers.has(info.id)) {
return;
@ -302,7 +305,6 @@ export class NotebookService extends Disposable implements INotebookService {
private readonly _notebookProviders = new Map<string, ComplexNotebookProviderInfo | SimpleNotebookProviderInfo>();
private readonly _notebookProviderInfoStore: NotebookProviderInfoStore;
private readonly _notebookRenderersInfoStore = this._instantiationService.createInstance(NotebookOutputRendererInfoStore);
private readonly _markdownRenderersInfos = new Set<INotebookMarkupRendererInfo>();
private readonly _models = new ResourceMap<ModelData>();
private readonly _onWillAddNotebookDocument = this._register(new Emitter<NotebookTextModel>());
@ -369,38 +371,6 @@ export class NotebookService extends Disposable implements INotebookService {
}
}
});
notebookMarkupRendererExtensionPoint.setHandler((renderers) => {
this._markdownRenderersInfos.clear();
for (const extension of renderers) {
if (!extension.description.enableProposedApi && !extension.description.isBuiltin) {
// Only allow proposed extensions to use this extension point
return;
}
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;
}
const id = notebookContribution.id;
if (!id) {
console.error(`Notebook renderer from ${extension.description.identifier.value} is missing an 'id'`);
continue;
}
this._markdownRenderersInfos.add(new NotebookMarkupRendererInfo({
id,
extension: extension.description,
entrypoint: notebookContribution.entrypoint,
displayName: notebookContribution.displayName,
mimeTypes: notebookContribution.mimeTypes,
dependsOn: notebookContribution.dependsOn,
}));
}
}
});
const updateOrder = () => {
const userOrder = this._configurationService.getValue<string[]>(DisplayOrderKey);
@ -552,8 +522,8 @@ export class NotebookService extends Disposable implements INotebookService {
this._notebookRenderersInfoStore.setPreferred(mimeType, rendererId);
}
getMarkupRendererInfo(): INotebookMarkupRendererInfo[] {
return Array.from(this._markdownRenderersInfos);
getRenderers(): INotebookRendererInfo[] {
return this._notebookRenderersInfoStore.getAll();
}
// --- notebook documents: create, destory, retrieve, enumerate

View File

@ -29,7 +29,7 @@ import { CellEditState, ICellOutputViewModel, ICommonCellInfo, ICommonNotebookEd
import { preloadsScriptStr, WebviewPreloadRenderer } from 'vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads';
import { transformWebviewThemeVars } from 'vs/workbench/contrib/notebook/browser/view/renderers/webviewThemeMapping';
import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel';
import { INotebookKernel, INotebookRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { INotebookKernel, INotebookRendererInfo, NotebookRendererMatch } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
import { IWebviewService, WebviewContentPurpose, WebviewElement } from 'vs/workbench/contrib/webview/browser/webview';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
@ -713,22 +713,21 @@ export class BackLayerWebView<T extends ICommonCellInfo> extends Disposable {
}
private getMarkdownRenderer(): WebviewPreloadRenderer[] {
const allRenderers = this.notebookService.getMarkupRendererInfo();
const markdownMimeType = 'text/markdown';
const allRenderers = this.notebookService.getRenderers()
.filter(renderer => renderer.matchesWithoutKernel(markdownMimeType) !== NotebookRendererMatch.Never);
const topLevelMarkdownRenderers = allRenderers
.filter(renderer => !renderer.dependsOn)
.filter(renderer => renderer.mimeTypes?.includes(markdownMimeType));
.filter(renderer => renderer.dependencies.length === 0);
const subRenderers = new Map<string, Array<{ entrypoint: string }>>();
for (const renderer of allRenderers) {
if (renderer.dependsOn) {
if (!subRenderers.has(renderer.dependsOn)) {
subRenderers.set(renderer.dependsOn, []);
for (const dep of renderer.dependencies) {
if (!subRenderers.has(dep)) {
subRenderers.set(dep, []);
}
const entryPoint = this.asWebviewUri(renderer.entrypoint, renderer.extensionLocation);
subRenderers.get(renderer.dependsOn)!.push({ entrypoint: entryPoint.toString(true) });
subRenderers.get(dep)!.push({ entrypoint: entryPoint.toString(true) });
}
}
@ -736,7 +735,7 @@ export class BackLayerWebView<T extends ICommonCellInfo> extends Disposable {
const src = this.asWebviewUri(renderer.entrypoint, renderer.extensionLocation);
return {
entrypoint: src.toString(),
mimeTypes: [markdownMimeType],
mimeTypes: renderer.mimeTypes,
dependencies: subRenderers.get(renderer.id) || [],
};
});
@ -1132,7 +1131,7 @@ var requirejs = (function() {
this.localResourceRootsCache = [
...this.notebookService.getNotebookProviderResourceRoots(),
...this.notebookService.getMarkupRendererInfo().map(x => dirname(x.entrypoint)),
...this.notebookService.getRenderers().map(x => dirname(x.entrypoint)),
...workspaceFolders,
rootPath,
];

View File

@ -134,19 +134,14 @@ export interface INotebookRendererInfo {
extensionLocation: URI;
extensionId: ExtensionIdentifier;
readonly mimeTypes: readonly string[];
readonly dependencies: readonly string[];
matchesWithoutKernel(mimeType: string): NotebookRendererMatch;
matches(mimeType: string, kernelProvides: ReadonlyArray<string>): NotebookRendererMatch;
}
export interface INotebookMarkupRendererInfo {
readonly id: string;
readonly entrypoint: URI;
readonly extensionLocation: URI;
readonly extensionId: ExtensionIdentifier;
readonly extensionIsBuiltin: boolean;
readonly dependsOn: string | undefined;
readonly mimeTypes: readonly string[] | undefined;
}
export interface NotebookCellOutputMetadata {
/**

View File

@ -1,39 +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 { joinPath } from 'vs/base/common/resources';
import { URI } from 'vs/base/common/uri';
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { INotebookMarkupRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookCommon';
export class NotebookMarkupRendererInfo implements INotebookMarkupRendererInfo {
readonly id: string;
readonly entrypoint: URI;
readonly displayName: string;
readonly extensionLocation: URI;
readonly extensionId: ExtensionIdentifier;
readonly extensionIsBuiltin: boolean;
readonly dependsOn: string | undefined;
readonly mimeTypes: readonly string[] | undefined;
constructor(descriptor: {
readonly id: string;
readonly displayName: string;
readonly entrypoint: string;
readonly extension: IExtensionDescription;
readonly mimeTypes: readonly string[] | undefined,
readonly dependsOn: string | undefined,
}) {
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.extensionIsBuiltin = descriptor.extension.isBuiltin;
this.dependsOn = descriptor.dependsOn;
this.mimeTypes = descriptor.mimeTypes;
}
}

View File

@ -19,6 +19,10 @@ class DependencyList {
this.defined = this.value.size > 0;
}
public values(): string[] {
return Array.from(this.value);
}
/** Gets whether any of the 'available' dependencies match the ones in this list */
public matches(available: ReadonlyArray<string>) {
// For now this is simple, but this may expand to support globs later
@ -39,7 +43,7 @@ export class NotebookOutputRendererInfo implements INotebookRendererInfo {
// todo: re-add preloads in pure renderer API
readonly preloads: ReadonlyArray<URI> = [];
private readonly mimeTypes: readonly string[];
readonly mimeTypes: readonly string[];
private readonly mimeTypeGlobs: glob.ParsedPattern[];
constructor(descriptor: {
@ -62,6 +66,10 @@ export class NotebookOutputRendererInfo implements INotebookRendererInfo {
this.optionalDependencies = new DependencyList(descriptor.optionalDependencies ?? Iterable.empty());
}
get dependencies(): string[] {
return this.hardDependencies.values();
}
matchesWithoutKernel(mimeType: string) {
if (!this.matchesMimeTypeOnly(mimeType)) {
return NotebookRendererMatch.Never;

View File

@ -8,7 +8,7 @@ import { URI } from 'vs/base/common/uri';
import { NotebookProviderInfo } from 'vs/workbench/contrib/notebook/common/notebookProvider';
import { NotebookExtensionDescription } from 'vs/workbench/api/common/extHost.protocol';
import { Event } from 'vs/base/common/event';
import { INotebookRendererInfo, NotebookDataDto, TransientOptions, IOrderedMimeType, IOutputDto, INotebookMarkupRendererInfo, INotebookContributionData } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { INotebookRendererInfo, NotebookDataDto, TransientOptions, IOrderedMimeType, IOutputDto, INotebookContributionData } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
import { CancellationToken } from 'vs/base/common/cancellation';
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
@ -73,7 +73,7 @@ export interface INotebookService {
getMimeTypeInfo(textModel: NotebookTextModel, kernelProvides: readonly string[] | undefined, output: IOutputDto): readonly IOrderedMimeType[];
getRendererInfo(id: string): INotebookRendererInfo | undefined;
getMarkupRendererInfo(): INotebookMarkupRendererInfo[];
getRenderers(): INotebookRendererInfo[];
/** Updates the preferred renderer for the given mimetype in the workspace. */
updateMimePreferredRenderer(mimeType: string, rendererId: string): void;