@d1g1tal/media-type 4.0.1 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -24,34 +24,33 @@ var MediaType = (() => {
24
24
  });
25
25
 
26
26
  // src/utils.js
27
- var removeLeadingAndTrailingHTTPWhitespace = (string) => string.replace(/^[ \t\n\r]+/u, "").replace(/[ \t\n\r]+$/u, "");
28
- var removeTrailingHTTPWhitespace = (string) => string.replace(/[ \t\n\r]+$/u, "");
29
- var isHTTPWhitespaceChar = (char) => char === " " || char === " " || char === "\n" || char === "\r";
30
- var solelyContainsHTTPTokenCodePoints = (string) => /^[-!#$%&'*+.^_`|~A-Za-z0-9]*$/u.test(string);
31
- var solelyContainsHTTPQuotedStringTokenCodePoints = (string) => /^[\t\u0020-\u007E\u0080-\u00FF]*$/u.test(string);
32
- var asciiLowercase = (string) => string.replace(/[A-Z]/ug, (l) => l.toLowerCase());
27
+ var whitespaceCharacters = [" ", " ", "\n", "\r"];
28
+ var leadingWhitespace = /^[ \t\n\r]+/u;
29
+ var trailingWhitespace = /[ \t\n\r]+$/u;
30
+ var httpTokenCodePoints = /^[-!#$%&'*+.^_`|~A-Za-z0-9]*$/u;
31
+ var httpQuotedTokenCodePoints = /^[\t\u0020-\u007E\u0080-\u00FF]*$/u;
32
+ var removeLeadingAndTrailingHTTPWhitespace = (string) => string.replace(leadingWhitespace, "").replace(trailingWhitespace, "");
33
+ var removeTrailingHTTPWhitespace = (string) => string.replace(trailingWhitespace, "");
34
+ var isHTTPWhitespaceChar = (char) => whitespaceCharacters.includes(char);
35
+ var solelyContainsHTTPTokenCodePoints = (string) => httpTokenCodePoints.test(string);
36
+ var solelyContainsHTTPQuotedStringTokenCodePoints = (string) => httpQuotedTokenCodePoints.test(string);
37
+ var asciiLowercase = (string) => {
38
+ let result = "";
39
+ for (const [char, charCode = char.charCodeAt(0)] of string) {
40
+ result += charCode >= 65 && charCode <= 90 ? String.fromCharCode(charCode + 32) : char;
41
+ }
42
+ return result;
43
+ };
33
44
  var collectAnHTTPQuotedString = (input, position) => {
34
45
  let value = "";
35
- position++;
36
- while (true) {
37
- while (position < input.length && input[position] !== '"' && input[position] !== "\\") {
38
- value += input[position];
39
- ++position;
40
- }
41
- if (position >= input.length) {
46
+ for (let length = input.length, char; ++position < length; ) {
47
+ char = input[position];
48
+ if (char == "\\") {
49
+ value += ++position < length ? input[position] : char;
50
+ } else if (char == '"') {
42
51
  break;
43
- }
44
- const quoteOrBackslash = input[position];
45
- ++position;
46
- if (quoteOrBackslash === "\\") {
47
- if (position >= input.length) {
48
- value += "\\";
49
- break;
50
- }
51
- value += input[position];
52
- ++position;
53
52
  } else {
54
- break;
53
+ value += char;
55
54
  }
56
55
  }
57
56
  return [value, position];
@@ -59,18 +58,50 @@ var MediaType = (() => {
59
58
 
60
59
  // src/media-type-parameters.js
61
60
  var MediaTypeParameters = class {
62
- constructor(map) {
63
- this._map = map;
64
- }
61
+ /** @type {Map<string, string>} */
62
+ #map;
63
+ /**
64
+ * Create a new MediaTypeParameters instance.
65
+ *
66
+ * @param {Array<Array<string>>} entries An array of [name, value] tuples.
67
+ */
68
+ constructor(entries) {
69
+ this.#map = new Map(entries);
70
+ }
71
+ /**
72
+ * Gets the number of media type parameters.
73
+ *
74
+ * @returns {number} The number of media type parameters
75
+ */
65
76
  get size() {
66
- return this._map.size;
67
- }
77
+ return this.#map.size;
78
+ }
79
+ /**
80
+ * Gets the media type parameter value for the supplied name.
81
+ *
82
+ * @param {string} name The name of the media type parameter to retrieve.
83
+ * @returns {string} The media type parameter value.
84
+ */
68
85
  get(name) {
69
- return this._map.get(asciiLowercase(String(name)));
70
- }
86
+ return this.#map.get(asciiLowercase(String(name)));
87
+ }
88
+ /**
89
+ * Indicates whether the media type parameter with the specified name exists or not.
90
+ *
91
+ * @param {string} name The name of the media type parameter to check.
92
+ * @returns {boolean} true if the media type parameter exists, false otherwise.
93
+ */
71
94
  has(name) {
72
- return this._map.has(asciiLowercase(String(name)));
73
- }
95
+ return this.#map.has(asciiLowercase(String(name)));
96
+ }
97
+ /**
98
+ * Adds a new media type parameter using the specified name and value to the MediaTypeParameters.
99
+ * If an parameter with the same name already exists, the parameter will be updated.
100
+ *
101
+ * @param {string} name The name of the media type parameter to set.
102
+ * @param {string} value The media type parameter value.
103
+ * @returns {MediaTypeParameters} This instance.
104
+ */
74
105
  set(name, value) {
75
106
  name = asciiLowercase(String(name));
76
107
  value = String(value);
@@ -80,30 +111,84 @@ var MediaType = (() => {
80
111
  if (!solelyContainsHTTPQuotedStringTokenCodePoints(value)) {
81
112
  throw new Error(`Invalid media type parameter value "${value}": only HTTP quoted-string token code points are valid.`);
82
113
  }
83
- this._map.set(name, value);
114
+ this.#map.set(name, value);
84
115
  return this;
85
116
  }
117
+ /**
118
+ * Clears all the media type parameters.
119
+ */
86
120
  clear() {
87
- this._map.clear();
88
- }
121
+ this.#map.clear();
122
+ }
123
+ /**
124
+ * Removes the media type parameter using the specified name.
125
+ *
126
+ * @param {string} name The name of the media type parameter to delete.
127
+ * @returns {boolean} true if the parameter existed and has been removed, or false if the parameter does not exist.
128
+ */
89
129
  delete(name) {
90
130
  name = asciiLowercase(String(name));
91
- return this._map.delete(name);
92
- }
131
+ return this.#map.delete(name);
132
+ }
133
+ /**
134
+ * Executes a provided function once per each name/value pair in the MediaTypeParameters, in insertion order.
135
+ *
136
+ * @param {function(string, string): void} callback The function called on each iteration.
137
+ * @param {*} [thisArg] Optional object when binding 'this' to the callback.
138
+ */
93
139
  forEach(callback, thisArg) {
94
- this._map.forEach(callback, thisArg);
140
+ this.#map.forEach(callback, thisArg);
95
141
  }
142
+ /**
143
+ * Returns an iterable of parameter names.
144
+ *
145
+ * @returns {IterableIterator<string>} The {@link IterableIterator} of media type parameter names.
146
+ */
96
147
  keys() {
97
- return this._map.keys();
148
+ return this.#map.keys();
98
149
  }
150
+ /**
151
+ * Returns an iterable of parameter values.
152
+ *
153
+ * @returns {IterableIterator<string>} The {@link IterableIterator} of media type parameter values.
154
+ */
99
155
  values() {
100
- return this._map.values();
156
+ return this.#map.values();
101
157
  }
158
+ /**
159
+ * Returns an iterable of name, value pairs for every parameter entry in the media type parameters.
160
+ *
161
+ * @returns {IterableIterator<Array<Array<string>>>} The media type parameter entries.
162
+ */
102
163
  entries() {
103
- return this._map.entries();
164
+ return this.#map.entries();
104
165
  }
166
+ /**
167
+ * A method that returns the default iterator for the {@link MediaTypeParameters}. Called by the semantics of the for-of statement.
168
+ *
169
+ * @returns {Iterator<string, string, undefined>} The {@link Symbol.iterator} for the media type parameters.
170
+ */
105
171
  [Symbol.iterator]() {
106
- return this._map[Symbol.iterator]();
172
+ return this.#map[Symbol.iterator]();
173
+ }
174
+ /**
175
+ * Returns a string representation of the media type parameters.
176
+ * This method is called by the `String()` function.
177
+ *
178
+ * @example
179
+ * const parameters = new MediaTypeParameters(new Map([['charset', 'utf-8']]));
180
+ * String(parameters); // 'charset=utf-8'
181
+ * parameters.toString(); // 'charset=utf-8'
182
+ * parameters + ''; // 'charset=utf-8'
183
+ * `${parameters}`; // 'charset=utf-8'
184
+ * parameters[Symbol.toStringTag]; // 'MediaTypeParameters'
185
+ * parameters[Symbol.toStringTag](); // 'MediaTypeParameters'
186
+ * Object.prototype.toString.call(parameters); // '[object MediaTypeParameters]'
187
+ * parameters + ''; // 'charset=utf-8'
188
+ * @returns {string} The string representation of the media type parameters.
189
+ */
190
+ [Symbol.toStringTag]() {
191
+ return "MediaTypeParameters";
107
192
  }
108
193
  };
109
194
 
@@ -112,7 +197,7 @@ var MediaType = (() => {
112
197
  input = removeLeadingAndTrailingHTTPWhitespace(input);
113
198
  let position = 0;
114
199
  let type = "";
115
- while (position < input.length && input[position] !== "/") {
200
+ while (position < input.length && input[position] != "/") {
116
201
  type += input[position];
117
202
  ++position;
118
203
  }
@@ -124,7 +209,7 @@ var MediaType = (() => {
124
209
  }
125
210
  ++position;
126
211
  let subtype = "";
127
- while (position < input.length && input[position] !== ";") {
212
+ while (position < input.length && input[position] != ";") {
128
213
  subtype += input[position];
129
214
  ++position;
130
215
  }
@@ -143,26 +228,26 @@ var MediaType = (() => {
143
228
  ++position;
144
229
  }
145
230
  let parameterName = "";
146
- while (position < input.length && input[position] !== ";" && input[position] !== "=") {
231
+ while (position < input.length && input[position] != ";" && input[position] != "=") {
147
232
  parameterName += input[position];
148
233
  ++position;
149
234
  }
150
235
  parameterName = asciiLowercase(parameterName);
151
236
  if (position < input.length) {
152
- if (input[position] === ";") {
237
+ if (input[position] == ";") {
153
238
  continue;
154
239
  }
155
240
  ++position;
156
241
  }
157
242
  let parameterValue = null;
158
- if (input[position] === '"') {
243
+ if (input[position] == '"') {
159
244
  [parameterValue, position] = collectAnHTTPQuotedString(input, position);
160
- while (position < input.length && input[position] !== ";") {
245
+ while (position < input.length && input[position] != ";") {
161
246
  ++position;
162
247
  }
163
248
  } else {
164
249
  parameterValue = "";
165
- while (position < input.length && input[position] !== ";") {
250
+ while (position < input.length && input[position] != ";") {
166
251
  parameterValue += input[position];
167
252
  ++position;
168
253
  }
@@ -186,12 +271,9 @@ var MediaType = (() => {
186
271
  return serialization;
187
272
  }
188
273
  for (let [name, value] of mediaType.parameters) {
189
- serialization += ";";
190
- serialization += name;
191
- serialization += "=";
274
+ serialization += `;${name}=`;
192
275
  if (!solelyContainsHTTPTokenCodePoints(value) || value.length === 0) {
193
- value = value.replace(/(["\\])/ug, "\\$1");
194
- value = `"${value}"`;
276
+ value = `"${value.replace(/(["\\])/ug, "\\$1")}"`;
195
277
  }
196
278
  serialization += value;
197
279
  }
@@ -201,29 +283,56 @@ var MediaType = (() => {
201
283
 
202
284
  // src/media-type.js
203
285
  var MediaType = class {
204
- constructor(string) {
205
- string = String(string);
206
- const result = parser_default(string);
207
- if (result === null) {
208
- throw new Error(`Could not parse media type string '${string}'`);
209
- }
210
- this._type = result.type;
211
- this._subtype = result.subtype;
212
- this._parameters = new MediaTypeParameters(result.parameters);
213
- }
286
+ /** @type {string} */
287
+ #type;
288
+ /** @type {string} */
289
+ #subtype;
290
+ /** @type {MediaTypeParameters} */
291
+ #parameters;
292
+ /**
293
+ * Create a new MediaType instance from a string representation.
294
+ *
295
+ * @param {string} mediaType The media type to parse.
296
+ * @param {Object} [parameters] Optional parameters.
297
+ */
298
+ constructor(mediaType, parameters = {}) {
299
+ const { type, subtype, parameters: parsedParameters } = parser_default(mediaType);
300
+ this.#type = type;
301
+ this.#subtype = subtype;
302
+ this.#parameters = new MediaTypeParameters([...parsedParameters, ...Object.entries(parameters).map(([name, value]) => [asciiLowercase(name), asciiLowercase(value)])]);
303
+ }
304
+ /**
305
+ * Static factory method for parsing a media type.
306
+ *
307
+ * @param {string} string The media type to parse.
308
+ * @returns {MediaType} The parsed {@link MediaType} object or null if the string could not be parsed.
309
+ */
214
310
  static parse(string) {
215
311
  try {
216
- return new this(string);
312
+ return new MediaType(string);
217
313
  } catch (e) {
218
- return null;
314
+ throw new Error(`Could not parse media type string '${string}'`);
219
315
  }
220
316
  }
317
+ /**
318
+ * Gets the media type essence (type/subtype).
319
+ *
320
+ * @returns {string} The media type without any parameters
321
+ */
221
322
  get essence() {
222
- return `${this.type}/${this.subtype}`;
323
+ return `${this.#type}/${this.#subtype}`;
223
324
  }
325
+ /**
326
+ * Gets the type.
327
+ *
328
+ * @returns {string} The type.
329
+ */
224
330
  get type() {
225
- return this._type;
331
+ return this.#type;
226
332
  }
333
+ /**
334
+ * Sets the type.
335
+ */
227
336
  set type(value) {
228
337
  value = asciiLowercase(String(value));
229
338
  if (value.length === 0) {
@@ -232,11 +341,19 @@ var MediaType = (() => {
232
341
  if (!solelyContainsHTTPTokenCodePoints(value)) {
233
342
  throw new Error(`Invalid type ${value}: must contain only HTTP token code points`);
234
343
  }
235
- this._type = value;
344
+ this.#type = value;
236
345
  }
346
+ /**
347
+ * Gets the subtype.
348
+ *
349
+ * @returns {string} The subtype.
350
+ */
237
351
  get subtype() {
238
- return this._subtype;
352
+ return this.#subtype;
239
353
  }
354
+ /**
355
+ * Sets the subtype.
356
+ */
240
357
  set subtype(value) {
241
358
  value = asciiLowercase(String(value));
242
359
  if (value.length === 0) {
@@ -245,18 +362,35 @@ var MediaType = (() => {
245
362
  if (!solelyContainsHTTPTokenCodePoints(value)) {
246
363
  throw new Error(`Invalid subtype ${value}: must contain only HTTP token code points`);
247
364
  }
248
- this._subtype = value;
365
+ this.#subtype = value;
249
366
  }
367
+ /**
368
+ * Gets the parameters.
369
+ *
370
+ * @returns {MediaTypeParameters} The media type parameters.
371
+ */
250
372
  get parameters() {
251
- return this._parameters;
373
+ return this.#parameters;
252
374
  }
375
+ /**
376
+ * Gets the serialized version of the media type.
377
+ *
378
+ * @returns {string} The serialized media type.
379
+ */
253
380
  toString() {
254
381
  return serializer_default(this);
255
382
  }
383
+ /**
384
+ * Determines if this instance is a JavaScript media type.
385
+ *
386
+ * @param {Object} [options] Optional options.
387
+ * @param {boolean} [options.prohibitParameters=false] The option to prohibit parameters when checking if the media type is JavaScript.
388
+ * @returns {boolean} true if this instance represents a JavaScript media type, false otherwise.
389
+ */
256
390
  isJavaScript({ prohibitParameters = false } = {}) {
257
- switch (this._type) {
391
+ switch (this.#type) {
258
392
  case "text": {
259
- switch (this._subtype) {
393
+ switch (this.#subtype) {
260
394
  case "ecmascript":
261
395
  case "javascript":
262
396
  case "javascript1.0":
@@ -269,18 +403,18 @@ var MediaType = (() => {
269
403
  case "livescript":
270
404
  case "x-ecmascript":
271
405
  case "x-javascript":
272
- return !prohibitParameters || this._parameters.size === 0;
406
+ return !prohibitParameters || this.#parameters.size === 0;
273
407
  default:
274
408
  return false;
275
409
  }
276
410
  }
277
411
  case "application": {
278
- switch (this._subtype) {
412
+ switch (this.#subtype) {
279
413
  case "ecmascript":
280
414
  case "javascript":
281
415
  case "x-ecmascript":
282
416
  case "x-javascript":
283
- return !prohibitParameters || this._parameters.size === 0;
417
+ return !prohibitParameters || this.#parameters.size === 0;
284
418
  default:
285
419
  return false;
286
420
  }
@@ -289,12 +423,27 @@ var MediaType = (() => {
289
423
  return false;
290
424
  }
291
425
  }
426
+ /**
427
+ * Determines if this instance is an XML media type.
428
+ *
429
+ * @returns {boolean} true if this instance represents an XML media type, false otherwise.
430
+ */
292
431
  isXML() {
293
- return this._subtype === "xml" && (this._type === "text" || this._type === "application") || this._subtype.endsWith("+xml");
432
+ return this.#subtype === "xml" && (this.#type === "text" || this.#type === "application") || this.#subtype.endsWith("+xml");
294
433
  }
434
+ /**
435
+ * Determines if this instance is an HTML media type.
436
+ *
437
+ * @returns {boolean} true if this instance represents an HTML media type, false otherwise.
438
+ */
295
439
  isHTML() {
296
- return this._subtype === "html" && this._type === "text";
440
+ return this.#subtype === "html" && this.#type === "text";
297
441
  }
442
+ /**
443
+ * Gets the name of the class.
444
+ *
445
+ * @returns {string} The class name
446
+ */
298
447
  get [Symbol.toStringTag]() {
299
448
  return "MediaType";
300
449
  }
@@ -1,4 +1,4 @@
1
- var MediaType=(()=>{var m=Object.defineProperty;var w=Object.getOwnPropertyDescriptor;var _=Object.getOwnPropertyNames;var P=Object.prototype.hasOwnProperty;var b=(t,e)=>{for(var r in e)m(t,r,{get:e[r],enumerable:!0})},H=(t,e,r,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of _(e))!P.call(t,n)&&n!==r&&m(t,n,{get:()=>e[n],enumerable:!(s=w(e,n))||s.enumerable});return t};var C=t=>H(m({},"__esModule",{value:!0}),t);var $={};b($,{default:()=>p});var u=t=>t.replace(/^[ \t\n\r]+/u,"").replace(/[ \t\n\r]+$/u,""),y=t=>t.replace(/[ \t\n\r]+$/u,""),T=t=>t===" "||t===" "||t===`
2
- `||t==="\r",i=t=>/^[-!#$%&'*+.^_`|~A-Za-z0-9]*$/u.test(t),h=t=>/^[\t\u0020-\u007E\u0080-\u00FF]*$/u.test(t),a=t=>t.replace(/[A-Z]/ug,e=>e.toLowerCase()),g=(t,e)=>{let r="";for(e++;;){for(;e<t.length&&t[e]!=='"'&&t[e]!=="\\";)r+=t[e],++e;if(e>=t.length)break;let s=t[e];if(++e,s==="\\"){if(e>=t.length){r+="\\";break}r+=t[e],++e}else break}return[r,e]};var c=class{constructor(e){this._map=e}get size(){return this._map.size}get(e){return this._map.get(a(String(e)))}has(e){return this._map.has(a(String(e)))}set(e,r){if(e=a(String(e)),r=String(r),!i(e))throw new Error(`Invalid media type parameter name "${e}": only HTTP token code points are valid.`);if(!h(r))throw new Error(`Invalid media type parameter value "${r}": only HTTP quoted-string token code points are valid.`);return this._map.set(e,r),this}clear(){this._map.clear()}delete(e){return e=a(String(e)),this._map.delete(e)}forEach(e,r){this._map.forEach(e,r)}keys(){return this._map.keys()}values(){return this._map.values()}entries(){return this._map.entries()}[Symbol.iterator](){return this._map[Symbol.iterator]()}};var S=t=>{t=u(t);let e=0,r="";for(;e<t.length&&t[e]!=="/";)r+=t[e],++e;if(r.length===0||!i(r)||e>=t.length)return null;++e;let s="";for(;e<t.length&&t[e]!==";";)s+=t[e],++e;if(s=y(s),s.length===0||!i(s))return null;let n={type:a(r),subtype:a(s),parameters:new Map};for(;e<t.length;){for(++e;T(t[e]);)++e;let l="";for(;e<t.length&&t[e]!==";"&&t[e]!=="=";)l+=t[e],++e;if(l=a(l),e<t.length){if(t[e]===";")continue;++e}let o=null;if(t[e]==='"')for([o,e]=g(t,e);e<t.length&&t[e]!==";";)++e;else{for(o="";e<t.length&&t[e]!==";";)o+=t[e],++e;if(o=y(o),o==="")continue}l.length>0&&i(l)&&h(o)&&!n.parameters.has(l)&&n.parameters.set(l,o)}return n},d=S;var k=t=>{let e=`${t.type}/${t.subtype}`;if(t.parameters.size===0)return e;for(let[r,s]of t.parameters)e+=";",e+=r,e+="=",(!i(s)||s.length===0)&&(s=s.replace(/(["\\])/ug,"\\$1"),s=`"${s}"`),e+=s;return e},f=k;var p=class{constructor(e){e=String(e);let r=d(e);if(r===null)throw new Error(`Could not parse media type string '${e}'`);this._type=r.type,this._subtype=r.subtype,this._parameters=new c(r.parameters)}static parse(e){try{return new this(e)}catch{return null}}get essence(){return`${this.type}/${this.subtype}`}get type(){return this._type}set type(e){if(e=a(String(e)),e.length===0)throw new Error("Invalid type: must be a non-empty string");if(!i(e))throw new Error(`Invalid type ${e}: must contain only HTTP token code points`);this._type=e}get subtype(){return this._subtype}set subtype(e){if(e=a(String(e)),e.length===0)throw new Error("Invalid subtype: must be a non-empty string");if(!i(e))throw new Error(`Invalid subtype ${e}: must contain only HTTP token code points`);this._subtype=e}get parameters(){return this._parameters}toString(){return f(this)}isJavaScript({prohibitParameters:e=!1}={}){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!e||this._parameters.size===0;default:return!1}case"application":switch(this._subtype){case"ecmascript":case"javascript":case"x-ecmascript":case"x-javascript":return!e||this._parameters.size===0;default:return!1}default:return!1}}isXML(){return this._subtype==="xml"&&(this._type==="text"||this._type==="application")||this._subtype.endsWith("+xml")}isHTML(){return this._subtype==="html"&&this._type==="text"}get[Symbol.toStringTag](){return"MediaType"}};return C($);})();
1
+ var MediaType=(()=>{var T=Object.defineProperty;var C=Object.getOwnPropertyDescriptor;var H=Object.getOwnPropertyNames;var S=Object.prototype.hasOwnProperty;var k=(t,e)=>{for(var r in e)T(t,r,{get:e[r],enumerable:!0})},b=(t,e,r,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of H(e))!S.call(t,i)&&i!==r&&T(t,i,{get:()=>e[i],enumerable:!(s=C(e,i))||s.enumerable});return t};var $=t=>b(T({},"__esModule",{value:!0}),t);var L={};k(L,{default:()=>l});var v=[" "," ",`
2
+ `,"\r"],x=/^[ \t\n\r]+/u,d=/[ \t\n\r]+$/u,j=/^[-!#$%&'*+.^_`|~A-Za-z0-9]*$/u,E=/^[\t\u0020-\u007E\u0080-\u00FF]*$/u,m=t=>t.replace(x,"").replace(d,""),g=t=>t.replace(d,""),u=t=>v.includes(t),n=t=>j.test(t),p=t=>E.test(t),a=t=>{let e="";for(let[r,s=r.charCodeAt(0)]of t)e+=s>=65&&s<=90?String.fromCharCode(s+32):r;return e},f=(t,e)=>{let r="";for(let s=t.length,i;++e<s;)if(i=t[e],i=="\\")r+=++e<s?t[e]:i;else{if(i=='"')break;r+=i}return[r,e]};var h=class{#e;constructor(e){this.#e=new Map(e)}get size(){return this.#e.size}get(e){return this.#e.get(a(String(e)))}has(e){return this.#e.has(a(String(e)))}set(e,r){if(e=a(String(e)),r=String(r),!n(e))throw new Error(`Invalid media type parameter name "${e}": only HTTP token code points are valid.`);if(!p(r))throw new Error(`Invalid media type parameter value "${r}": only HTTP quoted-string token code points are valid.`);return this.#e.set(e,r),this}clear(){this.#e.clear()}delete(e){return e=a(String(e)),this.#e.delete(e)}forEach(e,r){this.#e.forEach(e,r)}keys(){return this.#e.keys()}values(){return this.#e.values()}entries(){return this.#e.entries()}[Symbol.iterator](){return this.#e[Symbol.iterator]()}[Symbol.toStringTag](){return"MediaTypeParameters"}};var z=t=>{t=m(t);let e=0,r="";for(;e<t.length&&t[e]!="/";)r+=t[e],++e;if(r.length===0||!n(r)||e>=t.length)return null;++e;let s="";for(;e<t.length&&t[e]!=";";)s+=t[e],++e;if(s=g(s),s.length===0||!n(s))return null;let i={type:a(r),subtype:a(s),parameters:new Map};for(;e<t.length;){for(++e;u(t[e]);)++e;let c="";for(;e<t.length&&t[e]!=";"&&t[e]!="=";)c+=t[e],++e;if(c=a(c),e<t.length){if(t[e]==";")continue;++e}let o=null;if(t[e]=='"')for([o,e]=f(t,e);e<t.length&&t[e]!=";";)++e;else{for(o="";e<t.length&&t[e]!=";";)o+=t[e],++e;if(o=g(o),o==="")continue}c.length>0&&n(c)&&p(o)&&!i.parameters.has(c)&&i.parameters.set(c,o)}return i},y=z;var W=t=>{let e=`${t.type}/${t.subtype}`;if(t.parameters.size===0)return e;for(let[r,s]of t.parameters)e+=`;${r}=`,(!n(s)||s.length===0)&&(s=`"${s.replace(/(["\\])/ug,"\\$1")}"`),e+=s;return e},w=W;var l=class{#e;#t;#r;constructor(e,r={}){let{type:s,subtype:i,parameters:c}=y(e);this.#e=s,this.#t=i,this.#r=new h([...c,...Object.entries(r).map(([o,P])=>[a(o),a(P)])])}static parse(e){try{return new l(e)}catch{throw new Error(`Could not parse media type string '${e}'`)}}get essence(){return`${this.#e}/${this.#t}`}get type(){return this.#e}set type(e){if(e=a(String(e)),e.length===0)throw new Error("Invalid type: must be a non-empty string");if(!n(e))throw new Error(`Invalid type ${e}: must contain only HTTP token code points`);this.#e=e}get subtype(){return this.#t}set subtype(e){if(e=a(String(e)),e.length===0)throw new Error("Invalid subtype: must be a non-empty string");if(!n(e))throw new Error(`Invalid subtype ${e}: must contain only HTTP token code points`);this.#t=e}get parameters(){return this.#r}toString(){return w(this)}isJavaScript({prohibitParameters:e=!1}={}){switch(this.#e){case"text":switch(this.#t){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!e||this.#r.size===0;default:return!1}case"application":switch(this.#t){case"ecmascript":case"javascript":case"x-ecmascript":case"x-javascript":return!e||this.#r.size===0;default:return!1}default:return!1}}isXML(){return this.#t==="xml"&&(this.#e==="text"||this.#e==="application")||this.#t.endsWith("+xml")}isHTML(){return this.#t==="html"&&this.#e==="text"}get[Symbol.toStringTag](){return"MediaType"}};return $(L);})();
3
3
  window.MediaType = MediaType.default;
4
4
  //# sourceMappingURL=media-type.min.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/media-type.js", "../src/utils.js", "../src/media-type-parameters.js", "../src/parser.js", "../src/serializer.js"],
4
- "sourcesContent": ["import MediaTypeParameters from './media-type-parameters.js';\nimport parse from './parser.js';\nimport serialize from './serializer.js';\nimport { asciiLowercase, solelyContainsHTTPTokenCodePoints } from './utils.js';\n\n/**\n * Class used to parse media types.\n *\n * @see https://mimesniff.spec.whatwg.org/#understanding-mime-types\n * @module MediaType\n */\nexport default class MediaType {\n\t/**\n\t * Create a new MediaType instance from a string representation.\n\t *\n\t * @param {string} string The media type to parse\n\t */\n\tconstructor(string) {\n\t\tstring = String(string);\n\t\tconst result = parse(string);\n\t\tif (result === null) {\n\t\t\tthrow new Error(`Could not parse media type string '${string}'`);\n\t\t}\n\n\t\tthis._type = result.type;\n\t\tthis._subtype = result.subtype;\n\t\tthis._parameters = new MediaTypeParameters(result.parameters);\n\t}\n\n\t/**\n\t * Static factor method for parsing a media type.\n\t *\n\t * @param {string} string The media type to parse\n\t * @returns {MediaType} The parsed {@link MediaType} object\n\t */\n\tstatic parse(string) {\n\t\ttry {\n\t\t\treturn new this(string);\n\t\t} catch (e) {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Gets the media type essence (type/subtype).\n\t *\n\t * @returns {string} The media type without any parameters\n\t */\n\tget essence() {\n\t\treturn `${this.type}/${this.subtype}`;\n\t}\n\n\t/**\n\t * Gets the type.\n\t *\n\t * @returns {string} The type.\n\t */\n\tget type() {\n\t\treturn this._type;\n\t}\n\n\t/**\n\t * Sets the type.\n\t */\n\tset type(value) {\n\t\tvalue = asciiLowercase(String(value));\n\n\t\tif (value.length === 0) {\n\t\t\tthrow new Error('Invalid type: must be a non-empty string');\n\t\t}\n\t\tif (!solelyContainsHTTPTokenCodePoints(value)) {\n\t\t\tthrow new Error(`Invalid type ${value}: must contain only HTTP token code points`);\n\t\t}\n\n\t\tthis._type = value;\n\t}\n\n\t/**\n\t * Gets the subtype.\n\t *\n\t * @returns {string} The subtype.\n\t */\n\tget subtype() {\n\t\treturn this._subtype;\n\t}\n\n\t/**\n\t * Sets the subtype.\n\t */\n\tset subtype(value) {\n\t\tvalue = asciiLowercase(String(value));\n\n\t\tif (value.length === 0) {\n\t\t\tthrow new Error('Invalid subtype: must be a non-empty string');\n\t\t}\n\t\tif (!solelyContainsHTTPTokenCodePoints(value)) {\n\t\t\tthrow new Error(`Invalid subtype ${value}: must contain only HTTP token code points`);\n\t\t}\n\n\t\tthis._subtype = value;\n\t}\n\n\t/**\n\t * Gets the parameters.\n\t *\n\t * @returns {MediaTypeParameters} The media type parameters.\n\t */\n\tget parameters() {\n\t\treturn this._parameters;\n\t}\n\n\t/**\n\t * Gets the serialized version of the media type.\n\t *\n\t * @returns {string} The serialized media type.\n\t */\n\ttoString() {\n\t\t// The serialize function works on both 'media type records' (i.e. the results of parse) and on this class, since\n\t\t// this class's interface is identical.\n\t\treturn serialize(this);\n\t}\n\n\t/**\n\t * Determines if this instance is a JavaScript media type.\n\t *\n\t * @param {Object} [options] Optional options.\n\t * @param {boolean} [options.prohibitParameters=false] The option to prohibit parameters when checking if the media type is JavaScript.\n\t * @returns {boolean} true if this instance represents a JavaScript media type, false otherwise.\n\t */\n\tisJavaScript({prohibitParameters = false} = {}) {\n\t\tswitch (this._type) {\n\t\t\tcase 'text': {\n\t\t\t\tswitch (this._subtype) {\n\t\t\t\t\tcase 'ecmascript':\n\t\t\t\t\tcase 'javascript':\n\t\t\t\t\tcase 'javascript1.0':\n\t\t\t\t\tcase 'javascript1.1':\n\t\t\t\t\tcase 'javascript1.2':\n\t\t\t\t\tcase 'javascript1.3':\n\t\t\t\t\tcase 'javascript1.4':\n\t\t\t\t\tcase 'javascript1.5':\n\t\t\t\t\tcase 'jscript':\n\t\t\t\t\tcase 'livescript':\n\t\t\t\t\tcase 'x-ecmascript':\n\t\t\t\t\tcase 'x-javascript': return !prohibitParameters || this._parameters.size === 0;\n\t\t\t\t\tdefault: return false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tcase 'application': {\n\t\t\t\tswitch (this._subtype) {\n\t\t\t\t\tcase 'ecmascript':\n\t\t\t\t\tcase 'javascript':\n\t\t\t\t\tcase 'x-ecmascript':\n\t\t\t\t\tcase 'x-javascript': return !prohibitParameters || this._parameters.size === 0;\n\t\t\t\t\tdefault: return false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tdefault: return false;\n\t\t}\n\t}\n\n\t/**\n\t * Determines if this instance is an XML media type.\n\t *\n\t * @returns {boolean} true if this instance represents an XML media type, false otherwise.\n\t */\n\tisXML() {\n\t\treturn (this._subtype === 'xml' && (this._type === 'text' || this._type === 'application')) || this._subtype.endsWith('+xml');\n\t}\n\n\t/**\n\t * Determines if this instance is an HTML media type.\n\t *\n\t * @returns {boolean} true if this instance represents an HTML media type, false otherwise.\n\t */\n\tisHTML() {\n\t\treturn this._subtype === 'html' && this._type === 'text';\n\t}\n\n\t/**\n\t * Gets the name of the class.\n\t *\n\t * @returns {string} The class name\n\t */\n\tget [Symbol.toStringTag]() {\n\t\treturn 'MediaType';\n\t}\n}", "/** @module utils */\n\n/**\n * A function to remove any leading and trailing HTTP whitespace.\n *\n * @param {string} string The string to process.\n * @returns {string} The processed string.\n */\nconst removeLeadingAndTrailingHTTPWhitespace = (string) => string.replace(/^[ \\t\\n\\r]+/u, '').replace(/[ \\t\\n\\r]+$/u, '');\n\n/**\n * A function to remove any trailing HTTP whitespace.\n *\n * @param {string} string The string to process.\n * @returns {string} The processed string.\n */\nconst removeTrailingHTTPWhitespace = (string) => string.replace(/[ \\t\\n\\r]+$/u, '');\n\n/**\n * Determines if the provided character is whitespace.\n *\n * @param {string} char The character to evaluate.\n * @returns {boolean} true if the character is whitespace, false otherwise.\n */\nconst isHTTPWhitespaceChar = (char) => char === ' ' || char === '\\t' || char === '\\n' || char === '\\r';\n\n/**\n * Determines if the provided string contains only HTTP token code points.\n *\n * @param {string} string The string to evaluate.\n * @returns {boolean} true if the string contains only HTTP token code points.\n */\nconst solelyContainsHTTPTokenCodePoints = (string) => /^[-!#$%&'*+.^_`|~A-Za-z0-9]*$/u.test(string);\n\n/**\n * Determines if the provided string contains only quoted HTTP token code points.\n *\n * @param {string} string The string to evaluate.\n * @returns {boolean} true if the string contains only quoted HTTP token code points.\n */\nconst solelyContainsHTTPQuotedStringTokenCodePoints = (string) => /^[\\t\\u0020-\\u007E\\u0080-\\u00FF]*$/u.test(string);\n\n/**\n * A function to lower case ASCII characters.\n *\n * @param {string} string The string to process.\n * @returns {string} The processed string with all ASCII characters lower cased.\n */\nconst asciiLowercase = (string) => string.replace(/[A-Z]/ug, l => l.toLowerCase());\n\n/**\n * Collects all the HTTP quoted strings.\n * This variant only implements it with the extract-value flag set.\n *\n * @param {string} input The string to process.\n * @param {number} position The starting position.\n * @returns {Array<string | number>} An array that includes the resulting string and updated position.\n */\nconst collectAnHTTPQuotedString = (input, position) => {\n\tlet value = '';\n\n\tposition++;\n\n\twhile (true) {\n\t\twhile (position < input.length && input[position] !== '\"' && input[position] !== '\\\\') {\n\t\t\tvalue += input[position];\n\t\t\t++position;\n\t\t}\n\n\t\tif (position >= input.length) {\n\t\t\tbreak;\n\t\t}\n\n\t\tconst quoteOrBackslash = input[position];\n\t\t++position;\n\n\t\tif (quoteOrBackslash === '\\\\') {\n\t\t\tif (position >= input.length) {\n\t\t\t\tvalue += '\\\\';\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tvalue += input[position];\n\t\t\t++position;\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn [value, position];\n};\n\nexport { removeLeadingAndTrailingHTTPWhitespace, removeTrailingHTTPWhitespace, isHTTPWhitespaceChar, solelyContainsHTTPTokenCodePoints, solelyContainsHTTPQuotedStringTokenCodePoints, asciiLowercase, collectAnHTTPQuotedString };\n", "import { asciiLowercase, solelyContainsHTTPQuotedStringTokenCodePoints, solelyContainsHTTPTokenCodePoints } from './utils.js';\n\n/**\n * Class representing the parameters for a media type record.\n * This class has the equivalent surface API to a JavaScript {@link Map}.\n *\n * However, {@link MediaTypeParameters} methods will always interpret their arguments\n * as appropriate for media types, so parameter names will be lowercased,\n * and attempting to set invalid characters will throw an {@link Error}.\n *\n * @example charset=utf-8\n * @module MediaTypeParameters\n */\nexport default class MediaTypeParameters {\n\t/**\n\t * Create a new MediaTypeParameters instance.\n\t *\n\t * @param {Map.<string, string>} map The map of parameters for a media type.\n\t */\n\tconstructor(map) {\n\t\tthis._map = map;\n\t}\n\n\t/**\n\t * Gets the number of media type parameters.\n\t *\n\t * @returns {number} The number of media type parameters\n\t */\n\tget size() {\n\t\treturn this._map.size;\n\t}\n\n\t/**\n\t * Gets the media type parameter value for the supplied name.\n\t *\n\t * @param {string} name The name of the media type parameter to retrieve.\n\t * @returns {string} The media type parameter value.\n\t */\n\tget(name) {\n\t\treturn this._map.get(asciiLowercase(String(name)));\n\t}\n\n\t/**\n\t * Indicates whether the media type parameter with the specified name exists or not.\n\t *\n\t * @param {string} name The name of the media type parameter to check.\n\t * @returns {boolean} true if the media type parameter exists, false otherwise.\n\t */\n\thas(name) {\n\t\treturn this._map.has(asciiLowercase(String(name)));\n\t}\n\n\t/**\n\t * Adds a new media type parameter using the specified name and value to the MediaTypeParameters.\n\t * If an parameter with the same name already exists, the parameter will be updated.\n\t *\n\t * @param {string} name The name of the media type parameter to set.\n\t * @param {string} value The media type parameter value.\n\t * @returns {MediaTypeParameters} This instance.\n\t */\n\tset(name, value) {\n\t\tname = asciiLowercase(String(name));\n\t\tvalue = String(value);\n\n\t\tif (!solelyContainsHTTPTokenCodePoints(name)) {\n\t\t\tthrow new Error(`Invalid media type parameter name \"${name}\": only HTTP token code points are valid.`);\n\t\t}\n\n\t\tif (!solelyContainsHTTPQuotedStringTokenCodePoints(value)) {\n\t\t\tthrow new Error(`Invalid media type parameter value \"${value}\": only HTTP quoted-string token code points are valid.`);\n\t\t}\n\n\t\tthis._map.set(name, value);\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Clears all the media type parameters.\n\t */\n\tclear() {\n\t\tthis._map.clear();\n\t}\n\n\t/**\n\t * Removes the media type parameter using the specified name.\n\t *\n\t * @param {string} name The name of the media type parameter to delete.\n\t * @returns {boolean} true if the parameter existed and has been removed, or false if the parameter does not exist.\n\t */\n\tdelete(name) {\n\t\tname = asciiLowercase(String(name));\n\t\treturn this._map.delete(name);\n\t}\n\n\t/**\n\t * Executes a provided function once per each name/value pair in the MediaTypeParameters, in insertion order.\n\t *\n\t * @param {function(string, string): void} callback The function called on each iteration.\n\t * @param {*} [thisArg] Optional object when binding 'this' to the callback.\n\t */\n\tforEach(callback, thisArg) {\n\t\tthis._map.forEach(callback, thisArg);\n\t}\n\n\t/**\n\t * Returns an iterable of parameter names.\n\t *\n\t * @returns {IterableIterator<string>} The {@link IterableIterator} of media type parameter names.\n\t */\n\tkeys() {\n\t\treturn this._map.keys();\n\t}\n\n\t/**\n\t * Returns an iterable of parameter values.\n\t *\n\t * @returns {IterableIterator<string>} The {@link IterableIterator} of media type parameter values.\n\t */\n\tvalues() {\n\t\treturn this._map.values();\n\t}\n\n\t/**\n\t * Returns an iterable of name, value pairs for every parameter entry in the media type parameters.\n\t *\n\t * @returns {IterableIterator<Array<Array<string>>>} The media type parameter entries.\n\t */\n\tentries() {\n\t\treturn this._map.entries();\n\t}\n\n\t/**\n\t * A method that returns the default iterator for the {@link MediaTypeParameters}. Called by the semantics of the for-of statement.\n\t *\n\t * @returns {Iterator<string, string, undefined>} The {@link Symbol.iterator} for the media type parameters.\n\t */\n\t[Symbol.iterator]() {\n\t\treturn this._map[Symbol.iterator]();\n\t}\n}", "import {\n\tasciiLowercase,\n\tcollectAnHTTPQuotedString, isHTTPWhitespaceChar, removeLeadingAndTrailingHTTPWhitespace,\n\tremoveTrailingHTTPWhitespace, solelyContainsHTTPQuotedStringTokenCodePoints, solelyContainsHTTPTokenCodePoints\n} from './utils.js';\n\n/**\n * Function to parse a media type.\n *\n * @module parser\n * @param {string} input The media type to parse\n * @returns {{ type: string, subtype: string, parameters: Map<string, string> }} An object populated with the parsed media type properties and any parameters.\n */\nconst parse = (input) => {\n\tinput = removeLeadingAndTrailingHTTPWhitespace(input);\n\n\tlet position = 0;\n\tlet type = '';\n\twhile (position < input.length && input[position] !== '/') {\n\t\ttype += input[position];\n\t\t++position;\n\t}\n\n\tif (type.length === 0 || !solelyContainsHTTPTokenCodePoints(type)) {\n\t\treturn null;\n\t}\n\n\tif (position >= input.length) {\n\t\treturn null;\n\t}\n\n\t// Skips past \"/\"\n\t++position;\n\n\tlet subtype = '';\n\twhile (position < input.length && input[position] !== ';') {\n\t\tsubtype += input[position];\n\t\t++position;\n\t}\n\n\tsubtype = removeTrailingHTTPWhitespace(subtype);\n\n\tif (subtype.length === 0 || !solelyContainsHTTPTokenCodePoints(subtype)) {\n\t\treturn null;\n\t}\n\n\tconst mediaType = {\n\t\ttype: asciiLowercase(type),\n\t\tsubtype: asciiLowercase(subtype),\n\t\tparameters: new Map()\n\t};\n\n\twhile (position < input.length) {\n\t\t// Skip past \";\"\n\t\t++position;\n\n\t\twhile (isHTTPWhitespaceChar(input[position])) {\n\t\t\t++position;\n\t\t}\n\n\t\tlet parameterName = '';\n\t\twhile (position < input.length && input[position] !== ';' && input[position] !== '=') {\n\t\t\tparameterName += input[position];\n\t\t\t++position;\n\t\t}\n\t\tparameterName = asciiLowercase(parameterName);\n\n\t\tif (position < input.length) {\n\t\t\tif (input[position] === ';') {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Skip past \"=\"\n\t\t\t++position;\n\t\t}\n\n\t\tlet parameterValue = null;\n\t\tif (input[position] === '\"') {\n\t\t\t[parameterValue, position] = collectAnHTTPQuotedString(input, position);\n\n\t\t\twhile (position < input.length && input[position] !== ';') {\n\t\t\t\t++position;\n\t\t\t}\n\t\t} else {\n\t\t\tparameterValue = '';\n\t\t\twhile (position < input.length && input[position] !== ';') {\n\t\t\t\tparameterValue += input[position];\n\t\t\t\t++position;\n\t\t\t}\n\n\t\t\tparameterValue = removeTrailingHTTPWhitespace(parameterValue);\n\n\t\t\tif (parameterValue === '') {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\tif (parameterName.length > 0 &&\n\t\t\tsolelyContainsHTTPTokenCodePoints(parameterName) &&\n\t\t\tsolelyContainsHTTPQuotedStringTokenCodePoints(parameterValue) &&\n\t\t\t!mediaType.parameters.has(parameterName)) {\n\t\t\tmediaType.parameters.set(parameterName, parameterValue);\n\t\t}\n\t}\n\n\treturn mediaType;\n};\n\nexport default parse;", "import { solelyContainsHTTPTokenCodePoints } from './utils.js';\n// eslint-disable-next-line jsdoc/valid-types\n/** @typedef { import('./media-type.js').default } MediaType */\n\n/**\n * A function that serializes the provided {@link mediaType} to a string.\n *\n * @module serializer\n * @param {MediaType} mediaType The media type to serialize.\n * @returns {string} The serialized media type.\n */\nconst serialize = (mediaType) => {\n\tlet serialization = `${mediaType.type}/${mediaType.subtype}`;\n\n\tif (mediaType.parameters.size === 0) {\n\t\treturn serialization;\n\t}\n\n\tfor (let [name, value] of mediaType.parameters) {\n\t\tserialization += ';';\n\t\tserialization += name;\n\t\tserialization += '=';\n\n\t\tif (!solelyContainsHTTPTokenCodePoints(value) || value.length === 0) {\n\t\t\tvalue = value.replace(/([\"\\\\])/ug, '\\\\$1');\n\t\t\tvalue = `\"${value}\"`;\n\t\t}\n\n\t\tserialization += value;\n\t}\n\n\treturn serialization;\n};\n\nexport default serialize;"],
5
- "mappings": "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",
6
- "names": ["media_type_exports", "__export", "MediaType", "removeLeadingAndTrailingHTTPWhitespace", "string", "removeTrailingHTTPWhitespace", "isHTTPWhitespaceChar", "char", "solelyContainsHTTPTokenCodePoints", "solelyContainsHTTPQuotedStringTokenCodePoints", "asciiLowercase", "l", "collectAnHTTPQuotedString", "input", "position", "value", "quoteOrBackslash", "MediaTypeParameters", "map", "name", "asciiLowercase", "value", "solelyContainsHTTPTokenCodePoints", "solelyContainsHTTPQuotedStringTokenCodePoints", "callback", "thisArg", "parse", "input", "removeLeadingAndTrailingHTTPWhitespace", "position", "type", "solelyContainsHTTPTokenCodePoints", "subtype", "removeTrailingHTTPWhitespace", "mediaType", "asciiLowercase", "isHTTPWhitespaceChar", "parameterName", "parameterValue", "collectAnHTTPQuotedString", "solelyContainsHTTPQuotedStringTokenCodePoints", "parser_default", "serialize", "mediaType", "serialization", "name", "value", "solelyContainsHTTPTokenCodePoints", "serializer_default", "MediaType", "string", "result", "parser_default", "MediaTypeParameters", "value", "asciiLowercase", "solelyContainsHTTPTokenCodePoints", "serializer_default", "prohibitParameters"]
4
+ "sourcesContent": ["import MediaTypeParameters from './media-type-parameters.js';\nimport parse from './parser.js';\nimport serialize from './serializer.js';\nimport { asciiLowercase, solelyContainsHTTPTokenCodePoints } from './utils.js';\n\n/**\n * Class used to parse media types.\n *\n * @module {MediaType} media-type\n * @see https://mimesniff.spec.whatwg.org/#understanding-mime-types\n */\nexport default class MediaType {\n\t/** @type {string} */\n\t#type;\n\t/** @type {string} */\n\t#subtype;\n\t/** @type {MediaTypeParameters} */\n\t#parameters;\n\n\t/**\n\t * Create a new MediaType instance from a string representation.\n\t *\n\t * @param {string} mediaType The media type to parse.\n\t * @param {Object} [parameters] Optional parameters.\n\t */\n\tconstructor(mediaType, parameters = {}) {\n\t\tconst { type, subtype, parameters: parsedParameters } = parse(mediaType);\n\t\tthis.#type = type;\n\t\tthis.#subtype = subtype;\n\t\tthis.#parameters = new MediaTypeParameters([...parsedParameters, ...Object.entries(parameters).map(([name, value]) => [asciiLowercase(name), asciiLowercase(value)])]);\n\t}\n\n\t/**\n\t * Static factory method for parsing a media type.\n\t *\n\t * @param {string} string The media type to parse.\n\t * @returns {MediaType} The parsed {@link MediaType} object or null if the string could not be parsed.\n\t */\n\tstatic parse(string) {\n\t\ttry {\n\t\t\treturn new MediaType(string);\n\t\t} catch (e) {\n\t\t\tthrow new Error(`Could not parse media type string '${string}'`);\n\t\t}\n\t}\n\n\t/**\n\t * Gets the media type essence (type/subtype).\n\t *\n\t * @returns {string} The media type without any parameters\n\t */\n\tget essence() {\n\t\treturn `${this.#type}/${this.#subtype}`;\n\t}\n\n\t/**\n\t * Gets the type.\n\t *\n\t * @returns {string} The type.\n\t */\n\tget type() {\n\t\treturn this.#type;\n\t}\n\n\t/**\n\t * Sets the type.\n\t */\n\tset type(value) {\n\t\tvalue = asciiLowercase(String(value));\n\n\t\tif (value.length === 0) {\n\t\t\tthrow new Error('Invalid type: must be a non-empty string');\n\t\t}\n\t\tif (!solelyContainsHTTPTokenCodePoints(value)) {\n\t\t\tthrow new Error(`Invalid type ${value}: must contain only HTTP token code points`);\n\t\t}\n\n\t\tthis.#type = value;\n\t}\n\n\t/**\n\t * Gets the subtype.\n\t *\n\t * @returns {string} The subtype.\n\t */\n\tget subtype() {\n\t\treturn this.#subtype;\n\t}\n\n\t/**\n\t * Sets the subtype.\n\t */\n\tset subtype(value) {\n\t\tvalue = asciiLowercase(String(value));\n\n\t\tif (value.length === 0) {\n\t\t\tthrow new Error('Invalid subtype: must be a non-empty string');\n\t\t}\n\t\tif (!solelyContainsHTTPTokenCodePoints(value)) {\n\t\t\tthrow new Error(`Invalid subtype ${value}: must contain only HTTP token code points`);\n\t\t}\n\n\t\tthis.#subtype = value;\n\t}\n\n\t/**\n\t * Gets the parameters.\n\t *\n\t * @returns {MediaTypeParameters} The media type parameters.\n\t */\n\tget parameters() {\n\t\treturn this.#parameters;\n\t}\n\n\t/**\n\t * Gets the serialized version of the media type.\n\t *\n\t * @returns {string} The serialized media type.\n\t */\n\ttoString() {\n\t\t// The serialize function works on both 'media type records' (i.e. the results of parse) and on this class, since\n\t\t// this class's interface is identical.\n\t\treturn serialize(this);\n\t}\n\n\t/**\n\t * Determines if this instance is a JavaScript media type.\n\t *\n\t * @param {Object} [options] Optional options.\n\t * @param {boolean} [options.prohibitParameters=false] The option to prohibit parameters when checking if the media type is JavaScript.\n\t * @returns {boolean} true if this instance represents a JavaScript media type, false otherwise.\n\t */\n\tisJavaScript({prohibitParameters = false} = {}) {\n\t\tswitch (this.#type) {\n\t\t\tcase 'text': {\n\t\t\t\tswitch (this.#subtype) {\n\t\t\t\t\tcase 'ecmascript':\n\t\t\t\t\tcase 'javascript':\n\t\t\t\t\tcase 'javascript1.0':\n\t\t\t\t\tcase 'javascript1.1':\n\t\t\t\t\tcase 'javascript1.2':\n\t\t\t\t\tcase 'javascript1.3':\n\t\t\t\t\tcase 'javascript1.4':\n\t\t\t\t\tcase 'javascript1.5':\n\t\t\t\t\tcase 'jscript':\n\t\t\t\t\tcase 'livescript':\n\t\t\t\t\tcase 'x-ecmascript':\n\t\t\t\t\tcase 'x-javascript': return !prohibitParameters || this.#parameters.size === 0;\n\t\t\t\t\tdefault: return false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tcase 'application': {\n\t\t\t\tswitch (this.#subtype) {\n\t\t\t\t\tcase 'ecmascript':\n\t\t\t\t\tcase 'javascript':\n\t\t\t\t\tcase 'x-ecmascript':\n\t\t\t\t\tcase 'x-javascript': return !prohibitParameters || this.#parameters.size === 0;\n\t\t\t\t\tdefault: return false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tdefault: return false;\n\t\t}\n\t}\n\n\t/**\n\t * Determines if this instance is an XML media type.\n\t *\n\t * @returns {boolean} true if this instance represents an XML media type, false otherwise.\n\t */\n\tisXML() {\n\t\treturn (this.#subtype === 'xml' && (this.#type === 'text' || this.#type === 'application')) || this.#subtype.endsWith('+xml');\n\t}\n\n\t/**\n\t * Determines if this instance is an HTML media type.\n\t *\n\t * @returns {boolean} true if this instance represents an HTML media type, false otherwise.\n\t */\n\tisHTML() {\n\t\treturn this.#subtype === 'html' && this.#type === 'text';\n\t}\n\n\t/**\n\t * Gets the name of the class.\n\t *\n\t * @returns {string} The class name\n\t */\n\tget [Symbol.toStringTag]() {\n\t\treturn 'MediaType';\n\t}\n}", "/** @module utils */\n\nconst whitespaceCharacters = [' ', '\\t', '\\n', '\\r'];\nconst leadingWhitespace = /^[ \\t\\n\\r]+/u;\nconst trailingWhitespace = /[ \\t\\n\\r]+$/u;\nconst httpTokenCodePoints = /^[-!#$%&'*+.^_`|~A-Za-z0-9]*$/u;\nconst httpQuotedTokenCodePoints = /^[\\t\\u0020-\\u007E\\u0080-\\u00FF]*$/u;\n\n/**\n * A function to remove any leading and trailing HTTP whitespace.\n *\n * @param {string} string The string to process.\n * @returns {string} The processed string.\n */\nconst removeLeadingAndTrailingHTTPWhitespace = (string) => string.replace(leadingWhitespace, '').replace(trailingWhitespace, '');\n\n/**\n * A function to remove any trailing HTTP whitespace.\n *\n * @param {string} string The string to process.\n * @returns {string} The processed string.\n */\nconst removeTrailingHTTPWhitespace = (string) => string.replace(trailingWhitespace, '');\n\n/**\n * Determines if the provided character is whitespace.\n *\n * @param {string} char The character to evaluate.\n * @returns {boolean} true if the character is whitespace, false otherwise.\n */\nconst isHTTPWhitespaceChar = (char) => whitespaceCharacters.includes(char);\n\n/**\n * Determines if the provided string contains only HTTP token code points.\n *\n * @param {string} string The string to evaluate.\n * @returns {boolean} true if the string contains only HTTP token code points.\n */\nconst solelyContainsHTTPTokenCodePoints = (string) => httpTokenCodePoints.test(string);\n\n/**\n * Determines if the provided string contains only quoted HTTP token code points.\n *\n * @param {string} string The string to evaluate.\n * @returns {boolean} true if the string contains only quoted HTTP token code points.\n */\nconst solelyContainsHTTPQuotedStringTokenCodePoints = (string) => httpQuotedTokenCodePoints.test(string);\n\n/**\n * A function to lower case ASCII characters.\n * This implementation iterates over each element of the string, which is treated as an iterable.\n * The elements are destructured into [char, charCode] pairs, where char represents the character,\n * and charCode is assigned the character code using char.charCodeAt(0). If the charCode is not\n * provided, it falls back to the character code obtained from char.charCodeAt(0).\n *\n * @param {string} string The string to process.\n * @returns {string} The processed string with all ASCII characters lower cased.\n */\nconst asciiLowercase = (string) => {\n\tlet result = '';\n\tfor (const [char, charCode = char.charCodeAt(0)] of string) {\n\t\tresult += charCode >= 65 && charCode <= 90 ? String.fromCharCode(charCode + 32) : char;\n\t}\n\n\treturn result;\n};\n\n/**\n * Collects all the HTTP quoted strings.\n * This variant only implements it with the extract-value flag set.\n *\n * @param {string} input The string to process.\n * @param {number} position The starting position.\n * @returns {Array<string|number>} An array that includes the resulting string and updated position.\n */\nconst collectAnHTTPQuotedString = (input, position) => {\n\tlet value = '';\n\n\tfor (let length = input.length, char; ++position < length;) {\n\t\tchar = input[position];\n\n\t\tif (char == '\\\\') {\n\t\t\tvalue += ++position < length ? input[position] : char;\n\t\t} else if (char == '\"') {\n\t\t\tbreak;\n\t\t} else {\n\t\t\tvalue += char;\n\t\t}\n\t}\n\n\treturn [value, position];\n};\n\nexport { removeLeadingAndTrailingHTTPWhitespace, removeTrailingHTTPWhitespace, isHTTPWhitespaceChar, solelyContainsHTTPTokenCodePoints, solelyContainsHTTPQuotedStringTokenCodePoints, asciiLowercase, collectAnHTTPQuotedString };\n", "import { asciiLowercase, solelyContainsHTTPQuotedStringTokenCodePoints, solelyContainsHTTPTokenCodePoints } from './utils.js';\n\n/**\n * Class representing the parameters for a media type record.\n * This class has the equivalent surface API to a JavaScript {@link Map}.\n *\n * However, {@link MediaTypeParameters} methods will always interpret their arguments\n * as appropriate for media types, so parameter names will be lowercased,\n * and attempting to set invalid characters will throw an {@link Error}.\n *\n * @example charset=utf-8\n * @see https://mimesniff.spec.whatwg.org/#mime-type-essence\n * @see https://mimesniff.spec.whatwg.org/#mime-type-essence-record\n * @see https://mimesniff.spec.whatwg.org/#mime-type-essence-record-creation\n * @see https://mimesniff.spec.whatwg.org/#mime-type-essence-record-creation-algorithm\n * @module {MediaTypeParameters} media-type-parameters\n * @author D1g1talEntr0py <jason.dimeo@gmail.com>\n */\nexport default class MediaTypeParameters {\n\t/** @type {Map<string, string>} */\n\t#map;\n\n\t/**\n\t * Create a new MediaTypeParameters instance.\n\t *\n\t * @param {Array<Array<string>>} entries An array of [name, value] tuples.\n\t */\n\tconstructor(entries) {\n\t\tthis.#map = new Map(entries);\n\t}\n\n\t/**\n\t * Gets the number of media type parameters.\n\t *\n\t * @returns {number} The number of media type parameters\n\t */\n\tget size() {\n\t\treturn this.#map.size;\n\t}\n\n\t/**\n\t * Gets the media type parameter value for the supplied name.\n\t *\n\t * @param {string} name The name of the media type parameter to retrieve.\n\t * @returns {string} The media type parameter value.\n\t */\n\tget(name) {\n\t\treturn this.#map.get(asciiLowercase(String(name)));\n\t}\n\n\t/**\n\t * Indicates whether the media type parameter with the specified name exists or not.\n\t *\n\t * @param {string} name The name of the media type parameter to check.\n\t * @returns {boolean} true if the media type parameter exists, false otherwise.\n\t */\n\thas(name) {\n\t\treturn this.#map.has(asciiLowercase(String(name)));\n\t}\n\n\t/**\n\t * Adds a new media type parameter using the specified name and value to the MediaTypeParameters.\n\t * If an parameter with the same name already exists, the parameter will be updated.\n\t *\n\t * @param {string} name The name of the media type parameter to set.\n\t * @param {string} value The media type parameter value.\n\t * @returns {MediaTypeParameters} This instance.\n\t */\n\tset(name, value) {\n\t\tname = asciiLowercase(String(name));\n\t\tvalue = String(value);\n\n\t\tif (!solelyContainsHTTPTokenCodePoints(name)) {\n\t\t\tthrow new Error(`Invalid media type parameter name \"${name}\": only HTTP token code points are valid.`);\n\t\t}\n\n\t\tif (!solelyContainsHTTPQuotedStringTokenCodePoints(value)) {\n\t\t\tthrow new Error(`Invalid media type parameter value \"${value}\": only HTTP quoted-string token code points are valid.`);\n\t\t}\n\n\t\tthis.#map.set(name, value);\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Clears all the media type parameters.\n\t */\n\tclear() {\n\t\tthis.#map.clear();\n\t}\n\n\t/**\n\t * Removes the media type parameter using the specified name.\n\t *\n\t * @param {string} name The name of the media type parameter to delete.\n\t * @returns {boolean} true if the parameter existed and has been removed, or false if the parameter does not exist.\n\t */\n\tdelete(name) {\n\t\tname = asciiLowercase(String(name));\n\t\treturn this.#map.delete(name);\n\t}\n\n\t/**\n\t * Executes a provided function once per each name/value pair in the MediaTypeParameters, in insertion order.\n\t *\n\t * @param {function(string, string): void} callback The function called on each iteration.\n\t * @param {*} [thisArg] Optional object when binding 'this' to the callback.\n\t */\n\tforEach(callback, thisArg) {\n\t\tthis.#map.forEach(callback, thisArg);\n\t}\n\n\t/**\n\t * Returns an iterable of parameter names.\n\t *\n\t * @returns {IterableIterator<string>} The {@link IterableIterator} of media type parameter names.\n\t */\n\tkeys() {\n\t\treturn this.#map.keys();\n\t}\n\n\t/**\n\t * Returns an iterable of parameter values.\n\t *\n\t * @returns {IterableIterator<string>} The {@link IterableIterator} of media type parameter values.\n\t */\n\tvalues() {\n\t\treturn this.#map.values();\n\t}\n\n\t/**\n\t * Returns an iterable of name, value pairs for every parameter entry in the media type parameters.\n\t *\n\t * @returns {IterableIterator<Array<Array<string>>>} The media type parameter entries.\n\t */\n\tentries() {\n\t\treturn this.#map.entries();\n\t}\n\n\t/**\n\t * A method that returns the default iterator for the {@link MediaTypeParameters}. Called by the semantics of the for-of statement.\n\t *\n\t * @returns {Iterator<string, string, undefined>} The {@link Symbol.iterator} for the media type parameters.\n\t */\n\t[Symbol.iterator]() {\n\t\treturn this.#map[Symbol.iterator]();\n\t}\n\n\t/**\n\t * Returns a string representation of the media type parameters.\n\t * This method is called by the `String()` function.\n\t *\n\t * @example\n\t * const parameters = new MediaTypeParameters(new Map([['charset', 'utf-8']]));\n\t * String(parameters); // 'charset=utf-8'\n\t * parameters.toString(); // 'charset=utf-8'\n\t * parameters + ''; // 'charset=utf-8'\n\t * `${parameters}`; // 'charset=utf-8'\n\t * parameters[Symbol.toStringTag]; // 'MediaTypeParameters'\n\t * parameters[Symbol.toStringTag](); // 'MediaTypeParameters'\n\t * Object.prototype.toString.call(parameters); // '[object MediaTypeParameters]'\n\t * parameters + ''; // 'charset=utf-8'\n\t * @returns {string} The string representation of the media type parameters.\n\t */\n\t[Symbol.toStringTag]() {\n\t\treturn 'MediaTypeParameters';\n\t}\n}", "import {\n\tasciiLowercase,\n\tcollectAnHTTPQuotedString, isHTTPWhitespaceChar, removeLeadingAndTrailingHTTPWhitespace,\n\tremoveTrailingHTTPWhitespace, solelyContainsHTTPQuotedStringTokenCodePoints, solelyContainsHTTPTokenCodePoints\n} from './utils.js';\n\n/**\n * Function to parse a media type.\n *\n * @module parser\n * @param {string} input The media type to parse\n * @returns {{ type: string, subtype: string, parameters: Map<string, string> }} An object populated with the parsed media type properties and any parameters.\n */\nconst parse = (input) => {\n\tinput = removeLeadingAndTrailingHTTPWhitespace(input);\n\n\tlet position = 0;\n\tlet type = '';\n\twhile (position < input.length && input[position] != '/') {\n\t\ttype += input[position];\n\t\t++position;\n\t}\n\n\tif (type.length === 0 || !solelyContainsHTTPTokenCodePoints(type)) {\n\t\treturn null;\n\t}\n\n\tif (position >= input.length) {\n\t\treturn null;\n\t}\n\n\t// Skips past \"/\"\n\t++position;\n\n\tlet subtype = '';\n\twhile (position < input.length && input[position] != ';') {\n\t\tsubtype += input[position];\n\t\t++position;\n\t}\n\n\tsubtype = removeTrailingHTTPWhitespace(subtype);\n\n\tif (subtype.length === 0 || !solelyContainsHTTPTokenCodePoints(subtype)) {\n\t\treturn null;\n\t}\n\n\tconst mediaType = {\n\t\ttype: asciiLowercase(type),\n\t\tsubtype: asciiLowercase(subtype),\n\t\tparameters: new Map()\n\t};\n\n\twhile (position < input.length) {\n\t\t// Skip past \";\"\n\t\t++position;\n\n\t\twhile (isHTTPWhitespaceChar(input[position])) {\n\t\t\t++position;\n\t\t}\n\n\t\tlet parameterName = '';\n\t\twhile (position < input.length && input[position] != ';' && input[position] != '=') {\n\t\t\tparameterName += input[position];\n\t\t\t++position;\n\t\t}\n\t\tparameterName = asciiLowercase(parameterName);\n\n\t\tif (position < input.length) {\n\t\t\tif (input[position] == ';') {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Skip past \"=\"\n\t\t\t++position;\n\t\t}\n\n\t\tlet parameterValue = null;\n\t\tif (input[position] == '\"') {\n\t\t\t[parameterValue, position] = collectAnHTTPQuotedString(input, position);\n\n\t\t\twhile (position < input.length && input[position] != ';') {\n\t\t\t\t++position;\n\t\t\t}\n\t\t} else {\n\t\t\tparameterValue = '';\n\t\t\twhile (position < input.length && input[position] != ';') {\n\t\t\t\tparameterValue += input[position];\n\t\t\t\t++position;\n\t\t\t}\n\n\t\t\tparameterValue = removeTrailingHTTPWhitespace(parameterValue);\n\n\t\t\tif (parameterValue === '') {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\tif (parameterName.length > 0 &&\tsolelyContainsHTTPTokenCodePoints(parameterName) &&\tsolelyContainsHTTPQuotedStringTokenCodePoints(parameterValue) && !mediaType.parameters.has(parameterName)) {\n\t\t\tmediaType.parameters.set(parameterName, parameterValue);\n\t\t}\n\t}\n\n\treturn mediaType;\n};\n\nexport default parse;", "import { solelyContainsHTTPTokenCodePoints } from './utils.js';\n\n/** @typedef { import('./media-type.js').default } MediaType */\n\n/**\n * A function that serializes the provided {@link mediaType} to a string.\n *\n * @module serializer\n * @param {MediaType} mediaType The media type to serialize.\n * @returns {string} The serialized media type.\n */\nconst serialize = (mediaType) => {\n\tlet serialization = `${mediaType.type}/${mediaType.subtype}`;\n\n\tif (mediaType.parameters.size === 0) {\n\t\treturn serialization;\n\t}\n\n\tfor (let [name, value] of mediaType.parameters) {\n\t\tserialization += `;${name}=`;\n\n\t\tif (!solelyContainsHTTPTokenCodePoints(value) || value.length === 0) {\n\t\t\tvalue = `\"${value.replace(/([\"\\\\])/ug, '\\\\$1')}\"`;\n\t\t}\n\n\t\tserialization += value;\n\t}\n\n\treturn serialization;\n};\n\nexport default serialize;"],
5
+ "mappings": "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",
6
+ "names": ["media_type_exports", "__export", "MediaType", "whitespaceCharacters", "leadingWhitespace", "trailingWhitespace", "httpTokenCodePoints", "httpQuotedTokenCodePoints", "removeLeadingAndTrailingHTTPWhitespace", "string", "removeTrailingHTTPWhitespace", "isHTTPWhitespaceChar", "char", "solelyContainsHTTPTokenCodePoints", "solelyContainsHTTPQuotedStringTokenCodePoints", "asciiLowercase", "result", "charCode", "collectAnHTTPQuotedString", "input", "position", "value", "length", "MediaTypeParameters", "#map", "entries", "name", "asciiLowercase", "value", "solelyContainsHTTPTokenCodePoints", "solelyContainsHTTPQuotedStringTokenCodePoints", "callback", "thisArg", "parse", "input", "removeLeadingAndTrailingHTTPWhitespace", "position", "type", "solelyContainsHTTPTokenCodePoints", "subtype", "removeTrailingHTTPWhitespace", "mediaType", "asciiLowercase", "isHTTPWhitespaceChar", "parameterName", "parameterValue", "collectAnHTTPQuotedString", "solelyContainsHTTPQuotedStringTokenCodePoints", "parser_default", "serialize", "mediaType", "serialization", "name", "value", "solelyContainsHTTPTokenCodePoints", "serializer_default", "MediaType", "#type", "#subtype", "#parameters", "mediaType", "parameters", "type", "subtype", "parsedParameters", "parser_default", "MediaTypeParameters", "name", "value", "asciiLowercase", "string", "solelyContainsHTTPTokenCodePoints", "serializer_default", "prohibitParameters"]
7
7
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@d1g1tal/media-type",
3
3
  "description": "Parses, serializes, and manipulates media types, according to the WHATWG MIME Sniffing Standard",
4
- "version": "4.0.1",
4
+ "version": "4.1.0",
5
5
  "author": "Domenic Denicola <d@domenic.me> (https://domenic.me/)",
6
6
  "maintainers": [
7
7
  {
@@ -53,21 +53,18 @@
53
53
  },
54
54
  "devDependencies": {
55
55
  "@skypack/package-check": "^0.2.2",
56
- "esbuild": "^0.15.12",
57
- "eslint": "^8.25.0",
58
- "eslint-plugin-compat": "^4.0.2",
59
- "eslint-plugin-jsdoc": "^39.3.14",
60
- "jest": "^29.2.1",
61
- "minipass-fetch": "^3.0.0",
56
+ "esbuild": "^0.17.19",
57
+ "eslint": "^8.41.0",
58
+ "eslint-plugin-compat": "^4.1.4",
59
+ "eslint-plugin-jsdoc": "^44.2.4",
60
+ "jest": "^29.5.0",
61
+ "minipass-fetch": "^3.0.3",
62
62
  "printable-string": "^0.3.0",
63
- "rimraf": "^3.0.2",
63
+ "rimraf": "^5.0.1",
64
64
  "whatwg-encoding": "^2.0.0"
65
65
  },
66
66
  "browserslist": [
67
- ">= 0.5%",
68
- "last 2 major versions",
69
- "Firefox ESR",
70
- "not dead",
67
+ "defaults",
71
68
  "not ios_saf < 15",
72
69
  "not op_mini all"
73
70
  ],
@@ -9,16 +9,24 @@ import { asciiLowercase, solelyContainsHTTPQuotedStringTokenCodePoints, solelyCo
9
9
  * and attempting to set invalid characters will throw an {@link Error}.
10
10
  *
11
11
  * @example charset=utf-8
12
- * @module MediaTypeParameters
12
+ * @see https://mimesniff.spec.whatwg.org/#mime-type-essence
13
+ * @see https://mimesniff.spec.whatwg.org/#mime-type-essence-record
14
+ * @see https://mimesniff.spec.whatwg.org/#mime-type-essence-record-creation
15
+ * @see https://mimesniff.spec.whatwg.org/#mime-type-essence-record-creation-algorithm
16
+ * @module {MediaTypeParameters} media-type-parameters
17
+ * @author D1g1talEntr0py <jason.dimeo@gmail.com>
13
18
  */
14
19
  export default class MediaTypeParameters {
20
+ /** @type {Map<string, string>} */
21
+ #map;
22
+
15
23
  /**
16
24
  * Create a new MediaTypeParameters instance.
17
25
  *
18
- * @param {Map.<string, string>} map The map of parameters for a media type.
26
+ * @param {Array<Array<string>>} entries An array of [name, value] tuples.
19
27
  */
20
- constructor(map) {
21
- this._map = map;
28
+ constructor(entries) {
29
+ this.#map = new Map(entries);
22
30
  }
23
31
 
24
32
  /**
@@ -27,7 +35,7 @@ export default class MediaTypeParameters {
27
35
  * @returns {number} The number of media type parameters
28
36
  */
29
37
  get size() {
30
- return this._map.size;
38
+ return this.#map.size;
31
39
  }
32
40
 
33
41
  /**
@@ -37,7 +45,7 @@ export default class MediaTypeParameters {
37
45
  * @returns {string} The media type parameter value.
38
46
  */
39
47
  get(name) {
40
- return this._map.get(asciiLowercase(String(name)));
48
+ return this.#map.get(asciiLowercase(String(name)));
41
49
  }
42
50
 
43
51
  /**
@@ -47,7 +55,7 @@ export default class MediaTypeParameters {
47
55
  * @returns {boolean} true if the media type parameter exists, false otherwise.
48
56
  */
49
57
  has(name) {
50
- return this._map.has(asciiLowercase(String(name)));
58
+ return this.#map.has(asciiLowercase(String(name)));
51
59
  }
52
60
 
53
61
  /**
@@ -70,7 +78,7 @@ export default class MediaTypeParameters {
70
78
  throw new Error(`Invalid media type parameter value "${value}": only HTTP quoted-string token code points are valid.`);
71
79
  }
72
80
 
73
- this._map.set(name, value);
81
+ this.#map.set(name, value);
74
82
 
75
83
  return this;
76
84
  }
@@ -79,7 +87,7 @@ export default class MediaTypeParameters {
79
87
  * Clears all the media type parameters.
80
88
  */
81
89
  clear() {
82
- this._map.clear();
90
+ this.#map.clear();
83
91
  }
84
92
 
85
93
  /**
@@ -90,7 +98,7 @@ export default class MediaTypeParameters {
90
98
  */
91
99
  delete(name) {
92
100
  name = asciiLowercase(String(name));
93
- return this._map.delete(name);
101
+ return this.#map.delete(name);
94
102
  }
95
103
 
96
104
  /**
@@ -100,7 +108,7 @@ export default class MediaTypeParameters {
100
108
  * @param {*} [thisArg] Optional object when binding 'this' to the callback.
101
109
  */
102
110
  forEach(callback, thisArg) {
103
- this._map.forEach(callback, thisArg);
111
+ this.#map.forEach(callback, thisArg);
104
112
  }
105
113
 
106
114
  /**
@@ -109,7 +117,7 @@ export default class MediaTypeParameters {
109
117
  * @returns {IterableIterator<string>} The {@link IterableIterator} of media type parameter names.
110
118
  */
111
119
  keys() {
112
- return this._map.keys();
120
+ return this.#map.keys();
113
121
  }
114
122
 
115
123
  /**
@@ -118,7 +126,7 @@ export default class MediaTypeParameters {
118
126
  * @returns {IterableIterator<string>} The {@link IterableIterator} of media type parameter values.
119
127
  */
120
128
  values() {
121
- return this._map.values();
129
+ return this.#map.values();
122
130
  }
123
131
 
124
132
  /**
@@ -127,7 +135,7 @@ export default class MediaTypeParameters {
127
135
  * @returns {IterableIterator<Array<Array<string>>>} The media type parameter entries.
128
136
  */
129
137
  entries() {
130
- return this._map.entries();
138
+ return this.#map.entries();
131
139
  }
132
140
 
133
141
  /**
@@ -136,6 +144,26 @@ export default class MediaTypeParameters {
136
144
  * @returns {Iterator<string, string, undefined>} The {@link Symbol.iterator} for the media type parameters.
137
145
  */
138
146
  [Symbol.iterator]() {
139
- return this._map[Symbol.iterator]();
147
+ return this.#map[Symbol.iterator]();
148
+ }
149
+
150
+ /**
151
+ * Returns a string representation of the media type parameters.
152
+ * This method is called by the `String()` function.
153
+ *
154
+ * @example
155
+ * const parameters = new MediaTypeParameters(new Map([['charset', 'utf-8']]));
156
+ * String(parameters); // 'charset=utf-8'
157
+ * parameters.toString(); // 'charset=utf-8'
158
+ * parameters + ''; // 'charset=utf-8'
159
+ * `${parameters}`; // 'charset=utf-8'
160
+ * parameters[Symbol.toStringTag]; // 'MediaTypeParameters'
161
+ * parameters[Symbol.toStringTag](); // 'MediaTypeParameters'
162
+ * Object.prototype.toString.call(parameters); // '[object MediaTypeParameters]'
163
+ * parameters + ''; // 'charset=utf-8'
164
+ * @returns {string} The string representation of the media type parameters.
165
+ */
166
+ [Symbol.toStringTag]() {
167
+ return 'MediaTypeParameters';
140
168
  }
141
169
  }
package/src/media-type.js CHANGED
@@ -6,38 +6,41 @@ import { asciiLowercase, solelyContainsHTTPTokenCodePoints } from './utils.js';
6
6
  /**
7
7
  * Class used to parse media types.
8
8
  *
9
+ * @module {MediaType} media-type
9
10
  * @see https://mimesniff.spec.whatwg.org/#understanding-mime-types
10
- * @module MediaType
11
11
  */
12
12
  export default class MediaType {
13
+ /** @type {string} */
14
+ #type;
15
+ /** @type {string} */
16
+ #subtype;
17
+ /** @type {MediaTypeParameters} */
18
+ #parameters;
19
+
13
20
  /**
14
21
  * Create a new MediaType instance from a string representation.
15
22
  *
16
- * @param {string} string The media type to parse
23
+ * @param {string} mediaType The media type to parse.
24
+ * @param {Object} [parameters] Optional parameters.
17
25
  */
18
- constructor(string) {
19
- string = String(string);
20
- const result = parse(string);
21
- if (result === null) {
22
- throw new Error(`Could not parse media type string '${string}'`);
23
- }
24
-
25
- this._type = result.type;
26
- this._subtype = result.subtype;
27
- this._parameters = new MediaTypeParameters(result.parameters);
26
+ constructor(mediaType, parameters = {}) {
27
+ const { type, subtype, parameters: parsedParameters } = parse(mediaType);
28
+ this.#type = type;
29
+ this.#subtype = subtype;
30
+ this.#parameters = new MediaTypeParameters([...parsedParameters, ...Object.entries(parameters).map(([name, value]) => [asciiLowercase(name), asciiLowercase(value)])]);
28
31
  }
29
32
 
30
33
  /**
31
- * Static factor method for parsing a media type.
34
+ * Static factory method for parsing a media type.
32
35
  *
33
- * @param {string} string The media type to parse
34
- * @returns {MediaType} The parsed {@link MediaType} object
36
+ * @param {string} string The media type to parse.
37
+ * @returns {MediaType} The parsed {@link MediaType} object or null if the string could not be parsed.
35
38
  */
36
39
  static parse(string) {
37
40
  try {
38
- return new this(string);
41
+ return new MediaType(string);
39
42
  } catch (e) {
40
- return null;
43
+ throw new Error(`Could not parse media type string '${string}'`);
41
44
  }
42
45
  }
43
46
 
@@ -47,7 +50,7 @@ export default class MediaType {
47
50
  * @returns {string} The media type without any parameters
48
51
  */
49
52
  get essence() {
50
- return `${this.type}/${this.subtype}`;
53
+ return `${this.#type}/${this.#subtype}`;
51
54
  }
52
55
 
53
56
  /**
@@ -56,7 +59,7 @@ export default class MediaType {
56
59
  * @returns {string} The type.
57
60
  */
58
61
  get type() {
59
- return this._type;
62
+ return this.#type;
60
63
  }
61
64
 
62
65
  /**
@@ -72,7 +75,7 @@ export default class MediaType {
72
75
  throw new Error(`Invalid type ${value}: must contain only HTTP token code points`);
73
76
  }
74
77
 
75
- this._type = value;
78
+ this.#type = value;
76
79
  }
77
80
 
78
81
  /**
@@ -81,7 +84,7 @@ export default class MediaType {
81
84
  * @returns {string} The subtype.
82
85
  */
83
86
  get subtype() {
84
- return this._subtype;
87
+ return this.#subtype;
85
88
  }
86
89
 
87
90
  /**
@@ -97,7 +100,7 @@ export default class MediaType {
97
100
  throw new Error(`Invalid subtype ${value}: must contain only HTTP token code points`);
98
101
  }
99
102
 
100
- this._subtype = value;
103
+ this.#subtype = value;
101
104
  }
102
105
 
103
106
  /**
@@ -106,7 +109,7 @@ export default class MediaType {
106
109
  * @returns {MediaTypeParameters} The media type parameters.
107
110
  */
108
111
  get parameters() {
109
- return this._parameters;
112
+ return this.#parameters;
110
113
  }
111
114
 
112
115
  /**
@@ -128,9 +131,9 @@ export default class MediaType {
128
131
  * @returns {boolean} true if this instance represents a JavaScript media type, false otherwise.
129
132
  */
130
133
  isJavaScript({prohibitParameters = false} = {}) {
131
- switch (this._type) {
134
+ switch (this.#type) {
132
135
  case 'text': {
133
- switch (this._subtype) {
136
+ switch (this.#subtype) {
134
137
  case 'ecmascript':
135
138
  case 'javascript':
136
139
  case 'javascript1.0':
@@ -142,16 +145,16 @@ export default class MediaType {
142
145
  case 'jscript':
143
146
  case 'livescript':
144
147
  case 'x-ecmascript':
145
- case 'x-javascript': return !prohibitParameters || this._parameters.size === 0;
148
+ case 'x-javascript': return !prohibitParameters || this.#parameters.size === 0;
146
149
  default: return false;
147
150
  }
148
151
  }
149
152
  case 'application': {
150
- switch (this._subtype) {
153
+ switch (this.#subtype) {
151
154
  case 'ecmascript':
152
155
  case 'javascript':
153
156
  case 'x-ecmascript':
154
- case 'x-javascript': return !prohibitParameters || this._parameters.size === 0;
157
+ case 'x-javascript': return !prohibitParameters || this.#parameters.size === 0;
155
158
  default: return false;
156
159
  }
157
160
  }
@@ -165,7 +168,7 @@ export default class MediaType {
165
168
  * @returns {boolean} true if this instance represents an XML media type, false otherwise.
166
169
  */
167
170
  isXML() {
168
- return (this._subtype === 'xml' && (this._type === 'text' || this._type === 'application')) || this._subtype.endsWith('+xml');
171
+ return (this.#subtype === 'xml' && (this.#type === 'text' || this.#type === 'application')) || this.#subtype.endsWith('+xml');
169
172
  }
170
173
 
171
174
  /**
@@ -174,7 +177,7 @@ export default class MediaType {
174
177
  * @returns {boolean} true if this instance represents an HTML media type, false otherwise.
175
178
  */
176
179
  isHTML() {
177
- return this._subtype === 'html' && this._type === 'text';
180
+ return this.#subtype === 'html' && this.#type === 'text';
178
181
  }
179
182
 
180
183
  /**
package/src/parser.js CHANGED
@@ -16,7 +16,7 @@ const parse = (input) => {
16
16
 
17
17
  let position = 0;
18
18
  let type = '';
19
- while (position < input.length && input[position] !== '/') {
19
+ while (position < input.length && input[position] != '/') {
20
20
  type += input[position];
21
21
  ++position;
22
22
  }
@@ -33,7 +33,7 @@ const parse = (input) => {
33
33
  ++position;
34
34
 
35
35
  let subtype = '';
36
- while (position < input.length && input[position] !== ';') {
36
+ while (position < input.length && input[position] != ';') {
37
37
  subtype += input[position];
38
38
  ++position;
39
39
  }
@@ -59,14 +59,14 @@ const parse = (input) => {
59
59
  }
60
60
 
61
61
  let parameterName = '';
62
- while (position < input.length && input[position] !== ';' && input[position] !== '=') {
62
+ while (position < input.length && input[position] != ';' && input[position] != '=') {
63
63
  parameterName += input[position];
64
64
  ++position;
65
65
  }
66
66
  parameterName = asciiLowercase(parameterName);
67
67
 
68
68
  if (position < input.length) {
69
- if (input[position] === ';') {
69
+ if (input[position] == ';') {
70
70
  continue;
71
71
  }
72
72
 
@@ -75,15 +75,15 @@ const parse = (input) => {
75
75
  }
76
76
 
77
77
  let parameterValue = null;
78
- if (input[position] === '"') {
78
+ if (input[position] == '"') {
79
79
  [parameterValue, position] = collectAnHTTPQuotedString(input, position);
80
80
 
81
- while (position < input.length && input[position] !== ';') {
81
+ while (position < input.length && input[position] != ';') {
82
82
  ++position;
83
83
  }
84
84
  } else {
85
85
  parameterValue = '';
86
- while (position < input.length && input[position] !== ';') {
86
+ while (position < input.length && input[position] != ';') {
87
87
  parameterValue += input[position];
88
88
  ++position;
89
89
  }
@@ -95,10 +95,7 @@ const parse = (input) => {
95
95
  }
96
96
  }
97
97
 
98
- if (parameterName.length > 0 &&
99
- solelyContainsHTTPTokenCodePoints(parameterName) &&
100
- solelyContainsHTTPQuotedStringTokenCodePoints(parameterValue) &&
101
- !mediaType.parameters.has(parameterName)) {
98
+ if (parameterName.length > 0 && solelyContainsHTTPTokenCodePoints(parameterName) && solelyContainsHTTPQuotedStringTokenCodePoints(parameterValue) && !mediaType.parameters.has(parameterName)) {
102
99
  mediaType.parameters.set(parameterName, parameterValue);
103
100
  }
104
101
  }
package/src/serializer.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { solelyContainsHTTPTokenCodePoints } from './utils.js';
2
- // eslint-disable-next-line jsdoc/valid-types
2
+
3
3
  /** @typedef { import('./media-type.js').default } MediaType */
4
4
 
5
5
  /**
@@ -17,13 +17,10 @@ const serialize = (mediaType) => {
17
17
  }
18
18
 
19
19
  for (let [name, value] of mediaType.parameters) {
20
- serialization += ';';
21
- serialization += name;
22
- serialization += '=';
20
+ serialization += `;${name}=`;
23
21
 
24
22
  if (!solelyContainsHTTPTokenCodePoints(value) || value.length === 0) {
25
- value = value.replace(/(["\\])/ug, '\\$1');
26
- value = `"${value}"`;
23
+ value = `"${value.replace(/(["\\])/ug, '\\$1')}"`;
27
24
  }
28
25
 
29
26
  serialization += value;
package/src/utils.js CHANGED
@@ -1,12 +1,18 @@
1
1
  /** @module utils */
2
2
 
3
+ const whitespaceCharacters = [' ', '\t', '\n', '\r'];
4
+ const leadingWhitespace = /^[ \t\n\r]+/u;
5
+ const trailingWhitespace = /[ \t\n\r]+$/u;
6
+ const httpTokenCodePoints = /^[-!#$%&'*+.^_`|~A-Za-z0-9]*$/u;
7
+ const httpQuotedTokenCodePoints = /^[\t\u0020-\u007E\u0080-\u00FF]*$/u;
8
+
3
9
  /**
4
10
  * A function to remove any leading and trailing HTTP whitespace.
5
11
  *
6
12
  * @param {string} string The string to process.
7
13
  * @returns {string} The processed string.
8
14
  */
9
- const removeLeadingAndTrailingHTTPWhitespace = (string) => string.replace(/^[ \t\n\r]+/u, '').replace(/[ \t\n\r]+$/u, '');
15
+ const removeLeadingAndTrailingHTTPWhitespace = (string) => string.replace(leadingWhitespace, '').replace(trailingWhitespace, '');
10
16
 
11
17
  /**
12
18
  * A function to remove any trailing HTTP whitespace.
@@ -14,7 +20,7 @@ const removeLeadingAndTrailingHTTPWhitespace = (string) => string.replace(/^[ \t
14
20
  * @param {string} string The string to process.
15
21
  * @returns {string} The processed string.
16
22
  */
17
- const removeTrailingHTTPWhitespace = (string) => string.replace(/[ \t\n\r]+$/u, '');
23
+ const removeTrailingHTTPWhitespace = (string) => string.replace(trailingWhitespace, '');
18
24
 
19
25
  /**
20
26
  * Determines if the provided character is whitespace.
@@ -22,7 +28,7 @@ const removeTrailingHTTPWhitespace = (string) => string.replace(/[ \t\n\r]+$/u,
22
28
  * @param {string} char The character to evaluate.
23
29
  * @returns {boolean} true if the character is whitespace, false otherwise.
24
30
  */
25
- const isHTTPWhitespaceChar = (char) => char === ' ' || char === '\t' || char === '\n' || char === '\r';
31
+ const isHTTPWhitespaceChar = (char) => whitespaceCharacters.includes(char);
26
32
 
27
33
  /**
28
34
  * Determines if the provided string contains only HTTP token code points.
@@ -30,7 +36,7 @@ const isHTTPWhitespaceChar = (char) => char === ' ' || char === '\t' || char ===
30
36
  * @param {string} string The string to evaluate.
31
37
  * @returns {boolean} true if the string contains only HTTP token code points.
32
38
  */
33
- const solelyContainsHTTPTokenCodePoints = (string) => /^[-!#$%&'*+.^_`|~A-Za-z0-9]*$/u.test(string);
39
+ const solelyContainsHTTPTokenCodePoints = (string) => httpTokenCodePoints.test(string);
34
40
 
35
41
  /**
36
42
  * Determines if the provided string contains only quoted HTTP token code points.
@@ -38,15 +44,26 @@ const solelyContainsHTTPTokenCodePoints = (string) => /^[-!#$%&'*+.^_`|~A-Za-z0-
38
44
  * @param {string} string The string to evaluate.
39
45
  * @returns {boolean} true if the string contains only quoted HTTP token code points.
40
46
  */
41
- const solelyContainsHTTPQuotedStringTokenCodePoints = (string) => /^[\t\u0020-\u007E\u0080-\u00FF]*$/u.test(string);
47
+ const solelyContainsHTTPQuotedStringTokenCodePoints = (string) => httpQuotedTokenCodePoints.test(string);
42
48
 
43
49
  /**
44
50
  * A function to lower case ASCII characters.
51
+ * This implementation iterates over each element of the string, which is treated as an iterable.
52
+ * The elements are destructured into [char, charCode] pairs, where char represents the character,
53
+ * and charCode is assigned the character code using char.charCodeAt(0). If the charCode is not
54
+ * provided, it falls back to the character code obtained from char.charCodeAt(0).
45
55
  *
46
56
  * @param {string} string The string to process.
47
57
  * @returns {string} The processed string with all ASCII characters lower cased.
48
58
  */
49
- const asciiLowercase = (string) => string.replace(/[A-Z]/ug, l => l.toLowerCase());
59
+ const asciiLowercase = (string) => {
60
+ let result = '';
61
+ for (const [char, charCode = char.charCodeAt(0)] of string) {
62
+ result += charCode >= 65 && charCode <= 90 ? String.fromCharCode(charCode + 32) : char;
63
+ }
64
+
65
+ return result;
66
+ };
50
67
 
51
68
  /**
52
69
  * Collects all the HTTP quoted strings.
@@ -54,36 +71,20 @@ const asciiLowercase = (string) => string.replace(/[A-Z]/ug, l => l.toLowerCase(
54
71
  *
55
72
  * @param {string} input The string to process.
56
73
  * @param {number} position The starting position.
57
- * @returns {Array<string | number>} An array that includes the resulting string and updated position.
74
+ * @returns {Array<string|number>} An array that includes the resulting string and updated position.
58
75
  */
59
76
  const collectAnHTTPQuotedString = (input, position) => {
60
77
  let value = '';
61
78
 
62
- position++;
63
-
64
- while (true) {
65
- while (position < input.length && input[position] !== '"' && input[position] !== '\\') {
66
- value += input[position];
67
- ++position;
68
- }
79
+ for (let length = input.length, char; ++position < length;) {
80
+ char = input[position];
69
81
 
70
- if (position >= input.length) {
82
+ if (char == '\\') {
83
+ value += ++position < length ? input[position] : char;
84
+ } else if (char == '"') {
71
85
  break;
72
- }
73
-
74
- const quoteOrBackslash = input[position];
75
- ++position;
76
-
77
- if (quoteOrBackslash === '\\') {
78
- if (position >= input.length) {
79
- value += '\\';
80
- break;
81
- }
82
-
83
- value += input[position];
84
- ++position;
85
86
  } else {
86
- break;
87
+ value += char;
87
88
  }
88
89
  }
89
90