Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .changeset/avif-media-uploads.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
"emdash": patch
"@emdash-cms/admin": patch
---

Fixes AVIF images being rejected with "File type not allowed" on upload. `image/avif` is back in the default media allowlist alongside PNG, JPEG, GIF, and WebP, so editors can upload `.avif` files again from the media library and from image fields that use the default allowlist.

The admin file picker now offers `.avif` files and renders their thumbnails, the built-in "Images" preset in a field's allowed-types editor includes AVIF, and `.avif` works as extension shorthand in a field's `allowedMimeTypes`.

SVG stays excluded from the default allowlist.
2 changes: 1 addition & 1 deletion docs/src/content/docs/guides/media-library.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ EmDash accepts these file types by default:

| Category | Extensions |
| --------- | ----------------------------------------------- |
| Images | `.jpg`, `.jpeg`, `.png`, `.gif`, `.webp` |
| Images | `.jpg`, `.jpeg`, `.png`, `.gif`, `.webp`, `.avif` |
| Documents | `.pdf` |
| Video | `.mp4`, `.webm`, `.mov` |
| Audio | `.mp3`, `.wav`, `.ogg` |
Expand Down
5 changes: 4 additions & 1 deletion packages/admin/src/components/AllowedTypesEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ interface Preset {
}

const PRESETS: ReadonlyArray<Preset> = [
{ key: "images", mimeTypes: ["image/png", "image/jpeg", "image/gif", "image/webp"] },
{
key: "images",
mimeTypes: ["image/png", "image/jpeg", "image/gif", "image/webp", "image/avif"],
},
{ key: "pdf", mimeTypes: ["application/pdf"] },
{
key: "documents",
Expand Down
10 changes: 8 additions & 2 deletions packages/admin/src/components/MediaUploadDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,19 @@ import * as React from "react";
import { formatFileSize } from "../lib/media-utils.js";

export const LOCAL_MEDIA_UPLOAD_ACCEPT =
"image/png,image/jpeg,image/gif,image/webp,video/*,audio/*,application/pdf";
"image/png,image/jpeg,image/gif,image/webp,image/avif,video/*,audio/*,application/pdf";

const DEFAULT_CONCURRENCY = 3;
const MAX_CONCURRENCY = 6;
const MAX_VISIBLE_ROWS = 100;
const MAX_PREVIEW_BYTES = 8 * 1024 * 1024;
const PREVIEW_MIME_TYPES = new Set(["image/jpeg", "image/png", "image/gif", "image/webp"]);
const PREVIEW_MIME_TYPES = new Set([
"image/jpeg",
"image/png",
"image/gif",
"image/webp",
"image/avif",
]);

type UploadStatus = "queued" | "uploading" | "complete" | "failed";

Expand Down
1 change: 1 addition & 0 deletions packages/admin/src/lib/mime-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export const EXTENSION_TO_MIME: Readonly<Record<string, string>> = {
".jpeg": "image/jpeg",
".gif": "image/gif",
".webp": "image/webp",
".avif": "image/avif",
".svg": "image/svg+xml",
".mp3": "audio/mpeg",
".wav": "audio/wav",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/api/handlers/media-allowlist.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const GLOBAL_UPLOAD_ALLOWLIST: readonly string[] = [
"image/jpeg",
"image/gif",
"image/webp",
"image/avif",
"video/",
"audio/",
"application/pdf",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/media/mime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export const EXTENSION_TO_MIME: Readonly<Record<string, string>> = {
".jpeg": "image/jpeg",
".gif": "image/gif",
".webp": "image/webp",
".avif": "image/avif",
".svg": "image/svg+xml",
".mp3": "audio/mpeg",
".wav": "audio/wav",
Expand Down
4 changes: 4 additions & 0 deletions packages/core/tests/unit/media/media-allowlist.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ describe("GLOBAL_UPLOAD_ALLOWLIST", () => {
expect(matchesMimeAllowlist("image/webp", GLOBAL_UPLOAD_ALLOWLIST)).toBe(true);
});

it("allows image/avif, which the media routes already serve inline", () => {
expect(matchesMimeAllowlist("image/avif", GLOBAL_UPLOAD_ALLOWLIST)).toBe(true);
});

it("still allows video, audio, and pdf", () => {
expect(matchesMimeAllowlist("video/mp4", GLOBAL_UPLOAD_ALLOWLIST)).toBe(true);
expect(matchesMimeAllowlist("audio/mpeg", GLOBAL_UPLOAD_ALLOWLIST)).toBe(true);
Expand Down
1 change: 1 addition & 0 deletions packages/core/tests/unit/media/mime.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ describe("expandExtensionShorthand", () => {
it("expands known dot-extensions", () => {
expect(expandExtensionShorthand(".pdf")).toBe("application/pdf");
expect(expandExtensionShorthand(".PDF")).toBe("application/pdf");
expect(expandExtensionShorthand(".avif")).toBe("image/avif");
expect(expandExtensionShorthand(".docx")).toBe(
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
);
Expand Down
Loading