Only show paste as html when it is explicitly requested (#202039)

Fixes #202013
This commit is contained in:
Matt Bierner 2024-01-08 12:32:02 -08:00 committed by GitHub
parent 66023e11e6
commit 88a6ed6d9b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 26 additions and 14 deletions

View file

@ -812,6 +812,14 @@ export interface DocumentPasteEdit {
additionalEdit?: WorkspaceEdit;
}
/**
* @internal
*/
export interface DocumentPasteContext {
readonly only?: string;
readonly trigger: 'explicit' | 'implicit';
}
/**
* @internal
*/
@ -824,7 +832,7 @@ export interface DocumentPasteEditProvider {
prepareDocumentPaste?(model: model.ITextModel, ranges: readonly IRange[], dataTransfer: IReadonlyVSDataTransfer, token: CancellationToken): Promise<undefined | IReadonlyVSDataTransfer>;
provideDocumentPasteEdits?(model: model.ITextModel, ranges: readonly IRange[], dataTransfer: IReadonlyVSDataTransfer, token: CancellationToken): Promise<DocumentPasteEdit | undefined>;
provideDocumentPasteEdits?(model: model.ITextModel, ranges: readonly IRange[], dataTransfer: IReadonlyVSDataTransfer, context: DocumentPasteContext, token: CancellationToken): Promise<DocumentPasteEdit | undefined>;
}
/**

View file

@ -20,7 +20,7 @@ import { EditorOption } from 'vs/editor/common/config/editorOptions';
import { IRange, Range } from 'vs/editor/common/core/range';
import { Selection } from 'vs/editor/common/core/selection';
import { Handler, IEditorContribution, PastePayload } from 'vs/editor/common/editorCommon';
import { DocumentPasteEdit, DocumentPasteEditProvider } from 'vs/editor/common/languages';
import { DocumentPasteContext, DocumentPasteEdit, DocumentPasteEditProvider } from 'vs/editor/common/languages';
import { ITextModel } from 'vs/editor/common/model';
import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures';
import { createCombinedWorkspaceEdit, sortEditsByYieldTo } from 'vs/editor/contrib/dropOrPasteInto/browser/edit';
@ -252,13 +252,13 @@ export class CopyPasteController extends Disposable implements IEditorContributi
e.stopImmediatePropagation();
if (this._pasteAsActionContext) {
this.showPasteAsPick(this._pasteAsActionContext.preferredId, allProviders, selections, dataTransfer, metadata);
this.showPasteAsPick(this._pasteAsActionContext.preferredId, allProviders, selections, dataTransfer, metadata, { trigger: 'explicit', only: this._pasteAsActionContext.preferredId });
} else {
this.doPasteInline(allProviders, selections, dataTransfer, metadata);
this.doPasteInline(allProviders, selections, dataTransfer, metadata, { trigger: 'implicit' });
}
}
private doPasteInline(allProviders: readonly DocumentPasteEditProvider[], selections: readonly Selection[], dataTransfer: VSDataTransfer, metadata: CopyMetadata | undefined): void {
private doPasteInline(allProviders: readonly DocumentPasteEditProvider[], selections: readonly Selection[], dataTransfer: VSDataTransfer, metadata: CopyMetadata | undefined, context: DocumentPasteContext): void {
const p = createCancelablePromise(async (token) => {
const editor = this._editor;
if (!editor.hasModel()) {
@ -282,7 +282,7 @@ export class CopyPasteController extends Disposable implements IEditorContributi
return;
}
const providerEdits = await this.getPasteEdits(supportedProviders, dataTransfer, model, selections, tokenSource.token);
const providerEdits = await this.getPasteEdits(supportedProviders, dataTransfer, model, selections, context, tokenSource.token);
if (tokenSource.token.isCancellationRequested) {
return;
}
@ -311,7 +311,7 @@ export class CopyPasteController extends Disposable implements IEditorContributi
this._currentPasteOperation = p;
}
private showPasteAsPick(preferredId: string | undefined, allProviders: readonly DocumentPasteEditProvider[], selections: readonly Selection[], dataTransfer: VSDataTransfer, metadata: CopyMetadata | undefined): void {
private showPasteAsPick(preferredId: string | undefined, allProviders: readonly DocumentPasteEditProvider[], selections: readonly Selection[], dataTransfer: VSDataTransfer, metadata: CopyMetadata | undefined, context: DocumentPasteContext): void {
const p = createCancelablePromise(async (token) => {
const editor = this._editor;
if (!editor.hasModel()) {
@ -333,7 +333,7 @@ export class CopyPasteController extends Disposable implements IEditorContributi
supportedProviders = supportedProviders.filter(edit => edit.id === preferredId);
}
const providerEdits = await this.getPasteEdits(supportedProviders, dataTransfer, model, selections, tokenSource.token);
const providerEdits = await this.getPasteEdits(supportedProviders, dataTransfer, model, selections, context, tokenSource.token);
if (tokenSource.token.isCancellationRequested) {
return;
}
@ -437,11 +437,11 @@ export class CopyPasteController extends Disposable implements IEditorContributi
}
}
private async getPasteEdits(providers: readonly DocumentPasteEditProvider[], dataTransfer: VSDataTransfer, model: ITextModel, selections: readonly Selection[], token: CancellationToken): Promise<Array<DocumentPasteEdit & { providerId: string }>> {
private async getPasteEdits(providers: readonly DocumentPasteEditProvider[], dataTransfer: VSDataTransfer, model: ITextModel, selections: readonly Selection[], context: DocumentPasteContext, token: CancellationToken): Promise<Array<DocumentPasteEdit & { providerId: string }>> {
const results = await raceCancellation(
Promise.all(providers.map(async provider => {
try {
const edit = await provider.provideDocumentPasteEdits?.(model, selections, dataTransfer, token);
const edit = await provider.provideDocumentPasteEdits?.(model, selections, dataTransfer, context, token);
if (edit) {
return { ...edit, providerId: provider.id };
}

View file

@ -13,7 +13,7 @@ import { relativePath } from 'vs/base/common/resources';
import { URI } from 'vs/base/common/uri';
import { IPosition } from 'vs/editor/common/core/position';
import { IRange } from 'vs/editor/common/core/range';
import { DocumentOnDropEdit, DocumentOnDropEditProvider, DocumentPasteEdit, DocumentPasteEditProvider } from 'vs/editor/common/languages';
import { DocumentOnDropEdit, DocumentOnDropEditProvider, DocumentPasteContext, DocumentPasteEdit, DocumentPasteEditProvider } from 'vs/editor/common/languages';
import { ITextModel } from 'vs/editor/common/model';
import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures';
import { localize } from 'vs/nls';
@ -27,7 +27,7 @@ abstract class SimplePasteAndDropProvider implements DocumentOnDropEditProvider,
abstract readonly dropMimeTypes: readonly string[] | undefined;
abstract readonly pasteMimeTypes: readonly string[];
async provideDocumentPasteEdits(_model: ITextModel, _ranges: readonly IRange[], dataTransfer: IReadonlyVSDataTransfer, token: CancellationToken): Promise<DocumentPasteEdit | undefined> {
async provideDocumentPasteEdits(_model: ITextModel, _ranges: readonly IRange[], dataTransfer: IReadonlyVSDataTransfer, context: DocumentPasteContext, token: CancellationToken): Promise<DocumentPasteEdit | undefined> {
const edit = await this.getEdit(dataTransfer, token);
return edit ? { insertText: edit.insertText, label: edit.label, detail: edit.detail, handledMimeType: edit.handledMimeType, yieldTo: edit.yieldTo } : undefined;
}
@ -160,7 +160,11 @@ class PasteHtmlProvider implements DocumentPasteEditProvider {
private readonly _yieldTo = [{ mimeType: Mimes.text }];
async provideDocumentPasteEdits(_model: ITextModel, _ranges: readonly IRange[], dataTransfer: IReadonlyVSDataTransfer, token: CancellationToken): Promise<DocumentPasteEdit | undefined> {
async provideDocumentPasteEdits(_model: ITextModel, _ranges: readonly IRange[], dataTransfer: IReadonlyVSDataTransfer, context: DocumentPasteContext, token: CancellationToken): Promise<DocumentPasteEdit | undefined> {
if (context.trigger !== 'explicit' && context.only !== this.id) {
return;
}
const entry = dataTransfer.get('text/html');
const htmlText = await entry?.asString();
if (!htmlText || token.isCancellationRequested) {

View file

@ -1009,7 +1009,7 @@ class MainThreadPasteEditProvider implements languages.DocumentPasteEditProvider
}
if (metadata.supportsPaste) {
this.provideDocumentPasteEdits = async (model: ITextModel, selections: Selection[], dataTransfer: IReadonlyVSDataTransfer, token: CancellationToken) => {
this.provideDocumentPasteEdits = async (model: ITextModel, selections: Selection[], dataTransfer: IReadonlyVSDataTransfer, context: languages.DocumentPasteContext, token: CancellationToken) => {
const request = this.dataTransfers.add(dataTransfer);
try {
const dataTransferDto = await typeConvert.DataTransfer.from(dataTransfer);