Skip to main content


A module that assists in resolving media types and extensions.
Extremely Popular
Go to Latest
/*! * Ported from: and licensed as: * * (The MIT License) * * Copyright (c) 2014 Jonathan Ong <> * Copyright (c) 2015 Douglas Christopher Wilson <> * Copyright (c) 2020 the Deno authors * Copyright (c) 2020-2022 the oak authors * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * 'Software'), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
import { extname } from "";import { db } from "./db.ts";
const EXTRACT_TYPE_REGEXP = /^\s*([^;\s]*)(?:;|\s|$)/;const TEXT_TYPE_REGEXP = /^text\//i;
/** A map of extensions for a given media type */export const extensions = new Map<string, string[]>();
/** A map of the media type for a given extension */export const types = new Map<string, string>();
/** Internal function to populate the maps based on the Mime DB */function populateMaps( extensions: Map<string, string[]>, types: Map<string, string>,): void { const preference = ["nginx", "apache", undefined, "iana"];
for (const type of Object.keys(db)) { const mime = db[type]; const exts = mime.extensions;
if (!exts || !exts.length) { continue; }
extensions.set(type, exts);
for (const ext of exts) { const current = types.get(ext); if (current) { const from = preference.indexOf(db[current].source); const to = preference.indexOf(mime.source);
if ( current !== "application/octet-stream" && (from > to || (from === to && current.substr(0, 12) === "application/")) ) { continue; } }
types.set(ext, type); } }}
// Populate the maps upon module loadpopulateMaps(extensions, types);
/** Given a media type return any default charset string. Returns `undefined` * if not resolvable. */export function charset(type: string): string | undefined { const m = EXTRACT_TYPE_REGEXP.exec(type); if (!m) { return undefined; } const [match] = m; const mime = db[match.toLowerCase()];
if (mime && mime.charset) { return mime.charset; }
if (TEXT_TYPE_REGEXP.test(match)) { return "UTF-8"; }
return undefined;}
/** Given an extension, lookup the appropriate media type for that extension. * Likely you should be using `contentType()` though instead. */export function lookup(path: string): string | undefined { const extension = extname("x." + path) .toLowerCase() .substr(1);
return types.get(extension);}
/** Given an extension or media type, return the full `Content-Type` header * string. Returns `undefined` if not resolvable. */export function contentType(str: string): string | undefined { let mime = str.includes("/") ? str : lookup(str);
if (!mime) { return undefined; }
if (!mime.includes("charset")) { const cs = charset(mime); if (cs) { mime += `; charset=${cs.toLowerCase()}`; } }
return mime;}
/** Given a media type, return the most appropriate extension or return * `undefined` if there is none. */export function extension(type: string): string | undefined { const match = EXTRACT_TYPE_REGEXP.exec(type);
if (!match) { return undefined; }
const exts = extensions.get(match[1].toLowerCase());
if (!exts || !exts.length) { return undefined; }
return exts[0];}