Skip to content

Commit 31abc62

Browse files
feat: supported supports() and layer() in @import at-rule
1 parent 28ab0aa commit 31abc62

File tree

7 files changed

+285
-3110
lines changed

7 files changed

+285
-3110
lines changed

src/plugins/postcss-import-parser.js

+57-12
Original file line numberDiff line numberDiff line change
@@ -112,15 +112,40 @@ function parseNode(atRule, key) {
112112
throw error;
113113
}
114114

115-
const mediaNodes = paramsNodes.slice(1);
115+
const additionalNodes = paramsNodes.slice(1);
116+
117+
let supports;
118+
let layer;
116119
let media;
117120

118-
if (mediaNodes.length > 0) {
119-
media = valueParser.stringify(mediaNodes).trim().toLowerCase();
121+
if (additionalNodes.length > 0) {
122+
let nodes = [];
123+
124+
for (const node of additionalNodes) {
125+
nodes.push(node);
126+
127+
if (
128+
(node.type === "function" && node.value.toLowerCase() === "layer") ||
129+
(node.type === "word" && node.value.toLowerCase() === "layer")
130+
) {
131+
layer = valueParser.stringify(nodes).trim().toLowerCase();
132+
nodes = [];
133+
} else if (
134+
node.type === "function" &&
135+
node.value.toLowerCase() === "supports"
136+
) {
137+
supports = valueParser.stringify(nodes).trim().toLowerCase();
138+
nodes = [];
139+
}
140+
}
141+
142+
if (nodes.length > 0) {
143+
media = valueParser.stringify(nodes).trim().toLowerCase();
144+
}
120145
}
121146

122147
// eslint-disable-next-line consistent-return
123-
return { atRule, prefix, url, media, isRequestable };
148+
return { atRule, prefix, url, layer, supports, media, isRequestable };
124149
}
125150

126151
const plugin = (options = {}) => {
@@ -154,11 +179,23 @@ const plugin = (options = {}) => {
154179

155180
const resolvedAtRules = await Promise.all(
156181
parsedAtRules.map(async (parsedAtRule) => {
157-
const { atRule, isRequestable, prefix, url, media } =
158-
parsedAtRule;
182+
const {
183+
atRule,
184+
isRequestable,
185+
prefix,
186+
url,
187+
layer,
188+
supports,
189+
media,
190+
} = parsedAtRule;
159191

160192
if (options.filter) {
161-
const needKeep = await options.filter(url, media);
193+
const needKeep = await options.filter(
194+
url,
195+
media,
196+
layer,
197+
supports
198+
);
162199

163200
if (!needKeep) {
164201
return;
@@ -186,13 +223,20 @@ const plugin = (options = {}) => {
186223
atRule.remove();
187224

188225
// eslint-disable-next-line consistent-return
189-
return { url: resolvedUrl, media, prefix, isRequestable };
226+
return {
227+
url: resolvedUrl,
228+
layer,
229+
supports,
230+
media,
231+
prefix,
232+
isRequestable,
233+
};
190234
}
191235

192236
atRule.remove();
193237

194238
// eslint-disable-next-line consistent-return
195-
return { url, media, prefix, isRequestable };
239+
return { url, layer, supports, media, prefix, isRequestable };
196240
})
197241
);
198242

@@ -206,10 +250,11 @@ const plugin = (options = {}) => {
206250
continue;
207251
}
208252

209-
const { url, isRequestable, media } = resolvedAtRule;
253+
const { url, isRequestable, layer, supports, media } =
254+
resolvedAtRule;
210255

211256
if (!isRequestable) {
212-
options.api.push({ url, media, index });
257+
options.api.push({ url, layer, supports, media, index });
213258

214259
// eslint-disable-next-line no-continue
215260
continue;
@@ -231,7 +276,7 @@ const plugin = (options = {}) => {
231276
});
232277
}
233278

234-
options.api.push({ importName, media, index });
279+
options.api.push({ importName, layer, supports, media, index });
235280
}
236281
},
237282
};

src/runtime/api.js

+44-6
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,32 @@ module.exports = function (cssWithMappingToString) {
1010
// return the list of modules as css string
1111
list.toString = function toString() {
1212
return this.map((item) => {
13-
const content = cssWithMappingToString(item);
13+
let content = "";
14+
15+
if (item[4]) {
16+
content += `@${item[4]} {`;
17+
}
18+
19+
if (item[3]) {
20+
content += `@${item[3]} {`;
21+
}
22+
23+
if (item[2]) {
24+
content += `@media ${item[2]} {`;
25+
}
26+
27+
content += cssWithMappingToString(item);
1428

1529
if (item[2]) {
16-
return `@media ${item[2]} {${content}}`;
30+
content += "}";
31+
}
32+
33+
if (item[3]) {
34+
content += "}";
35+
}
36+
37+
if (item[4]) {
38+
content += "}";
1739
}
1840

1941
return content;
@@ -22,7 +44,7 @@ module.exports = function (cssWithMappingToString) {
2244

2345
// import a list of modules into the list
2446
// eslint-disable-next-line func-names
25-
list.i = function (modules, mediaQuery, dedupe) {
47+
list.i = function (modules, mediaQueryList, dedupe, layer, supports) {
2648
if (typeof modules === "string") {
2749
// eslint-disable-next-line no-param-reassign
2850
modules = [[null, modules, ""]];
@@ -49,11 +71,27 @@ module.exports = function (cssWithMappingToString) {
4971
continue;
5072
}
5173

52-
if (mediaQuery) {
74+
if (mediaQueryList) {
5375
if (!item[2]) {
54-
item[2] = mediaQuery;
76+
item[2] = mediaQueryList;
77+
} else {
78+
item[2] = `${mediaQueryList} and ${item[2]}`;
79+
}
80+
}
81+
82+
if (layer) {
83+
if (!item[3]) {
84+
item[3] = layer;
85+
} else {
86+
item[3] = `${layer} and ${item[3]}`;
87+
}
88+
}
89+
90+
if (supports) {
91+
if (!item[4]) {
92+
item[4] = supports;
5593
} else {
56-
item[2] = `${mediaQuery} and ${item[2]}`;
94+
item[4] = `${supports} and ${item[4]}`;
5795
}
5896
}
5997

src/utils.js

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

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

941967
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`;
968+
const { url, layer, supports, media, dedupe } = item;
969+
970+
if (url) {
971+
// eslint-disable-next-line no-undefined
972+
const printedParam = printParams(media, undefined, supports, layer);
973+
974+
beforeCode += `___CSS_LOADER_EXPORT___.push([module.id, ${JSON.stringify(
975+
`@import url(${url});`
976+
)}${printedParam.length > 0 ? `, ${printedParam}` : ""}]);\n`;
977+
} else {
978+
const printedParam = printParams(media, dedupe, supports, layer);
979+
980+
beforeCode += `___CSS_LOADER_EXPORT___.i(${item.importName}${
981+
printedParam.length > 0 ? `, ${printedParam}` : ""
982+
});\n`;
983+
}
951984
}
952985

953986
for (const item of replacements) {

0 commit comments

Comments
 (0)