Skip to content

Commit 833f56b

Browse files
shlykaiAlexey Shlyk
authored andcommitted
feat: search the package.json file in the current and parent directories
1 parent eac5f85 commit 833f56b

File tree

3 files changed

+32
-17
lines changed

3 files changed

+32
-17
lines changed

src/index.js

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,11 @@ import {
1414
normalizeSourceMap,
1515
normalizeSourceMapAfterPostcss,
1616
parsePackageJson,
17-
isFileExists,
17+
findPackageJsonDir,
1818
} from "./utils";
1919

2020
let hasExplicitDependencyOnPostCSS = false;
21-
22-
const PACKAGE_JSON_PATH = path.resolve(process.cwd(), "package.json");
21+
let packageJsonDir;
2322

2423
/**
2524
* **PostCSS Loader**
@@ -109,15 +108,22 @@ export default async function loader(content, sourceMap, meta) {
109108
processOptions
110109
);
111110
} 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+
}
112117
// Check postcss versions to avoid using PostCSS 7.
113118
// For caching reasons, we use the readFileSync and existsSync functions from the context,
114119
// not the functions from the `fs` module.
115120
if (
116121
!hasExplicitDependencyOnPostCSS &&
117122
postcssFactory().version.startsWith("7.") &&
118-
isFileExists(PACKAGE_JSON_PATH, this.fs.statSync)
123+
packageJsonDir
119124
) {
120-
const pkg = parsePackageJson(PACKAGE_JSON_PATH, this.fs.readFileSync);
125+
const filePath = path.resolve(packageJsonDir, "package.json");
126+
const pkg = parsePackageJson(filePath, this.fs.readFileSync);
121127
if (!pkg.dependencies.postcss && !pkg.devDependencies.postcss) {
122128
this.emitWarning(
123129
"Add postcss as project dependency. postcss is not a peer dependency for postcss-loader. " +

src/utils.js

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

411-
function isFileExists(filePath, statSync) {
412-
try {
413-
return statSync(filePath).isFile();
414-
} catch (error) {
415-
return false;
416-
}
417-
}
418-
419411
function parsePackageJson(filePath, readFileSync) {
420412
return JSON.parse(readFileSync(filePath, "utf8"));
421413
}
422414

415+
function findPackageJsonDir(cwd, statSync) {
416+
let dir = cwd;
417+
for (;;) {
418+
try {
419+
if (statSync(path.join(dir, "package.json")).isFile()) break;
420+
// eslint-disable-next-line no-empty
421+
} catch (error) {}
422+
const parent = path.dirname(dir);
423+
if (dir === parent) {
424+
dir = null;
425+
break;
426+
}
427+
dir = parent;
428+
}
429+
return dir;
430+
}
431+
423432
export {
424433
loadConfig,
425434
getPostcssOptions,
426435
exec,
427436
normalizeSourceMap,
428437
normalizeSourceMapAfterPostcss,
429438
parsePackageJson,
430-
isFileExists,
439+
findPackageJsonDir,
431440
};

test/loader.test.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ describe("check postcss versions to avoid using PostCSS 7", async () => {
224224
expect(getWarnings(stats)).toMatchSnapshot("warnings");
225225
});
226226

227-
it("disable checking when postcss version is explicitly defined", async () => {
227+
it("should not show a warning if postcss version is explicitly defined", async () => {
228228
jest.spyOn(utils, "parsePackageJson").mockReturnValue({
229229
dependencies: {},
230230
devDependencies: { postcss: "8.0.0" },
@@ -233,8 +233,8 @@ describe("check postcss versions to avoid using PostCSS 7", async () => {
233233
expect(stats.compilation.warnings.length).toBe(0);
234234
});
235235

236-
it("disable checking when package.json doesn't exist", async () => {
237-
jest.spyOn(utils, "isFileExists").mockReturnValue(false);
236+
it("should not show a warning if the package.json file was not found", async () => {
237+
jest.spyOn(utils, "findPackageJsonDir").mockReturnValue(null);
238238
jest.spyOn(utils, "parsePackageJson").mockReturnValue({
239239
dependencies: {},
240240
devDependencies: { postcss: "8.0.0" },

0 commit comments

Comments
 (0)