Skip to content

Commit ab54105

Browse files
authored
Merge pull request microsoft#262594 from mjbvz/blushing-giraffe
More clean up to MarkdownRenderer
2 parents bc9eaa3 + 6bc5bd2 commit ab54105

File tree

9 files changed

+58
-76
lines changed

9 files changed

+58
-76
lines changed

src/vs/base/browser/markdownRenderer.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ import * as DOM from './dom.js';
2222
import * as domSanitize from './domSanitize.js';
2323
import { convertTagToPlaintext } from './domSanitize.js';
2424
import { DomEmitter } from './event.js';
25-
import { IKeyboardEvent, StandardKeyboardEvent } from './keyboardEvent.js';
26-
import { IMouseEvent, StandardMouseEvent } from './mouseEvent.js';
25+
import { StandardKeyboardEvent } from './keyboardEvent.js';
26+
import { StandardMouseEvent } from './mouseEvent.js';
2727
import { renderLabelWithIcons } from './ui/iconLabel/iconLabels.js';
2828

29-
export type MarkdownActionHandler = (content: string, event: IMouseEvent | IKeyboardEvent) => void;
29+
export type MarkdownActionHandler = (linkContent: string, mdStr: IMarkdownString) => void;
3030

3131
/**
3232
* Options for the rendering of markdown with {@link renderMarkdown}.
@@ -345,7 +345,7 @@ function preprocessMarkdownString(markdown: IMarkdownString) {
345345
return value;
346346
}
347347

348-
function activateLink(markdown: IMarkdownString, options: MarkdownRenderOptions, event: StandardMouseEvent | StandardKeyboardEvent): void {
348+
function activateLink(mdStr: IMarkdownString, options: MarkdownRenderOptions, event: StandardMouseEvent | StandardKeyboardEvent): void {
349349
const target = event.target.closest('a[data-href]');
350350
if (!DOM.isHTMLElement(target)) {
351351
return;
@@ -354,10 +354,10 @@ function activateLink(markdown: IMarkdownString, options: MarkdownRenderOptions,
354354
try {
355355
let href = target.dataset['href'];
356356
if (href) {
357-
if (markdown.baseUri) {
358-
href = resolveWithBaseUri(URI.from(markdown.baseUri), href);
357+
if (mdStr.baseUri) {
358+
href = resolveWithBaseUri(URI.from(mdStr.baseUri), href);
359359
}
360-
options.actionHandler?.(href, event);
360+
options.actionHandler?.(href, mdStr);
361361
}
362362
} catch (err) {
363363
onUnexpectedError(err);

src/vs/editor/browser/widget/markdownRenderer/browser/markdownRenderer.ts

Lines changed: 40 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { MarkdownRenderOptions, renderMarkdown } from '../../../../../base/brows
77
import { createTrustedTypesPolicy } from '../../../../../base/browser/trustedTypes.js';
88
import { onUnexpectedError } from '../../../../../base/common/errors.js';
99
import { IMarkdownString, MarkdownStringTrustedOptions } from '../../../../../base/common/htmlContent.js';
10-
import { DisposableStore, IDisposable } from '../../../../../base/common/lifecycle.js';
10+
import { IDisposable } from '../../../../../base/common/lifecycle.js';
1111
import { IOpenerService } from '../../../../../platform/opener/common/opener.js';
1212
import { EditorOption } from '../../../../common/config/editorOptions.js';
1313
import { ILanguageService } from '../../../../common/languages/language.js';
@@ -45,58 +45,48 @@ export class MarkdownRenderer {
4545
@IOpenerService private readonly _openerService: IOpenerService,
4646
) { }
4747

48-
render(markdown: IMarkdownString | undefined, options?: MarkdownRenderOptions, outElement?: HTMLElement): IMarkdownRenderResult {
49-
if (!markdown) {
50-
const element = outElement ?? document.createElement('span');
51-
return { element, dispose: () => { } };
52-
}
53-
54-
const disposables = new DisposableStore();
55-
const rendered = disposables.add(renderMarkdown(markdown, { ...this._getRenderOptions(markdown), ...options }, outElement));
48+
render(markdown: IMarkdownString, options?: MarkdownRenderOptions, outElement?: HTMLElement): IMarkdownRenderResult {
49+
const rendered = renderMarkdown(markdown, {
50+
codeBlockRenderer: (alias, value) => this.renderCodeBlock(alias, value),
51+
actionHandler: (link, mdStr) => this.openMarkdownLink(link, mdStr),
52+
...options,
53+
}, outElement);
5654
rendered.element.classList.add('rendered-markdown');
57-
return {
58-
element: rendered.element,
59-
dispose: () => disposables.dispose()
60-
};
55+
return rendered;
6156
}
6257

63-
private _getRenderOptions(markdown: IMarkdownString): MarkdownRenderOptions {
64-
return {
65-
codeBlockRenderer: async (languageAlias, value) => {
66-
// In markdown,
67-
// it is possible that we stumble upon language aliases (e.g.js instead of javascript)
68-
// it is possible no alias is given in which case we fall back to the current editor lang
69-
let languageId: string | undefined | null;
70-
if (languageAlias) {
71-
languageId = this._languageService.getLanguageIdByLanguageName(languageAlias);
72-
} else if (this._options.editor) {
73-
languageId = this._options.editor.getModel()?.getLanguageId();
74-
}
75-
if (!languageId) {
76-
languageId = PLAINTEXT_LANGUAGE_ID;
77-
}
78-
const html = await tokenizeToString(this._languageService, value, languageId);
79-
80-
const element = document.createElement('span');
81-
82-
element.innerHTML = (MarkdownRenderer._ttpTokenizer?.createHTML(html) ?? html) as string;
83-
84-
// use "good" font
85-
if (this._options.editor) {
86-
const fontInfo = this._options.editor.getOption(EditorOption.fontInfo);
87-
applyFontInfo(element, fontInfo);
88-
} else if (this._options.codeBlockFontFamily) {
89-
element.style.fontFamily = this._options.codeBlockFontFamily;
90-
}
91-
92-
if (this._options.codeBlockFontSize !== undefined) {
93-
element.style.fontSize = this._options.codeBlockFontSize;
94-
}
95-
96-
return element;
97-
},
98-
actionHandler: (link) => this.openMarkdownLink(link, markdown),
99-
};
58+
private async renderCodeBlock(languageAlias: string | undefined, value: string): Promise<HTMLElement> {
59+
// In markdown,
60+
// it is possible that we stumble upon language aliases (e.g.js instead of javascript)
61+
// it is possible no alias is given in which case we fall back to the current editor lang
62+
let languageId: string | undefined | null;
63+
if (languageAlias) {
64+
languageId = this._languageService.getLanguageIdByLanguageName(languageAlias);
65+
} else if (this._options.editor) {
66+
languageId = this._options.editor.getModel()?.getLanguageId();
67+
}
68+
if (!languageId) {
69+
languageId = PLAINTEXT_LANGUAGE_ID;
70+
}
71+
const html = await tokenizeToString(this._languageService, value, languageId);
72+
73+
const element = document.createElement('span');
74+
75+
element.innerHTML = (MarkdownRenderer._ttpTokenizer?.createHTML(html) ?? html) as string;
76+
77+
// use "good" font
78+
if (this._options.editor) {
79+
const fontInfo = this._options.editor.getOption(EditorOption.fontInfo);
80+
applyFontInfo(element, fontInfo);
81+
} else if (this._options.codeBlockFontFamily) {
82+
element.style.fontFamily = this._options.codeBlockFontFamily;
83+
}
84+
85+
if (this._options.codeBlockFontSize !== undefined) {
86+
element.style.fontSize = this._options.codeBlockFontSize;
87+
}
88+
89+
return element;
10090
}
10191

10292
protected async openMarkdownLink(link: string, markdown: IMarkdownString) {

src/vs/editor/contrib/message/browser/messageController.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,9 @@ export class MessageController implements IEditorContribution {
6969

7070
if (isMarkdownString(message)) {
7171
const renderedMessage = this._messageListeners.add(renderMarkdown(message, {
72-
actionHandler: (url) => {
72+
actionHandler: (url, mdStr) => {
7373
this.closeMessage();
74-
openLinkFromMarkdown(this._openerService, url, isMarkdownString(message) ? message.isTrusted : undefined);
74+
openLinkFromMarkdown(this._openerService, url, mdStr.isTrusted);
7575
},
7676
}));
7777
this._messageWidget.value = new MessageWidget(this._editor, position, renderedMessage.element);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget {
271271
this.domNodes.scrollbar.scanDomNode();
272272
}
273273

274-
private renderMarkdownDocs(markdown: IMarkdownString | undefined): IMarkdownRenderResult {
274+
private renderMarkdownDocs(markdown: IMarkdownString): IMarkdownRenderResult {
275275
const renderedContents = this.renderDisposeables.add(this.markdownRenderer.render(markdown, {
276276
asyncRenderCallback: () => {
277277
this.domNodes?.scrollbar.scanDomNode();

src/vs/workbench/browser/parts/dialogs/dialogHandler.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ export class BrowserDialogHandler extends AbstractDialogHandler {
9898
parent.classList.add(...(customOptions.classes || []));
9999
customOptions.markdownDetails?.forEach(markdownDetail => {
100100
const result = dialogDisposables.add(this.markdownRenderer.render(markdownDetail.markdown, {
101-
actionHandler: markdownDetail.actionHandler || (link => {
102-
return openLinkFromMarkdown(this.openerService, link, markdownDetail.markdown.isTrusted, true /* skip URL validation to prevent another dialog from showing which is unsupported */);
101+
actionHandler: markdownDetail.actionHandler || ((link, mdStr) => {
102+
return openLinkFromMarkdown(this.openerService, link, mdStr.isTrusted, true /* skip URL validation to prevent another dialog from showing which is unsupported */);
103103
}),
104104
}));
105105
parent.appendChild(result.element);

src/vs/workbench/contrib/chat/browser/chatContentParts/chatConfirmationWidget.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { Emitter, Event } from '../../../../../base/common/event.js';
1111
import { IMarkdownString, MarkdownString } from '../../../../../base/common/htmlContent.js';
1212
import { Disposable, DisposableStore, MutableDisposable } from '../../../../../base/common/lifecycle.js';
1313
import type { ThemeIcon } from '../../../../../base/common/themables.js';
14-
import { IMarkdownRenderResult, MarkdownRenderer, openLinkFromMarkdown } from '../../../../../editor/browser/widget/markdownRenderer/browser/markdownRenderer.js';
14+
import { IMarkdownRenderResult, MarkdownRenderer } from '../../../../../editor/browser/widget/markdownRenderer/browser/markdownRenderer.js';
1515
import { localize } from '../../../../../nls.js';
1616
import { MenuWorkbenchToolBar } from '../../../../../platform/actions/browser/toolbar.js';
1717
import { MenuId } from '../../../../../platform/actions/common/actions.js';
@@ -21,7 +21,6 @@ import { IContextMenuService } from '../../../../../platform/contextview/browser
2121
import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js';
2222
import { ServiceCollection } from '../../../../../platform/instantiation/common/serviceCollection.js';
2323
import { FocusMode } from '../../../../../platform/native/common/native.js';
24-
import { IOpenerService } from '../../../../../platform/opener/common/opener.js';
2524
import { defaultButtonStyles } from '../../../../../platform/theme/browser/defaultStyles.js';
2625
import { IHostService } from '../../../../services/host/browser/host.js';
2726
import { IViewsService } from '../../../../services/views/common/viewsService.js';
@@ -77,7 +76,6 @@ export class ChatQueryTitlePart extends Disposable {
7776
private _title: IMarkdownString | string,
7877
subtitle: string | IMarkdownString | undefined,
7978
private readonly _renderer: MarkdownRenderer,
80-
@IOpenerService private readonly _openerService: IOpenerService,
8179
) {
8280
super();
8381

@@ -91,7 +89,6 @@ export class ChatQueryTitlePart extends Disposable {
9189
const str = this.toMdString(subtitle);
9290
const renderedTitle = this._register(_renderer.render(str, {
9391
asyncRenderCallback: () => this._onDidChangeHeight.fire(),
94-
actionHandler: link => openLinkFromMarkdown(this._openerService, link, str.isTrusted),
9592
}));
9693
const wrapper = document.createElement('small');
9794
wrapper.appendChild(renderedTitle.element);

src/vs/workbench/contrib/chat/browser/chatMarkdownRenderer.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ export class ChatMarkdownRenderer extends MarkdownRenderer {
7272
super(options ?? {}, languageService, openerService);
7373
}
7474

75-
override render(markdown: IMarkdownString | undefined, options?: MarkdownRenderOptions, outElement?: HTMLElement): IMarkdownRenderResult {
75+
override render(markdown: IMarkdownString, options?: MarkdownRenderOptions, outElement?: HTMLElement): IMarkdownRenderResult {
7676
options = {
7777
...options,
7878
sanitizerConfig: {
@@ -86,7 +86,7 @@ export class ChatMarkdownRenderer extends MarkdownRenderer {
8686
}
8787
};
8888

89-
const mdWithBody: IMarkdownString | undefined = (markdown && markdown.supportHtml) ?
89+
const mdWithBody: IMarkdownString = (markdown && markdown.supportHtml) ?
9090
{
9191
...markdown,
9292

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

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import * as dom from '../../../../base/browser/dom.js';
77
import * as nls from '../../../../nls.js';
88
import { renderMarkdown } from '../../../../base/browser/markdownRenderer.js';
99
import { IDisposable, DisposableStore } from '../../../../base/common/lifecycle.js';
10-
import { IOpenerService } from '../../../../platform/opener/common/opener.js';
1110
import { IResourceLabel, ResourceLabels } from '../../../browser/labels.js';
1211
import { CommentNode, ResourceWithCommentThreads } from '../common/commentModel.js';
1312
import { ITreeContextMenuEvent, ITreeFilter, ITreeNode, TreeFilterResult, TreeVisibility } from '../../../../base/browser/ui/tree/tree.js';
@@ -27,7 +26,6 @@ import { Color } from '../../../../base/common/color.js';
2726
import { IMatch } from '../../../../base/common/filters.js';
2827
import { FilterOptions } from './commentsFilterOptions.js';
2928
import { basename } from '../../../../base/common/resources.js';
30-
import { openLinkFromMarkdown } from '../../../../editor/browser/widget/markdownRenderer/browser/markdownRenderer.js';
3129
import { IStyleOverride } from '../../../../platform/theme/browser/defaultStyles.js';
3230
import { IListStyles } from '../../../../base/browser/ui/list/listWidget.js';
3331
import { ILocalizedString } from '../../../../platform/action/common/action.js';
@@ -183,7 +181,6 @@ export class CommentNodeRenderer implements IListRenderer<ITreeNode<CommentNode>
183181
constructor(
184182
private actionViewItemProvider: IActionViewItemProvider,
185183
private menus: CommentsMenus,
186-
@IOpenerService private readonly openerService: IOpenerService,
187184
@IConfigurationService private readonly configurationService: IConfigurationService,
188185
@IHoverService private readonly hoverService: IHoverService,
189186
@IThemeService private themeService: IThemeService
@@ -247,9 +244,7 @@ export class CommentNodeRenderer implements IListRenderer<ITreeNode<CommentNode>
247244
}
248245

249246
private getRenderedComment(commentBody: IMarkdownString) {
250-
const renderedComment = renderMarkdown(commentBody, {
251-
actionHandler: (link) => openLinkFromMarkdown(this.openerService, link, commentBody.isTrusted),
252-
}, document.createElement('span'));
247+
const renderedComment = renderMarkdown(commentBody, {}, document.createElement('span'));
253248
const images = renderedComment.element.getElementsByTagName('img');
254249
for (let i = 0; i < images.length; i++) {
255250
const image = images[i];

src/vs/workbench/contrib/scm/browser/scmViewPane.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2057,8 +2057,8 @@ class SCMInputWidget {
20572057

20582058
const renderer = this.instantiationService.createInstance(MarkdownRenderer, {});
20592059
const renderedMarkdown = renderer.render(message, {
2060-
actionHandler: (link) => {
2061-
openLinkFromMarkdown(this.openerService, link, message.isTrusted);
2060+
actionHandler: (link, mdStr) => {
2061+
openLinkFromMarkdown(this.openerService, link, mdStr.isTrusted);
20622062
this.element.style.borderBottomLeftRadius = '2px';
20632063
this.element.style.borderBottomRightRadius = '2px';
20642064
this.contextViewService.hideContextView();

0 commit comments

Comments
 (0)