css-loader
Advanced tools
Comparing version 6.2.0 to 6.3.0
@@ -54,18 +54,8 @@ "use strict"; | ||
if ((0, _utils.shouldUseImportPlugin)(options)) { | ||
const resolver = this.getResolve({ | ||
dependencyType: "css", | ||
conditionNames: ["style"], | ||
mainFields: ["css", "style", "main", "..."], | ||
mainFiles: ["index", "..."], | ||
extensions: [".css", "..."], | ||
preferRelative: true | ||
}); | ||
plugins.push((0, _plugins.importParser)({ | ||
isCSSStyleSheet: options.exportType === "css-style-sheet", | ||
loaderContext: this, | ||
imports: importPluginImports, | ||
api: importPluginApi, | ||
context: this.context, | ||
rootContext: this.rootContext, | ||
resourcePath: this.resourcePath, | ||
filter: (0, _utils.getFilter)(options.import.filter, this.resourcePath), | ||
resolver, | ||
filter: options.import.filter, | ||
urlHandler: url => (0, _utils.stringifyRequest)(this, (0, _utils.combineRequests)((0, _utils.getPreRequester)(this)(options.importLoaders), url)) | ||
@@ -103,11 +93,4 @@ })); | ||
if (needToUseIcssPlugin) { | ||
const icssResolver = this.getResolve({ | ||
dependencyType: "icss", | ||
conditionNames: ["style"], | ||
extensions: ["..."], | ||
mainFields: ["css", "style", "main", "..."], | ||
mainFiles: ["index", "..."], | ||
preferRelative: true | ||
}); | ||
plugins.push((0, _plugins.icssParser)({ | ||
loaderContext: this, | ||
imports: icssPluginImports, | ||
@@ -117,5 +100,2 @@ api: icssPluginApi, | ||
exports, | ||
context: this.context, | ||
rootContext: this.rootContext, | ||
resolver: icssResolver, | ||
urlHandler: url => (0, _utils.stringifyRequest)(this, (0, _utils.combineRequests)((0, _utils.getPreRequester)(this)(options.importLoaders), url)) | ||
@@ -178,6 +158,10 @@ })); | ||
imports.unshift({ | ||
type: "api_sourcemap_import", | ||
importName: "___CSS_LOADER_API_SOURCEMAP_IMPORT___", | ||
url: (0, _utils.stringifyRequest)(this, require.resolve("./runtime/cssWithMappingToString")) | ||
url: (0, _utils.stringifyRequest)(this, require.resolve("./runtime/sourceMaps")) | ||
}); | ||
} else { | ||
imports.unshift({ | ||
importName: "___CSS_LOADER_API_NO_SOURCEMAP_IMPORT___", | ||
url: (0, _utils.stringifyRequest)(this, require.resolve("./runtime/noSourceMaps")) | ||
}); | ||
} | ||
@@ -184,0 +168,0 @@ } |
@@ -196,2 +196,7 @@ { | ||
"type": "boolean" | ||
}, | ||
"exportType": { | ||
"description": "Allows exporting styles as array with modules, string or constructable stylesheet (i.e. `CSSStyleSheet`).", | ||
"link": "https://github.com/webpack-contrib/css-loader#exporttype", | ||
"enum": ["array", "string", "css-style-sheet"] | ||
} | ||
@@ -198,0 +203,0 @@ }, |
@@ -23,3 +23,14 @@ "use strict"; | ||
const imports = new Map(); | ||
const tasks = []; // eslint-disable-next-line guard-for-in | ||
const tasks = []; | ||
const { | ||
loaderContext | ||
} = options; | ||
const resolver = loaderContext.getResolve({ | ||
dependencyType: "icss", | ||
conditionNames: ["style"], | ||
extensions: ["..."], | ||
mainFields: ["css", "style", "main", "..."], | ||
mainFiles: ["index", "..."], | ||
preferRelative: true | ||
}); // eslint-disable-next-line guard-for-in | ||
@@ -43,10 +54,6 @@ for (const url in icssImports) { | ||
const request = (0, _utils.requestify)((0, _utils.normalizeUrl)(normalizedUrl, true), options.rootContext); | ||
const request = (0, _utils.requestify)((0, _utils.normalizeUrl)(normalizedUrl, true), loaderContext.rootContext); | ||
const doResolve = async () => { | ||
const { | ||
resolver, | ||
context | ||
} = options; | ||
const resolvedUrl = await (0, _utils.resolveRequests)(resolver, context, [...new Set([normalizedUrl, request])]); | ||
const resolvedUrl = await (0, _utils.resolveRequests)(resolver, loaderContext.context, [...new Set([normalizedUrl, request])]); | ||
@@ -53,0 +60,0 @@ if (!resolvedUrl) { |
@@ -46,5 +46,6 @@ "use strict"; | ||
const rawParams = atRule.raws && atRule.raws[key] && typeof atRule.raws[key].raw !== "undefined" ? atRule.raws[key].raw : atRule[key]; | ||
const { | ||
nodes: paramsNodes | ||
} = (0, _postcssValueParser.default)(atRule[key]); // No nodes - `@import ;` | ||
} = (0, _postcssValueParser.default)(rawParams); // No nodes - `@import ;` | ||
// Invalid type - `@import foo-bar;` | ||
@@ -96,7 +97,38 @@ | ||
const mediaNodes = paramsNodes.slice(1); | ||
const additionalNodes = paramsNodes.slice(1); | ||
let supports; | ||
let layer; | ||
let media; | ||
if (mediaNodes.length > 0) { | ||
media = _postcssValueParser.default.stringify(mediaNodes).trim().toLowerCase(); | ||
if (additionalNodes.length > 0) { | ||
let nodes = []; | ||
for (const node of additionalNodes) { | ||
nodes.push(node); | ||
const isLayerFunction = node.type === "function" && node.value.toLowerCase() === "layer"; | ||
const isLayerWord = node.type === "word" && node.value.toLowerCase() === "layer"; | ||
if (isLayerFunction || isLayerWord) { | ||
if (isLayerFunction) { | ||
nodes.splice(nodes.length - 1, 1, ...node.nodes); | ||
} else { | ||
nodes.splice(nodes.length - 1, 1, { | ||
type: "string", | ||
value: "", | ||
unclosed: false | ||
}); | ||
} | ||
layer = _postcssValueParser.default.stringify(nodes).trim().toLowerCase(); | ||
nodes = []; | ||
} else if (node.type === "function" && node.value.toLowerCase() === "supports") { | ||
nodes.splice(nodes.length - 1, 1, ...node.nodes); | ||
supports = _postcssValueParser.default.stringify(nodes).trim().toLowerCase(); | ||
nodes = []; | ||
} | ||
} | ||
if (nodes.length > 0) { | ||
media = _postcssValueParser.default.stringify(nodes).trim().toLowerCase(); | ||
} | ||
} // eslint-disable-next-line consistent-return | ||
@@ -109,2 +141,4 @@ | ||
url, | ||
layer, | ||
supports, | ||
media, | ||
@@ -124,2 +158,7 @@ isRequestable | ||
import(atRule) { | ||
if (options.isCSSStyleSheet) { | ||
options.loaderContext.emitError(new Error(atRule.error("'@import' rules are not allowed here and will not be processed").message)); | ||
return; | ||
} | ||
let parsedAtRule; | ||
@@ -149,2 +188,13 @@ | ||
const { | ||
loaderContext | ||
} = options; | ||
const resolver = loaderContext.getResolve({ | ||
dependencyType: "css", | ||
conditionNames: ["style"], | ||
mainFields: ["css", "style", "main", "..."], | ||
mainFiles: ["index", "..."], | ||
extensions: [".css", "..."], | ||
preferRelative: true | ||
}); | ||
const resolvedAtRules = await Promise.all(parsedAtRules.map(async parsedAtRule => { | ||
@@ -156,2 +206,4 @@ const { | ||
url, | ||
layer, | ||
supports, | ||
media | ||
@@ -161,3 +213,3 @@ } = parsedAtRule; | ||
if (options.filter) { | ||
const needKeep = await options.filter(url, media); | ||
const needKeep = await options.filter(url, media, loaderContext.resourcePath, supports, layer); | ||
@@ -170,8 +222,4 @@ if (!needKeep) { | ||
if (isRequestable) { | ||
const request = (0, _utils.requestify)(url, options.rootContext); | ||
const { | ||
resolver, | ||
context | ||
} = options; | ||
const resolvedUrl = await (0, _utils.resolveRequests)(resolver, context, [...new Set([request, url])]); | ||
const request = (0, _utils.requestify)(url, loaderContext.rootContext); | ||
const resolvedUrl = await (0, _utils.resolveRequests)(resolver, loaderContext.context, [...new Set([request, url])]); | ||
@@ -182,3 +230,3 @@ if (!resolvedUrl) { | ||
if (resolvedUrl === options.resourcePath) { | ||
if (resolvedUrl === loaderContext.resourcePath) { | ||
atRule.remove(); | ||
@@ -192,2 +240,4 @@ return; | ||
url: resolvedUrl, | ||
layer, | ||
supports, | ||
media, | ||
@@ -203,2 +253,4 @@ prefix, | ||
url, | ||
layer, | ||
supports, | ||
media, | ||
@@ -222,2 +274,4 @@ prefix, | ||
isRequestable, | ||
layer, | ||
supports, | ||
media | ||
@@ -229,2 +283,4 @@ } = resolvedAtRule; | ||
url, | ||
layer, | ||
supports, | ||
media, | ||
@@ -256,2 +312,4 @@ index | ||
importName, | ||
layer, | ||
supports, | ||
media, | ||
@@ -258,0 +316,0 @@ index |
@@ -7,4 +7,2 @@ "use strict"; | ||
*/ | ||
// css base code, injected by the css-loader | ||
// eslint-disable-next-line func-names | ||
module.exports = function (cssWithMappingToString) { | ||
@@ -15,18 +13,39 @@ var list = []; // return the list of modules as css string | ||
return this.map(function (item) { | ||
var content = cssWithMappingToString(item); | ||
var content = ""; | ||
var needLayer = typeof item[5] !== "undefined"; | ||
if (item[4]) { | ||
content += "@supports (".concat(item[4], ") {"); | ||
} | ||
if (item[2]) { | ||
return "@media ".concat(item[2], " {").concat(content, "}"); | ||
content += "@media ".concat(item[2], " {"); | ||
} | ||
if (needLayer) { | ||
content += "@layer".concat(item[5].length > 0 ? " ".concat(item[5]) : "", " {"); | ||
} | ||
content += cssWithMappingToString(item); | ||
if (needLayer) { | ||
content += "}"; | ||
} | ||
if (item[2]) { | ||
content += "}"; | ||
} | ||
if (item[4]) { | ||
content += "}"; | ||
} | ||
return content; | ||
}).join(""); | ||
}; // import a list of modules into the list | ||
// eslint-disable-next-line func-names | ||
list.i = function (modules, mediaQuery, dedupe) { | ||
list.i = function i(modules, media, dedupe, supports, layer) { | ||
if (typeof modules === "string") { | ||
// eslint-disable-next-line no-param-reassign | ||
modules = [[null, modules, ""]]; | ||
modules = [[null, modules, undefined]]; | ||
} | ||
@@ -37,5 +56,4 @@ | ||
if (dedupe) { | ||
for (var i = 0; i < this.length; i++) { | ||
// eslint-disable-next-line prefer-destructuring | ||
var id = this[i][0]; | ||
for (var _i = 0; _i < this.length; _i++) { | ||
var id = this[_i][0]; | ||
@@ -48,18 +66,36 @@ if (id != null) { | ||
for (var _i = 0; _i < modules.length; _i++) { | ||
var item = [].concat(modules[_i]); | ||
for (var _i2 = 0; _i2 < modules.length; _i2++) { | ||
var item = [].concat(modules[_i2]); | ||
if (dedupe && alreadyImportedModules[item[0]]) { | ||
// eslint-disable-next-line no-continue | ||
continue; | ||
} | ||
if (mediaQuery) { | ||
if (typeof layer !== "undefined") { | ||
if (typeof item[5] === "undefined") { | ||
item[5] = layer; | ||
} else { | ||
item[1] = "@layer".concat(item[5].length > 0 ? " ".concat(item[5]) : "", " {").concat(item[1], "}"); | ||
item[5] = layer; | ||
} | ||
} | ||
if (media) { | ||
if (!item[2]) { | ||
item[2] = mediaQuery; | ||
item[2] = media; | ||
} else { | ||
item[2] = "".concat(mediaQuery, " and ").concat(item[2]); | ||
item[1] = "@media ".concat(item[2], " {").concat(item[1], "}"); | ||
item[2] = media; | ||
} | ||
} | ||
if (supports) { | ||
if (!item[4]) { | ||
item[4] = "".concat(supports); | ||
} else { | ||
item[1] = "@supports (".concat(item[4], ") {").concat(item[1], "}"); | ||
item[4] = supports; | ||
} | ||
} | ||
list.push(item); | ||
@@ -66,0 +102,0 @@ } |
@@ -5,3 +5,2 @@ "use strict"; | ||
if (!options) { | ||
// eslint-disable-next-line no-param-reassign | ||
options = {}; | ||
@@ -12,9 +11,7 @@ } | ||
return url; | ||
} // eslint-disable-next-line no-underscore-dangle, no-param-reassign | ||
} | ||
url = String(url.__esModule ? url.default : url); // If url is already wrapped in quotes, remove them | ||
if (/^['"].*['"]$/.test(url)) { | ||
// eslint-disable-next-line no-param-reassign | ||
url = url.slice(1, -1); | ||
@@ -24,3 +21,2 @@ } | ||
if (options.hash) { | ||
// eslint-disable-next-line no-param-reassign | ||
url += options.hash; | ||
@@ -27,0 +23,0 @@ } // Should url be wrapped? |
@@ -316,10 +316,16 @@ "use strict"; | ||
function defaultGetLocalIdent(loaderContext, localIdentName, localName, options) { | ||
let relativeMatchResource = ""; // eslint-disable-next-line no-underscore-dangle | ||
let relativeMatchResource = ""; | ||
const { | ||
context | ||
} = options; | ||
const { | ||
resourcePath | ||
} = loaderContext; // eslint-disable-next-line no-underscore-dangle | ||
if (loaderContext._module && loaderContext._module.matchResource) { | ||
relativeMatchResource = `${normalizePath( // eslint-disable-next-line no-underscore-dangle | ||
_path.default.relative(options.context, loaderContext._module.matchResource))}\x00`; | ||
_path.default.relative(context, loaderContext._module.matchResource))}\x00`; | ||
} | ||
const relativeResourcePath = normalizePath(_path.default.relative(options.context, loaderContext.resourcePath)); // eslint-disable-next-line no-param-reassign | ||
const relativeResourcePath = normalizePath(_path.default.relative(context, resourcePath)); // eslint-disable-next-line no-param-reassign | ||
@@ -332,9 +338,9 @@ options.content = `${relativeMatchResource}${relativeResourcePath}\x00${localName}`; | ||
} = options; | ||
const mathes = localIdentName.match(/\[(?:([^:\]]+):)?(?:(hash|contenthash|fullhash))(?::([a-z]+\d*))?(?::(\d+))?\]/i); | ||
const matches = localIdentName.match(/\[(?:([^:\]]+):)?(?:(hash|contenthash|fullhash))(?::([a-z]+\d*))?(?::(\d+))?\]/i); | ||
if (mathes) { | ||
const hashName = mathes[2] || hashFunction; | ||
hashFunction = mathes[1] || hashFunction; | ||
hashDigest = mathes[3] || hashDigest; | ||
hashDigestLength = mathes[4] || hashDigestLength; // `hash` and `contenthash` are same in `loader-utils` context | ||
if (matches) { | ||
const hashName = matches[2] || hashFunction; | ||
hashFunction = matches[1] || hashFunction; | ||
hashDigest = matches[3] || hashDigest; | ||
hashDigestLength = matches[4] || hashDigestLength; // `hash` and `contenthash` are same in `loader-utils` context | ||
// let's keep `hash` for backward compatibility | ||
@@ -360,9 +366,9 @@ // eslint-disable-next-line no-param-reassign | ||
const ext = _path.default.extname(loaderContext.resourcePath); | ||
const ext = _path.default.extname(resourcePath); | ||
const base = _path.default.basename(loaderContext.resourcePath); | ||
const base = _path.default.basename(resourcePath); | ||
const name = base.slice(0, base.length - ext.length); | ||
const data = { | ||
filename: _path.default.relative(options.context, loaderContext.resourcePath), | ||
filename: _path.default.relative(context, resourcePath), | ||
contentHash: localIdentHash, | ||
@@ -378,4 +384,18 @@ chunk: { | ||
if (/\[folder\]/gi.test(result)) { | ||
const dirname = _path.default.dirname(resourcePath); | ||
let directory = normalizePath(_path.default.relative(context, `${dirname + _path.default.sep}_`)); | ||
directory = directory.substr(0, directory.length - 1); | ||
let folder = ""; | ||
if (directory.length > 1) { | ||
folder = _path.default.basename(directory); | ||
} | ||
result = result.replace(/\[folder\]/gi, () => folder); | ||
} | ||
if (options.regExp) { | ||
const match = loaderContext.resourcePath.match(options.regExp); | ||
const match = resourcePath.match(options.regExp); | ||
@@ -469,12 +489,4 @@ if (match) { | ||
function getValidLocalName(localName, exportLocalsConvention) { | ||
if (typeof exportLocalsConvention === "function") { | ||
const result = exportLocalsConvention(localName); | ||
return Array.isArray(result) ? result[0] : result; | ||
} | ||
if (exportLocalsConvention === "dashesOnly") { | ||
return dashesCamelCase(localName); | ||
} | ||
return camelCase(localName); | ||
const result = exportLocalsConvention(localName); | ||
return Array.isArray(result) ? result[0] : result; | ||
} | ||
@@ -485,3 +497,3 @@ | ||
function getModulesOptions(rawOptions, loaderContext) { | ||
function getModulesOptions(rawOptions, exportType, loaderContext) { | ||
if (typeof rawOptions.modules === "boolean" && rawOptions.modules === false) { | ||
@@ -516,2 +528,3 @@ return false; | ||
} = loaderContext._compilation; | ||
const needNamedExport = exportType === "css-style-sheet" || exportType === "string"; | ||
const modulesOptions = { | ||
@@ -531,8 +544,41 @@ auto, | ||
getLocalIdent: undefined, | ||
namedExport: false, | ||
exportLocalsConvention: rawModulesOptions.namedExport === true && typeof rawModulesOptions.exportLocalsConvention === "undefined" ? "camelCaseOnly" : "asIs", | ||
namedExport: needNamedExport || false, | ||
exportLocalsConvention: (rawModulesOptions.namedExport === true || needNamedExport) && typeof rawModulesOptions.exportLocalsConvention === "undefined" ? "camelCaseOnly" : "asIs", | ||
exportOnlyLocals: false, | ||
...rawModulesOptions | ||
}; | ||
let exportLocalsConventionType; | ||
if (typeof modulesOptions.exportLocalsConvention === "string") { | ||
exportLocalsConventionType = modulesOptions.exportLocalsConvention; | ||
modulesOptions.exportLocalsConvention = name => { | ||
switch (exportLocalsConventionType) { | ||
case "camelCase": | ||
{ | ||
return [name, camelCase(name)]; | ||
} | ||
case "camelCaseOnly": | ||
{ | ||
return camelCase(name); | ||
} | ||
case "dashes": | ||
{ | ||
return [name, dashesCamelCase(name)]; | ||
} | ||
case "dashesOnly": | ||
{ | ||
return dashesCamelCase(name); | ||
} | ||
case "asIs": | ||
default: | ||
return name; | ||
} | ||
}; | ||
} | ||
if (typeof modulesOptions.auto === "boolean") { | ||
@@ -571,8 +617,18 @@ const isModules = modulesOptions.auto && IS_MODULES.test(resourcePath); | ||
if (needNamedExport) { | ||
if (rawOptions.esModule === false) { | ||
throw new Error("The 'exportType' option with the 'css-style-sheet' or 'string' value requires the 'esModules' option to be enabled"); | ||
} | ||
if (modulesOptions.namedExport === false) { | ||
throw new Error("The 'exportType' option with the 'css-style-sheet' or 'string' value requires the 'modules.namedExport' option to be enabled"); | ||
} | ||
} | ||
if (modulesOptions.namedExport === true) { | ||
if (rawOptions.esModule === false) { | ||
throw new Error('The "modules.namedExport" option requires the "esModules" option to be enabled'); | ||
throw new Error("The 'modules.namedExport' option requires the 'esModules' option to be enabled"); | ||
} | ||
if (typeof modulesOptions.exportLocalsConvention === "string" && modulesOptions.exportLocalsConvention !== "camelCaseOnly" && modulesOptions.exportLocalsConvention !== "dashesOnly") { | ||
if (typeof exportLocalsConventionType === "string" && exportLocalsConventionType !== "camelCaseOnly" && exportLocalsConventionType !== "dashesOnly") { | ||
throw new Error('The "modules.namedExport" option requires the "modules.exportLocalsConvention" option to be "camelCaseOnly" or "dashesOnly"'); | ||
@@ -586,3 +642,4 @@ } | ||
function normalizeOptions(rawOptions, loaderContext) { | ||
const modulesOptions = getModulesOptions(rawOptions, loaderContext); | ||
const exportType = typeof rawOptions.exportType === "undefined" ? "array" : rawOptions.exportType; | ||
const modulesOptions = getModulesOptions(rawOptions, exportType, loaderContext); | ||
return { | ||
@@ -594,3 +651,4 @@ url: typeof rawOptions.url === "undefined" ? true : rawOptions.url, | ||
importLoaders: typeof rawOptions.importLoaders === "string" ? parseInt(rawOptions.importLoaders, 10) : rawOptions.importLoaders, | ||
esModule: typeof rawOptions.esModule === "undefined" ? true : rawOptions.esModule | ||
esModule: typeof rawOptions.esModule === "undefined" ? true : rawOptions.esModule, | ||
exportType | ||
}; | ||
@@ -824,2 +882,30 @@ } | ||
function printParams(media, dedupe, supports, layer) { | ||
let result = ""; | ||
if (typeof layer !== "undefined") { | ||
result = `, ${JSON.stringify(layer)}`; | ||
} | ||
if (typeof supports !== "undefined") { | ||
result = `, ${JSON.stringify(supports)}${result}`; | ||
} else if (result.length > 0) { | ||
result = `, undefined${result}`; | ||
} | ||
if (dedupe) { | ||
result = `, true${result}`; | ||
} else if (result.length > 0) { | ||
result = `, false${result}`; | ||
} | ||
if (media) { | ||
result = `${JSON.stringify(media)}${result}`; | ||
} else if (result.length > 0) { | ||
result = `""${result}`; | ||
} | ||
return result; | ||
} | ||
function getModuleCode(result, api, replacements, options, loaderContext) { | ||
@@ -832,3 +918,3 @@ if (options.modules.exportOnlyLocals === true) { | ||
let code = JSON.stringify(result.css); | ||
let beforeCode = `var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(${options.sourceMap ? "___CSS_LOADER_API_SOURCEMAP_IMPORT___" : "function(i){return i[1]}"});\n`; | ||
let beforeCode = `var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(${options.sourceMap ? "___CSS_LOADER_API_SOURCEMAP_IMPORT___" : "___CSS_LOADER_API_NO_SOURCEMAP_IMPORT___"});\n`; | ||
@@ -838,6 +924,16 @@ for (const item of api) { | ||
url, | ||
layer, | ||
supports, | ||
media, | ||
dedupe | ||
} = item; | ||
beforeCode += url ? `___CSS_LOADER_EXPORT___.push([module.id, ${JSON.stringify(`@import url(${url});`)}${media ? `, ${JSON.stringify(media)}` : ""}]);\n` : `___CSS_LOADER_EXPORT___.i(${item.importName}${media ? `, ${JSON.stringify(media)}` : dedupe ? ', ""' : ""}${dedupe ? ", true" : ""});\n`; | ||
if (url) { | ||
// eslint-disable-next-line no-undefined | ||
const printedParam = printParams(media, undefined, supports, layer); | ||
beforeCode += `___CSS_LOADER_EXPORT___.push([module.id, ${JSON.stringify(`@import url(${url});`)}${printedParam.length > 0 ? `, ${printedParam}` : ""}]);\n`; | ||
} else { | ||
const printedParam = printParams(media, dedupe, supports, layer); | ||
beforeCode += `___CSS_LOADER_EXPORT___.i(${item.importName}${printedParam.length > 0 ? `, ${printedParam}` : ""});\n`; | ||
} | ||
} | ||
@@ -864,4 +960,11 @@ | ||
} | ||
} | ||
} // Indexes description: | ||
// 0 - module id | ||
// 1 - CSS code | ||
// 2 - media | ||
// 3 - source map | ||
// 4 - supports | ||
// 5 - layer | ||
return `${beforeCode}// Module\n___CSS_LOADER_EXPORT___.push([module.id, ${code}, ""${sourceMapValue}]);\n`; | ||
@@ -874,103 +977,88 @@ } | ||
function getExportCode(exports, replacements, needToUseIcssPlugin, options) { | ||
function getExportCode(exports, replacements, icssPluginUsed, options) { | ||
let code = "// Exports\n"; | ||
if (!needToUseIcssPlugin) { | ||
code += `${options.esModule ? "export default" : "module.exports ="} ___CSS_LOADER_EXPORT___;\n`; | ||
return code; | ||
} | ||
if (icssPluginUsed) { | ||
let localsCode = ""; | ||
let localsCode = ""; | ||
const addExportToLocalsCode = (names, value) => { | ||
const normalizedNames = Array.isArray(names) ? new Set(names) : new Set([names]); | ||
const addExportToLocalsCode = (names, value) => { | ||
const normalizedNames = Array.isArray(names) ? new Set(names) : new Set([names]); | ||
for (const name of normalizedNames) { | ||
if (options.modules.namedExport) { | ||
localsCode += `export var ${name} = ${JSON.stringify(value)};\n`; | ||
} else { | ||
if (localsCode) { | ||
localsCode += `,\n`; | ||
} | ||
for (const name of normalizedNames) { | ||
if (options.modules.namedExport) { | ||
localsCode += `export var ${name} = ${JSON.stringify(value)};\n`; | ||
} else { | ||
if (localsCode) { | ||
localsCode += `,\n`; | ||
localsCode += `\t${JSON.stringify(name)}: ${JSON.stringify(value)}`; | ||
} | ||
} | ||
}; | ||
localsCode += `\t${JSON.stringify(name)}: ${JSON.stringify(value)}`; | ||
} | ||
for (const { | ||
name, | ||
value | ||
} of exports) { | ||
addExportToLocalsCode(options.modules.exportLocalsConvention(name), value); | ||
} | ||
}; | ||
for (const { | ||
name, | ||
value | ||
} of exports) { | ||
if (typeof options.modules.exportLocalsConvention === "function") { | ||
addExportToLocalsCode(options.modules.exportLocalsConvention(name), value); // eslint-disable-next-line no-continue | ||
for (const item of replacements) { | ||
const { | ||
replacementName, | ||
localName | ||
} = item; | ||
continue; | ||
if (localName) { | ||
const { | ||
importName | ||
} = item; | ||
localsCode = localsCode.replace(new RegExp(replacementName, "g"), () => { | ||
if (options.modules.namedExport) { | ||
return `" + ${importName}_NAMED___[${JSON.stringify(getValidLocalName(localName, options.modules.exportLocalsConvention))}] + "`; | ||
} else if (options.modules.exportOnlyLocals) { | ||
return `" + ${importName}[${JSON.stringify(localName)}] + "`; | ||
} | ||
return `" + ${importName}.locals[${JSON.stringify(localName)}] + "`; | ||
}); | ||
} else { | ||
localsCode = localsCode.replace(new RegExp(replacementName, "g"), () => `" + ${replacementName} + "`); | ||
} | ||
} | ||
switch (options.modules.exportLocalsConvention) { | ||
case "camelCase": | ||
{ | ||
const modifiedName = camelCase(name); | ||
addExportToLocalsCode([name, modifiedName], value); | ||
break; | ||
} | ||
if (options.modules.exportOnlyLocals) { | ||
code += options.modules.namedExport ? localsCode : `${options.esModule ? "export default" : "module.exports ="} {\n${localsCode}\n};\n`; | ||
return code; | ||
} | ||
case "camelCaseOnly": | ||
{ | ||
addExportToLocalsCode(camelCase(name), value); | ||
break; | ||
} | ||
code += options.modules.namedExport ? localsCode : `___CSS_LOADER_EXPORT___.locals = {${localsCode ? `\n${localsCode}\n` : ""}};\n`; | ||
} | ||
case "dashes": | ||
{ | ||
const modifiedName = dashesCamelCase(name); | ||
addExportToLocalsCode([name, modifiedName], value); | ||
break; | ||
} | ||
const isCSSStyleSheetExport = options.exportType === "css-style-sheet"; | ||
case "dashesOnly": | ||
{ | ||
addExportToLocalsCode(dashesCamelCase(name), value); | ||
break; | ||
} | ||
case "asIs": | ||
default: | ||
addExportToLocalsCode(name, value); | ||
break; | ||
} | ||
if (isCSSStyleSheetExport) { | ||
code += "var ___CSS_LOADER_STYLE_SHEET___ = new CSSStyleSheet();\n"; | ||
code += "___CSS_LOADER_STYLE_SHEET___.replaceSync(___CSS_LOADER_EXPORT___.toString());\n"; | ||
} | ||
for (const item of replacements) { | ||
const { | ||
replacementName, | ||
localName | ||
} = item; | ||
let finalExport; | ||
if (localName) { | ||
const { | ||
importName | ||
} = item; | ||
localsCode = localsCode.replace(new RegExp(replacementName, "g"), () => { | ||
if (options.modules.namedExport) { | ||
return `" + ${importName}_NAMED___[${JSON.stringify(getValidLocalName(localName, options.modules.exportLocalsConvention))}] + "`; | ||
} else if (options.modules.exportOnlyLocals) { | ||
return `" + ${importName}[${JSON.stringify(localName)}] + "`; | ||
} | ||
switch (options.exportType) { | ||
case "string": | ||
finalExport = "___CSS_LOADER_EXPORT___.toString()"; | ||
break; | ||
return `" + ${importName}.locals[${JSON.stringify(localName)}] + "`; | ||
}); | ||
} else { | ||
localsCode = localsCode.replace(new RegExp(replacementName, "g"), () => `" + ${replacementName} + "`); | ||
} | ||
} | ||
case "css-style-sheet": | ||
finalExport = "___CSS_LOADER_STYLE_SHEET___"; | ||
break; | ||
if (options.modules.exportOnlyLocals) { | ||
code += options.modules.namedExport ? localsCode : `${options.esModule ? "export default" : "module.exports ="} {\n${localsCode}\n};\n`; | ||
return code; | ||
default: | ||
case "array": | ||
finalExport = "___CSS_LOADER_EXPORT___"; | ||
break; | ||
} | ||
code += options.modules.namedExport ? localsCode : `___CSS_LOADER_EXPORT___.locals = {${localsCode ? `\n${localsCode}\n` : ""}};\n`; | ||
code += `${options.esModule ? "export default" : "module.exports ="} ___CSS_LOADER_EXPORT___;\n`; | ||
code += `${options.esModule ? "export default" : "module.exports ="} ${finalExport};\n`; | ||
return code; | ||
@@ -977,0 +1065,0 @@ } |
{ | ||
"name": "css-loader", | ||
"version": "6.2.0", | ||
"version": "6.3.0", | ||
"description": "css loader module for webpack", | ||
@@ -58,4 +58,4 @@ "license": "MIT", | ||
"@babel/preset-env": "^7.14.7", | ||
"@commitlint/cli": "^12.1.4", | ||
"@commitlint/config-conventional": "^12.1.4", | ||
"@commitlint/cli": "^13.1.0", | ||
"@commitlint/config-conventional": "^13.1.0", | ||
"@webpack-contrib/eslint-config-webpack": "^3.0.0", | ||
@@ -66,3 +66,3 @@ "babel-jest": "^27.0.6", | ||
"del-cli": "^4.0.1", | ||
"es-check": "^5.2.4", | ||
"es-check": "^6.0.0", | ||
"eslint": "^7.30.0", | ||
@@ -88,3 +88,3 @@ "eslint-config-prettier": "^8.3.0", | ||
"style-loader": "^3.1.0", | ||
"stylus": "^0.54.8", | ||
"stylus": "^0.55.0", | ||
"stylus-loader": "^6.1.0", | ||
@@ -91,0 +91,0 @@ "url-loader": "^4.1.1", |
290
README.md
@@ -57,65 +57,15 @@ <div align="center"> | ||
### `toString` | ||
If, for one reason or another, you need to extract CSS as a file (i.e. do not store CSS in a JS module) you might want to check out the [recommend example](https://github.com/webpack-contrib/css-loader#recommend). | ||
You can also use the css-loader results directly as a string, such as in Angular's component style. | ||
**webpack.config.js** | ||
```js | ||
module.exports = { | ||
module: { | ||
rules: [ | ||
{ | ||
test: /\.css$/i, | ||
use: ["to-string-loader", "css-loader"], | ||
}, | ||
], | ||
}, | ||
}; | ||
``` | ||
or | ||
```js | ||
const css = require("./test.css").toString(); | ||
console.log(css); // {String} | ||
``` | ||
If there are SourceMaps, they will also be included in the result string. | ||
If, for one reason or another, you need to extract CSS as a | ||
plain string resource (i.e. not wrapped in a JS module) you | ||
might want to check out the [extract-loader](https://github.com/peerigon/extract-loader). | ||
It's useful when you, for instance, need to post process the CSS as a string. | ||
**webpack.config.js** | ||
```js | ||
module.exports = { | ||
module: { | ||
rules: [ | ||
{ | ||
test: /\.css$/i, | ||
use: [ | ||
"handlebars-loader", // handlebars loader expects raw resource string | ||
"extract-loader", | ||
"css-loader", | ||
], | ||
}, | ||
], | ||
}, | ||
}; | ||
``` | ||
## Options | ||
| Name | Type | Default | Description | | ||
| :-----------------------------------: | :-------------------------: | :----------------: | :----------------------------------------------------------------------------------------------------------------------- | | ||
| **[`url`](#url)** | `{Boolean\|Object}` | `true` | Allows to enables/disables `url()`/`image-set()` functions handling | | ||
| **[`import`](#import)** | `{Boolean\|Object}` | `true` | Allows to enables/disables `@import` at-rules handling | | ||
| **[`modules`](#modules)** | `{Boolean\|String\|Object}` | `{auto: true}` | Allows to enables/disables or setup CSS Modules options | | ||
| **[`sourceMap`](#sourcemap)** | `{Boolean}` | `compiler.devtool` | Enables/Disables generation of source maps | | ||
| **[`importLoaders`](#importloaders)** | `{Number}` | `0` | Allows enables/disables or setups number of loaders applied before CSS loader for `@import`/CSS Modules and ICSS imports | | ||
| **[`esModule`](#esmodule)** | `{Boolean}` | `true` | Use ES modules syntax | | ||
| Name | Type | Default | Description | | ||
| :-----------------------------------: | :------------------------------------------: | :----------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| **[`url`](#url)** | `{Boolean\|Object}` | `true` | Allows to enables/disables `url()`/`image-set()` functions handling | | ||
| **[`import`](#import)** | `{Boolean\|Object}` | `true` | Allows to enables/disables `@import` at-rules handling | | ||
| **[`modules`](#modules)** | `{Boolean\|String\|Object}` | `{auto: true}` | Allows to enables/disables or setup CSS Modules options | | ||
| **[`sourceMap`](#sourcemap)** | `{Boolean}` | `compiler.devtool` | Enables/Disables generation of source maps | | ||
| **[`importLoaders`](#importloaders)** | `{Number}` | `0` | Allows enables/disables or setups number of loaders applied before CSS loader for `@import`/CSS Modules and ICSS imports | | ||
| **[`esModule`](#esmodule)** | `{Boolean}` | `true` | Use ES modules syntax | | ||
| **[`exportType`](#exporttype)** | `{'array' \| 'string' \| 'css-style-sheet'}` | `array` | Allows exporting styles as array with modules, string or [constructable stylesheet](https://developers.google.com/web/updates/2019/02/constructable-stylesheets) (i.e. [`CSSStyleSheet`](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet)) | | ||
@@ -749,9 +699,10 @@ ### `url` | ||
- [name] the basename of the resource | ||
- [path] the path of the resource relative to the `compiler.context` option or `modules.localIdentContext` option. | ||
- [file] - filename and path. | ||
- [ext] - extension with leading . | ||
- [hash] - the hash of the string, generated based on `localIdentHashSalt`, `localIdentHashFunction`, `localIdentHashDigest`, `localIdentHashDigestLength`, `localIdentContext`, `resourcePath` and `exportName` | ||
- [<hashFunction>:hash:<hashDigest>:<hashDigestLength>] - hash with hash settings. | ||
- [local] - original class. | ||
- `[name]` the basename of the resource | ||
- `[folder]` the folder the resource relative to the `compiler.context` option or `modules.localIdentContext` option. | ||
- `[path]` the path of the resource relative to the `compiler.context` option or `modules.localIdentContext` option. | ||
- `[file]` - filename and path. | ||
- `[ext]` - extension with leading `.`. | ||
- `[hash]` - the hash of the string, generated based on `localIdentHashSalt`, `localIdentHashFunction`, `localIdentHashDigest`, `localIdentHashDigestLength`, `localIdentContext`, `resourcePath` and `exportName` | ||
- `[<hashFunction>:hash:<hashDigest>:<hashDigestLength>]` - hash with hash settings. | ||
- `[local]` - original class. | ||
@@ -1295,2 +1246,199 @@ Recommendations: | ||
### `exportType` | ||
Type: `'array' | 'string' | 'css-style-sheet'` | ||
Default: `'array'` | ||
Allows exporting styles as array with modules, string or [constructable stylesheet](https://developers.google.com/web/updates/2019/02/constructable-stylesheets) (i.e. [`CSSStyleSheet`](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet)). | ||
Default value is `'array'`, i.e. loader exports array of modules with specific API which is used in `style-loader` or other. | ||
**webpack.config.js** | ||
```js | ||
module.exports = { | ||
module: { | ||
rules: [ | ||
{ | ||
assert: { type: "css" }, | ||
loader: "css-loader", | ||
options: { | ||
exportType: "css-style-sheet", | ||
}, | ||
}, | ||
], | ||
}, | ||
}; | ||
``` | ||
**src/index.js** | ||
```js | ||
import sheet from "./styles.css" assert { type: "css" }; | ||
document.adoptedStyleSheets = [sheet]; | ||
shadowRoot.adoptedStyleSheets = [sheet]; | ||
``` | ||
#### `'array'` | ||
The default export is array of modules with specific API which is used in `style-loader` or other. | ||
**webpack.config.js** | ||
```js | ||
module.exports = { | ||
module: { | ||
rules: [ | ||
{ | ||
test: /\.(sa|sc|c)ss$/i, | ||
use: ["style-loader", "css-loader", "postcss-loader", "sass-loader"], | ||
}, | ||
], | ||
}, | ||
}; | ||
``` | ||
**src/index.js** | ||
```js | ||
// `style-loader` applies styles to DOM | ||
import "./styles.css"; | ||
``` | ||
#### `'string'` | ||
> ⚠ You don't need [`style-loader`](https://github.com/webpack-contrib/style-loader) anymore, please remove it. | ||
> ⚠ The `esModules` option should be enabled if you want to use it with [`CSS modules`](https://github.com/webpack-contrib/css-loader#modules), by default for locals will be used [named export](https://github.com/webpack-contrib/css-loader#namedexport). | ||
The default export is `string`. | ||
**webpack.config.js** | ||
```js | ||
module.exports = { | ||
module: { | ||
rules: [ | ||
{ | ||
test: /\.(sa|sc|c)ss$/i, | ||
use: ["css-loader", "postcss-loader", "sass-loader"], | ||
}, | ||
], | ||
}, | ||
}; | ||
``` | ||
**src/index.js** | ||
```js | ||
import sheet from "./styles.css"; | ||
console.log(sheet); | ||
``` | ||
#### `'css-style-sheet'` | ||
> ⚠ `@import` rules not yet allowed, more [information](https://web.dev/css-module-scripts/#@import-rules-not-yet-allowed) | ||
> ⚠ You don't need [`style-loader`](https://github.com/webpack-contrib/style-loader) anymore, please remove it. | ||
> ⚠ The `esModules` option should be enabled if you want to use it with [`CSS modules`](https://github.com/webpack-contrib/css-loader#modules), by default for locals will be used [named export](https://github.com/webpack-contrib/css-loader#namedexport). | ||
> ⚠ Source maps are not currently supported in `Chrome` due [bug](https://bugs.chromium.org/p/chromium/issues/detail?id=1174094&q=CSSStyleSheet%20source%20maps&can=2) | ||
The default export is a [constructable stylesheet](https://developers.google.com/web/updates/2019/02/constructable-stylesheets) (i.e. [`CSSStyleSheet`](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet)). | ||
Useful for [custom elements](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements) and shadow DOM. | ||
More information: | ||
- [Using CSS Module Scripts to import stylesheets](https://web.dev/css-module-scripts/) | ||
- [Constructable Stylesheets: seamless reusable styles](https://developers.google.com/web/updates/2019/02/constructable-stylesheets) | ||
**webpack.config.js** | ||
```js | ||
module.exports = { | ||
module: { | ||
rules: [ | ||
{ | ||
assert: { type: "css" }, | ||
loader: "css-loader", | ||
options: { | ||
exportType: "css-style-sheet", | ||
}, | ||
}, | ||
// For Sass/SCSS: | ||
// | ||
// { | ||
// assert: { type: "css" }, | ||
// rules: [ | ||
// { | ||
// loader: "css-loader", | ||
// options: { | ||
// exportType: "css-style-sheet", | ||
// // Other options | ||
// }, | ||
// }, | ||
// { | ||
// loader: "sass-loader", | ||
// options: { | ||
// // Other options | ||
// }, | ||
// }, | ||
// ], | ||
// }, | ||
], | ||
}, | ||
}; | ||
``` | ||
**src/index.js** | ||
```js | ||
// Example for Sass/SCSS: | ||
// import sheet from "./styles.scss" assert { type: "css" }; | ||
// Example for CSS modules: | ||
// import sheet, { myClass } from "./styles.scss" assert { type: "css" }; | ||
// Example for CSS: | ||
import sheet from "./styles.css" assert { type: "css" }; | ||
document.adoptedStyleSheets = [sheet]; | ||
shadowRoot.adoptedStyleSheets = [sheet]; | ||
``` | ||
For migration purposes, you can use the following configuration: | ||
```js | ||
module.exports = { | ||
module: { | ||
rules: [ | ||
{ | ||
test: /\.css$/i, | ||
oneOf: [ | ||
{ | ||
assert: { type: "css" }, | ||
loader: "css-loader", | ||
options: { | ||
exportType: "css-style-sheet", | ||
// Other options | ||
}, | ||
}, | ||
{ | ||
use: [ | ||
"style-loader", | ||
{ | ||
loader: "css-loader", | ||
options: { | ||
// Other options | ||
}, | ||
}, | ||
], | ||
}, | ||
], | ||
}, | ||
], | ||
}, | ||
}; | ||
``` | ||
## Examples | ||
@@ -1316,3 +1464,3 @@ | ||
{ | ||
test: /\.(sa|sc|c)ss$/, | ||
test: /\.(sa|sc|c)ss$/i, | ||
use: [ | ||
@@ -1540,4 +1688,4 @@ devMode ? "style-loader" : MiniCssExtractPlugin.loader, | ||
{ | ||
test: /\.scss$/, | ||
exclude: /\.module\.scss$/, | ||
test: /\.scss$/i, | ||
exclude: /\.module\.scss$/i, | ||
use: [ | ||
@@ -1564,3 +1712,3 @@ { | ||
{ | ||
test: /\.module\.scss$/, | ||
test: /\.module\.scss$/i, | ||
use: [ | ||
@@ -1567,0 +1715,0 @@ { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
125863
17
2091
1797