Skip to content

Commit 45081a7

Browse files
committed
Combine related md stripping functions
`renderStringAsPlaintext` just called `renderMarkdownAsPlaintext`. I think it makes sense to combine them
1 parent 38179d3 commit 45081a7

File tree

17 files changed

+51
-54
lines changed

17 files changed

+51
-54
lines changed

src/vs/base/browser/markdownRenderer.ts

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import { onUnexpectedError } from '../common/errors.js';
77
import { Event } from '../common/event.js';
8-
import { escapeDoubleQuotes, IMarkdownString, isMarkdownString, MarkdownStringTrustedOptions, parseHrefAndDimensions, removeMarkdownEscapes } from '../common/htmlContent.js';
8+
import { escapeDoubleQuotes, IMarkdownString, MarkdownStringTrustedOptions, parseHrefAndDimensions, removeMarkdownEscapes } from '../common/htmlContent.js';
99
import { markdownEscapeEscapedIcons } from '../common/iconLabels.js';
1010
import { defaultGenerator } from '../common/idGenerator.js';
1111
import { KeyCode } from '../common/keyCodes.js';
@@ -585,28 +585,25 @@ function getSanitizerOptions(options: IInternalSanitizerOptions): domSanitize.Sa
585585
}
586586

587587
/**
588-
* Strips all markdown from `string`, if it's an IMarkdownString. For example
589-
* `# Header` would be output as `Header`. If it's not, the string is returned.
590-
*/
591-
export function renderStringAsPlaintext(string: IMarkdownString | string) {
592-
return isMarkdownString(string) ? renderMarkdownAsPlaintext(string) : string;
593-
}
594-
595-
/**
596-
* Strips all markdown from `markdown`
588+
* Renders `str` as plaintext, stripping out Markdown syntax if it's a {@link IMarkdownString}.
597589
*
598590
* For example `# Header` would be output as `Header`.
599-
*
600-
* @param withCodeBlocks Include the ``` of code blocks as well
601591
*/
602-
export function renderMarkdownAsPlaintext(markdown: IMarkdownString, withCodeBlocks?: boolean) {
592+
export function renderAsPlaintext(str: IMarkdownString | string, options?: {
593+
/** Controls if the ``` of code blocks should be preserved in the output or not */
594+
readonly includeCodeBlocksFences?: boolean;
595+
}) {
596+
if (typeof str === 'string') {
597+
return str;
598+
}
599+
603600
// values that are too long will freeze the UI
604-
let value = markdown.value ?? '';
601+
let value = str.value ?? '';
605602
if (value.length > 100_000) {
606603
value = `${value.substr(0, 100_000)}…`;
607604
}
608605

609-
const html = marked.parse(value, { async: false, renderer: withCodeBlocks ? plainTextWithCodeBlocksRenderer.value : plainTextRenderer.value });
606+
const html = marked.parse(value, { async: false, renderer: options?.includeCodeBlocksFences ? plainTextWithCodeBlocksRenderer.value : plainTextRenderer.value });
610607
return sanitizeRenderedMarkdown({ isTrusted: false }, html)
611608
.toString()
612609
.replace(/&(#\d+|[a-zA-Z]+);/g, m => unescapeInfo.get(m) ?? m)

src/vs/base/browser/ui/button/button.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import { IContextMenuProvider } from '../../contextmenu.js';
77
import { addDisposableListener, EventHelper, EventType, IFocusTracker, isActiveElement, reset, trackFocus, $ } from '../../dom.js';
88
import { StandardKeyboardEvent } from '../../keyboardEvent.js';
9-
import { renderMarkdown, renderStringAsPlaintext } from '../../markdownRenderer.js';
9+
import { renderMarkdown, renderAsPlaintext } from '../../markdownRenderer.js';
1010
import { Gesture, EventType as TouchEventType } from '../../touch.js';
1111
import { createInstantHoverDelegate, getDefaultHoverDelegate } from '../hover/hoverDelegateFactory.js';
1212
import { IHoverDelegate } from '../hover/hoverDelegate.js';
@@ -269,7 +269,7 @@ export class Button extends Disposable implements IButton {
269269
if (typeof this.options.title === 'string') {
270270
title = this.options.title;
271271
} else if (this.options.title) {
272-
title = renderStringAsPlaintext(value);
272+
title = renderAsPlaintext(value);
273273
}
274274

275275
this.setTitle(title);
@@ -393,7 +393,7 @@ export class ButtonWithDropdown extends Disposable implements IButton {
393393

394394
this.primaryButton = this._register(new Button(this.element, options));
395395
this._register(this.primaryButton.onDidClick(e => this._onDidClick.fire(e)));
396-
this.action = this._register(new Action('primaryAction', renderStringAsPlaintext(this.primaryButton.label), undefined, true, async () => this._onDidClick.fire(undefined)));
396+
this.action = this._register(new Action('primaryAction', renderAsPlaintext(this.primaryButton.label), undefined, true, async () => this._onDidClick.fire(undefined)));
397397

398398
this.separatorContainer = document.createElement('div');
399399
this.separatorContainer.classList.add('monaco-button-dropdown-separator');
@@ -670,7 +670,7 @@ export class ButtonWithIcon extends Button {
670670
if (typeof this.options.title === 'string') {
671671
title = this.options.title;
672672
} else if (this.options.title) {
673-
title = renderStringAsPlaintext(value);
673+
title = renderAsPlaintext(value);
674674
}
675675

676676
this.setTitle(title);

src/vs/base/test/browser/markdownRenderer.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import assert from 'assert';
7-
import { fillInIncompleteTokens, renderMarkdown, renderMarkdownAsPlaintext } from '../../browser/markdownRenderer.js';
7+
import { fillInIncompleteTokens, renderMarkdown, renderAsPlaintext } from '../../browser/markdownRenderer.js';
88
import { IMarkdownString, MarkdownString } from '../../common/htmlContent.js';
99
import * as marked from '../../common/marked/marked.js';
1010
import { parse } from '../../common/marshalling.js';
@@ -261,14 +261,14 @@ suite('MarkdownRenderer', () => {
261261
test('test code, blockquote, heading, list, listitem, paragraph, table, tablerow, tablecell, strong, em, br, del, text are rendered plaintext', () => {
262262
const markdown = { value: '`code`\n>quote\n# heading\n- list\n\ntable | table2\n--- | --- \none | two\n\n\nbo**ld**\n_italic_\n~~del~~\nsome text' };
263263
const expected = 'code\nquote\nheading\nlist\n\ntable table2\none two\nbold\nitalic\ndel\nsome text';
264-
const result: string = renderMarkdownAsPlaintext(markdown);
264+
const result: string = renderAsPlaintext(markdown);
265265
assert.strictEqual(result, expected);
266266
});
267267

268268
test('test html, hr, image, link are rendered plaintext', () => {
269269
const markdown = { value: '<div>html</div>\n\n---\n![image](imageLink)\n[text](textLink)' };
270270
const expected = 'text';
271-
const result: string = renderMarkdownAsPlaintext(markdown);
271+
const result: string = renderAsPlaintext(markdown);
272272
assert.strictEqual(result, expected);
273273
});
274274

@@ -285,7 +285,7 @@ suite('MarkdownRenderer', () => {
285285
'<form>html</form>',
286286
'```',
287287
].join('\n');
288-
const result: string = renderMarkdownAsPlaintext(markdown, true);
288+
const result: string = renderAsPlaintext(markdown, { includeCodeBlocksFences: true });
289289
assert.strictEqual(result, expected);
290290
});
291291
});

src/vs/workbench/browser/parts/views/treeView.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import { DataTransfers, IDragAndDropData } from '../../../../base/browser/dnd.js';
77
import * as DOM from '../../../../base/browser/dom.js';
88
import * as cssJs from '../../../../base/browser/cssValue.js';
9-
import { renderMarkdownAsPlaintext } from '../../../../base/browser/markdownRenderer.js';
9+
import { renderAsPlaintext } from '../../../../base/browser/markdownRenderer.js';
1010
import { ActionBar, IActionViewItemProvider } from '../../../../base/browser/ui/actionbar/actionbar.js';
1111
import { ActionViewItem } from '../../../../base/browser/ui/actionbar/actionViewItems.js';
1212
import { IHoverDelegate } from '../../../../base/browser/ui/hover/hoverDelegate.js';
@@ -1306,7 +1306,7 @@ class TreeRenderer extends Disposable implements ITreeRenderer<ITreeItem, FuzzyS
13061306
} else if (node.tooltip === undefined) {
13071307
return label;
13081308
} else if (!isString(node.tooltip)) {
1309-
return { markdown: node.tooltip, markdownNotSupportedFallback: resource ? undefined : renderMarkdownAsPlaintext(node.tooltip) }; // Passing undefined as the fallback for a resource falls back to the old native hover
1309+
return { markdown: node.tooltip, markdownNotSupportedFallback: resource ? undefined : renderAsPlaintext(node.tooltip) }; // Passing undefined as the fallback for a resource falls back to the old native hover
13101310
} else if (node.tooltip !== '') {
13111311
return node.tooltip;
13121312
} else {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { IInstantiationService } from '../../../../platform/instantiation/common
1010
import { AccessibilityProgressSignalScheduler } from '../../../../platform/accessibilitySignal/browser/progressAccessibilitySignalScheduler.js';
1111
import { IChatAccessibilityService } from './chat.js';
1212
import { IChatResponseViewModel } from '../common/chatViewModel.js';
13-
import { renderStringAsPlaintext } from '../../../../base/browser/markdownRenderer.js';
13+
import { renderAsPlaintext } from '../../../../base/browser/markdownRenderer.js';
1414
import { MarkdownString } from '../../../../base/common/htmlContent.js';
1515
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
1616
import { AccessibilityVoiceSettingId } from '../../accessibility/browser/accessibilityConfiguration.js';
@@ -46,7 +46,7 @@ export class ChatAccessibilityService extends Disposable implements IChatAccessi
4646
return;
4747
}
4848
const errorDetails = isPanelChat && response.errorDetails ? ` ${response.errorDetails.message}` : '';
49-
const plainTextResponse = renderStringAsPlaintext(new MarkdownString(responseContent));
49+
const plainTextResponse = renderAsPlaintext(new MarkdownString(responseContent));
5050
if (!isVoiceInput || this._configurationService.getValue(AccessibilityVoiceSettingId.AutoSynthesize) !== 'on') {
5151
status(plainTextResponse + errorDetails);
5252
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import * as dom from '../../../../../base/browser/dom.js';
7-
import { renderStringAsPlaintext } from '../../../../../base/browser/markdownRenderer.js';
7+
import { renderAsPlaintext } from '../../../../../base/browser/markdownRenderer.js';
88
import { Button, ButtonWithDropdown, IButton, IButtonOptions } from '../../../../../base/browser/ui/button/button.js';
99
import { Action } from '../../../../../base/common/actions.js';
1010
import { Emitter, Event } from '../../../../../base/common/event.js';
@@ -201,7 +201,7 @@ abstract class BaseChatConfirmationWidget extends Disposable {
201201
this._hostService.focus(targetWindow, { mode: FocusMode.Notify });
202202

203203
// Notify
204-
const title = renderStringAsPlaintext(this.title);
204+
const title = renderAsPlaintext(this.title);
205205
const notification = await dom.triggerNotification(title ? localize('notificationTitle', "Chat: {0}", title) : localize('defaultTitle', "Chat: Confirmation Required"),
206206
{
207207
detail: localize('notificationDetail', "The current chat session requires your confirmation to proceed.")

src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingEditorOverlay.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import { Codicon } from '../../../../../base/common/codicons.js';
3131
import { renderIcon } from '../../../../../base/browser/ui/iconLabel/iconLabels.js';
3232
import { ThemeIcon } from '../../../../../base/common/themables.js';
3333
import * as arrays from '../../../../../base/common/arrays.js';
34-
import { renderStringAsPlaintext } from '../../../../../base/browser/markdownRenderer.js';
34+
import { renderAsPlaintext } from '../../../../../base/browser/markdownRenderer.js';
3535
import { IKeybindingService } from '../../../../../platform/keybinding/common/keybinding.js';
3636

3737
class ChatEditorOverlayWidget extends Disposable {
@@ -112,7 +112,7 @@ class ChatEditorOverlayWidget extends Disposable {
112112
if (!busy || !value || this._session.read(r)?.isGlobalEditingSession) {
113113
textProgress.innerText = '';
114114
} else if (value) {
115-
textProgress.innerText = renderStringAsPlaintext(value.message);
115+
textProgress.innerText = renderAsPlaintext(value.message);
116116
}
117117
}));
118118

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { renderMarkdownAsPlaintext } from '../../../../base/browser/markdownRenderer.js';
6+
import { renderAsPlaintext } from '../../../../base/browser/markdownRenderer.js';
77
import { MarkdownString } from '../../../../base/common/htmlContent.js';
88
import { stripIcons } from '../../../../base/common/iconLabels.js';
99
import { Disposable } from '../../../../base/common/lifecycle.js';
@@ -71,7 +71,7 @@ class ChatResponseAccessibleProvider extends Disposable implements IAccessibleVi
7171
for (const toolInvocation of toolInvocations) {
7272
if (toolInvocation.confirmationMessages) {
7373
const title = typeof toolInvocation.confirmationMessages.title === 'string' ? toolInvocation.confirmationMessages.title : toolInvocation.confirmationMessages.title.value;
74-
const message = typeof toolInvocation.confirmationMessages.message === 'string' ? toolInvocation.confirmationMessages.message : stripIcons(renderMarkdownAsPlaintext(toolInvocation.confirmationMessages.message));
74+
const message = typeof toolInvocation.confirmationMessages.message === 'string' ? toolInvocation.confirmationMessages.message : stripIcons(renderAsPlaintext(toolInvocation.confirmationMessages.message));
7575
let input = '';
7676
if (toolInvocation.toolSpecificData) {
7777
input = toolInvocation.toolSpecificData?.kind === 'terminal'
@@ -89,20 +89,20 @@ class ChatResponseAccessibleProvider extends Disposable implements IAccessibleVi
8989
responseContent += `\n${message}\n`;
9090
} else if (toolInvocation.isComplete && toolInvocation.resultDetails && 'input' in toolInvocation.resultDetails) {
9191
responseContent += '\n' + toolInvocation.resultDetails.isError ? 'Errored ' : 'Completed ';
92-
responseContent += `${`${typeof toolInvocation.invocationMessage === 'string' ? toolInvocation.invocationMessage : stripIcons(renderMarkdownAsPlaintext(toolInvocation.invocationMessage))} with input: ${toolInvocation.resultDetails.input}`}\n`;
92+
responseContent += `${`${typeof toolInvocation.invocationMessage === 'string' ? toolInvocation.invocationMessage : stripIcons(renderAsPlaintext(toolInvocation.invocationMessage))} with input: ${toolInvocation.resultDetails.input}`}\n`;
9393
}
9494
}
9595

9696
const pastConfirmations = item.response.value.filter(item => item.kind === 'toolInvocationSerialized');
9797
for (const pastConfirmation of pastConfirmations) {
9898
if (pastConfirmation.isComplete && pastConfirmation.resultDetails && 'input' in pastConfirmation.resultDetails) {
9999
if (pastConfirmation.pastTenseMessage) {
100-
responseContent += `\n${`${typeof pastConfirmation.pastTenseMessage === 'string' ? pastConfirmation.pastTenseMessage : stripIcons(renderMarkdownAsPlaintext(pastConfirmation.pastTenseMessage))} with input: ${pastConfirmation.resultDetails.input}`}\n`;
100+
responseContent += `\n${`${typeof pastConfirmation.pastTenseMessage === 'string' ? pastConfirmation.pastTenseMessage : stripIcons(renderAsPlaintext(pastConfirmation.pastTenseMessage))} with input: ${pastConfirmation.resultDetails.input}`}\n`;
101101
}
102102
}
103103
}
104104
}
105-
return renderMarkdownAsPlaintext(new MarkdownString(responseContent), true);
105+
return renderAsPlaintext(new MarkdownString(responseContent), { includeCodeBlocksFences: true });
106106
}
107107

108108
onClose(): void {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { renderStringAsPlaintext } from '../../../../base/browser/markdownRenderer.js';
6+
import { renderAsPlaintext } from '../../../../base/browser/markdownRenderer.js';
77
import { assertNever } from '../../../../base/common/assert.js';
88
import { RunOnceScheduler } from '../../../../base/common/async.js';
99
import { encodeBase64 } from '../../../../base/common/buffer.js';
@@ -295,7 +295,7 @@ export class LanguageModelToolsService extends Disposable implements ILanguageMo
295295
} else {
296296
const prepared = await this.prepareToolInvocation(tool, dto, token);
297297
if (prepared?.confirmationMessages && !this.shouldAutoConfirm(tool.data.id, tool.data.runsInWorkspace)) {
298-
const result = await this._dialogService.confirm({ message: renderStringAsPlaintext(prepared.confirmationMessages.title), detail: renderStringAsPlaintext(prepared.confirmationMessages.message) });
298+
const result = await this._dialogService.confirm({ message: renderAsPlaintext(prepared.confirmationMessages.title), detail: renderAsPlaintext(prepared.confirmationMessages.message) });
299299
if (!result.confirmed) {
300300
throw new CancellationError();
301301
}

src/vs/workbench/contrib/chat/electron-browser/actions/voiceChatActions.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { renderStringAsPlaintext } from '../../../../../base/browser/markdownRenderer.js';
6+
import { renderAsPlaintext } from '../../../../../base/browser/markdownRenderer.js';
77
import { RunOnceScheduler, disposableTimeout, raceCancellation } from '../../../../../base/common/async.js';
88
import { CancellationToken, CancellationTokenSource } from '../../../../../base/common/cancellation.js';
99
import { Codicon } from '../../../../../base/common/codicons.js';
@@ -818,7 +818,7 @@ class ChatSynthesizerSessions {
818818
}
819819

820820
return {
821-
chunk: chunk ? renderStringAsPlaintext({ value: chunk }) : chunk, // convert markdown to plain text
821+
chunk: chunk ? renderAsPlaintext({ value: chunk }) : chunk, // convert markdown to plain text
822822
offset
823823
};
824824
}

0 commit comments

Comments
 (0)