Skip to content

Commit f318a0c

Browse files
refactor: code
1 parent 342043e commit f318a0c

File tree

7 files changed

+203
-59
lines changed

7 files changed

+203
-59
lines changed

src/index.js

Lines changed: 47 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,10 @@ import {
1313
exec,
1414
normalizeSourceMap,
1515
normalizeSourceMapAfterPostcss,
16-
parsePackageJson,
17-
findPackageJsonDir,
16+
findPackageJSONDir,
1817
} from "./utils";
1918

2019
let hasExplicitDependencyOnPostCSS = false;
21-
let packageJsonDir;
2220

2321
/**
2422
* **PostCSS Loader**
@@ -101,36 +99,58 @@ export default async function loader(content, sourceMap, meta) {
10199
}
102100

103101
let result;
102+
let processor;
104103

105104
try {
106-
result = await postcssFactory(plugins).process(
107-
root || content,
108-
processOptions
109-
);
105+
processor = postcssFactory(plugins);
106+
result = await processor.process(root || content, processOptions);
110107
} catch (error) {
111-
// The `findPackageJsonDir` function returns `string` or `null`.
112-
// This is used to do for caching, that is, an explicit comparison with `undefined`
113-
// is used to make the condition body run once.
114-
if (packageJsonDir === undefined) {
115-
packageJsonDir = findPackageJsonDir(process.cwd(), this.fs.statSync);
116-
}
117108
// Check postcss versions to avoid using PostCSS 7.
118109
// For caching reasons, we use the readFileSync and existsSync functions from the context,
119110
// not the functions from the `fs` module.
120-
if (
121-
!hasExplicitDependencyOnPostCSS &&
122-
postcssFactory().version.startsWith("7.") &&
123-
packageJsonDir
124-
) {
125-
const filePath = path.resolve(packageJsonDir, "package.json");
126-
const pkg = parsePackageJson(filePath, this.fs.readFileSync);
127-
if (!pkg.dependencies.postcss && !pkg.devDependencies.postcss) {
128-
this.emitWarning(
129-
"Add postcss as project dependency. postcss is not a peer dependency for postcss-loader. " +
130-
"Use `npm install postcss` or `yarn add postcss`"
131-
);
132-
} else {
133-
hasExplicitDependencyOnPostCSS = true;
111+
if (!hasExplicitDependencyOnPostCSS && processor.version.startsWith("7.")) {
112+
// The `findPackageJsonDir` function returns `string` or `null`.
113+
// This is used to do for caching, that is, an explicit comparison with `undefined`
114+
// is used to make the condition body run once.
115+
const packageJSONDir = findPackageJSONDir(
116+
process.cwd(),
117+
this.fs.statSync
118+
);
119+
120+
if (packageJSONDir) {
121+
let bufferOfPackageJSON;
122+
123+
try {
124+
bufferOfPackageJSON = this.fs.readFileSync(
125+
path.resolve(packageJSONDir, "package.json"),
126+
"utf8"
127+
);
128+
} catch (_error) {
129+
// Nothing
130+
}
131+
132+
if (bufferOfPackageJSON) {
133+
let pkg;
134+
135+
try {
136+
pkg = JSON.parse(bufferOfPackageJSON);
137+
} catch (_error) {
138+
// Nothing
139+
}
140+
141+
if (pkg) {
142+
if (!pkg.dependencies.postcss && !pkg.devDependencies.postcss) {
143+
this.emitWarning(
144+
new Error(
145+
"Add postcss as project dependency. postcss is not a peer dependency for postcss-loader. " +
146+
"Use `npm install postcss` or `yarn add postcss`"
147+
)
148+
);
149+
} else {
150+
hasExplicitDependencyOnPostCSS = true;
151+
}
152+
}
153+
}
134154
}
135155
}
136156

src/utils.js

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -408,24 +408,28 @@ function normalizeSourceMapAfterPostcss(map, resourceContext) {
408408
return newMap;
409409
}
410410

411-
function parsePackageJson(filePath, readFileSync) {
412-
return JSON.parse(readFileSync(filePath, "utf8"));
413-
}
414-
415-
function findPackageJsonDir(cwd, statSync) {
411+
function findPackageJSONDir(cwd, statSync) {
416412
let dir = cwd;
413+
417414
for (;;) {
418415
try {
419-
if (statSync(path.join(dir, "package.json")).isFile()) break;
420-
// eslint-disable-next-line no-empty
421-
} catch (error) {}
416+
if (statSync(path.join(dir, "package.json")).isFile()) {
417+
break;
418+
}
419+
} catch (error) {
420+
// Nothing
421+
}
422+
422423
const parent = path.dirname(dir);
424+
423425
if (dir === parent) {
424426
dir = null;
425427
break;
426428
}
429+
427430
dir = parent;
428431
}
432+
429433
return dir;
430434
}
431435

@@ -435,6 +439,5 @@ export {
435439
exec,
436440
normalizeSourceMap,
437441
normalizeSourceMapAfterPostcss,
438-
parsePackageJson,
439-
findPackageJsonDir,
442+
findPackageJSONDir,
440443
};

test/__snapshots__/loader.test.js.snap

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,54 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3+
exports[`check postcss versions to avoid using PostCSS 7 should emit a warning if postcss version is not explicitly specified when the loader is failed: errors 1`] = `
4+
Array [
5+
"ModuleBuildError: Module build failed (from \`replaced original path\`):
6+
Error: Something went wrong.
7+
at Processor.process (/test/loader.test.js:216:26)
8+
at Object.loader (/src/index.js:106:30)",
9+
]
10+
`;
11+
312
exports[`check postcss versions to avoid using PostCSS 7 should emit a warning if postcss version is not explicitly specified when the loader is failed: warnings 1`] = `
413
Array [
514
"ModuleWarning: Module Warning (from \`replaced original path\`):
6-
(Emitted value instead of an instance of Error) Add postcss as project dependency. postcss is not a peer dependency for postcss-loader. Use \`npm install postcss\` or \`yarn add postcss\`",
15+
Add postcss as project dependency. postcss is not a peer dependency for postcss-loader. Use \`npm install postcss\` or \`yarn add postcss\`",
16+
]
17+
`;
18+
19+
exports[`check postcss versions to avoid using PostCSS 7 should not show a warning if 'package.json' file was not found: errors 1`] = `
20+
Array [
21+
"ModuleBuildError: Module build failed (from \`replaced original path\`):
22+
Error: Something went wrong.
23+
at Processor.process (/test/loader.test.js:294:28)
24+
at Object.loader (/src/index.js:106:30)",
725
]
826
`;
927

28+
exports[`check postcss versions to avoid using PostCSS 7 should not show a warning if 'package.json' file was not found: warnings 1`] = `Array []`;
29+
30+
exports[`check postcss versions to avoid using PostCSS 7 should not show a warning if 'postcss' version is explicitly defined in 'dependencies': errors 1`] = `
31+
Array [
32+
"ModuleBuildError: Module build failed (from \`replaced original path\`):
33+
Error: Something went wrong.
34+
at Processor.process (/test/loader.test.js:242:26)
35+
at Object.loader (/src/index.js:106:30)",
36+
]
37+
`;
38+
39+
exports[`check postcss versions to avoid using PostCSS 7 should not show a warning if 'postcss' version is explicitly defined in 'dependencies': warnings 1`] = `Array []`;
40+
41+
exports[`check postcss versions to avoid using PostCSS 7 should not show a warning if 'postcss' version is explicitly defined in 'devDependencies': errors 1`] = `
42+
Array [
43+
"ModuleBuildError: Module build failed (from \`replaced original path\`):
44+
Error: Something went wrong.
45+
at Processor.process (/test/loader.test.js:268:28)
46+
at Object.loader (/src/index.js:106:30)",
47+
]
48+
`;
49+
50+
exports[`check postcss versions to avoid using PostCSS 7 should not show a warning if 'postcss' version is explicitly defined in 'devDependencies': warnings 1`] = `Array []`;
51+
1052
exports[`loader should emit asset using the "messages" API: errors 1`] = `Array []`;
1153

1254
exports[`loader should emit asset using the "messages" API: warnings 1`] = `Array []`;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"dependencies": {},
3+
"devDependencies": {}
4+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"dependencies": {
3+
"postcss": "^8.0.0"
4+
},
5+
"devDependencies": {}
6+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"dependencies": {},
3+
"devDependencies": {
4+
"postcss": "^8.0.0"
5+
}
6+
}

test/loader.test.js

Lines changed: 84 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -200,50 +200,113 @@ describe("loader", () => {
200200
});
201201

202202
describe("check postcss versions to avoid using PostCSS 7", () => {
203-
async function getStats() {
203+
it("should emit a warning if postcss version is not explicitly specified when the loader is failed", async () => {
204+
const spy = jest
205+
.spyOn(utils, "findPackageJSONDir")
206+
.mockReturnValue(
207+
path.resolve(__dirname, "./fixtures/package-json-files/no-postcss")
208+
);
209+
204210
const compiler = getCompiler("./css/index.js", {
205211
implementation: (...args) => {
206212
const result = postcss(...args);
213+
207214
result.version = "7.0.0";
208215
result.process = () =>
209216
Promise.reject(new Error("Something went wrong."));
217+
210218
return result;
211219
},
212220
});
221+
const stats = await compile(compiler);
222+
223+
expect(getWarnings(stats)).toMatchSnapshot("warnings");
224+
expect(getErrors(stats)).toMatchSnapshot("errors");
213225

214-
return compile(compiler);
215-
}
226+
spy.mockRestore();
227+
});
216228

217-
it("should emit a warning if postcss version is not explicitly specified when the loader is failed", async () => {
218-
jest
219-
.spyOn(utils, "parsePackageJson")
220-
.mockReturnValue({ dependencies: {}, devDependencies: {} });
229+
it("should not show a warning if 'postcss' version is explicitly defined in 'dependencies'", async () => {
230+
const spy = jest
231+
.spyOn(utils, "findPackageJSONDir")
232+
.mockReturnValue(
233+
path.resolve(
234+
__dirname,
235+
"./fixtures/package-json-files/postcss-v8-in-dependencies"
236+
)
237+
);
238+
239+
const compiler = getCompiler("./css/index.js", {
240+
implementation: (...args) => {
241+
const result = postcss(...args);
221242

222-
const stats = await getStats();
243+
result.version = "7.0.0";
244+
result.process = () =>
245+
Promise.reject(new Error("Something went wrong."));
246+
247+
return result;
248+
},
249+
});
250+
const stats = await compile(compiler);
223251

224252
expect(getWarnings(stats)).toMatchSnapshot("warnings");
253+
expect(getErrors(stats)).toMatchSnapshot("errors");
254+
255+
spy.mockRestore();
225256
});
226257

227-
it("should not show a warning if postcss version is explicitly defined", async () => {
228-
jest.spyOn(utils, "parsePackageJson").mockReturnValue({
229-
dependencies: {},
230-
devDependencies: { postcss: "8.0.0" },
258+
it("should not show a warning if 'postcss' version is explicitly defined in 'devDependencies'", async () => {
259+
const spy = jest
260+
.spyOn(utils, "findPackageJSONDir")
261+
.mockReturnValue(
262+
path.resolve(
263+
__dirname,
264+
"./fixtures/package-json-files/postcss-v8-in-devDependencies"
265+
)
266+
);
267+
268+
const compiler = getCompiler("./css/index.js", {
269+
implementation: (...args) => {
270+
const result = postcss(...args);
271+
272+
result.version = "7.0.0";
273+
result.process = () =>
274+
Promise.reject(new Error("Something went wrong."));
275+
276+
return result;
277+
},
231278
});
279+
const stats = await compile(compiler);
232280

233-
const stats = await getStats();
281+
expect(getWarnings(stats)).toMatchSnapshot("warnings");
282+
expect(getErrors(stats)).toMatchSnapshot("errors");
234283

235-
expect(stats.compilation.warnings.length).toBe(0);
284+
spy.mockRestore();
236285
});
237286

238-
it("should not show a warning if the package.json file was not found", async () => {
239-
jest.spyOn(utils, "findPackageJsonDir").mockReturnValue(null);
240-
jest.spyOn(utils, "parsePackageJson").mockReturnValue({
241-
dependencies: {},
242-
devDependencies: { postcss: "8.0.0" },
287+
it("should not show a warning if 'package.json' file was not found", async () => {
288+
const spy = jest
289+
.spyOn(utils, "findPackageJSONDir")
290+
.mockReturnValue(
291+
path.resolve(__dirname, "./fixtures/package-json-files/unknown")
292+
);
293+
294+
const compiler = getCompiler("./css/index.js", {
295+
implementation: (...args) => {
296+
const result = postcss(...args);
297+
298+
result.version = "7.0.0";
299+
result.process = () =>
300+
Promise.reject(new Error("Something went wrong."));
301+
302+
return result;
303+
},
243304
});
305+
const stats = await compile(compiler);
244306

245-
const stats = await getStats();
307+
expect(getWarnings(stats)).toMatchSnapshot("warnings");
308+
expect(getErrors(stats)).toMatchSnapshot("errors");
246309

247-
expect(stats.compilation.warnings.length).toBe(0);
310+
spy.mockRestore();
248311
});
249312
});

0 commit comments

Comments
 (0)