@d1g1tal/media-type 5.0.2 → 6.0.1
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.
- package/CHANGELOG.md +393 -0
- package/README.md +150 -6
- package/package.json +84 -77
- package/dist/media-type.js +0 -299
- package/dist/media-type.min.js +0 -3
- package/dist/media-type.min.js.map +0 -7
- package/src/media-type-parameters.js +0 -111
- package/src/media-type-parser.js +0 -120
- package/src/media-type.js +0 -101
- package/src/utils.js +0 -3
- /package/{LICENSE.txt → LICENSE} +0 -0
package/src/media-type-parser.js
DELETED
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
import MediaTypeParameters from './media-type-parameters.js';
|
|
2
|
-
import httpTokenCodePoints from './utils.js';
|
|
3
|
-
|
|
4
|
-
const whitespaceCharacters = [' ', '\t', '\n', '\r'];
|
|
5
|
-
const trailingWhitespace = /[ \t\n\r]+$/u;
|
|
6
|
-
const leadingAndTrailingWhitespace = /^[ \t\n\r]+|[ \t\n\r]+$/ug;
|
|
7
|
-
|
|
8
|
-
export default class MediaTypeParser {
|
|
9
|
-
/**
|
|
10
|
-
* Function to parse a media type.
|
|
11
|
-
*
|
|
12
|
-
* @static
|
|
13
|
-
* @param {string} input The media type to parse
|
|
14
|
-
* @returns {{ type: string, subtype: string, parameters: MediaTypeParameters }} An object populated with the parsed media type properties and any parameters.
|
|
15
|
-
*/
|
|
16
|
-
static parse(input) {
|
|
17
|
-
input = input.replace(leadingAndTrailingWhitespace, '');
|
|
18
|
-
|
|
19
|
-
const length = input.length, trim = true, lowerCase = false;
|
|
20
|
-
let { position, result: type, subtype = '' } = MediaTypeParser.#filterComponent({ input }, '/');
|
|
21
|
-
|
|
22
|
-
if (!type.length || position >= length || !httpTokenCodePoints.test(type)) { throw new TypeError(MediaTypeParser.#generateErrorMessage('type', type)) }
|
|
23
|
-
|
|
24
|
-
({ position, result: subtype } = MediaTypeParser.#filterComponent({ position: ++position, input, trim }, ';')); // `++position` Skips past "/"
|
|
25
|
-
|
|
26
|
-
if (!subtype.length || !httpTokenCodePoints.test(subtype)) { throw new TypeError(MediaTypeParser.#generateErrorMessage('subtype', subtype)) }
|
|
27
|
-
|
|
28
|
-
let parameterName = '', parameterValue = null;
|
|
29
|
-
const parameters = new MediaTypeParameters();
|
|
30
|
-
|
|
31
|
-
while (position++ < length) { // `position++` Skips past "/"
|
|
32
|
-
while (whitespaceCharacters.includes(input[position])) { ++position }
|
|
33
|
-
|
|
34
|
-
({ position, result: parameterName } = MediaTypeParser.#filterComponent({ position, input, lowerCase }, ';', '='));
|
|
35
|
-
|
|
36
|
-
if (position < length) {
|
|
37
|
-
if (input[position] == ';') { continue }
|
|
38
|
-
|
|
39
|
-
// Skip past "="
|
|
40
|
-
++position;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
if (input[position] == '"') {
|
|
44
|
-
[ parameterValue, position ] = MediaTypeParser.#collectHttpQuotedString(input, position);
|
|
45
|
-
|
|
46
|
-
while (position < length && input[position] != ';') { ++position }
|
|
47
|
-
} else {
|
|
48
|
-
({ position, result: parameterValue } = MediaTypeParser.#filterComponent({ position, input, lowerCase, trim }, ';'));
|
|
49
|
-
|
|
50
|
-
if (!parameterValue) { continue }
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (parameterName && MediaTypeParameters.isValid(parameterName, parameterValue) && !parameters.has(parameterName)) {
|
|
54
|
-
parameters.set(parameterName, parameterValue);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return { type, subtype, parameters };
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Filters a component from the input string.
|
|
63
|
-
*
|
|
64
|
-
* @private
|
|
65
|
-
* @static
|
|
66
|
-
* @param {Object} options The options.
|
|
67
|
-
* @param {number} [options.position] The starting position.
|
|
68
|
-
* @param {string} options.input The input string.
|
|
69
|
-
* @param {boolean} [options.lowerCase] Indicates whether the result should be lowercased.
|
|
70
|
-
* @param {boolean} [options.trim] Indicates whether the result should be trimmed.
|
|
71
|
-
* @param {string[]} charactersToFilter The characters to filter.
|
|
72
|
-
* @returns {{ position: number, result: string }} An object that includes the resulting string and updated position.
|
|
73
|
-
*/
|
|
74
|
-
static #filterComponent({ position = 0, input, lowerCase = true, trim = false }, ...charactersToFilter) {
|
|
75
|
-
let result = '';
|
|
76
|
-
for (const length = input.length; position < length && !charactersToFilter.includes(input[position]); position++) {
|
|
77
|
-
result += input[position];
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
if (lowerCase) { result = result.toLowerCase() }
|
|
81
|
-
if (trim) { result = result.replace(trailingWhitespace, '') }
|
|
82
|
-
|
|
83
|
-
return { position, result };
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Collects all the HTTP quoted strings.
|
|
88
|
-
* This variant only implements it with the extract-value flag set.
|
|
89
|
-
*
|
|
90
|
-
* @private
|
|
91
|
-
* @static
|
|
92
|
-
* @param {string} input The string to process.
|
|
93
|
-
* @param {number} position The starting position.
|
|
94
|
-
* @returns {Array<string|number>} An array that includes the resulting string and updated position.
|
|
95
|
-
*/
|
|
96
|
-
static #collectHttpQuotedString(input, position) {
|
|
97
|
-
let value = '';
|
|
98
|
-
|
|
99
|
-
for (let length = input.length, char; ++position < length;) {
|
|
100
|
-
if ((char = input[position]) == '"') { break }
|
|
101
|
-
|
|
102
|
-
value += char == '\\' && ++position < length ? input[position] : char;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
return [ value, position ];
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Generates an error message.
|
|
110
|
-
*
|
|
111
|
-
* @private
|
|
112
|
-
* @static
|
|
113
|
-
* @param {string} component The component name.
|
|
114
|
-
* @param {string} value The component value.
|
|
115
|
-
* @returns {string} The error message.
|
|
116
|
-
*/
|
|
117
|
-
static #generateErrorMessage(component, value) {
|
|
118
|
-
return `Invalid ${component} "${value}": only HTTP token code points are valid.`;
|
|
119
|
-
}
|
|
120
|
-
}
|
package/src/media-type.js
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { _type } from '@d1g1tal/chrysalis';
|
|
2
|
-
import MediaTypeParameters from './media-type-parameters.js';
|
|
3
|
-
import MediaTypeParser from './media-type-parser.js';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Class used to parse media types.
|
|
7
|
-
*
|
|
8
|
-
* @module {MediaType} media-type
|
|
9
|
-
* @see https://mimesniff.spec.whatwg.org/#understanding-mime-types
|
|
10
|
-
*/
|
|
11
|
-
export default class MediaType {
|
|
12
|
-
/** @type {string} */
|
|
13
|
-
#type;
|
|
14
|
-
/** @type {string} */
|
|
15
|
-
#subtype;
|
|
16
|
-
/** @type {MediaTypeParameters} */
|
|
17
|
-
#parameters;
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Create a new MediaType instance from a string representation.
|
|
21
|
-
*
|
|
22
|
-
* @param {string} mediaType The media type to parse.
|
|
23
|
-
* @param {Object} [parameters] Optional parameters.
|
|
24
|
-
*/
|
|
25
|
-
constructor(mediaType, parameters = {}) {
|
|
26
|
-
if (_type(parameters) != Object) { throw new TypeError('The parameters argument must be an object') }
|
|
27
|
-
({ type: this.#type, subtype: this.#subtype, parameters: this.#parameters } = MediaTypeParser.parse(mediaType));
|
|
28
|
-
for (const [ name, value ] of Object.entries(parameters)) { this.#parameters.set(name, value) }
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
static parse(mediaType) {
|
|
32
|
-
try { return new MediaType(mediaType) } catch(e) { /* ignore */ }
|
|
33
|
-
|
|
34
|
-
return null;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Gets the type.
|
|
39
|
-
*
|
|
40
|
-
* @returns {string} The type.
|
|
41
|
-
*/
|
|
42
|
-
get type() {
|
|
43
|
-
return this.#type;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Gets the subtype.
|
|
48
|
-
*
|
|
49
|
-
* @returns {string} The subtype.
|
|
50
|
-
*/
|
|
51
|
-
get subtype() {
|
|
52
|
-
return this.#subtype;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Gets the media type essence (type/subtype).
|
|
57
|
-
*
|
|
58
|
-
* @returns {string} The media type without any parameters
|
|
59
|
-
*/
|
|
60
|
-
get essence() {
|
|
61
|
-
return `${this.#type}/${this.#subtype}`;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Gets the parameters.
|
|
66
|
-
*
|
|
67
|
-
* @returns {MediaTypeParameters} The media type parameters.
|
|
68
|
-
*/
|
|
69
|
-
get parameters() {
|
|
70
|
-
return this.#parameters;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Checks if the media type matches the specified type.
|
|
75
|
-
*
|
|
76
|
-
* @todo Fix string handling to parse the type and subtype from the string.
|
|
77
|
-
* @param {MediaType|string} mediaType The media type to check.
|
|
78
|
-
* @returns {boolean} true if the media type matches the specified type, false otherwise.
|
|
79
|
-
*/
|
|
80
|
-
matches(mediaType) {
|
|
81
|
-
return (this.#type === mediaType?.type && this.#subtype === mediaType?.subtype) || this.essence.includes(mediaType);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Gets the serialized version of the media type.
|
|
86
|
-
*
|
|
87
|
-
* @returns {string} The serialized media type.
|
|
88
|
-
*/
|
|
89
|
-
toString() {
|
|
90
|
-
return `${this.essence}${this.#parameters.toString()}`;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Gets the name of the class.
|
|
95
|
-
*
|
|
96
|
-
* @returns {string} The class name
|
|
97
|
-
*/
|
|
98
|
-
get [Symbol.toStringTag]() {
|
|
99
|
-
return 'MediaType';
|
|
100
|
-
}
|
|
101
|
-
}
|
package/src/utils.js
DELETED
/package/{LICENSE.txt → LICENSE}
RENAMED
|
File without changes
|