mirror of
https://github.com/microsoft/vscode.git
synced 2025-12-24 04:09:28 +00:00
Support more image/video/audio types for markdown copy into files
Fixes #239016
This commit is contained in:
@@ -6,7 +6,8 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { Utils } from 'vscode-uri';
|
||||
import { Command } from '../commandManager';
|
||||
import { createUriListSnippet, linkEditKind, mediaFileExtensions } from '../languageFeatures/copyFiles/shared';
|
||||
import { createUriListSnippet, linkEditKind } from '../languageFeatures/copyFiles/shared';
|
||||
import { mediaFileExtensions } from '../util/mimes';
|
||||
import { coalesce } from '../util/arrays';
|
||||
import { getParentDocumentUri } from '../util/document';
|
||||
import { Schemes } from '../util/schemes';
|
||||
|
||||
@@ -7,12 +7,12 @@ import * as vscode from 'vscode';
|
||||
import { IMdParser } from '../../markdownEngine';
|
||||
import { coalesce } from '../../util/arrays';
|
||||
import { getParentDocumentUri } from '../../util/document';
|
||||
import { Mime, mediaMimes } from '../../util/mimes';
|
||||
import { getMediaKindForMime, MediaKind, Mime, rootMediaMimesTypes } from '../../util/mimes';
|
||||
import { Schemes } from '../../util/schemes';
|
||||
import { NewFilePathGenerator } from './newFilePathGenerator';
|
||||
import { DropOrPasteEdit, createInsertUriListEdit, createUriListSnippet, getSnippetLabelAndKind, baseLinkEditKind, linkEditKind, audioEditKind, videoEditKind, imageEditKind } from './shared';
|
||||
import { InsertMarkdownLink, shouldInsertMarkdownLinkByDefault } from './smartDropOrPaste';
|
||||
import { UriList } from '../../util/uriList';
|
||||
import { NewFilePathGenerator } from './newFilePathGenerator';
|
||||
import { audioEditKind, baseLinkEditKind, createInsertUriListEdit, createUriListSnippet, DropOrPasteEdit, getSnippetLabelAndKind, imageEditKind, linkEditKind, videoEditKind } from './shared';
|
||||
import { InsertMarkdownLink, shouldInsertMarkdownLinkByDefault } from './smartDropOrPaste';
|
||||
|
||||
enum CopyFilesSettings {
|
||||
Never = 'never',
|
||||
@@ -33,7 +33,7 @@ class ResourcePasteOrDropProvider implements vscode.DocumentPasteEditProvider, v
|
||||
public static readonly mimeTypes = [
|
||||
Mime.textUriList,
|
||||
'files',
|
||||
...mediaMimes,
|
||||
...Object.values(rootMediaMimesTypes).map(type => `${type}/*`),
|
||||
];
|
||||
|
||||
private readonly _yieldTo = [
|
||||
@@ -206,12 +206,14 @@ class ResourcePasteOrDropProvider implements vscode.DocumentPasteEditProvider, v
|
||||
|
||||
interface FileEntry {
|
||||
readonly uri: vscode.Uri;
|
||||
readonly kind: MediaKind;
|
||||
readonly newFile?: { readonly contents: vscode.DataTransferFile; readonly overwrite: boolean };
|
||||
}
|
||||
|
||||
const pathGenerator = new NewFilePathGenerator();
|
||||
const fileEntries = coalesce(await Promise.all(Array.from(dataTransfer, async ([mime, item]): Promise<FileEntry | undefined> => {
|
||||
if (!mediaMimes.has(mime)) {
|
||||
const mediaKind = getMediaKindForMime(mime);
|
||||
if (!mediaKind) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -224,7 +226,7 @@ class ResourcePasteOrDropProvider implements vscode.DocumentPasteEditProvider, v
|
||||
// If the file is already in a workspace, we don't want to create a copy of it
|
||||
const workspaceFolder = vscode.workspace.getWorkspaceFolder(file.uri);
|
||||
if (workspaceFolder) {
|
||||
return { uri: file.uri };
|
||||
return { uri: file.uri, kind: mediaKind };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,7 +234,7 @@ class ResourcePasteOrDropProvider implements vscode.DocumentPasteEditProvider, v
|
||||
if (!newFile) {
|
||||
return;
|
||||
}
|
||||
return { uri: newFile.uri, newFile: { contents: file, overwrite: newFile.overwrite } };
|
||||
return { uri: newFile.uri, kind: mediaKind, newFile: { contents: file, overwrite: newFile.overwrite } };
|
||||
})));
|
||||
if (!fileEntries.length) {
|
||||
return;
|
||||
|
||||
@@ -11,6 +11,7 @@ import { getDocumentDir } from '../../util/document';
|
||||
import { Schemes } from '../../util/schemes';
|
||||
import { UriList } from '../../util/uriList';
|
||||
import { resolveSnippet } from './snippets';
|
||||
import { mediaFileExtensions, MediaKind } from '../../util/mimes';
|
||||
|
||||
/** Base kind for any sort of markdown link, including both path and media links */
|
||||
export const baseLinkEditKind = vscode.DocumentDropOrPasteEditKind.Empty.append('markdown', 'link');
|
||||
@@ -22,39 +23,6 @@ export const imageEditKind = baseLinkEditKind.append('image');
|
||||
export const audioEditKind = baseLinkEditKind.append('audio');
|
||||
export const videoEditKind = baseLinkEditKind.append('video');
|
||||
|
||||
enum MediaKind {
|
||||
Image,
|
||||
Video,
|
||||
Audio,
|
||||
}
|
||||
|
||||
export const mediaFileExtensions = new Map<string, MediaKind>([
|
||||
// Images
|
||||
['avif', MediaKind.Image],
|
||||
['bmp', MediaKind.Image],
|
||||
['gif', MediaKind.Image],
|
||||
['ico', MediaKind.Image],
|
||||
['jpe', MediaKind.Image],
|
||||
['jpeg', MediaKind.Image],
|
||||
['jpg', MediaKind.Image],
|
||||
['png', MediaKind.Image],
|
||||
['psd', MediaKind.Image],
|
||||
['svg', MediaKind.Image],
|
||||
['tga', MediaKind.Image],
|
||||
['tif', MediaKind.Image],
|
||||
['tiff', MediaKind.Image],
|
||||
['webp', MediaKind.Image],
|
||||
|
||||
// Videos
|
||||
['ogg', MediaKind.Video],
|
||||
['mp4', MediaKind.Video],
|
||||
|
||||
// Audio Files
|
||||
['mp3', MediaKind.Audio],
|
||||
['aac', MediaKind.Audio],
|
||||
['wav', MediaKind.Audio],
|
||||
]);
|
||||
|
||||
export function getSnippetLabelAndKind(counter: { readonly insertedAudioCount: number; readonly insertedVideoCount: number; readonly insertedImageCount: number; readonly insertedLinkCount: number }): {
|
||||
label: string;
|
||||
kind: vscode.DocumentDropOrPasteEditKind;
|
||||
@@ -207,6 +175,7 @@ export function createUriListSnippet(
|
||||
uris: ReadonlyArray<{
|
||||
readonly uri: vscode.Uri;
|
||||
readonly str?: string;
|
||||
readonly kind?: MediaKind;
|
||||
}>,
|
||||
options?: UriListSnippetOptions,
|
||||
): UriSnippet | undefined {
|
||||
@@ -229,7 +198,7 @@ export function createUriListSnippet(
|
||||
uris.forEach((uri, i) => {
|
||||
const mdPath = (!options?.preserveAbsoluteUris ? getRelativeMdPath(documentDir, uri.uri) : undefined) ?? uri.str ?? uri.uri.toString();
|
||||
|
||||
const desiredKind = getDesiredLinkKind(uri.uri, options);
|
||||
const desiredKind = getDesiredLinkKind(uri.uri, uri.kind, options);
|
||||
|
||||
if (desiredKind === DesiredLinkKind.Link) {
|
||||
insertedLinkCount++;
|
||||
@@ -276,7 +245,7 @@ enum DesiredLinkKind {
|
||||
Audio,
|
||||
}
|
||||
|
||||
function getDesiredLinkKind(uri: vscode.Uri, options: UriListSnippetOptions | undefined): DesiredLinkKind {
|
||||
function getDesiredLinkKind(uri: vscode.Uri, uriFileKind: MediaKind | undefined, options: UriListSnippetOptions | undefined): DesiredLinkKind {
|
||||
if (options?.linkKindHint instanceof vscode.DocumentDropOrPasteEditKind) {
|
||||
if (linkEditKind.contains(options.linkKindHint)) {
|
||||
return DesiredLinkKind.Link;
|
||||
@@ -289,6 +258,14 @@ function getDesiredLinkKind(uri: vscode.Uri, options: UriListSnippetOptions | un
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof uriFileKind !== 'undefined') {
|
||||
switch (uriFileKind) {
|
||||
case MediaKind.Video: return DesiredLinkKind.Video;
|
||||
case MediaKind.Audio: return DesiredLinkKind.Audio;
|
||||
case MediaKind.Image: return DesiredLinkKind.Image;
|
||||
}
|
||||
}
|
||||
|
||||
const normalizedExt = URI.Utils.extname(uri).toLowerCase().replace('.', '');
|
||||
if (options?.linkKindHint === 'media' || mediaFileExtensions.has(normalizedExt)) {
|
||||
switch (mediaFileExtensions.get(normalizedExt)) {
|
||||
|
||||
@@ -8,16 +8,52 @@ export const Mime = {
|
||||
textPlain: 'text/plain',
|
||||
} as const;
|
||||
|
||||
export const mediaMimes = new Set([
|
||||
'image/avif',
|
||||
'image/bmp',
|
||||
'image/gif',
|
||||
'image/jpeg',
|
||||
'image/png',
|
||||
'image/webp',
|
||||
'video/mp4',
|
||||
'video/ogg',
|
||||
'audio/mpeg',
|
||||
'audio/aac',
|
||||
'audio/x-wav',
|
||||
export const rootMediaMimesTypes = Object.freeze({
|
||||
image: 'image',
|
||||
audio: 'audio',
|
||||
video: 'video',
|
||||
});
|
||||
|
||||
export enum MediaKind {
|
||||
Image = 1,
|
||||
Video,
|
||||
Audio
|
||||
}
|
||||
|
||||
export function getMediaKindForMime(mime: string): MediaKind | undefined {
|
||||
const root = mime.toLowerCase().split('/').at(0);
|
||||
switch (root) {
|
||||
case 'image': return MediaKind.Image;
|
||||
case 'video': return MediaKind.Video;
|
||||
case 'audio': return MediaKind.Audio;
|
||||
default: return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export const mediaFileExtensions = new Map<string, MediaKind>([
|
||||
// Images
|
||||
['avif', MediaKind.Image],
|
||||
['bmp', MediaKind.Image],
|
||||
['gif', MediaKind.Image],
|
||||
['ico', MediaKind.Image],
|
||||
['jpe', MediaKind.Image],
|
||||
['jpeg', MediaKind.Image],
|
||||
['jpg', MediaKind.Image],
|
||||
['png', MediaKind.Image],
|
||||
['psd', MediaKind.Image],
|
||||
['svg', MediaKind.Image],
|
||||
['tga', MediaKind.Image],
|
||||
['tif', MediaKind.Image],
|
||||
['tiff', MediaKind.Image],
|
||||
['webp', MediaKind.Image],
|
||||
|
||||
// Videos
|
||||
['ogg', MediaKind.Video],
|
||||
['mp4', MediaKind.Video],
|
||||
['mov', MediaKind.Video],
|
||||
|
||||
// Audio Files
|
||||
['mp3', MediaKind.Audio],
|
||||
['aac', MediaKind.Audio],
|
||||
['wav', MediaKind.Audio],
|
||||
]);
|
||||
|
||||
Reference in New Issue
Block a user