Prettier: Change HTML/JSX formatting to have one attribute/prop per line

Created on 19 Nov 2018  ·  81Comments  ·  Source: prettier/prettier

Similar to what was done for #3847 I think it best to break some of the discussion from #3101 into a new issue that people can 👍 or 👎.

I'm proposing that for HTML and JSX to have Prettier always have one attribute/prop per line (and thus not respect the developer's original preference). Code would then be formatted as shown below. This is in contrast to the current behaviour where we fit as much as possible with the print-width.

Expected behavior:

<MyComponent lorem="1"/>

<MyComponent
  lorem="1"
  ipsum="2"
/>

<MyComponent
  lorem="1"
  ipsum="2"
  dolor="3"
/>

This suggestion for one attribute/prop per line was proposed several times in the discussion of #3101 but I think it is clearer if this is pulled into it's own proposal. The original proposal in #3101 is that Prettier would add an option to preserve original formatting which, while I agree with the author with the style that they want, I don't think a) an option, nor b) preserving original formatting follows the aims for Prettier (see also #2068). Instead I think the aims of #3101 are better served by this proposal to ignore the print-width and always place attributes/props on new lines (assuming that there is more than one).

This style appears to be the most common formatting for Angular, Vue and React from what I can tell. It style appears to be the style enforced by the rules:

html jsx vue needs discussion

Most helpful comment

The point I am trying to make is that the vertical space matters. Wasting it (too much) has negative impact on code manageability.

On the other hand, many diff tools are line-based. So by putting each attribute on it's own line, we reduce the number of conflicts a team has to solve.

From the example above consider

-     <ui-currency v-model="income.business.incomePrevYear" :minInclusive="0" required key="incomePrevYear">Last year income</ui-currency>
+     <ui-currency v-model="income.business.incomePrevYear" :minInclusive="1" required key="incomePrevYear">Last year income</ui-currency>

vs.

    <ui-currency
      v-model="income.business.incomePrevYear"
-     :minInclusive="0"
+     :minInclusive="1"
      required
      key="incomePrevYear"
    >Last year income</ui-currency>

All 81 comments

While I agree that I'd like to see this being default behavior, I would suggest the following steps:

  • introduce new config option (singleAttributePerLine: true ?)
  • make default of that option to have attributes on single line (for backwards compatibility)
  • now we can have it 🎉
  • open discussion about changing the default behavior
  • depending on the outcome:

    • change default behavior of the option

    • deprecate option

@lydell This probably also should have lang:vue as a label 😄

It looks neat only on simple examples. Consider this fragment:

<h2 slot="header">What is your income?</h2> 
<template v-if="employmentType === 'Entrepreneur'">
    <ui-currency v-model="income.business.incomePrevYear" :minInclusive="0" required key="incomePrevYear">Last year income</ui-currency>
    <ui-currency v-model="income.business.income" :minInclusive="0" required key="income">Current income</ui-currency>
    <ui-date v-model="income.business.incomeToDate" :minDate="minDate" max-date="today" required>Income to date</ui-date>
    <ui-currency v-model="income.business.taxableIncome" :minInclusive="0" required key="taxableIncome">Last year tax assessment base</ui-currency>
    <ui-currency v-model="income.business.incomeTax" :minInclusive="0" required key="incomeTax">Tax value</ui-currency>
</template>
<template v-else>
    <label class="field text salary">
        <span class="label">Net income for last 3 months *</span>
        <span>
            <ui-currency v-model="income.personal.salaries[0].value" :minInclusive="0" required key="fMonth" placeholder="1. month*"></ui-currency>
            <ui-currency v-model="income.personal.salaries[1].value" :minInclusive="0" required key="sMonth" placeholder="2. month *"></ui-currency>
            <ui-currency v-model="income.personal.salaries[2].value" :minInclusive="0" required key="tMonth" placeholder="3. month *"></ui-currency>
        </span>
    </label>
    <ui-currency v-model="income.personal.otherIncome" :minInclusive="0" key="otherIncome">Sum of other incomes</ui-currency>
</template>
<ui-select v-if="contract.calculatedProduct.class === 'ConsumerCredit'" v-model="income.personal.nonCashIncome" :options="decisions" :optionName="opt => opt ? 'Yes' : 'No'" required>Income sent to bank account</ui-select>

The structure of the template is obvious, so is the data-binding. The other, less important information (validation, l10n,...) comes next.
If you "format" the code using current rules, you get... well, something similar to a punch tape.

The point I am trying to make is that the vertical space matters. Wasting it (too much) has negative impact on code manageability.

I would suggest to stick with object-literal-like formatting, which has two forms, either:

const a = { prop1, prop1 };

or

const a = {
              prop1,
              prop2,
            };

From the two, the first one is currently missing (in HTML formatting).

The point I am trying to make is that the vertical space matters. Wasting it (too much) has negative impact on code manageability.

On the other hand, many diff tools are line-based. So by putting each attribute on it's own line, we reduce the number of conflicts a team has to solve.

From the example above consider

-     <ui-currency v-model="income.business.incomePrevYear" :minInclusive="0" required key="incomePrevYear">Last year income</ui-currency>
+     <ui-currency v-model="income.business.incomePrevYear" :minInclusive="1" required key="incomePrevYear">Last year income</ui-currency>

vs.

    <ui-currency
      v-model="income.business.incomePrevYear"
-     :minInclusive="0"
+     :minInclusive="1"
      required
      key="incomePrevYear"
    >Last year income</ui-currency>

Sure, if the division of labor has a form that results in many conflicts, then yes, it can help. Or if the formatting does not result in a "punch tape".
I am not really against it. I am just saying, that the first formatting option is also valid and _both_ options should be supported (as in the case of JS object literal).

I like the idea in concept, and to not have an option for this, however - I agree with @marosivanco's idea above of keeping it more like how objects are formatted today, and add what @scrimothy wrote here:

@JoshMcCullough I think treat the attributes as an object literal should be a good compromise. If the input element is with the first attribute in the same line, then it should colapse to one line if it fits. (This is how objects literals behave in 1.15). If is in another line, it doesn't matter how many attributes it have, it should expand.

  • Input:
<my-table [header]="header"
          [items]="items"
          (onScroll)="onScroll($event)">
</my-table>
  • Output:
<my-table [header]="header" [items]="items" (onScroll)="onScroll($event)">
</my-table>
  • Input:
<MyComponent
  foo="John" bar="Smith"
/>
  • Output:
<MyComponent
  foo="John"
  bar="Smith"
/>

IMO this could be a good approach in something that have some many opinions around it. There are many different ways to format element attributes in HTML, but as I said, this seems like a good compromise.

It seems appropriate to focus on breaking HTML-like elements to object literal format after exceeding a given line length (which should just correspond to the print-width attribute rather than adding another length flag specific to this rule). Otherwise, you may have a very long single attribute that would do well on the next line, or 2 or 3 very short attributes that would work perfectly well all on one line. Ultimately, the long line length is the biggest hindrance to readability.

Similarly, sometimes the cause of a long line has more to do with the length of your custom component's name more so than the attributes' key/value pairs.

Input:

<my-app-prefix-comp-a attr1="foo" attr2="bar" />

<my-app-prefix-comp-b attribute-one="methodOneReturnValue()" attribute-two="methodTwoReturnValue()" />

<my-app-prefix-with-a-very-long-custom-component-name attr1="foo" attr2="bar" />

Output:

<my-app-prefix-comp-a attr1="foo" attr2="bar" />

<my-app-prefix-comp-b
    attribute-one="methodOneReturnValue()"
    attribute-two="methodTwoReturnValue()"
/>

<my-app-prefix-with-a-very-long-custom-component-name
    attr1="foo"
    attr2="bar"
/>

I think this should satisfy, or at least be acceptable, for most people - we both have no new option(s) yet still format the input, allowing both putting as many attributes/props as fit in the same line, or break each one to its own line (if the first attribute/prop is put in the line below the open tag).

Any support for something like this would be great. At the moment, prettier only seems to collapse jsx attributes to be on a single line - of all of the proposed options, (for me) that's the least desirable.

This would be very good to have

Still no solution at this day ?

Having that option would at least allow people to opt in. Is this something too time-consuming to implement?

@webberwang See our (slightly outdated) option philosophy.

I will say that since posting in this issue, I have adopted prettier across my projects, and I am absolutely never going back. The productivity increase far outweighs my old preferences for syntax formatting. 🎉

This one is really needed, otherwise, it conflicts with vue-eslint rule max-attributes-per-line.

@mittalyashu We recommend turning off all linter rules that conflict with Prettier. See:

I have already installed https://github.com/prettier/eslint-plugin-prettier, do I have to explicitly install https://github.com/prettier/eslint-config-prettier too?

BTW, what are the difference in both of the packages?

@lydell

Yes, you need to install eslint-config-prettier too.

  • eslint-config-prettier: A _config_ that turns off a bunch of rules.
  • eslint-plugin-prettier: A _plugin_ that lets you run Prettier inside eslint --fix.

@mbifulco While I agree buying into the Prettier opinions of syntactic styling allows for developers to focus on less trivial matters, I'd argue that this specific issue is more important than a strictly syntactic issue such as using tabs vs spaces (though I'm still very appreciative that Prettier allows tabs, even though that issue is one I would have "bought in" to).

Here is why I see this as more than just "preferred syntax":

  • Improved code scan-ability: we can search for the desired attribute in a list, not a grid
  • Consolidated diffs: only the attribute you changed is in the diff, could reduce merge conflicts
  • Compatibility with major frameworks: looking at Vue here, their docs and eslint plugin prefer this format

Disabling recommendations of major frameworks is one approach, but if Prettier defines one standard and doesn't adapt as the leading edge of development adapts, it will ultimately be left behind and replaced with something that does.

That's my opinion, and of course reasonable people can disagree :slightly_smiling_face:

/cc @vjeux Want you feedback. It is really hard to read when we have multiple properties in one lines

@evankennedy My comments about eslint-config-prettier was directed at @mittalyashu who was having problems with their linting setup.

@lydell, got it, thanks for clarifying! I definitely didn't mean for that to seem targeted. I just wanted to consolidate my feelings on the subject so I didn't want to leave that part out.

While fully understanding the philosophy of limiting options in this tool, I hope we can at least have "the attributes as an object literal" concept as default behavior implemented.
The current formatting strategy keeps us from using Prettier to format html. Attribute per line is much better for readability and ease of merging in a large scaled project.

I'm trying to upgrade prettier to the latest version in my Vue project, but the new default behavior changed almost every component template by forcing attributes into one line(unless reaches max-len limit), previously I put one attribute per line, and I have some concerns:

  1. Scan the whole line from left to right maybe just to find a single letter change across multiple attributes is not efficient and takes longer time, also not good for readability.
  2. It makes my eyes dry after reviewing a lot of "diff"s in Git, and I think it's not only me have this issue :)
  3. Still about Git diffs. Even if I agree on this new formatting rule, given a Vue template I couldn't predict the situation some day later if the value of an attribute becomes longer which conflicts with the max-len rule and have to be put into a new line, e.g. a class name "my-component__foo" can be changed to "my-component__foo-bar", in that case the Git diff will report more changes which ideally should happen between two lines.

Throwing my hat in the ring too, agreeing with @hanyu-natsu, @evankennedy, @gitlab-winnie, and thank you @aboyton for reporting this in the first place.

This from @mbifulco sums it up:

Here is why I see this as more than just "preferred syntax":

  • Improved code scan-ability: we can search for the desired attribute in a list, not a grid
  • Consolidated diffs: only the attribute you changed is in the diff, could reduce merge conflicts
  • Compatibility with major frameworks: looking at Vue here, their docs and eslint plugin prefer this format

Disabling recommendations of major frameworks is one approach, but if Prettier defines one standard and doesn't adapt as the leading edge of development adapts, it will ultimately be left behind and replaced with something that does.

As long as it's configurable, that's all I'm asking 😸 It's a great tool, but this is killing my team in our current [massive] Angular project. We have so many props on components it makes the git diffs a mess, and also really impacts readability overall.

Also, similar behavior is currently implemented by Prettier for function parameters. I just saved a file with 3 DI params for an Angular constructor and this

  constructor(private _codes: CodeService, private _currency: DecimalPipe, private _dao: DataAccessService) {
    // ...
  }

was auto-formatted by Prettier as

  constructor(
    private _codes: CodeService,
    private _currency: DecimalPipe,
    private _dao: DataAccessService
  ) {
     // ...
  }

My perspective because nobody asked: I appreciate the desire for fewer options. However, the options that do exist already are less impactful than this option. Given that there are _any_ options, it makes sense to add this one.

(Especially considering how long attributes/props get and how many there often are). We tend to format properties 1 per line in css and js)

@thedamon In case you haven’t seen it – check out our (recently updated) option philosophy.

Is this something that the plugins could add?

This might get a bit spicy here, but I think it's the issue that prettier is meant for jsx/react first and foremost. All other languages have been secondary. I respect the teams work on prettier and I love it on my react projects, there's just issues when you start porting it to other languages and aren't constantly using it.

Instead of asking for an option for this, could we instead start working on a vue or html plugin that does this? I'd love a vue plugin that just matches the vue styleguide so I don't have to worry about conflicts between prettier and vue.

@CalebKester Sure thing, please go ahead and create a plugin, you can start here https://prettier.io/docs/en/plugins.html.

Please, just do it without any option - 1 attr per line is the best compromise for any case, no need for any extra cases. You can always add a new attr in a new line without any pain and it will look really nice with the diff.
All attrs in single line, that we have now, is the worst.
Those, who find their files as the "punch tapes", just must split them.

+1

Just an idea: there could be one option which could be used to switch between "pack all items in one line as much as possible" vs "always spread when there's more than one" and it would affect everything: parameters, arguments, imports, array/object items, etc.

This might also resolve #5995

I hope prettier can also support having one attribute in first line in *.html files, just like js-beautify in VSCode: "html.format.wrapAttributes": "force-aligned", or the rule in eslint-plugin-vue: 'vue/max-attributes-per-line': ['error', { multiline: { allowFirstLine: true } }],

@iiiyx

Please, just do it without any option - 1 attr per line is the best compromise for any case, no need for any extra cases.

It is not a compromise, it is just one of the extremes.

You can always add a new attr in a new line without any pain and it will look really nice with the diff.
All attrs in single line, that we have now, is the worst.
Those, who find their files as the "punch tapes", just must split them.

Splitting is not possible for plain HTML files (HTML has no support for fragment includes)
Splitting using server-side includes comes with run-time overhead.
Decomposition into client-side components has issues of its own:

  • comes with runtime overhead
  • it is not always possible, as some frameworks (vuejs for instance) require components to have a single top-level HTML element. For instance splitting:
<div>
    <label>Name</label>
    <label>Surname</label>
    ...
    // lots of labels
</div>

into:

<div>
   <label-group1 />
   <label-group2 />
    ...
</div>

where label-group1 is:

<template>
  <label>Name</label>
  <label>Surname</label>
  <label>Birthdate</label>
</template>

is not possible, because template in vuejs is required to have 1 top-level element.

IMHO, the prettier should be framework agnostic. You shouldn't be forced to use a certain framework or to change HTML structure, just to format your HTML templates.

My team at work started using the ESLint rules react/jsx-first-prop-new-line and react/jsx-max-props-per-line to try out a formatting with max. one prop per line with the rules set like that:

{
  "rules": {
    "react/jsx-first-prop-new-line": "warn",
    "react/jsx-max-props-per-line": "warn"
  }
}

We use these rules for almost half a year now and it definitely increased readability and made it faster to find specific attributes!

When attributes are listed in one line, you have to skim through all previous attributes and their values and pay attention to where an attribute key starts and where its value ends to find the one you're searching for. Also adding or deleting attributes is more time consuming because you have to move the cursor to a specific place within the line and then operate on part of a line.

On the other hand when the attributes are all on their own line, you read the attribute names from top to bottom and never have to pay attention to their values. Often you can skip over an attribute if you see that the first characters don't match what you're searching for. Removing attributes is usually only a matter of a keystroke to delete the whole line and becomes faster and safer. Same for adding attributes, especially if you review diffs in PRs.

Prettier 2.0 in https://github.com/prettier/prettier/issues/6888 would be an interesting opportunity to make this happen. In the end there seem to be quite some people who are in favour of the idea here. 😊

@dcastil :eyes: could you open an issue for this proposal for 2.0? :eyes:

Good idea @vhoyer, I'll write something for that.

No need, it is not heuristic, it can be implemented under option only so it can be implemented in any version of prettier, it is out of scope prettier@2

Any updates? I also would like it if prettier would put JSX elements in multiple lines. Makes reading code a lot easier

Any updates? I also would like it if prettier would put JSX elements in multiple lines. Makes reading code a lot easier

Yes, there is open PR #6644

I generally like prettier. It does a great job for JS code, but issues such as this make it completely unsuitable for JSX. This basic issue has languished for almost 2 years and hasn't been addressed due to philosophical reasons, which is unfortunate. Time to find another formatting tool 😦

@peacechen Prettier is used in Facebook, the company that created React and JSX. How can it be "completely unsuitable for JSX"?

The issue has already been discussed at length in this thread. Putting props on separate lines improves readability, which is what tools such as prettier are supposed to help with. Instead, it does the opposite in this case.

I don't know where FB uses prettier. Do you? Have they had discussions about prettier mangling JSX?

@peacechen

See https://prettier.io/blog/2018/02/26/1.11.0.html#facebook-is--prettier

As for readability, readability is in the eye of the beholder. It's all just personal preferences. Prettier can't please everybody.

That news blurb doesn't go into detail about what work-arounds FB uses, their config file, etc. They may have to resort to ignoring entire JSX blocks, for all we know.

"As for readability, readability is in the eye of the beholder. It's all just personal preferences. Prettier can't please everybody."

It's true that no tool can please everyone. However readability isn't just "in the eye of the beholder". There are very good reasons to separate a long line of props. It's as though you're trying to argue that a minified file is just as readable as a formatted version with line breaks. Of course that's an extreme comparison, but you can't argue that it's merely "personal preference".

@peacechen React and many other Facebook's projects are open source. Go and check yourself "what work-arounds FB uses" if you want.

Long line of props? What printWidth value do you use?

Issues with having one jsx attribute per line:

  1. For monitors, screen width is almost always greater than screen height. Putting one attribute per line utilizes limited height, and wastes abundant width.
  2. Once you set an attribute, you typically don't need to change it very often. Typically you are working with some other aspect of the code, and an attribute per line forces you to have to filter out more noise.
  3. Due to limited height, one attribute per line forces you to scroll far more than you would otherwise.
  4. How is an attribute different than a function parameter? Don't all the arguments for an attribute per line apply to function parameters?
function MyComponent(x, y, z){ ... }

<MyComponent x="1" y="2" z="3"/>

someFunction("1", "2", "3");
function MyComponent(
  x,
  y,
  z
){...}

<MyComponent
  x="1"
  y="2"
  z="3"
/>  

someFunction(
  "1",
  "2",
  "3"
)

well I see props as named parameters for a function, I always call named parameters one per line

someFunction({
  x: "1",
  y: "2",
  z: "3",
});

also, generally the names for parameters and props are much larger than "x" and "z".

@jasonmcaffee

  1. For monitors, screen width is almost always greater than screen height. Putting one attribute per line utilizes limited height, and wastes abundant width.

Some users display 3 or 4 columns in their editor window, each with a different file. So perhaps you're wasting your width, but not everyone is.

yeah, normally I use three columns, it's quite comfortable for me one attribute per line, I don't feel like I'm scrolling to much.

For monitors, screen width is almost always greater than screen height. Putting one attribute per line utilizes limited height, and wastes abundant width.

The argument made by @pjg for multiple editors side-by-side here is a great one, and I use this all the time. There's also the argument that long lines are bad for readability.

Once you set an attribute, you typically don't need to change it very often. Typically you are working with some other aspect of the code, and an attribute per line forces you to have to filter out more noise.

It's less about needing to change, and more about readability. Being able to read a list of attributes knowing your eye can always start at the beginning of a line is a huge win IMO. Just because you don't change code doesn't mean you don't need to read the code. Other strategies can be used to make a long file shorter while keeping readability. If you're using a tool like React, they allow you to create contexts to access props from children components without passing them down explicitly.

Due to limited height, one attribute per line forces you to scroll far more than you would otherwise.

This is a fine argument, but I'd suggest using tools to jump to code rather than scrolling. Jump to definition, searching for a component by name, etc. In general though, I'd suggest short files, even while keeping one line per attribute.

How is an attribute different than a function parameter? Don't all the arguments for an attribute per line apply to function parameters?

If we're being technical, they're put into a props object, that is passed along. If using React as the JSX pragma, this:

<MyComponent propA="a", propB={true} />

It's actually this:

React.createElement(
  MyComponent,
  {
    propA: 'a',
    propB: true,
  },
  null
);

Not that we need to be super technical about that I suppose. It's syntactic sugar, so we can impose different styling rules on it, but I do think of props as an object. Props are key-value pairs, not just a list of values.


I posted a while back about wanting this feature before using Prettier. Now I'm using it and love a lot about Prettier, but still think this would be a useful feature. Prettier not keeping prop placement consistent is one of my biggest annoyances, such as this:

<>
  <MyComponent propA="a" propB="b" propC="c" />
  <MyComponent
    propA="a"
    propB="b"
    propC="c"
    propD="d"
  />
</>

Allowing us to always do one per line would fix these issues where prop placement is inconsistent.

Good points @evankennedy, thanks.

I have a similar view with regards to object literals and destructuring as I do with attributes, so maybe that ties into it.
I think it's fine to have a limit of some kind, but one attribute or property per line seems like overkill.
e.g. I much prefer destructing like this over multiline:

const {prop1, prop2, prop3} = someObject;

Same for named params. I can't find a language (C++, Ruby, C#, Python, etc) that advocates for placing each named param on a separate line. The same can be said about terminal command parameters.

XML, HTML, SVG, etc have all had attributes defined on a single line since inception, but now with JSX, readability is all of a sudden a problem that we need to enforce having an attribute per line?

edit: oh, forgot to mention, with attributes I don't find myself even needing to look at them very often. Most of time you set and forget. So for me, when they are on separate lines, they end up being noise/distractions hindering me from finding the piece of code I'm looking for.

svg and xml and terminal command parameters are not good examples in my opinion, because neither of then was really meant for you to be reading.

But I always care about readability, when make a shell script, i generally separete them in several lines, specially curl.

And same for html, always have parameters on separate lines.

I'm sorry @vhoyer, but that is incorrect.
https://www.w3.org/TR/REC-xml/#sec-origin-goals

  1. XML documents should be human-legible and reasonably clear.

I'm not really sure what you mean by terminal command params not being meant to be read. You have to type them, right? :)
Maybe an example would help. Most people would not advocate for putting these named params on separate lines:

eslint ./src --ext .tsx --ext .ts --ext .js

Nor would you find many people advocating for env vars on separate lines:

NODE_ENV="dev" PORT=3000 npm run start

I agree with your point on some curl commands, where you have to set headers with session cookies, etc, but that seems to be somewhat of an outlier.

The same can be said about terminal command parameters.

This is the worst example since using a new line executes the command. You're forced to add extra characters to get it look nice if you want. They're powerful tools to get the job done, and the faster you can enter the command, the better. That being said, I even see terminal commands with the new line syntax in textbooks and things where the focus is readability. Terminal commands are rarely meant to be read, but the newline syntax exists for readability, when that matters.

I'm sorry @vhoyer, but that is incorrect.
https://www.w3.org/TR/REC-xml/#sec-origin-goals

XML documents should be human-legible and reasonably clear.

I think there is still a distinction between legible and readable. I'd say single line JSON is still legible. I hate reading it, but it's possible. And if you look at the original request post, this is more in consideration with frameworks like React, Angular, and Vue. The attributes there are fairly complex, much more so than object literals, destructuring, and environment variables.

I still like the suggestion made by @bengry nearly 2 years ago. Seems like a good compromise to make both sides happy, honestly.

I'm sorry @vhoyer, but that is incorrect.
https://www.w3.org/TR/REC-xml/#sec-origin-goals

  1. XML documents should be human-legible and reasonably clear.

oops, sorry for the misconception :shrug: still, I normally don't look foward to reading any XML/SVG file :sweat_smile:. @blakekl has made the point way clearer than I did. It's legible, it's not nice.

I'm not really sure what you mean by terminal command params not being meant to be read. You have to type them, right? :)

Yeah, you're right :sweat_smile:, sorry, I meant that that they are not meant to be read, just written, and when you really want them to be read, you'd separate them in lines.


This are examples taken from the project I most work in, and they were not even made by me (different files):

npm run build $1 \
  && PORT=3050 npm run start $1

cross-env \
  API_KEY=this-is-a-very-belivable-key \
  HOST=0.0.0.0 \
  PORT=3050 \
  NODE_ICU_DATA=node_modules/full-icu \
  SYSTEM_NAME="${SYSTEM_NAME:=$1}" \
  nuxt

cross-env SYSTEM_NAME="${SYSTEM_NAME:=$1}" nuxt build

# this is a counter example
grep -R --exclude-dir={node_modules} -e "\(from \|import(\|require(\)'%system\/[^']\+'" . |\
  sed "s/.*%system\/\([^']\+\)'.*/.\/\1/p" |\
  sort -u

anyway, I think anymore shell example would deviate from the main topic, wouldn't it? sorry if I'm wrong, but I did hide those examples inside the details to not draw a lot of attention due to, as I see it, a side topic :D

I still like the suggestion made by @bengry nearly 2 years ago. Seems like a good compromise to make both sides happy, honestly.

Yeah, I also think this is acceptable.

I concur with @evankennedy,

Inconsistent prop handling is the biggest issue. I would prefer an option on this.

One side effect of this is unnecessarily large git diffs when making tiny changes.

imho that really depends on the type of content you are working with... for single elements or small dom trees I fully agree putting attributes/properties on individual lines is very nice - but for big nested dom trees it's really breaking readability.

consider the following example:
yes it's tense but you get the idea what is grouped and how/why... because you can scan over it in 12 lines

<div class="wrapper" something="else" aria-live="polite">
  <div class="inner-wrapper">
    <div class="part-one" id="left" aria-hidden="true">
      <label for="my-input-one">some info</label>
      <input id="my-input-one" type="text" value="something" />
    </div>
    <div class="part-two" id="middle">
      <label for="my-input-two">some info</label>
      <input id="my-input-two" type="text" value="something" />
    </div>
  </div>
</div>

now if you put every attributes on an extra line... it becomes 36 lines and imho quite tough to get the big picture...

<div 
  class="wrapper" 
  something="else" 
  aria-live="polite"
>
  <div 
    class="inner-wrapper"
  >
    <div 
      class="part-one"
      id="left"
      aria-hidden="true"
    >
      <label 
        for="my-input-one"
      >some info</label>
      <input 
        id="my-input-one"
        type="text"
        value="something" 
      />
    </div>
    <div 
      class="part-two" 
      id="middle"
    >
      <label 
        for="my-input-two"
      >some info</label>
      <input 
        id="my-input-two" 
        type="text" 
        value="something" 
      />
    </div>
  </div>
</div>

So it comes down to what it the main way of information in HTML? Let compare it to CSS... everything is on a separate line as a selector focuses on ONE element.

.wrapper {
  display: block;
  position: relative;
  padding: 20px;
}

Same goes for JS... you assign only one object and that is all you care about - hence having each object property on a separate line

const myObject = {
  foo: 'one',
  bar: 'two',
  baz: 'three',
}

What is different for html is that the overview is very important. In many case the information on where in the DOM the element is - is more important then which individual attributes/properties it has.

Hence giving the dom structure the importants and not the individual dom nodes.

Therefore having one line for each tag is probably a good call - and you see it implemented like this in all modern browser dev tools.

@daKmoR your HTML example formatting is misleading. Here's how prettier's 1-attribute-pe-line PR formats it for me:

    <div
      className="wrapper"
      something="else"
      aria-live="polite">
      <div className="inner-wrapper">
        <div
          className="part-one"
          id="left"
          aria-hidden="true">
          <label htmlFor="my-input-one">some info</label>
          <input
            id="my-input-one"
            type="text"
            value="something"
          />
        </div>
        <div
          className="part-two"
          id="middle">
          <label htmlFor="my-input-two">some info</label>
          <input
            id="my-input-two"
            type="text"
            value="something"
          />
        </div>
      </div>
    </div>

It's a matter of style and personal preference, but personally I prefer this output to your original one. It makes editing it much easier, it makes for very nice diffs. And looking at different attributes in this layout is easier for me.

fair enough - I apparently miss-understood and thought every attribute (also 1 attribute) would be on an individual line.
with that it's ok I would say 👍

my vote would probably go to keep 2 attributes on one line and with >2 start putting each on an individual line.

This issue has a 95% approval rating and plenty of good, well-rationalized reasons for it to exist (whether you _agree_ with the reasons or not, there are many)

At this point, the resistance just seems like stubbornness.

You see, while I do agree that one attribute per line is better (personal opinion + all the reasons stated above), I think it's an erroneous statement saing this has a 95% approval rating based on this issue's :+1:s and :-1:s. Because I think that ppl that support this change would find this issue way more than the ones that wouldn't agree on this change, for some reasons, like "why would I search for I change I don't want" probably this person don't even know this issue exist. So if we are seeking for approving rates, we should search for another way of statistically getting this information.

BUT, if you are not talking about this issue's :+1:s e :-1:s, them sorry to misinterpret you, but what would you be referring to?

@vhoyer absolutely the +/- on this issue is not likely a representation of the general public. but i think it's fair to think its extremeness indicates at the very least solid lean. I doubt a proper sociological study is in scope.. i've just never seen a preference so extreme on a "contentious" github issue before.

https://github.com/prettier/prettier/issues/5377#issuecomment-669877250 - is this about same discussion right?

So prettier is dead? Good to know, a prettifier that does not allow customizing ist pretty useless... Just remove all customizations and force everybody to use your preferences, that's exactly what developers love... to adjust to the opinion of others, thanks!

@CreeTar No, prettier is not dead, please read https://prettier.io/docs/en/option-philosophy.html

yeah, it's not dead, @CreeTar, in fact options goes agains the hole point of prettier as you can read in the link evilebottnawi posted.

If you really want to configure everything yourself, I can kindly recommend you try using eslint 😊

Convention-based design does not preclude configurability. This feature has a lot of thumbs ups and would be worth making the default behavior if maintainers are allergic to adding an option.
CreeTar makes a valid point, whether or not you agree with him. Fortunately there are other tools to choose from.

Does anyone know if there is a PR lying around somewhere for this?

according to @evilebottnawi link, I think the developers do not want to add any more options or limit the development of new options so that they can maintain Prettier as something that matches their own styling philosophies. Correct me if I am wrong.

On the other hand, does anyone have recommendations for other formatting extensions for VSCode that allow the one attribute/prop per line?

maintain Prettier as something that matches their own styling philosophies

I’m not very active in Prettier anymore, but I don’t think this is accurate. Prettier generally maintains its own consistent styling from version to version, which is informed by common practices in the programming and web dev world. Not everyone on the team necessarily likes every choice Prettier makes, but I think it’s fair to say we all value consistent, opinionated, automatic formatting for the JS ecosystem more than our individual preferences.

What I think would make the most sense is to have a community vote, just as it's done in different projects when setting new defaults. Here's a very recent example from the node community regarding changing the default behaviour for unhandled promises: https://www.surveymonkey.com/results/SM-82X6PX3B7/ and from Rubocop (eslinter for Ruby) https://twitter.com/bbatsov/status/1250701829903654912.

Why not have a similar vote regarding some of the mostly debated default settings? And if community chooses one option over the other, then so be it. It would end all discussions. Surely it wouldn't please everyone, but it would please the _majority_. Democracy ftw etc.

@j-f1 I agree to the point where a particular styling would improve and increase readability. This particular issue is for readability that I'd very much like to see an option to enable it. IMHO - readability should be given an "opinion" by those that have to view it.

I know Prettier is placing its bets on the plugin system, but who knows when or if it'll see the light of day.

is this seriously not solved yet? deal breaker

I think the solution at this point is to stop using prettier for html, jsx and vue files. It sucks but the intransigence of the maintainers regarding options, sensible defaults, and Vue (in particular) isn't something I want to spend my energy on if they are not open to listening to the community.

Any progress on this?

Any progress on this?

Nope, and I think it won't be. That is not a "philosophy" of Prettier. There is a PR already for this feature https://github.com/prettier/prettier/pull/6644, which awaiting to be merged for a year, and the best you can do to use it, just make a fork and apply it for yourself.

Have been using prettier for ages for everything except html, team recently added it to our html as well and already thinking of getting rid of it b/c of this issue.

Most things, even when I don't personally like the choice that Prettier makes I can get used to it and it doesn't get in my way. I mostly agree with the 'as few config options as possible to prevent wasting time on arguments' philosophy they have. But in this case it legitimately gets in the way of how we do work.

We started getting unnecessary merge conflicts, PR changes are harder to spot, and (using Angular) certain things like attribute directives are harder to recognize. Prettier makes rare exceptions where there is a config option and this absolutely deserves to be one of those exceptions.

Hey Guys I've been through a lot of pain until I found a way for the html files specifically. I like the simplicity of prettier and I use it for my TS and JS files but for the html I use the default formatter that ships with VSC. The default formatter is based on js-beautify. Which seems to have that ability to wrap each of the attributes on that line. Here you can read more
(https://code.visualstudio.com/Docs/languages/html#_formatting
What I did in my case was to set in my settings.json
"html.format.wrapAttributes": "force-aligned"

That is doing exactly what I wanted in my case. You can check the page and see what other options the default formatter have and you can configure it for your cases but I think it will satisfy most of your needs regarding the formatting of the html files

@lydell Is the ‘status: needs discussion’ label on this issue still warranted?

Was this page helpful?
0 / 5 - 0 ratings