Add pug support for vue templates
maksnester opened this issue Β· 31 comments
Hello, it is very desired feature to have in eslint-plugin-vue, but they relay on this lib to parse things. So I just wanted to ask if there are any plans to add pug support?
Original issue: vuejs/eslint-plugin-vue#310
Thank you for this issue.
Yes, it will be good if this parser can parse pug.
But I don't have knowledge about pug syntax and semantics, so I don't have enough time to implement it for now.
PR is welcome.
It should parse pug and generate this AST.
@mysticatea I've started looking into this, and have found https://github.com/pugjs/pug-lint which could be a good starting point:
Internally it uses pug-lexer
, which does all the parsing, and already outputs a type of AST. Maybe it won't be all that hard to translate this AST into the form that vue-eslint-parser
requires?
@lehni Thank you!
You are right. That pug-lexer
looks good starting point.
I image the steps are below:
- Parse the inside of
<template lang="pug">
withpug-lexer
. - Convert the result of the parse to our AST. Note some parts such as expression containers, directives, etc, should be re-parsed as JavaScript.
- Extract tokens from the result of the parse. For example,
div(data-foo="bar")
may be the sequence ofdiv
(
data-foo
=
"bar"
)
. (Tokens are separated at the places we can add spaces freely without semantic changes.) Store the tokens toast.templateBody.tokens
. - Extract comments from the result of the parse. Store the comments to
ast.templateBody.comments
.
@mysticatea thank you for the detailed description! Could you point me to the part in the parser code that does this for HTML?
- Making AST nodes and tokens is in https://github.com/mysticatea/vue-eslint-parser/tree/da877ec63b2314e6ee0e9f7df9b4e4aa3b359bc5/src/html.
- Re-parsing for Vue.js directives is in https://github.com/mysticatea/vue-eslint-parser/blob/da877ec63b2314e6ee0e9f7df9b4e4aa3b359bc5/src/html/parser.ts#L386-L398
- Re-parsing for mustaches (e.g.
{{foo}}
) is https://github.com/mysticatea/vue-eslint-parser/blob/da877ec63b2314e6ee0e9f7df9b4e4aa3b359bc5/src/html/parser.ts#L555
Anyone working on it maybe?
Unfortunately I don't have the time to do so at the moment
@ppsirius @lehni some time ago there was some work on it by @leo-buneev
leo-buneev/vue-eslint-parser@de3fe7f...master
I have abandoned this project.
If anyone will continue, beware, pug-lexer returns a little bit different format of tokens, and doesn't provide all necessary data - some hacking done by me here is useful to return consistent data from pug-lexer.
My idea was to return HTML syntax tree that is equivalent to PUG source code (so existing vue-eslint-plugin rules do not need reimplementation), but with different character indexes (corresponding to pug code). It was coming along nicely, but still far from finishing.
We've moved our projects to html since (https://github.com/leo-buneev/pug-to-html). Curiously, it increased character count only by 3.8% - much less than I expected. Pug has more drawbacks than benefits, imho -
Benefits:
- 3.8% less characters
- Less syntax noise
Drawbacks:
- Pug creates problems for junior team members (they have hard time understanding why it's not html, and even harder time putting correct amount of spaces to nest elements)
- You need to switch mentally between coding (Pug) and inspecting in devtools (HTML)
- Worse IDE support
- vue-eslint-plugin doesn't work yet
Why don't you use https://github.com/myfreeweb/eslint-plugin-pug ?
Any news on this one?
Is there any perspective of solving this issue?
@tats-u because eslint-plugin-pug
is to validate javascript inside pug. Not pug inside vue.
Honestly, why I'm slightly saddened at the reduced flexibility, I think @leo-buneev made the right call here. Open Source is maintained out of the good-will of kind developers. And Leo made a good analysis showing why adding the extra work load of supporting Pug just doesn't have enough objective benefits to warrant it.
To everyone who want this feature be implemented by have not time to implement it yourself:
How about chip in and hire someone who can do it for fee?
I am ready to invest 300$ for implementing of this feature.
P. S.
When this feature will be implemented, it will be a new page of quality management automation history.
FYI: There's a prettier-pug plugin now that works quite well for my use-case:
@lehni
Thatβs very kind of you. I'll try.
Oh Boy, I wish I had seen this issue before starting a big Vue project using PUG π
Author of https://github.com/prettier/plugin-pug here.
Please watch/star
https://github.com/Shinigami92/eslint-plugin-vue-pug-sfc
I will try to tackle eslint vue pug support in next time
I have currently a hard time trying to find out what could be the best/correct way of processing the files.
I may need to implement the pug parser as @leo-buneev pointed out in https://github.com/leo-buneev/vue-eslint-parser/blob/master/src/pug/tokenizer.ts
But I would just use the default tokens instead of the HTML variant of tokens and then just process these. Cause the HTML variant of tokens are really hard to use, if not to impossible.
It seems I cannot implement just a e.g. pug-eslint-parser
cause this way I could not access vue files, cause these need the vue-eslint-parser
and this is needed for vue files. And we cannot declare two parsers for vue at the same time π
... So could take a while ... mainly because I also have a real life π€£
Any help is very welcome
I'm not progressing as fast as I wanted π
I have currently so much other stuff around me, and this PR/Issue has a low-mid priority for me π
So this could take a while and I didn't expect that it is that hard to understand all of this stuff and bring everything together. Until now I'm even not sure what would be the best and most efficient solution.
I'm still interested in solving this (for my pug-vue community), but this could take weeks to month due to the other stuff around me π€·
https://www.npmjs.com/package/eslint-plugin-vue-pug-sfc/v/1.0.0-alpha.2 π
This is a first alpha and "supports" vue-pug-sfc/this-in-template
for the never
option. always
is currently NOT supported due to it is much harder to implement.
Please give it a try and please also start to create issues in the repo for every rule you want to get support for!
Please do NOT use the --fix
option right know (or at least with a backup), cause it can damage your code!
The ranges
are not accurate yet so the ~~~~
lines are positioned to broad right now.
Please also feel free to jump into the code and help me π
If you use VSCode jump into the Debug Launcher and run the tests with debug-breakpoints.
@TokugawaTakeshi You don't need to but I would really love to get at least a bit of your offered investment.
I'm working hard on the project and it took me a while to get to this point
- reading how to create eslint plugins
- finding a way to parse the pug content
thanks to @ota-meshi for the initial help, maybe you should get also a bit of the payout if there is one - etc...
I will not spam here anymore, so please lets move all discussions to the project's repo.
I am responsible for my words.
I'll send the email on the address mentioned in your profile soon.
It seems that there is no desire to add support for it - but I'll still leave my comment, as I am one of many who love and want to continue using Pug, but not having the ability to use https://github.com/vuejs/eslint-plugin-vue is a big issue
@doutatsu Whats wrong with my plugin? https://github.com/Shinigami92/eslint-plugin-vue-pug-sfc
Do you need anything special?
Maybe you could even help contribute to it? Then we all have something from it π
You can see the project board here: https://github.com/Shinigami92/eslint-plugin-vue-pug-sfc/projects/1
@Shinigami92 Nothing particularly wrong with yours, but this is an official VueJS ESLint parser, so I think it's still appropriate to ask for the official support for pug here.
Moreover, this specific plugin is the one being used by this repository, which is what I need specifically - https://github.com/vuejs/eslint-plugin-vue. If they decide to use your plugin, then that'll be fine as well
Ah yeah, sry now I understand: yeah I would love if the parser would parse the pug content. But sadly the structure is not really compatible.
In my plugin I extract the pug content out of it and the use the real pug-lexer to generate the tokens.
I'm not sure if it's really possible to support this like it is currently designed out of the box.
Totally understand @doutatsu here with no disrespect to the incredible, selfless work @Shinigami92 is doing here for the pug community. As much a third-party solution is appreciated, let's keep hoping that's at some point pug support is added to vue-eslint-parser
. Since it's unlikely any larger than small-scale production app will want to go for anything but "officially" recommended community plugins. Having more than one templating option will never be a bad thing.
Having said that, I feel for @juliovedovatto ... Our last greenfield project's head foolishly decided to go for pug templates out of personal coding preference despite the team's overwhelming amount of evidence against it and it also left us with a ton of pug-related issues...
- IDE support was poor and plenty of easy to catch linter errors got in frequently.
- There was a large initial learning curve
- We had a mess of PR quality control with people mixing Pug / Vue templating logic instead of being consistent and sticking to only one (due to the Pug/Vue PR overlap).
Hope at the very least this PR conversation helps folks considering pug in their vue project think twice before using it (at least until official support is added to vue-eslint-parser
)
@sgarcia-dev Thanks for the kind words regarding me, but I would say that it is okay to use pug (maybe without all the pug-js stuff, but using framework stuff like v-if
)
If they know how html works, they can also use pug, it's just shorter syntax.
I gave implementing this also a shot and got most of the attribute-hyphenation
rule to work as a proof of concept. You can find the code here https://github.com/rashfael/vue-eslint-parser/tree/pug-parser .
I also used the approach of generating HTML*
tokens, but I now think this will lead to some issues down the line.
Since HTML*
tokens are used in actual rules to check syntax, we would need to always generate the correct structure (including whitespace) to satisfy these rules. Since these rules are configurable, that's not a rabbithole I want to go down.
I now think it would be better to generate higher level tokens from ast.md to support rules not looking at syntax, indentation, etc. Especially since rules like html-end-tags
don't make sense for pug.
To lint pug-specific syntax adding rules just for pug might be best (these could totally live in a different project apart from eslint-plugin-vue
) and vue-eslint-parser
could emit pug-specific tokens.
Since supporting pug like that might involve bigger changes, what's the opinion of the maintainers (@mysticatea , @ota-meshi?) on pug specific tokens?
In the meantime I'll contribute to @Shinigami92's project.
Pug support has been added via eslint-plugin-vue-pug, which adds a template tokenizer to vue-eslint-parser, making a lot of rules of eslint-plugin-vue just work.
For full rule compat see this table.
Please try it out on your real world projects and see if you can find some bugs!