webpack 5.94.0 → 5.96.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/README.md +1 -1
- package/lib/AsyncDependenciesBlock.js +1 -1
- package/lib/BannerPlugin.js +2 -1
- package/lib/Chunk.js +30 -0
- package/lib/ChunkGraph.js +11 -6
- package/lib/ChunkGroup.js +2 -2
- package/lib/CleanPlugin.js +4 -5
- package/lib/CodeGenerationResults.js +6 -5
- package/lib/Compilation.js +71 -48
- package/lib/Compiler.js +7 -5
- package/lib/ConcatenationScope.js +7 -20
- package/lib/ContextModule.js +7 -8
- package/lib/CssModule.js +25 -21
- package/lib/DefinePlugin.js +14 -8
- package/lib/DelegatedModule.js +3 -3
- package/lib/DllModule.js +4 -4
- package/lib/DynamicEntryPlugin.js +29 -22
- package/lib/EnvironmentPlugin.js +3 -2
- package/lib/EvalDevToolModulePlugin.js +5 -2
- package/lib/EvalSourceMapDevToolPlugin.js +5 -2
- package/lib/ExternalModule.js +118 -99
- package/lib/ExternalModuleFactoryPlugin.js +33 -9
- package/lib/FileSystemInfo.js +12 -8
- package/lib/Generator.js +5 -4
- package/lib/HotModuleReplacementPlugin.js +8 -6
- package/lib/IgnorePlugin.js +19 -1
- package/lib/LoaderOptionsPlugin.js +3 -1
- package/lib/Module.js +9 -8
- package/lib/ModuleSourceTypesConstants.js +100 -0
- package/lib/NormalModule.js +27 -13
- package/lib/NormalModuleFactory.js +38 -22
- package/lib/OptionsApply.js +12 -1
- package/lib/ProgressPlugin.js +50 -10
- package/lib/RawModule.js +3 -4
- package/lib/RuntimeModule.js +3 -4
- package/lib/RuntimePlugin.js +11 -4
- package/lib/RuntimeTemplate.js +13 -42
- package/lib/SourceMapDevToolPlugin.js +10 -7
- package/lib/TemplatedPathPlugin.js +9 -3
- package/lib/Watching.js +2 -2
- package/lib/WebpackOptionsApply.js +42 -21
- package/lib/asset/AssetGenerator.js +347 -194
- package/lib/asset/AssetModulesPlugin.js +2 -1
- package/lib/asset/AssetSourceGenerator.js +82 -27
- package/lib/asset/RawDataUrlModule.js +5 -4
- package/lib/buildChunkGraph.js +79 -62
- package/lib/cache/PackFileCacheStrategy.js +69 -31
- package/lib/cache/ResolverCachePlugin.js +248 -173
- package/lib/config/defaults.js +135 -126
- package/lib/container/ContainerEntryModule.js +3 -4
- package/lib/container/ContainerPlugin.js +8 -0
- package/lib/container/FallbackModule.js +2 -2
- package/lib/container/HoistContainerReferencesPlugin.js +250 -0
- package/lib/container/ModuleFederationPlugin.js +38 -1
- package/lib/container/RemoteModule.js +4 -2
- package/lib/container/RemoteRuntimeModule.js +4 -2
- package/lib/css/CssExportsGenerator.js +16 -12
- package/lib/css/CssGenerator.js +22 -16
- package/lib/css/CssLoadingRuntimeModule.js +7 -6
- package/lib/css/CssModulesPlugin.js +122 -77
- package/lib/css/CssParser.js +655 -526
- package/lib/css/walkCssTokens.js +1168 -338
- package/lib/debug/ProfilingPlugin.js +5 -0
- package/lib/dependencies/CommonJsExportsParserPlugin.js +5 -2
- package/lib/dependencies/CommonJsImportsParserPlugin.js +3 -6
- package/lib/dependencies/ContextDependency.js +6 -1
- package/lib/dependencies/ContextElementDependency.js +33 -6
- package/lib/dependencies/CssExportDependency.js +3 -3
- package/lib/dependencies/CssLocalIdentifierDependency.js +26 -17
- package/lib/dependencies/CssUrlDependency.js +33 -3
- package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +3 -3
- package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +39 -14
- package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +15 -82
- package/lib/dependencies/HarmonyImportSpecifierDependency.js +5 -2
- package/lib/dependencies/ImportParserPlugin.js +9 -7
- package/lib/dependencies/LoaderPlugin.js +19 -0
- package/lib/dependencies/SystemPlugin.js +2 -1
- package/lib/dependencies/URLPlugin.js +7 -1
- package/lib/dependencies/WorkerPlugin.js +1 -1
- package/lib/esm/ModuleChunkLoadingRuntimeModule.js +4 -2
- package/lib/hmr/HotModuleReplacement.runtime.js +1 -0
- package/lib/hmr/JavascriptHotModuleReplacement.runtime.js +1 -0
- package/lib/hmr/LazyCompilationPlugin.js +16 -4
- package/lib/hmr/lazyCompilationBackend.js +1 -7
- package/lib/index.js +35 -6
- package/lib/javascript/EnableChunkLoadingPlugin.js +2 -2
- package/lib/javascript/JavascriptGenerator.js +8 -8
- package/lib/javascript/JavascriptModulesPlugin.js +166 -88
- package/lib/javascript/JavascriptParser.js +338 -117
- package/lib/json/JsonGenerator.js +5 -5
- package/lib/library/EnableLibraryPlugin.js +2 -2
- package/lib/library/ExportPropertyLibraryPlugin.js +1 -1
- package/lib/library/UmdLibraryPlugin.js +16 -8
- package/lib/logging/Logger.js +11 -11
- package/lib/logging/createConsoleLogger.js +14 -14
- package/lib/logging/truncateArgs.js +1 -1
- package/lib/node/NodeWatchFileSystem.js +3 -1
- package/lib/node/ReadFileCompileAsyncWasmPlugin.js +20 -18
- package/lib/node/ReadFileCompileWasmPlugin.js +1 -2
- package/lib/node/nodeConsole.js +11 -8
- package/lib/optimize/AggressiveSplittingPlugin.js +21 -7
- package/lib/optimize/ConcatenatedModule.js +44 -148
- package/lib/optimize/FlagIncludedChunksPlugin.js +6 -0
- package/lib/optimize/InnerGraphPlugin.js +57 -16
- package/lib/optimize/LimitChunkCountPlugin.js +2 -4
- package/lib/optimize/MergeDuplicateChunksPlugin.js +2 -2
- package/lib/optimize/ModuleConcatenationPlugin.js +4 -2
- package/lib/optimize/RealContentHashPlugin.js +1 -1
- package/lib/optimize/SideEffectsFlagPlugin.js +6 -3
- package/lib/rules/RuleSetCompiler.js +2 -2
- package/lib/runtime/GetChunkFilenameRuntimeModule.js +2 -2
- package/lib/schemes/DataUriPlugin.js +1 -1
- package/lib/serialization/BinaryMiddleware.js +32 -19
- package/lib/serialization/ObjectMiddleware.js +23 -9
- package/lib/serialization/SerializerMiddleware.js +3 -2
- package/lib/serialization/types.js +2 -2
- package/lib/sharing/ConsumeSharedModule.js +2 -3
- package/lib/sharing/ConsumeSharedRuntimeModule.js +3 -1
- package/lib/sharing/ProvideSharedModule.js +2 -3
- package/lib/stats/DefaultStatsFactoryPlugin.js +22 -20
- package/lib/stats/StatsFactory.js +12 -12
- package/lib/stats/StatsPrinter.js +7 -7
- package/lib/util/AsyncQueue.js +17 -1
- package/lib/util/IterableHelpers.js +1 -1
- package/lib/util/LazySet.js +12 -0
- package/lib/util/SetHelpers.js +1 -1
- package/lib/util/cleverMerge.js +48 -24
- package/lib/util/concatenate.js +227 -0
- package/lib/util/create-schema-validation.js +22 -9
- package/lib/util/deprecation.js +86 -28
- package/lib/util/fs.js +10 -10
- package/lib/util/hash/wasm-hash.js +12 -1
- package/lib/util/magicComment.js +21 -0
- package/lib/util/makeSerializable.js +24 -1
- package/lib/util/memoize.js +2 -1
- package/lib/util/runtime.js +10 -1
- package/lib/util/semver.js +130 -23
- package/lib/wasm/EnableWasmLoadingPlugin.js +2 -2
- package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +3 -3
- package/lib/wasm-async/AsyncWebAssemblyGenerator.js +5 -5
- package/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js +5 -5
- package/lib/wasm-sync/WebAssemblyGenerator.js +8 -9
- package/lib/wasm-sync/WebAssemblyJavascriptGenerator.js +5 -5
- package/lib/web/FetchCompileAsyncWasmPlugin.js +1 -2
- package/lib/web/FetchCompileWasmPlugin.js +1 -2
- package/lib/web/JsonpChunkLoadingRuntimeModule.js +6 -6
- package/package.json +19 -20
- package/schemas/WebpackOptions.check.js +1 -1
- package/schemas/WebpackOptions.json +12 -2
- package/types.d.ts +817 -269
- package/lib/util/mergeScope.js +0 -76
package/lib/css/walkCssTokens.js
CHANGED
@@ -7,22 +7,21 @@
|
|
7
7
|
|
8
8
|
/**
|
9
9
|
* @typedef {object} CssTokenCallbacks
|
10
|
-
* @property {function(string, number):
|
11
|
-
* @property {function(string, number, number
|
12
|
-
* @property {function(string, number, number): number=} string
|
13
|
-
* @property {function(string, number, number): number=} leftParenthesis
|
14
|
-
* @property {function(string, number, number): number=} rightParenthesis
|
15
|
-
* @property {function(string, number, number): number=}
|
16
|
-
* @property {function(string, number, number): number=}
|
17
|
-
* @property {function(string, number, number): number=}
|
18
|
-
* @property {function(string, number, number): number=}
|
19
|
-
* @property {function(string, number, number): number=}
|
20
|
-
* @property {function(string, number, number): number=}
|
21
|
-
* @property {function(string, number, number): number=}
|
22
|
-
* @property {function(string, number, number): number=}
|
23
|
-
* @property {function(string, number, number): number=}
|
24
|
-
* @property {function(string, number, number): number=}
|
25
|
-
* @property {function(string, number, number): number=} comma
|
10
|
+
* @property {(function(string, number, number, number, number): number)=} url
|
11
|
+
* @property {(function(string, number, number): number)=} comment
|
12
|
+
* @property {(function(string, number, number): number)=} string
|
13
|
+
* @property {(function(string, number, number): number)=} leftParenthesis
|
14
|
+
* @property {(function(string, number, number): number)=} rightParenthesis
|
15
|
+
* @property {(function(string, number, number): number)=} function
|
16
|
+
* @property {(function(string, number, number): number)=} colon
|
17
|
+
* @property {(function(string, number, number): number)=} atKeyword
|
18
|
+
* @property {(function(string, number, number): number)=} delim
|
19
|
+
* @property {(function(string, number, number): number)=} identifier
|
20
|
+
* @property {(function(string, number, number, boolean): number)=} hash
|
21
|
+
* @property {(function(string, number, number): number)=} leftCurlyBracket
|
22
|
+
* @property {(function(string, number, number): number)=} rightCurlyBracket
|
23
|
+
* @property {(function(string, number, number): number)=} semicolon
|
24
|
+
* @property {(function(string, number, number): number)=} comma
|
26
25
|
*/
|
27
26
|
|
28
27
|
/** @typedef {function(string, number, CssTokenCallbacks): number} CharHandler */
|
@@ -59,12 +58,14 @@ const CC_AT_SIGN = "@".charCodeAt(0);
|
|
59
58
|
|
60
59
|
const CC_LOW_LINE = "_".charCodeAt(0);
|
61
60
|
const CC_LOWER_A = "a".charCodeAt(0);
|
62
|
-
const
|
61
|
+
const CC_LOWER_F = "f".charCodeAt(0);
|
63
62
|
const CC_LOWER_E = "e".charCodeAt(0);
|
63
|
+
const CC_LOWER_U = "u".charCodeAt(0);
|
64
64
|
const CC_LOWER_Z = "z".charCodeAt(0);
|
65
65
|
const CC_UPPER_A = "A".charCodeAt(0);
|
66
|
+
const CC_UPPER_F = "F".charCodeAt(0);
|
66
67
|
const CC_UPPER_E = "E".charCodeAt(0);
|
67
|
-
const CC_UPPER_U = "
|
68
|
+
const CC_UPPER_U = "E".charCodeAt(0);
|
68
69
|
const CC_UPPER_Z = "Z".charCodeAt(0);
|
69
70
|
const CC_0 = "0".charCodeAt(0);
|
70
71
|
const CC_9 = "9".charCodeAt(0);
|
@@ -85,12 +86,12 @@ const _isNewLine = cc =>
|
|
85
86
|
|
86
87
|
/** @type {CharHandler} */
|
87
88
|
const consumeSpace = (input, pos, _callbacks) => {
|
88
|
-
|
89
|
-
|
90
|
-
do {
|
89
|
+
// Consume as much whitespace as possible.
|
90
|
+
while (_isWhiteSpace(input.charCodeAt(pos))) {
|
91
91
|
pos++;
|
92
|
-
|
93
|
-
|
92
|
+
}
|
93
|
+
|
94
|
+
// Return a <whitespace-token>.
|
94
95
|
return pos;
|
95
96
|
};
|
96
97
|
|
@@ -127,313 +128,560 @@ const isIdentStartCodePoint = cc =>
|
|
127
128
|
cc >= 0x80;
|
128
129
|
|
129
130
|
/** @type {CharHandler} */
|
130
|
-
const consumeDelimToken = (input, pos, _callbacks) =>
|
131
|
+
const consumeDelimToken = (input, pos, _callbacks) =>
|
132
|
+
// Return a <delim-token> with its value set to the current input code point.
|
133
|
+
pos;
|
131
134
|
|
132
135
|
/** @type {CharHandler} */
|
133
|
-
const consumeComments = (input, pos,
|
134
|
-
//
|
135
|
-
//
|
136
|
-
//
|
137
|
-
//
|
138
|
-
//
|
139
|
-
|
140
|
-
// But we are silent on errors.
|
141
|
-
if (
|
136
|
+
const consumeComments = (input, pos, callbacks) => {
|
137
|
+
// This section describes how to consume comments from a stream of code points. It returns nothing.
|
138
|
+
// If the next two input code point are U+002F SOLIDUS (/) followed by a U+002A ASTERISK (*),
|
139
|
+
// consume them and all following code points up to and including the first U+002A ASTERISK (*)
|
140
|
+
// followed by a U+002F SOLIDUS (/), or up to an EOF code point.
|
141
|
+
// Return to the start of this step.
|
142
|
+
while (
|
142
143
|
input.charCodeAt(pos) === CC_SOLIDUS &&
|
143
144
|
input.charCodeAt(pos + 1) === CC_ASTERISK
|
144
145
|
) {
|
145
|
-
|
146
|
-
|
146
|
+
const start = pos;
|
147
|
+
pos += 2;
|
148
|
+
|
149
|
+
for (;;) {
|
150
|
+
if (pos === input.length) {
|
151
|
+
// If the preceding paragraph ended by consuming an EOF code point, this is a parse error.
|
152
|
+
return pos;
|
153
|
+
}
|
154
|
+
|
147
155
|
if (
|
148
156
|
input.charCodeAt(pos) === CC_ASTERISK &&
|
149
157
|
input.charCodeAt(pos + 1) === CC_SOLIDUS
|
150
158
|
) {
|
151
159
|
pos += 2;
|
160
|
+
|
161
|
+
if (callbacks.comment) {
|
162
|
+
pos = callbacks.comment(input, start, pos);
|
163
|
+
}
|
164
|
+
|
152
165
|
break;
|
153
166
|
}
|
167
|
+
|
154
168
|
pos++;
|
155
169
|
}
|
156
170
|
}
|
157
|
-
return pos;
|
158
|
-
};
|
159
171
|
|
160
|
-
/** @type {function(number): CharHandler} */
|
161
|
-
const consumeString = quoteCc => (input, pos, callbacks) => {
|
162
|
-
const start = pos;
|
163
|
-
pos = _consumeString(input, pos, quoteCc);
|
164
|
-
if (callbacks.string !== undefined) {
|
165
|
-
pos = callbacks.string(input, start, pos);
|
166
|
-
}
|
167
172
|
return pos;
|
168
173
|
};
|
169
174
|
|
175
|
+
/**
|
176
|
+
* @param {number} cc char code
|
177
|
+
* @returns {boolean} true, if cc is a hex digit
|
178
|
+
*/
|
179
|
+
const _isHexDigit = cc =>
|
180
|
+
_isDigit(cc) ||
|
181
|
+
(cc >= CC_UPPER_A && cc <= CC_UPPER_F) ||
|
182
|
+
(cc >= CC_LOWER_A && cc <= CC_LOWER_F);
|
183
|
+
|
170
184
|
/**
|
171
185
|
* @param {string} input input
|
172
186
|
* @param {number} pos position
|
173
|
-
* @
|
174
|
-
* @returns {number} new position
|
187
|
+
* @returns {number} position
|
175
188
|
*/
|
176
|
-
const
|
189
|
+
const _consumeAnEscapedCodePoint = (input, pos) => {
|
190
|
+
// This section describes how to consume an escaped code point.
|
191
|
+
// It assumes that the U+005C REVERSE SOLIDUS (\) has already been consumed and that the next input code point has already been verified to be part of a valid escape.
|
192
|
+
// It will return a code point.
|
193
|
+
|
194
|
+
// Consume the next input code point.
|
195
|
+
const cc = input.charCodeAt(pos);
|
177
196
|
pos++;
|
197
|
+
|
198
|
+
// EOF
|
199
|
+
// This is a parse error. Return U+FFFD REPLACEMENT CHARACTER (�).
|
200
|
+
if (pos === input.length) {
|
201
|
+
return pos;
|
202
|
+
}
|
203
|
+
|
204
|
+
// hex digit
|
205
|
+
// Consume as many hex digits as possible, but no more than 5.
|
206
|
+
// Note that this means 1-6 hex digits have been consumed in total.
|
207
|
+
// If the next input code point is whitespace, consume it as well.
|
208
|
+
// Interpret the hex digits as a hexadecimal number.
|
209
|
+
// If this number is zero, or is for a surrogate, or is greater than the maximum allowed code point, return U+FFFD REPLACEMENT CHARACTER (�).
|
210
|
+
// Otherwise, return the code point with that value.
|
211
|
+
if (_isHexDigit(cc)) {
|
212
|
+
for (let i = 0; i < 5; i++) {
|
213
|
+
if (_isHexDigit(input.charCodeAt(pos))) {
|
214
|
+
pos++;
|
215
|
+
}
|
216
|
+
}
|
217
|
+
|
218
|
+
if (_isWhiteSpace(input.charCodeAt(pos))) {
|
219
|
+
pos++;
|
220
|
+
}
|
221
|
+
|
222
|
+
return pos;
|
223
|
+
}
|
224
|
+
|
225
|
+
// anything else
|
226
|
+
// Return the current input code point.
|
227
|
+
return pos;
|
228
|
+
};
|
229
|
+
|
230
|
+
/** @type {CharHandler} */
|
231
|
+
const consumeAStringToken = (input, pos, callbacks) => {
|
232
|
+
// This section describes how to consume a string token from a stream of code points.
|
233
|
+
// It returns either a <string-token> or <bad-string-token>.
|
234
|
+
//
|
235
|
+
// This algorithm may be called with an ending code point, which denotes the code point that ends the string.
|
236
|
+
// If an ending code point is not specified, the current input code point is used.
|
237
|
+
const start = pos - 1;
|
238
|
+
const endingCodePoint = input.charCodeAt(pos - 1);
|
239
|
+
|
240
|
+
// Initially create a <string-token> with its value set to the empty string.
|
241
|
+
|
242
|
+
// Repeatedly consume the next input code point from the stream:
|
178
243
|
for (;;) {
|
179
|
-
|
244
|
+
// EOF
|
245
|
+
// This is a parse error. Return the <string-token>.
|
246
|
+
if (pos === input.length) {
|
247
|
+
if (callbacks.string !== undefined) {
|
248
|
+
return callbacks.string(input, start, pos);
|
249
|
+
}
|
250
|
+
|
251
|
+
return pos;
|
252
|
+
}
|
253
|
+
|
180
254
|
const cc = input.charCodeAt(pos);
|
181
|
-
|
182
|
-
|
255
|
+
pos++;
|
256
|
+
|
257
|
+
// ending code point
|
258
|
+
// Return the <string-token>.
|
259
|
+
if (cc === endingCodePoint) {
|
260
|
+
if (callbacks.string !== undefined) {
|
261
|
+
return callbacks.string(input, start, pos);
|
262
|
+
}
|
263
|
+
|
264
|
+
return pos;
|
265
|
+
}
|
266
|
+
// newline
|
267
|
+
// This is a parse error.
|
268
|
+
// Reconsume the current input code point, create a <bad-string-token>, and return it.
|
269
|
+
else if (_isNewLine(cc)) {
|
270
|
+
pos--;
|
183
271
|
// bad string
|
184
272
|
return pos;
|
185
273
|
}
|
186
|
-
|
187
|
-
|
188
|
-
//
|
189
|
-
pos
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
pos
|
274
|
+
// U+005C REVERSE SOLIDUS (\)
|
275
|
+
else if (cc === CC_REVERSE_SOLIDUS) {
|
276
|
+
// If the next input code point is EOF, do nothing.
|
277
|
+
if (pos === input.length) {
|
278
|
+
return pos;
|
279
|
+
}
|
280
|
+
// Otherwise, if the next input code point is a newline, consume it.
|
281
|
+
else if (_isNewLine(input.charCodeAt(pos))) {
|
282
|
+
pos++;
|
283
|
+
}
|
284
|
+
// Otherwise, (the stream starts with a valid escape) consume an escaped code point and append the returned code point to the <string-token>’s value.
|
285
|
+
else if (_ifTwoCodePointsAreValidEscape(input, pos)) {
|
286
|
+
pos = _consumeAnEscapedCodePoint(input, pos);
|
287
|
+
}
|
288
|
+
}
|
289
|
+
// anything else
|
290
|
+
// Append the current input code point to the <string-token>’s value.
|
291
|
+
else {
|
292
|
+
// Append
|
194
293
|
}
|
195
294
|
}
|
196
295
|
};
|
197
296
|
|
198
297
|
/**
|
199
298
|
* @param {number} cc char code
|
200
|
-
* @
|
299
|
+
* @param {number} q char code
|
300
|
+
* @returns {boolean} is non-ASCII code point
|
201
301
|
*/
|
202
|
-
const
|
203
|
-
|
204
|
-
(cc >= CC_LOWER_A && cc <= CC_LOWER_Z) ||
|
205
|
-
(cc >= CC_UPPER_A && cc <= CC_UPPER_Z) ||
|
302
|
+
const isNonASCIICodePoint = (cc, q) =>
|
303
|
+
// Simplify
|
206
304
|
cc > 0x80;
|
305
|
+
/**
|
306
|
+
* @param {number} cc char code
|
307
|
+
* @returns {boolean} is letter
|
308
|
+
*/
|
309
|
+
const isLetter = cc =>
|
310
|
+
(cc >= CC_LOWER_A && cc <= CC_LOWER_Z) ||
|
311
|
+
(cc >= CC_UPPER_A && cc <= CC_UPPER_Z);
|
312
|
+
|
313
|
+
/**
|
314
|
+
* @param {number} cc char code
|
315
|
+
* @param {number} q char code
|
316
|
+
* @returns {boolean} is identifier start code
|
317
|
+
*/
|
318
|
+
const _isIdentStartCodePoint = (cc, q) =>
|
319
|
+
isLetter(cc) || isNonASCIICodePoint(cc, q) || cc === CC_LOW_LINE;
|
320
|
+
|
321
|
+
/**
|
322
|
+
* @param {number} cc char code
|
323
|
+
* @param {number} q char code
|
324
|
+
* @returns {boolean} is identifier code
|
325
|
+
*/
|
326
|
+
const _isIdentCodePoint = (cc, q) =>
|
327
|
+
_isIdentStartCodePoint(cc, q) || _isDigit(cc) || cc === CC_HYPHEN_MINUS;
|
328
|
+
/**
|
329
|
+
* @param {number} cc char code
|
330
|
+
* @returns {boolean} is digit
|
331
|
+
*/
|
332
|
+
const _isDigit = cc => cc >= CC_0 && cc <= CC_9;
|
207
333
|
|
208
334
|
/**
|
209
|
-
* @param {
|
210
|
-
* @param {number}
|
335
|
+
* @param {string} input input
|
336
|
+
* @param {number} pos position
|
337
|
+
* @param {number=} f first code point
|
338
|
+
* @param {number=} s second code point
|
211
339
|
* @returns {boolean} true if two code points are a valid escape
|
212
340
|
*/
|
213
|
-
const
|
341
|
+
const _ifTwoCodePointsAreValidEscape = (input, pos, f, s) => {
|
342
|
+
// This section describes how to check if two code points are a valid escape.
|
343
|
+
// The algorithm described here can be called explicitly with two code points, or can be called with the input stream itself.
|
344
|
+
// In the latter case, the two code points in question are the current input code point and the next input code point, in that order.
|
345
|
+
|
346
|
+
// Note: This algorithm will not consume any additional code point.
|
347
|
+
const first = f || input.charCodeAt(pos - 1);
|
348
|
+
const second = s || input.charCodeAt(pos);
|
349
|
+
|
350
|
+
// If the first code point is not U+005C REVERSE SOLIDUS (\), return false.
|
214
351
|
if (first !== CC_REVERSE_SOLIDUS) return false;
|
352
|
+
// Otherwise, if the second code point is a newline, return false.
|
215
353
|
if (_isNewLine(second)) return false;
|
354
|
+
// Otherwise, return true.
|
216
355
|
return true;
|
217
356
|
};
|
218
357
|
|
219
358
|
/**
|
220
|
-
* @param {
|
221
|
-
* @
|
359
|
+
* @param {string} input input
|
360
|
+
* @param {number} pos position
|
361
|
+
* @param {number=} f first
|
362
|
+
* @param {number=} s second
|
363
|
+
* @param {number=} t third
|
364
|
+
* @returns {boolean} true, if input at pos starts an identifier
|
222
365
|
*/
|
223
|
-
const
|
366
|
+
const _ifThreeCodePointsWouldStartAnIdentSequence = (input, pos, f, s, t) => {
|
367
|
+
// This section describes how to check if three code points would start an ident sequence.
|
368
|
+
// The algorithm described here can be called explicitly with three code points, or can be called with the input stream itself.
|
369
|
+
// In the latter case, the three code points in question are the current input code point and the next two input code points, in that order.
|
370
|
+
|
371
|
+
// Note: This algorithm will not consume any additional code points.
|
372
|
+
|
373
|
+
const first = f || input.charCodeAt(pos - 1);
|
374
|
+
const second = s || input.charCodeAt(pos);
|
375
|
+
const third = t || input.charCodeAt(pos + 1);
|
376
|
+
|
377
|
+
// Look at the first code point:
|
378
|
+
|
379
|
+
// U+002D HYPHEN-MINUS
|
380
|
+
if (first === CC_HYPHEN_MINUS) {
|
381
|
+
// If the second code point is an ident-start code point or a U+002D HYPHEN-MINUS
|
382
|
+
// or a U+002D HYPHEN-MINUS, or the second and third code points are a valid escape, return true.
|
383
|
+
if (
|
384
|
+
_isIdentStartCodePoint(second, pos) ||
|
385
|
+
second === CC_HYPHEN_MINUS ||
|
386
|
+
_ifTwoCodePointsAreValidEscape(input, pos, second, third)
|
387
|
+
) {
|
388
|
+
return true;
|
389
|
+
}
|
390
|
+
return false;
|
391
|
+
}
|
392
|
+
// ident-start code point
|
393
|
+
else if (_isIdentStartCodePoint(first, pos - 1)) {
|
394
|
+
return true;
|
395
|
+
}
|
396
|
+
// U+005C REVERSE SOLIDUS (\)
|
397
|
+
// If the first and second code points are a valid escape, return true. Otherwise, return false.
|
398
|
+
else if (first === CC_REVERSE_SOLIDUS) {
|
399
|
+
if (_ifTwoCodePointsAreValidEscape(input, pos, first, second)) {
|
400
|
+
return true;
|
401
|
+
}
|
402
|
+
|
403
|
+
return false;
|
404
|
+
}
|
405
|
+
// anything else
|
406
|
+
// Return false.
|
407
|
+
return false;
|
408
|
+
};
|
224
409
|
|
225
410
|
/**
|
226
411
|
* @param {string} input input
|
227
412
|
* @param {number} pos position
|
413
|
+
* @param {number=} f first
|
414
|
+
* @param {number=} s second
|
415
|
+
* @param {number=} t third
|
228
416
|
* @returns {boolean} true, if input at pos starts an identifier
|
229
417
|
*/
|
230
|
-
const
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
418
|
+
const _ifThreeCodePointsWouldStartANumber = (input, pos, f, s, t) => {
|
419
|
+
// This section describes how to check if three code points would start a number.
|
420
|
+
// The algorithm described here can be called explicitly with three code points, or can be called with the input stream itself.
|
421
|
+
// In the latter case, the three code points in question are the current input code point and the next two input code points, in that order.
|
422
|
+
|
423
|
+
// Note: This algorithm will not consume any additional code points.
|
424
|
+
|
425
|
+
const first = f || input.charCodeAt(pos - 1);
|
426
|
+
const second = s || input.charCodeAt(pos);
|
427
|
+
const third = t || input.charCodeAt(pos);
|
428
|
+
|
429
|
+
// Look at the first code point:
|
430
|
+
|
431
|
+
// U+002B PLUS SIGN (+)
|
432
|
+
// U+002D HYPHEN-MINUS (-)
|
433
|
+
//
|
434
|
+
// If the second code point is a digit, return true.
|
435
|
+
// Otherwise, if the second code point is a U+002E FULL STOP (.) and the third code point is a digit, return true.
|
436
|
+
// Otherwise, return false.
|
437
|
+
if (first === CC_PLUS_SIGN || first === CC_HYPHEN_MINUS) {
|
438
|
+
if (_isDigit(second)) {
|
439
|
+
return true;
|
440
|
+
} else if (second === CC_FULL_STOP && _isDigit(third)) {
|
441
|
+
return true;
|
442
|
+
}
|
443
|
+
|
444
|
+
return false;
|
445
|
+
}
|
446
|
+
// U+002E FULL STOP (.)
|
447
|
+
// If the second code point is a digit, return true. Otherwise, return false.
|
448
|
+
else if (first === CC_FULL_STOP) {
|
449
|
+
if (_isDigit(second)) {
|
450
|
+
return true;
|
239
451
|
}
|
240
|
-
|
452
|
+
|
453
|
+
return false;
|
241
454
|
}
|
242
|
-
|
243
|
-
|
244
|
-
|
455
|
+
// digit
|
456
|
+
// Return true.
|
457
|
+
else if (_isDigit(first)) {
|
458
|
+
return true;
|
245
459
|
}
|
246
|
-
|
460
|
+
|
461
|
+
// anything else
|
462
|
+
// Return false.
|
463
|
+
return false;
|
247
464
|
};
|
248
465
|
|
249
466
|
/** @type {CharHandler} */
|
250
467
|
const consumeNumberSign = (input, pos, callbacks) => {
|
251
|
-
|
252
|
-
|
253
|
-
|
468
|
+
// If the next input code point is an ident code point or the next two input code points are a valid escape, then:
|
469
|
+
// - Create a <hash-token>.
|
470
|
+
// - If the next 3 input code points would start an ident sequence, set the <hash-token>’s type flag to "id".
|
471
|
+
// - Consume an ident sequence, and set the <hash-token>’s value to the returned string.
|
472
|
+
// - Return the <hash-token>.
|
473
|
+
const start = pos - 1;
|
474
|
+
const first = input.charCodeAt(pos);
|
475
|
+
const second = input.charCodeAt(pos + 1);
|
476
|
+
|
254
477
|
if (
|
255
|
-
|
256
|
-
|
257
|
-
_startsIdentifier(input, pos)
|
478
|
+
_isIdentCodePoint(first, pos - 1) ||
|
479
|
+
_ifTwoCodePointsAreValidEscape(input, pos, first, second)
|
258
480
|
) {
|
259
|
-
|
260
|
-
|
261
|
-
|
481
|
+
const third = input.charCodeAt(pos + 2);
|
482
|
+
let isId = false;
|
483
|
+
|
484
|
+
if (
|
485
|
+
_ifThreeCodePointsWouldStartAnIdentSequence(
|
486
|
+
input,
|
487
|
+
pos,
|
488
|
+
first,
|
489
|
+
second,
|
490
|
+
third
|
491
|
+
)
|
492
|
+
) {
|
493
|
+
isId = true;
|
494
|
+
}
|
495
|
+
|
496
|
+
pos = _consumeAnIdentSequence(input, pos, callbacks);
|
497
|
+
|
498
|
+
if (callbacks.hash !== undefined) {
|
499
|
+
return callbacks.hash(input, start, pos, isId);
|
262
500
|
}
|
501
|
+
|
502
|
+
return pos;
|
263
503
|
}
|
504
|
+
|
505
|
+
// Otherwise, return a <delim-token> with its value set to the current input code point.
|
264
506
|
return pos;
|
265
507
|
};
|
266
508
|
|
267
509
|
/** @type {CharHandler} */
|
268
|
-
const
|
269
|
-
const start = pos;
|
270
|
-
pos++;
|
271
|
-
if (pos === input.length) return pos;
|
272
|
-
const cc = input.charCodeAt(pos);
|
510
|
+
const consumeHyphenMinus = (input, pos, callbacks) => {
|
273
511
|
// If the input stream starts with a number, reconsume the current input code point, consume a numeric token, and return it.
|
274
|
-
if (
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
pos
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
const cc = input.charCodeAt(pos + 1);
|
290
|
-
if (_isNewLine(cc)) return pos;
|
291
|
-
pos = _consumeIdentifier(input, pos, callbacks);
|
292
|
-
if (callbacks.identifier !== undefined) {
|
293
|
-
return callbacks.identifier(input, start, pos);
|
294
|
-
}
|
295
|
-
} else if (_isIdentifierStartCode(cc)) {
|
296
|
-
pos = consumeOtherIdentifier(input, pos - 1, callbacks);
|
512
|
+
if (_ifThreeCodePointsWouldStartANumber(input, pos)) {
|
513
|
+
pos--;
|
514
|
+
return consumeANumericToken(input, pos, callbacks);
|
515
|
+
}
|
516
|
+
// Otherwise, if the next 2 input code points are U+002D HYPHEN-MINUS U+003E GREATER-THAN SIGN (->), consume them and return a <CDC-token>.
|
517
|
+
else if (
|
518
|
+
input.charCodeAt(pos) === CC_HYPHEN_MINUS &&
|
519
|
+
input.charCodeAt(pos + 1) === CC_GREATER_THAN_SIGN
|
520
|
+
) {
|
521
|
+
return pos + 2;
|
522
|
+
}
|
523
|
+
// Otherwise, if the input stream starts with an ident sequence, reconsume the current input code point, consume an ident-like token, and return it.
|
524
|
+
else if (_ifThreeCodePointsWouldStartAnIdentSequence(input, pos)) {
|
525
|
+
pos--;
|
526
|
+
return consumeAnIdentLikeToken(input, pos, callbacks);
|
297
527
|
}
|
528
|
+
|
529
|
+
// Otherwise, return a <delim-token> with its value set to the current input code point.
|
298
530
|
return pos;
|
299
531
|
};
|
300
532
|
|
301
533
|
/** @type {CharHandler} */
|
302
|
-
const
|
303
|
-
const start = pos;
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
534
|
+
const consumeFullStop = (input, pos, callbacks) => {
|
535
|
+
const start = pos - 1;
|
536
|
+
|
537
|
+
// If the input stream starts with a number, reconsume the current input code point, consume a numeric token, and return it.
|
538
|
+
if (_ifThreeCodePointsWouldStartANumber(input, pos)) {
|
539
|
+
pos--;
|
540
|
+
return consumeANumericToken(input, pos, callbacks);
|
541
|
+
}
|
542
|
+
|
543
|
+
// Otherwise, return a <delim-token> with its value set to the current input code point.
|
544
|
+
if (callbacks.delim !== undefined) {
|
545
|
+
return callbacks.delim(input, start, pos);
|
546
|
+
}
|
547
|
+
|
315
548
|
return pos;
|
316
549
|
};
|
317
550
|
|
318
551
|
/** @type {CharHandler} */
|
319
|
-
const
|
320
|
-
|
321
|
-
if (pos
|
322
|
-
|
323
|
-
return
|
324
|
-
|
325
|
-
|
552
|
+
const consumePlusSign = (input, pos, callbacks) => {
|
553
|
+
// If the input stream starts with a number, reconsume the current input code point, consume a numeric token, and return it.
|
554
|
+
if (_ifThreeCodePointsWouldStartANumber(input, pos)) {
|
555
|
+
pos--;
|
556
|
+
return consumeANumericToken(input, pos, callbacks);
|
557
|
+
}
|
558
|
+
|
559
|
+
// Otherwise, return a <delim-token> with its value set to the current input code point.
|
326
560
|
return pos;
|
327
561
|
};
|
328
562
|
|
329
563
|
/** @type {CharHandler} */
|
330
|
-
const
|
331
|
-
|
332
|
-
|
333
|
-
|
564
|
+
const _consumeANumber = (input, pos) => {
|
565
|
+
// This section describes how to consume a number from a stream of code points.
|
566
|
+
// It returns a numeric value, and a type which is either "integer" or "number".
|
567
|
+
|
568
|
+
// Execute the following steps in order:
|
569
|
+
// Initially set type to "integer". Let repr be the empty string.
|
570
|
+
|
571
|
+
// If the next input code point is U+002B PLUS SIGN (+) or U+002D HYPHEN-MINUS (-), consume it and append it to repr.
|
572
|
+
if (
|
573
|
+
input.charCodeAt(pos) === CC_HYPHEN_MINUS ||
|
574
|
+
input.charCodeAt(pos) === CC_PLUS_SIGN
|
575
|
+
) {
|
334
576
|
pos++;
|
335
|
-
if (callbacks.function !== undefined) {
|
336
|
-
return callbacks.function(input, start, pos);
|
337
|
-
}
|
338
|
-
} else if (callbacks.identifier !== undefined) {
|
339
|
-
return callbacks.identifier(input, start, pos);
|
340
577
|
}
|
341
|
-
return pos;
|
342
|
-
};
|
343
578
|
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
579
|
+
// While the next input code point is a digit, consume it and append it to repr.
|
580
|
+
while (_isDigit(input.charCodeAt(pos))) {
|
581
|
+
pos++;
|
582
|
+
}
|
583
|
+
|
584
|
+
// If the next 2 input code points are U+002E FULL STOP (.) followed by a digit, then:
|
585
|
+
// 1. Consume the next input code point and append it to number part.
|
586
|
+
// 2. While the next input code point is a digit, consume it and append it to number part.
|
587
|
+
// 3. Set type to "number".
|
349
588
|
if (
|
350
|
-
pos ===
|
351
|
-
input.
|
589
|
+
input.charCodeAt(pos) === CC_FULL_STOP &&
|
590
|
+
_isDigit(input.charCodeAt(pos + 1))
|
352
591
|
) {
|
353
592
|
pos++;
|
354
|
-
|
355
|
-
while (
|
593
|
+
|
594
|
+
while (_isDigit(input.charCodeAt(pos))) {
|
356
595
|
pos++;
|
357
|
-
if (pos === input.length) return pos;
|
358
|
-
cc = input.charCodeAt(pos);
|
359
596
|
}
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
pos++;
|
383
|
-
if (callbacks.url !== undefined) {
|
384
|
-
return callbacks.url(input, start, pos, contentStart, contentEnd);
|
385
|
-
}
|
386
|
-
return pos;
|
387
|
-
} else if (cc === CC_RIGHT_PARENTHESIS) {
|
388
|
-
contentEnd = pos;
|
389
|
-
pos++;
|
390
|
-
if (callbacks.url !== undefined) {
|
391
|
-
return callbacks.url(input, start, pos, contentStart, contentEnd);
|
392
|
-
}
|
393
|
-
return pos;
|
394
|
-
} else if (cc === CC_LEFT_PARENTHESIS) {
|
395
|
-
return pos;
|
396
|
-
} else {
|
397
|
-
pos++;
|
398
|
-
}
|
399
|
-
if (pos === input.length) return pos;
|
400
|
-
cc = input.charCodeAt(pos);
|
597
|
+
}
|
598
|
+
|
599
|
+
// If the next 2 or 3 input code points are U+0045 LATIN CAPITAL LETTER E (E) or U+0065 LATIN SMALL LETTER E (e), optionally followed by U+002D HYPHEN-MINUS (-) or U+002B PLUS SIGN (+), followed by a digit, then:
|
600
|
+
// 1. Consume the next input code point.
|
601
|
+
// 2. If the next input code point is "+" or "-", consume it and append it to exponent part.
|
602
|
+
// 3. While the next input code point is a digit, consume it and append it to exponent part.
|
603
|
+
// 4. Set type to "number".
|
604
|
+
if (
|
605
|
+
(input.charCodeAt(pos) === CC_LOWER_E ||
|
606
|
+
input.charCodeAt(pos) === CC_UPPER_E) &&
|
607
|
+
(((input.charCodeAt(pos + 1) === CC_HYPHEN_MINUS ||
|
608
|
+
input.charCodeAt(pos + 1) === CC_PLUS_SIGN) &&
|
609
|
+
_isDigit(input.charCodeAt(pos + 2))) ||
|
610
|
+
_isDigit(input.charCodeAt(pos + 1)))
|
611
|
+
) {
|
612
|
+
pos++;
|
613
|
+
|
614
|
+
if (
|
615
|
+
input.charCodeAt(pos) === CC_PLUS_SIGN ||
|
616
|
+
input.charCodeAt(pos) === CC_HYPHEN_MINUS
|
617
|
+
) {
|
618
|
+
pos++;
|
401
619
|
}
|
402
|
-
|
403
|
-
|
404
|
-
|
620
|
+
|
621
|
+
while (_isDigit(input.charCodeAt(pos))) {
|
622
|
+
pos++;
|
405
623
|
}
|
406
|
-
return pos;
|
407
624
|
}
|
625
|
+
|
626
|
+
// Let value be the result of interpreting number part as a base-10 number.
|
627
|
+
|
628
|
+
// If exponent part is non-empty, interpret it as a base-10 integer, then raise 10 to the power of the result, multiply it by value, and set value to that result.
|
629
|
+
|
630
|
+
// Return value and type.
|
631
|
+
return pos;
|
408
632
|
};
|
409
633
|
|
410
634
|
/** @type {CharHandler} */
|
411
|
-
const
|
412
|
-
|
413
|
-
|
635
|
+
const consumeANumericToken = (input, pos, callbacks) => {
|
636
|
+
// This section describes how to consume a numeric token from a stream of code points.
|
637
|
+
// It returns either a <number-token>, <percentage-token>, or <dimension-token>.
|
638
|
+
|
639
|
+
// Consume a number and let number be the result.
|
640
|
+
pos = _consumeANumber(input, pos, callbacks);
|
641
|
+
|
642
|
+
// If the next 3 input code points would start an ident sequence, then:
|
643
|
+
//
|
644
|
+
// - Create a <dimension-token> with the same value and type flag as number, and a unit set initially to the empty string.
|
645
|
+
// - Consume an ident sequence. Set the <dimension-token>’s unit to the returned value.
|
646
|
+
// - Return the <dimension-token>.
|
647
|
+
|
648
|
+
const first = input.charCodeAt(pos);
|
649
|
+
const second = input.charCodeAt(pos + 1);
|
650
|
+
const third = input.charCodeAt(pos + 2);
|
651
|
+
|
414
652
|
if (
|
415
|
-
(
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
return callbacks.pseudoFunction(input, start, pos);
|
425
|
-
}
|
426
|
-
return pos;
|
653
|
+
_ifThreeCodePointsWouldStartAnIdentSequence(
|
654
|
+
input,
|
655
|
+
pos,
|
656
|
+
first,
|
657
|
+
second,
|
658
|
+
third
|
659
|
+
)
|
660
|
+
) {
|
661
|
+
return _consumeAnIdentSequence(input, pos, callbacks);
|
427
662
|
}
|
428
|
-
if
|
429
|
-
|
663
|
+
// Otherwise, if the next input code point is U+0025 PERCENTAGE SIGN (%), consume it.
|
664
|
+
// Create a <percentage-token> with the same value as number, and return it.
|
665
|
+
else if (first === CC_PERCENTAGE) {
|
666
|
+
return pos + 1;
|
667
|
+
}
|
668
|
+
|
669
|
+
// Otherwise, create a <number-token> with the same value and type flag as number, and return it.
|
670
|
+
return pos;
|
671
|
+
};
|
672
|
+
|
673
|
+
/** @type {CharHandler} */
|
674
|
+
const consumeColon = (input, pos, callbacks) => {
|
675
|
+
// Return a <colon-token>.
|
676
|
+
if (callbacks.colon !== undefined) {
|
677
|
+
return callbacks.colon(input, pos - 1, pos);
|
430
678
|
}
|
431
679
|
return pos;
|
432
680
|
};
|
433
681
|
|
434
682
|
/** @type {CharHandler} */
|
435
683
|
const consumeLeftParenthesis = (input, pos, callbacks) => {
|
436
|
-
|
684
|
+
// Return a <(-token>.
|
437
685
|
if (callbacks.leftParenthesis !== undefined) {
|
438
686
|
return callbacks.leftParenthesis(input, pos - 1, pos);
|
439
687
|
}
|
@@ -442,16 +690,26 @@ const consumeLeftParenthesis = (input, pos, callbacks) => {
|
|
442
690
|
|
443
691
|
/** @type {CharHandler} */
|
444
692
|
const consumeRightParenthesis = (input, pos, callbacks) => {
|
445
|
-
|
693
|
+
// Return a <)-token>.
|
446
694
|
if (callbacks.rightParenthesis !== undefined) {
|
447
695
|
return callbacks.rightParenthesis(input, pos - 1, pos);
|
448
696
|
}
|
449
697
|
return pos;
|
450
698
|
};
|
451
699
|
|
700
|
+
/** @type {CharHandler} */
|
701
|
+
const consumeLeftSquareBracket = (input, pos, callbacks) =>
|
702
|
+
// Return a <]-token>.
|
703
|
+
pos;
|
704
|
+
|
705
|
+
/** @type {CharHandler} */
|
706
|
+
const consumeRightSquareBracket = (input, pos, callbacks) =>
|
707
|
+
// Return a <]-token>.
|
708
|
+
pos;
|
709
|
+
|
452
710
|
/** @type {CharHandler} */
|
453
711
|
const consumeLeftCurlyBracket = (input, pos, callbacks) => {
|
454
|
-
|
712
|
+
// Return a <{-token>.
|
455
713
|
if (callbacks.leftCurlyBracket !== undefined) {
|
456
714
|
return callbacks.leftCurlyBracket(input, pos - 1, pos);
|
457
715
|
}
|
@@ -460,7 +718,7 @@ const consumeLeftCurlyBracket = (input, pos, callbacks) => {
|
|
460
718
|
|
461
719
|
/** @type {CharHandler} */
|
462
720
|
const consumeRightCurlyBracket = (input, pos, callbacks) => {
|
463
|
-
|
721
|
+
// Return a <}-token>.
|
464
722
|
if (callbacks.rightCurlyBracket !== undefined) {
|
465
723
|
return callbacks.rightCurlyBracket(input, pos - 1, pos);
|
466
724
|
}
|
@@ -469,7 +727,7 @@ const consumeRightCurlyBracket = (input, pos, callbacks) => {
|
|
469
727
|
|
470
728
|
/** @type {CharHandler} */
|
471
729
|
const consumeSemicolon = (input, pos, callbacks) => {
|
472
|
-
|
730
|
+
// Return a <semicolon-token>.
|
473
731
|
if (callbacks.semicolon !== undefined) {
|
474
732
|
return callbacks.semicolon(input, pos - 1, pos);
|
475
733
|
}
|
@@ -478,7 +736,7 @@ const consumeSemicolon = (input, pos, callbacks) => {
|
|
478
736
|
|
479
737
|
/** @type {CharHandler} */
|
480
738
|
const consumeComma = (input, pos, callbacks) => {
|
481
|
-
|
739
|
+
// Return a <comma-token>.
|
482
740
|
if (callbacks.comma !== undefined) {
|
483
741
|
return callbacks.comma(input, pos - 1, pos);
|
484
742
|
}
|
@@ -486,117 +744,319 @@ const consumeComma = (input, pos, callbacks) => {
|
|
486
744
|
};
|
487
745
|
|
488
746
|
/** @type {CharHandler} */
|
489
|
-
const
|
747
|
+
const _consumeAnIdentSequence = (input, pos) => {
|
748
|
+
// This section describes how to consume an ident sequence from a stream of code points.
|
749
|
+
// It returns a string containing the largest name that can be formed from adjacent code points in the stream, starting from the first.
|
750
|
+
|
751
|
+
// Note: This algorithm does not do the verification of the first few code points that are necessary to ensure the returned code points would constitute an <ident-token>.
|
752
|
+
// If that is the intended use, ensure that the stream starts with an ident sequence before calling this algorithm.
|
753
|
+
|
754
|
+
// Let result initially be an empty string.
|
755
|
+
|
756
|
+
// Repeatedly consume the next input code point from the stream:
|
490
757
|
for (;;) {
|
491
758
|
const cc = input.charCodeAt(pos);
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
_isDigit(cc) ||
|
499
|
-
cc === CC_HYPHEN_MINUS
|
500
|
-
) {
|
501
|
-
pos++;
|
502
|
-
} else {
|
503
|
-
return pos;
|
759
|
+
pos++;
|
760
|
+
|
761
|
+
// ident code point
|
762
|
+
// Append the code point to result.
|
763
|
+
if (_isIdentCodePoint(cc, pos - 1)) {
|
764
|
+
// Nothing
|
504
765
|
}
|
505
|
-
|
766
|
+
// the stream starts with a valid escape
|
767
|
+
// Consume an escaped code point. Append the returned code point to result.
|
768
|
+
else if (_ifTwoCodePointsAreValidEscape(input, pos)) {
|
769
|
+
pos = _consumeAnEscapedCodePoint(input, pos);
|
770
|
+
}
|
771
|
+
// anything else
|
772
|
+
// Reconsume the current input code point. Return result.
|
773
|
+
else {
|
774
|
+
return pos - 1;
|
775
|
+
}
|
776
|
+
}
|
506
777
|
};
|
507
778
|
|
508
|
-
/**
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
779
|
+
/**
|
780
|
+
* @param {number} cc char code
|
781
|
+
* @returns {boolean} true, when cc is the non-printable code point, otherwise false
|
782
|
+
*/
|
783
|
+
const _isNonPrintableCodePoint = cc =>
|
784
|
+
(cc >= 0x00 && cc <= 0x08) ||
|
785
|
+
cc === 0x0b ||
|
786
|
+
(cc >= 0x0e && cc <= 0x1f) ||
|
787
|
+
cc === 0x7f;
|
788
|
+
|
789
|
+
/**
|
790
|
+
* @param {string} input input
|
791
|
+
* @param {number} pos position
|
792
|
+
* @returns {number} position
|
793
|
+
*/
|
794
|
+
const consumeTheRemnantsOfABadUrl = (input, pos) => {
|
795
|
+
// This section describes how to consume the remnants of a bad url from a stream of code points,
|
796
|
+
// "cleaning up" after the tokenizer realizes that it’s in the middle of a <bad-url-token> rather than a <url-token>.
|
797
|
+
// It returns nothing; its sole use is to consume enough of the input stream to reach a recovery point where normal tokenizing can resume.
|
798
|
+
|
799
|
+
// Repeatedly consume the next input code point from the stream:
|
800
|
+
for (;;) {
|
801
|
+
// EOF
|
802
|
+
// Return.
|
803
|
+
if (pos === input.length) {
|
804
|
+
return pos;
|
805
|
+
}
|
806
|
+
|
807
|
+
const cc = input.charCodeAt(pos);
|
514
808
|
pos++;
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
809
|
+
|
810
|
+
// U+0029 RIGHT PARENTHESIS ())
|
811
|
+
// Return.
|
812
|
+
if (cc === CC_RIGHT_PARENTHESIS) {
|
813
|
+
return pos;
|
814
|
+
}
|
815
|
+
// the input stream starts with a valid escape
|
816
|
+
// Consume an escaped code point.
|
817
|
+
// This allows an escaped right parenthesis ("\)") to be encountered without ending the <bad-url-token>.
|
818
|
+
// This is otherwise identical to the "anything else" clause.
|
819
|
+
else if (_ifTwoCodePointsAreValidEscape(input, pos)) {
|
820
|
+
pos = _consumeAnEscapedCodePoint(input, pos);
|
821
|
+
}
|
822
|
+
// anything else
|
823
|
+
// Do nothing.
|
824
|
+
else {
|
825
|
+
// Do nothing.
|
528
826
|
}
|
529
827
|
}
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
828
|
+
};
|
829
|
+
|
830
|
+
/**
|
831
|
+
* @param {string} input input
|
832
|
+
* @param {number} pos position
|
833
|
+
* @param {number} fnStart start
|
834
|
+
* @param {CssTokenCallbacks} callbacks callbacks
|
835
|
+
* @returns {pos} pos
|
836
|
+
*/
|
837
|
+
const consumeAUrlToken = (input, pos, fnStart, callbacks) => {
|
838
|
+
// This section describes how to consume a url token from a stream of code points.
|
839
|
+
// It returns either a <url-token> or a <bad-url-token>.
|
840
|
+
|
841
|
+
// Note: This algorithm assumes that the initial "url(" has already been consumed.
|
842
|
+
// This algorithm also assumes that it’s being called to consume an "unquoted" value, like url(foo).
|
843
|
+
// A quoted value, like url("foo"), is parsed as a <function-token>.
|
844
|
+
// Consume an ident-like token automatically handles this distinction; this algorithm shouldn’t be called directly otherwise.
|
845
|
+
|
846
|
+
// Initially create a <url-token> with its value set to the empty string.
|
847
|
+
|
848
|
+
// Consume as much whitespace as possible.
|
849
|
+
while (_isWhiteSpace(input.charCodeAt(pos))) {
|
850
|
+
pos++;
|
851
|
+
}
|
852
|
+
|
853
|
+
const contentStart = pos;
|
854
|
+
|
855
|
+
// Repeatedly consume the next input code point from the stream:
|
856
|
+
for (;;) {
|
857
|
+
// EOF
|
858
|
+
// This is a parse error. Return the <url-token>.
|
859
|
+
if (pos === input.length) {
|
860
|
+
if (callbacks.url !== undefined) {
|
861
|
+
return callbacks.url(input, fnStart, pos, contentStart, pos - 1);
|
862
|
+
}
|
863
|
+
|
864
|
+
return pos;
|
865
|
+
}
|
866
|
+
|
867
|
+
const cc = input.charCodeAt(pos);
|
868
|
+
pos++;
|
869
|
+
|
870
|
+
// U+0029 RIGHT PARENTHESIS ())
|
871
|
+
// Return the <url-token>.
|
872
|
+
if (cc === CC_RIGHT_PARENTHESIS) {
|
873
|
+
if (callbacks.url !== undefined) {
|
874
|
+
return callbacks.url(input, fnStart, pos, contentStart, pos - 1);
|
875
|
+
}
|
876
|
+
|
877
|
+
return pos;
|
878
|
+
}
|
879
|
+
// whitespace
|
880
|
+
// Consume as much whitespace as possible.
|
881
|
+
// If the next input code point is U+0029 RIGHT PARENTHESIS ()) or EOF, consume it and return the <url-token>
|
882
|
+
// (if EOF was encountered, this is a parse error); otherwise, consume the remnants of a bad url, create a <bad-url-token>, and return it.
|
883
|
+
else if (_isWhiteSpace(cc)) {
|
884
|
+
const end = pos - 1;
|
885
|
+
|
886
|
+
while (_isWhiteSpace(input.charCodeAt(pos))) {
|
887
|
+
pos++;
|
888
|
+
}
|
889
|
+
|
890
|
+
if (pos === input.length) {
|
891
|
+
if (callbacks.url !== undefined) {
|
892
|
+
return callbacks.url(input, fnStart, pos, contentStart, end);
|
544
893
|
}
|
545
|
-
|
894
|
+
|
546
895
|
return pos;
|
547
896
|
}
|
897
|
+
|
898
|
+
if (input.charCodeAt(pos) === CC_RIGHT_PARENTHESIS) {
|
899
|
+
pos++;
|
900
|
+
|
901
|
+
if (callbacks.url !== undefined) {
|
902
|
+
return callbacks.url(input, fnStart, pos, contentStart, end);
|
903
|
+
}
|
904
|
+
|
905
|
+
return pos;
|
906
|
+
}
|
907
|
+
|
908
|
+
// Don't handle bad urls
|
909
|
+
return consumeTheRemnantsOfABadUrl(input, pos);
|
910
|
+
}
|
911
|
+
// U+0022 QUOTATION MARK (")
|
912
|
+
// U+0027 APOSTROPHE (')
|
913
|
+
// U+0028 LEFT PARENTHESIS (()
|
914
|
+
// non-printable code point
|
915
|
+
// This is a parse error. Consume the remnants of a bad url, create a <bad-url-token>, and return it.
|
916
|
+
else if (
|
917
|
+
cc === CC_QUOTATION_MARK ||
|
918
|
+
cc === CC_APOSTROPHE ||
|
919
|
+
cc === CC_LEFT_PARENTHESIS ||
|
920
|
+
_isNonPrintableCodePoint(cc)
|
921
|
+
) {
|
922
|
+
// Don't handle bad urls
|
923
|
+
return consumeTheRemnantsOfABadUrl(input, pos);
|
924
|
+
}
|
925
|
+
// // U+005C REVERSE SOLIDUS (\)
|
926
|
+
// // If the stream starts with a valid escape, consume an escaped code point and append the returned code point to the <url-token>’s value.
|
927
|
+
// // Otherwise, this is a parse error. Consume the remnants of a bad url, create a <bad-url-token>, and return it.
|
928
|
+
else if (cc === CC_REVERSE_SOLIDUS) {
|
929
|
+
if (_ifTwoCodePointsAreValidEscape(input, pos)) {
|
930
|
+
pos = _consumeAnEscapedCodePoint(input, pos);
|
931
|
+
} else {
|
932
|
+
// Don't handle bad urls
|
933
|
+
return consumeTheRemnantsOfABadUrl(input, pos);
|
934
|
+
}
|
935
|
+
}
|
936
|
+
// anything else
|
937
|
+
// Append the current input code point to the <url-token>’s value.
|
938
|
+
else {
|
939
|
+
// Nothing
|
548
940
|
}
|
549
|
-
} else {
|
550
|
-
return pos;
|
551
941
|
}
|
552
|
-
|
553
|
-
|
942
|
+
};
|
943
|
+
|
944
|
+
/** @type {CharHandler} */
|
945
|
+
const consumeAnIdentLikeToken = (input, pos, callbacks) => {
|
946
|
+
const start = pos;
|
947
|
+
// This section describes how to consume an ident-like token from a stream of code points.
|
948
|
+
// It returns an <ident-token>, <function-token>, <url-token>, or <bad-url-token>.
|
949
|
+
pos = _consumeAnIdentSequence(input, pos, callbacks);
|
950
|
+
|
951
|
+
// If string’s value is an ASCII case-insensitive match for "url", and the next input code point is U+0028 LEFT PARENTHESIS ((), consume it.
|
952
|
+
// While the next two input code points are whitespace, consume the next input code point.
|
953
|
+
// If the next one or two input code points are U+0022 QUOTATION MARK ("), U+0027 APOSTROPHE ('), or whitespace followed by U+0022 QUOTATION MARK (") or U+0027 APOSTROPHE ('), then create a <function-token> with its value set to string and return it.
|
954
|
+
// Otherwise, consume a url token, and return it.
|
955
|
+
if (
|
956
|
+
input.slice(start, pos).toLowerCase() === "url" &&
|
957
|
+
input.charCodeAt(pos) === CC_LEFT_PARENTHESIS
|
958
|
+
) {
|
554
959
|
pos++;
|
555
|
-
|
556
|
-
|
960
|
+
const end = pos;
|
961
|
+
|
962
|
+
while (
|
963
|
+
_isWhiteSpace(input.charCodeAt(pos)) &&
|
964
|
+
_isWhiteSpace(input.charCodeAt(pos + 1))
|
965
|
+
) {
|
966
|
+
pos++;
|
967
|
+
}
|
968
|
+
|
969
|
+
if (
|
970
|
+
input.charCodeAt(pos) === CC_QUOTATION_MARK ||
|
971
|
+
input.charCodeAt(pos) === CC_APOSTROPHE ||
|
972
|
+
(_isWhiteSpace(input.charCodeAt(pos)) &&
|
973
|
+
(input.charCodeAt(pos + 1) === CC_QUOTATION_MARK ||
|
974
|
+
input.charCodeAt(pos + 1) === CC_APOSTROPHE))
|
975
|
+
) {
|
976
|
+
if (callbacks.function !== undefined) {
|
977
|
+
return callbacks.function(input, start, end);
|
978
|
+
}
|
979
|
+
|
980
|
+
return pos;
|
981
|
+
}
|
982
|
+
|
983
|
+
return consumeAUrlToken(input, pos, start, callbacks);
|
557
984
|
}
|
985
|
+
|
986
|
+
// Otherwise, if the next input code point is U+0028 LEFT PARENTHESIS ((), consume it.
|
987
|
+
// Create a <function-token> with its value set to string and return it.
|
988
|
+
if (input.charCodeAt(pos) === CC_LEFT_PARENTHESIS) {
|
989
|
+
pos++;
|
990
|
+
|
991
|
+
if (callbacks.function !== undefined) {
|
992
|
+
return callbacks.function(input, start, pos);
|
993
|
+
}
|
994
|
+
|
995
|
+
return pos;
|
996
|
+
}
|
997
|
+
|
998
|
+
// Otherwise, create an <ident-token> with its value set to string and return it.
|
999
|
+
if (callbacks.identifier !== undefined) {
|
1000
|
+
return callbacks.identifier(input, start, pos);
|
1001
|
+
}
|
1002
|
+
|
558
1003
|
return pos;
|
559
1004
|
};
|
560
1005
|
|
561
1006
|
/** @type {CharHandler} */
|
562
1007
|
const consumeLessThan = (input, pos, _callbacks) => {
|
563
|
-
|
564
|
-
|
1008
|
+
// If the next 3 input code points are U+0021 EXCLAMATION MARK U+002D HYPHEN-MINUS U+002D HYPHEN-MINUS (!--), consume them and return a <CDO-token>.
|
1009
|
+
if (input.slice(pos, pos + 3) === "!--") {
|
1010
|
+
return pos + 3;
|
1011
|
+
}
|
1012
|
+
|
1013
|
+
// Otherwise, return a <delim-token> with its value set to the current input code point.
|
1014
|
+
return pos;
|
565
1015
|
};
|
566
1016
|
|
567
1017
|
/** @type {CharHandler} */
|
568
|
-
const
|
569
|
-
const start = pos;
|
570
|
-
|
571
|
-
|
572
|
-
if (
|
573
|
-
|
1018
|
+
const consumeCommercialAt = (input, pos, callbacks) => {
|
1019
|
+
const start = pos - 1;
|
1020
|
+
|
1021
|
+
// If the next 3 input code points would start an ident sequence, consume an ident sequence, create an <at-keyword-token> with its value set to the returned value, and return it.
|
1022
|
+
if (
|
1023
|
+
_ifThreeCodePointsWouldStartAnIdentSequence(
|
1024
|
+
input,
|
1025
|
+
pos,
|
1026
|
+
input.charCodeAt(pos),
|
1027
|
+
input.charCodeAt(pos + 1),
|
1028
|
+
input.charCodeAt(pos + 2)
|
1029
|
+
)
|
1030
|
+
) {
|
1031
|
+
pos = _consumeAnIdentSequence(input, pos, callbacks);
|
1032
|
+
|
574
1033
|
if (callbacks.atKeyword !== undefined) {
|
575
1034
|
pos = callbacks.atKeyword(input, start, pos);
|
576
1035
|
}
|
1036
|
+
|
1037
|
+
return pos;
|
577
1038
|
}
|
1039
|
+
|
1040
|
+
// Otherwise, return a <delim-token> with its value set to the current input code point.
|
578
1041
|
return pos;
|
579
1042
|
};
|
580
1043
|
|
581
1044
|
/** @type {CharHandler} */
|
582
1045
|
const consumeReverseSolidus = (input, pos, callbacks) => {
|
583
|
-
const start = pos;
|
584
|
-
pos++;
|
585
|
-
if (pos === input.length) return pos;
|
586
1046
|
// If the input stream starts with a valid escape, reconsume the current input code point, consume an ident-like token, and return it.
|
587
|
-
if (
|
588
|
-
|
589
|
-
|
590
|
-
input.charCodeAt(pos)
|
591
|
-
)
|
592
|
-
) {
|
593
|
-
return consumeOtherIdentifier(input, pos - 1, callbacks);
|
1047
|
+
if (_ifTwoCodePointsAreValidEscape(input, pos)) {
|
1048
|
+
pos--;
|
1049
|
+
return consumeAnIdentLikeToken(input, pos, callbacks);
|
594
1050
|
}
|
1051
|
+
|
595
1052
|
// Otherwise, this is a parse error. Return a <delim-token> with its value set to the current input code point.
|
596
1053
|
return pos;
|
597
1054
|
};
|
598
1055
|
|
599
|
-
|
1056
|
+
/** @type {CharHandler} */
|
1057
|
+
const consumeAToken = (input, pos, callbacks) => {
|
1058
|
+
const cc = input.charCodeAt(pos - 1);
|
1059
|
+
|
600
1060
|
// https://drafts.csswg.org/css-syntax/#consume-token
|
601
1061
|
switch (cc) {
|
602
1062
|
// whitespace
|
@@ -605,77 +1065,94 @@ const CHAR_MAP = Array.from({ length: 0x80 }, (_, cc) => {
|
|
605
1065
|
case CC_FORM_FEED:
|
606
1066
|
case CC_TAB:
|
607
1067
|
case CC_SPACE:
|
608
|
-
return consumeSpace;
|
1068
|
+
return consumeSpace(input, pos, callbacks);
|
609
1069
|
// U+0022 QUOTATION MARK (")
|
610
1070
|
case CC_QUOTATION_MARK:
|
611
|
-
return
|
1071
|
+
return consumeAStringToken(input, pos, callbacks);
|
612
1072
|
// U+0023 NUMBER SIGN (#)
|
613
1073
|
case CC_NUMBER_SIGN:
|
614
|
-
return consumeNumberSign;
|
1074
|
+
return consumeNumberSign(input, pos, callbacks);
|
615
1075
|
// U+0027 APOSTROPHE (')
|
616
1076
|
case CC_APOSTROPHE:
|
617
|
-
return
|
1077
|
+
return consumeAStringToken(input, pos, callbacks);
|
618
1078
|
// U+0028 LEFT PARENTHESIS (()
|
619
1079
|
case CC_LEFT_PARENTHESIS:
|
620
|
-
return consumeLeftParenthesis;
|
1080
|
+
return consumeLeftParenthesis(input, pos, callbacks);
|
621
1081
|
// U+0029 RIGHT PARENTHESIS ())
|
622
1082
|
case CC_RIGHT_PARENTHESIS:
|
623
|
-
return consumeRightParenthesis;
|
1083
|
+
return consumeRightParenthesis(input, pos, callbacks);
|
624
1084
|
// U+002B PLUS SIGN (+)
|
625
1085
|
case CC_PLUS_SIGN:
|
626
|
-
return
|
1086
|
+
return consumePlusSign(input, pos, callbacks);
|
627
1087
|
// U+002C COMMA (,)
|
628
1088
|
case CC_COMMA:
|
629
|
-
return consumeComma;
|
1089
|
+
return consumeComma(input, pos, callbacks);
|
630
1090
|
// U+002D HYPHEN-MINUS (-)
|
631
1091
|
case CC_HYPHEN_MINUS:
|
632
|
-
return
|
1092
|
+
return consumeHyphenMinus(input, pos, callbacks);
|
633
1093
|
// U+002E FULL STOP (.)
|
634
1094
|
case CC_FULL_STOP:
|
635
|
-
return
|
1095
|
+
return consumeFullStop(input, pos, callbacks);
|
636
1096
|
// U+003A COLON (:)
|
637
1097
|
case CC_COLON:
|
638
|
-
return
|
1098
|
+
return consumeColon(input, pos, callbacks);
|
639
1099
|
// U+003B SEMICOLON (;)
|
640
1100
|
case CC_SEMICOLON:
|
641
|
-
return consumeSemicolon;
|
1101
|
+
return consumeSemicolon(input, pos, callbacks);
|
642
1102
|
// U+003C LESS-THAN SIGN (<)
|
643
1103
|
case CC_LESS_THAN_SIGN:
|
644
|
-
return consumeLessThan;
|
1104
|
+
return consumeLessThan(input, pos, callbacks);
|
645
1105
|
// U+0040 COMMERCIAL AT (@)
|
646
1106
|
case CC_AT_SIGN:
|
647
|
-
return
|
1107
|
+
return consumeCommercialAt(input, pos, callbacks);
|
648
1108
|
// U+005B LEFT SQUARE BRACKET ([)
|
649
1109
|
case CC_LEFT_SQUARE:
|
650
|
-
return
|
1110
|
+
return consumeLeftSquareBracket(input, pos, callbacks);
|
651
1111
|
// U+005C REVERSE SOLIDUS (\)
|
652
1112
|
case CC_REVERSE_SOLIDUS:
|
653
|
-
return consumeReverseSolidus;
|
1113
|
+
return consumeReverseSolidus(input, pos, callbacks);
|
654
1114
|
// U+005D RIGHT SQUARE BRACKET (])
|
655
1115
|
case CC_RIGHT_SQUARE:
|
656
|
-
return
|
1116
|
+
return consumeRightSquareBracket(input, pos, callbacks);
|
657
1117
|
// U+007B LEFT CURLY BRACKET ({)
|
658
1118
|
case CC_LEFT_CURLY:
|
659
|
-
return consumeLeftCurlyBracket;
|
1119
|
+
return consumeLeftCurlyBracket(input, pos, callbacks);
|
660
1120
|
// U+007D RIGHT CURLY BRACKET (})
|
661
1121
|
case CC_RIGHT_CURLY:
|
662
|
-
return consumeRightCurlyBracket;
|
663
|
-
// Optimization
|
664
|
-
case CC_LOWER_U:
|
665
|
-
case CC_UPPER_U:
|
666
|
-
return consumePotentialUrl;
|
1122
|
+
return consumeRightCurlyBracket(input, pos, callbacks);
|
667
1123
|
default:
|
668
1124
|
// digit
|
669
|
-
|
1125
|
+
// Reconsume the current input code point, consume a numeric token, and return it.
|
1126
|
+
if (_isDigit(cc)) {
|
1127
|
+
pos--;
|
1128
|
+
return consumeANumericToken(input, pos, callbacks);
|
1129
|
+
} else if (cc === CC_LOWER_U || cc === CC_UPPER_U) {
|
1130
|
+
// If unicode ranges allowed is true and the input stream would start a unicode-range,
|
1131
|
+
// reconsume the current input code point, consume a unicode-range token, and return it.
|
1132
|
+
// Skip now
|
1133
|
+
// if (_ifThreeCodePointsWouldStartAUnicodeRange(input, pos)) {
|
1134
|
+
// pos--;
|
1135
|
+
// return consumeAUnicodeRangeToken(input, pos, callbacks);
|
1136
|
+
// }
|
1137
|
+
|
1138
|
+
// Otherwise, reconsume the current input code point, consume an ident-like token, and return it.
|
1139
|
+
pos--;
|
1140
|
+
return consumeAnIdentLikeToken(input, pos, callbacks);
|
1141
|
+
}
|
670
1142
|
// ident-start code point
|
671
|
-
|
672
|
-
|
1143
|
+
// Reconsume the current input code point, consume an ident-like token, and return it.
|
1144
|
+
else if (isIdentStartCodePoint(cc)) {
|
1145
|
+
pos--;
|
1146
|
+
return consumeAnIdentLikeToken(input, pos, callbacks);
|
673
1147
|
}
|
1148
|
+
|
674
1149
|
// EOF, but we don't have it
|
1150
|
+
|
675
1151
|
// anything else
|
676
|
-
|
1152
|
+
// Return a <delim-token> with its value set to the current input code point.
|
1153
|
+
return consumeDelimToken(input, pos, callbacks);
|
677
1154
|
}
|
678
|
-
}
|
1155
|
+
};
|
679
1156
|
|
680
1157
|
/**
|
681
1158
|
* @param {string} input input css
|
@@ -689,14 +1166,9 @@ module.exports = (input, callbacks) => {
|
|
689
1166
|
// Consume comments.
|
690
1167
|
pos = consumeComments(input, pos, callbacks);
|
691
1168
|
|
692
|
-
const cc = input.charCodeAt(pos);
|
693
|
-
|
694
1169
|
// Consume the next input code point.
|
695
|
-
|
696
|
-
|
697
|
-
} else {
|
698
|
-
pos++;
|
699
|
-
}
|
1170
|
+
pos++;
|
1171
|
+
pos = consumeAToken(input, pos, callbacks);
|
700
1172
|
}
|
701
1173
|
};
|
702
1174
|
|
@@ -752,6 +1224,23 @@ module.exports.eatWhitespaceAndComments = (input, pos) => {
|
|
752
1224
|
return pos;
|
753
1225
|
};
|
754
1226
|
|
1227
|
+
/**
|
1228
|
+
* @param {string} input input
|
1229
|
+
* @param {number} pos position
|
1230
|
+
* @returns {number} position after whitespace and comments
|
1231
|
+
*/
|
1232
|
+
module.exports.eatComments = (input, pos) => {
|
1233
|
+
for (;;) {
|
1234
|
+
const originalPos = pos;
|
1235
|
+
pos = consumeComments(input, pos, {});
|
1236
|
+
if (originalPos === pos) {
|
1237
|
+
break;
|
1238
|
+
}
|
1239
|
+
}
|
1240
|
+
|
1241
|
+
return pos;
|
1242
|
+
};
|
1243
|
+
|
755
1244
|
/**
|
756
1245
|
* @param {string} input input
|
757
1246
|
* @param {number} pos position
|
@@ -773,3 +1262,344 @@ module.exports.eatWhiteLine = (input, pos) => {
|
|
773
1262
|
|
774
1263
|
return pos;
|
775
1264
|
};
|
1265
|
+
|
1266
|
+
/**
|
1267
|
+
* @param {string} input input
|
1268
|
+
* @param {number} pos position
|
1269
|
+
* @returns {[number, number] | undefined} positions of ident sequence
|
1270
|
+
*/
|
1271
|
+
module.exports.skipCommentsAndEatIdentSequence = (input, pos) => {
|
1272
|
+
pos = module.exports.eatComments(input, pos);
|
1273
|
+
|
1274
|
+
const start = pos;
|
1275
|
+
|
1276
|
+
if (
|
1277
|
+
_ifThreeCodePointsWouldStartAnIdentSequence(
|
1278
|
+
input,
|
1279
|
+
pos,
|
1280
|
+
input.charCodeAt(pos),
|
1281
|
+
input.charCodeAt(pos + 1),
|
1282
|
+
input.charCodeAt(pos + 2)
|
1283
|
+
)
|
1284
|
+
) {
|
1285
|
+
return [start, _consumeAnIdentSequence(input, pos, {})];
|
1286
|
+
}
|
1287
|
+
|
1288
|
+
return undefined;
|
1289
|
+
};
|
1290
|
+
|
1291
|
+
/**
|
1292
|
+
* @param {string} input input
|
1293
|
+
* @param {number} pos position
|
1294
|
+
* @returns {[number, number] | undefined} positions of ident sequence
|
1295
|
+
*/
|
1296
|
+
module.exports.eatString = (input, pos) => {
|
1297
|
+
pos = module.exports.eatWhitespaceAndComments(input, pos);
|
1298
|
+
|
1299
|
+
const start = pos;
|
1300
|
+
|
1301
|
+
if (
|
1302
|
+
input.charCodeAt(pos) === CC_QUOTATION_MARK ||
|
1303
|
+
input.charCodeAt(pos) === CC_APOSTROPHE
|
1304
|
+
) {
|
1305
|
+
return [start, consumeAStringToken(input, pos + 1, {})];
|
1306
|
+
}
|
1307
|
+
|
1308
|
+
return undefined;
|
1309
|
+
};
|
1310
|
+
|
1311
|
+
/**
|
1312
|
+
* @param {string} input input
|
1313
|
+
* @param {number} pos position
|
1314
|
+
* @param {CssTokenCallbacks} cbs callbacks
|
1315
|
+
* @returns {[number, number][]} positions of ident sequence
|
1316
|
+
*/
|
1317
|
+
module.exports.eatImageSetStrings = (input, pos, cbs) => {
|
1318
|
+
/** @type {[number, number][]} */
|
1319
|
+
const result = [];
|
1320
|
+
|
1321
|
+
let isFirst = true;
|
1322
|
+
let needStop = false;
|
1323
|
+
// We already in `func(` token
|
1324
|
+
let balanced = 1;
|
1325
|
+
|
1326
|
+
/** @type {CssTokenCallbacks} */
|
1327
|
+
const callbacks = {
|
1328
|
+
...cbs,
|
1329
|
+
string: (_input, start, end) => {
|
1330
|
+
if (isFirst && balanced === 1) {
|
1331
|
+
result.push([start, end]);
|
1332
|
+
isFirst = false;
|
1333
|
+
}
|
1334
|
+
|
1335
|
+
return end;
|
1336
|
+
},
|
1337
|
+
comma: (_input, _start, end) => {
|
1338
|
+
if (balanced === 1) {
|
1339
|
+
isFirst = true;
|
1340
|
+
}
|
1341
|
+
|
1342
|
+
return end;
|
1343
|
+
},
|
1344
|
+
leftParenthesis: (input, start, end) => {
|
1345
|
+
balanced++;
|
1346
|
+
|
1347
|
+
return end;
|
1348
|
+
},
|
1349
|
+
function: (_input, start, end) => {
|
1350
|
+
balanced++;
|
1351
|
+
|
1352
|
+
return end;
|
1353
|
+
},
|
1354
|
+
rightParenthesis: (_input, _start, end) => {
|
1355
|
+
balanced--;
|
1356
|
+
|
1357
|
+
if (balanced === 0) {
|
1358
|
+
needStop = true;
|
1359
|
+
}
|
1360
|
+
|
1361
|
+
return end;
|
1362
|
+
}
|
1363
|
+
};
|
1364
|
+
|
1365
|
+
while (pos < input.length) {
|
1366
|
+
// Consume comments.
|
1367
|
+
pos = consumeComments(input, pos, callbacks);
|
1368
|
+
|
1369
|
+
// Consume the next input code point.
|
1370
|
+
pos++;
|
1371
|
+
pos = consumeAToken(input, pos, callbacks);
|
1372
|
+
|
1373
|
+
if (needStop) {
|
1374
|
+
break;
|
1375
|
+
}
|
1376
|
+
}
|
1377
|
+
|
1378
|
+
return result;
|
1379
|
+
};
|
1380
|
+
|
1381
|
+
/**
|
1382
|
+
* @param {string} input input
|
1383
|
+
* @param {number} pos position
|
1384
|
+
* @param {CssTokenCallbacks} cbs callbacks
|
1385
|
+
* @returns {[[number, number, number, number] | undefined, [number, number] | undefined, [number, number] | undefined, [number, number] | undefined]} positions of top level tokens
|
1386
|
+
*/
|
1387
|
+
module.exports.eatImportTokens = (input, pos, cbs) => {
|
1388
|
+
const result =
|
1389
|
+
/** @type {[[number, number, number, number] | undefined, [number, number] | undefined, [number, number] | undefined, [number, number] | undefined]} */
|
1390
|
+
(new Array(4));
|
1391
|
+
|
1392
|
+
/** @type {0 | 1 | 2 | undefined} */
|
1393
|
+
let scope;
|
1394
|
+
let needStop = false;
|
1395
|
+
let balanced = 0;
|
1396
|
+
|
1397
|
+
/** @type {CssTokenCallbacks} */
|
1398
|
+
const callbacks = {
|
1399
|
+
...cbs,
|
1400
|
+
url: (_input, start, end, contentStart, contentEnd) => {
|
1401
|
+
if (
|
1402
|
+
result[0] === undefined &&
|
1403
|
+
balanced === 0 &&
|
1404
|
+
result[1] === undefined &&
|
1405
|
+
result[2] === undefined &&
|
1406
|
+
result[3] === undefined
|
1407
|
+
) {
|
1408
|
+
result[0] = [start, end, contentStart, contentEnd];
|
1409
|
+
scope = undefined;
|
1410
|
+
}
|
1411
|
+
|
1412
|
+
return end;
|
1413
|
+
},
|
1414
|
+
string: (_input, start, end) => {
|
1415
|
+
if (
|
1416
|
+
balanced === 0 &&
|
1417
|
+
result[0] === undefined &&
|
1418
|
+
result[1] === undefined &&
|
1419
|
+
result[2] === undefined &&
|
1420
|
+
result[3] === undefined
|
1421
|
+
) {
|
1422
|
+
result[0] = [start, end, start + 1, end - 1];
|
1423
|
+
scope = undefined;
|
1424
|
+
} else if (result[0] !== undefined && scope === 0) {
|
1425
|
+
result[0][2] = start + 1;
|
1426
|
+
result[0][3] = end - 1;
|
1427
|
+
}
|
1428
|
+
|
1429
|
+
return end;
|
1430
|
+
},
|
1431
|
+
leftParenthesis: (_input, _start, end) => {
|
1432
|
+
balanced++;
|
1433
|
+
|
1434
|
+
return end;
|
1435
|
+
},
|
1436
|
+
rightParenthesis: (_input, _start, end) => {
|
1437
|
+
balanced--;
|
1438
|
+
|
1439
|
+
if (balanced === 0 && scope !== undefined) {
|
1440
|
+
/** @type {[number, number]} */
|
1441
|
+
(result[scope])[1] = end;
|
1442
|
+
scope = undefined;
|
1443
|
+
}
|
1444
|
+
|
1445
|
+
return end;
|
1446
|
+
},
|
1447
|
+
function: (input, start, end) => {
|
1448
|
+
if (balanced === 0) {
|
1449
|
+
const name = input
|
1450
|
+
.slice(start, end - 1)
|
1451
|
+
.replace(/\\/g, "")
|
1452
|
+
.toLowerCase();
|
1453
|
+
|
1454
|
+
if (
|
1455
|
+
name === "url" &&
|
1456
|
+
result[0] === undefined &&
|
1457
|
+
result[1] === undefined &&
|
1458
|
+
result[2] === undefined &&
|
1459
|
+
result[3] === undefined
|
1460
|
+
) {
|
1461
|
+
scope = 0;
|
1462
|
+
result[scope] = [start, end + 1, end + 1, end + 1];
|
1463
|
+
} else if (
|
1464
|
+
name === "layer" &&
|
1465
|
+
result[1] === undefined &&
|
1466
|
+
result[2] === undefined
|
1467
|
+
) {
|
1468
|
+
scope = 1;
|
1469
|
+
result[scope] = [start, end];
|
1470
|
+
} else if (name === "supports" && result[2] === undefined) {
|
1471
|
+
scope = 2;
|
1472
|
+
result[scope] = [start, end];
|
1473
|
+
} else {
|
1474
|
+
scope = undefined;
|
1475
|
+
}
|
1476
|
+
}
|
1477
|
+
|
1478
|
+
balanced++;
|
1479
|
+
|
1480
|
+
return end;
|
1481
|
+
},
|
1482
|
+
identifier: (input, start, end) => {
|
1483
|
+
if (
|
1484
|
+
balanced === 0 &&
|
1485
|
+
result[1] === undefined &&
|
1486
|
+
result[2] === undefined
|
1487
|
+
) {
|
1488
|
+
const name = input.slice(start, end).replace(/\\/g, "").toLowerCase();
|
1489
|
+
|
1490
|
+
if (name === "layer") {
|
1491
|
+
result[1] = [start, end];
|
1492
|
+
scope = undefined;
|
1493
|
+
}
|
1494
|
+
}
|
1495
|
+
|
1496
|
+
return end;
|
1497
|
+
},
|
1498
|
+
semicolon: (_input, start, end) => {
|
1499
|
+
if (balanced === 0) {
|
1500
|
+
needStop = true;
|
1501
|
+
result[3] = [start, end];
|
1502
|
+
}
|
1503
|
+
|
1504
|
+
return end;
|
1505
|
+
}
|
1506
|
+
};
|
1507
|
+
|
1508
|
+
while (pos < input.length) {
|
1509
|
+
// Consume comments.
|
1510
|
+
pos = consumeComments(input, pos, callbacks);
|
1511
|
+
|
1512
|
+
// Consume the next input code point.
|
1513
|
+
pos++;
|
1514
|
+
pos = consumeAToken(input, pos, callbacks);
|
1515
|
+
|
1516
|
+
if (needStop) {
|
1517
|
+
break;
|
1518
|
+
}
|
1519
|
+
}
|
1520
|
+
|
1521
|
+
return result;
|
1522
|
+
};
|
1523
|
+
|
1524
|
+
/**
|
1525
|
+
* @param {string} input input
|
1526
|
+
* @param {number} pos position
|
1527
|
+
* @returns {[number, number] | undefined} positions of ident sequence
|
1528
|
+
*/
|
1529
|
+
module.exports.eatIdentSequence = (input, pos) => {
|
1530
|
+
pos = module.exports.eatWhitespaceAndComments(input, pos);
|
1531
|
+
|
1532
|
+
const start = pos;
|
1533
|
+
|
1534
|
+
if (
|
1535
|
+
_ifThreeCodePointsWouldStartAnIdentSequence(
|
1536
|
+
input,
|
1537
|
+
pos,
|
1538
|
+
input.charCodeAt(pos),
|
1539
|
+
input.charCodeAt(pos + 1),
|
1540
|
+
input.charCodeAt(pos + 2)
|
1541
|
+
)
|
1542
|
+
) {
|
1543
|
+
return [start, _consumeAnIdentSequence(input, pos, {})];
|
1544
|
+
}
|
1545
|
+
|
1546
|
+
return undefined;
|
1547
|
+
};
|
1548
|
+
|
1549
|
+
/**
|
1550
|
+
* @param {string} input input
|
1551
|
+
* @param {number} pos position
|
1552
|
+
* @returns {[number, number, boolean] | undefined} positions of ident sequence or string
|
1553
|
+
*/
|
1554
|
+
module.exports.eatIdentSequenceOrString = (input, pos) => {
|
1555
|
+
pos = module.exports.eatWhitespaceAndComments(input, pos);
|
1556
|
+
|
1557
|
+
const start = pos;
|
1558
|
+
|
1559
|
+
if (
|
1560
|
+
input.charCodeAt(pos) === CC_QUOTATION_MARK ||
|
1561
|
+
input.charCodeAt(pos) === CC_APOSTROPHE
|
1562
|
+
) {
|
1563
|
+
return [start, consumeAStringToken(input, pos + 1, {}), false];
|
1564
|
+
} else if (
|
1565
|
+
_ifThreeCodePointsWouldStartAnIdentSequence(
|
1566
|
+
input,
|
1567
|
+
pos,
|
1568
|
+
input.charCodeAt(pos),
|
1569
|
+
input.charCodeAt(pos + 1),
|
1570
|
+
input.charCodeAt(pos + 2)
|
1571
|
+
)
|
1572
|
+
) {
|
1573
|
+
return [start, _consumeAnIdentSequence(input, pos, {}), true];
|
1574
|
+
}
|
1575
|
+
|
1576
|
+
return undefined;
|
1577
|
+
};
|
1578
|
+
|
1579
|
+
/**
|
1580
|
+
* @param {string} chars characters
|
1581
|
+
* @returns {(input: string, pos: number) => number} function to eat characters
|
1582
|
+
*/
|
1583
|
+
module.exports.eatUntil = chars => {
|
1584
|
+
const charCodes = Array.from({ length: chars.length }, (_, i) =>
|
1585
|
+
chars.charCodeAt(i)
|
1586
|
+
);
|
1587
|
+
const arr = Array.from(
|
1588
|
+
{ length: charCodes.reduce((a, b) => Math.max(a, b), 0) + 1 },
|
1589
|
+
() => false
|
1590
|
+
);
|
1591
|
+
for (const cc of charCodes) {
|
1592
|
+
arr[cc] = true;
|
1593
|
+
}
|
1594
|
+
|
1595
|
+
return (input, pos) => {
|
1596
|
+
for (;;) {
|
1597
|
+
const cc = input.charCodeAt(pos);
|
1598
|
+
if (cc < arr.length && arr[cc]) {
|
1599
|
+
return pos;
|
1600
|
+
}
|
1601
|
+
pos++;
|
1602
|
+
if (pos === input.length) return pos;
|
1603
|
+
}
|
1604
|
+
};
|
1605
|
+
};
|