Skip to content

Commit 5e4a77b

Browse files
fix: resolve from and to from config and options (#467)
BREAKING CHANGE: `from` and `to` options are resolved now
1 parent 225b2e5 commit 5e4a77b

File tree

9 files changed

+194
-38
lines changed

9 files changed

+194
-38
lines changed

src/index.js

+2-5
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,7 @@ export default async function loader(content, sourceMap) {
7474
processOptions.map = { inline: false, annotation: false };
7575

7676
if (sourceMap) {
77-
processOptions.map.prev = normalizeSourceMap(
78-
sourceMap,
79-
this.resourcePath
80-
);
77+
processOptions.map.prev = normalizeSourceMap(sourceMap, this.context);
8178
}
8279
} else if (sourceMap && typeof processOptions.map !== 'undefined') {
8380
if (typeof processOptions.map === 'boolean') {
@@ -128,7 +125,7 @@ export default async function loader(content, sourceMap) {
128125
let map = result.map ? result.map.toJSON() : undefined;
129126

130127
if (map && useSourceMap) {
131-
map = normalizeSourceMapAfterPostcss(map, this.resourcePath);
128+
map = normalizeSourceMapAfterPostcss(map, this.context);
132129
}
133130

134131
const ast = {

src/utils.js

+32-7
Original file line numberDiff line numberDiff line change
@@ -192,18 +192,45 @@ function getPostcssOptions(loaderContext, config, postcssOptions = {}) {
192192

193193
const processOptionsFromConfig = { ...config };
194194

195+
if (processOptionsFromConfig.from) {
196+
processOptionsFromConfig.from = path.resolve(
197+
path.dirname(config.file),
198+
processOptionsFromConfig.from
199+
);
200+
}
201+
202+
if (processOptionsFromConfig.to) {
203+
processOptionsFromConfig.to = path.resolve(
204+
path.dirname(config.file),
205+
processOptionsFromConfig.to
206+
);
207+
}
208+
195209
// No need them for processOptions
196210
delete processOptionsFromConfig.plugins;
197211
delete processOptionsFromConfig.file;
198212

199213
const processOptionsFromOptions = { ...normalizedPostcssOptions };
200214

215+
if (processOptionsFromOptions.from) {
216+
processOptionsFromOptions.from = path.resolve(
217+
loaderContext.rootContext,
218+
processOptionsFromOptions.from
219+
);
220+
}
221+
222+
if (processOptionsFromOptions.to) {
223+
processOptionsFromOptions.to = path.resolve(
224+
loaderContext.rootContext,
225+
processOptionsFromOptions.to
226+
);
227+
}
228+
201229
// No need them for processOptions
202230
delete processOptionsFromOptions.config;
203231
delete processOptionsFromOptions.plugins;
204232

205233
const processOptions = {
206-
// TODO path.resolve
207234
from: file,
208235
to: file,
209236
map: false,
@@ -272,7 +299,7 @@ function getURLType(source) {
272299
return ABSOLUTE_SCHEME.test(source) ? 'absolute' : 'path-relative';
273300
}
274301

275-
function normalizeSourceMap(map, resourcePath) {
302+
function normalizeSourceMap(map, resourceContext) {
276303
let newMap = map;
277304

278305
// Some loader emit source map as string
@@ -298,7 +325,7 @@ function normalizeSourceMap(map, resourcePath) {
298325
? path.resolve(sourceRoot, path.normalize(source))
299326
: path.normalize(source);
300327

301-
return path.relative(path.dirname(resourcePath), absoluteSource);
328+
return path.relative(resourceContext, absoluteSource);
302329
}
303330

304331
return source;
@@ -308,7 +335,7 @@ function normalizeSourceMap(map, resourcePath) {
308335
return newMap;
309336
}
310337

311-
function normalizeSourceMapAfterPostcss(map, resourcePath) {
338+
function normalizeSourceMapAfterPostcss(map, resourceContext) {
312339
const newMap = map;
313340

314341
// result.map.file is an optional property that provides the output filename.
@@ -329,9 +356,7 @@ function normalizeSourceMapAfterPostcss(map, resourcePath) {
329356

330357
// Do no touch `scheme-relative`, `path-absolute` and `absolute` types
331358
if (sourceType === 'path-relative') {
332-
const dirname = path.dirname(resourcePath);
333-
334-
return path.resolve(dirname, source);
359+
return path.resolve(resourceContext, source);
335360
}
336361

337362
return source;

test/__snapshots__/config.test.js.snap

+34
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,40 @@ exports[`"config" option should work "String" value (relative path): errors 1`]
3131

3232
exports[`"config" option should work "String" value (relative path): warnings 1`] = `Array []`;
3333

34+
exports[`"config" option should work and resolve "from" and "to" options: css 1`] = `
35+
"a { color: black }
36+
37+
.foo {
38+
float: right;
39+
}
40+
"
41+
`;
42+
43+
exports[`"config" option should work and resolve "from" and "to" options: errors 1`] = `Array []`;
44+
45+
exports[`"config" option should work and resolve "from" and "to" options: source map 1`] = `
46+
Object {
47+
"file": "style.css",
48+
"mappings": "AAAA,IAAI,aAAa;;AAEjB;EACE,YAAY;AACd",
49+
"names": Array [],
50+
"sourceRoot": "",
51+
"sources": Array [
52+
"style.css",
53+
],
54+
"sourcesContent": Array [
55+
"a { color: black }
56+
57+
.foo {
58+
float: right;
59+
}
60+
",
61+
],
62+
"version": 3,
63+
}
64+
`;
65+
66+
exports[`"config" option should work and resolve "from" and "to" options: warnings 1`] = `Array []`;
67+
3468
exports[`"config" option should work with "String" value (absolute path): css 1`] = `
3569
"a { color: rgba(0, 0, 0, 1.0) }
3670

test/__snapshots__/postcssOptins.test.js.snap

+57-4
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ exports[`"postcssOptions" option should work "Function" value: errors 1`] = `Arr
153153

154154
exports[`"postcssOptions" option should work "Function" value: warnings 1`] = `Array []`;
155155

156-
exports[`"postcssOptions" option should work with "from", "to" and "map" options: css 1`] = `
156+
exports[`"postcssOptions" option should work with "from", "to" and "map" options (absolute paths): css 1`] = `
157157
"a {
158158
color: black;
159159
}
@@ -200,11 +200,64 @@ a {
200200
"
201201
`;
202202

203-
exports[`"postcssOptions" option should work with "from", "to" and "map" options: errors 1`] = `Array []`;
203+
exports[`"postcssOptions" option should work with "from", "to" and "map" options (absolute paths): errors 1`] = `Array []`;
204204

205-
exports[`"postcssOptions" option should work with "from", "to" and "map" options: map 1`] = `undefined`;
205+
exports[`"postcssOptions" option should work with "from", "to" and "map" options (absolute paths): map 1`] = `undefined`;
206206

207-
exports[`"postcssOptions" option should work with "from", "to" and "map" options: warnings 1`] = `Array []`;
207+
exports[`"postcssOptions" option should work with "from", "to" and "map" options (absolute paths): warnings 1`] = `Array []`;
208+
209+
exports[`"postcssOptions" option should work with "from", "to" and "map" options (relative paths): css 1`] = `
210+
"a {
211+
color: black;
212+
}
213+
214+
a {
215+
color: red;
216+
}
217+
218+
a {
219+
color: green;
220+
}
221+
222+
a {
223+
color: blue;
224+
}
225+
226+
.class {
227+
-x-border-color: blue blue *;
228+
-x-color: * #fafafa;
229+
}
230+
231+
.class-foo {
232+
-z-border-color: blue blue *;
233+
-z-color: * #fafafa;
234+
}
235+
236+
.phone {
237+
&_title {
238+
width: 500px;
239+
240+
@media (max-width: 500px) {
241+
width: auto;
242+
}
243+
244+
body.is_dark & {
245+
color: white;
246+
}
247+
}
248+
249+
img {
250+
display: block;
251+
}
252+
}
253+
"
254+
`;
255+
256+
exports[`"postcssOptions" option should work with "from", "to" and "map" options (relative paths): errors 1`] = `Array []`;
257+
258+
exports[`"postcssOptions" option should work with "from", "to" and "map" options (relative paths): map 1`] = `undefined`;
259+
260+
exports[`"postcssOptions" option should work with "from", "to" and "map" options (relative paths): warnings 1`] = `Array []`;
208261

209262
exports[`"postcssOptions" option should work with the "map" option and generate inlined source maps: css 1`] = `
210263
"a {

test/config-autoload.test.js

+2-6
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,8 @@ describe('autoload config', () => {
3535
expect(config.parser).toEqual(false);
3636
expect(config.syntax).toEqual(false);
3737
expect(config.map).toEqual(false);
38-
expect(config.from).toEqual(
39-
'./test/fixtures/config-autoload/pkg/index.css'
40-
);
41-
expect(config.to).toEqual(
42-
'./test/fixtures/config-autoload/pkg/expected/index.css'
43-
);
38+
expect(config.from).toEqual('./index.css');
39+
expect(config.to).toEqual('./index.css');
4440
expect(Object.keys(config.plugins).length).toEqual(2);
4541
expect(config.file).toEqual(
4642
path.resolve(testDirectory, 'pkg', 'package.json')

test/config.test.js

+27
Original file line numberDiff line numberDiff line change
@@ -191,4 +191,31 @@ describe('"config" option', () => {
191191
expect(getWarnings(stats)).toMatchSnapshot('warnings');
192192
expect(getErrors(stats, true)).toMatchSnapshot('errors');
193193
});
194+
195+
it('should work and resolve "from" and "to" options', async () => {
196+
const compiler = getCompiler('./config-scope/css/index.js', {
197+
postcssOptions: {
198+
config: path.resolve(
199+
__dirname,
200+
'./fixtures/config-scope/from-to/postcss.config.js'
201+
),
202+
},
203+
});
204+
const stats = await compile(compiler);
205+
206+
const { css, sourceMap } = getCodeFromBundle('style.css', stats);
207+
208+
sourceMap.sourceRoot = '';
209+
sourceMap.sources = sourceMap.sources.map((source) => {
210+
expect(path.isAbsolute(source)).toBe(false);
211+
expect(source).toBe(path.normalize(source));
212+
213+
return source.replace(/\\/g, '/');
214+
});
215+
216+
expect(css).toMatchSnapshot('css');
217+
expect(sourceMap).toMatchSnapshot('source map');
218+
expect(getWarnings(stats)).toMatchSnapshot('warnings');
219+
expect(getErrors(stats)).toMatchSnapshot('errors');
220+
});
194221
});

test/fixtures/config-autoload/pkg/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
"parser": false,
66
"syntax": false,
77
"map": false,
8-
"from": "./test/fixtures/config-autoload/pkg/index.css",
9-
"to": "./test/fixtures/config-autoload/pkg/expected/index.css",
8+
"from": "./index.css",
9+
"to": "./index.css",
1010
"plugins": [
1111
"postcss-import",
1212
["postcss-nested", {}]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
module.exports = {
2+
from: '../../css/style.css',
3+
to: '../../css/style.css',
4+
map: {
5+
inline: false,
6+
annotation: false,
7+
sourcesContent: true,
8+
},
9+
plugins: [
10+
['postcss-short', { prefix: 'x' }]
11+
]
12+
};

test/postcssOptins.test.js

+26-14
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
} from './helpers';
88

99
describe('"postcssOptions" option', () => {
10-
it('should work with "from", "to" and "map" options', async () => {
10+
it('should work with "from", "to" and "map" options (absolute paths)', async () => {
1111
const compiler = getCompiler('./css/index.js', {
1212
postcssOptions: {
1313
from: '/test/from.css',
@@ -16,25 +16,37 @@ describe('"postcssOptions" option', () => {
1616
},
1717
});
1818
const stats = await compile(compiler);
19-
2019
const codeFromBundle = getCodeFromBundle('style.css', stats);
21-
const notNormalizecodeFromBundle = getCodeFromBundle(
22-
'style.css',
23-
stats,
24-
false
25-
);
26-
27-
const toIsWork = notNormalizecodeFromBundle.sourceMap.file.endsWith(
28-
'to.css'
29-
);
20+
const toIsWork = codeFromBundle.sourceMap.file.endsWith('to.css');
3021
const fromIsWork =
31-
notNormalizecodeFromBundle.sourceMap.sources.filter((i) =>
32-
i.endsWith('from.css')
33-
).length > 0;
22+
codeFromBundle.sourceMap.sources.filter((i) => i.endsWith('from.css'))
23+
.length > 0;
3424

3525
expect(toIsWork).toBe(true);
3626
expect(fromIsWork).toBe(true);
27+
expect(codeFromBundle.css).toMatchSnapshot('css');
28+
expect(codeFromBundle.map).toMatchSnapshot('map');
29+
expect(getWarnings(stats)).toMatchSnapshot('warnings');
30+
expect(getErrors(stats)).toMatchSnapshot('errors');
31+
});
32+
33+
it('should work with "from", "to" and "map" options (relative paths)', async () => {
34+
const compiler = getCompiler('./css/index.js', {
35+
postcssOptions: {
36+
from: './css/style.css',
37+
to: './css/style.css',
38+
map: { inline: false, annotation: false },
39+
},
40+
});
41+
const stats = await compile(compiler);
42+
const codeFromBundle = getCodeFromBundle('style.css', stats);
43+
const toIsWork = codeFromBundle.sourceMap.file.endsWith('style.css');
44+
const fromIsWork =
45+
codeFromBundle.sourceMap.sources.filter((i) => i.endsWith('style.css'))
46+
.length > 0;
3747

48+
expect(toIsWork).toBe(true);
49+
expect(fromIsWork).toBe(true);
3850
expect(codeFromBundle.css).toMatchSnapshot('css');
3951
expect(codeFromBundle.map).toMatchSnapshot('map');
4052
expect(getWarnings(stats)).toMatchSnapshot('warnings');

0 commit comments

Comments
 (0)