diff --git a/src/sql/workbench/contrib/notebook/browser/notebook.contribution.ts b/src/sql/workbench/contrib/notebook/browser/notebook.contribution.ts index 2e72ce68af..681ef6c5c6 100644 --- a/src/sql/workbench/contrib/notebook/browser/notebook.contribution.ts +++ b/src/sql/workbench/contrib/notebook/browser/notebook.contribution.ts @@ -61,6 +61,7 @@ import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileE import { IModeService } from 'vs/editor/common/services/modeService'; import { ILogService } from 'vs/platform/log/common/log'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; +import { useNewMarkdownRendererKey } from 'sql/workbench/contrib/notebook/common/notebookCommon'; Registry.as(EditorExtensions.EditorInputFactories) .registerEditorInputSerializer(FileNotebookInput.ID, FileNoteBookEditorInputSerializer); @@ -279,15 +280,7 @@ configurationRegistry.registerConfiguration({ 'type': 'boolean', 'default': true, 'description': localize('notebook.sqlStopOnError', "SQL kernel: stop Notebook execution when error occurs in a cell.") - } - } -}); - -configurationRegistry.registerConfiguration({ - 'id': 'notebook', - 'title': 'Notebook', - 'type': 'object', - 'properties': { + }, 'notebook.showAllKernels': { 'type': 'boolean', 'default': false, @@ -345,6 +338,11 @@ configurationRegistry.registerConfiguration({ 'type': 'boolean', 'default': false, 'description': localize('notebook.enableIncrementalGridRendering', "Enable incremental grid rendering for notebooks. This will improve the initial rendering time for large notebooks. There may be performance issues when interacting with the notebook while the rest of the grids are rendering.") + }, + [useNewMarkdownRendererKey]: { + 'type': 'boolean', + default: false, + 'description': localize('notebook.useNewMarkdownRenderer', "Whether to use the newer version of the markdown renderer for Notebooks. This may result in markdown being rendered differently than previous versions.") } } }); diff --git a/src/sql/workbench/contrib/notebook/browser/outputs/notebookMarkdown.ts b/src/sql/workbench/contrib/notebook/browser/outputs/notebookMarkdown.ts index d0174c1214..21abf5d894 100644 --- a/src/sql/workbench/contrib/notebook/browser/outputs/notebookMarkdown.ts +++ b/src/sql/workbench/contrib/notebook/browser/outputs/notebookMarkdown.ts @@ -8,19 +8,22 @@ import { nb } from 'azdata'; import { URI } from 'vs/base/common/uri'; import { IMarkdownString, removeMarkdownEscapes } from 'vs/base/common/htmlContent'; import { IMarkdownRenderResult } from 'vs/editor/browser/core/markdownRenderer'; -import * as marked from 'sql/base/common/marked/marked'; +import * as sqlMarked from 'sql/base/common/marked/marked'; +import * as vsMarked from 'vs/base/common/marked/marked'; import { defaultGenerator } from 'vs/base/common/idGenerator'; import { revive } from 'vs/base/common/marshalling'; import { ImageMimeTypes } from 'sql/workbench/services/notebook/common/contracts'; import { IMarkdownStringWithCellAttachments, MarkdownRenderOptionsWithCellAttachments } from 'sql/workbench/contrib/notebook/browser/cellViews/interfaces'; import { replaceInvalidLinkPath } from 'sql/workbench/contrib/notebook/common/utils'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { useNewMarkdownRendererKey } from 'sql/workbench/contrib/notebook/common/notebookCommon'; // Based off of HtmlContentRenderer export class NotebookMarkdownRenderer { private _notebookURI: URI; private _baseUrls: string[] = []; - constructor() { + constructor(@IConfigurationService private _configurationService: IConfigurationService) { } @@ -65,7 +68,8 @@ export class NotebookMarkdownRenderer { if (!this._baseUrls.some(x => x === notebookFolder)) { this._baseUrls.push(notebookFolder); } - const renderer = new marked.Renderer({ baseUrl: notebookFolder }); + const useNewRenderer = this._configurationService.getValue(useNewMarkdownRendererKey); + const renderer = useNewRenderer ? new vsMarked.Renderer({ baseUrl: notebookFolder }) : new sqlMarked.Renderer({ baseUrl: notebookFolder }); renderer.image = (href: string, title: string, text: string) => { const attachment = findAttachmentIfExists(href, options.cellAttachments); // Attachments are already properly formed, so do not need cleaning. Cleaning only takes into account relative/absolute @@ -178,13 +182,22 @@ export class NotebookMarkdownRenderer { }; } - const markedOptions: marked.MarkedOptions = { - sanitize: !markdown.isTrusted, - renderer, - baseUrl: notebookFolder - }; + if (useNewRenderer) { + const markedOptions: vsMarked.MarkedOptions = { + sanitize: !markdown.isTrusted, + renderer, + baseUrl: notebookFolder + }; + element.innerHTML = vsMarked.parse(markdown.value, markedOptions); + } else { + const markedOptions: sqlMarked.MarkedOptions = { + sanitize: !markdown.isTrusted, + renderer, + baseUrl: notebookFolder + }; + element.innerHTML = sqlMarked.parse(markdown.value, markedOptions); + } - element.innerHTML = marked.parse(markdown.value, markedOptions); signalInnerHTML!(); return element; diff --git a/src/sql/workbench/contrib/notebook/common/notebookCommon.ts b/src/sql/workbench/contrib/notebook/common/notebookCommon.ts new file mode 100644 index 0000000000..f2fab60d03 --- /dev/null +++ b/src/sql/workbench/contrib/notebook/common/notebookCommon.ts @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export const useNewMarkdownRendererKey = 'notebook.useNewMarkdownRenderer'; diff --git a/src/sql/workbench/contrib/notebook/test/browser/notebookMarkdown.test.ts b/src/sql/workbench/contrib/notebook/test/browser/notebookMarkdown.test.ts index ac00aae031..552b54494d 100644 --- a/src/sql/workbench/contrib/notebook/test/browser/notebookMarkdown.test.ts +++ b/src/sql/workbench/contrib/notebook/test/browser/notebookMarkdown.test.ts @@ -7,9 +7,10 @@ import * as assert from 'assert'; import * as marked from 'vs/base/common/marked/marked'; import { NotebookMarkdownRenderer } from '../../browser/outputs/notebookMarkdown'; import { URI } from 'vs/base/common/uri'; +import { TestConfigurationService } from 'sql/platform/connection/test/common/testConfigurationService'; suite('NotebookMarkdownRenderer', () => { - let notebookMarkdownRenderer = new NotebookMarkdownRenderer(); + let notebookMarkdownRenderer = new NotebookMarkdownRenderer(new TestConfigurationService({ user: { 'notebook': { 'useNewMarkdownRenderer': false } } })); test('image rendering conforms to default', () => { const markdown = { value: `![image](someimageurl 'caption')` }; const result: HTMLElement = notebookMarkdownRenderer.renderMarkdown(markdown); diff --git a/src/sql/workbench/contrib/notebook/test/electron-browser/notebookFindModel.test.ts b/src/sql/workbench/contrib/notebook/test/electron-browser/notebookFindModel.test.ts index 4046722951..a3c31d3a4c 100644 --- a/src/sql/workbench/contrib/notebook/test/electron-browser/notebookFindModel.test.ts +++ b/src/sql/workbench/contrib/notebook/test/electron-browser/notebookFindModel.test.ts @@ -31,7 +31,7 @@ import { NotebookRange } from 'sql/workbench/services/notebook/browser/notebookS import { NotebookMarkdownRenderer } from 'sql/workbench/contrib/notebook/browser/outputs/notebookMarkdown'; import { NullAdsTelemetryService } from 'sql/platform/telemetry/common/adsTelemetryService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; +import { TestConfigurationService } from 'sql/platform/connection/test/common/testConfigurationService'; let expectedNotebookContent: nb.INotebookContents = { cells: [{ @@ -74,7 +74,7 @@ suite('Notebook Find Model', function (): void { let defaultModelOptions: INotebookModelOptions; const logService = new NullLogService(); let model: NotebookModel; - let markdownRenderer: NotebookMarkdownRenderer = new NotebookMarkdownRenderer(); + let markdownRenderer: NotebookMarkdownRenderer = new NotebookMarkdownRenderer(new TestConfigurationService()); let configurationService: IConfigurationService; setup(async () => {