Skip to content

Commit 9073a3c

Browse files
committed
chore - consolidate markdown rendering more, reduce innerHTML usage, related #106395
1 parent f711344 commit 9073a3c

File tree

13 files changed

+69
-34
lines changed

13 files changed

+69
-34
lines changed

src/vs/base/browser/markdownRenderer.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,16 @@ export interface MarkedOptions extends marked.MarkedOptions {
2525
}
2626

2727
export interface MarkdownRenderOptions extends FormattedTextRenderOptions {
28-
codeBlockRenderer?: (modeId: string, value: string) => Promise<string>;
28+
codeBlockRenderer?: (modeId: string, value: string) => Promise<HTMLElement>;
2929
codeBlockRenderCallback?: () => void;
3030
baseUrl?: URI;
3131
}
3232

3333
/**
34-
* Create html nodes for the given content element.
34+
* Low-level way create a html element from a markdown string.
35+
*
36+
* **Note** that for most cases you should be using [`MarkdownRenderer`](./src/vs/editor/browser/core/markdownRenderer.ts)
37+
* which comes with support for pretty code block rendering and which uses the default way of handling links.
3538
*/
3639
export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRenderOptions = {}, markedOptions: MarkedOptions = {}): HTMLElement {
3740
const element = createElement(options);
@@ -158,12 +161,11 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende
158161
// but update the node with the real result later.
159162
const id = defaultGenerator.nextId();
160163
const promise = Promise.all([value, withInnerHTML]).then(values => {
161-
const strValue = values[0];
162-
const span = element.querySelector(`div[data-code="${id}"]`);
164+
const span = <HTMLDivElement>element.querySelector(`div[data-code="${id}"]`);
163165
if (span) {
164-
span.innerHTML = strValue;
166+
DOM.reset(span, values[0]);
165167
}
166-
}).catch(err => {
168+
}).catch(_err => {
167169
// ignore
168170
});
169171

src/vs/editor/contrib/markdown/markdownRenderer.ts renamed to src/vs/editor/browser/core/markdownRenderer.ts

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { tokenizeToString } from 'vs/editor/common/modes/textToHtmlTokenizer';
1212
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
1313
import { Emitter } from 'vs/base/common/event';
1414
import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
15-
import { TokenizationRegistry } from 'vs/editor/common/modes';
15+
import { ITokenizationSupport, TokenizationRegistry } from 'vs/editor/common/modes';
1616
import { EditorOption } from 'vs/editor/common/config/editorOptions';
1717
import { URI } from 'vs/base/common/uri';
1818

@@ -22,11 +22,22 @@ export interface IMarkdownRenderResult extends IDisposable {
2222

2323
export interface IMarkdownRendererOptions {
2424
editor?: ICodeEditor;
25-
baseUrl?: URI
25+
baseUrl?: URI;
26+
codeBlockFontFamily?: string;
2627
}
2728

29+
/**
30+
* Markdown renderer that can render codeblocks with the editor mechanics. This
31+
* renderer should always be preferred.
32+
*/
2833
export class MarkdownRenderer {
2934

35+
private static _ttpTokenizer = window.trustedTypes?.createPolicy('tokenizeToString', {
36+
createHTML(value: string, tokenizer: ITokenizationSupport | undefined) {
37+
return tokenizeToString(value, tokenizer);
38+
}
39+
});
40+
3041
private readonly _onDidRenderCodeBlock = new Emitter<void>();
3142
readonly onDidRenderCodeBlock = this._onDidRenderCodeBlock.event;
3243

@@ -47,7 +58,7 @@ export class MarkdownRenderer {
4758
if (!markdown) {
4859
element = document.createElement('span');
4960
} else {
50-
element = renderMarkdown(markdown, this._getOptions(disposeables), markedOptions);
61+
element = renderMarkdown(markdown, this._getRenderOptions(disposeables), markedOptions);
5162
}
5263

5364
return {
@@ -56,7 +67,7 @@ export class MarkdownRenderer {
5667
};
5768
}
5869

59-
protected _getOptions(disposeables: DisposableStore): MarkdownRenderOptions {
70+
protected _getRenderOptions(disposeables: DisposableStore): MarkdownRenderOptions {
6071
return {
6172
baseUrl: this._options.baseUrl,
6273
codeBlockRenderer: async (languageAlias, value) => {
@@ -74,16 +85,27 @@ export class MarkdownRenderer {
7485
}
7586
this._modeService.triggerMode(modeId);
7687
const tokenization = await TokenizationRegistry.getPromise(modeId) ?? undefined;
77-
const code = tokenizeToString(value, tokenization);
78-
return this._options.editor
79-
? `<span style="font-family: ${this._options.editor.getOption(EditorOption.fontInfo).fontFamily}">${code}</span>`
80-
: `<span>${code}</span>`;
88+
89+
const element = document.createElement('span');
90+
91+
element.innerHTML = MarkdownRenderer._ttpTokenizer
92+
? MarkdownRenderer._ttpTokenizer.createHTML(value, tokenization) as unknown as string
93+
: tokenizeToString(value, tokenization);
94+
95+
// use "good" font
96+
let fontFamily = this._options.codeBlockFontFamily;
97+
if (this._options.editor) {
98+
fontFamily = this._options.editor.getOption(EditorOption.fontInfo).fontFamily;
99+
}
100+
if (fontFamily) {
101+
element.style.fontFamily = fontFamily;
102+
}
103+
104+
return element;
81105
},
82106
codeBlockRenderCallback: () => this._onDidRenderCodeBlock.fire(),
83107
actionHandler: {
84-
callback: (content) => {
85-
this._openerService.open(content, { fromUserGesture: true }).catch(onUnexpectedError);
86-
},
108+
callback: (content) => this._openerService.open(content, { fromUserGesture: true }).catch(onUnexpectedError),
87109
disposeables
88110
}
89111
};

src/vs/editor/contrib/hover/modesContentHover.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import { ColorPickerWidget } from 'vs/editor/contrib/colorPicker/colorPickerWidg
2121
import { getHover } from 'vs/editor/contrib/hover/getHover';
2222
import { HoverOperation, HoverStartMode, IHoverComputer } from 'vs/editor/contrib/hover/hoverOperation';
2323
import { ContentHoverWidget } from 'vs/editor/contrib/hover/hoverWidgets';
24-
import { MarkdownRenderer } from 'vs/editor/contrib/markdown/markdownRenderer';
24+
import { MarkdownRenderer } from 'vs/editor/browser/core/markdownRenderer';
2525
import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
2626
import { coalesce, isNonEmptyArray, asArray } from 'vs/base/common/arrays';
2727
import { IMarker, IMarkerData, MarkerSeverity } from 'vs/platform/markers/common/markers';

src/vs/editor/contrib/hover/modesGlyphHover.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { DisposableStore } from 'vs/base/common/lifecycle';
99
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
1010
import { HoverOperation, HoverStartMode, IHoverComputer } from 'vs/editor/contrib/hover/hoverOperation';
1111
import { GlyphHoverWidget } from 'vs/editor/contrib/hover/hoverWidgets';
12-
import { MarkdownRenderer } from 'vs/editor/contrib/markdown/markdownRenderer';
12+
import { MarkdownRenderer } from 'vs/editor/browser/core/markdownRenderer';
1313
import { IModeService } from 'vs/editor/common/services/modeService';
1414
import { IOpenerService, NullOpenerService } from 'vs/platform/opener/common/opener';
1515
import { asArray } from 'vs/base/common/arrays';

src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { ContentWidgetPositionPreference, ICodeEditor, IContentWidget, IContentW
1414
import { ConfigurationChangedEvent, EditorOption } from 'vs/editor/common/config/editorOptions';
1515
import * as modes from 'vs/editor/common/modes';
1616
import { IModeService } from 'vs/editor/common/services/modeService';
17-
import { MarkdownRenderer } from 'vs/editor/contrib/markdown/markdownRenderer';
17+
import { MarkdownRenderer } from 'vs/editor/browser/core/markdownRenderer';
1818
import { Context } from 'vs/editor/contrib/parameterHints/provideSignatureHelp';
1919
import * as nls from 'vs/nls';
2020
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';

src/vs/editor/contrib/suggest/suggestWidget.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import { attachListStyler } from 'vs/platform/theme/common/styler';
2525
import { IThemeService, IColorTheme, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
2626
import { registerColor, editorWidgetBackground, listFocusBackground, activeContrastBorder, listHighlightForeground, editorForeground, editorWidgetBorder, focusBorder, textLinkForeground, textCodeBlockBackground } from 'vs/platform/theme/common/colorRegistry';
2727
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
28-
import { MarkdownRenderer } from 'vs/editor/contrib/markdown/markdownRenderer';
28+
import { MarkdownRenderer } from 'vs/editor/browser/core/markdownRenderer';
2929
import { IModeService } from 'vs/editor/common/services/modeService';
3030
import { IOpenerService } from 'vs/platform/opener/common/opener';
3131
import { TimeoutTimer, CancelablePromise, createCancelablePromise, disposableTimeout } from 'vs/base/common/async';

src/vs/editor/contrib/suggest/suggestWidgetDetails.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableEle
1010
import { EditorOption } from 'vs/editor/common/config/editorOptions';
1111
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
1212
import { CompletionItem } from './suggest';
13-
import { MarkdownRenderer } from 'vs/editor/contrib/markdown/markdownRenderer';
13+
import { MarkdownRenderer } from 'vs/editor/browser/core/markdownRenderer';
1414
import { MarkdownString } from 'vs/base/common/htmlContent';
1515
import { Codicon } from 'vs/base/common/codicons';
1616
import { Emitter, Event } from 'vs/base/common/event';

src/vs/workbench/contrib/comments/browser/commentNode.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { URI } from 'vs/base/common/uri';
1313
import { ITextModel } from 'vs/editor/common/model';
1414
import { IModelService } from 'vs/editor/common/services/modelService';
1515
import { IModeService } from 'vs/editor/common/services/modeService';
16-
import { MarkdownRenderer } from 'vs/editor/contrib/markdown/markdownRenderer';
16+
import { MarkdownRenderer } from 'vs/editor/browser/core/markdownRenderer';
1717
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
1818
import { IThemeService } from 'vs/platform/theme/common/themeService';
1919
import { ICommentService } from 'vs/workbench/contrib/comments/browser/commentService';

src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import { ITextModel } from 'vs/editor/common/model';
2222
import * as modes from 'vs/editor/common/modes';
2323
import { IModelService } from 'vs/editor/common/services/modelService';
2424
import { IModeService } from 'vs/editor/common/services/modeService';
25-
import { MarkdownRenderer } from 'vs/editor/contrib/markdown/markdownRenderer';
25+
import { MarkdownRenderer } from 'vs/editor/browser/core/markdownRenderer';
2626
import { peekViewBorder } from 'vs/editor/contrib/peekView/peekView';
2727
import { ZoneWidget } from 'vs/editor/contrib/zoneWidget/zoneWidget';
2828
import * as nls from 'vs/nls';

src/vs/workbench/contrib/notebook/browser/view/output/transforms/richTransform.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { IModelService } from 'vs/editor/common/services/modelService';
1414
import { IModeService } from 'vs/editor/common/services/modeService';
1515
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
1616
import { URI } from 'vs/base/common/uri';
17-
import { MarkdownRenderer } from 'vs/editor/contrib/markdown/markdownRenderer';
17+
import { MarkdownRenderer } from 'vs/editor/browser/core/markdownRenderer';
1818
import { IThemeService } from 'vs/platform/theme/common/themeService';
1919
import { handleANSIOutput } from 'vs/workbench/contrib/notebook/browser/view/output/transforms/errorTransform';
2020
import { dirname } from 'vs/base/common/resources';

0 commit comments

Comments
 (0)