mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-08 17:19:48 +01:00
Merge pull request #270594 from mjbvz/dev/mjbvz/inner-xerinae
Avoid using custom markdown actionHandlers in a few more cases
This commit is contained in:
@@ -13,8 +13,7 @@ import { IConfigurationService } from '../../../../platform/configuration/common
|
||||
import { HoverAction, HoverPosition, HoverWidget as BaseHoverWidget, getHoverAccessibleViewHint } from '../../../../base/browser/ui/hover/hoverWidget.js';
|
||||
import { Widget } from '../../../../base/browser/ui/widget.js';
|
||||
import { AnchorPosition } from '../../../../base/browser/ui/contextview/contextview.js';
|
||||
import { IOpenerService } from '../../../../platform/opener/common/opener.js';
|
||||
import { IMarkdownRendererService, openLinkFromMarkdown } from '../../../../platform/markdown/browser/markdownRenderer.js';
|
||||
import { IMarkdownRendererService } from '../../../../platform/markdown/browser/markdownRenderer.js';
|
||||
import { isMarkdownString } from '../../../../base/common/htmlContent.js';
|
||||
import { localize } from '../../../../nls.js';
|
||||
import { isMacintosh } from '../../../../base/common/platform.js';
|
||||
@@ -49,7 +48,7 @@ export class HoverWidget extends Widget implements IHoverWidget {
|
||||
private readonly _hoverPointer: HTMLElement | undefined;
|
||||
private readonly _hoverContainer: HTMLElement;
|
||||
private readonly _target: IHoverTarget;
|
||||
private readonly _linkHandler: (url: string) => void;
|
||||
private readonly _linkHandler: ((url: string) => void) | undefined;
|
||||
|
||||
private _isDisposed: boolean = false;
|
||||
private _hoverPosition: HoverPosition;
|
||||
@@ -98,15 +97,12 @@ export class HoverWidget extends Widget implements IHoverWidget {
|
||||
options: IHoverOptions,
|
||||
@IKeybindingService private readonly _keybindingService: IKeybindingService,
|
||||
@IConfigurationService private readonly _configurationService: IConfigurationService,
|
||||
@IOpenerService private readonly _openerService: IOpenerService,
|
||||
@IMarkdownRendererService private readonly _markdownRenderer: IMarkdownRendererService,
|
||||
@IAccessibilityService private readonly _accessibilityService: IAccessibilityService
|
||||
) {
|
||||
super();
|
||||
|
||||
this._linkHandler = options.linkHandler || (url => {
|
||||
return openLinkFromMarkdown(this._openerService, url, isMarkdownString(options.content) ? options.content.isTrusted : undefined);
|
||||
});
|
||||
this._linkHandler = options.linkHandler;
|
||||
|
||||
this._target = 'targetElements' in options.target ? options.target : new ElementHoverTarget(options.target);
|
||||
|
||||
@@ -166,7 +162,7 @@ export class HoverWidget extends Widget implements IHoverWidget {
|
||||
const markdown = options.content;
|
||||
|
||||
const { element, dispose } = this._markdownRenderer.render(markdown, {
|
||||
actionHandler: (content) => this._linkHandler(content),
|
||||
actionHandler: this._linkHandler,
|
||||
asyncRenderCallback: () => {
|
||||
contentsElement.classList.add('code-hover-contents');
|
||||
this.layout();
|
||||
|
||||
@@ -62,13 +62,21 @@ export class MarkdownRendererService implements IMarkdownRendererService {
|
||||
) { }
|
||||
|
||||
render(markdown: IMarkdownString, options?: MarkdownRenderOptions & IMarkdownRendererExtraOptions, outElement?: HTMLElement): IRenderedMarkdown {
|
||||
const rendered = renderMarkdown(markdown, {
|
||||
codeBlockRenderer: (alias, value) => this._defaultCodeBlockRenderer?.renderCodeBlock(alias, value, options ?? {}) ?? Promise.resolve(document.createElement('span')),
|
||||
actionHandler: (link, mdStr) => {
|
||||
const resolvedOptions = { ...options };
|
||||
|
||||
if (!resolvedOptions.actionHandler) {
|
||||
resolvedOptions.actionHandler = (link, mdStr) => {
|
||||
return openLinkFromMarkdown(this._openerService, link, mdStr.isTrusted);
|
||||
},
|
||||
...options,
|
||||
}, outElement);
|
||||
};
|
||||
}
|
||||
|
||||
if (!resolvedOptions.codeBlockRenderer) {
|
||||
resolvedOptions.codeBlockRenderer = (alias, value) => {
|
||||
return this._defaultCodeBlockRenderer?.renderCodeBlock(alias, value, resolvedOptions ?? {}) ?? Promise.resolve(document.createElement('span'));
|
||||
};
|
||||
}
|
||||
|
||||
const rendered = renderMarkdown(markdown, resolvedOptions, outElement);
|
||||
rendered.element.classList.add('rendered-markdown');
|
||||
return rendered;
|
||||
}
|
||||
|
||||
@@ -17,9 +17,7 @@ import { getExtensionId } from '../../../../platform/extensionManagement/common/
|
||||
import { IListRenderer, IListVirtualDelegate } from '../../../../base/browser/ui/list/list.js';
|
||||
import { Button } from '../../../../base/browser/ui/button/button.js';
|
||||
import { defaultButtonStyles, defaultKeybindingLabelStyles } from '../../../../platform/theme/browser/defaultStyles.js';
|
||||
import { renderMarkdown } from '../../../../base/browser/markdownRenderer.js';
|
||||
import { getErrorMessage, onUnexpectedError } from '../../../../base/common/errors.js';
|
||||
import { IOpenerService } from '../../../../platform/opener/common/opener.js';
|
||||
import { getErrorMessage } from '../../../../base/common/errors.js';
|
||||
import { PANEL_SECTION_BORDER } from '../../../common/theme.js';
|
||||
import { IThemeService, Themable } from '../../../../platform/theme/common/themeService.js';
|
||||
import { DomScrollableElement } from '../../../../base/browser/ui/scrollbar/scrollableElement.js';
|
||||
@@ -39,6 +37,7 @@ import { ResolvedKeybinding } from '../../../../base/common/keybindings.js';
|
||||
import { asCssVariable } from '../../../../platform/theme/common/colorUtils.js';
|
||||
import { foreground, chartAxis, chartGuide, chartLine } from '../../../../platform/theme/common/colorRegistry.js';
|
||||
import { IHoverService } from '../../../../platform/hover/browser/hover.js';
|
||||
import { IMarkdownRendererService } from '../../../../platform/markdown/browser/markdownRenderer.js';
|
||||
|
||||
interface IExtensionFeatureElementRenderer extends IExtensionFeatureRenderer {
|
||||
type: 'element';
|
||||
@@ -52,9 +51,9 @@ class RuntimeStatusMarkdownRenderer extends Disposable implements IExtensionFeat
|
||||
|
||||
constructor(
|
||||
@IExtensionService private readonly extensionService: IExtensionService,
|
||||
@IOpenerService private readonly openerService: IOpenerService,
|
||||
@IHoverService private readonly hoverService: IHoverService,
|
||||
@IExtensionFeaturesManagementService private readonly extensionFeaturesManagementService: IExtensionFeaturesManagementService,
|
||||
@IMarkdownRendererService private readonly markdownRendererService: IMarkdownRendererService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
@@ -152,15 +151,11 @@ class RuntimeStatusMarkdownRenderer extends Disposable implements IExtensionFeat
|
||||
}
|
||||
|
||||
private renderMarkdown(markdown: IMarkdownString, container: HTMLElement, disposables: DisposableStore): void {
|
||||
const { element } = disposables.add(renderMarkdown(
|
||||
{
|
||||
value: markdown.value,
|
||||
isTrusted: markdown.isTrusted,
|
||||
supportThemeIcons: true
|
||||
},
|
||||
{
|
||||
actionHandler: (content) => this.openerService.open(content, { allowCommands: !!markdown.isTrusted }).catch(onUnexpectedError),
|
||||
}));
|
||||
const { element } = disposables.add(this.markdownRendererService.render({
|
||||
value: markdown.value,
|
||||
isTrusted: markdown.isTrusted,
|
||||
supportThemeIcons: true
|
||||
}));
|
||||
append(container, element);
|
||||
}
|
||||
|
||||
@@ -547,10 +542,10 @@ class ExtensionFeatureView extends Disposable {
|
||||
private readonly extensionId: ExtensionIdentifier,
|
||||
private readonly manifest: IExtensionManifest,
|
||||
readonly feature: IExtensionFeatureDescriptor,
|
||||
@IOpenerService private readonly openerService: IOpenerService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IExtensionFeaturesManagementService private readonly extensionFeaturesManagementService: IExtensionFeaturesManagementService,
|
||||
@IDialogService private readonly dialogService: IDialogService,
|
||||
@IMarkdownRendererService private readonly markdownRendererService: IMarkdownRendererService,
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -702,15 +697,11 @@ class ExtensionFeatureView extends Disposable {
|
||||
}
|
||||
|
||||
private renderMarkdown(markdown: IMarkdownString, container: HTMLElement): void {
|
||||
const { element } = this._register(renderMarkdown(
|
||||
{
|
||||
value: markdown.value,
|
||||
isTrusted: markdown.isTrusted,
|
||||
supportThemeIcons: true
|
||||
},
|
||||
{
|
||||
actionHandler: (content) => this.openerService.open(content, { allowCommands: !!markdown.isTrusted }).catch(onUnexpectedError),
|
||||
}));
|
||||
const { element } = this._register(this.markdownRendererService.render({
|
||||
value: markdown.value,
|
||||
isTrusted: markdown.isTrusted,
|
||||
supportThemeIcons: true
|
||||
}));
|
||||
append(container, element);
|
||||
}
|
||||
|
||||
|
||||
@@ -32,9 +32,7 @@ import { IExtensionService } from '../../../services/extensions/common/extension
|
||||
import { areSameExtensions } from '../../../../platform/extensionManagement/common/extensionManagementUtil.js';
|
||||
import Severity from '../../../../base/common/severity.js';
|
||||
import { Color } from '../../../../base/common/color.js';
|
||||
import { renderMarkdown } from '../../../../base/browser/markdownRenderer.js';
|
||||
import { IOpenerService } from '../../../../platform/opener/common/opener.js';
|
||||
import { onUnexpectedError } from '../../../../base/common/errors.js';
|
||||
import { renderIcon } from '../../../../base/browser/ui/iconLabel/iconLabels.js';
|
||||
import { StandardKeyboardEvent } from '../../../../base/browser/keyboardEvent.js';
|
||||
import { KeyCode } from '../../../../base/common/keyCodes.js';
|
||||
@@ -51,6 +49,7 @@ import { IExplorerService } from '../../files/browser/files.js';
|
||||
import { IViewsService } from '../../../services/views/common/viewsService.js';
|
||||
import { VIEW_ID as EXPLORER_VIEW_ID } from '../../files/common/files.js';
|
||||
import { IExtensionGalleryManifest, IExtensionGalleryManifestService } from '../../../../platform/extensionManagement/common/extensionGalleryManifest.js';
|
||||
import { IMarkdownRendererService } from '../../../../platform/markdown/browser/markdownRenderer.js';
|
||||
|
||||
export abstract class ExtensionWidget extends Disposable implements IExtensionContainer {
|
||||
private _extension: IExtension | null = null;
|
||||
@@ -998,7 +997,7 @@ export class ExtensionStatusWidget extends ExtensionWidget {
|
||||
constructor(
|
||||
private readonly container: HTMLElement,
|
||||
private readonly extensionStatusAction: ExtensionStatusAction,
|
||||
@IOpenerService private readonly openerService: IOpenerService,
|
||||
@IMarkdownRendererService private readonly markdownRendererService: IMarkdownRendererService,
|
||||
) {
|
||||
super();
|
||||
this.render();
|
||||
@@ -1023,11 +1022,7 @@ export class ExtensionStatusWidget extends ExtensionWidget {
|
||||
markdown.appendText(`\n`);
|
||||
}
|
||||
}
|
||||
const rendered = disposables.add(renderMarkdown(markdown, {
|
||||
actionHandler: (content) => {
|
||||
this.openerService.open(content, { allowCommands: true }).catch(onUnexpectedError);
|
||||
},
|
||||
}));
|
||||
const rendered = disposables.add(this.markdownRendererService.render(markdown));
|
||||
append(this.container, rendered.element);
|
||||
}
|
||||
this._onDidRender.fire();
|
||||
|
||||
@@ -24,14 +24,13 @@ import { McpServerStatusAction } from './mcpServerActions.js';
|
||||
import { reset } from '../../../../base/browser/dom.js';
|
||||
import { mcpLicenseIcon, mcpServerIcon, mcpServerRemoteIcon, mcpServerWorkspaceIcon, mcpStarredIcon } from './mcpServerIcons.js';
|
||||
import { MarkdownString } from '../../../../base/common/htmlContent.js';
|
||||
import { renderMarkdown } from '../../../../base/browser/markdownRenderer.js';
|
||||
import { onUnexpectedError } from '../../../../base/common/errors.js';
|
||||
import { ExtensionHoverOptions, ExtensionIconBadge } from '../../extensions/browser/extensionsWidgets.js';
|
||||
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
|
||||
import { LocalMcpServerScope } from '../../../services/mcp/common/mcpWorkbenchManagementService.js';
|
||||
import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';
|
||||
import { registerColor } from '../../../../platform/theme/common/colorUtils.js';
|
||||
import { textLinkForeground } from '../../../../platform/theme/common/colorRegistry.js';
|
||||
import { IMarkdownRendererService } from '../../../../platform/markdown/browser/markdownRenderer.js';
|
||||
|
||||
export abstract class McpServerWidget extends Disposable implements IMcpServerContainer {
|
||||
private _mcpServer: IWorkbenchMcpServer | null = null;
|
||||
@@ -451,7 +450,7 @@ export class McpServerStatusWidget extends McpServerWidget {
|
||||
constructor(
|
||||
private readonly container: HTMLElement,
|
||||
private readonly extensionStatusAction: McpServerStatusAction,
|
||||
@IOpenerService private readonly openerService: IOpenerService,
|
||||
@IMarkdownRendererService private readonly markdownRendererService: IMarkdownRendererService,
|
||||
) {
|
||||
super();
|
||||
this.render();
|
||||
@@ -476,11 +475,7 @@ export class McpServerStatusWidget extends McpServerWidget {
|
||||
markdown.appendText(`\n`);
|
||||
}
|
||||
}
|
||||
const rendered = disposables.add(renderMarkdown(markdown, {
|
||||
actionHandler: (content) => {
|
||||
this.openerService.open(content, { allowCommands: true }).catch(onUnexpectedError);
|
||||
}
|
||||
}));
|
||||
const rendered = disposables.add(this.markdownRendererService.render(markdown));
|
||||
dom.append(this.container, rendered.element);
|
||||
}
|
||||
this._onDidRender.fire();
|
||||
|
||||
@@ -32,7 +32,6 @@ import { PublisherWidget, StarredWidget, McpServerIconWidget, McpServerHoverWidg
|
||||
import { ActionRunner, IAction, Separator } from '../../../../base/common/actions.js';
|
||||
import { IActionViewItemOptions } from '../../../../base/browser/ui/actionbar/actionViewItems.js';
|
||||
import { IAllowedMcpServersService, mcpGalleryServiceEnablementConfig, mcpGalleryServiceUrlConfig } from '../../../../platform/mcp/common/mcpManagement.js';
|
||||
import { URI } from '../../../../base/common/uri.js';
|
||||
import { ThemeIcon } from '../../../../base/common/themables.js';
|
||||
import { alert } from '../../../../base/browser/ui/aria/aria.js';
|
||||
import { Registry } from '../../../../platform/registry/common/platform.js';
|
||||
@@ -40,7 +39,6 @@ import { IWorkbenchContribution } from '../../../common/contributions.js';
|
||||
import { SyncDescriptor } from '../../../../platform/instantiation/common/descriptors.js';
|
||||
import { DefaultViewsContext, SearchMcpServersContext } from '../../extensions/common/extensions.js';
|
||||
import { VIEW_CONTAINER } from '../../extensions/browser/extensions.contribution.js';
|
||||
import { renderMarkdown } from '../../../../base/browser/markdownRenderer.js';
|
||||
import { ChatContextKeys } from '../../chat/common/chatContextKeys.js';
|
||||
import { Button } from '../../../../base/browser/ui/button/button.js';
|
||||
import { defaultButtonStyles } from '../../../../platform/theme/browser/defaultStyles.js';
|
||||
@@ -53,6 +51,7 @@ import { IPagedRenderer } from '../../../../base/browser/ui/list/listPaging.js';
|
||||
import { IMcpGalleryManifestService, McpGalleryManifestStatus } from '../../../../platform/mcp/common/mcpGalleryManifest.js';
|
||||
import { ProductQualityContext } from '../../../../platform/contextkey/common/contextkeys.js';
|
||||
import { SeverityIcon } from '../../../../base/browser/ui/severityIcon/severityIcon.js';
|
||||
import { IMarkdownRendererService } from '../../../../platform/markdown/browser/markdownRenderer.js';
|
||||
|
||||
export interface McpServerListViewOptions {
|
||||
showWelcome?: boolean;
|
||||
@@ -100,6 +99,7 @@ export class McpServersListView extends AbstractExtensionsListView<IWorkbenchMcp
|
||||
@IMcpWorkbenchService private readonly mcpWorkbenchService: IMcpWorkbenchService,
|
||||
@IMcpGalleryManifestService protected readonly mcpGalleryManifestService: IMcpGalleryManifestService,
|
||||
@IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService,
|
||||
@IMarkdownRendererService protected readonly markdownRendererService: IMarkdownRendererService,
|
||||
) {
|
||||
super(options, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, hoverService);
|
||||
}
|
||||
@@ -263,17 +263,14 @@ export class McpServersListView extends AbstractExtensionsListView<IWorkbenchMcp
|
||||
|
||||
const settingsCommandLink = markdownCommandLink({ id: 'workbench.action.openSettings', arguments: [`@id:${mcpGalleryServiceEnablementConfig}`], title: mcpGalleryServiceEnablementConfig, tooltip: localize('mcp.welcome.settings.tooltip', "Open Settings") }).toString();
|
||||
const description = dom.append(welcomeContent, dom.$('.mcp-welcome-description'));
|
||||
const markdownResult = this._register(renderMarkdown(new MarkdownString(
|
||||
localize('mcp.welcome.descriptionWithLink', "Browse and install [Model Context Protocol (MCP) servers](https://code.visualstudio.com/docs/copilot/customization/mcp-servers) directly from VS Code to extend agent mode with extra tools for connecting to databases, invoking APIs and performing specialized tasks."),
|
||||
true,
|
||||
)
|
||||
.appendMarkdown('\n\n')
|
||||
.appendMarkdown(localize('mcp.gallery.enableDialog.setting', "This feature is currently in preview. You can disable it anytime using the setting {0}.", settingsCommandLink)),
|
||||
{
|
||||
actionHandler: (content: string) => {
|
||||
this.openerService.open(URI.parse(content), { allowCommands: ['workbench.action.openSettings'] });
|
||||
}
|
||||
}));
|
||||
const markdownResult = this._register(this.markdownRendererService.render(
|
||||
new MarkdownString(
|
||||
localize('mcp.welcome.descriptionWithLink', "Browse and install [Model Context Protocol (MCP) servers](https://code.visualstudio.com/docs/copilot/customization/mcp-servers) directly from VS Code to extend agent mode with extra tools for connecting to databases, invoking APIs and performing specialized tasks."),
|
||||
{ isTrusted: { enabledCommands: ['workbench.action.openSettings'] } },
|
||||
)
|
||||
.appendMarkdown('\n\n')
|
||||
.appendMarkdown(localize('mcp.gallery.enableDialog.setting', "This feature is currently in preview. You can disable it anytime using the setting {0}.", settingsCommandLink)),
|
||||
));
|
||||
description.appendChild(markdownResult.element);
|
||||
|
||||
const buttonContainer = dom.append(welcomeContent, dom.$('.mcp-welcome-button-container'));
|
||||
|
||||
Reference in New Issue
Block a user