"use strict";
|
const parse = require("./parser.js");
|
const serialize = require("./serializer.js");
|
const {
|
asciiLowercase,
|
solelyContainsHTTPTokenCodePoints,
|
soleyContainsHTTPQuotedStringTokenCodePoints
|
} = require("./utils.js");
|
|
module.exports = class MIMEType {
|
constructor(string) {
|
string = String(string);
|
const result = parse(string);
|
if (result === null) {
|
throw new Error(`Could not parse MIME type string "${string}"`);
|
}
|
|
this._type = result.type;
|
this._subtype = result.subtype;
|
this._parameters = new MIMETypeParameters(result.parameters);
|
}
|
|
static parse(string) {
|
try {
|
return new this(string);
|
} catch (e) {
|
return null;
|
}
|
}
|
|
get essence() {
|
return `${this.type}/${this.subtype}`;
|
}
|
|
get type() {
|
return this._type;
|
}
|
|
set type(value) {
|
value = asciiLowercase(String(value));
|
|
if (value.length === 0) {
|
throw new Error("Invalid type: must be a non-empty string");
|
}
|
if (!solelyContainsHTTPTokenCodePoints(value)) {
|
throw new Error(`Invalid type ${value}: must contain only HTTP token code points`);
|
}
|
|
this._type = value;
|
}
|
|
get subtype() {
|
return this._subtype;
|
}
|
|
set subtype(value) {
|
value = asciiLowercase(String(value));
|
|
if (value.length === 0) {
|
throw new Error("Invalid subtype: must be a non-empty string");
|
}
|
if (!solelyContainsHTTPTokenCodePoints(value)) {
|
throw new Error(`Invalid subtype ${value}: must contain only HTTP token code points`);
|
}
|
|
this._subtype = value;
|
}
|
|
get parameters() {
|
return this._parameters;
|
}
|
|
toString() {
|
// The serialize function works on both "MIME type records" (i.e. the results of parse) and on this class, since
|
// this class's interface is identical.
|
return serialize(this);
|
}
|
|
isJavaScript({ allowParameters = false } = {}) {
|
switch (this._type) {
|
case "text": {
|
switch (this._subtype) {
|
case "ecmascript":
|
case "javascript":
|
case "javascript1.0":
|
case "javascript1.1":
|
case "javascript1.2":
|
case "javascript1.3":
|
case "javascript1.4":
|
case "javascript1.5":
|
case "jscript":
|
case "livescript":
|
case "x-ecmascript":
|
case "x-javascript": {
|
return allowParameters || this._parameters.size === 0;
|
}
|
default: {
|
return false;
|
}
|
}
|
}
|
case "application": {
|
switch (this._subtype) {
|
case "ecmascript":
|
case "javascript":
|
case "x-ecmascript":
|
case "x-javascript": {
|
return allowParameters || this._parameters.size === 0;
|
}
|
default: {
|
return false;
|
}
|
}
|
}
|
default: {
|
return false;
|
}
|
}
|
}
|
isXML() {
|
return (this._subtype === "xml" && (this._type === "text" || this._type === "application")) ||
|
this._subtype.endsWith("+xml");
|
}
|
isHTML() {
|
return this._subtype === "html" && this._type === "text";
|
}
|
};
|
|
class MIMETypeParameters {
|
constructor(map) {
|
this._map = map;
|
}
|
|
get size() {
|
return this._map.size;
|
}
|
|
get(name) {
|
name = asciiLowercase(String(name));
|
return this._map.get(name);
|
}
|
|
has(name) {
|
name = asciiLowercase(String(name));
|
return this._map.has(name);
|
}
|
|
set(name, value) {
|
name = asciiLowercase(String(name));
|
value = String(value);
|
|
if (!solelyContainsHTTPTokenCodePoints(name)) {
|
throw new Error(`Invalid MIME type parameter name "${name}": only HTTP token code points are valid.`);
|
}
|
if (!soleyContainsHTTPQuotedStringTokenCodePoints(value)) {
|
throw new Error(`Invalid MIME type parameter value "${value}": only HTTP quoted-string token code points are ` +
|
`valid.`);
|
}
|
|
return this._map.set(name, value);
|
}
|
|
clear() {
|
this._map.clear();
|
}
|
|
delete(name) {
|
name = asciiLowercase(String(name));
|
return this._map.delete(name);
|
}
|
|
forEach(callbackFn, thisArg) {
|
this._map.forEach(callbackFn, thisArg);
|
}
|
|
keys() {
|
return this._map.keys();
|
}
|
|
values() {
|
return this._map.values();
|
}
|
|
entries() {
|
return this._map.entries();
|
}
|
|
[Symbol.iterator]() {
|
return this._map[Symbol.iterator]();
|
}
|
}
|