deno.land / x / deno@v1.28.2 / ext / web / 01_mimesniff.js
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
// @ts-check/// <reference path="../../core/internal.d.ts" />/// <reference path="../../core/lib.deno_core.d.ts" />/// <reference path="../web/internal.d.ts" />/// <reference path="../web/lib.deno_web.d.ts" />
"use strict";
((window) => { const { ArrayPrototypeIncludes, Map, MapPrototypeGet, MapPrototypeHas, MapPrototypeSet, RegExpPrototypeTest, StringPrototypeReplaceAll, StringPrototypeToLowerCase, } = window.__bootstrap.primordials; const { collectSequenceOfCodepoints, HTTP_WHITESPACE, HTTP_WHITESPACE_PREFIX_RE, HTTP_WHITESPACE_SUFFIX_RE, HTTP_QUOTED_STRING_TOKEN_POINT_RE, HTTP_TOKEN_CODE_POINT_RE, collectHttpQuotedString, } = window.__bootstrap.infra;
/** * @typedef MimeType * @property {string} type * @property {string} subtype * @property {Map<string,string>} parameters */
/** * @param {string} input * @returns {MimeType | null} */ function parseMimeType(input) { // 1. input = StringPrototypeReplaceAll(input, HTTP_WHITESPACE_PREFIX_RE, ""); input = StringPrototypeReplaceAll(input, HTTP_WHITESPACE_SUFFIX_RE, "");
// 2. let position = 0; const endOfInput = input.length;
// 3. const res1 = collectSequenceOfCodepoints( input, position, (c) => c != "\u002F", ); const type = res1.result; position = res1.position;
// 4. if (type === "" || !RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, type)) { return null; }
// 5. if (position >= endOfInput) return null;
// 6. position++;
// 7. const res2 = collectSequenceOfCodepoints( input, position, (c) => c != "\u003B", ); let subtype = res2.result; position = res2.position;
// 8. subtype = StringPrototypeReplaceAll(subtype, HTTP_WHITESPACE_SUFFIX_RE, "");
// 9. if ( subtype === "" || !RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, subtype) ) { return null; }
// 10. const mimeType = { type: StringPrototypeToLowerCase(type), subtype: StringPrototypeToLowerCase(subtype), /** @type {Map<string, string>} */ parameters: new Map(), };
// 11. while (position < endOfInput) { // 11.1. position++;
// 11.2. const res1 = collectSequenceOfCodepoints( input, position, (c) => ArrayPrototypeIncludes(HTTP_WHITESPACE, c), ); position = res1.position;
// 11.3. const res2 = collectSequenceOfCodepoints( input, position, (c) => c !== "\u003B" && c !== "\u003D", ); let parameterName = res2.result; position = res2.position;
// 11.4. parameterName = StringPrototypeToLowerCase(parameterName);
// 11.5. if (position < endOfInput) { if (input[position] == "\u003B") continue; position++; }
// 11.6. if (position >= endOfInput) break;
// 11.7. let parameterValue = null;
// 11.8. if (input[position] === "\u0022") { // 11.8.1. const res = collectHttpQuotedString(input, position, true); parameterValue = res.result; position = res.position;
// 11.8.2. position++; } else { // 11.9. // 11.9.1. const res = collectSequenceOfCodepoints( input, position, (c) => c !== "\u003B", ); parameterValue = res.result; position = res.position;
// 11.9.2. parameterValue = StringPrototypeReplaceAll( parameterValue, HTTP_WHITESPACE_SUFFIX_RE, "", );
// 11.9.3. if (parameterValue === "") continue; }
// 11.10. if ( parameterName !== "" && RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, parameterName) && RegExpPrototypeTest( HTTP_QUOTED_STRING_TOKEN_POINT_RE, parameterValue, ) && !MapPrototypeHas(mimeType.parameters, parameterName) ) { MapPrototypeSet(mimeType.parameters, parameterName, parameterValue); } }
// 12. return mimeType; }
/** * @param {MimeType} mimeType * @returns {string} */ function essence(mimeType) { return `${mimeType.type}/${mimeType.subtype}`; }
/** * @param {MimeType} mimeType * @returns {string} */ function serializeMimeType(mimeType) { let serialization = essence(mimeType); for (const param of mimeType.parameters) { serialization += `;${param[0]}=`; let value = param[1]; if (!RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, value)) { value = StringPrototypeReplaceAll(value, "\\", "\\\\"); value = StringPrototypeReplaceAll(value, '"', '\\"'); value = `"${value}"`; } serialization += value; } return serialization; }
/** * Part of the Fetch spec's "extract a MIME type" algorithm * (https://fetch.spec.whatwg.org/#concept-header-extract-mime-type). * @param {string[] | null} headerValues The result of getting, decoding and * splitting the "Content-Type" header. * @returns {MimeType | null} */ function extractMimeType(headerValues) { if (headerValues === null) return null;
let charset = null; let essence_ = null; let mimeType = null; for (const value of headerValues) { const temporaryMimeType = parseMimeType(value); if ( temporaryMimeType === null || essence(temporaryMimeType) == "*/*" ) { continue; } mimeType = temporaryMimeType; if (essence(mimeType) !== essence_) { charset = null; const newCharset = MapPrototypeGet(mimeType.parameters, "charset"); if (newCharset !== undefined) { charset = newCharset; } essence_ = essence(mimeType); } else { if ( !MapPrototypeHas(mimeType.parameters, "charset") && charset !== null ) { MapPrototypeSet(mimeType.parameters, "charset", charset); } } } return mimeType; }
window.__bootstrap.mimesniff = { parseMimeType, essence, serializeMimeType, extractMimeType, };})(this);
Version Info