Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for prettierIgnore key in package.json #12672

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
37 changes: 37 additions & 0 deletions changelog_unreleased/cli/12672.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#### Add support for `prettierIgnore` key in `package.json` (#12672 by @mataha)

```json
{
"name": "pretty-package",
"version": "0.0.1",
"prettier": {
"semi": true,
"singleQuote": true,
"trailingComma": "all"
},
"prettierIgnore": ["dirty-file.js", "another-dirty-file.js"]
}
```

```console
# stable
$ ls -1 --color=never *.js
another-dirty-file.js
dirty-file.js
yet-another-dirty-file.js
$ prettier *.js --check
[warn] another-dirty-file.js
[warn] dirty-file.js
[warn] yet-another-dirty-file.js
[warn] Code style issues found in the above file(s). Forgot to run Prettier?


# main
$ ls -1 --color=never *.js
another-dirty-file.js
dirty-file.js
yet-another-dirty-file.js
$ prettier *.js --check
[warn] yet-another-dirty-file.js
[warn] Code style issues found in the above file(s). Forgot to run Prettier?
```
19 changes: 18 additions & 1 deletion docs/ignore.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ id: ignore
title: Ignoring Code
---

Use `.prettierignore` to ignore (i.e. not reformat) certain files and folders completely.
Use `.prettierignore` or a `prettierIgnore` key to ignore (i.e. not reformat) certain files and folders completely.

Use “prettier-ignore” comments to ignore parts of files.

Expand Down Expand Up @@ -47,6 +47,23 @@ if [`--with-node-modules` CLI option](cli.md#--with-node-modules) provided

(See also the [`--ignore-path` CLI option](cli.md#--ignore-path).)

## Ignoring Files: prettierIgnore key

If Prettier fails to find a `.prettierignore` file and an alternate file is not specified via `--ignore-path`, a `prettierIgnore` key in package.json will be checked for files to ignore instead:

```json
{
"name": "pretty-package",
"version": "0.0.1",
"prettier": {
"semi": true,
"singleQuote": true,
"trailingComma": "all"
},
"prettierIgnore": ["dirty-file.js", "another-dirty-file.js"]
}
```

## JavaScript

A JavaScript comment of `// prettier-ignore` will exclude the next node in the abstract syntax tree from formatting.
Expand Down
66 changes: 54 additions & 12 deletions src/utils/ignore.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,46 @@ import path from "node:path";
import url from "node:url";
import { isUrl, toPath } from "url-or-path";
import ignoreModule from "ignore";
import mockable from "../common/mockable.js";
import readFile from "../utils/read-file.js";

const { lilconfig } = mockable;

const createExplorer = lilconfig("prettierignore", {
packageProp: "prettierIgnore",
searchPlaces: ["package.json"],
transform(result) {
if (!result?.config) {
return result;
}

const { config, filepath } = result;

if (
!(
Array.isArray(config) &&
config.every((entry) => typeof entry === "string")
)
) {
if (typeof config === "string") {
result.config = [config];
} else {
throw new TypeError(
"File list is only allowed to be an array of strings, " +
`but received ${typeof config} in "${filepath}"`,
);
}
}

return result;
},
});

const createIgnore = ignoreModule.default;

/** @type {(file: string | URL) => Promise<import('lilconfig').LilconfigResult>} */
const search = (file) => createExplorer.search(toResolvedPath(file));

/** @type {(filePath: string) => string} */
const slash =
path.sep === "\\"
Expand All @@ -13,15 +50,23 @@ const slash =

/**
* @param {string | URL} file
* @param {string | URL | undefined} ignoreFile
* @returns {string}
*/
function getRelativePath(file, ignoreFile) {
const ignoreFilePath = toPath(ignoreFile);
const filePath = isUrl(file)
function toResolvedPath(file) {
return isUrl(file)
? url.fileURLToPath(file)
: // @ts-expect-error -- URLs handled by `isUrl`
path.resolve(file);
}

/**
* @param {string | URL} file
* @param {string | URL | undefined} ignoreFile
* @returns {string}
*/
function getRelativePath(file, ignoreFile) {
const filePath = toResolvedPath(file);
const ignoreFilePath = toPath(ignoreFile);

return path.relative(
// If there's an ignore-path set, the filename must be relative to the
Expand All @@ -34,7 +79,7 @@ function getRelativePath(file, ignoreFile) {
/**
* @param {string | URL | undefined} ignoreFile
* @param {boolean} [withNodeModules]
* @returns {Promise<(file: string | URL) => boolean>}
* @returns {Promise<(file: string | URL) => Promise<boolean>>}
*/
async function createSingleIsIgnoredFunction(ignoreFile, withNodeModules) {
let content = "";
Expand All @@ -47,13 +92,10 @@ async function createSingleIsIgnoredFunction(ignoreFile, withNodeModules) {
content += "\n" + "node_modules";
}

if (!content) {
return;
}

const ignore = createIgnore({ allowRelativePaths: true }).add(content);

return (file) => ignore.ignores(slash(getRelativePath(file, ignoreFile)));
return async (file) =>
createIgnore({ allowRelativePaths: true })
.add(content || (await search(file)).config)
.ignores(slash(getRelativePath(file, ignoreFile)));
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`ignore file when using --debug-check (write) 1`] = `Array []`;

exports[`outputs files as-is if no --write (write) 1`] = `Array []`;

exports[`support prettierIgnore key in package.json (write) 1`] = `Array []`;
25 changes: 25 additions & 0 deletions tests/integration/__tests__/ignore-package-json.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
describe("support prettierIgnore key in package.json", () => {
runCli("cli/ignore-package-json", ["**/*.js", "-l"]).test({
status: 1,
stdout: "not-ignored.js\n",
stderr: "",
});
});

describe("ignore file when using --debug-check", () => {
runCli("cli/ignore-package-json", ["**/*.js", "--debug-check"]).test({
status: 0,
stdout: "not-ignored.js\n",
stderr: "",
});
});

describe("outputs files as-is if no --write", () => {
runCli("cli/ignore-package-json", ["ignored.js"], {
ignoreLineEndings: true,
}).test({
status: 0,
stdout: "'use strict';\n",
stderr: "",
});
});
1 change: 1 addition & 0 deletions tests/integration/cli/ignore-package-json/ignored.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
'use strict';
1 change: 1 addition & 0 deletions tests/integration/cli/ignore-package-json/not-ignored.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
'use strict';
6 changes: 6 additions & 0 deletions tests/integration/cli/ignore-package-json/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "ignore-package",
"version": "0.0.1",
"private": true,
"prettierIgnore": ["ignored.js"]
}
1 change: 1 addition & 0 deletions tests/integration/cli/ignore-path/other-regular-modules.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
'use strict';