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

Supporting HTML #1882

Closed
vjeux opened this issue Jun 2, 2017 · 70 comments · Fixed by #5259
Closed

Supporting HTML #1882

vjeux opened this issue Jun 2, 2017 · 70 comments · Fixed by #5259
Labels
status:has pr Issues with an accompanying pull request. These issues will probably be fixed soon! type:enhancement A potential new feature to be added, or an improvement to how we print something
Milestone

Comments

@vjeux
Copy link
Contributor

vjeux commented Jun 2, 2017

Angular, Vue and Ember all use variants of html/mustache with JS and CSS embedded. It would be really awesome to make prettier support it as well. This would allow the project to be the one stop destination for all the front-end related code.

@josephfrazier
Copy link
Collaborator

(related to #1674)

@octref
Copy link

octref commented Jun 2, 2017

Really wish http://codeguide.co/#html-syntax by @mdo could be enforced, so people can write consistent html:

  • Use soft tabs with two spaces—they're the only way to guarantee code renders the same in any environment.
  • Nested elements should be indented once (two spaces).
  • Always use double quotes, never single quotes, on attributes.
  • Don't include a trailing slash in self-closing elements—the HTML5 spec says they're optional.
  • Don’t omit optional closing tags (e.g. </li> or </body>).

Also, this feels like perfect use case for prettier 😉 :

<foo
  class="i have so many classes"
  data-really-long-attr="bar"
  data-another-long-attr="bar"
></foo>

I don't know specifics for formatting ember/angular, but for Vue SFC, my Vue/VSCode plugin https://github.com/octref/vetur has code that takes each region and send them to respective formatters:

<template>
  <!-- send to html formatter -->
</template>
<script lang="ts">
  // send to ts formatter
</script>
<style lang="scss">
  // send to scss formatter
</style>

Previously I hooked up js-beautify as formatter for script and style regions, but now prettier has TS support so I'm switching over to it for formatting js/ts/css/scss/less.

Once html supports land in prettier, I can make a Vue formatter that takes any Vue file written with html, js/ts, css/less/scss/postcss and outputs consistent code. That is 🔥 🔥 🔥

@vjeux vjeux added type:enhancement A potential new feature to be added, or an improvement to how we print something type:option request Issues requesting a new option. We generally don’t accept these unless there is technical necessity. labels Jun 3, 2017
@donaldpipowitch
Copy link

Will this cover underscore/lodash templates, too? ♥

@thedamon
Copy link

This would be amazing. Other use case is working in not specifically js related environments such as CMSs that use html styled templates. A tool available to the command line to verify and correct HTML errors could be incredibly useful for processing user input in WYSIWYG HTML fields in CMS fields as well (Unfortunately these still do exist...).

One thing that could help a lot would be a list of acceptable (custom) attributes, though that may beyond the scope of prettier and more appropriate for a linter.

@gabrielmaldi
Copy link

This would allow the project to be the one stop destination for all the front-end related code.

👏👏👏

Just outputting each attribute in a newline would already be amazing for most frameworks like Angular.

@maraisr
Copy link

maraisr commented Jul 12, 2017

@gabrielmaldi yeah exactly, be kinda cool to also hook into the json/js prettifier to also do stuff to the angular 1.X ng-X things.

@thedamon
Copy link

I ran prettier on 343+ html files and it didn't run in to any exceptions. Spot checking a few of the changes seems to have made reasonable changes. (assuming this is based on the jsx parsing) Should I trust that the changes won't break any code? 😉

@vjeux
Copy link
Contributor Author

vjeux commented Jul 25, 2017

Should I trust that the changes won't break any code? 😉

For all the supported languages, we've done extensive testing so it should be a fair assumption. For html, we have done not such thing yet so there's a good chance that it broke something. If you could do a manual review that would be very helpful.

@thedamon
Copy link

I've spotchecked a few of the files through the diff, and loading some pages and haven't noticed anything breaking, but unfortunately we don't have integration tests for me to run to make sure...

I noticed some extra newlines and I know technically if they were between inline elements that could affect rendering.

Everything SEEEEEMS to be fine, but it's certainly a big risk to take. 🙃

@gabrielmaldi
Copy link

gabrielmaldi commented Jul 27, 2017

I ran prettier 1.5.3 through 269 HTML files and found a couple of issues:

  • Every file now starts with 2 newlines.
  • Every file had its last newline removed.
  • Newlines inserted everywhere between elements.
    • This isn't bad per se, but sometimes comments end up "associated" to a different element. See example below where "Display exchange rate conversion" is no longer tied to the next li element.
  • Close tags removed for elements with no children.

Example:

+
+
 <div class="melilla_step"
     ng-class="['melilla_step-' + (mode || 'editable'), { 'melilla_step_product_locked': readonly && mode != 'result', 'disabled': icProductField.isDisabled }]">
     <!-- Label above product when loaded -->
-    <ng-include src="'directives/icProductField/icProductFieldTitle.html'"></ng-include>
+    <ng-include src="'directives/icProductField/icProductFieldTitle.html'" />
 
     <!-- Product content (loaded) -->
+
     <div ng-if="icProductField.model"
         class="melilla_step_field_container_content"
         ng-class="{ 'melilla_step_field_container_content-fulfilled-on-initial': !readonly }"
         select="icProductField.selectProduct()">
+
         <ul class="melilla_step_field_container_fulfilled"
             ng-class="{ 'melilla_step_required': icProductField.required }">
+
             <li class="melilla_step_field_container_product">
                 <span class="melilla_step_field_container_product_alias">{{ icProductField.model.productAlias }}</span>
             </li>
 
             <li class="melilla_step_field_container_product">
-                <ng-include src="'directives/icProductField/icProductFieldCurrency.html'"></ng-include>
+                <ng-include src="'directives/icProductField/icProductFieldCurrency.html'" />
+
             </li>
 
             <li class="melilla_step_field_container_product">
                 <span class="melilla_step_field_container_product_number">{{ icProductField.model.productNumber }}</span>
             </li>
-
             <!-- Display exchange rate conversion -->
+
             <li ng-if="icProductField.conversionModel"
                 class="melilla_step_field_container_product">
-                <ng-include src="'directives/icProductField/icProductFieldExchangeRate.html'"></ng-include>
+                <ng-include src="'directives/icProductField/icProductFieldExchangeRate.html'" />
+
             </li>
         </ul>
     </div>
-</div>
+</div>
\ No newline at end of file

Sorry if this is already being looked at in another issue or if I missed something (like formatting goals).

EDIT

I ran prettier again through the same set of already prettified files, and only 13 (out of 269) weren't modified, the rest got "prettified" again.

Example (diff generated by running prettier twice on the same file):

     <switch class="melilla_step_switch_control"
         is-selected="icSwitch.model"
         on-select="toggle()"
-        is-disabled="icSwitch.isDisabled" />
-
-    <span class="melilla_step_switch_label">{{ getPlaceholderText() }}</span>
+        is-disabled="icSwitch.isDisabled">
+        <span class="melilla_step_switch_label">{{ getPlaceholderText() }}</span>
+    </switch>
 </div>
 
 <div ng-class="{ 'melilla_step_locked': mode != 'result' }"
@@ -21,13 +21,13 @@
 
             <div ng-if="!field.model"
                 class="melilla_step_field_container_confirm_input_value"
-                translate="common.no" />
-
-
-            <div ng-if="field.model"
-                class="melilla_step_field_container_confirm_input_value"
-                translate="common.yes" />
+                translate="common.no">
 
+                <div ng-if="field.model"
+                    class="melilla_step_field_container_confirm_input_value"
+                    translate="common.yes">
+                </div>
+            </div>
         </div>
     </div>
 </div>
\ No newline at end of file

Thanks

@thedamon
Copy link

Making empty tags self-closing seems like maybe a feature instead of a bug. But it depends on your framework. Ideal is probably an option, even though we hate options.

@aboyton
Copy link
Contributor

aboyton commented Aug 1, 2017

My understanding was the the HTML spec for custom elements didn't allow you to create custom self-closing tags and thus many frameworks (like say Angular) don't allow them. Thus I don't think prettier should do this conversion (or if people really want it to it should be an option).

@gabrielmaldi
Copy link

At some point we had to add self-closing tags because without them we had some issues (can't recall exactly what) using AngularJS. I'm in favor of having an opt-in setting for this.

@maraisr
Copy link

maraisr commented Aug 1, 2017

Yeah, angular.js does some funky parsing of the dom tags, and without the closing tags, angular.js just throws a hissy fit.

Personally, we already have the "use semi-colon's or not" option for js, why not have a "closing tags or not" option for html.

@octref
Copy link

octref commented Aug 18, 2017

Wondering what's the current status on this issue (@azz since it seems you were doing a lot of work for it). From what I gather there is already some support for HTML in 1.5.3, but not without issues as @gabrielmaldi pointed out.

@octref
Copy link

octref commented Sep 7, 2017

I'm interested in helping moving this forward (or the Vue one #2097).
I'd appreciate someone giving me a picture as to what has been done, what still needs to be done for release, which issues / part-of-codebase I can start looking into. Thanks!

@vjeux @azz

@azz
Copy link
Member

azz commented Sep 9, 2017

Hi @octref,

What's done:

What needs to be done:

@Rayraegah
Copy link

Pardon me for asking but could we also validate against / support single file components in https://svelte.technology/

  1. Its just HTML & Mustache artifacts
  2. Some vue like syntax for bindings

@azz
Copy link
Member

azz commented Sep 11, 2017

I have no experience with svelte, but if someone wants to build support for it that would be really cool.

@octref
Copy link

octref commented Oct 20, 2017

Yo guys, you ever heard of https://github.com/reshape/reshape?

Seems pretty solid to me. Same approach as prettier (down to AST -> pretty print). @jescalan did an awesome job there.

Maybe include it instead of reinventing the wheel?

@jescalan
Copy link

Hi! I wrote reshape, happy to be of assistance in this if I can be. We're using reshape pretty heavily in production and it has been quite stable. Big fan of prettier for javascript and would be honored to be able to contribute in any way.

@alexander-akait
Copy link
Member

Feedback welcome #4753

@j-f1 j-f1 removed the help wanted We're a small group who can't get to every issue promptly. We’d appreciate help fixing this issue! label Jul 6, 2018
@mohd-akram
Copy link

I created a very simple HTML formatter available on npm and as a VS Code Extension if anyone is interested. I made it because I couldn't find a formatter that worked well with Handlebars. It does not make any assumptions about content except for dealing with self-closing tags (to avoid indenting after them) and pre, script and style (to prevent formatting them).

@ikatyang
Copy link
Member

Opened #5259 to address this issue, feedbacks welcome.

@ikatyang ikatyang added this to the 1.15 milestone Oct 25, 2018
@robert-j-webb
Copy link
Contributor

I hate to be a stickler because this is a really impressive amount of work but it still doesn't support handlebars / mustache.

@michaeljota
Copy link

I think that was requested in the PR thread, but seems to be a lot of work. I think is because of hard would be to tokenized just { and }, but I ain't sure. @ikatyang provides more inside in the pr.

@ikatyang
Copy link
Member

ikatyang commented Nov 5, 2018

@robert-j-webb Can you open another issue for handlebars? Thanks!

@michaeljota Yeah, it's #5259 (comment).

@ikatyang ikatyang changed the title Supporting HTML/Mustache Supporting HTML Nov 5, 2018
@suchipi
Copy link
Member

suchipi commented Nov 5, 2018

I actually just opened #5340

@capaj
Copy link

capaj commented Nov 10, 2018

@aboyton did no one else from prettier team read your comment? I just updated to prettier 1.15.2 and I get this when I format our angular.js templates:
image

this totally breaks our angular.js app.
Guess it's back to the old 1.14.x version for us.
Can't you make the conversion to self-closing tags configurable?

@lipis
Copy link
Member

lipis commented Nov 10, 2018

@capaj Could you open a new issue if that's a real problem?

@capaj
Copy link

capaj commented Nov 10, 2018

@lipis opened as #5436 but now that I think about it-it may be just a misunderstanding stemming from the fact that angular.js has almost the same name as angular yet they are both very different frameworks. Also prettier only supports angular, not angular.js so it's not a bug. It's more like documentation addition request.

@lipis
Copy link
Member

lipis commented Nov 10, 2018

Thank you @capaj, I'll lock this conversation to avoid further comments. If there is anything wrong please file new issues instead.

@prettier prettier locked as resolved and limited conversation to collaborators Nov 10, 2018
@ikatyang
Copy link
Member

To clarify, we won't change normal tags into self-closing tags in HTML, we only apply this kind of tag transformation in JSX, which is valid. Please make sure you're using --parser html.

A common mistake is that people are using top-level parser: "babylon", which treats everything as JavaScript (JSX), see here for more info.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
status:has pr Issues with an accompanying pull request. These issues will probably be fixed soon! type:enhancement A potential new feature to be added, or an improvement to how we print something
Projects
None yet
Development

Successfully merging a pull request may close this issue.