Prettier: Vue Support

Created on 11 Jun 2017  Ā·  98Comments  Ā·  Source: prettier/prettier

Most helpful comment

To start with, I'd love to just see Prettier work inside

All 98 comments

Just want to add this to the list 😁 https://github.com/vuetifyjs/vuetify

Looks like we'll need to run some js expansion inside of :class value:

<template>
  <h2
    class="title"
    :class="{
      'issue-realtime-pre-pulse': preAnimation,
      'issue-realtime-trigger-pulse': pulseAnimation
    }"
    v-html="titleHtml"
  >
  </h2>
</template>

https://github.com/gitlabhq/gitlabhq/blob/master/app/assets/javascripts/issue_show/components/title.vue#L46-L49

Template supports a lang attribute. https://github.com/vuetifyjs/vuetify/blob/master/src/components/carousel/Carousel.vue

<template lang="pug">
  div(class="carousel")
    div(class="carousel__left")
      v-btn(icon v-on:click.native.stop="prev")
        v-icon chevron_left
...

Looks like we'll need to run some js expansion inside of :class value

Except that's not valid JS. The {} in this case would be parsed as a block, not an object. We'd need to wrap it with () before parsing.

Also the attributes in htmlparser2 aren't individual nodes, it's just an object on the parent tag node, so it makes this hard to intercept.

Didn't want to open a new issue, but feel free to tell me to shove off if this isn't the place...

I've got the parse5 parser up and running on my large (unfortunately not open source) Vue codebase, and it seems to work well for <script> tags in .vue files, but for .js files and the <template> part of my .vue files it just sticks everything on one long line...

Is this expected? Should I be using the default parser for .js files separately? Is it just too early to be trying out the master branch?!

Would be happy to provide samples etc. if that would be helpful. Thanks for the great work so far!

Is it just too early to be trying out the master branch?!

The html5 printer is super bare-bones at the moment. We need to take the time to figure out how best to re-use some of the particularly fancy code that formats JSX.

@karl @vjeux r.e. above comment. Can either of you think of any issues with the idea of transforming the htmlparser2 AST into a JSX AST, then just printing that?

First things that come to mind:

  • Whitespace treatment
  • <!doctype>
  • Void elements

To start with, I'd love to just see Prettier work inside

@azz ā˜šŸ» I've opened an issue to discuss how we might solve the white space differences between JSX and HTML.

Another big project using vuejs thats open source that we would like to run prettier on

https://github.com/voten-co/voten

Hi! Trying to follow through relevant issues, but am unsure where things currently stand. This is a feature I'm particularly interested in and would love to help out!

@kaicataldo you could start searching for commits from this folder/files https://github.com/prettier/prettier/tree/master/tests/multiparser_vue
Unfortunately, I couldn't understand how to test it against real files 😢 . Seems like build scripts have to be updated to use multiparsers, but not sure.

Example of Vue pretty print using jsbeautify https://github.com/LeslieYQ/vue-format
Line 46 and 48 you can pass prettier instead of jsbeautify.

I have written a simple node script to format the <script> section of vue file (actually any html-like file should do). I use it with the sublime text's build system.

https://medium.com/@jackysee/prettier-vue-file-with-sublime-text-475062375956

There's a known solution coming soon, using eslint. See this comment: https://github.com/prettier/prettier/issues/2648#issuecomment-323973082

Basically using both eslint-plugin-script-tags and eslint-plugin-prettier together will yield the exact result that you're looking for. You should be able to test using the branch of that pull request.

I've already tested eslint-plugin-script-tags + eslint-plugin-prettier and linting works, just eslint's auto-fix mode doesn't come into play like it does with normal .js files. That pull request turns on --fix mode for "processor" plugins (f.e. eslint-plugin-script-tags), which will make eslint-plugin-prettier's fixes automatically apply.

@trusktr, this is nice! Though I wish we did not had to rely on eslint --fix to "prettierize" vue files..

That's great!

This issue also tracks reformatting the HTML as well as the JS inside the script tags.

@trusktr I tried your solution and it doesn't seem to work for me. ESLint complains about line-breaks that an auto-fix don't solve. Also, all the rules of eslint-plugin-vuethat should be triggered in templateare simply ignored.

I would very much like an update on this issue and any pointer to where to start in order to help.

I finally had some time to look at this and was pleasantly surprised to find that it already seems to just work with the multiparser behavior. Reading through this issue, I was under the impression it hadn't been implemented yet! For my own understanding, what still needs to be done? Happy to help out :)

@kaicataldo My issues appear to be with Pug and Sass only, I've made a gist demonstrating this. https://gist.github.com/samtgarson/6cce2b7df9f5ba6c5b0ccf722c3fe588

However I tried with HTML as well rather than Pug and there seemed to still be issues with line breaks... šŸ¤”

@samtgarson Prettier support neither the indented Sass syntax nor Pug.

@lydell gist updated to use HTML and CSS—still getting some weird linespace issues.

@samtgarson I have no idea how HTML/Vue formatting works in Prettier, just wanted to clarify that indented Sass and Pug are not supported.

Is there anyone working on this?

I think we were hoping to leverage https://github.com/prettier/prettier/pull/2976 to do this, once it's completed

One more Vue fan!
I can't wait to try this feature! :+1:

I got Prettier working for <script> tags in my .vue files using the following setup:

Packages:

eslint-plugin-html
eslint-plugin-prettier
eslint-config-prettier

Eslint config:

  "eslintConfig": {
    "extends": [
      "eslint:recommended",
      "prettier"
    ],
    "plugins": [
      "prettier",
      "html"
    ],
    "rules": {
      "prettier/prettier": [
        "error",
        {
          "printWidth": 90,
          "semi": false,
          "trailingComma": "es5",
          "bracketSpacing": false,
          "singleQuote": true
        }
      ],
      "camelcase": [
        "error",
        {
          "properties": "never"
        }
      ]
    }
  }

Run using:

eslint --ext .js,.vue src --fix

Great @flybayer but eslint-plugin-html is not compatible (anymore) with eslint-plugin-vue.

@flybayer Your configuration will only enable prettier for the script part. You will not get any linting for the template part.

Yes, my solution is only temporary until we get proper Vue support.

@yacinehmito, right, I wrote that it only works for <script> tags.

For the note, as for a bunch of people in this issue, I care a _lot_ less about Prettier's ability to format Vue templates than I care about the ability for Prettier to format supported languages in .vue files. I don't necessarily care if my HTML is not formatted right, but I do care about my CSS/JS code next to it.

I think properly indebted HTML is important too, tagged less brain cycle to process.

No yeah of course, what I mean is if Vue support were to be released in two times, with support for .vue files first then Vue templating, I'd love getting JS/CSS formatting earlier instead of having to wait for the final part of it since it's an entirely new syntax to support and might take longer

This is how I format my vue projects, assuming everything is under src/:

#!/bin/bash -e
PROC="./node_modules/prettier/bin/prettier.js"
DIR="src"
format() {
  find $DIR -iname "*.vue" -print -exec sh -c "\
    sed -n '/^${1}/,/${2}/p' {} | \
    sed '1d;\$d' | ${PROC} --stdin-filepath dummy.${3} | \
    sed -e '1i${1}' -e '\$a${2}' | \
    sed -i -e '/^${1}/r /dev/stdin' -e '/^${1}/,/${2}/d' {} \
  " \;
}
$PROC --write $DIR/**/*.js webpack.config.js
format "<style lang=\"scss\">" "<\/style>" "scss"
format "<style>" "<\/style>" "css"
format "<style scoped>" "<\/style>" "css"
format "<script>" "<\/script>" "js"

How it works, it extracts <script>...</script> or <style>...</style> sections (section tags required to not have any leading whitespace, just to be safe), feeds each section separately to prettier, and puts it back.

My .prettierrc.json:

{
  "bracketSpacing": true,
  "printWidth": 80,
  "semi": true,
  "singleQuote": true,
  "tabWidth": 2,
  "useTabs": false
}

Disadvantage is that it processes each file multiple times, but the goal was to keep the script stupid simple and throw it away once prettier can format HTML5 properly.

Just FYI, the vetur extension for VS Code supports formatting <script> tags based on prettier-eslint out of the box.

Not sure if this may help implementing this for prettier more generally, but it definitely improves the coding experience for developers using VS Code. :)

Just FYI, the vetur extension for VS Code supports formatting

Related issues

ikatyang picture ikatyang  Ā·  91Comments

vjeux picture vjeux  Ā·  70Comments

reflog picture reflog  Ā·  70Comments

Brian-Gaffney picture Brian-Gaffney  Ā·  107Comments

glen-84 picture glen-84  Ā·  69Comments