Skip to content

Commit bce2c17

Browse files
authoredSep 17, 2021
feat: supported supports() and layer() and fix multiple @media merging in @import at-rule (#1377)
1 parent cf3a3a7 commit bce2c17

27 files changed

+1251
-1874
lines changed
 

‎.eslintrc.js

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ module.exports = {
1212
"no-param-reassign": "off",
1313
"no-continue": "off",
1414
"no-underscore-dangle": "off",
15+
"no-undefined": "off",
1516
},
1617
},
1718
],

‎src/index.js

+2-4
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export default async function loader(content, map, meta) {
7171
context: this.context,
7272
rootContext: this.rootContext,
7373
resourcePath: this.resourcePath,
74-
filter: getFilter(options.import.filter, this.resourcePath),
74+
filter: options.import.filter,
7575
resolver,
7676
urlHandler: (url) =>
7777
stringifyRequest(
@@ -205,13 +205,11 @@ export default async function loader(content, map, meta) {
205205

206206
if (options.sourceMap) {
207207
imports.unshift({
208-
type: "api_sourcemap_import",
209208
importName: "___CSS_LOADER_API_SOURCEMAP_IMPORT___",
210-
url: stringifyRequest(this, require.resolve("./runtime/noSourceMaps")),
209+
url: stringifyRequest(this, require.resolve("./runtime/sourceMaps")),
211210
});
212211
} else {
213212
imports.unshift({
214-
type: "api_sourcemap_import",
215213
importName: "___CSS_LOADER_API_NO_SOURCEMAP_IMPORT___",
216214
url: stringifyRequest(this, require.resolve("./runtime/noSourceMaps")),
217215
});

‎src/plugins/postcss-import-parser.js

+72-12
Original file line numberDiff line numberDiff line change
@@ -118,15 +118,54 @@ function parseNode(atRule, key) {
118118
throw error;
119119
}
120120

121-
const mediaNodes = paramsNodes.slice(1);
121+
const additionalNodes = paramsNodes.slice(1);
122+
123+
let supports;
124+
let layer;
122125
let media;
123126

124-
if (mediaNodes.length > 0) {
125-
media = valueParser.stringify(mediaNodes).trim().toLowerCase();
127+
if (additionalNodes.length > 0) {
128+
let nodes = [];
129+
130+
for (const node of additionalNodes) {
131+
nodes.push(node);
132+
133+
const isLayerFunction =
134+
node.type === "function" && node.value.toLowerCase() === "layer";
135+
const isLayerWord =
136+
node.type === "word" && node.value.toLowerCase() === "layer";
137+
138+
if (isLayerFunction || isLayerWord) {
139+
if (isLayerFunction) {
140+
nodes.splice(nodes.length - 1, 1, ...node.nodes);
141+
} else {
142+
nodes.splice(nodes.length - 1, 1, {
143+
type: "string",
144+
value: "",
145+
unclosed: false,
146+
});
147+
}
148+
149+
layer = valueParser.stringify(nodes).trim().toLowerCase();
150+
nodes = [];
151+
} else if (
152+
node.type === "function" &&
153+
node.value.toLowerCase() === "supports"
154+
) {
155+
nodes.splice(nodes.length - 1, 1, ...node.nodes);
156+
157+
supports = valueParser.stringify(nodes).trim().toLowerCase();
158+
nodes = [];
159+
}
160+
}
161+
162+
if (nodes.length > 0) {
163+
media = valueParser.stringify(nodes).trim().toLowerCase();
164+
}
126165
}
127166

128167
// eslint-disable-next-line consistent-return
129-
return { atRule, prefix, url, media, isRequestable };
168+
return { atRule, prefix, url, layer, supports, media, isRequestable };
130169
}
131170

132171
const plugin = (options = {}) => {
@@ -160,11 +199,24 @@ const plugin = (options = {}) => {
160199

161200
const resolvedAtRules = await Promise.all(
162201
parsedAtRules.map(async (parsedAtRule) => {
163-
const { atRule, isRequestable, prefix, url, media } =
164-
parsedAtRule;
202+
const {
203+
atRule,
204+
isRequestable,
205+
prefix,
206+
url,
207+
layer,
208+
supports,
209+
media,
210+
} = parsedAtRule;
165211

166212
if (options.filter) {
167-
const needKeep = await options.filter(url, media);
213+
const needKeep = await options.filter(
214+
url,
215+
media,
216+
options.resourcePath,
217+
supports,
218+
layer
219+
);
168220

169221
if (!needKeep) {
170222
return;
@@ -192,13 +244,20 @@ const plugin = (options = {}) => {
192244
atRule.remove();
193245

194246
// eslint-disable-next-line consistent-return
195-
return { url: resolvedUrl, media, prefix, isRequestable };
247+
return {
248+
url: resolvedUrl,
249+
layer,
250+
supports,
251+
media,
252+
prefix,
253+
isRequestable,
254+
};
196255
}
197256

198257
atRule.remove();
199258

200259
// eslint-disable-next-line consistent-return
201-
return { url, media, prefix, isRequestable };
260+
return { url, layer, supports, media, prefix, isRequestable };
202261
})
203262
);
204263

@@ -212,10 +271,11 @@ const plugin = (options = {}) => {
212271
continue;
213272
}
214273

215-
const { url, isRequestable, media } = resolvedAtRule;
274+
const { url, isRequestable, layer, supports, media } =
275+
resolvedAtRule;
216276

217277
if (!isRequestable) {
218-
options.api.push({ url, media, index });
278+
options.api.push({ url, layer, supports, media, index });
219279

220280
// eslint-disable-next-line no-continue
221281
continue;
@@ -237,7 +297,7 @@ const plugin = (options = {}) => {
237297
});
238298
}
239299

240-
options.api.push({ importName, media, index });
300+
options.api.push({ importName, layer, supports, media, index });
241301
}
242302
},
243303
};

‎src/runtime/api.js

+52-7
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,44 @@ module.exports = (cssWithMappingToString) => {
88
// return the list of modules as css string
99
list.toString = function toString() {
1010
return this.map((item) => {
11-
const content = cssWithMappingToString(item);
11+
let content = "";
12+
13+
const needLayer = typeof item[5] !== "undefined";
14+
15+
if (item[4]) {
16+
content += `@supports (${item[4]}) {`;
17+
}
18+
19+
if (item[2]) {
20+
content += `@media ${item[2]} {`;
21+
}
22+
23+
if (needLayer) {
24+
content += `@layer${item[5].length > 0 ? ` ${item[5]}` : ""} {`;
25+
}
26+
27+
content += cssWithMappingToString(item);
28+
29+
if (needLayer) {
30+
content += "}";
31+
}
1232

1333
if (item[2]) {
14-
return `@media ${item[2]} {${content}}`;
34+
content += "}";
35+
}
36+
37+
if (item[4]) {
38+
content += "}";
1539
}
1640

1741
return content;
1842
}).join("");
1943
};
2044

2145
// import a list of modules into the list
22-
list.i = function i(modules, mediaQuery, dedupe) {
46+
list.i = function i(modules, media, dedupe, supports, layer) {
2347
if (typeof modules === "string") {
24-
modules = [[null, modules, ""]];
48+
modules = [[null, modules, undefined]];
2549
}
2650

2751
const alreadyImportedModules = {};
@@ -43,11 +67,32 @@ module.exports = (cssWithMappingToString) => {
4367
continue;
4468
}
4569

46-
if (mediaQuery) {
70+
if (typeof layer !== "undefined") {
71+
if (typeof item[5] === "undefined") {
72+
item[5] = layer;
73+
} else {
74+
item[1] = `@layer${item[5].length > 0 ? ` ${item[5]}` : ""} {${
75+
item[1]
76+
}}`;
77+
item[5] = layer;
78+
}
79+
}
80+
81+
if (media) {
4782
if (!item[2]) {
48-
item[2] = mediaQuery;
83+
item[2] = media;
84+
} else {
85+
item[1] = `@media ${item[2]} {${item[1]}}`;
86+
item[2] = media;
87+
}
88+
}
89+
90+
if (supports) {
91+
if (!item[4]) {
92+
item[4] = `${supports}`;
4993
} else {
50-
item[2] = `${mediaQuery} and ${item[2]}`;
94+
item[1] = `@supports (${item[4]}) {${item[1]}}`;
95+
item[4] = supports;
5196
}
5297
}
5398

‎src/utils.js

+51-9
Original file line numberDiff line numberDiff line change
@@ -921,6 +921,34 @@ function normalizeSourceMapForRuntime(map, loaderContext) {
921921
return JSON.stringify(resultMap);
922922
}
923923

924+
function printParams(media, dedupe, supports, layer) {
925+
let result = "";
926+
927+
if (typeof layer !== "undefined") {
928+
result = `, ${JSON.stringify(layer)}`;
929+
}
930+
931+
if (typeof supports !== "undefined") {
932+
result = `, ${JSON.stringify(supports)}${result}`;
933+
} else if (result.length > 0) {
934+
result = `, undefined${result}`;
935+
}
936+
937+
if (dedupe) {
938+
result = `, true${result}`;
939+
} else if (result.length > 0) {
940+
result = `, false${result}`;
941+
}
942+
943+
if (media) {
944+
result = `${JSON.stringify(media)}${result}`;
945+
} else if (result.length > 0) {
946+
result = `""${result}`;
947+
}
948+
949+
return result;
950+
}
951+
924952
function getModuleCode(result, api, replacements, options, loaderContext) {
925953
if (options.modules.exportOnlyLocals === true) {
926954
return "";
@@ -939,15 +967,22 @@ function getModuleCode(result, api, replacements, options, loaderContext) {
939967
});\n`;
940968

941969
for (const item of api) {
942-
const { url, media, dedupe } = item;
943-
944-
beforeCode += url
945-
? `___CSS_LOADER_EXPORT___.push([module.id, ${JSON.stringify(
946-
`@import url(${url});`
947-
)}${media ? `, ${JSON.stringify(media)}` : ""}]);\n`
948-
: `___CSS_LOADER_EXPORT___.i(${item.importName}${
949-
media ? `, ${JSON.stringify(media)}` : dedupe ? ', ""' : ""
950-
}${dedupe ? ", true" : ""});\n`;
970+
const { url, layer, supports, media, dedupe } = item;
971+
972+
if (url) {
973+
// eslint-disable-next-line no-undefined
974+
const printedParam = printParams(media, undefined, supports, layer);
975+
976+
beforeCode += `___CSS_LOADER_EXPORT___.push([module.id, ${JSON.stringify(
977+
`@import url(${url});`
978+
)}${printedParam.length > 0 ? `, ${printedParam}` : ""}]);\n`;
979+
} else {
980+
const printedParam = printParams(media, dedupe, supports, layer);
981+
982+
beforeCode += `___CSS_LOADER_EXPORT___.i(${item.importName}${
983+
printedParam.length > 0 ? `, ${printedParam}` : ""
984+
});\n`;
985+
}
951986
}
952987

953988
for (const item of replacements) {
@@ -980,6 +1015,13 @@ function getModuleCode(result, api, replacements, options, loaderContext) {
9801015
}
9811016
}
9821017

1018+
// Indexes description:
1019+
// 0 - module id
1020+
// 1 - CSS code
1021+
// 2 - media
1022+
// 3 - source map
1023+
// 4 - supports
1024+
// 5 - layer
9831025
return `${beforeCode}// Module\n___CSS_LOADER_EXPORT___.push([module.id, ${code}, ""${sourceMapValue}]);\n`;
9841026
}
9851027

‎test/__snapshots__/import-option.test.js.snap

+854-1,794
Large diffs are not rendered by default.

‎test/__snapshots__/sourceMap-option.test.js.snap

+11-11
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ exports[`"sourceMap" option true should generate source maps #2: errors 1`] = `A
182182

183183
exports[`"sourceMap" option true should generate source maps #2: module 1`] = `
184184
"// Imports
185-
import ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \\"../../../src/runtime/noSourceMaps.js\\";
185+
import ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \\"../../../src/runtime/sourceMaps.js\\";
186186
import ___CSS_LOADER_API_IMPORT___ from \\"../../../src/runtime/api.js\\";
187187
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);
188188
// Module
@@ -226,7 +226,7 @@ exports[`"sourceMap" option true should generate source maps and do not change "
226226

227227
exports[`"sourceMap" option true should generate source maps and do not change "[contenthash]" on different platform: module 1`] = `
228228
"// Imports
229-
import ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \\"../../../src/runtime/noSourceMaps.js\\";
229+
import ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \\"../../../src/runtime/sourceMaps.js\\";
230230
import ___CSS_LOADER_API_IMPORT___ from \\"../../../src/runtime/api.js\\";
231231
import ___CSS_LOADER_AT_RULE_IMPORT_0___ from \\"-!../../../src/index.js??ruleSet[1].rules[0].rules[0]!./nested/nested.css\\";
232232
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);
@@ -395,7 +395,7 @@ exports[`"sourceMap" option true should generate source maps when previous loade
395395

396396
exports[`"sourceMap" option true should generate source maps when previous loader does not generate source maps: module 1`] = `
397397
"// Imports
398-
import ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \\"../../../src/runtime/noSourceMaps.js\\";
398+
import ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \\"../../../src/runtime/sourceMaps.js\\";
399399
import ___CSS_LOADER_API_IMPORT___ from \\"../../../src/runtime/api.js\\";
400400
import ___CSS_LOADER_AT_RULE_IMPORT_0___ from \\"-!../../../src/index.js??ruleSet[1].rules[0].use[0]!./nested/nested.css\\";
401401
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);
@@ -466,7 +466,7 @@ exports[`"sourceMap" option true should generate source maps when previous loade
466466

467467
exports[`"sourceMap" option true should generate source maps when previous loader generates different source in source maps: module 1`] = `
468468
"// Imports
469-
import ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \\"../../../src/runtime/noSourceMaps.js\\";
469+
import ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \\"../../../src/runtime/sourceMaps.js\\";
470470
import ___CSS_LOADER_API_IMPORT___ from \\"../../../src/runtime/api.js\\";
471471
import ___CSS_LOADER_AT_RULE_IMPORT_0___ from \\"-!../../../src/index.js??ruleSet[1].rules[0].use[0]!./nested/nested.css\\";
472472
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);
@@ -537,7 +537,7 @@ exports[`"sourceMap" option true should generate source maps when previous loade
537537

538538
exports[`"sourceMap" option true should generate source maps when previous loader generates source maps ("less-loader"): module 1`] = `
539539
"// Imports
540-
import ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \\"../../../src/runtime/noSourceMaps.js\\";
540+
import ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \\"../../../src/runtime/sourceMaps.js\\";
541541
import ___CSS_LOADER_API_IMPORT___ from \\"../../../src/runtime/api.js\\";
542542
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);
543543
// Module
@@ -586,7 +586,7 @@ exports[`"sourceMap" option true should generate source maps when previous loade
586586

587587
exports[`"sourceMap" option true should generate source maps when previous loader generates source maps ("postcss-loader"): module 1`] = `
588588
"// Imports
589-
import ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \\"../../../src/runtime/noSourceMaps.js\\";
589+
import ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \\"../../../src/runtime/sourceMaps.js\\";
590590
import ___CSS_LOADER_API_IMPORT___ from \\"../../../src/runtime/api.js\\";
591591
import ___CSS_LOADER_AT_RULE_IMPORT_0___ from \\"-!../../../src/index.js??ruleSet[1].rules[0].use[0]!./nested/nested.postcss.css\\";
592592
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);
@@ -727,7 +727,7 @@ exports[`"sourceMap" option true should generate source maps when previous loade
727727

728728
exports[`"sourceMap" option true should generate source maps when previous loader generates source maps ("sass-loader"): module 1`] = `
729729
"// Imports
730-
import ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \\"../../../src/runtime/noSourceMaps.js\\";
730+
import ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \\"../../../src/runtime/sourceMaps.js\\";
731731
import ___CSS_LOADER_API_IMPORT___ from \\"../../../src/runtime/api.js\\";
732732
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);
733733
// Module
@@ -775,7 +775,7 @@ exports[`"sourceMap" option true should generate source maps when previous loade
775775

776776
exports[`"sourceMap" option true should generate source maps when previous loader generates source maps ("stylus-loader"): module 1`] = `
777777
"// Imports
778-
import ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \\"../../../src/runtime/noSourceMaps.js\\";
778+
import ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \\"../../../src/runtime/sourceMaps.js\\";
779779
import ___CSS_LOADER_API_IMPORT___ from \\"../../../src/runtime/api.js\\";
780780
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);
781781
// Module
@@ -825,7 +825,7 @@ exports[`"sourceMap" option true should generate source maps when previous loade
825825

826826
exports[`"sourceMap" option true should generate source maps when previous loader generates source maps with "sourceRoot": module 1`] = `
827827
"// Imports
828-
import ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \\"../../../src/runtime/noSourceMaps.js\\";
828+
import ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \\"../../../src/runtime/sourceMaps.js\\";
829829
import ___CSS_LOADER_API_IMPORT___ from \\"../../../src/runtime/api.js\\";
830830
import ___CSS_LOADER_AT_RULE_IMPORT_0___ from \\"-!../../../src/index.js??ruleSet[1].rules[0].use[0]!./nested/nested.css\\";
831831
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);
@@ -896,7 +896,7 @@ exports[`"sourceMap" option true should generate source maps when previous loade
896896

897897
exports[`"sourceMap" option true should generate source maps when previous loader generates source maps without "sourceRoot": module 1`] = `
898898
"// Imports
899-
import ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \\"../../../src/runtime/noSourceMaps.js\\";
899+
import ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \\"../../../src/runtime/sourceMaps.js\\";
900900
import ___CSS_LOADER_API_IMPORT___ from \\"../../../src/runtime/api.js\\";
901901
import ___CSS_LOADER_AT_RULE_IMPORT_0___ from \\"-!../../../src/index.js??ruleSet[1].rules[0].use[0]!./nested/nested.css\\";
902902
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);
@@ -967,7 +967,7 @@ exports[`"sourceMap" option true should generate source maps: errors 1`] = `Arra
967967

968968
exports[`"sourceMap" option true should generate source maps: module 1`] = `
969969
"// Imports
970-
import ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \\"../../../src/runtime/noSourceMaps.js\\";
970+
import ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \\"../../../src/runtime/sourceMaps.js\\";
971971
import ___CSS_LOADER_API_IMPORT___ from \\"../../../src/runtime/api.js\\";
972972
import ___CSS_LOADER_AT_RULE_IMPORT_0___ from \\"-!../../../src/index.js??ruleSet[1].rules[0].use[0]!./nested/nested.css\\";
973973
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
@import url("./import-with-layer.css") layer(form);
2+
3+
@layer form {
4+
.bar {
5+
color: red;
6+
}
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@import url("./import-with-media.css") screen and (min-width: 400px);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@import url("./import-with-supports.css") supports(display: block);
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/* unnamed wrapper layers around each sub-file */
2+
@import url("./relative.css") layer;
3+
@import url("./test.css") layer;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/* the internal names are hidden from access, subsumed in "base" */
2+
@import url("./deep-layer-base.css") layer(base);

‎test/fixtures/import/deep-layer.css

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
@import url(./deep-layer-first-level.css) layer(bootstrap);
2+
3+
/* Adds additional styles to the bootstrap layer: */
4+
@layer bootstrap {
5+
.test {
6+
color: red;
7+
}
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@import url("./import-with-supports-and-media.css") supports(display: flex) screen and (min-width: 400px);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
@import url("./test.css") layer;
2+
@import url("./relative.css") layer;
3+
4+
.foo {
5+
color: red;
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
@import url('./test.css') layer(base);
2+
@import url('./relative.css') layer(base);
3+
4+
@layer base {
5+
.foo {
6+
color: red;
7+
}
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@import url("./test.css") layer;
2+
3+
.foo {
4+
color: red;
5+
}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
@import url("./import-with-layer-and-supports-and-media.css") layer(base) supports(display: grid) screen and (min-width: 900px);
1+
@import url("./test.css") layer(base) supports(display: grid) screen and (min-width: 900px);
+7-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,7 @@
1-
@import url('./test.css') layer(base) supports(display: grid);
1+
@import url('./test.css') layer(base);
2+
3+
@layer base {
4+
.foo {
5+
color: red;
6+
}
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@import url('./test.css') screen and (max-width: 1200px);
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
@import url('./test.css') supports(display: grid) handheld and (max-width: 400px);
1+
@import url('./test.css') supports(display: grid) screen and (max-width: 1200px);

‎test/fixtures/import/import.css

+22-5
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
@import url( test.css);
88
@import url( test.css );
99
@import url(
10-
test.css
10+
test.css
1111
);
1212
@import url();
1313
@import url('');
@@ -53,7 +53,7 @@ test.css
5353
}
5454

5555
.foo {
56-
@import 'path.css';
56+
@import 'path.css';
5757
}
5858

5959
@import url('./relative.css');
@@ -159,11 +159,17 @@ st.css');
159159
@import url(package/first.css);
160160
@import url(package/second.css);
161161

162+
@import url("./test.css") supports();
163+
@import url("./test.css") supports(unknown);
162164
@import url("./test.css") supports(display: flex);
165+
@import url("./test.css") supports(display: flex !important);
163166
@import url("./test.css") supports(display: flex) screen and (min-width: 400px);
164167
@import url("./test.css") layer;
165168
@import url("./test.css") layer(default);
166169
@import url("./test.css") layer(default) supports(display: flex) screen and (min-width: 400px);
170+
@import url("./test.css") layer supports(display: flex) screen and (min-width: 400px);
171+
@import url("./test.css") layer() supports(display: flex) screen and (min-width: 400px);
172+
@import url("./test.css") layer();
167173
@import url("http://example.com/style.css") supports(display: flex) screen and (min-width: 400px);
168174
@import url("./test.css")layer(default)supports(display: flex)screen and (min-width:400px);
169175
@import url("./test.css")screen and (min-width: 400px);
@@ -175,12 +181,23 @@ st.css');
175181
@import url(test.css) /* Comment */ print and (orientation:landscape);
176182
@import /* Comment */ url(test.css) /* Comment */ print and (orientation:landscape);
177183

184+
@import url("./import-with-media.css") screen and (min-width: 400px);
185+
@import url("./deep-import-with-media.css") (prefers-color-scheme: dark);
178186
@import url("./import-with-supports.css") supports(display: flex);
187+
@import url("./import-with-supports.css") supports(((display: flex)));
188+
@import url("./deep-import-with-supports.css") supports(display: flex);
189+
@import url('./test.css') supports(display: grid);
179190
@import url("./import-with-supports-and-media.css") supports(display: flex) screen and (min-width: 400px);
180-
@import url("./import-with-layer.css") layer(default);
191+
@import url("./import-deep-with-supports-and-media.css") supports(display: flex) screen and (min-width: 400px);
192+
@import url("./test.css") layer(framework);
193+
@import url("./import-with-layer.css") layer(framework);
194+
@import url("./deep-import-with-layer.css") layer(framework);
195+
@import url("./import-multiple-with-layer.css") layer(default);
181196
@import url("./import-with-layer-unnamed.css") layer(default);
197+
@import url("./import-unnamed-layer.css") layer(base);
198+
@import url("./import-multiple-unnamed-layer.css") layer(base);
182199
@import url("./import-with-layer-and-supports.css") layer(default) supports(display: flex);
183200
@import url("./import-with-layer-and-supports-and-media.css") layer(default) supports(display: flex) screen and (min-width: 400px);
201+
@import url("./deep-layer.css");
184202

185-
/* TODO fix comments */
186-
/* TODO check source maps generation */
203+
@import url("./test.css") unknown(default) unknown(display: flex) unknown;

‎test/fixtures/import/import.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import css from './import.css';
22

3-
__export__ = css;
3+
__export__ = css.toString();
44

55
export default css;

‎test/import-option.test.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,18 @@ describe('"import" option', () => {
8686
it("should work with import.filter", async () => {
8787
const compiler = getCompiler("./import/import.js", {
8888
import: {
89-
filter: (url, media, resourcePath) => {
89+
filter: (url, media, resourcePath, supports, layer) => {
9090
expect(url).toBeDefined();
9191

9292
if (url === "test-nested-media.css") {
9393
expect(media).toBeDefined();
9494
}
9595

96+
if (url === "./import-with-layer-and-supports-and-media.css") {
97+
expect(supports).toBeDefined();
98+
expect(layer).toBeDefined();
99+
}
100+
96101
expect(resourcePath).toBeDefined();
97102

98103
// Don't handle `test.css`

‎test/runtime/__snapshots__/api.test.js.snap

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3-
exports[`api should import modules 1`] = `"body { b: 2; }body { c: 3; }body { b: 2; }@media print {body { b: 2; }}@media print {body { d: 4; }}@media screen and (orientation:landscape) {body { a: 1; }}@media (orientation:landscape) {body { a: 1; }}"`;
3+
exports[`api should import modules 1`] = `"body { b: 2; }body { c: 3; }body { b: 2; }@media print {body { b: 2; }}@media print {body { d: 4; }}@media screen {@media (orientation:landscape) {body { a: 1; }}}@media (orientation:landscape) {body { a: 1; }}"`;
44

55
exports[`api should import modules when module string 1`] = `".button { b: 2; }"`;
66

@@ -20,12 +20,18 @@ exports[`api should toString with a source map without "sourceRoot" 1`] = `
2020

2121
exports[`api should toString with a source map without map 1`] = `"@import url('https://fonts.googleapis.com/css?family=Open+Sans&display=swap');"`;
2222

23-
exports[`api should toString with media query 1`] = `"body { b: 2; }body { c: 3; }body { b: 2; }@media print {body { b: 2; }}@media print {body { d: 4; }}@media screen {body { a: 1; }}"`;
23+
exports[`api should toString with layer 1`] = `"body { b: 2; }body { c: 3; }body { b: 2; }@media print {body { b: 2; }}@media print {body { d: 4; }}@layer default {body { a: 1; }}@layer {body { e: 5; }}@layer framework {@layer default {body { a: 1; }}}@layer framework {@layer {body { e: 5; }}}@layer framework {body { f: 6; }}"`;
24+
25+
exports[`api should toString with media query list 1`] = `"body { b: 2; }body { c: 3; }body { b: 2; }@media print {body { b: 2; }}@media print {body { d: 4; }}@media (min-width: 900px) {body { a: 1; }}@media screen {@media (min-width: 900px) {body { a: 1; }}}@media screen and (min-width: 900px) {body { e: 5; }}"`;
26+
27+
exports[`api should toString with media query list, layer and supports 1`] = `"body { b: 2; }body { c: 3; }body { b: 2; }@media print {body { b: 2; }}@media print {body { d: 4; }}@supports (display: grid) {@media screen {@layer default {body { a: 1; }}}}@supports (display: block) {@media screen and (mix-width: 100px) {@layer framework {@supports (display: grid) {@media screen {@layer default {body { a: 1; }}}}}}}"`;
2428

2529
exports[`api should toString with source mapping 1`] = `
2630
"body { a: 1; }
2731
/*# sourceURL=webpack://./path/to/test.scss */
2832
/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoidGVzdC5zY3NzIiwic291cmNlcyI6WyIuL3BhdGgvdG8vdGVzdC5zY3NzIl0sIm1hcHBpbmdzIjoiQUFBQTsiLCJzb3VyY2VSb290Ijoid2VicGFjazovLyJ9 */"
2933
`;
3034

35+
exports[`api should toString with supports 1`] = `"body { b: 2; }body { c: 3; }body { b: 2; }@supports (display: flex) {body { b: 2; }}@supports (display: flex) {body { d: 4; }}@supports (display: flex) {body { a: 1; }}@supports (display: block) {@supports (display: flex) {body { a: 1; }}}@supports (display: block) {@supports (display: grid) {body { e: 5; }}}@supports (display: grid) {body { e: 5; }}"`;
36+
3137
exports[`api should toString without source mapping if btoa not available 1`] = `"body { a: 1; }"`;

‎test/runtime/api.test.js

+118-24
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* @jest-environment jsdom
33
*/
44

5-
/* eslint-disable func-names */
5+
/* eslint-disable func-names, no-undefined */
66

77
const api = require("../../src/runtime/api");
88
const noSourceMaps = require("../../src/runtime/noSourceMaps");
@@ -30,45 +30,140 @@ describe("api", () => {
3030
it("should toString a single module", () => {
3131
const m = api(noSourceMaps);
3232

33-
m.push([1, "body { a: 1; }", ""]);
33+
m.push([1, "body { a: 1; }"]);
3434

3535
expect(m.toString()).toMatchSnapshot();
3636
});
3737

3838
it("should toString multiple modules", () => {
3939
const m = api(noSourceMaps);
4040

41-
m.push([2, "body { b: 2; }", ""]);
42-
m.push([1, "body { a: 1; }", ""]);
41+
m.push([2, "body { b: 2; }"]);
42+
m.push([1, "body { a: 1; }"]);
4343

4444
expect(m.toString()).toMatchSnapshot();
4545
});
4646

47-
it("should toString with media query", () => {
47+
it("should toString with media query list", () => {
4848
const m = api(noSourceMaps);
4949

50-
const m1 = [1, "body { a: 1; }", "screen"];
51-
const m2 = [2, "body { b: 2; }", ""];
52-
const m3 = [3, "body { c: 3; }", ""];
53-
const m4 = [4, "body { d: 4; }", ""];
50+
const m1 = [1, "body { a: 1; }", "(min-width: 900px)"];
51+
const m2 = [2, "body { b: 2; }", undefined];
52+
const m3 = [3, "body { c: 3; }", undefined];
53+
const m4 = [4, "body { d: 4; }", undefined];
54+
const m5 = [5, "body { e: 5; }", "screen and (min-width: 900px)"];
5455

55-
m.i([m2, m3], "");
56-
m.i([m2], "");
56+
m.i([m2, m3]);
57+
m.i([m2]);
5758
m.i([m2, m4], "print");
5859
m.push(m1);
60+
m.i([m1], "screen");
61+
m.i([m5]);
62+
63+
expect(m.toString()).toMatchSnapshot();
64+
});
65+
66+
it("should toString with supports", () => {
67+
const m = api(noSourceMaps);
68+
69+
const m1 = [1, "body { a: 1; }", undefined, undefined, "display: flex"];
70+
const m2 = [2, "body { b: 2; }", undefined];
71+
const m3 = [3, "body { c: 3; }", undefined];
72+
const m4 = [4, "body { d: 4; }", undefined];
73+
const m5 = [5, "body { e: 5; }", undefined, undefined, "display: grid"];
74+
75+
m.i([m2, m3]);
76+
m.i([m2]);
77+
m.i([m2, m4], undefined, false, "display: flex");
78+
m.push(m1);
79+
m.i([m1, m5], undefined, false, "display: block");
80+
m.i([m5]);
81+
82+
expect(m.toString()).toMatchSnapshot();
83+
});
84+
85+
it("should toString with layer", () => {
86+
const m = api(noSourceMaps);
87+
88+
const m1 = [
89+
1,
90+
"body { a: 1; }",
91+
undefined,
92+
undefined,
93+
undefined,
94+
"default",
95+
];
96+
const m2 = [2, "body { b: 2; }", undefined];
97+
const m3 = [3, "body { c: 3; }", undefined];
98+
const m4 = [4, "body { d: 4; }", undefined];
99+
const m5 = [5, "body { e: 5; }", undefined, undefined, undefined, ""];
100+
const m6 = [
101+
5,
102+
"body { f: 6; }",
103+
undefined,
104+
undefined,
105+
undefined,
106+
undefined,
107+
];
108+
109+
m.i([m2, m3], undefined);
110+
m.i([m2], undefined);
111+
m.i([m2, m4], "print");
112+
m.push(m1);
113+
m.i([m5]);
114+
m.i([m1, m5], undefined, undefined, undefined, "framework");
115+
m.i([m6], undefined, undefined, undefined, "framework");
116+
117+
expect(m.toString()).toMatchSnapshot();
118+
});
119+
120+
it("should toString with media query list, layer and supports", () => {
121+
const m = api(noSourceMaps);
122+
123+
const m1 = [
124+
1,
125+
"body { a: 1; }",
126+
"screen",
127+
undefined,
128+
"display: grid",
129+
"default",
130+
];
131+
const m2 = [2, "body { b: 2; }", undefined];
132+
const m3 = [3, "body { c: 3; }", undefined];
133+
const m4 = [4, "body { d: 4; }", undefined];
134+
const m5 = [
135+
5,
136+
"body { a: 1; }",
137+
"screen",
138+
undefined,
139+
"display: grid",
140+
"default",
141+
];
142+
143+
m.i([m2, m3], undefined);
144+
m.i([m2], undefined);
145+
m.i([m2, m4], "print");
146+
m.push(m1);
147+
m.i(
148+
[m5],
149+
"screen and (mix-width: 100px)",
150+
false,
151+
"display: block",
152+
"framework"
153+
);
59154

60155
expect(m.toString()).toMatchSnapshot();
61156
});
62157

63158
it("should import modules", () => {
64159
const m = api(noSourceMaps);
65160
const m1 = [1, "body { a: 1; }", "(orientation:landscape)"];
66-
const m2 = [2, "body { b: 2; }", ""];
67-
const m3 = [3, "body { c: 3; }", ""];
68-
const m4 = [4, "body { d: 4; }", ""];
161+
const m2 = [2, "body { b: 2; }", undefined];
162+
const m3 = [3, "body { c: 3; }", undefined];
163+
const m4 = [4, "body { d: 4; }", undefined];
69164

70-
m.i([m2, m3], "");
71-
m.i([m2], "");
165+
m.i([m2, m3], undefined);
166+
m.i([m2], undefined);
72167
m.i([m2, m4], "print");
73168
m.i([m1], "screen");
74169
m.push(m1);
@@ -79,12 +174,12 @@ describe("api", () => {
79174
it("should import named modules", () => {
80175
const m = api(noSourceMaps);
81176
const m1 = ["./module1", "body { a: 1; }", "screen"];
82-
const m2 = ["./module2", "body { b: 2; }", ""];
83-
const m3 = ["./module3", "body { c: 3; }", ""];
84-
const m4 = ["./module4", "body { d: 4; }", ""];
177+
const m2 = ["./module2", "body { b: 2; }", undefined];
178+
const m3 = ["./module3", "body { c: 3; }", undefined];
179+
const m4 = ["./module4", "body { d: 4; }", undefined];
85180

86-
m.i([m2, m3], "");
87-
m.i([m2], "");
181+
m.i([m2, m3], undefined);
182+
m.i([m2], undefined);
88183
m.i([m2, m4], "print");
89184
m.push(m1);
90185

@@ -97,7 +192,7 @@ describe("api", () => {
97192
m.push([
98193
1,
99194
"body { a: 1; }",
100-
"",
195+
undefined,
101196
{
102197
file: "test.scss",
103198
sources: ["./path/to/test.scss"],
@@ -134,7 +229,7 @@ describe("api", () => {
134229
m.push([
135230
1,
136231
"body { a: 1; }",
137-
"",
232+
undefined,
138233
{
139234
file: "test.scss",
140235
sources: ["./path/to/test.scss"],
@@ -184,4 +279,3 @@ describe("api", () => {
184279
expect(m.toString()).toMatchSnapshot();
185280
});
186281
});
187-
/* eslint-enable func-names */

‎test/sourceMap-option.test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@ describe('"sourceMap" option', () => {
498498
(assetName) => /\.js$/.test(assetName)
499499
);
500500

501-
expect(chunkName).toBe("main.3d1970f1effd30ed73f3.bundle.js");
501+
expect(chunkName).toBe("main.37fd3b99e870aa818226.bundle.js");
502502
expect(
503503
getModuleSource("fixtures/source-map/basic.css", stats)
504504
).toMatchSnapshot("module");

0 commit comments

Comments
 (0)
Please sign in to comment.