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

Volar support #2

Closed
texastoland opened this issue Jul 1, 2023 · 19 comments
Closed

Volar support #2

texastoland opened this issue Jul 1, 2023 · 19 comments

Comments

@texastoland
Copy link

Unsupported correct? I don't see where to inject this plugin and they depend on sourcemaps anyway.

@matthewjumpsoffbuildings
Copy link
Owner

I haven't implemented Volar support, and I am not sure what is required to do so, do you have any suggestions or resources I could refer to to see how viable that is?

@matthewjumpsoffbuildings
Copy link
Owner

It looks like I would have to fork this Volar plugin? https://github.com/vuejs/language-tools/tree/master/packages/vue-language-plugin-pug

Does adding the existing Volar plugin help? eg
Install

npm i -D @vue/language-plugin-pug

Add to tsconfig.json

 {
 	"vueCompilerOptions": {
 		"plugins": ["@vue/language-plugin-pug"]
 	}
 }

@texastoland
Copy link
Author

texastoland commented Jul 2, 2023

No I don't think that's a good idea.

Pug parsing indeed starts in @vue/language-plugin-pug:
https://github.com/vuejs/language-tools/blob/2b262b5a63d8e19e486a4c758f07eea641e4381d/packages/vue-language-plugin-pug/src/index.ts#L17

But defers to volar-service-pug which:

  1. First lexes (string => Token[]) with https://github.com/pugjs/pug/tree/master/packages/pug-lexer
  2. Then parses (Token[] => ASTree) with https://github.com/pugjs/pug/tree/master/packages/pug-parser
  3. And finally recursively maps sourcemaps in https://github.com/volarjs/services/blob/b3a5b5642bd39d0542a113cd06743f968b053458/packages/pug/src/baseParse.ts#L68-L96

I think the correct place to hook would be between steps 2 and 3 by transforming the AST without modifying the line numbers here:
https://github.com/volarjs/services/blob/b3a5b5642bd39d0542a113cd06743f968b053458/packages/pug/src/baseParse.ts#L30-L31

Problems:

  1. volar-service-pug isn't currently configurable.
  2. @vue/language-plugin-pug would have to propogate any new option.
  3. It'd be specific to this plugin since transforming Pug isn't useful otherwise.

It looks like they're both maintained by @johnsoncodehk. It'd probably need approved by the core team though.

For their reference I ended up here because I was confused by Pug in Vue but this plugin works the way I expected intuitively. Specifically it transforms Pug interpolation and control flow to their Vue equivalents.

This Pug:

vue-pug-plugin/README.md

Lines 22 to 30 in 2438e88

<template lang="pug">
ul
for item in items
li
if item.type == 'link'
a(:href="item.url") some link title: #{item.title}
else
p= item.content
</template>

Transforms into:

<template lang="pug">
ul
li(v-for="item in items")
a(v-if="item.type == 'link'" :href="item.url") some link title: {{item.title}}
p(v-else) {{item.content}}
</template>

@matthewjumpsoffbuildings
Copy link
Owner

matthewjumpsoffbuildings commented Jul 2, 2023

Technically this was forked from the repo @yyx990803 made, but the codebase is basically from scratch. I only really forked since it was kind of covering the same base, just with a more pug native approach.

Honestly I think this approach should be merged into the core Vue pug library, since it allows both the normal Vue approach, as well as the native Pug approach, but I don't know how to propose that or go about making it happen

@texastoland
Copy link
Author

texastoland commented Jul 2, 2023

I thought it might be a fork. I agree with you about belonging in @vuejs. I think this should be <template lang="pug-vue"> or something. The RFC process is (understandably) really closed.

I imagine Evan won't see this but maybe Johnson can give his opinion. I looked for any other relevant activity but only found a stale PR in vuejs/core#7723.

Can't hurt to tag them just in case 😅

@matthewjumpsoffbuildings
Copy link
Owner

matthewjumpsoffbuildings commented Jul 2, 2023

I see what you mean about the <template lang="pug-vue"> option, honestly i think it should just be the default when you do <template lang="pug">

Really, in what world do you want to use pug control structures like if and for and not have them come from the Vue data? There is no way to even pass useful js data to the pug compiler in this context, the only real data sources are either Vue, or manually defining data inside the pug template itself which is basically useless

And as I said, you can still use standard Vue antlers syntax, as well as standard Vue if and for attribute based definitions, so it doesnt really break anything

As far as tagging Evan or Johnson, do you think your @ mentions above are sufficient or are you suggesting I contact them in their repos?

@texastoland
Copy link
Author

texastoland commented Jul 2, 2023

i think it should just be the default when you do <template lang="pug">

That isn't possible because it's a breaking change. In other words someone could have written some funky Pug that suddenly outputs differently. Pug's current behavior works kinda like static rendering.

Projects at Vue's scale only introduce breaking changes for really good reasons. Pug support is just too niche to be worth it.

do you think your @ mentions above are sufficient or are you suggesting I contact them in their repos?

The only other place that would make sense is https://github.com/vuejs/core/discussions. But TBH I don't think they actually read those 🙈

@matthewjumpsoffbuildings
Copy link
Owner

matthewjumpsoffbuildings commented Jul 2, 2023

That isn't possible because it's a breaking change. In other words someone could have written some crazy Pug that suddenly outputs differently. Pug's current behavior works kinda like static rendering.

Fair.

The only other place that would make sense is https://github.com/vuejs/core/discussions. But TBH I don't think they actually read those 🙈

That is a bummer... though what I am even more concerned about is that pug dev seems completely inactive, no commits since 2021, several issues opened asking for any updates on dev status, a bunch of unmerged pull requests 😕

@texastoland
Copy link
Author

Exactly. I liked Pug when it was still called Jade. As you said it isn't active and the Vue integration is slightly useless. The general concensus seems to be HTML is good enough. If Evan answered it'd probably be vuejs/core#4871 (comment).

@matthewjumpsoffbuildings
Copy link
Owner

What Evan said in your linked comment vuejs/core#4871 (comment)

I do not recommend using coffeescript with Vue 3 anyway, there's little benefit.

Do you think pug is on the same kind of level as coffeescript in terms of benefit or enhancement?

For me, once I got started using pug, i just cannot stand HTML any more. 'Good enough' is not even close to good enough haha

@texastoland
Copy link
Author

Pug was created around the same time as CoffeeScript before component frameworks. In theory components solve the problem of verbose HTML by letting you divide it up. But considering how many apps use Tailwind these days I think concise templates just aren't a priority anymore.

@matthewjumpsoffbuildings
Copy link
Owner

I guess, the main aspect of native pug templates (as supported by this plugin) that I prefer is the fact that control structures are visually 'first class'

if someVar == true
  p someVar is true

is so much easier to visually scan and parse than

<p v-if="someVar == true">someVar is true</p>

It makes scanning a source file so much simpler because the logical flow of the template can be top level. Even with a relatively small number of conditionals and loops in a template, using the standard HTML approach with the control structures as HTML attributes, requires you to mentally parse the code in a lot more depth as you scroll through.

It's just so inefficient to me, and this is a hill I will die on haha

@matthewjumpsoffbuildings
Copy link
Owner

Honestly a part of me wants to just create a new, lean component framework in the vein of Vue or perhaps Svelte, that just uses pug style templating out of the box, but I cant help but feel that the world doesnt really need another one now does it 😄

@texastoland
Copy link
Author

Svelte has a gorgeous syntax including "normal" if. I have FOMO all the time 🥲

@matthewjumpsoffbuildings
Copy link
Owner

matthewjumpsoffbuildings commented Jul 2, 2023

I am aware though I wouldnt call it gorgeous or normal hahah

{#if answer === 42}
  <p>what was the question?</p>
{/if}

The {#if ...} syntax seems ugly and unnecessary to me, as does the requirement of an {/if}, when I am so used to the clean pug syntax

if answer === 42
  p what was the question?

But it is certainly better than html 😉

@matthewjumpsoffbuildings
Copy link
Owner

matthewjumpsoffbuildings commented Jul 2, 2023

Just looking at how Svelte handles pug:

ul
  +if('posts && posts.length > 1')
    +each('posts as post')
      li
        a(rel="prefetch" href="blog/{post.slug}") {post.title}
    +else()
      span No posts :c

They use a bunch of mixins for if and each etc, instead of doing what I do here which is convert valid pug syntax into valid vue syntax, which is kinda only half correct IMO

Looking at their preprocess library - https://github.com/sveltejs/svelte-preprocess/blob/main/src/transformers/pug.ts

I feel like I could probably fork this and do something similar to what I do here?

@texastoland
Copy link
Author

texastoland commented Jul 2, 2023

The {#if ...} syntax seems ugly and unnecessary to me, as does the requirement of an {/if}, when I am so used to the clean pug syntax

There's always https://civet.dev/cheatsheet#solidjs 😆

const Component = (items: Item[]) =>
  <ul>
    <For each=items()>
      (item) =>
        <li>{
          if item.type === "link"
            <a href=item.url>some link title: {item.title}
          else
            <p>{item.content}
        }

I feel like I could probably fork this and do something similar to what I do here?

You won't get tooling support in general without hooking into their LSP.

@texastoland
Copy link
Author

texastoland commented Jul 2, 2023

I'm going to stick with HTML but wanted to leave you with another alternative. A macro would be more work but ccould integrate with tooling.

Relevant example:
https://vue-macros.sxzz.moe/features/named-template.html

Source:
https://github.com/sxzz/vue-macros/blob/main/packages/named-template/src/core/index.ts

@matthewjumpsoffbuildings
Copy link
Owner

Im sorry this plugin couldnt cover your needs, but appreciate the input and conversation. I will investigate macros, thanks

@matthewjumpsoffbuildings matthewjumpsoffbuildings closed this as not planned Won't fix, can't repro, duplicate, stale Nov 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants