Skip to content

Commit edf5347

Browse files
authoredJul 7, 2020
feat: respected the style field from package.json (#1099)
1 parent fcdc1ab commit edf5347

24 files changed

+1492
-1148
lines changed
 

‎.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ Thumbs.db
1616
.vscode
1717
*.sublime-project
1818
*.sublime-workspace
19+
/test/fixtures/import/import-absolute.css

‎package-lock.json

+958-1,036
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎src/index.js

+29
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,20 @@ export default function loader(content, map, meta) {
4747
plugins.push(icssParser({ urlHandler }));
4848

4949
if (options.import !== false && exportType === 'full') {
50+
const resolver = this.getResolve({
51+
mainFields: ['css', 'style', 'main', '...'],
52+
mainFiles: ['index', '...'],
53+
extensions: ['.css'],
54+
restrictions: [/\.css$/i],
55+
conditionNames: ['style'],
56+
});
57+
5058
plugins.push(
5159
importParser({
60+
context: this.context,
61+
rootContext: this.rootContext,
5262
filter: getFilter(options.import, this.resourcePath),
63+
resolver,
5364
urlHandler,
5465
})
5566
);
@@ -125,6 +136,24 @@ export default function loader(content, map, meta) {
125136
}
126137
}
127138

139+
apiImports.sort((a, b) => a.index - b.index);
140+
141+
/*
142+
* Order
143+
* CSS_LOADER_ICSS_IMPORT: [],
144+
* CSS_LOADER_AT_RULE_IMPORT: [],
145+
* CSS_LOADER_GET_URL_IMPORT: [],
146+
* CSS_LOADER_URL_IMPORT: [],
147+
* CSS_LOADER_URL_REPLACEMENT: [],
148+
* */
149+
150+
imports.sort((a, b) => {
151+
return (
152+
(b.order < a.order) - (a.order < b.order) ||
153+
(b.index < a.index) - (a.index < b.index)
154+
);
155+
});
156+
128157
const { localsConvention } = options;
129158
const esModule =
130159
typeof options.esModule !== 'undefined' ? options.esModule : false;

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

+2
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ export default postcss.plugin(
4242
{
4343
type: 'import',
4444
value: {
45+
// 'CSS_LOADER_ICSS_IMPORT'
46+
order: 0,
4547
importName,
4648
url: options.urlHandler ? options.urlHandler(url) : url,
4749
},

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

+139-96
Original file line numberDiff line numberDiff line change
@@ -1,132 +1,175 @@
11
import postcss from 'postcss';
22
import valueParser from 'postcss-value-parser';
3-
import { isUrlRequest } from 'loader-utils';
43

5-
import { normalizeUrl } from '../utils';
4+
import { normalizeUrl, resolveRequests, isUrlRequestable } from '../utils';
65

76
const pluginName = 'postcss-import-parser';
87

98
export default postcss.plugin(pluginName, (options) => (css, result) => {
10-
const importsMap = new Map();
11-
12-
css.walkAtRules(/^import$/i, (atRule) => {
13-
// Convert only top-level @import
14-
if (atRule.parent.type !== 'root') {
15-
return;
16-
}
17-
18-
// Nodes do not exists - `@import url('http://') :root {}`
19-
if (atRule.nodes) {
20-
result.warn(
21-
"It looks like you didn't end your @import statement correctly. Child nodes are attached to it.",
22-
{ node: atRule }
23-
);
9+
return new Promise((resolve, reject) => {
10+
const importsMap = new Map();
11+
const tasks = [];
2412

25-
return;
26-
}
27-
28-
const { nodes } = valueParser(atRule.params);
29-
30-
// No nodes - `@import ;`
31-
// Invalid type - `@import foo-bar;`
32-
if (
33-
nodes.length === 0 ||
34-
(nodes[0].type !== 'string' && nodes[0].type !== 'function')
35-
) {
36-
result.warn(`Unable to find uri in "${atRule.toString()}"`, {
37-
node: atRule,
38-
});
39-
40-
return;
41-
}
42-
43-
let isStringValue;
44-
let url;
45-
46-
if (nodes[0].type === 'string') {
47-
isStringValue = true;
48-
url = nodes[0].value;
49-
} else if (nodes[0].type === 'function') {
50-
// Invalid function - `@import nourl(test.css);`
51-
if (nodes[0].value.toLowerCase() !== 'url') {
52-
result.warn(`Unable to find uri in "${atRule.toString()}"`, {
53-
node: atRule,
54-
});
13+
// A counter is used instead of an index in callback css.walkAtRules because we mutate AST (atRule.remove())
14+
let index = 0;
5515

16+
css.walkAtRules(/^import$/i, (atRule) => {
17+
// Convert only top-level @import
18+
if (atRule.parent.type !== 'root') {
5619
return;
5720
}
5821

59-
isStringValue =
60-
nodes[0].nodes.length !== 0 && nodes[0].nodes[0].type === 'string';
61-
url = isStringValue
62-
? nodes[0].nodes[0].value
63-
: valueParser.stringify(nodes[0].nodes);
64-
}
22+
// Nodes do not exists - `@import url('http://') :root {}`
23+
if (atRule.nodes) {
24+
result.warn(
25+
"It looks like you didn't end your @import statement correctly. Child nodes are attached to it.",
26+
{ node: atRule }
27+
);
6528

66-
// Empty url - `@import "";` or `@import url();`
67-
if (url.trim().length === 0) {
68-
result.warn(`Unable to find uri in "${atRule.toString()}"`, {
69-
node: atRule,
70-
});
29+
return;
30+
}
7131

72-
return;
73-
}
32+
const { nodes } = valueParser(atRule.params);
7433

75-
const isRequestable = isUrlRequest(url);
34+
// No nodes - `@import ;`
35+
// Invalid type - `@import foo-bar;`
36+
if (
37+
nodes.length === 0 ||
38+
(nodes[0].type !== 'string' && nodes[0].type !== 'function')
39+
) {
40+
result.warn(`Unable to find uri in "${atRule.toString()}"`, {
41+
node: atRule,
42+
});
7643

77-
if (isRequestable) {
78-
url = normalizeUrl(url, isStringValue);
44+
return;
45+
}
46+
47+
let isStringValue;
48+
let url;
49+
50+
if (nodes[0].type === 'string') {
51+
isStringValue = true;
52+
url = nodes[0].value;
53+
} else if (nodes[0].type === 'function') {
54+
// Invalid function - `@import nourl(test.css);`
55+
if (nodes[0].value.toLowerCase() !== 'url') {
56+
result.warn(`Unable to find uri in "${atRule.toString()}"`, {
57+
node: atRule,
58+
});
59+
60+
return;
61+
}
62+
63+
isStringValue =
64+
nodes[0].nodes.length !== 0 && nodes[0].nodes[0].type === 'string';
65+
url = isStringValue
66+
? nodes[0].nodes[0].value
67+
: valueParser.stringify(nodes[0].nodes);
68+
}
7969

80-
// Empty url after normalize - `@import '\
81-
// \
82-
// \
83-
// ';
70+
// Empty url - `@import "";` or `@import url();`
8471
if (url.trim().length === 0) {
8572
result.warn(`Unable to find uri in "${atRule.toString()}"`, {
8673
node: atRule,
8774
});
8875

8976
return;
9077
}
91-
}
9278

93-
const media = valueParser.stringify(nodes.slice(1)).trim().toLowerCase();
79+
let normalizedUrl;
9480

95-
if (options.filter && !options.filter({ url, media })) {
96-
return;
97-
}
81+
const isRequestable = isUrlRequestable(url);
9882

99-
atRule.remove();
83+
if (isRequestable) {
84+
normalizedUrl = normalizeUrl(url, isStringValue, options.rootContext);
10085

101-
if (isRequestable) {
102-
const importKey = url;
103-
let importName = importsMap.get(importKey);
86+
// Empty url after normalize - `@import '\
87+
// \
88+
// \
89+
// ';
90+
if (normalizedUrl.trim().length === 0) {
91+
result.warn(`Unable to find uri in "${atRule.toString()}"`, {
92+
node: atRule,
93+
});
10494

105-
if (!importName) {
106-
importName = `___CSS_LOADER_AT_RULE_IMPORT_${importsMap.size}___`;
107-
importsMap.set(importKey, importName);
108-
109-
result.messages.push({
110-
type: 'import',
111-
value: {
112-
importName,
113-
url: options.urlHandler ? options.urlHandler(url) : url,
114-
},
115-
});
95+
return;
96+
}
11697
}
11798

118-
result.messages.push({
119-
type: 'api-import',
120-
value: { type: 'internal', importName, media },
121-
});
99+
const media = valueParser.stringify(nodes.slice(1)).trim().toLowerCase();
122100

123-
return;
124-
}
101+
if (
102+
options.filter &&
103+
!options.filter({ url: normalizedUrl || url, media })
104+
) {
105+
return;
106+
}
125107

126-
result.messages.push({
127-
pluginName,
128-
type: 'api-import',
129-
value: { type: 'external', url, media },
108+
atRule.remove();
109+
110+
index += 1;
111+
112+
tasks.push(
113+
Promise.resolve(index).then(async (currentIndex) => {
114+
if (isRequestable) {
115+
const importKey = normalizedUrl;
116+
let importName = importsMap.get(importKey);
117+
118+
if (!importName) {
119+
importName = `___CSS_LOADER_AT_RULE_IMPORT_${importsMap.size}___`;
120+
importsMap.set(importKey, importName);
121+
122+
const { resolver, context } = options;
123+
124+
let resolvedUrl;
125+
126+
try {
127+
resolvedUrl = await resolveRequests(resolver, context, [
128+
...new Set([normalizedUrl, url]),
129+
]);
130+
} catch (error) {
131+
throw error;
132+
}
133+
134+
result.messages.push({
135+
type: 'import',
136+
value: {
137+
// 'CSS_LOADER_AT_RULE_IMPORT'
138+
order: 1,
139+
importName,
140+
url: options.urlHandler
141+
? options.urlHandler(resolvedUrl)
142+
: resolvedUrl,
143+
index: currentIndex,
144+
},
145+
});
146+
}
147+
148+
result.messages.push({
149+
type: 'api-import',
150+
value: {
151+
type: 'internal',
152+
importName,
153+
media,
154+
index: currentIndex,
155+
},
156+
});
157+
158+
return;
159+
}
160+
161+
result.messages.push({
162+
pluginName,
163+
type: 'api-import',
164+
value: { type: 'external', url, media, index: currentIndex },
165+
});
166+
})
167+
);
130168
});
169+
170+
Promise.all(tasks).then(
171+
() => resolve(),
172+
(error) => reject(error)
173+
);
131174
});
132175
});

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

+19-1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ export default postcss.plugin(pluginName, (options) => (css, result) => {
6565

6666
let hasHelper = false;
6767

68+
let index = 0;
69+
6870
css.walkDecls((decl) => {
6971
if (!needParseDecl.test(decl.value)) {
7072
return;
@@ -99,6 +101,8 @@ export default postcss.plugin(pluginName, (options) => (css, result) => {
99101
const importKey = normalizedUrl;
100102
let importName = importsMap.get(importKey);
101103

104+
index += 1;
105+
102106
if (!importName) {
103107
importName = `___CSS_LOADER_URL_IMPORT_${importsMap.size}___`;
104108
importsMap.set(importKey, importName);
@@ -110,10 +114,13 @@ export default postcss.plugin(pluginName, (options) => (css, result) => {
110114
pluginName,
111115
type: 'import',
112116
value: {
117+
// 'CSS_LOADER_GET_URL_IMPORT'
118+
order: 2,
113119
importName: '___CSS_LOADER_GET_URL_IMPORT___',
114120
url: options.urlHandler
115121
? options.urlHandler(urlToHelper)
116122
: urlToHelper,
123+
index,
117124
},
118125
});
119126

@@ -124,10 +131,13 @@ export default postcss.plugin(pluginName, (options) => (css, result) => {
124131
pluginName,
125132
type: 'import',
126133
value: {
134+
// 'CSS_LOADER_URL_IMPORT'
135+
order: 3,
127136
importName,
128137
url: options.urlHandler
129138
? options.urlHandler(normalizedUrl)
130139
: normalizedUrl,
140+
index,
131141
},
132142
});
133143
}
@@ -142,7 +152,15 @@ export default postcss.plugin(pluginName, (options) => (css, result) => {
142152
result.messages.push({
143153
pluginName,
144154
type: 'url-replacement',
145-
value: { replacementName, importName, hash, needQuotes },
155+
value: {
156+
// 'CSS_LOADER_URL_REPLACEMENT'
157+
order: 4,
158+
replacementName,
159+
importName,
160+
hash,
161+
needQuotes,
162+
index,
163+
},
146164
});
147165
}
148166

0 commit comments

Comments
 (0)