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

Allow overriding options based on a language #5378

Open
bengry opened this issue Nov 7, 2018 · 26 comments
Open

Allow overriding options based on a language #5378

bengry opened this issue Nov 7, 2018 · 26 comments
Labels
area:multiparser Issues with printing one language inside another, like CSS-in-JS status:needs discussion Issues needing discussion and a decision to be made before action can be taken type:enhancement A potential new feature to be added, or an improvement to how we print something

Comments

@bengry
Copy link

bengry commented Nov 7, 2018

Currently it's only possible to override Prettier options based on a glob pattern, for example:

// .prettierrc
"overrides": [
  {
	"files": ["*.{component,widget}.html"],
	"options": {
	  "parser": "angular",
	  "printWidth": 80
	}
  }
]

However, there are cases where multiple languages "live" in the same file, namely .vue files and Angular components (found in .ts files).

For brevity, I'll focus on Angular components, but the same holds true for Vue, as mentioned above.

// hero-app.component.ts
@Component({
  selector: 'app-root',
  template: `
    <h1>Tour of Heroes</h1>
    <app-hero-main [hero]="hero"></app-hero-main>
  `,
  styles: ['h1 { font-weight: normal; }']
})
export class HeroAppComponent {
/* . . . */
}

For the above file, there can only be one printWidth setting, even though it actually encapsulates (up to) 3 different types of files: typescript, css and html (with the angular parser). Similarly to how .vue files are constructed.

It sometimes makes sense to have different printWidths for different file type (for example, it would make sense to have HTML files shorter in width to force each attribute to its own line, in most cases - though this is another issue on its own, that Prettier doesn't currently address in HTML/Angular/Vue templates/files). This can be done today, based on a glob pattern:

{
	"semi": true,
	"singleQuote": true,
	"trailingComma": "es5",
	"printWidth": 110,
	"useTabs": true,
	"tabWidth": 4,
	"overrides": [
		{
			"files": ["*.{component,widget}.html"],
			"options": {
				"parser": "angular",
				"printWidth": 80
			}
		}
	]
}

I suggest adding another option to the "overrides", similar to the files one, to allow specifying the "type" (for lack of a better name), for which the options would apply. e.g.:

{
	"semi": true,
	"singleQuote": true,
	"trailingComma": "es5",
	"printWidth": 110,
	"useTabs": true,
	"tabWidth": 4,
	"overrides": [
		{
			"files": "*.component.html",
			"types": "angular-template",
			"options": {
				"parser": "angular",
				"printWidth": 80
			}
		}
	]
}
@michaeljota
Copy link

I think this could be actually useful as Prettier is getting support for more and more language, and even files that are parsed by multiple parsers.

There is an issue to rename parser to language, so maybe this could use the same enum as language to override options for that language.

@ikatyang
Copy link
Member

ikatyang commented Nov 8, 2018

I'm not sure if this is possible but I guess we just need to add a new Doc to dynamically set the current printWidth? something like printWidth(110, concat([blah, printWidth(80, blah)])). It should be useful in the markdown codeblock.

@ikatyang ikatyang added type:enhancement A potential new feature to be added, or an improvement to how we print something status:needs discussion Issues needing discussion and a decision to be made before action can be taken labels Nov 8, 2018
@michaeljota
Copy link

I think this would require some work as it needs a new way to pass options to the parser. But I don't think this should be about printWidth only, but also all the other options available.

What is being requested at the end is the ability to set options to a certain language, instead of doing it file based.

@bengry
Copy link
Author

bengry commented Nov 8, 2018

Right, the title doesn't describe the issue to its full extent really. The printWidth is a specific case. There are probably more use cases that would benefit from this though.

@michaeljota
Copy link

Do you mind to update the issue and the title to request a new way to override the options based on a language instead of a file? I think this is what you want to do, isn't it?

@bengry bengry changed the title [Angular] inline templates' printWidth is set by the default one, and cannot be overriden Allow overriding options based on a language Nov 8, 2018
@bengry
Copy link
Author

bengry commented Nov 8, 2018

@michaeljota I updated the title and the issue description to reflect this better.

@michaeljota
Copy link

I would prefer something like this instead:

{
  "singleQuote": true,
  "printWidth": 100,
  "overrides": [
    {
      "languages": ["angular", "html"],
      "options": {
        "printWidth": 80
      }
    }
  ]
}

A property languages that allow an array of languages to override the options declared.

What do you think?

@michaeljota
Copy link

I open another issue to request to ignore formatting based on languages. #5408

@TomCaserta

This comment has been minimized.

@j-f1

This comment has been minimized.

@ikatyang

This comment has been minimized.

@G-Rath
Copy link

G-Rath commented Dec 5, 2019

I'd like to throw my hat into the ring for this one, as it would let you mix styles across languages a lot easier.

For example, I've got css string literals in my .tsx files b/c css-in-js which prettier runs the css parser on. If I want double quotes in my css, and single quotes in my ts files, I can't have prettier apply that to my css-in-js.

If I could just say "when formatting using the css parser, use double quotes" I wouldn't have to worry about it ever again (which is the point of prettier).


I'm happy to take a whack at implementing this, if the team are interested in exploring supporting it, and could provide a pointer on where to look to do the actual implementation :)

@lydell
Copy link
Member

lydell commented Dec 5, 2019

@G-Rath See #7073

@G-Rath
Copy link

G-Rath commented Dec 5, 2019

@lydell ooh that looks exciting.

Would the team be against me making a PR anyway in the meantime, if I found some free time?
That kind of issue strikes me as a big one that might take a while 😬

@thorn0
Copy link
Member

thorn0 commented Jun 3, 2020

Related issues merged into this one:

@Maxim-Mazurok
Copy link

So, we wanted to have the following markdown:

For example:
```json
{
	// ...
	"dependencies": {
		// ...
		"@hot-loader/react-dom": "16.14.0+4.13.0",
		// ...
	},
	// ...
}
```

But comments are not supported by JSON, only by JSON5.

So, we switched to JSON5.
And prettier removed quotes and replaced some with single quotes, because we have "singleQuote": true,

So, I wanted to override JSON5 file format formatting to leave quotes and use double quotes inside of the markdown.

Unfortunately, this is not possible, so we removed comments and replaced json5 with json.

Thought I'd share our use-case. Thanks!

@thorn0
Copy link
Member

thorn0 commented Jan 12, 2021

@Maxim-Mazurok FWIW Prettier does support comments in JSON. playground

@Maxim-Mazurok
Copy link

Maxim-Mazurok commented Jan 12, 2021

@Maxim-Mazurok FWIW Prettier does support comments in JSON. playground

Yeah, I know. I just respect the way GitHub handles it. If it's json - there should be no comments and it makes total sense to me.
So, for the ultimate accuracy sake, we decided to stick to the specs. Just in case if our markdown renderer of choice will ever adopt GitHub's JSON highlighting implementation :)

@thorn0
Copy link
Member

thorn0 commented Jan 12, 2021

Consider marking the code block as jsonc then. It seems to be supported by both Prettier and GitHub.

@Maxim-Mazurok
Copy link

Since the goal is to show part of packages.json file, using anything other than JSON wouldn't be correct. But JSONC is a nice hack, I'll take a note about it, thanks!

@dietergeerts
Copy link

Hi, is there any progress on this one? Linting tools like ESLint can lint code blocks in markdown for example, and now we are getting errors there because Prettier can't rewrite them based on our overrides.

@abdonrd
Copy link

abdonrd commented Jan 10, 2022

Any progress on this? Thanks!

My use case is using singleQuote: true for Javascript and singleQuote: false for CSS.
And both languages live in .js/.ts files.

A small example if it helps:

import {html, css, LitElement} from 'lit';

export class SimpleGreeting extends LitElement {
  static styles = css`
    p:after {
      content: " 🌎";
    }
  `;

  render() {
    return html`<p>Hello, world!</p>`;
  }
}

customElements.define('simple-greeting', SimpleGreeting);

https://lit.dev/playground/#project=W3sibmFtZSI6In...

@andrewnicols
Copy link

Another one to throw into the mix - we want to be able to have Prettier treat our codeblocks as their formatted langauge in markdown.

For example, I'd like to be able to have Prettier set a tabWidth of 2 for all content, except for PHP codeblocks where we use a tabWidth of 4.

Any code examples in separate files and included into the markdown are fine, because we can set a file-name based override, but any inline code block is formatted with the default tabWidth instead of the php-specific variant, despite the langauge being set in the code block.

@charlespwd
Copy link

Same issue with the Liquid prettier plugin. I can confidently predict that partners will want singleQuote: true in JS but not in Liquid/HTML.

Proposed solution:

{
  printWidth: 80,
  singleQuote: true,
  overrides: [{
    parser: "liquid-html", // as opposed to "files" globs (or in tandem with?)
    options: {
      printWidth: 120,
      singleQuote: false,
    }
  }]
}

That is, accept a new property in overridesparser—which targets the parser you want to extend.

  • When you only have files, behave as usual
  • When you only have parser, apply those options for this parser only in top level or embedded contexts.
  • When you have both files and parser, the options are applied for embedded languages or top level languages.

@lihanspace
Copy link

In the .vue file, I want singleQuote: true in JS but not in CSS/SCSS/LESS

@mikemaccana
Copy link

mikemaccana commented Aug 24, 2023

Heya! Here from #15289 - here's a really common scenario where this is needed.

Any Markdown documentation that involves multiple programming languages probably needs this feature. At Solana Foundation we often, for example, product documentation with both JS and Rust examples:

  • JS uses two spaces, per prettier defaults, StandardJS, node style guide, idiomatic JS, AirBnB style guide, MDN, Google Style guide, codepen, jsfiddle, etc.

  • Rust uses four spaces per rustfmt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:multiparser Issues with printing one language inside another, like CSS-in-JS status:needs discussion Issues needing discussion and a decision to be made before action can be taken type:enhancement A potential new feature to be added, or an improvement to how we print something
Projects
None yet
Development

No branches or pull requests