mirror of https://github.com/webpack/webpack.git
add support for :export {} block
This commit is contained in:
parent
b9c6691ff5
commit
453e5cac05
|
|
@ -32,6 +32,13 @@
|
|||
* @property {CodeGenerationResults} codeGenerationResults the code generation results
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} CssDependencyTemplateContextExtras
|
||||
* @property {Map<string, string>} cssExports the css exports
|
||||
*/
|
||||
|
||||
/** @typedef {DependencyTemplateContext & CssDependencyTemplateContextExtras} CssDependencyTemplateContext */
|
||||
|
||||
class DependencyTemplate {
|
||||
/* istanbul ignore next */
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -599,9 +599,27 @@ const applyModuleDefaults = (
|
|||
preferRelative: true
|
||||
}
|
||||
};
|
||||
const cssModulesRule = {
|
||||
type: "css/module",
|
||||
resolve: {
|
||||
fullySpecified: true
|
||||
}
|
||||
};
|
||||
rules.push({
|
||||
test: /\.css$/i,
|
||||
...cssRule
|
||||
oneOf: [
|
||||
{
|
||||
test: /\.module\.css$/i,
|
||||
...cssModulesRule
|
||||
},
|
||||
{
|
||||
...cssRule
|
||||
}
|
||||
]
|
||||
});
|
||||
rules.push({
|
||||
mimetype: "text/css+module",
|
||||
...cssModulesRule
|
||||
});
|
||||
rules.push({
|
||||
mimetype: "text/css",
|
||||
|
|
|
|||
|
|
@ -32,8 +32,23 @@ class CssGenerator extends Generator {
|
|||
const originalSource = module.originalSource();
|
||||
const source = new ReplaceSource(originalSource);
|
||||
const initFragments = [];
|
||||
const cssExports = new Map();
|
||||
|
||||
for (const dependency of module.dependencies) {
|
||||
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
|
||||
};
|
||||
|
||||
const handleDependency = dependency => {
|
||||
const constructor = /** @type {new (...args: any[]) => Dependency} */ (
|
||||
dependency.constructor
|
||||
);
|
||||
|
|
@ -44,21 +59,17 @@ class CssGenerator extends Generator {
|
|||
);
|
||||
}
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -120,6 +120,8 @@ class CssLoadingRuntimeModule extends RuntimeModule {
|
|||
: ""
|
||||
]);
|
||||
|
||||
const cc = str => str.charCodeAt(0);
|
||||
|
||||
return Template.asString([
|
||||
"// object to store loaded and loading chunks",
|
||||
"// undefined = chunk not loaded, null = chunk preloaded/prefetched",
|
||||
|
|
@ -132,27 +134,29 @@ class CssLoadingRuntimeModule extends RuntimeModule {
|
|||
).join(",")}};`,
|
||||
"",
|
||||
`var loadCssChunkData = ${runtimeTemplate.basicFunction("chunkId, link", [
|
||||
'var data, tokens = [], token = "", i = 0;',
|
||||
'var data, token = "", token2, exports = {}, i = 0, cc = 1;',
|
||||
"try { if(!link) link = loadStylesheet(chunkId); data = link.sheet.cssRules; data = data[data.length - 1].style; } catch(e) { data = getComputedStyle(document.head); }",
|
||||
'data = data.getPropertyValue("--webpack-" + chunkId);',
|
||||
"if(!data) return;",
|
||||
"for(; i < data.length; i++) {",
|
||||
"for(; cc; i++) {",
|
||||
Template.indent([
|
||||
"var cc = data.charCodeAt(i);",
|
||||
'if(cc == 44) { tokens.push(token); token = ""; }',
|
||||
"else if(cc == 92) { token += data[++i] }",
|
||||
"else { token += data[i]; }"
|
||||
"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(",")}) { ${
|
||||
RuntimeGlobals.makeNamespaceObject
|
||||
}(exports); ${
|
||||
RuntimeGlobals.moduleFactories
|
||||
}[token.replace(/^_/, "")] = (${runtimeTemplate.basicFunction(
|
||||
"exports, module",
|
||||
`module.exports = exports;`
|
||||
)}).bind(null, exports); token = ""; exports = {}; }`,
|
||||
`else if(cc == ${cc("\\")}) { token += data[++i] }`,
|
||||
`else { token += data[i]; }`
|
||||
]),
|
||||
"}",
|
||||
"token && tokens.push(token);",
|
||||
`tokens.forEach(${runtimeTemplate.basicFunction("token", [
|
||||
`${
|
||||
RuntimeGlobals.moduleFactories
|
||||
}[token.replace(/^_/, "")] = ${runtimeTemplate.basicFunction(
|
||||
"module, exports",
|
||||
[`${RuntimeGlobals.makeNamespaceObject}(exports);`]
|
||||
)};`
|
||||
])});`,
|
||||
"installedChunks[chunkId] = 0;"
|
||||
])}`,
|
||||
'var loadingAttribute = "data-webpack-loading";',
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
const { ConcatSource } = require("webpack-sources");
|
||||
const HotUpdateChunk = require("../HotUpdateChunk");
|
||||
const RuntimeGlobals = require("../RuntimeGlobals");
|
||||
const CssExportDependency = require("../dependencies/CssExportDependency");
|
||||
const CssImportDependency = require("../dependencies/CssImportDependency");
|
||||
const CssUrlDependency = require("../dependencies/CssUrlDependency");
|
||||
const StaticExportsDependency = require("../dependencies/StaticExportsDependency");
|
||||
|
|
@ -85,6 +86,10 @@ class CssModulesPlugin {
|
|||
CssUrlDependency,
|
||||
new CssUrlDependency.Template()
|
||||
);
|
||||
compilation.dependencyTemplates.set(
|
||||
CssExportDependency,
|
||||
new CssExportDependency.Template()
|
||||
);
|
||||
compilation.dependencyFactories.set(
|
||||
CssImportDependency,
|
||||
normalModuleFactory
|
||||
|
|
@ -103,12 +108,36 @@ class CssModulesPlugin {
|
|||
validateParserOptions(parserOptions);
|
||||
return new CssParser();
|
||||
});
|
||||
normalModuleFactory.hooks.createParser
|
||||
.for("css/global")
|
||||
.tap(plugin, parserOptions => {
|
||||
validateParserOptions(parserOptions);
|
||||
return new CssParser({ allowPseudoBlocks: false });
|
||||
});
|
||||
normalModuleFactory.hooks.createParser
|
||||
.for("css/module")
|
||||
.tap(plugin, parserOptions => {
|
||||
validateParserOptions(parserOptions);
|
||||
return new CssParser({ allowPseudoBlocks: true });
|
||||
});
|
||||
normalModuleFactory.hooks.createGenerator
|
||||
.for("css")
|
||||
.tap(plugin, generatorOptions => {
|
||||
validateGeneratorOptions(generatorOptions);
|
||||
return new CssGenerator();
|
||||
});
|
||||
normalModuleFactory.hooks.createGenerator
|
||||
.for("css/global")
|
||||
.tap(plugin, generatorOptions => {
|
||||
validateGeneratorOptions(generatorOptions);
|
||||
return new CssGenerator();
|
||||
});
|
||||
normalModuleFactory.hooks.createGenerator
|
||||
.for("css/module")
|
||||
.tap(plugin, generatorOptions => {
|
||||
validateGeneratorOptions(generatorOptions);
|
||||
return new CssGenerator();
|
||||
});
|
||||
compilation.hooks.contentHash.tap("JavascriptModulesPlugin", chunk => {
|
||||
const {
|
||||
chunkGraph,
|
||||
|
|
@ -204,25 +233,43 @@ class CssModulesPlugin {
|
|||
renderChunk({ chunk, chunkGraph, codeGenerationResults }) {
|
||||
const modules = this.getOrderedChunkCssModules(chunk, chunkGraph);
|
||||
const source = new ConcatSource();
|
||||
const metaData = [];
|
||||
for (const module of modules) {
|
||||
try {
|
||||
const codeGenResult = codeGenerationResults.get(module, chunk.runtime);
|
||||
|
||||
const s =
|
||||
codeGenerationResults.getSource(module, chunk.runtime, "css") ||
|
||||
codeGenerationResults.getSource(module, chunk.runtime, "css-import");
|
||||
codeGenResult.sources.get("css") ||
|
||||
codeGenResult.sources.get("css-import");
|
||||
if (s) {
|
||||
source.add(s);
|
||||
source.add("\n");
|
||||
}
|
||||
const exports =
|
||||
codeGenResult.data && codeGenResult.data.get("css-exports");
|
||||
metaData.push(
|
||||
`${
|
||||
exports
|
||||
? Array.from(
|
||||
exports,
|
||||
([n, v]) =>
|
||||
`${escapeCssIdentifierPart(
|
||||
n,
|
||||
true
|
||||
)}(${escapeCssIdentifierPart(v, true)})`
|
||||
).join("")
|
||||
: ""
|
||||
}${escapeCssIdentifierPart(chunkGraph.getModuleId(module), true)}`
|
||||
);
|
||||
} catch (e) {
|
||||
e.message += `\nduring rendering of css ${module.identifier()}`;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
source.add(
|
||||
`head{--webpack-${escapeCssIdentifierPart(chunk.id)}:${Array.from(
|
||||
modules,
|
||||
m => `${escapeCssIdentifierPart(chunkGraph.getModuleId(m), true)}`
|
||||
).join(",")};}`
|
||||
`head{--webpack-${escapeCssIdentifierPart(chunk.id)}:${metaData.join(
|
||||
","
|
||||
)};}`
|
||||
);
|
||||
return source;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
"use strict";
|
||||
|
||||
const Parser = require("../Parser");
|
||||
const ConstDependency = require("../dependencies/ConstDependency");
|
||||
const CssExportDependency = require("../dependencies/CssExportDependency");
|
||||
const CssImportDependency = require("../dependencies/CssImportDependency");
|
||||
const CssUrlDependency = require("../dependencies/CssUrlDependency");
|
||||
const StaticExportsDependency = require("../dependencies/StaticExportsDependency");
|
||||
|
|
@ -14,6 +16,12 @@ const walkCssTokens = require("./walkCssTokens");
|
|||
/** @typedef {import("../Parser").ParserState} ParserState */
|
||||
/** @typedef {import("../Parser").PreparsedAst} PreparsedAst */
|
||||
|
||||
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);
|
||||
|
||||
const cssUnescape = str => {
|
||||
return str.replace(/\\([0-9a-fA-F]{1,6}[ \t\n\r\f]?|[\s\S])/g, match => {
|
||||
if (match.length > 2) {
|
||||
|
|
@ -87,8 +95,9 @@ const explainMode = mode => {
|
|||
};
|
||||
|
||||
class CssParser extends Parser {
|
||||
constructor() {
|
||||
constructor({ allowPseudoBlocks = true } = {}) {
|
||||
super();
|
||||
this.allowPseudoBlocks = allowPseudoBlocks;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -111,7 +120,9 @@ class CssParser extends Parser {
|
|||
const locConverter = new LocConverter(source);
|
||||
let mode = CSS_MODE_TOP_LEVEL;
|
||||
let modePos = 0;
|
||||
let modeNestingLevel = 0;
|
||||
let modeData = undefined;
|
||||
const modeStack = [];
|
||||
const eatWhiteLine = (input, pos) => {
|
||||
for (;;) {
|
||||
const cc = input.charCodeAt(pos);
|
||||
|
|
@ -124,6 +135,104 @@ class CssParser extends Parser {
|
|||
}
|
||||
return pos;
|
||||
};
|
||||
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;
|
||||
}
|
||||
};
|
||||
};
|
||||
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.trimRight()];
|
||||
};
|
||||
const eatExportName = eatUntil(":};/");
|
||||
const eatExportValue = eatUntil("};/");
|
||||
const parseExports = (input, pos) => {
|
||||
pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
|
||||
const cc = input.charCodeAt(pos);
|
||||
if (cc !== CC_LEFT_CURLY)
|
||||
throw new Error(
|
||||
`Unexpected ${input[pos]} at ${pos} during parsing of ':export' (expected '{')`
|
||||
);
|
||||
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) {
|
||||
throw new Error(
|
||||
`Unexpected ${input[pos]} at ${pos} during parsing of export name in ':export' (expected ':')`
|
||||
);
|
||||
}
|
||||
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) {
|
||||
throw new Error(
|
||||
`Unexpected ${input[pos]} at ${pos} during parsing of export value in ':export' (expected ';' or '}')`
|
||||
);
|
||||
}
|
||||
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 = eatWhiteLine(input, pos);
|
||||
return pos;
|
||||
};
|
||||
walkCssTokens(source, {
|
||||
url: (input, start, end, contentStart, contentEnd) => {
|
||||
const value = cssUnescape(input.slice(contentStart, contentEnd));
|
||||
|
|
@ -208,6 +317,64 @@ class CssParser extends Parser {
|
|||
mode = CSS_MODE_TOP_LEVEL;
|
||||
modeData = undefined;
|
||||
return end;
|
||||
},
|
||||
leftCurlyBracket: (input, start, end) => {
|
||||
switch (mode) {
|
||||
case CSS_MODE_TOP_LEVEL:
|
||||
mode = CSS_MODE_IN_RULE;
|
||||
modeNestingLevel = 1;
|
||||
break;
|
||||
case CSS_MODE_IN_RULE:
|
||||
modeNestingLevel++;
|
||||
break;
|
||||
}
|
||||
return end;
|
||||
},
|
||||
rightCurlyBracket: (input, start, end) => {
|
||||
switch (mode) {
|
||||
case CSS_MODE_IN_RULE:
|
||||
if (--modeNestingLevel === 0) {
|
||||
mode = CSS_MODE_TOP_LEVEL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return end;
|
||||
},
|
||||
leftParenthesis: (input, start, end) => {
|
||||
return end;
|
||||
},
|
||||
rightParenthesis: (input, start, end) => {
|
||||
return end;
|
||||
},
|
||||
pseudoClass: (input, start, end) => {
|
||||
switch (mode) {
|
||||
case CSS_MODE_TOP_LEVEL: {
|
||||
if (this.allowPseudoBlocks) {
|
||||
const name = input.slice(start, end);
|
||||
if (name === ":global") {
|
||||
modeData = ":global";
|
||||
} else if (name === ":local") {
|
||||
modeData = ":local";
|
||||
} else if (name === ":export") {
|
||||
const pos = parseExports(input, end);
|
||||
const dep = new ConstDependency("", [start, pos]);
|
||||
module.addPresentationalDependency(dep);
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return end;
|
||||
},
|
||||
comma: (input, start, end) => {
|
||||
switch (mode) {
|
||||
case CSS_MODE_TOP_LEVEL:
|
||||
modeData = undefined;
|
||||
modeStack.length = 0;
|
||||
break;
|
||||
}
|
||||
return end;
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -108,8 +108,8 @@ const consumePotentialComment = (input, pos, callbacks) => {
|
|||
if (pos === input.length) return pos;
|
||||
let cc = input.charCodeAt(pos);
|
||||
if (cc !== CC_ASTERISK) return pos;
|
||||
pos++;
|
||||
for (;;) {
|
||||
pos++;
|
||||
if (pos === input.length) return pos;
|
||||
cc = input.charCodeAt(pos);
|
||||
while (cc === CC_ASTERISK) {
|
||||
|
|
@ -587,3 +587,60 @@ module.exports = (input, callbacks) => {
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.eatComments = (input, pos) => {
|
||||
loop: for (;;) {
|
||||
const cc = input.charCodeAt(pos);
|
||||
if (cc === CC_SLASH) {
|
||||
if (pos === input.length) return pos;
|
||||
let cc = input.charCodeAt(pos + 1);
|
||||
if (cc !== CC_ASTERISK) return pos;
|
||||
pos++;
|
||||
for (;;) {
|
||||
pos++;
|
||||
if (pos === input.length) return pos;
|
||||
cc = input.charCodeAt(pos);
|
||||
while (cc === CC_ASTERISK) {
|
||||
pos++;
|
||||
if (pos === input.length) return pos;
|
||||
cc = input.charCodeAt(pos);
|
||||
if (cc === CC_SLASH) {
|
||||
pos++;
|
||||
continue loop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.eatWhitespaceAndComments = (input, pos) => {
|
||||
loop: for (;;) {
|
||||
const cc = input.charCodeAt(pos);
|
||||
if (cc === CC_SLASH) {
|
||||
if (pos === input.length) return pos;
|
||||
let cc = input.charCodeAt(pos + 1);
|
||||
if (cc !== CC_ASTERISK) return pos;
|
||||
pos++;
|
||||
for (;;) {
|
||||
pos++;
|
||||
if (pos === input.length) return pos;
|
||||
cc = input.charCodeAt(pos);
|
||||
while (cc === CC_ASTERISK) {
|
||||
pos++;
|
||||
if (pos === input.length) return pos;
|
||||
cc = input.charCodeAt(pos);
|
||||
if (cc === CC_SLASH) {
|
||||
pos++;
|
||||
continue loop;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (_isWhiteSpace(cc)) {
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Ivan Kopeykin @vankop
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const makeSerializable = require("../util/makeSerializable");
|
||||
const NullDependency = require("./NullDependency");
|
||||
|
||||
/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
|
||||
/** @typedef {import("../Dependency")} Dependency */
|
||||
/** @typedef {import("../Dependency").ExportsSpec} ExportsSpec */
|
||||
/** @typedef {import("../DependencyTemplate").CssDependencyTemplateContext} DependencyTemplateContext */
|
||||
/** @typedef {import("../ModuleGraph")} ModuleGraph */
|
||||
|
||||
class CssExportDependency extends NullDependency {
|
||||
/**
|
||||
* @param {string} name name
|
||||
* @param {string} value value
|
||||
*/
|
||||
constructor(name, value) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
get type() {
|
||||
return "css :export";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the exported names
|
||||
* @param {ModuleGraph} moduleGraph module graph
|
||||
* @returns {ExportsSpec | undefined} export names
|
||||
*/
|
||||
getExports(moduleGraph) {
|
||||
const name = this.name;
|
||||
return {
|
||||
exports: [
|
||||
{
|
||||
name,
|
||||
canMangle: true
|
||||
}
|
||||
],
|
||||
dependencies: undefined
|
||||
};
|
||||
}
|
||||
|
||||
serialize(context) {
|
||||
const { write } = context;
|
||||
write(this.name);
|
||||
write(this.value);
|
||||
super.serialize(context);
|
||||
}
|
||||
|
||||
deserialize(context) {
|
||||
const { read } = context;
|
||||
this.name = read();
|
||||
this.value = read();
|
||||
super.deserialize(context);
|
||||
}
|
||||
}
|
||||
|
||||
CssExportDependency.Template = class CssExportDependencyTemplate extends (
|
||||
NullDependency.Template
|
||||
) {
|
||||
/**
|
||||
* @param {Dependency} dependency the dependency for which the template should be applied
|
||||
* @param {ReplaceSource} source the current replace source which can be modified
|
||||
* @param {DependencyTemplateContext} templateContext the context object
|
||||
* @returns {void}
|
||||
*/
|
||||
apply(dependency, source, { cssExports }) {
|
||||
const dep = /** @type {CssExportDependency} */ (dependency);
|
||||
cssExports.set(dep.name, dep.value);
|
||||
}
|
||||
};
|
||||
|
||||
makeSerializable(
|
||||
CssExportDependency,
|
||||
"webpack/lib/dependencies/CssExportDependency"
|
||||
);
|
||||
|
||||
module.exports = CssExportDependency;
|
||||
|
|
@ -69,6 +69,8 @@ module.exports = {
|
|||
require("../dependencies/CriticalDependencyWarning"),
|
||||
"dependencies/CssImportDependency": () =>
|
||||
require("../dependencies/CssImportDependency"),
|
||||
"dependencies/CssExportDependency": () =>
|
||||
require("../dependencies/CssExportDependency"),
|
||||
"dependencies/CssUrlDependency": () =>
|
||||
require("../dependencies/CssUrlDependency"),
|
||||
"dependencies/DelegatedSourceDependency": () =>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
import * as style from "./style.module.css?imported";
|
||||
|
||||
export default Object(style);
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
it("should allow to dynamic import a css module", done => {
|
||||
import("./style.module.css").then(x => {
|
||||
try {
|
||||
expect(x).toEqual(
|
||||
nsObj({
|
||||
a: "a",
|
||||
abc: "a b c",
|
||||
comments: "abc def",
|
||||
"white space": "abc\n\tdef",
|
||||
default: "default"
|
||||
})
|
||||
);
|
||||
} catch (e) {
|
||||
return done(e);
|
||||
}
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
it("should allow to reexport a css module", done => {
|
||||
__non_webpack_require__("./reexported_js.bundle0.js");
|
||||
import("./reexported").then(x => {
|
||||
try {
|
||||
expect(x).toEqual(
|
||||
nsObj({
|
||||
a: "a",
|
||||
abc: "a b c",
|
||||
comments: "abc def",
|
||||
"white space": "abc\n\tdef"
|
||||
})
|
||||
);
|
||||
} catch (e) {
|
||||
return done(e);
|
||||
}
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
it("should allow to import a css module", done => {
|
||||
__non_webpack_require__("./imported_js.bundle0.js");
|
||||
import("./imported").then(({ default: x }) => {
|
||||
try {
|
||||
expect(x).toEqual(
|
||||
nsObj({
|
||||
a: "a",
|
||||
abc: "a b c",
|
||||
comments: "abc def",
|
||||
"white space": "abc\n\tdef",
|
||||
default: "default"
|
||||
})
|
||||
);
|
||||
} catch (e) {
|
||||
return done(e);
|
||||
}
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
|
@ -0,0 +1 @@
|
|||
export * from "./style.module.css?reexported";
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
:export {
|
||||
a: a;
|
||||
}
|
||||
|
||||
:export {
|
||||
abc: a b c;
|
||||
comments: abc/****/ /* hello world *//****/ def
|
||||
}
|
||||
|
||||
:export
|
||||
|
||||
|
||||
{
|
||||
|
||||
|
||||
white space
|
||||
|
||||
:
|
||||
|
||||
abc
|
||||
def
|
||||
|
||||
}
|
||||
|
||||
:export{default:default}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
/** @type {import("../../../../").Configuration} */
|
||||
module.exports = {
|
||||
target: "web",
|
||||
mode: "development",
|
||||
experiments: {
|
||||
css: true
|
||||
}
|
||||
};
|
||||
Loading…
Reference in New Issue