Skip to content

Commit

Permalink
Merge pull request #239046 from mjbvz/gross-yak
Browse files Browse the repository at this point in the history
Support more image/video/audio types for markdown copy into files
  • Loading branch information
mjbvz authored Feb 4, 2025
2 parents 12acdea + f9213d7 commit 0252e92
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 { UriList } from '../../util/uriList';
import { NewFilePathGenerator } from './newFilePathGenerator';
import { DropOrPasteEdit, createInsertUriListEdit, createUriListSnippet, getSnippetLabelAndKind, baseLinkEditKind, linkEditKind, audioEditKind, videoEditKind, imageEditKind } from './shared';
import { audioEditKind, baseLinkEditKind, createInsertUriListEdit, createUriListSnippet, DropOrPasteEdit, getSnippetLabelAndKind, imageEditKind, linkEditKind, videoEditKind } from './shared';
import { InsertMarkdownLink, shouldInsertMarkdownLinkByDefault } from './smartDropOrPaste';
import { UriList } from '../../util/uriList';

enum CopyFilesSettings {
Never = 'never',
Expand All @@ -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 = [
Expand Down Expand Up @@ -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;
}

Expand All @@ -224,15 +226,15 @@ 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 };
}
}

const newFile = await pathGenerator.getNewFilePath(document, file, token);
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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand All @@ -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;
Expand Down Expand Up @@ -207,6 +175,7 @@ export function createUriListSnippet(
uris: ReadonlyArray<{
readonly uri: vscode.Uri;
readonly str?: string;
readonly kind?: MediaKind;
}>,
options?: UriListSnippetOptions,
): UriSnippet | undefined {
Expand All @@ -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++;
Expand Down Expand Up @@ -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;
Expand All @@ -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)) {
Expand Down
60 changes: 48 additions & 12 deletions extensions/markdown-language-features/src/util/mimes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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],
]);

0 comments on commit 0252e92

Please sign in to comment.