8000 Disable embedded language formatting by default and make it configurable · Issue #5588 · prettier/prettier · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Disable embedded language formatting by default and make it configurable #5588

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

Open
Coder-256 opened this issue Dec 3, 2018 · 57 comments
Open
Labels
area:multiparser Issues with printing one language inside another, like CSS-in-JS lang:javascript Issues affecting JS priority:high Code is printed in a way that alters the AST, breaks syntax, or is a significant regression. Urgent!

Comments

@Coder-256
Copy link

Prettier 1.15.2
Playground link

--parser babylon

Input:

const foo = html`<p>test
</p>`;

Output:

const foo = html`
  <p>test</p>
`;

Expected behavior:
I would like a way to disable HTML template string formatting for a js/ts file, but I still want to format the file using Prettier (I just want the template strings to be treated as regular template strings rather than being formatted as HTML). In other words, I would like a way to disable the function here:

/**
* - html`...`
* - HTML comment block
*/
function isHtml(path) {
const node = path.getValue();
return (
hasLanguageComment(node, "HTML") ||
isPathMatch(path, [
node => node.type === "TemplateLiteral",
(node, name) =>
node.type === "TaggedTemplateExpression" &&
node.tag.type === "Identifier" &&
node.tag.name === "html" &&
name === "quasi"
])
);
}

Other than using // prettier-ignore for every single template string, I do not think there is currently any way to do this.

My use case is creating test cases for an editor extension that provides autocomplete for HTML; so I want the tests themselves to be formatted as TypeScript, but I don't want to have Prettier format the HTML inside the template strings. Basically, something like htmlWhitespaceSensitivity: "ignore" but that only applies for template strings (I also have Vue files that I want to format).

@j-f1
Copy link
Member
j-f1 8000 commented Dec 3, 2018

Why don’t you want Prettier to format the HTML inside the template strings? Does it break your code’s syntax?

@j-f1 j-f1 added status:awaiting response Issues that require answers to questions from maintainers before action can be taken lang:javascript Issues affecting JS area:multiparser Issues with printing one language inside another, like CSS-in-JS lang:html Issues affecting HTML (and SVG but not JSX) labels Dec 3, 2018
Coder-256 added a commit to Coder-256/vetur that referenced this issue Dec 3, 2018
@Coder-256
Copy link
Author

@j-f1 It was breaking tests for autocomplete because the tests compare the input HTML to the autocompleted HTML, and it was breaking the smart "hover" functionality (selecting an open tag highlights the closing tag, and vice versa) because the cursor would be in the wrong character position in the text due to the added indentation. The HTML is still valid and displays properly, but it is impossible to test the hover functionality because we don't know where in the string the tags are.

@no-response no-response bot removed the status:awaiting response Issues that require answers to questions from maintainers before action can be taken label Dec 3, 2018
@lydell
Copy link
Member
lydell commented Dec 3, 2018

Workaround:

// Avoid Prettier formatting our template literals.
const html2 = html;

const foo = html2`<p>test
</p>`;

@Coder-256
Copy link
Author

@lydell Yes I can see that this would work, as Prettier only checks for the html template tag, as demonstrated by the code I linked. However this clearly is a bad workaround. There should be some way to disable this functionality without renaming the template tag.

@lydell
Copy link
Member
lydell commented Dec 3, 2018

Yeah, I only mentioned it as a workaround, not a solution.

@j-f1
Copy link
Member
j-f1 commented Dec 3, 2018

Perhaps we should keep single-line HTML literals single-line?

How about renaming your template tag expect? That would fit in with its usage, and it avoids the formatting issue.

@lydell lydell removed the lang:html Issues affecting HTML (and SVG but not JSX) label Dec 3, 2018
@lydell
Copy link
Member
lydell commented Dec 3, 2018

The issue here isn't about HTML. It's about Prettier assuming that the contents of certain tagged template literals is safe to format, while in theory it obviously isn't. For the gql tag this is tremendously helpful, as an example. So far nobody has really bumped into issues due to this, except maybe having to use an occasional // prettier-ignore comment.

The question is what to do about it. Should be there be a way to opt out? Or is it OK to ask people to change their tag name?

I remember @bakkot having commented on this early on (EDIT: #2337 (comment) and #2337 (comment) might be what I'm thinking of, not sure), but I can't find it now. I did find #4424 though which is a bit related.

@icopp
Copy link
icopp commented Dec 4, 2018

Similar to a configuration setting for this would be something to tell Prettier what parser any given tagged template literal should use. I'm using AngularJS in template literals, for example.

@Coder-256
Copy link
Author

IMHO the user never expects a formatter to behave differently based on the content of an identifier, so this is a bug. Naming a variable differently should not affect how the file is formatted (except for if the length changes); and in this case, the name of the tag not only changes the formatting of the file but actually changes the contents of the literal string. Not only should the contents of a string never be changed by a formatter, but that behavior shouldn't be enabled or disabled based on the name of the template tag.

I think the best solution here is very simple: only format the contents of templates for a list of tag names that the user explicitly enables this behavior for. Whether the list should be empty by default, or ["html", "jsx", ...], is another point to discuss. I would vote for empty by default because users expect the same treatment for all strings, but at the same time, enabling support for formatting template strings would require the user to add another setting, which complicates the config. Either way, there should at least be a way to disable this behavior.

@bakkot
Copy link
Collaborator
bakkot commented Dec 4, 2018

IMHO the user never expects a formatter to behave differently based on the content of an identifier

Empirically, many users do expect this. I agree with you overall (see my comments linked above), just saying, this claim is wrong as a question of fact.

@lydell
Copy link
Member
lydell commented Dec 4, 2018

I think the best solution here is very simple: only format the contents of templates for a list of tag names that the user explicitly enables this behavior for.

It’s not that easy, though, because there’s also non-identifier-only stuff such as graphql.experimental, styled.foo, Component.extend, styled(Component), styled.foo.attr({}), <style jsx>{`div{color:red}`}</style> and some crazy angular stuff. https://github.com/prettier/prettier/blob/525c076be82b0bb28a090163884080853e198814/src/language-js/embed.js

@Coder-256
Copy link
Author

@bakkot I agree, hence the "IMHO" :)

@lydell Interesting. Now that you mention this, it seems to me current behavior makes sense as a default. However, I still feel that users should still have a way to disable all of these behaviors in their config rather than using prettier-ignore every time.

@jeremyhill-up

This comment has been minimized.

@jakepark

This comment has been minimized.

@j-f1

This comment has been minimized.

@jakepark

This comment has been minimized.

@j-f1

This comment has been minimized.

@jakepark

This comment has been minimized.

@j-f1

This comment has been minimized.

@jakepark

This comment has been minimized.

@Coder-256

This comment has been minimized.

@fisker
Copy link
Member
fisker commented Aug 28, 2020

Feel difficult to config

@thorn0 thorn0 changed the title Disable template string formatting by default and make it configurable Disable embedded language formatting by default and make it configurable Jan 17, 2021
@nickserv
Copy link
Member
nickserv commented Feb 11, 2021

Could we add an option to allow automatic formatting for JSON.parse literals as well? Rationale and examples in #7043.

If possible I'd also like some sort of mode that automatically enables both the existing embedded formatting and new embedded formatting features like what I'm suggesting for JSON.parse.

@Pyrolistical
Copy link
Pyrolistical commented Jul 22, 2022

A generic way to format template strings would be nice. lit-html exposes both an html tag and an svg tag, and currently only my html tags are formatted by prettier. It would be nice to also have the svg tags formatted.

@bschlenk One dirty hack is to use:

import { svg as html } from "lit-html";

@nickserv
Copy link
Member

@Coder-256 Prettier now formats this onto one line.

const foo = html`<p>test</p>`;

Does that fix your issue?

@somahargitai
Copy link

@Coder-256 Prettier now formats this onto one line.

const foo = html`<p>test</p>`;

I am just facing this issue, but I would like to be able to have a normal html formatting in a template literal instead of a oneliner. In bigger html template literals it is not a good behaviour

@Pyrolistical
Copy link
Pyrolistical commented Aug 8, 2022

I am just facing this issue, but I would like to be able to have a normal html formatting in a template literal instead of a oneliner. In bigger html template literals it is not a good behaviour

@somahargitai Please describe the problem you have. When the html template gets longer, prettier does turn it into multiple lines.

@lionel-rowe
Copy link

Agree this should be turned off by default — different html tagged-template functions exported by different libraries use different logic, so Prettier can't know for sure that its modifications won't break things. It's already changing things that have a meaningful difference at runtime, which I thought Prettier wasn't supposed to do?

@boredland
Copy link

I am currently in a dead-lock between either having mjml-template-literal to enable inline mjml syntax support and using a tag named html to have prettier formatting it.

@nwalters512
Copy link
9E88

Chiming in to +1 support for custom tags. I'd like to be able to use a plugin to support sql tagged template literals in JS files, but there's currently no way to extend the JS formatter to support this.

@so1ve

This comment was marked as duplicate.

@Sec-ant
Copy link
Sec-ant commented Oct 20, 2023

I'm working on a Prettier plugin called prettier-plugin-embed to customize embedded languages formatting. It's not production ready and lacks tests, but I think it's time to let more users try this plugin.

To simply put:

  • It supports some additional languages like XML, SQL, GLSL and new ones can be added gradually with relatively little effort.
  • It provides options to disable formatting for certain languages, even those ones from Prettier.
  • It provides options to customize the tag identifiers you want to use for detecting certain languages.

Check the README file for a more detailed introduction: https://github.com/Sec-ant/prettier-plugin-embed#readme

Hope you find it helpful ❤️

@karlhorky
Copy link
Contributor
karlhorky commented Oct 28, 2023

@Sec-ant thanks so much for this!

I can confirm, this works well with formatting SQL inside tagged template literals with prettier-plugin-sql by @JounQin 🙌

@Alonski
Copy link
Contributor
Alonski commented Feb 19, 2024

Hey awesome people, any way to push this forward please?

@JounQin
Copy link
Member
JounQin commented Feb 19, 2024

You can try to use https://github.com/Sec-ant/prettier-plugin-embed

@titoBouzout
Copy link

Why don’t you want Prettier to format the HTML inside the template strings? Does it break your code’s syntax?

Yes it does, the problem I am having now is that this

html`<A/>`

becomes

html`<a/>`

and it breaks the A component.

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 lang:javascript Issues affecting JS priority:high Code is printed in a way that alters the AST, breaks syntax, or is a significant regression. Urgent!
Projects
None yet
Development

No branches or pull requests

0