diff --git a/public/index/constants.js b/public/index/constants.js index b2a6970..b53b92a 100644 --- a/public/index/constants.js +++ b/public/index/constants.js @@ -17,6 +17,22 @@ /** @type {SupportedFileType[]} */ export const SUPPORTED_FILE_TYPES = [ + { + name: "GIF", + extensions: [".gif", "image/gif"], + mimeType: "image/gif", + route: "/gif", + mimeSniffPatterns: [ + { + bytes: [0x47, 0x49, 0x46, 0x38, 0x37, 0x61], + mask: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF], + }, + { + bytes: [0x47, 0x49, 0x46, 0x38, 0x39, 0x61], + mask: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF], + }, + ], + }, { name: "PNG", extensions: [".png", ".apng"], diff --git a/public/index/index.js b/public/index/index.js index 0c24bc2..410a0bd 100644 --- a/public/index/index.js +++ b/public/index/index.js @@ -17,13 +17,24 @@ const inputEl = /** @type {HTMLInputElement} */ ( ); const inputContainerEl = crel("p", {}, inputEl); -const supportedFileTypeNameString = SUPPORTED_FILE_TYPES - .map((t, index, array) => ( - (array.length > 1 && (index === array.length - 1)) - ? `and ${t.name}` - : t.name - )) - .join(", "); +const supportedFileTypeNameString = (() => { + switch (SUPPORTED_FILE_TYPES.length) { + case 0: + return "no"; + case 2: + return `${SUPPORTED_FILE_TYPES[0].name} and ${ + SUPPORTED_FILE_TYPES[1].name + }`; + default: + return SUPPORTED_FILE_TYPES + .map((t, index, array) => ( + (array.length > 1 && (index === array.length - 1)) + ? `and ${t.name}` + : t.name + )) + .join(", "); + } +})(); const labelParagraphEl = crel( "p", {}, diff --git a/test/index/routeFile.test.ts b/test/index/routeFile.test.ts index de1612f..b49a47a 100644 --- a/test/index/routeFile.test.ts +++ b/test/index/routeFile.test.ts @@ -2,13 +2,30 @@ import { assertEquals } from "assert"; import routeFile from "../../public/index/routeFile.js"; Deno.test("routes files correctly", async () => { - const PNG_SIGNATURE = new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10]); + const PNG_SIGNATURE = new Uint8Array([ + 0x89, + 0x50, + 0x4E, + 0x47, + 0x0D, + 0x0A, + 0x1A, + 0x0A, + ]); + const GIF87_SIGNATURE = new Uint8Array([0x47, 0x49, 0x46, 0x38, 0x37, 0x61]); + const GIF89_SIGNATURE = new Uint8Array([0x47, 0x49, 0x46, 0x38, 0x39, 0x61]); const testCases = new Map([ // No matching type [new File([], "foo"), null], [new File([], "foo.txt"), null], [new File([], "foo.txt", { type: "text/plain" }), null], + // GIF + [new File([], "foo", { type: "image/gif" }), "/gif"], + [new File([], "foo.gif"), "/gif"], + [new File([], "foo.gif", { type: "text/plain" }), "/gif"], + [new File([GIF87_SIGNATURE], "foo"), "/gif"], + [new File([GIF89_SIGNATURE], "foo"), "/gif"], // PNG [new File([], "foo", { type: "image/png" }), "/png"], [new File([], "foo.png"), "/png"],