whatwg-mimetype 2.3.0 → 4.0.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.
- package/LICENSE.txt +1 -1
- package/README.md +2 -2
- package/lib/mime-type-parameters.js +70 -0
- package/lib/mime-type.js +5 -69
- package/lib/parser.js +5 -24
- package/lib/serializer.js +1 -1
- package/lib/utils.js +40 -5
- package/package.json +17 -15
package/LICENSE.txt
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Copyright ©
|
|
1
|
+
Copyright © Domenic Denicola <d@domenic.me>
|
|
2
2
|
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
4
|
|
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ console.assert(mimeType.isXML() === false);
|
|
|
24
24
|
|
|
25
25
|
Parsing is a fairly complex process; see [the specification](https://mimesniff.spec.whatwg.org/#parsing-a-mime-type) for details (and similarly [for serialization](https://mimesniff.spec.whatwg.org/#serializing-a-mime-type)).
|
|
26
26
|
|
|
27
|
-
This package's algorithms conform to those of the WHATWG [MIME Sniffing Standard](https://mimesniff.spec.whatwg.org/), and is aligned up to commit [
|
|
27
|
+
This package's algorithms conform to those of the WHATWG [MIME Sniffing Standard](https://mimesniff.spec.whatwg.org/), and is aligned up to commit [8e9a7dd](https://github.com/whatwg/mimesniff/commit/8e9a7dd90717c595a4e4d982cd216e4411d33736).
|
|
28
28
|
|
|
29
29
|
## `MIMEType` API
|
|
30
30
|
|
|
@@ -52,7 +52,7 @@ As an alternative to the constructor, you can use `MIMEType.parse(string)`. The
|
|
|
52
52
|
- `toString()` serializes the MIME type to a string
|
|
53
53
|
- `isHTML()`: returns true if this instance represents [a HTML MIME type](https://mimesniff.spec.whatwg.org/#html-mime-type)
|
|
54
54
|
- `isXML()`: returns true if this instance represents [an XML MIME type](https://mimesniff.spec.whatwg.org/#xml-mime-type)
|
|
55
|
-
- `isJavaScript({
|
|
55
|
+
- `isJavaScript({ prohibitParameters })`: returns true if this instance represents [a JavaScript MIME type](https://html.spec.whatwg.org/multipage/scripting.html#javascript-mime-type). `prohibitParameters` can be set to true to disallow any parameters, i.e. to test if the MIME type's serialization is a [JavaScript MIME type essence match](https://mimesniff.spec.whatwg.org/#javascript-mime-type-essence-match).
|
|
56
56
|
|
|
57
57
|
_Note: the `isHTML()`, `isXML()`, and `isJavaScript()` methods are speculative, and may be removed or changed in future major versions. See [whatwg/mimesniff#48](https://github.com/whatwg/mimesniff/issues/48) for brainstorming in this area. Currently we implement these mainly because they are useful in jsdom._
|
|
58
58
|
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const {
|
|
3
|
+
asciiLowercase,
|
|
4
|
+
solelyContainsHTTPTokenCodePoints,
|
|
5
|
+
soleyContainsHTTPQuotedStringTokenCodePoints
|
|
6
|
+
} = require("./utils.js");
|
|
7
|
+
|
|
8
|
+
module.exports = class MIMETypeParameters {
|
|
9
|
+
constructor(map) {
|
|
10
|
+
this._map = map;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
get size() {
|
|
14
|
+
return this._map.size;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
get(name) {
|
|
18
|
+
name = asciiLowercase(String(name));
|
|
19
|
+
return this._map.get(name);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
has(name) {
|
|
23
|
+
name = asciiLowercase(String(name));
|
|
24
|
+
return this._map.has(name);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
set(name, value) {
|
|
28
|
+
name = asciiLowercase(String(name));
|
|
29
|
+
value = String(value);
|
|
30
|
+
|
|
31
|
+
if (!solelyContainsHTTPTokenCodePoints(name)) {
|
|
32
|
+
throw new Error(`Invalid MIME type parameter name "${name}": only HTTP token code points are valid.`);
|
|
33
|
+
}
|
|
34
|
+
if (!soleyContainsHTTPQuotedStringTokenCodePoints(value)) {
|
|
35
|
+
throw new Error(`Invalid MIME type parameter value "${value}": only HTTP quoted-string token code points are ` +
|
|
36
|
+
`valid.`);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return this._map.set(name, value);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
clear() {
|
|
43
|
+
this._map.clear();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
delete(name) {
|
|
47
|
+
name = asciiLowercase(String(name));
|
|
48
|
+
return this._map.delete(name);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
forEach(callbackFn, thisArg) {
|
|
52
|
+
this._map.forEach(callbackFn, thisArg);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
keys() {
|
|
56
|
+
return this._map.keys();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
values() {
|
|
60
|
+
return this._map.values();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
entries() {
|
|
64
|
+
return this._map.entries();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
[Symbol.iterator]() {
|
|
68
|
+
return this._map[Symbol.iterator]();
|
|
69
|
+
}
|
|
70
|
+
};
|
package/lib/mime-type.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
const MIMETypeParameters = require("./mime-type-parameters.js");
|
|
2
3
|
const parse = require("./parser.js");
|
|
3
4
|
const serialize = require("./serializer.js");
|
|
4
5
|
const {
|
|
5
6
|
asciiLowercase,
|
|
6
|
-
solelyContainsHTTPTokenCodePoints
|
|
7
|
-
soleyContainsHTTPQuotedStringTokenCodePoints
|
|
7
|
+
solelyContainsHTTPTokenCodePoints
|
|
8
8
|
} = require("./utils.js");
|
|
9
9
|
|
|
10
10
|
module.exports = class MIMEType {
|
|
@@ -76,7 +76,7 @@ module.exports = class MIMEType {
|
|
|
76
76
|
return serialize(this);
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
isJavaScript({
|
|
79
|
+
isJavaScript({ prohibitParameters = false } = {}) {
|
|
80
80
|
switch (this._type) {
|
|
81
81
|
case "text": {
|
|
82
82
|
switch (this._subtype) {
|
|
@@ -92,7 +92,7 @@ module.exports = class MIMEType {
|
|
|
92
92
|
case "livescript":
|
|
93
93
|
case "x-ecmascript":
|
|
94
94
|
case "x-javascript": {
|
|
95
|
-
return
|
|
95
|
+
return !prohibitParameters || this._parameters.size === 0;
|
|
96
96
|
}
|
|
97
97
|
default: {
|
|
98
98
|
return false;
|
|
@@ -105,7 +105,7 @@ module.exports = class MIMEType {
|
|
|
105
105
|
case "javascript":
|
|
106
106
|
case "x-ecmascript":
|
|
107
107
|
case "x-javascript": {
|
|
108
|
-
return
|
|
108
|
+
return !prohibitParameters || this._parameters.size === 0;
|
|
109
109
|
}
|
|
110
110
|
default: {
|
|
111
111
|
return false;
|
|
@@ -125,67 +125,3 @@ module.exports = class MIMEType {
|
|
|
125
125
|
return this._subtype === "html" && this._type === "text";
|
|
126
126
|
}
|
|
127
127
|
};
|
|
128
|
-
|
|
129
|
-
class MIMETypeParameters {
|
|
130
|
-
constructor(map) {
|
|
131
|
-
this._map = map;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
get size() {
|
|
135
|
-
return this._map.size;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
get(name) {
|
|
139
|
-
name = asciiLowercase(String(name));
|
|
140
|
-
return this._map.get(name);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
has(name) {
|
|
144
|
-
name = asciiLowercase(String(name));
|
|
145
|
-
return this._map.has(name);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
set(name, value) {
|
|
149
|
-
name = asciiLowercase(String(name));
|
|
150
|
-
value = String(value);
|
|
151
|
-
|
|
152
|
-
if (!solelyContainsHTTPTokenCodePoints(name)) {
|
|
153
|
-
throw new Error(`Invalid MIME type parameter name "${name}": only HTTP token code points are valid.`);
|
|
154
|
-
}
|
|
155
|
-
if (!soleyContainsHTTPQuotedStringTokenCodePoints(value)) {
|
|
156
|
-
throw new Error(`Invalid MIME type parameter value "${value}": only HTTP quoted-string token code points are ` +
|
|
157
|
-
`valid.`);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
return this._map.set(name, value);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
clear() {
|
|
164
|
-
this._map.clear();
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
delete(name) {
|
|
168
|
-
name = asciiLowercase(String(name));
|
|
169
|
-
return this._map.delete(name);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
forEach(callbackFn, thisArg) {
|
|
173
|
-
this._map.forEach(callbackFn, thisArg);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
keys() {
|
|
177
|
-
return this._map.keys();
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
values() {
|
|
181
|
-
return this._map.values();
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
entries() {
|
|
185
|
-
return this._map.entries();
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
[Symbol.iterator]() {
|
|
189
|
-
return this._map[Symbol.iterator]();
|
|
190
|
-
}
|
|
191
|
-
}
|
package/lib/parser.js
CHANGED
|
@@ -5,7 +5,8 @@ const {
|
|
|
5
5
|
isHTTPWhitespaceChar,
|
|
6
6
|
solelyContainsHTTPTokenCodePoints,
|
|
7
7
|
soleyContainsHTTPQuotedStringTokenCodePoints,
|
|
8
|
-
asciiLowercase
|
|
8
|
+
asciiLowercase,
|
|
9
|
+
collectAnHTTPQuotedString
|
|
9
10
|
} = require("./utils.js");
|
|
10
11
|
|
|
11
12
|
module.exports = input => {
|
|
@@ -71,35 +72,15 @@ module.exports = input => {
|
|
|
71
72
|
++position;
|
|
72
73
|
}
|
|
73
74
|
|
|
74
|
-
let parameterValue =
|
|
75
|
+
let parameterValue = null;
|
|
75
76
|
if (input[position] === "\"") {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
while (true) {
|
|
79
|
-
while (position < input.length && input[position] !== "\"" && input[position] !== "\\") {
|
|
80
|
-
parameterValue += input[position];
|
|
81
|
-
++position;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (position < input.length && input[position] === "\\") {
|
|
85
|
-
++position;
|
|
86
|
-
if (position < input.length) {
|
|
87
|
-
parameterValue += input[position];
|
|
88
|
-
++position;
|
|
89
|
-
continue;
|
|
90
|
-
} else {
|
|
91
|
-
parameterValue += "\\";
|
|
92
|
-
break;
|
|
93
|
-
}
|
|
94
|
-
} else {
|
|
95
|
-
break;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
77
|
+
[parameterValue, position] = collectAnHTTPQuotedString(input, position);
|
|
98
78
|
|
|
99
79
|
while (position < input.length && input[position] !== ";") {
|
|
100
80
|
++position;
|
|
101
81
|
}
|
|
102
82
|
} else {
|
|
83
|
+
parameterValue = "";
|
|
103
84
|
while (position < input.length && input[position] !== ";") {
|
|
104
85
|
parameterValue += input[position];
|
|
105
86
|
++position;
|
package/lib/serializer.js
CHANGED
package/lib/utils.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
exports.removeLeadingAndTrailingHTTPWhitespace = string => {
|
|
4
|
-
return string.replace(/^[ \t\n\r]
|
|
4
|
+
return string.replace(/^[ \t\n\r]+/u, "").replace(/[ \t\n\r]+$/u, "");
|
|
5
5
|
};
|
|
6
6
|
|
|
7
7
|
exports.removeTrailingHTTPWhitespace = string => {
|
|
8
|
-
return string.replace(/[ \t\n\r]
|
|
8
|
+
return string.replace(/[ \t\n\r]+$/u, "");
|
|
9
9
|
};
|
|
10
10
|
|
|
11
11
|
exports.isHTTPWhitespaceChar = char => {
|
|
@@ -13,13 +13,48 @@ exports.isHTTPWhitespaceChar = char => {
|
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
exports.solelyContainsHTTPTokenCodePoints = string => {
|
|
16
|
-
return /^[-!#$%&'*+.^_`|~A-Za-z0-9]
|
|
16
|
+
return /^[-!#$%&'*+.^_`|~A-Za-z0-9]*$/u.test(string);
|
|
17
17
|
};
|
|
18
18
|
|
|
19
19
|
exports.soleyContainsHTTPQuotedStringTokenCodePoints = string => {
|
|
20
|
-
return /^[\t\u0020-\u007E\u0080-\u00FF]
|
|
20
|
+
return /^[\t\u0020-\u007E\u0080-\u00FF]*$/u.test(string);
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
exports.asciiLowercase = string => {
|
|
24
|
-
return string.replace(/[A-Z]/
|
|
24
|
+
return string.replace(/[A-Z]/ug, l => l.toLowerCase());
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// This variant only implements it with the extract-value flag set.
|
|
28
|
+
exports.collectAnHTTPQuotedString = (input, position) => {
|
|
29
|
+
let value = "";
|
|
30
|
+
|
|
31
|
+
position++;
|
|
32
|
+
|
|
33
|
+
while (true) {
|
|
34
|
+
while (position < input.length && input[position] !== "\"" && input[position] !== "\\") {
|
|
35
|
+
value += input[position];
|
|
36
|
+
++position;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (position >= input.length) {
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const quoteOrBackslash = input[position];
|
|
44
|
+
++position;
|
|
45
|
+
|
|
46
|
+
if (quoteOrBackslash === "\\") {
|
|
47
|
+
if (position >= input.length) {
|
|
48
|
+
value += "\\";
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
value += input[position];
|
|
53
|
+
++position;
|
|
54
|
+
} else {
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return [value, position];
|
|
25
60
|
};
|
package/package.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"http",
|
|
9
9
|
"whatwg"
|
|
10
10
|
],
|
|
11
|
-
"version": "
|
|
11
|
+
"version": "4.0.0",
|
|
12
12
|
"author": "Domenic Denicola <d@domenic.me> (https://domenic.me/)",
|
|
13
13
|
"license": "MIT",
|
|
14
14
|
"repository": "jsdom/whatwg-mimetype",
|
|
@@ -17,27 +17,29 @@
|
|
|
17
17
|
"lib/"
|
|
18
18
|
],
|
|
19
19
|
"scripts": {
|
|
20
|
-
"test": "
|
|
21
|
-
"coverage": "
|
|
20
|
+
"test": "node --test",
|
|
21
|
+
"coverage": "c8 node --test --experimental-test-coverage",
|
|
22
22
|
"lint": "eslint .",
|
|
23
23
|
"pretest": "node scripts/get-latest-platform-tests.js"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"eslint": "^
|
|
27
|
-
"
|
|
26
|
+
"@domenic/eslint-config": "^3.0.0",
|
|
27
|
+
"c8": "^8.0.1",
|
|
28
|
+
"eslint": "^8.53.0",
|
|
28
29
|
"printable-string": "^0.3.0",
|
|
29
|
-
"
|
|
30
|
-
"whatwg-encoding": "^1.0.5"
|
|
30
|
+
"whatwg-encoding": "^3.0.0"
|
|
31
31
|
},
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=18"
|
|
34
|
+
},
|
|
35
|
+
"c8": {
|
|
36
|
+
"reporter": [
|
|
37
|
+
"text",
|
|
38
|
+
"html"
|
|
37
39
|
],
|
|
38
|
-
"
|
|
39
|
-
|
|
40
|
-
"
|
|
40
|
+
"exclude": [
|
|
41
|
+
"scripts/",
|
|
42
|
+
"test/"
|
|
41
43
|
]
|
|
42
44
|
}
|
|
43
45
|
}
|