// Copyright 2018-2026 the Deno authors. MIT license. // This module is browser compatible. import { parseMediaType } from "./parse_media_type.ts"; import { getCharset } from "./get_charset.ts"; import { formatMediaType } from "./format_media_type.ts"; import type { db } from "./_db.ts"; import { typeByExtension } from "./type_by_extension.ts"; /** MIME-types database. */ // deno-lint-ignore deno-style-guide/naming-convention export type DB = typeof db; /** Maps content types to their corresponding file extensions. */ export type ContentTypeToExtension = { /** * Maps each content type key to its corresponding file extension. */ [K in keyof DB]: DB[K] extends { "extensions": readonly string[] } ? DB[K]["extensions"][number] : never; }; /** Known extension or type. Used in {@linkcode contentType}. */ export type KnownExtensionOrType = | keyof ContentTypeToExtension | ContentTypeToExtension[keyof ContentTypeToExtension] | `.${ContentTypeToExtension[keyof ContentTypeToExtension]}`; /** * Returns the full `Content-Type` or `Content-Disposition` header value for the * given extension or media type. * * The function will treat the `extensionOrType` as a media type when it * contains a `/`, otherwise it will process it as an extension, with or without * the leading `.`. * * Returns `undefined` if unable to resolve the media type. * * @typeParam T Type of the extension or media type to resolve. * * @param extensionOrType The extension or media type to resolve. * * @returns The full `Content-Type` or `Content-Disposition` header value, or * `undefined` if unable to resolve the media type. * * @example Usage * ```ts * import { contentType } from "../media-types/content_type.ts"; * import { assertEquals } from "../assert/mod.ts"; * * assertEquals(contentType(".json"), "application/json; charset=UTF-8"); * assertEquals(contentType("text/html"), "text/html; charset=UTF-8"); * assertEquals(contentType("text/html; charset=UTF-8"), "text/html; charset=UTF-8"); * assertEquals(contentType("txt"), "text/plain; charset=UTF-8"); * assertEquals(contentType("foo"), undefined); * assertEquals(contentType("file.json"), undefined); * ``` */ export function contentType< // Workaround to autocomplete for parameters: https://github.com/microsoft/TypeScript/issues/29729#issuecomment-567871939 // deno-lint-ignore ban-types T extends (string & {}) | KnownExtensionOrType, >( extensionOrType: T, ): Lowercase extends KnownExtensionOrType ? string : string | undefined { try { const [mediaType, params = {}] = extensionOrType.includes("/") ? parseMediaType(extensionOrType) : [typeByExtension(extensionOrType), undefined]; if (!mediaType) { return undefined as Lowercase extends KnownExtensionOrType ? string : string | undefined; } if (!("charset" in params)) { const charset = getCharset(mediaType); if (charset) { params.charset = charset; } } return formatMediaType(mediaType, params); } catch { // just swallow returning undefined } return undefined as Lowercase extends KnownExtensionOrType ? string : string | undefined; }