Skip to content

Commit

Permalink
feat: Add support for .prettierignore
Browse files Browse the repository at this point in the history
  • Loading branch information
disquisition authored and zimme committed Dec 13, 2017
1 parent f436416 commit 33ec2e4
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 29 deletions.
10 changes: 7 additions & 3 deletions __mocks__/fs.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@ const readFileSync = jest.fn(filePath => {
return '{ "rules": { "semi": "error" } }';
}

if (filePath.indexOf("eslintignore")) {
return "*ignored*\n**/ignored/**\n";
if (filePath.indexOf("eslintignore") >= 0) {
return "**/*eslintignored*\n";
}

if (filePath.indexOf("prettierignore") >= 0) {
return "**/*prettierignored*\n";
} else {
throw new Error("readFileSync mock does nto yet handle ", filePath);
throw new Error("readFileSync mock does not yet handle ", filePath);
}
});

Expand Down
17 changes: 12 additions & 5 deletions __mocks__/glob.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,21 @@ module.exports = jest.fn(function mockGlob(globString, options, callback) {
fredProject("no-change/2.js"),
fredProject("no-change/3.js")
]);
} else if (globString.includes("ignored")) {
} else if (globString.includes("eslintignored")) {
callback(null, [
fredProject("ignored1.js"),
fredProject("ignored2.js"),
fredProject("ignored3.js"),
fredProject("eslintignored1.js"),
fredProject("eslintignored2.js"),
fredProject("eslintignored3.js"),
fredProject("applied4.js")
]);
} else if (globString.includes("no-eslint-ignore")) {
} else if (globString.includes("prettierignored")) {
callback(null, [
fredProject("prettierignored1.js"),
fredProject("prettierignored2.js"),
fredProject("prettierignored3.js"),
fredProject("applied4.js")
]);
} else if (globString.includes("no-ignore")) {
callback(null, [
barneyProject("no-ignore/1.js"),
barneyProject("no-ignore/2.js"),
Expand Down
86 changes: 69 additions & 17 deletions src/format-files.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,14 @@ const LINE_SEPERATOR_REGEX = /(\r|\n|\r\n)/;
const rxGlob = Observable.bindNodeCallback(glob);
const rxReadFile = Observable.bindNodeCallback(fs.readFile);
const rxWriteFile = Observable.bindNodeCallback(fs.writeFile);
const findUpSyncMemoized = memoize(findUpSync, function resolver(...args) {
return args.join("::");
});
const findUpEslintignoreSyncMemoized = memoize(
findUpEslintignoreSync,
findUpMemoizeResolver
);
const findUpPrettierignoreSyncMemoized = memoize(
findUpPrettierignoreSync,
findUpMemoizeResolver
);

const getIsIgnoredMemoized = memoize(getIsIgnored);

Expand All @@ -46,6 +51,7 @@ function formatFilesFromArgv({
prettierPath,
ignore: ignoreGlobs = [],
eslintIgnore: applyEslintIgnore = true,
prettierIgnore: applyPrettierIgnore = true,
eslintConfigPath,
prettierLast,
...prettierOptions
Expand All @@ -71,13 +77,14 @@ function formatFilesFromArgv({
if (stdin) {
return formatStdin({ filePath: stdinFilepath, ...prettierESLintOptions });
} else {
return formatFilesFromGlobs(
return formatFilesFromGlobs({
fileGlobs,
[...ignoreGlobs], // make a copy to avoid manipulation
ignoreGlobs: [...ignoreGlobs], // make a copy to avoid manipulation
cliOptions,
prettierESLintOptions,
applyEslintIgnore
);
applyEslintIgnore,
applyPrettierIgnore
});
}
}

Expand All @@ -97,13 +104,14 @@ async function formatStdin(prettierESLintOptions) {
}
}

function formatFilesFromGlobs(
function formatFilesFromGlobs({
fileGlobs,
ignoreGlobs,
cliOptions,
prettierESLintOptions,
applyEslintIgnore
) {
applyEslintIgnore,
applyPrettierIgnore
}) {
const concurrentGlobs = 3;
const concurrentFormats = 10;
return new Promise(resolve => {
Expand All @@ -112,7 +120,12 @@ function formatFilesFromGlobs(
const unchanged = [];
Observable.from(fileGlobs)
.mergeMap(
getFilesFromGlob.bind(null, ignoreGlobs, applyEslintIgnore),
getFilesFromGlob.bind(
null,
ignoreGlobs,
applyEslintIgnore,
applyPrettierIgnore
),
null,
concurrentGlobs
)
Expand Down Expand Up @@ -184,7 +197,12 @@ function formatFilesFromGlobs(
});
}

function getFilesFromGlob(ignoreGlobs, applyEslintIgnore, fileGlob) {
function getFilesFromGlob(
ignoreGlobs,
applyEslintIgnore,
applyPrettierIgnore,
fileGlob
) {
const globOptions = { ignore: ignoreGlobs };
if (!fileGlob.includes("node_modules")) {
// basically, we're going to protect you from doing something
Expand All @@ -193,9 +211,15 @@ function getFilesFromGlob(ignoreGlobs, applyEslintIgnore, fileGlob) {
}
return rxGlob(fileGlob, globOptions).map(filePaths => {
return filePaths.filter(filePath => {
return applyEslintIgnore
? !isFilePathMatchedByEslintignore(filePath)
: true;
if (applyEslintIgnore && isFilePathMatchedByEslintignore(filePath)) {
return false;
}

if (applyPrettierIgnore && isFilePathMatchedByPrettierignore(filePath)) {
return false;
}

return true;
});
});
}
Expand Down Expand Up @@ -243,7 +267,7 @@ function formatFile(filePath, prettierESLintOptions, cliOptions) {

function getNearestEslintignorePath(filePath) {
const { dir } = path.parse(filePath);
return findUpSyncMemoized(".eslintignore", dir);
return findUpEslintignoreSyncMemoized(".eslintignore", dir);
}

function isFilePathMatchedByEslintignore(filePath) {
Expand All @@ -261,10 +285,38 @@ function isFilePathMatchedByEslintignore(filePath) {
return isIgnored(filePathRelativeToEslintignoreDir);
}

function findUpSync(filename, cwd) {
function getNearestPrettierignorePath(filePath) {
const { dir } = path.parse(filePath);
return findUpPrettierignoreSyncMemoized(".prettierignore", dir);
}

function isFilePathMatchedByPrettierignore(filePath) {
const prettierignorePath = getNearestPrettierignorePath(filePath);
if (!prettierignorePath) {
return false;
}

const prettierignoreDir = path.parse(prettierignorePath).dir;
const filePathRelativeToPrettierignoreDir = path.relative(
prettierignoreDir,
filePath
);
const isIgnored = getIsIgnoredMemoized(prettierignorePath);
return isIgnored(filePathRelativeToPrettierignoreDir);
}

function findUpMemoizeResolver(...args) {
return args.join("::");
}

function findUpEslintignoreSync(filename, cwd) {
return findUp.sync(".eslintignore", { cwd });
}

function findUpPrettierignoreSync(filename, cwd) {
return findUp.sync(".prettierignore", { cwd });
}

function getIsIgnored(filename) {
const ignoreLines = fs
.readFileSync(filename, "utf8")
Expand Down
38 changes: 34 additions & 4 deletions src/format-files.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ test("allows you to specify an ignore glob", async () => {
});

test("wont modify a file if it is eslint ignored", async () => {
await formatFiles({ _: ["src/**/ignored*.js"], write: true });
await formatFiles({ _: ["src/**/eslintignored*.js"], write: true });
expect(fsMock.readFile).toHaveBeenCalledTimes(1);
expect(fsMock.writeFile).toHaveBeenCalledTimes(1);
expect(fsMock.readFile).toHaveBeenCalledWith(
Expand All @@ -213,7 +213,7 @@ test("wont modify a file if it is eslint ignored", async () => {

test("will modify a file if it is eslint ignored with noIgnore", async () => {
await formatFiles({
_: ["src/**/ignored*.js"],
_: ["src/**/eslintignored*.js"],
write: true,
eslintIgnore: false
});
Expand All @@ -223,12 +223,42 @@ test("will modify a file if it is eslint ignored with noIgnore", async () => {
expect(console.error).toHaveBeenCalledWith(ignoredOutput);
});

test("will not blow up if an .eslintignore cannot be found", async () => {
test("wont modify a file if it is prettier ignored", async () => {
await formatFiles({ _: ["src/**/prettierignored*.js"], write: true });
expect(fsMock.readFile).toHaveBeenCalledTimes(1);
expect(fsMock.writeFile).toHaveBeenCalledTimes(1);
expect(fsMock.readFile).toHaveBeenCalledWith(
expect.stringMatching(/applied/),
"utf8",
expect.any(Function)
);
expect(fsMock.writeFile).toHaveBeenCalledWith(
expect.stringMatching(/applied/),
expect.stringMatching(/MOCK_OUTPUT.*?applied/),
expect.any(Function)
);
const ignoredOutput = expect.stringMatching(/success.*1.*file/);
expect(console.error).toHaveBeenCalledWith(ignoredOutput);
});

test("will modify a file if it is prettier ignored with noIgnore", async () => {
await formatFiles({
_: ["src/**/prettierignored*.js"],
write: true,
prettierIgnore: false
});
expect(fsMock.readFile).toHaveBeenCalledTimes(4);
expect(fsMock.writeFile).toHaveBeenCalledTimes(4);
const ignoredOutput = expect.stringMatching(/success.*4.*files/);
expect(console.error).toHaveBeenCalledWith(ignoredOutput);
});

test("will not blow up if an .eslintignore or .prettierignore cannot be found", async () => {
const originalSync = findUpMock.sync;
findUpMock.sync = () => null;
try {
await formatFiles({
_: ["src/**/no-eslint-ignore/*.js"],
_: ["src/**/no-ignore/*.js"],
write: true
});
} catch (error) {
Expand Down
9 changes: 9 additions & 0 deletions src/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@ const parser = yargs
(can use --no-eslint-ignore to disable this)
`
},
"prettier-ignore": {
default: true,
type: "boolean",
describe: oneLine`
Only format matching files even if
they are not ignored by .prettierignore.
(can use --no-prettier-ignore to disable this)
`
},
"list-different": {
default: false,
type: "boolean",
Expand Down

0 comments on commit 33ec2e4

Please sign in to comment.