diff options
Diffstat (limited to 'node_modules/webpack/lib/css')
| -rw-r--r-- | node_modules/webpack/lib/css/CssExportsGenerator.js | 148 | ||||
| -rw-r--r-- | node_modules/webpack/lib/css/CssGenerator.js | 113 | ||||
| -rw-r--r-- | node_modules/webpack/lib/css/CssLoadingRuntimeModule.js | 473 | ||||
| -rw-r--r-- | node_modules/webpack/lib/css/CssModulesPlugin.js | 641 | ||||
| -rw-r--r-- | node_modules/webpack/lib/css/CssParser.js | 1033 | ||||
| -rw-r--r-- | node_modules/webpack/lib/css/walkCssTokens.js | 790 |
6 files changed, 0 insertions, 3198 deletions
diff --git a/node_modules/webpack/lib/css/CssExportsGenerator.js b/node_modules/webpack/lib/css/CssExportsGenerator.js deleted file mode 100644 index 0fc400e0..00000000 --- a/node_modules/webpack/lib/css/CssExportsGenerator.js +++ /dev/null @@ -1,148 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Sergey Melyukov @smelukov -*/ - -"use strict"; - -const { ReplaceSource, RawSource, ConcatSource } = require("webpack-sources"); -const { UsageState } = require("../ExportsInfo"); -const Generator = require("../Generator"); -const RuntimeGlobals = require("../RuntimeGlobals"); -const Template = require("../Template"); - -/** @typedef {import("webpack-sources").Source} Source */ -/** @typedef {import("../Dependency")} Dependency */ -/** @typedef {import("../Generator").GenerateContext} GenerateContext */ -/** @typedef {import("../Generator").UpdateHashContext} UpdateHashContext */ -/** @typedef {import("../Module").ConcatenationBailoutReasonContext} ConcatenationBailoutReasonContext */ -/** @typedef {import("../NormalModule")} NormalModule */ -/** @typedef {import("../util/Hash")} Hash */ - -/** - * @template T - * @typedef {import("../InitFragment")<T>} InitFragment - */ - -const TYPES = new Set(["javascript"]); - -class CssExportsGenerator extends Generator { - constructor() { - super(); - } - - // TODO add getConcatenationBailoutReason to allow concatenation - // but how to make it have a module id - - /** - * @param {NormalModule} module module for which the code should be generated - * @param {GenerateContext} generateContext context for generate - * @returns {Source} generated code - */ - generate(module, generateContext) { - const source = new ReplaceSource(new RawSource("")); - /** @type {InitFragment<TODO>[]} */ - const initFragments = []; - const cssExports = new Map(); - - generateContext.runtimeRequirements.add(RuntimeGlobals.module); - - const runtimeRequirements = new Set(); - - const templateContext = { - runtimeTemplate: generateContext.runtimeTemplate, - dependencyTemplates: generateContext.dependencyTemplates, - moduleGraph: generateContext.moduleGraph, - chunkGraph: generateContext.chunkGraph, - module, - runtime: generateContext.runtime, - runtimeRequirements: runtimeRequirements, - concatenationScope: generateContext.concatenationScope, - codeGenerationResults: generateContext.codeGenerationResults, - initFragments, - cssExports - }; - - /** - * @param {Dependency} dependency the dependency - */ - const handleDependency = dependency => { - const constructor = /** @type {new (...args: any[]) => Dependency} */ ( - dependency.constructor - ); - const template = generateContext.dependencyTemplates.get(constructor); - if (!template) { - throw new Error( - "No template for dependency: " + dependency.constructor.name - ); - } - - template.apply(dependency, source, templateContext); - }; - module.dependencies.forEach(handleDependency); - - if (generateContext.concatenationScope) { - const source = new ConcatSource(); - const usedIdentifiers = new Set(); - for (const [k, v] of cssExports) { - let identifier = Template.toIdentifier(k); - let i = 0; - while (usedIdentifiers.has(identifier)) { - identifier = Template.toIdentifier(k + i); - } - usedIdentifiers.add(identifier); - generateContext.concatenationScope.registerExport(k, identifier); - source.add( - `${ - generateContext.runtimeTemplate.supportsConst ? "const" : "var" - } ${identifier} = ${JSON.stringify(v)};\n` - ); - } - return source; - } else { - const otherUsed = - generateContext.moduleGraph - .getExportsInfo(module) - .otherExportsInfo.getUsed(generateContext.runtime) !== - UsageState.Unused; - if (otherUsed) { - generateContext.runtimeRequirements.add( - RuntimeGlobals.makeNamespaceObject - ); - } - return new RawSource( - `${otherUsed ? `${RuntimeGlobals.makeNamespaceObject}(` : ""}${ - module.moduleArgument - }.exports = {\n${Array.from( - cssExports, - ([k, v]) => `\t${JSON.stringify(k)}: ${JSON.stringify(v)}` - ).join(",\n")}\n}${otherUsed ? ")" : ""};` - ); - } - } - - /** - * @param {NormalModule} module fresh module - * @returns {Set<string>} available types (do not mutate) - */ - getTypes(module) { - return TYPES; - } - - /** - * @param {NormalModule} module the module - * @param {string=} type source type - * @returns {number} estimate size of the module - */ - getSize(module, type) { - return 42; - } - - /** - * @param {Hash} hash hash that will be modified - * @param {UpdateHashContext} updateHashContext context for updating hash - */ - updateHash(hash, { module }) {} -} - -module.exports = CssExportsGenerator; diff --git a/node_modules/webpack/lib/css/CssGenerator.js b/node_modules/webpack/lib/css/CssGenerator.js deleted file mode 100644 index e18c70b0..00000000 --- a/node_modules/webpack/lib/css/CssGenerator.js +++ /dev/null @@ -1,113 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Sergey Melyukov @smelukov -*/ - -"use strict"; - -const { ReplaceSource } = require("webpack-sources"); -const Generator = require("../Generator"); -const InitFragment = require("../InitFragment"); -const RuntimeGlobals = require("../RuntimeGlobals"); - -/** @typedef {import("webpack-sources").Source} Source */ -/** @typedef {import("../Dependency")} Dependency */ -/** @typedef {import("../Generator").GenerateContext} GenerateContext */ -/** @typedef {import("../Generator").UpdateHashContext} UpdateHashContext */ -/** @typedef {import("../NormalModule")} NormalModule */ -/** @typedef {import("../util/Hash")} Hash */ - -const TYPES = new Set(["css"]); - -class CssGenerator extends Generator { - constructor() { - super(); - } - - /** - * @param {NormalModule} module module for which the code should be generated - * @param {GenerateContext} generateContext context for generate - * @returns {Source} generated code - */ - generate(module, generateContext) { - const originalSource = /** @type {Source} */ (module.originalSource()); - const source = new ReplaceSource(originalSource); - /** @type {InitFragment[]} */ - const initFragments = []; - const cssExports = new Map(); - - generateContext.runtimeRequirements.add(RuntimeGlobals.hasCssModules); - - const templateContext = { - runtimeTemplate: generateContext.runtimeTemplate, - dependencyTemplates: generateContext.dependencyTemplates, - moduleGraph: generateContext.moduleGraph, - chunkGraph: generateContext.chunkGraph, - module, - runtime: generateContext.runtime, - runtimeRequirements: generateContext.runtimeRequirements, - concatenationScope: generateContext.concatenationScope, - codeGenerationResults: generateContext.codeGenerationResults, - initFragments, - cssExports - }; - - /** - * @param {Dependency} dependency dependency - */ - const handleDependency = dependency => { - const constructor = /** @type {new (...args: any[]) => Dependency} */ ( - dependency.constructor - ); - const template = generateContext.dependencyTemplates.get(constructor); - if (!template) { - throw new Error( - "No template for dependency: " + dependency.constructor.name - ); - } - - template.apply(dependency, source, templateContext); - }; - module.dependencies.forEach(handleDependency); - if (module.presentationalDependencies !== undefined) - module.presentationalDependencies.forEach(handleDependency); - - if (cssExports.size > 0) { - const data = generateContext.getData(); - data.set("css-exports", cssExports); - } - - return InitFragment.addToSource(source, initFragments, generateContext); - } - - /** - * @param {NormalModule} module fresh module - * @returns {Set<string>} available types (do not mutate) - */ - getTypes(module) { - return TYPES; - } - - /** - * @param {NormalModule} module the module - * @param {string=} type source type - * @returns {number} estimate size of the module - */ - getSize(module, type) { - const originalSource = module.originalSource(); - - if (!originalSource) { - return 0; - } - - return originalSource.size(); - } - - /** - * @param {Hash} hash hash that will be modified - * @param {UpdateHashContext} updateHashContext context for updating hash - */ - updateHash(hash, { module }) {} -} - -module.exports = CssGenerator; diff --git a/node_modules/webpack/lib/css/CssLoadingRuntimeModule.js b/node_modules/webpack/lib/css/CssLoadingRuntimeModule.js deleted file mode 100644 index a0b164f3..00000000 --- a/node_modules/webpack/lib/css/CssLoadingRuntimeModule.js +++ /dev/null @@ -1,473 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ - -"use strict"; - -const { SyncWaterfallHook } = require("tapable"); -const Compilation = require("../Compilation"); -const RuntimeGlobals = require("../RuntimeGlobals"); -const RuntimeModule = require("../RuntimeModule"); -const Template = require("../Template"); -const compileBooleanMatcher = require("../util/compileBooleanMatcher"); -const { chunkHasCss } = require("./CssModulesPlugin"); - -/** @typedef {import("../Chunk")} Chunk */ -/** @typedef {import("../ChunkGraph")} ChunkGraph */ -/** @typedef {import("../Compilation").RuntimeRequirementsContext} RuntimeRequirementsContext */ - -/** - * @typedef {Object} JsonpCompilationPluginHooks - * @property {SyncWaterfallHook<[string, Chunk]>} createStylesheet - */ - -/** @type {WeakMap<Compilation, JsonpCompilationPluginHooks>} */ -const compilationHooksMap = new WeakMap(); - -class CssLoadingRuntimeModule extends RuntimeModule { - /** - * @param {Compilation} compilation the compilation - * @returns {JsonpCompilationPluginHooks} hooks - */ - static getCompilationHooks(compilation) { - if (!(compilation instanceof Compilation)) { - throw new TypeError( - "The 'compilation' argument must be an instance of Compilation" - ); - } - let hooks = compilationHooksMap.get(compilation); - if (hooks === undefined) { - hooks = { - createStylesheet: new SyncWaterfallHook(["source", "chunk"]) - }; - compilationHooksMap.set(compilation, hooks); - } - return hooks; - } - - /** - * @param {Set<string>} runtimeRequirements runtime requirements - */ - constructor(runtimeRequirements) { - super("css loading", 10); - - this._runtimeRequirements = runtimeRequirements; - } - - /** - * @returns {string | null} runtime code - */ - generate() { - const { compilation, chunk, _runtimeRequirements } = this; - const { - chunkGraph, - runtimeTemplate, - outputOptions: { - crossOriginLoading, - uniqueName, - chunkLoadTimeout: loadTimeout - } - } = /** @type {Compilation} */ (compilation); - const fn = RuntimeGlobals.ensureChunkHandlers; - const conditionMap = chunkGraph.getChunkConditionMap( - /** @type {Chunk} */ (chunk), - /** - * @param {Chunk} chunk the chunk - * @param {ChunkGraph} chunkGraph the chunk graph - * @returns {boolean} true, if the chunk has css - */ - (chunk, chunkGraph) => - !!chunkGraph.getChunkModulesIterableBySourceType(chunk, "css") - ); - const hasCssMatcher = compileBooleanMatcher(conditionMap); - - const withLoading = - _runtimeRequirements.has(RuntimeGlobals.ensureChunkHandlers) && - hasCssMatcher !== false; - /** @type {boolean} */ - const withHmr = _runtimeRequirements.has( - RuntimeGlobals.hmrDownloadUpdateHandlers - ); - /** @type {Set<number | string | null>} */ - const initialChunkIdsWithCss = new Set(); - /** @type {Set<number | string | null>} */ - const initialChunkIdsWithoutCss = new Set(); - for (const c of /** @type {Chunk} */ (chunk).getAllInitialChunks()) { - (chunkHasCss(c, chunkGraph) - ? initialChunkIdsWithCss - : initialChunkIdsWithoutCss - ).add(c.id); - } - - if (!withLoading && !withHmr && initialChunkIdsWithCss.size === 0) { - return null; - } - - const { createStylesheet } = CssLoadingRuntimeModule.getCompilationHooks( - /** @type {Compilation} */ (compilation) - ); - - const stateExpression = withHmr - ? `${RuntimeGlobals.hmrRuntimeStatePrefix}_css` - : undefined; - - const code = Template.asString([ - "link = document.createElement('link');", - uniqueName - ? 'link.setAttribute("data-webpack", uniqueName + ":" + key);' - : "", - "link.setAttribute(loadingAttribute, 1);", - 'link.rel = "stylesheet";', - "link.href = url;", - crossOriginLoading - ? crossOriginLoading === "use-credentials" - ? 'link.crossOrigin = "use-credentials";' - : Template.asString([ - "if (link.href.indexOf(window.location.origin + '/') !== 0) {", - Template.indent( - `link.crossOrigin = ${JSON.stringify(crossOriginLoading)};` - ), - "}" - ]) - : "" - ]); - - /** @type {(str: string) => number} */ - const cc = str => str.charCodeAt(0); - const name = uniqueName - ? runtimeTemplate.concatenation( - "--webpack-", - { expr: "uniqueName" }, - "-", - { expr: "chunkId" } - ) - : runtimeTemplate.concatenation("--webpack-", { expr: "chunkId" }); - - return Template.asString([ - "// object to store loaded and loading chunks", - "// undefined = chunk not loaded, null = chunk preloaded/prefetched", - "// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded", - `var installedChunks = ${ - stateExpression ? `${stateExpression} = ${stateExpression} || ` : "" - }{${Array.from( - initialChunkIdsWithoutCss, - id => `${JSON.stringify(id)}:0` - ).join(",")}};`, - "", - uniqueName - ? `var uniqueName = ${JSON.stringify( - runtimeTemplate.outputOptions.uniqueName - )};` - : "// data-webpack is not used as build has no uniqueName", - `var loadCssChunkData = ${runtimeTemplate.basicFunction( - "target, link, chunkId", - [ - `var data, token = "", token2, exports = {}, exportsWithId = [], exportsWithDashes = [], ${ - withHmr ? "moduleIds = [], " : "" - }name = ${name}, i = 0, cc = 1;`, - "try {", - Template.indent([ - "if(!link) link = loadStylesheet(chunkId);", - // `link.sheet.rules` for legacy browsers - "var cssRules = link.sheet.cssRules || link.sheet.rules;", - "var j = cssRules.length - 1;", - "while(j > -1 && !data) {", - Template.indent([ - "var style = cssRules[j--].style;", - "if(!style) continue;", - `data = style.getPropertyValue(name);` - ]), - "}" - ]), - "}catch(e){}", - "if(!data) {", - Template.indent([ - "data = getComputedStyle(document.head).getPropertyValue(name);" - ]), - "}", - "if(!data) return [];", - "for(; cc; i++) {", - Template.indent([ - "cc = data.charCodeAt(i);", - `if(cc == ${cc("(")}) { token2 = token; token = ""; }`, - `else if(cc == ${cc( - ")" - )}) { exports[token2.replace(/^_/, "")] = token.replace(/^_/, ""); token = ""; }`, - `else if(cc == ${cc("/")} || cc == ${cc( - "%" - )}) { token = token.replace(/^_/, ""); exports[token] = token; exportsWithId.push(token); if(cc == ${cc( - "%" - )}) exportsWithDashes.push(token); token = ""; }`, - `else if(!cc || cc == ${cc( - "," - )}) { token = token.replace(/^_/, ""); exportsWithId.forEach(${runtimeTemplate.expressionFunction( - `exports[x] = ${ - uniqueName - ? runtimeTemplate.concatenation( - { expr: "uniqueName" }, - "-", - { expr: "token" }, - "-", - { expr: "exports[x]" } - ) - : runtimeTemplate.concatenation({ expr: "token" }, "-", { - expr: "exports[x]" - }) - }`, - "x" - )}); exportsWithDashes.forEach(${runtimeTemplate.expressionFunction( - `exports[x] = "--" + exports[x]`, - "x" - )}); ${ - RuntimeGlobals.makeNamespaceObject - }(exports); target[token] = (${runtimeTemplate.basicFunction( - "exports, module", - `module.exports = exports;` - )}).bind(null, exports); ${ - withHmr ? "moduleIds.push(token); " : "" - }token = ""; exports = {}; exportsWithId.length = 0; }`, - `else if(cc == ${cc("\\")}) { token += data[++i] }`, - `else { token += data[i]; }` - ]), - "}", - `${ - withHmr ? `if(target == ${RuntimeGlobals.moduleFactories}) ` : "" - }installedChunks[chunkId] = 0;`, - withHmr ? "return moduleIds;" : "" - ] - )}`, - 'var loadingAttribute = "data-webpack-loading";', - `var loadStylesheet = ${runtimeTemplate.basicFunction( - "chunkId, url, done" + (withHmr ? ", hmr" : ""), - [ - 'var link, needAttach, key = "chunk-" + chunkId;', - withHmr ? "if(!hmr) {" : "", - 'var links = document.getElementsByTagName("link");', - "for(var i = 0; i < links.length; i++) {", - Template.indent([ - "var l = links[i];", - `if(l.rel == "stylesheet" && (${ - withHmr - ? 'l.href.startsWith(url) || l.getAttribute("href").startsWith(url)' - : 'l.href == url || l.getAttribute("href") == url' - }${ - uniqueName - ? ' || l.getAttribute("data-webpack") == uniqueName + ":" + key' - : "" - })) { link = l; break; }` - ]), - "}", - "if(!done) return link;", - withHmr ? "}" : "", - "if(!link) {", - Template.indent([ - "needAttach = true;", - createStylesheet.call(code, /** @type {Chunk} */ (this.chunk)) - ]), - "}", - `var onLinkComplete = ${runtimeTemplate.basicFunction( - "prev, event", - Template.asString([ - "link.onerror = link.onload = null;", - "link.removeAttribute(loadingAttribute);", - "clearTimeout(timeout);", - 'if(event && event.type != "load") link.parentNode.removeChild(link)', - "done(event);", - "if(prev) return prev(event);" - ]) - )};`, - "if(link.getAttribute(loadingAttribute)) {", - Template.indent([ - `var timeout = setTimeout(onLinkComplete.bind(null, undefined, { type: 'timeout', target: link }), ${loadTimeout});`, - "link.onerror = onLinkComplete.bind(null, link.onerror);", - "link.onload = onLinkComplete.bind(null, link.onload);" - ]), - "} else onLinkComplete(undefined, { type: 'load', target: link });", // We assume any existing stylesheet is render blocking - withHmr ? "hmr ? document.head.insertBefore(link, hmr) :" : "", - "needAttach && document.head.appendChild(link);", - "return link;" - ] - )};`, - initialChunkIdsWithCss.size > 2 - ? `${JSON.stringify( - Array.from(initialChunkIdsWithCss) - )}.forEach(loadCssChunkData.bind(null, ${ - RuntimeGlobals.moduleFactories - }, 0));` - : initialChunkIdsWithCss.size > 0 - ? `${Array.from( - initialChunkIdsWithCss, - id => - `loadCssChunkData(${ - RuntimeGlobals.moduleFactories - }, 0, ${JSON.stringify(id)});` - ).join("")}` - : "// no initial css", - "", - withLoading - ? Template.asString([ - `${fn}.css = ${runtimeTemplate.basicFunction("chunkId, promises", [ - "// css chunk loading", - `var installedChunkData = ${RuntimeGlobals.hasOwnProperty}(installedChunks, chunkId) ? installedChunks[chunkId] : undefined;`, - 'if(installedChunkData !== 0) { // 0 means "already installed".', - Template.indent([ - "", - '// a Promise means "currently loading".', - "if(installedChunkData) {", - Template.indent(["promises.push(installedChunkData[2]);"]), - "} else {", - Template.indent([ - hasCssMatcher === true - ? "if(true) { // all chunks have CSS" - : `if(${hasCssMatcher("chunkId")}) {`, - Template.indent([ - "// setup Promise in chunk cache", - `var promise = new Promise(${runtimeTemplate.expressionFunction( - `installedChunkData = installedChunks[chunkId] = [resolve, reject]`, - "resolve, reject" - )});`, - "promises.push(installedChunkData[2] = promise);", - "", - "// start chunk loading", - `var url = ${RuntimeGlobals.publicPath} + ${RuntimeGlobals.getChunkCssFilename}(chunkId);`, - "// create error before stack unwound to get useful stacktrace later", - "var error = new Error();", - `var loadingEnded = ${runtimeTemplate.basicFunction( - "event", - [ - `if(${RuntimeGlobals.hasOwnProperty}(installedChunks, chunkId)) {`, - Template.indent([ - "installedChunkData = installedChunks[chunkId];", - "if(installedChunkData !== 0) installedChunks[chunkId] = undefined;", - "if(installedChunkData) {", - Template.indent([ - 'if(event.type !== "load") {', - Template.indent([ - "var errorType = event && event.type;", - "var realSrc = event && event.target && event.target.src;", - "error.message = 'Loading css chunk ' + chunkId + ' failed.\\n(' + errorType + ': ' + realSrc + ')';", - "error.name = 'ChunkLoadError';", - "error.type = errorType;", - "error.request = realSrc;", - "installedChunkData[1](error);" - ]), - "} else {", - Template.indent([ - `loadCssChunkData(${RuntimeGlobals.moduleFactories}, link, chunkId);`, - "installedChunkData[0]();" - ]), - "}" - ]), - "}" - ]), - "}" - ] - )};`, - "var link = loadStylesheet(chunkId, url, loadingEnded);" - ]), - "} else installedChunks[chunkId] = 0;" - ]), - "}" - ]), - "}" - ])};` - ]) - : "// no chunk loading", - "", - withHmr - ? Template.asString([ - "var oldTags = [];", - "var newTags = [];", - `var applyHandler = ${runtimeTemplate.basicFunction("options", [ - `return { dispose: ${runtimeTemplate.basicFunction( - "", - [] - )}, apply: ${runtimeTemplate.basicFunction("", [ - "var moduleIds = [];", - `newTags.forEach(${runtimeTemplate.expressionFunction( - "info[1].sheet.disabled = false", - "info" - )});`, - "while(oldTags.length) {", - Template.indent([ - "var oldTag = oldTags.pop();", - "if(oldTag.parentNode) oldTag.parentNode.removeChild(oldTag);" - ]), - "}", - "while(newTags.length) {", - Template.indent([ - `var info = newTags.pop();`, - `var chunkModuleIds = loadCssChunkData(${RuntimeGlobals.moduleFactories}, info[1], info[0]);`, - `chunkModuleIds.forEach(${runtimeTemplate.expressionFunction( - "moduleIds.push(id)", - "id" - )});` - ]), - "}", - "return moduleIds;" - ])} };` - ])}`, - `var cssTextKey = ${runtimeTemplate.returningFunction( - `Array.from(link.sheet.cssRules, ${runtimeTemplate.returningFunction( - "r.cssText", - "r" - )}).join()`, - "link" - )}`, - `${ - RuntimeGlobals.hmrDownloadUpdateHandlers - }.css = ${runtimeTemplate.basicFunction( - "chunkIds, removedChunks, removedModules, promises, applyHandlers, updatedModulesList", - [ - "applyHandlers.push(applyHandler);", - `chunkIds.forEach(${runtimeTemplate.basicFunction("chunkId", [ - `var filename = ${RuntimeGlobals.getChunkCssFilename}(chunkId);`, - `var url = ${RuntimeGlobals.publicPath} + filename;`, - "var oldTag = loadStylesheet(chunkId, url);", - "if(!oldTag) return;", - `promises.push(new Promise(${runtimeTemplate.basicFunction( - "resolve, reject", - [ - `var link = loadStylesheet(chunkId, url + (url.indexOf("?") < 0 ? "?" : "&") + "hmr=" + Date.now(), ${runtimeTemplate.basicFunction( - "event", - [ - 'if(event.type !== "load") {', - Template.indent([ - "var errorType = event && event.type;", - "var realSrc = event && event.target && event.target.src;", - "error.message = 'Loading css hot update chunk ' + chunkId + ' failed.\\n(' + errorType + ': ' + realSrc + ')';", - "error.name = 'ChunkLoadError';", - "error.type = errorType;", - "error.request = realSrc;", - "reject(error);" - ]), - "} else {", - Template.indent([ - "try { if(cssTextKey(oldTag) == cssTextKey(link)) { if(link.parentNode) link.parentNode.removeChild(link); return resolve(); } } catch(e) {}", - "var factories = {};", - "loadCssChunkData(factories, link, chunkId);", - `Object.keys(factories).forEach(${runtimeTemplate.expressionFunction( - "updatedModulesList.push(id)", - "id" - )})`, - "link.sheet.disabled = true;", - "oldTags.push(oldTag);", - "newTags.push([chunkId, link]);", - "resolve();" - ]), - "}" - ] - )}, oldTag);` - ] - )}));` - ])});` - ] - )}` - ]) - : "// no hmr" - ]); - } -} - -module.exports = CssLoadingRuntimeModule; diff --git a/node_modules/webpack/lib/css/CssModulesPlugin.js b/node_modules/webpack/lib/css/CssModulesPlugin.js deleted file mode 100644 index 103ea670..00000000 --- a/node_modules/webpack/lib/css/CssModulesPlugin.js +++ /dev/null @@ -1,641 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ - -"use strict"; - -const { ConcatSource, PrefixSource } = require("webpack-sources"); -const CssModule = require("../CssModule"); -const HotUpdateChunk = require("../HotUpdateChunk"); -const { - CSS_MODULE_TYPE, - CSS_MODULE_TYPE_GLOBAL, - CSS_MODULE_TYPE_MODULE, - CSS_MODULE_TYPE_AUTO -} = require("../ModuleTypeConstants"); -const RuntimeGlobals = require("../RuntimeGlobals"); -const SelfModuleFactory = require("../SelfModuleFactory"); -const WebpackError = require("../WebpackError"); -const CssExportDependency = require("../dependencies/CssExportDependency"); -const CssImportDependency = require("../dependencies/CssImportDependency"); -const CssLocalIdentifierDependency = require("../dependencies/CssLocalIdentifierDependency"); -const CssSelfLocalIdentifierDependency = require("../dependencies/CssSelfLocalIdentifierDependency"); -const CssUrlDependency = require("../dependencies/CssUrlDependency"); -const StaticExportsDependency = require("../dependencies/StaticExportsDependency"); -const { compareModulesByIdentifier } = require("../util/comparators"); -const createSchemaValidation = require("../util/create-schema-validation"); -const createHash = require("../util/createHash"); -const memoize = require("../util/memoize"); -const nonNumericOnlyHash = require("../util/nonNumericOnlyHash"); -const CssExportsGenerator = require("./CssExportsGenerator"); -const CssGenerator = require("./CssGenerator"); -const CssParser = require("./CssParser"); - -/** @typedef {import("webpack-sources").Source} Source */ -/** @typedef {import("../../declarations/WebpackOptions").CssExperimentOptions} CssExperimentOptions */ -/** @typedef {import("../../declarations/WebpackOptions").Output} OutputOptions */ -/** @typedef {import("../Chunk")} Chunk */ -/** @typedef {import("../ChunkGraph")} ChunkGraph */ -/** @typedef {import("../CodeGenerationResults")} CodeGenerationResults */ -/** @typedef {import("../Compilation")} Compilation */ -/** @typedef {import("../Compiler")} Compiler */ -/** @typedef {import("../Module")} Module */ -/** @typedef {import("../util/memoize")} Memoize */ - -const getCssLoadingRuntimeModule = memoize(() => - require("./CssLoadingRuntimeModule") -); - -/** - * @param {string} name name - * @returns {{oneOf: [{$ref: string}], definitions: *}} schema - */ -const getSchema = name => { - const { definitions } = require("../../schemas/WebpackOptions.json"); - return { - definitions, - oneOf: [{ $ref: `#/definitions/${name}` }] - }; -}; - -const validateGeneratorOptions = createSchemaValidation( - require("../../schemas/plugins/css/CssGeneratorOptions.check.js"), - () => getSchema("CssGeneratorOptions"), - { - name: "Css Modules Plugin", - baseDataPath: "parser" - } -); -const validateParserOptions = createSchemaValidation( - require("../../schemas/plugins/css/CssParserOptions.check.js"), - () => getSchema("CssParserOptions"), - { - name: "Css Modules Plugin", - baseDataPath: "parser" - } -); - -/** - * @param {string} str string - * @param {boolean=} omitOptionalUnderscore if true, optional underscore is not added - * @returns {string} escaped string - */ -const escapeCss = (str, omitOptionalUnderscore) => { - const escaped = `${str}`.replace( - // cspell:word uffff - /[^a-zA-Z0-9_\u0081-\uffff-]/g, - s => `\\${s}` - ); - return !omitOptionalUnderscore && /^(?!--)[0-9_-]/.test(escaped) - ? `_${escaped}` - : escaped; -}; - -const plugin = "CssModulesPlugin"; - -class CssModulesPlugin { - /** - * @param {CssExperimentOptions} options options - */ - constructor({ exportsOnly = false }) { - this._exportsOnly = exportsOnly; - } - /** - * Apply the plugin - * @param {Compiler} compiler the compiler instance - * @returns {void} - */ - apply(compiler) { - compiler.hooks.compilation.tap( - plugin, - (compilation, { normalModuleFactory }) => { - const selfFactory = new SelfModuleFactory(compilation.moduleGraph); - compilation.dependencyFactories.set( - CssUrlDependency, - normalModuleFactory - ); - compilation.dependencyTemplates.set( - CssUrlDependency, - new CssUrlDependency.Template() - ); - compilation.dependencyTemplates.set( - CssLocalIdentifierDependency, - new CssLocalIdentifierDependency.Template() - ); - compilation.dependencyFactories.set( - CssSelfLocalIdentifierDependency, - selfFactory - ); - compilation.dependencyTemplates.set( - CssSelfLocalIdentifierDependency, - new CssSelfLocalIdentifierDependency.Template() - ); - compilation.dependencyTemplates.set( - CssExportDependency, - new CssExportDependency.Template() - ); - compilation.dependencyFactories.set( - CssImportDependency, - normalModuleFactory - ); - compilation.dependencyTemplates.set( - CssImportDependency, - new CssImportDependency.Template() - ); - compilation.dependencyTemplates.set( - StaticExportsDependency, - new StaticExportsDependency.Template() - ); - for (const type of [ - CSS_MODULE_TYPE, - CSS_MODULE_TYPE_GLOBAL, - CSS_MODULE_TYPE_MODULE, - CSS_MODULE_TYPE_AUTO - ]) { - normalModuleFactory.hooks.createParser - .for(type) - .tap(plugin, parserOptions => { - validateParserOptions(parserOptions); - - switch (type) { - case CSS_MODULE_TYPE: - case CSS_MODULE_TYPE_AUTO: - return new CssParser(); - case CSS_MODULE_TYPE_GLOBAL: - return new CssParser({ - allowModeSwitch: false - }); - case CSS_MODULE_TYPE_MODULE: - return new CssParser({ - defaultMode: "local" - }); - } - }); - normalModuleFactory.hooks.createGenerator - .for(type) - .tap(plugin, generatorOptions => { - validateGeneratorOptions(generatorOptions); - return this._exportsOnly - ? new CssExportsGenerator() - : new CssGenerator(); - }); - normalModuleFactory.hooks.createModuleClass - .for(type) - .tap(plugin, (createData, resolveData) => { - if (resolveData.dependencies.length > 0) { - // When CSS is imported from CSS there is only one dependency - const dependency = resolveData.dependencies[0]; - - if (dependency instanceof CssImportDependency) { - const parent = - /** @type {CssModule} */ - (compilation.moduleGraph.getParentModule(dependency)); - - if (parent instanceof CssModule) { - /** @type {import("../CssModule").Inheritance | undefined} */ - let inheritance; - - if ( - (parent.cssLayer !== null && - parent.cssLayer !== undefined) || - parent.supports || - parent.media - ) { - if (!inheritance) { - inheritance = []; - } - - inheritance.push([ - parent.cssLayer, - parent.supports, - parent.media - ]); - } - - if (parent.inheritance) { - if (!inheritance) { - inheritance = []; - } - - inheritance.push(...parent.inheritance); - } - - return new CssModule({ - ...createData, - cssLayer: dependency.layer, - supports: dependency.supports, - media: dependency.media, - inheritance - }); - } - - return new CssModule({ - ...createData, - cssLayer: dependency.layer, - supports: dependency.supports, - media: dependency.media - }); - } - } - - return new CssModule(createData); - }); - } - const orderedCssModulesPerChunk = new WeakMap(); - compilation.hooks.afterCodeGeneration.tap("CssModulesPlugin", () => { - const { chunkGraph } = compilation; - for (const chunk of compilation.chunks) { - if (CssModulesPlugin.chunkHasCss(chunk, chunkGraph)) { - orderedCssModulesPerChunk.set( - chunk, - this.getOrderedChunkCssModules(chunk, chunkGraph, compilation) - ); - } - } - }); - compilation.hooks.contentHash.tap("CssModulesPlugin", chunk => { - const { - chunkGraph, - outputOptions: { - hashSalt, - hashDigest, - hashDigestLength, - hashFunction - } - } = compilation; - const modules = orderedCssModulesPerChunk.get(chunk); - if (modules === undefined) return; - const hash = createHash(hashFunction); - if (hashSalt) hash.update(hashSalt); - for (const module of modules) { - hash.update(chunkGraph.getModuleHash(module, chunk.runtime)); - } - const digest = /** @type {string} */ (hash.digest(hashDigest)); - chunk.contentHash.css = nonNumericOnlyHash(digest, hashDigestLength); - }); - compilation.hooks.renderManifest.tap(plugin, (result, options) => { - const { chunkGraph } = compilation; - const { hash, chunk, codeGenerationResults } = options; - - if (chunk instanceof HotUpdateChunk) return result; - - /** @type {CssModule[] | undefined} */ - const modules = orderedCssModulesPerChunk.get(chunk); - if (modules !== undefined) { - result.push({ - render: () => - this.renderChunk({ - chunk, - chunkGraph, - codeGenerationResults, - uniqueName: compilation.outputOptions.uniqueName, - modules - }), - filenameTemplate: CssModulesPlugin.getChunkFilenameTemplate( - chunk, - compilation.outputOptions - ), - pathOptions: { - hash, - runtime: chunk.runtime, - chunk, - contentHashType: "css" - }, - identifier: `css${chunk.id}`, - hash: chunk.contentHash.css - }); - } - return result; - }); - const globalChunkLoading = compilation.outputOptions.chunkLoading; - /** - * @param {Chunk} chunk the chunk - * @returns {boolean} true, when enabled - */ - const isEnabledForChunk = chunk => { - const options = chunk.getEntryOptions(); - const chunkLoading = - options && options.chunkLoading !== undefined - ? options.chunkLoading - : globalChunkLoading; - return chunkLoading === "jsonp"; - }; - const onceForChunkSet = new WeakSet(); - /** - * @param {Chunk} chunk chunk to check - * @param {Set<string>} set runtime requirements - */ - const handler = (chunk, set) => { - if (onceForChunkSet.has(chunk)) return; - onceForChunkSet.add(chunk); - if (!isEnabledForChunk(chunk)) return; - - set.add(RuntimeGlobals.publicPath); - set.add(RuntimeGlobals.getChunkCssFilename); - set.add(RuntimeGlobals.hasOwnProperty); - set.add(RuntimeGlobals.moduleFactoriesAddOnly); - set.add(RuntimeGlobals.makeNamespaceObject); - - const CssLoadingRuntimeModule = getCssLoadingRuntimeModule(); - compilation.addRuntimeModule(chunk, new CssLoadingRuntimeModule(set)); - }; - compilation.hooks.runtimeRequirementInTree - .for(RuntimeGlobals.hasCssModules) - .tap(plugin, handler); - compilation.hooks.runtimeRequirementInTree - .for(RuntimeGlobals.ensureChunkHandlers) - .tap(plugin, handler); - compilation.hooks.runtimeRequirementInTree - .for(RuntimeGlobals.hmrDownloadUpdateHandlers) - .tap(plugin, handler); - } - ); - } - - /** - * @param {Chunk} chunk chunk - * @param {Iterable<Module>} modules unordered modules - * @param {Compilation} compilation compilation - * @returns {Module[]} ordered modules - */ - getModulesInOrder(chunk, modules, compilation) { - if (!modules) return []; - - /** @type {Module[]} */ - const modulesList = [...modules]; - - // Get ordered list of modules per chunk group - // Lists are in reverse order to allow to use Array.pop() - const modulesByChunkGroup = Array.from(chunk.groupsIterable, chunkGroup => { - const sortedModules = modulesList - .map(module => { - return { - module, - index: chunkGroup.getModulePostOrderIndex(module) - }; - }) - .filter(item => item.index !== undefined) - .sort( - (a, b) => - /** @type {number} */ (b.index) - /** @type {number} */ (a.index) - ) - .map(item => item.module); - - return { list: sortedModules, set: new Set(sortedModules) }; - }); - - if (modulesByChunkGroup.length === 1) - return modulesByChunkGroup[0].list.reverse(); - - const compareModuleLists = ({ list: a }, { list: b }) => { - if (a.length === 0) { - return b.length === 0 ? 0 : 1; - } else { - if (b.length === 0) return -1; - return compareModulesByIdentifier(a[a.length - 1], b[b.length - 1]); - } - }; - - modulesByChunkGroup.sort(compareModuleLists); - - /** @type {Module[]} */ - const finalModules = []; - - for (;;) { - const failedModules = new Set(); - const list = modulesByChunkGroup[0].list; - if (list.length === 0) { - // done, everything empty - break; - } - /** @type {Module} */ - let selectedModule = list[list.length - 1]; - let hasFailed = undefined; - outer: for (;;) { - for (const { list, set } of modulesByChunkGroup) { - if (list.length === 0) continue; - const lastModule = list[list.length - 1]; - if (lastModule === selectedModule) continue; - if (!set.has(selectedModule)) continue; - failedModules.add(selectedModule); - if (failedModules.has(lastModule)) { - // There is a conflict, try other alternatives - hasFailed = lastModule; - continue; - } - selectedModule = lastModule; - hasFailed = false; - continue outer; // restart - } - break; - } - if (hasFailed) { - // There is a not resolve-able conflict with the selectedModule - if (compilation) { - // TODO print better warning - compilation.warnings.push( - new WebpackError( - `chunk ${chunk.name || chunk.id}\nConflicting order between ${ - /** @type {Module} */ - (hasFailed).readableIdentifier(compilation.requestShortener) - } and ${selectedModule.readableIdentifier( - compilation.requestShortener - )}` - ) - ); - } - selectedModule = /** @type {Module} */ (hasFailed); - } - // Insert the selected module into the final modules list - finalModules.push(selectedModule); - // Remove the selected module from all lists - for (const { list, set } of modulesByChunkGroup) { - const lastModule = list[list.length - 1]; - if (lastModule === selectedModule) list.pop(); - else if (hasFailed && set.has(selectedModule)) { - const idx = list.indexOf(selectedModule); - if (idx >= 0) list.splice(idx, 1); - } - } - modulesByChunkGroup.sort(compareModuleLists); - } - return finalModules; - } - - /** - * @param {Chunk} chunk chunk - * @param {ChunkGraph} chunkGraph chunk graph - * @param {Compilation} compilation compilation - * @returns {Module[]} ordered css modules - */ - getOrderedChunkCssModules(chunk, chunkGraph, compilation) { - return [ - ...this.getModulesInOrder( - chunk, - /** @type {Iterable<Module>} */ - ( - chunkGraph.getOrderedChunkModulesIterableBySourceType( - chunk, - "css-import", - compareModulesByIdentifier - ) - ), - compilation - ), - ...this.getModulesInOrder( - chunk, - /** @type {Iterable<Module>} */ - ( - chunkGraph.getOrderedChunkModulesIterableBySourceType( - chunk, - "css", - compareModulesByIdentifier - ) - ), - compilation - ) - ]; - } - - /** - * @param {Object} options options - * @param {string | undefined} options.uniqueName unique name - * @param {Chunk} options.chunk chunk - * @param {ChunkGraph} options.chunkGraph chunk graph - * @param {CodeGenerationResults} options.codeGenerationResults code generation results - * @param {CssModule[]} options.modules ordered css modules - * @returns {Source} generated source - */ - renderChunk({ - uniqueName, - chunk, - chunkGraph, - codeGenerationResults, - modules - }) { - const source = new ConcatSource(); - /** @type {string[]} */ - const metaData = []; - for (const module of modules) { - try { - const codeGenResult = codeGenerationResults.get(module, chunk.runtime); - - let moduleSource = - /** @type {Source} */ - ( - codeGenResult.sources.get("css") || - codeGenResult.sources.get("css-import") - ); - - let inheritance = [[module.cssLayer, module.supports, module.media]]; - - if (module.inheritance) { - inheritance.push(...module.inheritance); - } - - for (let i = 0; i < inheritance.length; i++) { - const layer = inheritance[i][0]; - const supports = inheritance[i][1]; - const media = inheritance[i][2]; - - if (media) { - moduleSource = new ConcatSource( - `@media ${media} {\n`, - new PrefixSource("\t", moduleSource), - "}\n" - ); - } - - if (supports) { - moduleSource = new ConcatSource( - `@supports (${supports}) {\n`, - new PrefixSource("\t", moduleSource), - "}\n" - ); - } - - // Layer can be anonymous - if (layer !== undefined && layer !== null) { - moduleSource = new ConcatSource( - `@layer${layer ? ` ${layer}` : ""} {\n`, - new PrefixSource("\t", moduleSource), - "}\n" - ); - } - } - - if (moduleSource) { - source.add(moduleSource); - source.add("\n"); - } - /** @type {Map<string, string> | undefined} */ - const exports = - codeGenResult.data && codeGenResult.data.get("css-exports"); - let moduleId = chunkGraph.getModuleId(module) + ""; - - // When `optimization.moduleIds` is `named` the module id is a path, so we need to normalize it between platforms - if (typeof moduleId === "string") { - moduleId = moduleId.replace(/\\/g, "/"); - } - - metaData.push( - `${ - exports - ? Array.from(exports, ([n, v]) => { - const shortcutValue = `${ - uniqueName ? uniqueName + "-" : "" - }${moduleId}-${n}`; - return v === shortcutValue - ? `${escapeCss(n)}/` - : v === "--" + shortcutValue - ? `${escapeCss(n)}%` - : `${escapeCss(n)}(${escapeCss(v)})`; - }).join("") - : "" - }${escapeCss(moduleId)}` - ); - } catch (e) { - /** @type {Error} */ - (e).message += `\nduring rendering of css ${module.identifier()}`; - throw e; - } - } - source.add( - `head{--webpack-${escapeCss( - (uniqueName ? uniqueName + "-" : "") + chunk.id, - true - )}:${metaData.join(",")};}` - ); - return source; - } - - /** - * @param {Chunk} chunk chunk - * @param {OutputOptions} outputOptions output options - * @returns {Chunk["cssFilenameTemplate"] | OutputOptions["cssFilename"] | OutputOptions["cssChunkFilename"]} used filename template - */ - static getChunkFilenameTemplate(chunk, outputOptions) { - if (chunk.cssFilenameTemplate) { - return chunk.cssFilenameTemplate; - } else if (chunk.canBeInitial()) { - return outputOptions.cssFilename; - } else { - return outputOptions.cssChunkFilename; - } - } - - /** - * @param {Chunk} chunk chunk - * @param {ChunkGraph} chunkGraph chunk graph - * @returns {boolean} true, when the chunk has css - */ - static chunkHasCss(chunk, chunkGraph) { - return ( - !!chunkGraph.getChunkModulesIterableBySourceType(chunk, "css") || - !!chunkGraph.getChunkModulesIterableBySourceType(chunk, "css-import") - ); - } -} - -module.exports = CssModulesPlugin; diff --git a/node_modules/webpack/lib/css/CssParser.js b/node_modules/webpack/lib/css/CssParser.js deleted file mode 100644 index 98a937d9..00000000 --- a/node_modules/webpack/lib/css/CssParser.js +++ /dev/null @@ -1,1033 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ - -"use strict"; - -const ModuleDependencyWarning = require("../ModuleDependencyWarning"); -const { CSS_MODULE_TYPE_AUTO } = require("../ModuleTypeConstants"); -const Parser = require("../Parser"); -const WebpackError = require("../WebpackError"); -const ConstDependency = require("../dependencies/ConstDependency"); -const CssExportDependency = require("../dependencies/CssExportDependency"); -const CssImportDependency = require("../dependencies/CssImportDependency"); -const CssLocalIdentifierDependency = require("../dependencies/CssLocalIdentifierDependency"); -const CssSelfLocalIdentifierDependency = require("../dependencies/CssSelfLocalIdentifierDependency"); -const CssUrlDependency = require("../dependencies/CssUrlDependency"); -const StaticExportsDependency = require("../dependencies/StaticExportsDependency"); -const { parseResource } = require("../util/identifier"); -const walkCssTokens = require("./walkCssTokens"); - -/** @typedef {import("../Parser").ParserState} ParserState */ -/** @typedef {import("../Parser").PreparsedAst} PreparsedAst */ -/** @typedef {[number, number]} Range */ - -const CC_LEFT_CURLY = "{".charCodeAt(0); -const CC_RIGHT_CURLY = "}".charCodeAt(0); -const CC_COLON = ":".charCodeAt(0); -const CC_SLASH = "/".charCodeAt(0); -const CC_SEMICOLON = ";".charCodeAt(0); - -// https://www.w3.org/TR/css-syntax-3/#newline -// We don't have `preprocessing` stage, so we need specify all of them -const STRING_MULTILINE = /\\[\n\r\f]/g; -// https://www.w3.org/TR/css-syntax-3/#whitespace -const TRIM_WHITE_SPACES = /(^[ \t\n\r\f]*|[ \t\n\r\f]*$)/g; -const UNESCAPE = /\\([0-9a-fA-F]{1,6}[ \t\n\r\f]?|[\s\S])/g; -const IMAGE_SET_FUNCTION = /^(-\w+-)?image-set$/i; -const OPTIONALLY_VENDOR_PREFIXED_KEYFRAMES_AT_RULE = /^@(-\w+-)?keyframes$/; -const OPTIONALLY_VENDOR_PREFIXED_ANIMATION_PROPERTY = - /^(-\w+-)?animation(-name)?$/i; -const IS_MODULES = /\.module(s)?\.[^.]+$/i; - -/** - * @param {string} str url string - * @param {boolean} isString is url wrapped in quotes - * @returns {string} normalized url - */ -const normalizeUrl = (str, isString) => { - // Remove extra spaces and newlines: - // `url("im\ - // g.png")` - if (isString) { - str = str.replace(STRING_MULTILINE, ""); - } - - str = str - // Remove unnecessary spaces from `url(" img.png ")` - .replace(TRIM_WHITE_SPACES, "") - // Unescape - .replace(UNESCAPE, match => { - if (match.length > 2) { - return String.fromCharCode(parseInt(match.slice(1).trim(), 16)); - } else { - return match[1]; - } - }); - - if (/^data:/i.test(str)) { - return str; - } - - if (str.includes("%")) { - // Convert `url('%2E/img.png')` -> `url('./img.png')` - try { - str = decodeURIComponent(str); - } catch (error) { - // Ignore - } - } - - return str; -}; - -class LocConverter { - /** - * @param {string} input input - */ - constructor(input) { - this._input = input; - this.line = 1; - this.column = 0; - this.pos = 0; - } - - /** - * @param {number} pos position - * @returns {LocConverter} location converter - */ - get(pos) { - if (this.pos !== pos) { - if (this.pos < pos) { - const str = this._input.slice(this.pos, pos); - let i = str.lastIndexOf("\n"); - if (i === -1) { - this.column += str.length; - } else { - this.column = str.length - i - 1; - this.line++; - while (i > 0 && (i = str.lastIndexOf("\n", i - 1)) !== -1) - this.line++; - } - } else { - let i = this._input.lastIndexOf("\n", this.pos); - while (i >= pos) { - this.line--; - i = i > 0 ? this._input.lastIndexOf("\n", i - 1) : -1; - } - this.column = pos - i; - } - this.pos = pos; - } - return this; - } -} - -const CSS_MODE_TOP_LEVEL = 0; -const CSS_MODE_IN_BLOCK = 1; -const CSS_MODE_IN_AT_IMPORT = 2; -const CSS_MODE_AT_IMPORT_INVALID = 3; -const CSS_MODE_AT_NAMESPACE_INVALID = 4; - -class CssParser extends Parser { - constructor({ allowModeSwitch = true, defaultMode = "global" } = {}) { - super(); - this.allowModeSwitch = allowModeSwitch; - this.defaultMode = defaultMode; - } - - /** - * @param {ParserState} state parser state - * @param {string} message warning message - * @param {LocConverter} locConverter location converter - * @param {number} start start offset - * @param {number} end end offset - */ - _emitWarning(state, message, locConverter, start, end) { - const { line: sl, column: sc } = locConverter.get(start); - const { line: el, column: ec } = locConverter.get(end); - - state.current.addWarning( - new ModuleDependencyWarning(state.module, new WebpackError(message), { - start: { line: sl, column: sc }, - end: { line: el, column: ec } - }) - ); - } - - /** - * @param {string | Buffer | PreparsedAst} source the source to parse - * @param {ParserState} state the parser state - * @returns {ParserState} the parser state - */ - parse(source, state) { - if (Buffer.isBuffer(source)) { - source = source.toString("utf-8"); - } else if (typeof source === "object") { - throw new Error("webpackAst is unexpected for the CssParser"); - } - if (source[0] === "\ufeff") { - source = source.slice(1); - } - - const module = state.module; - - /** @type {string | undefined} */ - let oldDefaultMode; - - if ( - module.type === CSS_MODULE_TYPE_AUTO && - IS_MODULES.test( - parseResource(module.matchResource || module.resource).path - ) - ) { - oldDefaultMode = this.defaultMode; - - this.defaultMode = "local"; - } - - const locConverter = new LocConverter(source); - /** @type {Set<string>}*/ - const declaredCssVariables = new Set(); - /** @type {number} */ - let scope = CSS_MODE_TOP_LEVEL; - /** @type {number} */ - let blockNestingLevel = 0; - /** @type {boolean} */ - let allowImportAtRule = true; - /** @type {"local" | "global" | undefined} */ - let modeData = undefined; - /** @type {[number, number] | undefined} */ - let lastIdentifier = undefined; - /** @type [string, number, number][] */ - let balanced = []; - /** @type {undefined | { start: number, url?: string, urlStart?: number, urlEnd?: number, layer?: string, layerStart?: number, layerEnd?: number, supports?: string, supportsStart?: number, supportsEnd?: number, inSupports?:boolean, media?: string }} */ - let importData = undefined; - /** @type {boolean} */ - let inAnimationProperty = false; - /** @type {boolean} */ - let isNextRulePrelude = true; - - /** - * @param {string} input input - * @param {number} pos position - * @returns {boolean} true, when next is nested syntax - */ - const isNextNestedSyntax = (input, pos) => { - pos = walkCssTokens.eatWhitespaceAndComments(input, pos); - - if (input[pos] === "}") { - return false; - } - - // According spec only identifier can be used as a property name - const isIdentifier = walkCssTokens.isIdentStartCodePoint( - input.charCodeAt(pos) - ); - - return !isIdentifier; - }; - /** - * @returns {boolean} true, when in local scope - */ - const isLocalMode = () => - modeData === "local" || - (this.defaultMode === "local" && modeData === undefined); - /** - * @param {string} chars characters - * @returns {(input: string, pos: number) => number} function to eat characters - */ - const eatUntil = chars => { - const charCodes = Array.from({ length: chars.length }, (_, i) => - chars.charCodeAt(i) - ); - const arr = Array.from( - { length: charCodes.reduce((a, b) => Math.max(a, b), 0) + 1 }, - () => false - ); - charCodes.forEach(cc => (arr[cc] = true)); - return (input, pos) => { - for (;;) { - const cc = input.charCodeAt(pos); - if (cc < arr.length && arr[cc]) { - return pos; - } - pos++; - if (pos === input.length) return pos; - } - }; - }; - /** - * @param {string} input input - * @param {number} pos start position - * @param {(input: string, pos: number) => number} eater eater - * @returns {[number,string]} new position and text - */ - const eatText = (input, pos, eater) => { - let text = ""; - for (;;) { - if (input.charCodeAt(pos) === CC_SLASH) { - const newPos = walkCssTokens.eatComments(input, pos); - if (pos !== newPos) { - pos = newPos; - if (pos === input.length) break; - } else { - text += "/"; - pos++; - if (pos === input.length) break; - } - } - const newPos = eater(input, pos); - if (pos !== newPos) { - text += input.slice(pos, newPos); - pos = newPos; - } else { - break; - } - if (pos === input.length) break; - } - return [pos, text.trimEnd()]; - }; - const eatExportName = eatUntil(":};/"); - const eatExportValue = eatUntil("};/"); - /** - * @param {string} input input - * @param {number} pos start position - * @returns {number} position after parse - */ - const parseExports = (input, pos) => { - pos = walkCssTokens.eatWhitespaceAndComments(input, pos); - const cc = input.charCodeAt(pos); - if (cc !== CC_LEFT_CURLY) { - this._emitWarning( - state, - `Unexpected '${input[pos]}' at ${pos} during parsing of ':export' (expected '{')`, - locConverter, - pos, - pos - ); - return pos; - } - pos++; - pos = walkCssTokens.eatWhitespaceAndComments(input, pos); - for (;;) { - if (input.charCodeAt(pos) === CC_RIGHT_CURLY) break; - pos = walkCssTokens.eatWhitespaceAndComments(input, pos); - if (pos === input.length) return pos; - let start = pos; - let name; - [pos, name] = eatText(input, pos, eatExportName); - if (pos === input.length) return pos; - if (input.charCodeAt(pos) !== CC_COLON) { - this._emitWarning( - state, - `Unexpected '${input[pos]}' at ${pos} during parsing of export name in ':export' (expected ':')`, - locConverter, - start, - pos - ); - return pos; - } - pos++; - if (pos === input.length) return pos; - pos = walkCssTokens.eatWhitespaceAndComments(input, pos); - if (pos === input.length) return pos; - let value; - [pos, value] = eatText(input, pos, eatExportValue); - if (pos === input.length) return pos; - const cc = input.charCodeAt(pos); - if (cc === CC_SEMICOLON) { - pos++; - if (pos === input.length) return pos; - pos = walkCssTokens.eatWhitespaceAndComments(input, pos); - if (pos === input.length) return pos; - } else if (cc !== CC_RIGHT_CURLY) { - this._emitWarning( - state, - `Unexpected '${input[pos]}' at ${pos} during parsing of export value in ':export' (expected ';' or '}')`, - locConverter, - start, - pos - ); - return pos; - } - const dep = new CssExportDependency(name, value); - const { line: sl, column: sc } = locConverter.get(start); - const { line: el, column: ec } = locConverter.get(pos); - dep.setLoc(sl, sc, el, ec); - module.addDependency(dep); - } - pos++; - if (pos === input.length) return pos; - pos = walkCssTokens.eatWhiteLine(input, pos); - return pos; - }; - const eatPropertyName = eatUntil(":{};"); - /** - * @param {string} input input - * @param {number} pos name start position - * @param {number} end name end position - * @returns {number} position after handling - */ - const processLocalDeclaration = (input, pos, end) => { - modeData = undefined; - pos = walkCssTokens.eatWhitespaceAndComments(input, pos); - const propertyNameStart = pos; - const [propertyNameEnd, propertyName] = eatText( - input, - pos, - eatPropertyName - ); - if (input.charCodeAt(propertyNameEnd) !== CC_COLON) return end; - pos = propertyNameEnd + 1; - if (propertyName.startsWith("--")) { - // CSS Variable - const { line: sl, column: sc } = locConverter.get(propertyNameStart); - const { line: el, column: ec } = locConverter.get(propertyNameEnd); - const name = propertyName.slice(2); - const dep = new CssLocalIdentifierDependency( - name, - [propertyNameStart, propertyNameEnd], - "--" - ); - dep.setLoc(sl, sc, el, ec); - module.addDependency(dep); - declaredCssVariables.add(name); - } else if ( - !propertyName.startsWith("--") && - OPTIONALLY_VENDOR_PREFIXED_ANIMATION_PROPERTY.test(propertyName) - ) { - inAnimationProperty = true; - } - return pos; - }; - /** - * @param {string} input input - */ - const processDeclarationValueDone = input => { - if (inAnimationProperty && lastIdentifier) { - const { line: sl, column: sc } = locConverter.get(lastIdentifier[0]); - const { line: el, column: ec } = locConverter.get(lastIdentifier[1]); - const name = input.slice(lastIdentifier[0], lastIdentifier[1]); - const dep = new CssSelfLocalIdentifierDependency(name, lastIdentifier); - dep.setLoc(sl, sc, el, ec); - module.addDependency(dep); - lastIdentifier = undefined; - } - }; - const eatKeyframes = eatUntil("{};/"); - const eatNameInVar = eatUntil(",)};/"); - walkCssTokens(source, { - isSelector: () => { - return isNextRulePrelude; - }, - url: (input, start, end, contentStart, contentEnd) => { - let value = normalizeUrl(input.slice(contentStart, contentEnd), false); - - switch (scope) { - case CSS_MODE_IN_AT_IMPORT: { - // Do not parse URLs in `supports(...)` - if (importData.inSupports) { - break; - } - - if (importData.url) { - this._emitWarning( - state, - `Duplicate of 'url(...)' in '${input.slice( - importData.start, - end - )}'`, - locConverter, - start, - end - ); - - break; - } - - importData.url = value; - importData.urlStart = start; - importData.urlEnd = end; - break; - } - // Do not parse URLs in import between rules - case CSS_MODE_AT_NAMESPACE_INVALID: - case CSS_MODE_AT_IMPORT_INVALID: { - break; - } - case CSS_MODE_IN_BLOCK: { - // Ignore `url()`, `url('')` and `url("")`, they are valid by spec - if (value.length === 0) { - break; - } - - const dep = new CssUrlDependency(value, [start, end], "url"); - const { line: sl, column: sc } = locConverter.get(start); - const { line: el, column: ec } = locConverter.get(end); - dep.setLoc(sl, sc, el, ec); - module.addDependency(dep); - module.addCodeGenerationDependency(dep); - break; - } - } - return end; - }, - string: (input, start, end) => { - switch (scope) { - case CSS_MODE_IN_AT_IMPORT: { - const insideURLFunction = - balanced[balanced.length - 1] && - balanced[balanced.length - 1][0] === "url"; - - // Do not parse URLs in `supports(...)` and other strings if we already have a URL - if ( - importData.inSupports || - (!insideURLFunction && importData.url) - ) { - break; - } - - if (insideURLFunction && importData.url) { - this._emitWarning( - state, - `Duplicate of 'url(...)' in '${input.slice( - importData.start, - end - )}'`, - locConverter, - start, - end - ); - - break; - } - - importData.url = normalizeUrl( - input.slice(start + 1, end - 1), - true - ); - - if (!insideURLFunction) { - importData.urlStart = start; - importData.urlEnd = end; - } - - break; - } - case CSS_MODE_IN_BLOCK: { - // TODO move escaped parsing to tokenizer - const last = balanced[balanced.length - 1]; - - if ( - last && - (last[0].replace(/\\/g, "").toLowerCase() === "url" || - IMAGE_SET_FUNCTION.test(last[0].replace(/\\/g, ""))) - ) { - let value = normalizeUrl(input.slice(start + 1, end - 1), true); - - // Ignore `url()`, `url('')` and `url("")`, they are valid by spec - if (value.length === 0) { - break; - } - - const isUrl = last[0].replace(/\\/g, "").toLowerCase() === "url"; - const dep = new CssUrlDependency( - value, - [start, end], - isUrl ? "string" : "url" - ); - const { line: sl, column: sc } = locConverter.get(start); - const { line: el, column: ec } = locConverter.get(end); - dep.setLoc(sl, sc, el, ec); - module.addDependency(dep); - module.addCodeGenerationDependency(dep); - } - } - } - return end; - }, - atKeyword: (input, start, end) => { - const name = input.slice(start, end).toLowerCase(); - if (name === "@namespace") { - scope = CSS_MODE_AT_NAMESPACE_INVALID; - this._emitWarning( - state, - "'@namespace' is not supported in bundled CSS", - locConverter, - start, - end - ); - return end; - } else if (name === "@import") { - if (!allowImportAtRule) { - scope = CSS_MODE_AT_IMPORT_INVALID; - this._emitWarning( - state, - "Any '@import' rules must precede all other rules", - locConverter, - start, - end - ); - return end; - } - - scope = CSS_MODE_IN_AT_IMPORT; - importData = { start }; - } else if ( - this.allowModeSwitch && - OPTIONALLY_VENDOR_PREFIXED_KEYFRAMES_AT_RULE.test(name) - ) { - let pos = end; - pos = walkCssTokens.eatWhitespaceAndComments(input, pos); - if (pos === input.length) return pos; - const [newPos, name] = eatText(input, pos, eatKeyframes); - if (newPos === input.length) return newPos; - if (input.charCodeAt(newPos) !== CC_LEFT_CURLY) { - this._emitWarning( - state, - `Unexpected '${input[newPos]}' at ${newPos} during parsing of @keyframes (expected '{')`, - locConverter, - start, - end - ); - - return newPos; - } - const { line: sl, column: sc } = locConverter.get(pos); - const { line: el, column: ec } = locConverter.get(newPos); - const dep = new CssLocalIdentifierDependency(name, [pos, newPos]); - dep.setLoc(sl, sc, el, ec); - module.addDependency(dep); - pos = newPos; - return pos + 1; - } else if (this.allowModeSwitch && name === "@property") { - let pos = end; - pos = walkCssTokens.eatWhitespaceAndComments(input, pos); - if (pos === input.length) return pos; - const propertyNameStart = pos; - const [propertyNameEnd, propertyName] = eatText( - input, - pos, - eatKeyframes - ); - if (propertyNameEnd === input.length) return propertyNameEnd; - if (!propertyName.startsWith("--")) return propertyNameEnd; - if (input.charCodeAt(propertyNameEnd) !== CC_LEFT_CURLY) { - this._emitWarning( - state, - `Unexpected '${input[propertyNameEnd]}' at ${propertyNameEnd} during parsing of @property (expected '{')`, - locConverter, - start, - end - ); - - return propertyNameEnd; - } - const { line: sl, column: sc } = locConverter.get(pos); - const { line: el, column: ec } = locConverter.get(propertyNameEnd); - const name = propertyName.slice(2); - const dep = new CssLocalIdentifierDependency( - name, - [propertyNameStart, propertyNameEnd], - "--" - ); - dep.setLoc(sl, sc, el, ec); - module.addDependency(dep); - declaredCssVariables.add(name); - pos = propertyNameEnd; - return pos + 1; - } else if ( - name === "@media" || - name === "@supports" || - name === "@layer" || - name === "@container" - ) { - modeData = isLocalMode() ? "local" : "global"; - isNextRulePrelude = true; - return end; - } else if (this.allowModeSwitch) { - modeData = "global"; - isNextRulePrelude = false; - } - return end; - }, - semicolon: (input, start, end) => { - switch (scope) { - case CSS_MODE_IN_AT_IMPORT: { - const { start } = importData; - - if (importData.url === undefined) { - this._emitWarning( - state, - `Expected URL in '${input.slice(start, end)}'`, - locConverter, - start, - end - ); - importData = undefined; - scope = CSS_MODE_TOP_LEVEL; - return end; - } - if ( - importData.urlStart > importData.layerStart || - importData.urlStart > importData.supportsStart - ) { - this._emitWarning( - state, - `An URL in '${input.slice( - start, - end - )}' should be before 'layer(...)' or 'supports(...)'`, - locConverter, - start, - end - ); - importData = undefined; - scope = CSS_MODE_TOP_LEVEL; - return end; - } - if (importData.layerStart > importData.supportsStart) { - this._emitWarning( - state, - `The 'layer(...)' in '${input.slice( - start, - end - )}' should be before 'supports(...)'`, - locConverter, - start, - end - ); - importData = undefined; - scope = CSS_MODE_TOP_LEVEL; - return end; - } - - const semicolonPos = end; - end = walkCssTokens.eatWhiteLine(input, end + 1); - const { line: sl, column: sc } = locConverter.get(start); - const { line: el, column: ec } = locConverter.get(end); - const lastEnd = - importData.supportsEnd || - importData.layerEnd || - importData.urlEnd || - start; - const pos = walkCssTokens.eatWhitespaceAndComments(input, lastEnd); - // Prevent to consider comments as a part of media query - if (pos !== semicolonPos - 1) { - importData.media = input.slice(lastEnd, semicolonPos - 1).trim(); - } - - const url = importData.url.trim(); - - if (url.length === 0) { - const dep = new ConstDependency("", [start, end]); - module.addPresentationalDependency(dep); - dep.setLoc(sl, sc, el, ec); - } else { - const dep = new CssImportDependency( - url, - [start, end], - importData.layer, - importData.supports, - importData.media && importData.media.length > 0 - ? importData.media - : undefined - ); - dep.setLoc(sl, sc, el, ec); - module.addDependency(dep); - } - - importData = undefined; - scope = CSS_MODE_TOP_LEVEL; - - break; - } - case CSS_MODE_AT_IMPORT_INVALID: - case CSS_MODE_AT_NAMESPACE_INVALID: { - scope = CSS_MODE_TOP_LEVEL; - - break; - } - case CSS_MODE_IN_BLOCK: { - if (this.allowModeSwitch) { - processDeclarationValueDone(input); - inAnimationProperty = false; - isNextRulePrelude = isNextNestedSyntax(input, end); - } - break; - } - } - return end; - }, - leftCurlyBracket: (input, start, end) => { - switch (scope) { - case CSS_MODE_TOP_LEVEL: { - allowImportAtRule = false; - scope = CSS_MODE_IN_BLOCK; - blockNestingLevel = 1; - - if (this.allowModeSwitch) { - isNextRulePrelude = isNextNestedSyntax(input, end); - } - - break; - } - case CSS_MODE_IN_BLOCK: { - blockNestingLevel++; - - if (this.allowModeSwitch) { - isNextRulePrelude = isNextNestedSyntax(input, end); - } - break; - } - } - return end; - }, - rightCurlyBracket: (input, start, end) => { - switch (scope) { - case CSS_MODE_IN_BLOCK: { - if (isLocalMode()) { - processDeclarationValueDone(input); - inAnimationProperty = false; - } - if (--blockNestingLevel === 0) { - scope = CSS_MODE_TOP_LEVEL; - - if (this.allowModeSwitch) { - isNextRulePrelude = true; - modeData = undefined; - } - } else if (this.allowModeSwitch) { - isNextRulePrelude = isNextNestedSyntax(input, end); - } - break; - } - } - return end; - }, - identifier: (input, start, end) => { - switch (scope) { - case CSS_MODE_IN_BLOCK: { - if (isLocalMode()) { - // Handle only top level values and not inside functions - if (inAnimationProperty && balanced.length === 0) { - lastIdentifier = [start, end]; - } else { - return processLocalDeclaration(input, start, end); - } - } - break; - } - case CSS_MODE_IN_AT_IMPORT: { - if (input.slice(start, end).toLowerCase() === "layer") { - importData.layer = ""; - importData.layerStart = start; - importData.layerEnd = end; - } - break; - } - } - return end; - }, - class: (input, start, end) => { - if (isLocalMode()) { - const name = input.slice(start + 1, end); - const dep = new CssLocalIdentifierDependency(name, [start + 1, end]); - const { line: sl, column: sc } = locConverter.get(start); - const { line: el, column: ec } = locConverter.get(end); - dep.setLoc(sl, sc, el, ec); - module.addDependency(dep); - } - - return end; - }, - id: (input, start, end) => { - if (isLocalMode()) { - const name = input.slice(start + 1, end); - const dep = new CssLocalIdentifierDependency(name, [start + 1, end]); - const { line: sl, column: sc } = locConverter.get(start); - const { line: el, column: ec } = locConverter.get(end); - dep.setLoc(sl, sc, el, ec); - module.addDependency(dep); - } - return end; - }, - function: (input, start, end) => { - let name = input.slice(start, end - 1); - - balanced.push([name, start, end]); - - if ( - scope === CSS_MODE_IN_AT_IMPORT && - name.toLowerCase() === "supports" - ) { - importData.inSupports = true; - } - - if (isLocalMode()) { - name = name.toLowerCase(); - - // Don't rename animation name when we have `var()` function - if (inAnimationProperty && balanced.length === 1) { - lastIdentifier = undefined; - } - - if (name === "var") { - let pos = walkCssTokens.eatWhitespaceAndComments(input, end); - if (pos === input.length) return pos; - const [newPos, name] = eatText(input, pos, eatNameInVar); - if (!name.startsWith("--")) return end; - const { line: sl, column: sc } = locConverter.get(pos); - const { line: el, column: ec } = locConverter.get(newPos); - const dep = new CssSelfLocalIdentifierDependency( - name.slice(2), - [pos, newPos], - "--", - declaredCssVariables - ); - dep.setLoc(sl, sc, el, ec); - module.addDependency(dep); - return newPos; - } - } - - return end; - }, - leftParenthesis: (input, start, end) => { - balanced.push(["(", start, end]); - - return end; - }, - rightParenthesis: (input, start, end) => { - const last = balanced[balanced.length - 1]; - const popped = balanced.pop(); - - if ( - this.allowModeSwitch && - popped && - (popped[0] === ":local" || popped[0] === ":global") - ) { - modeData = balanced[balanced.length - 1] - ? /** @type {"local" | "global"} */ - (balanced[balanced.length - 1][0]) - : undefined; - const dep = new ConstDependency("", [start, end]); - module.addPresentationalDependency(dep); - - return end; - } - - switch (scope) { - case CSS_MODE_IN_AT_IMPORT: { - if (last && last[0] === "url" && !importData.inSupports) { - importData.urlStart = last[1]; - importData.urlEnd = end; - } else if ( - last && - last[0].toLowerCase() === "layer" && - !importData.inSupports - ) { - importData.layer = input.slice(last[2], end - 1).trim(); - importData.layerStart = last[1]; - importData.layerEnd = end; - } else if (last && last[0].toLowerCase() === "supports") { - importData.supports = input.slice(last[2], end - 1).trim(); - importData.supportsStart = last[1]; - importData.supportsEnd = end; - importData.inSupports = false; - } - break; - } - } - - return end; - }, - pseudoClass: (input, start, end) => { - if (this.allowModeSwitch) { - const name = input.slice(start, end).toLowerCase(); - - if (name === ":global") { - modeData = "global"; - // Eat extra whitespace and comments - end = walkCssTokens.eatWhitespace(input, end); - const dep = new ConstDependency("", [start, end]); - module.addPresentationalDependency(dep); - return end; - } else if (name === ":local") { - modeData = "local"; - // Eat extra whitespace and comments - end = walkCssTokens.eatWhitespace(input, end); - const dep = new ConstDependency("", [start, end]); - module.addPresentationalDependency(dep); - return end; - } - - switch (scope) { - case CSS_MODE_TOP_LEVEL: { - if (name === ":export") { - const pos = parseExports(input, end); - const dep = new ConstDependency("", [start, pos]); - module.addPresentationalDependency(dep); - return pos; - } - break; - } - } - } - - return end; - }, - pseudoFunction: (input, start, end) => { - let name = input.slice(start, end - 1); - - balanced.push([name, start, end]); - - if (this.allowModeSwitch) { - name = name.toLowerCase(); - - if (name === ":global") { - modeData = "global"; - const dep = new ConstDependency("", [start, end]); - module.addPresentationalDependency(dep); - } else if (name === ":local") { - modeData = "local"; - const dep = new ConstDependency("", [start, end]); - module.addPresentationalDependency(dep); - } - } - - return end; - }, - comma: (input, start, end) => { - if (this.allowModeSwitch) { - // Reset stack for `:global .class :local .class-other` selector after - modeData = undefined; - - switch (scope) { - case CSS_MODE_IN_BLOCK: { - if (isLocalMode()) { - processDeclarationValueDone(input); - } - - break; - } - } - } - return end; - } - }); - - if (oldDefaultMode) { - this.defaultMode = oldDefaultMode; - } - - module.buildInfo.strict = true; - module.buildMeta.exportsType = "namespace"; - module.addDependency(new StaticExportsDependency([], true)); - return state; - } -} - -module.exports = CssParser; diff --git a/node_modules/webpack/lib/css/walkCssTokens.js b/node_modules/webpack/lib/css/walkCssTokens.js deleted file mode 100644 index badc61aa..00000000 --- a/node_modules/webpack/lib/css/walkCssTokens.js +++ /dev/null @@ -1,790 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ - -"use strict"; - -/** - * @typedef {Object} CssTokenCallbacks - * @property {function(string, number): boolean=} isSelector - * @property {function(string, number, number, number, number): number=} url - * @property {function(string, number, number): number=} string - * @property {function(string, number, number): number=} leftParenthesis - * @property {function(string, number, number): number=} rightParenthesis - * @property {function(string, number, number): number=} pseudoFunction - * @property {function(string, number, number): number=} function - * @property {function(string, number, number): number=} pseudoClass - * @property {function(string, number, number): number=} atKeyword - * @property {function(string, number, number): number=} class - * @property {function(string, number, number): number=} identifier - * @property {function(string, number, number): number=} id - * @property {function(string, number, number): number=} leftCurlyBracket - * @property {function(string, number, number): number=} rightCurlyBracket - * @property {function(string, number, number): number=} semicolon - * @property {function(string, number, number): number=} comma - */ - -/** @typedef {function(string, number, CssTokenCallbacks): number} CharHandler */ - -// spec: https://drafts.csswg.org/css-syntax/ - -const CC_LINE_FEED = "\n".charCodeAt(0); -const CC_CARRIAGE_RETURN = "\r".charCodeAt(0); -const CC_FORM_FEED = "\f".charCodeAt(0); - -const CC_TAB = "\t".charCodeAt(0); -const CC_SPACE = " ".charCodeAt(0); - -const CC_SOLIDUS = "/".charCodeAt(0); -const CC_REVERSE_SOLIDUS = "\\".charCodeAt(0); -const CC_ASTERISK = "*".charCodeAt(0); - -const CC_LEFT_PARENTHESIS = "(".charCodeAt(0); -const CC_RIGHT_PARENTHESIS = ")".charCodeAt(0); -const CC_LEFT_CURLY = "{".charCodeAt(0); -const CC_RIGHT_CURLY = "}".charCodeAt(0); -const CC_LEFT_SQUARE = "[".charCodeAt(0); -const CC_RIGHT_SQUARE = "]".charCodeAt(0); - -const CC_QUOTATION_MARK = '"'.charCodeAt(0); -const CC_APOSTROPHE = "'".charCodeAt(0); - -const CC_FULL_STOP = ".".charCodeAt(0); -const CC_COLON = ":".charCodeAt(0); -const CC_SEMICOLON = ";".charCodeAt(0); -const CC_COMMA = ",".charCodeAt(0); -const CC_PERCENTAGE = "%".charCodeAt(0); -const CC_AT_SIGN = "@".charCodeAt(0); - -const CC_LOW_LINE = "_".charCodeAt(0); -const CC_LOWER_A = "a".charCodeAt(0); -const CC_LOWER_U = "u".charCodeAt(0); -const CC_LOWER_E = "e".charCodeAt(0); -const CC_LOWER_Z = "z".charCodeAt(0); -const CC_UPPER_A = "A".charCodeAt(0); -const CC_UPPER_E = "E".charCodeAt(0); -const CC_UPPER_U = "U".charCodeAt(0); -const CC_UPPER_Z = "Z".charCodeAt(0); -const CC_0 = "0".charCodeAt(0); -const CC_9 = "9".charCodeAt(0); - -const CC_NUMBER_SIGN = "#".charCodeAt(0); -const CC_PLUS_SIGN = "+".charCodeAt(0); -const CC_HYPHEN_MINUS = "-".charCodeAt(0); - -const CC_LESS_THAN_SIGN = "<".charCodeAt(0); -const CC_GREATER_THAN_SIGN = ">".charCodeAt(0); - -/** - * @param {number} cc char code - * @returns {boolean} true, if cc is a newline - */ -const _isNewLine = cc => { - return ( - cc === CC_LINE_FEED || cc === CC_CARRIAGE_RETURN || cc === CC_FORM_FEED - ); -}; - -/** @type {CharHandler} */ -const consumeSpace = (input, pos, callbacks) => { - /** @type {number} */ - let cc; - do { - pos++; - cc = input.charCodeAt(pos); - } while (_isWhiteSpace(cc)); - return pos; -}; - -/** - * @param {number} cc char code - * @returns {boolean} true, if cc is a newline - */ -const _isNewline = cc => { - return ( - cc === CC_LINE_FEED || cc === CC_CARRIAGE_RETURN || cc === CC_FORM_FEED - ); -}; - -/** - * @param {number} cc char code - * @returns {boolean} true, if cc is a space (U+0009 CHARACTER TABULATION or U+0020 SPACE) - */ -const _isSpace = cc => { - return cc === CC_TAB || cc === CC_SPACE; -}; - -/** - * @param {number} cc char code - * @returns {boolean} true, if cc is a whitespace - */ -const _isWhiteSpace = cc => { - return _isNewline(cc) || _isSpace(cc); -}; - -/** - * ident-start code point - * - * A letter, a non-ASCII code point, or U+005F LOW LINE (_). - * - * @param {number} cc char code - * @returns {boolean} true, if cc is a start code point of an identifier - */ -const isIdentStartCodePoint = cc => { - return ( - (cc >= CC_LOWER_A && cc <= CC_LOWER_Z) || - (cc >= CC_UPPER_A && cc <= CC_UPPER_Z) || - cc === CC_LOW_LINE || - cc >= 0x80 - ); -}; - -/** @type {CharHandler} */ -const consumeDelimToken = (input, pos, callbacks) => { - return pos + 1; -}; - -/** @type {CharHandler} */ -const consumeComments = (input, pos, callbacks) => { - // If the next two input code point are U+002F SOLIDUS (/) followed by a U+002A - // ASTERISK (*), consume them and all following code points up to and including - // the first U+002A ASTERISK (*) followed by a U+002F SOLIDUS (/), or up to an - // EOF code point. Return to the start of this step. - // - // If the preceding paragraph ended by consuming an EOF code point, this is a parse error. - // But we are silent on errors. - if ( - input.charCodeAt(pos) === CC_SOLIDUS && - input.charCodeAt(pos + 1) === CC_ASTERISK - ) { - pos += 1; - while (pos < input.length) { - if ( - input.charCodeAt(pos) === CC_ASTERISK && - input.charCodeAt(pos + 1) === CC_SOLIDUS - ) { - pos += 2; - break; - } - pos++; - } - } - return pos; -}; - -/** @type {function(number): CharHandler} */ -const consumeString = quote_cc => (input, pos, callbacks) => { - const start = pos; - pos = _consumeString(input, pos, quote_cc); - if (callbacks.string !== undefined) { - pos = callbacks.string(input, start, pos); - } - return pos; -}; - -/** - * @param {string} input input - * @param {number} pos position - * @param {number} quote_cc quote char code - * @returns {number} new position - */ -const _consumeString = (input, pos, quote_cc) => { - pos++; - for (;;) { - if (pos === input.length) return pos; - const cc = input.charCodeAt(pos); - if (cc === quote_cc) return pos + 1; - if (_isNewLine(cc)) { - // bad string - return pos; - } - if (cc === CC_REVERSE_SOLIDUS) { - // we don't need to fully parse the escaped code point - // just skip over a potential new line - pos++; - if (pos === input.length) return pos; - pos++; - } else { - pos++; - } - } -}; - -/** - * @param {number} cc char code - * @returns {boolean} is identifier start code - */ -const _isIdentifierStartCode = cc => { - return ( - cc === CC_LOW_LINE || - (cc >= CC_LOWER_A && cc <= CC_LOWER_Z) || - (cc >= CC_UPPER_A && cc <= CC_UPPER_Z) || - cc > 0x80 - ); -}; - -/** - * @param {number} first first code point - * @param {number} second second code point - * @returns {boolean} true if two code points are a valid escape - */ -const _isTwoCodePointsAreValidEscape = (first, second) => { - if (first !== CC_REVERSE_SOLIDUS) return false; - if (_isNewLine(second)) return false; - return true; -}; - -/** - * @param {number} cc char code - * @returns {boolean} is digit - */ -const _isDigit = cc => { - return cc >= CC_0 && cc <= CC_9; -}; - -/** - * @param {string} input input - * @param {number} pos position - * @returns {boolean} true, if input at pos starts an identifier - */ -const _startsIdentifier = (input, pos) => { - const cc = input.charCodeAt(pos); - if (cc === CC_HYPHEN_MINUS) { - if (pos === input.length) return false; - const cc = input.charCodeAt(pos + 1); - if (cc === CC_HYPHEN_MINUS) return true; - if (cc === CC_REVERSE_SOLIDUS) { - const cc = input.charCodeAt(pos + 2); - return !_isNewLine(cc); - } - return _isIdentifierStartCode(cc); - } - if (cc === CC_REVERSE_SOLIDUS) { - const cc = input.charCodeAt(pos + 1); - return !_isNewLine(cc); - } - return _isIdentifierStartCode(cc); -}; - -/** @type {CharHandler} */ -const consumeNumberSign = (input, pos, callbacks) => { - const start = pos; - pos++; - if (pos === input.length) return pos; - if (callbacks.isSelector(input, pos) && _startsIdentifier(input, pos)) { - pos = _consumeIdentifier(input, pos, callbacks); - if (callbacks.id !== undefined) { - return callbacks.id(input, start, pos); - } - } - return pos; -}; - -/** @type {CharHandler} */ -const consumeMinus = (input, pos, callbacks) => { - const start = pos; - pos++; - if (pos === input.length) return pos; - const cc = input.charCodeAt(pos); - // If the input stream starts with a number, reconsume the current input code point, consume a numeric token, and return it. - if (cc === CC_FULL_STOP || _isDigit(cc)) { - return consumeNumericToken(input, pos, callbacks); - } else if (cc === CC_HYPHEN_MINUS) { - pos++; - if (pos === input.length) return pos; - const cc = input.charCodeAt(pos); - if (cc === CC_GREATER_THAN_SIGN) { - return pos + 1; - } else { - pos = _consumeIdentifier(input, pos, callbacks); - if (callbacks.identifier !== undefined) { - return callbacks.identifier(input, start, pos); - } - } - } else if (cc === CC_REVERSE_SOLIDUS) { - if (pos + 1 === input.length) return pos; - const cc = input.charCodeAt(pos + 1); - if (_isNewLine(cc)) return pos; - pos = _consumeIdentifier(input, pos, callbacks); - if (callbacks.identifier !== undefined) { - return callbacks.identifier(input, start, pos); - } - } else if (_isIdentifierStartCode(cc)) { - pos = consumeOtherIdentifier(input, pos - 1, callbacks); - } - return pos; -}; - -/** @type {CharHandler} */ -const consumeDot = (input, pos, callbacks) => { - const start = pos; - pos++; - if (pos === input.length) return pos; - const cc = input.charCodeAt(pos); - if (_isDigit(cc)) return consumeNumericToken(input, pos - 2, callbacks); - if (!callbacks.isSelector(input, pos) || !_startsIdentifier(input, pos)) - return pos; - pos = _consumeIdentifier(input, pos, callbacks); - if (callbacks.class !== undefined) return callbacks.class(input, start, pos); - return pos; -}; - -/** @type {CharHandler} */ -const consumeNumericToken = (input, pos, callbacks) => { - pos = _consumeNumber(input, pos, callbacks); - if (pos === input.length) return pos; - if (_startsIdentifier(input, pos)) - return _consumeIdentifier(input, pos, callbacks); - const cc = input.charCodeAt(pos); - if (cc === CC_PERCENTAGE) return pos + 1; - return pos; -}; - -/** @type {CharHandler} */ -const consumeOtherIdentifier = (input, pos, callbacks) => { - const start = pos; - pos = _consumeIdentifier(input, pos, callbacks); - if (pos !== input.length && input.charCodeAt(pos) === CC_LEFT_PARENTHESIS) { - pos++; - if (callbacks.function !== undefined) { - return callbacks.function(input, start, pos); - } - } else { - if (callbacks.identifier !== undefined) { - return callbacks.identifier(input, start, pos); - } - } - return pos; -}; - -/** @type {CharHandler} */ -const consumePotentialUrl = (input, pos, callbacks) => { - const start = pos; - pos = _consumeIdentifier(input, pos, callbacks); - const nextPos = pos + 1; - if ( - pos === start + 3 && - input.slice(start, nextPos).toLowerCase() === "url(" - ) { - pos++; - let cc = input.charCodeAt(pos); - while (_isWhiteSpace(cc)) { - pos++; - if (pos === input.length) return pos; - cc = input.charCodeAt(pos); - } - if (cc === CC_QUOTATION_MARK || cc === CC_APOSTROPHE) { - if (callbacks.function !== undefined) { - return callbacks.function(input, start, nextPos); - } - return nextPos; - } else { - const contentStart = pos; - /** @type {number} */ - let contentEnd; - for (;;) { - if (cc === CC_REVERSE_SOLIDUS) { - pos++; - if (pos === input.length) return pos; - pos++; - } else if (_isWhiteSpace(cc)) { - contentEnd = pos; - do { - pos++; - if (pos === input.length) return pos; - cc = input.charCodeAt(pos); - } while (_isWhiteSpace(cc)); - if (cc !== CC_RIGHT_PARENTHESIS) return pos; - pos++; - if (callbacks.url !== undefined) { - return callbacks.url(input, start, pos, contentStart, contentEnd); - } - return pos; - } else if (cc === CC_RIGHT_PARENTHESIS) { - contentEnd = pos; - pos++; - if (callbacks.url !== undefined) { - return callbacks.url(input, start, pos, contentStart, contentEnd); - } - return pos; - } else if (cc === CC_LEFT_PARENTHESIS) { - return pos; - } else { - pos++; - } - if (pos === input.length) return pos; - cc = input.charCodeAt(pos); - } - } - } else { - if (callbacks.identifier !== undefined) { - return callbacks.identifier(input, start, pos); - } - return pos; - } -}; - -/** @type {CharHandler} */ -const consumePotentialPseudo = (input, pos, callbacks) => { - const start = pos; - pos++; - if (!callbacks.isSelector(input, pos) || !_startsIdentifier(input, pos)) - return pos; - pos = _consumeIdentifier(input, pos, callbacks); - let cc = input.charCodeAt(pos); - if (cc === CC_LEFT_PARENTHESIS) { - pos++; - if (callbacks.pseudoFunction !== undefined) { - return callbacks.pseudoFunction(input, start, pos); - } - return pos; - } - if (callbacks.pseudoClass !== undefined) { - return callbacks.pseudoClass(input, start, pos); - } - return pos; -}; - -/** @type {CharHandler} */ -const consumeLeftParenthesis = (input, pos, callbacks) => { - pos++; - if (callbacks.leftParenthesis !== undefined) { - return callbacks.leftParenthesis(input, pos - 1, pos); - } - return pos; -}; - -/** @type {CharHandler} */ -const consumeRightParenthesis = (input, pos, callbacks) => { - pos++; - if (callbacks.rightParenthesis !== undefined) { - return callbacks.rightParenthesis(input, pos - 1, pos); - } - return pos; -}; - -/** @type {CharHandler} */ -const consumeLeftCurlyBracket = (input, pos, callbacks) => { - pos++; - if (callbacks.leftCurlyBracket !== undefined) { - return callbacks.leftCurlyBracket(input, pos - 1, pos); - } - return pos; -}; - -/** @type {CharHandler} */ -const consumeRightCurlyBracket = (input, pos, callbacks) => { - pos++; - if (callbacks.rightCurlyBracket !== undefined) { - return callbacks.rightCurlyBracket(input, pos - 1, pos); - } - return pos; -}; - -/** @type {CharHandler} */ -const consumeSemicolon = (input, pos, callbacks) => { - pos++; - if (callbacks.semicolon !== undefined) { - return callbacks.semicolon(input, pos - 1, pos); - } - return pos; -}; - -/** @type {CharHandler} */ -const consumeComma = (input, pos, callbacks) => { - pos++; - if (callbacks.comma !== undefined) { - return callbacks.comma(input, pos - 1, pos); - } - return pos; -}; - -/** @type {CharHandler} */ -const _consumeIdentifier = (input, pos) => { - for (;;) { - const cc = input.charCodeAt(pos); - if (cc === CC_REVERSE_SOLIDUS) { - pos++; - if (pos === input.length) return pos; - pos++; - } else if ( - _isIdentifierStartCode(cc) || - _isDigit(cc) || - cc === CC_HYPHEN_MINUS - ) { - pos++; - } else { - return pos; - } - } -}; - -/** @type {CharHandler} */ -const _consumeNumber = (input, pos) => { - pos++; - if (pos === input.length) return pos; - let cc = input.charCodeAt(pos); - while (_isDigit(cc)) { - pos++; - if (pos === input.length) return pos; - cc = input.charCodeAt(pos); - } - if (cc === CC_FULL_STOP && pos + 1 !== input.length) { - const next = input.charCodeAt(pos + 1); - if (_isDigit(next)) { - pos += 2; - cc = input.charCodeAt(pos); - while (_isDigit(cc)) { - pos++; - if (pos === input.length) return pos; - cc = input.charCodeAt(pos); - } - } - } - if (cc === CC_LOWER_E || cc === CC_UPPER_E) { - if (pos + 1 !== input.length) { - const next = input.charCodeAt(pos + 2); - if (_isDigit(next)) { - pos += 2; - } else if ( - (next === CC_HYPHEN_MINUS || next === CC_PLUS_SIGN) && - pos + 2 !== input.length - ) { - const next = input.charCodeAt(pos + 2); - if (_isDigit(next)) { - pos += 3; - } else { - return pos; - } - } else { - return pos; - } - } - } else { - return pos; - } - cc = input.charCodeAt(pos); - while (_isDigit(cc)) { - pos++; - if (pos === input.length) return pos; - cc = input.charCodeAt(pos); - } - return pos; -}; - -/** @type {CharHandler} */ -const consumeLessThan = (input, pos, callbacks) => { - if (input.slice(pos + 1, pos + 4) === "!--") return pos + 4; - return pos + 1; -}; - -/** @type {CharHandler} */ -const consumeAt = (input, pos, callbacks) => { - const start = pos; - pos++; - if (pos === input.length) return pos; - if (_startsIdentifier(input, pos)) { - pos = _consumeIdentifier(input, pos, callbacks); - if (callbacks.atKeyword !== undefined) { - pos = callbacks.atKeyword(input, start, pos); - } - } - return pos; -}; - -/** @type {CharHandler} */ -const consumeReverseSolidus = (input, pos, callbacks) => { - const start = pos; - pos++; - if (pos === input.length) return pos; - // If the input stream starts with a valid escape, reconsume the current input code point, consume an ident-like token, and return it. - if ( - _isTwoCodePointsAreValidEscape( - input.charCodeAt(start), - input.charCodeAt(pos) - ) - ) { - return consumeOtherIdentifier(input, pos - 1, callbacks); - } - // Otherwise, this is a parse error. Return a <delim-token> with its value set to the current input code point. - return pos; -}; - -const CHAR_MAP = Array.from({ length: 0x80 }, (_, cc) => { - // https://drafts.csswg.org/css-syntax/#consume-token - switch (cc) { - // whitespace - case CC_LINE_FEED: - case CC_CARRIAGE_RETURN: - case CC_FORM_FEED: - case CC_TAB: - case CC_SPACE: - return consumeSpace; - // U+0022 QUOTATION MARK (") - case CC_QUOTATION_MARK: - return consumeString(cc); - // U+0023 NUMBER SIGN (#) - case CC_NUMBER_SIGN: - return consumeNumberSign; - // U+0027 APOSTROPHE (') - case CC_APOSTROPHE: - return consumeString(cc); - // U+0028 LEFT PARENTHESIS (() - case CC_LEFT_PARENTHESIS: - return consumeLeftParenthesis; - // U+0029 RIGHT PARENTHESIS ()) - case CC_RIGHT_PARENTHESIS: - return consumeRightParenthesis; - // U+002B PLUS SIGN (+) - case CC_PLUS_SIGN: - return consumeNumericToken; - // U+002C COMMA (,) - case CC_COMMA: - return consumeComma; - // U+002D HYPHEN-MINUS (-) - case CC_HYPHEN_MINUS: - return consumeMinus; - // U+002E FULL STOP (.) - case CC_FULL_STOP: - return consumeDot; - // U+003A COLON (:) - case CC_COLON: - return consumePotentialPseudo; - // U+003B SEMICOLON (;) - case CC_SEMICOLON: - return consumeSemicolon; - // U+003C LESS-THAN SIGN (<) - case CC_LESS_THAN_SIGN: - return consumeLessThan; - // U+0040 COMMERCIAL AT (@) - case CC_AT_SIGN: - return consumeAt; - // U+005B LEFT SQUARE BRACKET ([) - case CC_LEFT_SQUARE: - return consumeDelimToken; - // U+005C REVERSE SOLIDUS (\) - case CC_REVERSE_SOLIDUS: - return consumeReverseSolidus; - // U+005D RIGHT SQUARE BRACKET (]) - case CC_RIGHT_SQUARE: - return consumeDelimToken; - // U+007B LEFT CURLY BRACKET ({) - case CC_LEFT_CURLY: - return consumeLeftCurlyBracket; - // U+007D RIGHT CURLY BRACKET (}) - case CC_RIGHT_CURLY: - return consumeRightCurlyBracket; - // Optimization - case CC_LOWER_U: - case CC_UPPER_U: - return consumePotentialUrl; - default: - // digit - if (_isDigit(cc)) return consumeNumericToken; - // ident-start code point - if (isIdentStartCodePoint(cc)) { - return consumeOtherIdentifier; - } - // EOF, but we don't have it - // anything else - return consumeDelimToken; - } -}); - -/** - * @param {string} input input css - * @param {CssTokenCallbacks} callbacks callbacks - * @returns {void} - */ -module.exports = (input, callbacks) => { - // This section describes how to consume a token from a stream of code points. It will return a single token of any type. - let pos = 0; - while (pos < input.length) { - // Consume comments. - pos = consumeComments(input, pos, callbacks); - - const cc = input.charCodeAt(pos); - - // Consume the next input code point. - if (cc < 0x80) { - pos = CHAR_MAP[cc](input, pos, callbacks); - } else { - pos++; - } - } -}; - -module.exports.isIdentStartCodePoint = isIdentStartCodePoint; - -/** - * @param {string} input input - * @param {number} pos position - * @returns {number} position after comments - */ -module.exports.eatComments = (input, pos) => { - for (;;) { - let originalPos = pos; - pos = consumeComments(input, pos, {}); - if (originalPos === pos) { - break; - } - } - - return pos; -}; - -/** - * @param {string} input input - * @param {number} pos position - * @returns {number} position after whitespace - */ -module.exports.eatWhitespace = (input, pos) => { - while (_isWhiteSpace(input.charCodeAt(pos))) { - pos++; - } - - return pos; -}; - -/** - * @param {string} input input - * @param {number} pos position - * @returns {number} position after whitespace and comments - */ -module.exports.eatWhitespaceAndComments = (input, pos) => { - for (;;) { - let originalPos = pos; - pos = consumeComments(input, pos, {}); - while (_isWhiteSpace(input.charCodeAt(pos))) { - pos++; - } - if (originalPos === pos) { - break; - } - } - - return pos; -}; - -/** - * @param {string} input input - * @param {number} pos position - * @returns {number} position after whitespace - */ -module.exports.eatWhiteLine = (input, pos) => { - for (;;) { - const cc = input.charCodeAt(pos); - if (_isSpace(cc)) { - pos++; - continue; - } - if (_isNewLine(cc)) pos++; - // For `\r\n` - if (cc === CC_CARRIAGE_RETURN && input.charCodeAt(pos + 1) === CC_LINE_FEED) - pos++; - break; - } - - return pos; -}; |
