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

Proposal: Filter using ".gitignore" first, then ".prettierignore" second #8506

Closed
octogonz opened this issue Jun 5, 2020 · 20 comments
Closed
Labels
area:cli Issues with Prettier's Command Line Interface area:ignore .prettierignore file, --ignore-path CLI option, /* prettier-ignore */ comments and so on locked-due-to-inactivity Please open a new issue and fill out the template instead of commenting. status:needs discussion Issues needing discussion and a decision to be made before action can be taken

Comments

@octogonz
Copy link

octogonz commented Jun 5, 2020

  • Prettier Version: 2.0.5
  • Running Prettier via: CLI
  • Runtime: Node.js v12
  • Operating System:Windows

Steps to reproduce:

From the root of my repo:

$ prettier -c .

Expected behavior:

Prettier should process all files with relevant file extensions, but it should ignore the patterns from .gitignore. In other words, ignore the build outputs. It absolutely does not make sense, by default, to reformat build outputs.

Actual behavior:

prettier -c . formats source files AND build outputs.

People will tell you to use .prettierignore to fix that. But the patterns I find myself writing there are the exact same patterns from .gitignore, which may be a complicated file in some repos.

How did nobody notice this?

From what I can tell (see #6280 for some early research), most Prettier users do not run into this problem. There are a couple reasons why:

  1. Nobody uses the Prettier CLI for everyday formatting. Instead they use a wrapper such as lint-staged that already applies .gitignore filtering.

  2. Well hold up -- what about the VS Code extension that reformats files whenever you save? For that case, people simply don't edit the ignored files very much.

These factors make the problem less noticeable. However (unless I'm misunderstanding something) the current design is nonetheless a bit misguided.

Proposed Solution

Work item 1: The --ignore-path setting needs to be specifiable by .prettierrc file. This setting does not much sense as a CLI parameter. Prettier gets invoked in many ways (lint-staged, VS Code extension, Webstorm extension, etc), and all these tools must agree about the --ignore-path.

Work item 2: The --ignore-path setting should be an array. The files in the array are all considered, and applied one after the other. This allows incremental refinements.

To "opt-in" to the improved behavior, I can now write this:

.prettierrc.json

{
  "lineWidth": 100,
  "ignorePath": [ ".gitignore", ".prettierignore" ]
}

This way, Prettier will apply .gitignore first, then .prettierignore only needs to include incremental adjustments. In most cases .prettierignore can be omitted entirely.

Work item 3: In some future release, [ ".gitignore", ".prettierignore" ] should become the default for the ignorePath setting.

@Vadorequest
Copy link

Currently, setting up prettier forced me to carefully report most of my .gitignore rules to .prettierignore, because there are small (but important) differences between both.

Having such a workflow [ ".gitignore", ".prettierignore" ] would make a lot of sense, ease configuration/adoption and increase maintainability of the prettier config.

@kachkaev
Copy link
Member

kachkaev commented Jun 6, 2020

There can be several problems with this solution. Eg. if you are inheriting the config, will the paths be relative to the original config itself or to the app’s .prettierigore? What should happen to config autodiscovery if that option is present and you are running prettier from a sub-folder? How to resolve patterns in ignore files that are not in the same folder as prettierrc.json?

My current solution is the same for prettier, eslint and markdownlit. In essence, all .xyzignore files have the following structure:

## extensions
*.*
LICENSE
!*.js
!*.json
!*.md
!*.ts
!*.tsx
!*.yml

## special cases
!/.github/

## same as in .gitignore
# ...

Example:

.gitignore

.eslintignore .markdownlintignore .prettierignore
package.json (see scripts and lint-staged hooks)

Yes, there is stuff to copy from .gitignore to all other .xyzignorefiles, but this is consistent requirement for all linting tools. Whether the files are in sync can be checked automatically in CI if it is a concern, but what’s important is that there is no added abstraction to think about.

@alexander-akait
Copy link
Member

Why do not allow using prettier --ignore .gitignore --ignore .prettierignore .?

@kachkaev
Copy link
Member

kachkaev commented Jun 7, 2020

@evilebottnawi while several non-standard ignore files can be passed to a CLI, they won’t be fed to the editor extensions. Thus, Prettier will work differently in CI and locally on file save.

@octogonz
Copy link
Author

octogonz commented Jun 7, 2020

[deleted, since the algorithm I initially described was flawed]

@octogonz
Copy link
Author

octogonz commented Jun 7, 2020

There can be several problems with this solution. Eg. if you are inheriting the config, will the paths be relative to the original config itself or to the app’s .prettierignore?

The patterns are always interpreted relative to the folder containing their ignore file. That's how Git works.

If the ignore files are in different folders, the patterns will resolve differently, but the "inheritance" is straightforward, because these patterns simply add/remove items from a subset of file paths to be processed. This combining of ignore files already happens in real life, for example with lint-staged when the Git diff is filtered by .gitignore first, before those file paths are piped to Prettier.

What should happen to config autodiscovery if that option is present and you are running prettier from a sub-folder? How to resolve patterns in ignore files that are not in the same folder as prettierrc.json?

The behavior would be like this [corrected from my original post]:

  1. Start with the set of all file paths under Prettier's working folder.
  2. Apply any .gitignore files. Conceptually, this step reduces the subset of file paths.
  3. Apply any .prettierignore file(s). This step adds/removes items from the subset.

🤔 Hmmm... you have pointed out something I overlooked in the original proposal, though: The .gitignore files are recursively combined from all parent folders, whereas today Prettier does not support this (issue #4081). Today Prettier only supports .prettierignore in the "root" folder. And unfortunately PR #6203 has been open for over a year. 😢

Until then, there are a couple possible approaches:

  • Only consider the "root" folder for both Step 2 and 3. This misinterprets .gitignore, but Prettier's --include option already had that flaw. This is maximally backwards compatible.
  • Properly apply .gitignore files for parent folders in Step 2, but only look for .prettierignore in the "root" folder in Step 3. This is more intuitive, and a step towards the superior future that PR .prettierignore: resolve upwards like .gitignore #6203 will eventually bring.

while several non-standard ignore files can be passed to a CLI, they won’t be fed to the editor extensions. Thus, Prettier will work differently in CI and locally on file save.

+1 This is the core motivation for this issue. The CLI isn't blocking anyone, because the Prettier API makes it very easy to build your own custom CLI that works however you like. Whereas it's not feasible to make your own plugin for every editor. The settings need to be driven by config files so that all these tools can agree on how files get selected.

@thorn0 thorn0 added area:ignore .prettierignore file, --ignore-path CLI option, /* prettier-ignore */ comments and so on status:needs discussion Issues needing discussion and a decision to be made before action can be taken labels Jun 18, 2020
@remcohaszing
Copy link

Another alternative would be to support the include syntax used by the Google Cloud SDK

#!include:.gitignore

See https://cloud.google.com/sdk/gcloud/reference/topic/gcloudignore

I proposed support for this in kaelzhang/node-ignore#58, but the owner suggested opening issues for each related project instead.

The default ignore pattern could be:

#!include:.gitignore
node_modules/

@Vadorequest
Copy link

This #!include:.gitignore is even more flexible, and has the advantage of being explicit instead of implicit.

@blaggacao
Copy link

Slightly related: #8679 (ignore submodules by default)

@blaggacao
Copy link

Similar suggestions:

@remcohaszing Your suggestion just nails it (possible upstream support looks very promising, too!)

Just one flag would have to be changed + docs. Getting such thing merged should be trivial.
It essentially yields

  • apply DRY principle
  • no magic

@pikeas
Copy link

pikeas commented Aug 29, 2020

There is growing support across tooling for a shared .ignore file as well. Precedence should likely be .prettierignore > .ignore > .gitignore.

@coolreader18
Copy link

coolreader18 commented Dec 7, 2020

Something else is that prettier doesn't seem to respect nested gitignore files, so if I have

- a/
  - .gitignore: build/
  - build
  - b/
    - .gitgnore: dist/
    - dist/

prettier doesn't ignore the files in dist, even with --ignore-path .gitignore

@yinonov
Copy link

yinonov commented Feb 11, 2021

Something else is that prettier doesn't seem to respect nested gitignore files, so if I have

- a/
  - .gitignore: build/
  - build
  - b/
    - .gitgnore: dist/
    - dist/

prettier doesn't ignore the files in dist, even with --ignore-path .gitignore

2nd that. any workaround for getting this to apply?

@dietergeerts
Copy link

Hi, is there any progress on this? I'm adding Prettier to an existing project, and there are some rush generated files that needs to be checked in, but ignored by Prettier.

@justingolden21
Copy link

My package.json has

"scripts": {
	"dev": "svelte-kit dev",
	"build": "svelte-kit build",
	"preview": "svelte-kit preview",
	"lint": "prettier --ignore-path .gitignore --ignore-path .prettierignore --check --plugin-search-dir=. . && eslint --ignore-path .gitignore .",
	"format": "prettier --ignore-path .gitignore --ignore-path .prettierignore --write --plugin-search-dir=. .",
},

And when I run npm run lint I still get:

Output:
>npm run lint

> desktop-clock@1.0.4 lint
> prettier --ignore-path .gitignore --ignore-path .prettierignore --check --plugin-search-dir=. . && eslint --ignore-path .gitignore .

Checking formatting...
[warn] .eslintrc.json
[warn] .imgbotconfig
[warn] .netlify\functions-internal\__render.js
[warn] .netlify\package.json
[warn] .prettierrc
[warn] .svelte-kit\build\app.js
[warn] .svelte-kit\build\components\layout.svelte
[warn] .svelte-kit\build\generated\manifest.js
[warn] .svelte-kit\build\generated\root.svelte
[warn] .svelte-kit\build\runtime\service-worker.js
[warn] .svelte-kit\dev\components\layout.svelte
[warn] .svelte-kit\dev\generated\manifest.js
[warn] .svelte-kit\dev\generated\root.svelte
[warn] .svelte-kit\output\client\_app\assets\AnalogClock-dc193618.css
[warn] .svelte-kit\output\client\_app\assets\pages\__layout.svelte-59a2f67c.css
[warn] .svelte-kit\output\client\_app\assets\pages\index.svelte-9837f661.css
[warn] .svelte-kit\output\client\_app\assets\start-464e9d0a.css
[warn] .svelte-kit\output\client\_app\chunks\AnalogClock-7f462656.js
[warn] .svelte-kit\output\client\_app\chunks\settings-ff374313.js
[warn] .svelte-kit\output\client\_app\chunks\stores-b99ec55e.js
[warn] .svelte-kit\output\client\_app\chunks\vendor-5e4dee83.js
[warn] .svelte-kit\output\client\_app\pages\__error.svelte-b9d71d45.js
[warn] .svelte-kit\output\client\_app\pages\__layout.svelte-69c6fb85.js
[warn] .svelte-kit\output\client\_app\pages\index.svelte-c1cf5738.js
[warn] .svelte-kit\output\client\_app\pages\stopwatch.svelte-ec539bac.js
[warn] .svelte-kit\output\client\_app\pages\timers.svelte-47612bcf.js
[warn] .svelte-kit\output\client\_app\pages\worldclock.svelte-0698e47e.js
[warn] .svelte-kit\output\client\_app\start-4cf0731b.js
[warn] .svelte-kit\output\client\service-worker.js
[warn] .svelte-kit\output\manifest.json
[warn] .svelte-kit\output\server\app.js
[warn] build\publish\_app\assets\AnalogClock-dc193618.css
[warn] build\publish\_app\assets\pages\__layout.svelte-59a2f67c.css
[warn] build\publish\_app\assets\start-464e9d0a.css
[warn] build\publish\_app\chunks\AnalogClock-7f462656.js
[warn] build\publish\_app\chunks\settings-ff374313.js
[warn] build\publish\_app\chunks\stores-b99ec55e.js
[warn] build\publish\_app\chunks\vendor-5e4dee83.js
[warn] build\publish\_app\pages\__error.svelte-b9d71d45.js
[warn] build\publish\_app\pages\__layout.svelte-69c6fb85.js
[warn] build\publish\_app\pages\index.svelte-c1cf5738.js
[warn] build\publish\_app\pages\stopwatch.svelte-ec539bac.js
[warn] build\publish\_app\pages\timers.svelte-47612bcf.js
[warn] build\publish\_app\pages\worldclock.svelte-0698e47e.js
[warn] build\publish\_app\start-4cf0731b.js
[warn] build\publish\lang\de_WIP.json
[warn] build\publish\lang\en.json
[warn] build\publish\lang\es_WIP.json
[warn] build\publish\lang\fr_WIP.json
[warn] build\publish\lang\ru_WIP.json
[warn] build\publish\service-worker.js
[warn] jsconfig.json
[warn] package-lock.json
[warn] package.json
[warn] postcss.config.cjs
[warn] README.md
[warn] src\app.html
[warn] src\components\_Clock\AnalogClock.svelte
[warn] src\components\_Clock\BatteryIcon.svelte
[warn] src\components\_Clock\ClockSettings.svelte
[warn] src\components\_Clock\DigitalDisplays.svelte
[warn] src\components\Accordion\_accordion.js
[warn] src\components\Accordion\Accordion.svelte
[warn] src\components\Accordion\AccordionPanel.svelte
[warn] src\components\GoogleAnalytics.svelte
[warn] src\components\Header.svelte
[warn] src\components\Icon.svelte
[warn] src\components\KeyboardShortcuts.svelte
[warn] src\components\Loader.svelte
[warn] src\components\Modal.svelte
[warn] src\components\Nav.svelte
[warn] src\components\settings.js
[warn] src\components\Settings.svelte
[warn] src\components\Tabs\_tabs.js
[warn] src\components\Tabs\Tab.svelte
[warn] src\components\Tabs\TabList.svelte
[warn] src\components\Tabs\TabPanel.svelte
[warn] src\components\Tabs\Tabs.svelte
[warn] src\components\ThemeButtons.svelte
[warn] src\components\Toast\_toast.js
[warn] src\components\Toast\Toast.svelte
[warn] src\components\Toast\Toasts.svelte
[warn] src\components\Toast\toastStore.js
[warn] src\components\Toggle.svelte
[warn] src\css\animatedIcons.css
[warn] src\css\app.postcss
[warn] src\css\scrollbar.css
[warn] src\data\all_locales.js
[warn] src\data\consts.js
[warn] src\data\timezones.js
[warn] src\global.d.ts
[warn] src\hooks.js
[warn] src\routes\__error.svelte
[warn] src\routes\__layout.svelte
[warn] src\routes\index.svelte
[warn] src\routes\manifest.webmanifest.js
[warn] src\routes\stopwatch.svelte
[warn] src\routes\timers.svelte
[warn] src\routes\worldclock.svelte
[warn] src\service-worker.js
[warn] src\themes\classic.js
[warn] src\themes\classicNight.js
[warn] src\themes\default.js
[warn] src\themes\defaultNight.js
[warn] src\util\cast.js
[warn] src\util\install.js
[warn] src\util\localStore.js
[warn] src\util\now.js
[warn] static\lang\de_WIP.json
[warn] static\lang\en.json
[warn] static\lang\es_WIP.json
[warn] static\lang\fr_WIP.json
[warn] static\lang\ru_WIP.json
[warn] svelte.config.js
[warn] tailwind.config.cjs
[warn] Code style issues found in the above file(s). Forgot to run Prettier?

C:\Users\justi\Documents\GitHub\desktopclock>npm run lint

> desktop-clock@1.0.4 lint
> prettier --ignore .gitignore --ignore .prettierignore --check --plugin-search-dir=. . && eslint --ignore-path .gitignore .

[warn] Ignored unknown option --ignore=.gitignore,.prettierignore.
Checking formatting...
[warn] .eslintrc.json
[warn] .imgbotconfig
[warn] .netlify\functions-internal\__render.js
[warn] .netlify\package.json
[warn] .prettierrc
[warn] .svelte-kit\build\app.js
[warn] .svelte-kit\build\components\layout.svelte
[warn] .svelte-kit\build\generated\manifest.js
[warn] .svelte-kit\build\generated\root.svelte
[warn] .svelte-kit\build\runtime\service-worker.js
[warn] .svelte-kit\dev\components\layout.svelte
[warn] .svelte-kit\dev\generated\manifest.js
[warn] .svelte-kit\dev\generated\root.svelte
[warn] .svelte-kit\output\client\_app\assets\AnalogClock-dc193618.css
[warn] .svelte-kit\output\client\_app\assets\pages\__layout.svelte-59a2f67c.css
[warn] .svelte-kit\output\client\_app\assets\pages\index.svelte-9837f661.css
[warn] .svelte-kit\output\client\_app\assets\start-464e9d0a.css
[warn] .svelte-kit\output\client\_app\chunks\AnalogClock-7f462656.js
[warn] .svelte-kit\output\client\_app\chunks\settings-ff374313.js
[warn] .svelte-kit\output\client\_app\chunks\stores-b99ec55e.js
[warn] .svelte-kit\output\client\_app\chunks\vendor-5e4dee83.js
[warn] .svelte-kit\output\client\_app\pages\__error.svelte-b9d71d45.js
[warn] .svelte-kit\output\client\_app\pages\__layout.svelte-69c6fb85.js
[warn] .svelte-kit\output\client\_app\pages\index.svelte-c1cf5738.js
[warn] .svelte-kit\output\client\_app\pages\stopwatch.svelte-ec539bac.js
[warn] .svelte-kit\output\client\_app\pages\timers.svelte-47612bcf.js
[warn] .svelte-kit\output\client\_app\pages\worldclock.svelte-0698e47e.js
[warn] .svelte-kit\output\client\_app\start-4cf0731b.js
[warn] .svelte-kit\output\client\service-worker.js
[warn] .svelte-kit\output\manifest.json
[warn] .svelte-kit\output\server\app.js
[warn] build\publish\_app\assets\AnalogClock-dc193618.css
[warn] build\publish\_app\assets\pages\__layout.svelte-59a2f67c.css
[warn] build\publish\_app\assets\pages\index.svelte-9837f661.css
[warn] build\publish\_app\assets\start-464e9d0a.css
[warn] build\publish\_app\chunks\AnalogClock-7f462656.js
[warn] build\publish\_app\chunks\settings-ff374313.js
[warn] build\publish\_app\chunks\stores-b99ec55e.js
[warn] build\publish\_app\chunks\vendor-5e4dee83.js
[warn] build\publish\_app\pages\__error.svelte-b9d71d45.js
[warn] build\publish\_app\pages\__layout.svelte-69c6fb85.js
[warn] build\publish\_app\pages\index.svelte-c1cf5738.js
[warn] build\publish\_app\pages\stopwatch.svelte-ec539bac.js
[warn] build\publish\_app\pages\timers.svelte-47612bcf.js
[warn] build\publish\_app\pages\worldclock.svelte-0698e47e.js
[warn] build\publish\_app\start-4cf0731b.js
[warn] build\publish\lang\de_WIP.json
[warn] build\publish\lang\en.json
[warn] build\publish\lang\es_WIP.json
[warn] build\publish\lang\fr_WIP.json
[warn] build\publish\lang\ru_WIP.json
[warn] build\publish\service-worker.js
[warn] jsconfig.json
[warn] package-lock.json
[warn] package.json
[warn] postcss.config.cjs
[warn] README.md
[warn] src\app.html
[warn] src\components\_Clock\AnalogClock.svelte
[warn] src\components\_Clock\BatteryIcon.svelte
[warn] src\components\_Clock\ClockSettings.svelte
[warn] src\components\_Clock\DigitalDisplays.svelte
[warn] src\components\Accordion\_accordion.js
[warn] src\components\Accordion\Accordion.svelte
[warn] src\components\Accordion\AccordionPanel.svelte
[warn] src\components\GoogleAnalytics.svelte
[warn] src\components\Header.svelte
[warn] src\components\Icon.svelte
[warn] src\components\KeyboardShortcuts.svelte
[warn] src\components\Loader.svelte
[warn] src\components\Modal.svelte
[warn] src\components\Nav.svelte
[warn] src\components\settings.js
[warn] src\components\Settings.svelte
[warn] src\components\Tabs\_tabs.js
[warn] src\components\Tabs\Tab.svelte
[warn] src\components\Tabs\TabList.svelte
[warn] src\components\Tabs\TabPanel.svelte
[warn] src\components\Tabs\Tabs.svelte
[warn] src\components\ThemeButtons.svelte
[warn] src\components\Toast\_toast.js
[warn] src\components\Toast\Toast.svelte
[warn] src\components\Toast\Toasts.svelte
[warn] src\components\Toast\toastStore.js
[warn] src\components\Toggle.svelte
[warn] src\css\animatedIcons.css
[warn] src\css\app.postcss
[warn] src\css\scrollbar.css
[warn] src\data\all_locales.js
[warn] src\data\consts.js
[warn] src\data\timezones.js
[warn] src\global.d.ts
[warn] src\hooks.js
[warn] src\routes\__error.svelte
[warn] src\routes\__layout.svelte
[warn] src\routes\index.svelte
[warn] src\routes\manifest.webmanifest.js
[warn] src\routes\stopwatch.svelte
[warn] src\routes\timers.svelte
[warn] src\routes\worldclock.svelte
[warn] src\service-worker.js
[warn] src\themes\classic.js
[warn] src\themes\classicNight.js
[warn] src\themes\default.js
[warn] src\themes\defaultNight.js
[warn] src\util\cast.js
[warn] src\util\install.js
[warn] src\util\localStore.js
[warn] src\util\now.js
[warn] static\lang\de_WIP.json
[warn] static\lang\en.json
[warn] static\lang\es_WIP.json
[warn] static\lang\fr_WIP.json
[warn] static\lang\ru_WIP.json
[warn] svelte.config.js
[warn] tailwind.config.cjs
[warn] Code style issues found in the above file(s). Forgot to run Prettier?

This is my .prettierignore:

src/js/lib

And this is my .gitignore:

.DS_Store
node_modules
/build
/.svelte-kit
/package
/.netlify

But these files are still searched anyways.

I tried replacing --ignore-path with --ignore as mentioned above but no dice.

@fisker
Copy link
Member

fisker commented Apr 24, 2022

We can add multiple ignore files support as suggested in #8506 (comment)

Closing this in favor of #8048.

@fisker fisker closed this as completed Apr 24, 2022
@coolreader18

This comment was marked as outdated.

@fisker

This comment was marked as outdated.

@babakfp
Copy link

babakfp commented Mar 4, 2023

We can add multiple ignore files support as suggested in #8506 (comment)

Closing this in favor of #8048.

But the editor isn't going to see that!

mrm007 added a commit to seek-oss/braid-design-system that referenced this issue Mar 17, 2023
there's no (simple) way to merge `.prettierignore` with`.gitignore` prettier/prettier#8506
@rmartine-ias
Copy link

@babakfp see #8192

@github-actions github-actions bot added the locked-due-to-inactivity Please open a new issue and fill out the template instead of commenting. label Nov 25, 2023
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 25, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area:cli Issues with Prettier's Command Line Interface area:ignore .prettierignore file, --ignore-path CLI option, /* prettier-ignore */ comments and so on locked-due-to-inactivity Please open a new issue and fill out the template instead of commenting. status:needs discussion Issues needing discussion and a decision to be made before action can be taken
Projects
None yet
Development

No branches or pull requests