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

[Feature Request] Volar Tags Support for Vuetify 2 #14798

Open
douglasg14b opened this issue Mar 8, 2022 · 24 comments
Open

[Feature Request] Volar Tags Support for Vuetify 2 #14798

douglasg14b opened this issue Mar 8, 2022 · 24 comments
Labels
framework Issues and Feature Requests that have needs framework-wide. has workaround help wanted We are looking for community help T: enhancement Functionality that enhances existing features

Comments

@douglasg14b
Copy link

douglasg14b commented Mar 8, 2022

Problem to solve

Currently with volar there are no tags for Vuetify, it seems to be suggested that this is the responsibility of the framework to provide these tags. Or the user to make sure that they have included every framework tag into a global components definitions, which seems not-ideal.

Proposed solution

I'm not entirely sure what actually needs to be done here?

The jist of it would be adding support so that all the Vuetify tags & bits show up in volar? Or a copy/paste block that users user.

Relevant:

vuejs/language-tools#418

@KaelWD
Copy link
Member

KaelWD commented Mar 8, 2022

This was added in c3c98ba

@KaelWD KaelWD closed this as completed Mar 8, 2022
@douglasg14b
Copy link
Author

douglasg14b commented Mar 8, 2022

@KaelWD Do you have a docs link that describes how this is supposed to work for v2? What release version is this in? I see there is a yarn command, but if we are not using yarn does that matter? Is this supposed to "just work"? If so, it does not appear to be.

That's great that this has already been handled, but not so much if how to utilize it is unknown.

Googlers will end up in this issue, having a description here is very helpful to the community that ends up at this point, as opposed to it being a dead end.

@douglasg14b
Copy link
Author

Actually, looking again, this seems to only be for V3?

If so, this issue should be re-opened, as this is for V2 & Vue2.

@KaelWD
Copy link
Member

KaelWD commented Mar 9, 2022

Yes this is only v3, for v2 you need to use vetur instead.

@kingyue737
Copy link
Contributor

Yes this is only v3, for v2 you need to use vetur instead.

Vetur is no longer supported and there are many bugs left. Is it possible to also support volar in v2?

@douglasg14b
Copy link
Author

douglasg14b commented Mar 9, 2022

Yes this is only v3, for v2 you need to use vetur instead.

Volar supports Vue 2, and Vetur is turning out to be a bit of a mess to use... Especially with typescript, and newer Vue 2 features. In addition to Pinia which also works on Vue 2.

Eventually Vue2 shops will be using Volar for Vue 2, and dropping Vetur.

@KaelWD
Copy link
Member

KaelWD commented Mar 9, 2022

possible to also support volar in v2

I don't know, volar requires shimming @vue/runtime-core which is vue 3 only. We also don't have typescript definitions for v2 components which would be a fair bit of work.

@douglasg14b
Copy link
Author

douglasg14b commented Mar 9, 2022

@KaelWD

What would the process look like for this, and what would be required?

There are already some sort of integrated docs for V2, can those be transformed in some manner?

Or would this just be a slog through each component?

I asked because it may be possible for myself or a spare FE in my workplace to dedicate time to solving this problem if it's laid out and clear.


Can this issue be reopened? I'll modify the title to make it clear that this is a request for V2.

@douglasg14b douglasg14b changed the title [Feature Request] Volar Tags Support [Feature Request] Volar Tags Support for Vuetify 2 Mar 9, 2022
@KaelWD
Copy link
Member

KaelWD commented Mar 9, 2022

Vetur and web-types are generated here: https://github.com/vuetifyjs/vuetify/blob/91c135be/packages/api-generator/src/export.js

You may be able to do something similar to generate a .d.ts as well, I don't know how you'd get that to work in volar though judging by your comment in vuejs/language-tools#418

@KaelWD KaelWD reopened this Mar 9, 2022
@KaelWD KaelWD added framework Issues and Feature Requests that have needs framework-wide. help wanted We are looking for community help T: enhancement Functionality that enhances existing features and removed S: triage labels Mar 9, 2022
@KaelWD KaelWD added this to the v2.7.0 milestone Mar 9, 2022
@douglasg14b
Copy link
Author

douglasg14b commented Mar 9, 2022

Thanks! I'm not entirely sure what that code does yet, but I'm sure I'll sort something out when circling back around.

As for this working or not with Volar in vue 2, I'll be testing more there, and circle back in that repo if this wasn't just an issue with what I was trying.

Request:

  • Do you have a copy/paste example of the Vuetify 3 data interfaces output that can be used as a reference? This will be quite helpful.

@kingyue737
Copy link
Contributor

kingyue737 commented Mar 10, 2022

  • Do you have a copy/paste example of the Vuetify 3 data interfaces output that can be used as a reference? This will be quite helpful.

https://unpkg.com/browse/[email protected]/lib/index.d.ts

@douglasg14b
Copy link
Author

Ah I see, just the import statements. After some more reading it may be the entire defineComponent({}) may have to be done for each component before the declaration of the GlobalComponents bit.

I imagine this could be generated to some degree using the existing stuff 🤔 I'll have to try later.

@kingyue737
Copy link
Contributor

kingyue737 commented May 27, 2022

I write a script to generate type declaration from web types. It works like a charm for me. Now volar can provide intellisense in template for vuetify2.

// ./scripts/vuetify-type.mjs

import { readFileSync } from 'fs'
const webTypes = JSON.parse(
  readFileSync('./node_modules/vuetify/dist/json/web-types.json')
)

const blackList = ['VFlex', 'VLayout'] // Components not to define in global

function convertType(typeStr) {
  switch (typeStr) {
    case 'array':
      return 'any[]'
    case 'function':
      return 'Function'
    case 'date':
      return 'Date'
    case 'regexp':
      return 'RegExp'
    default:
      return typeStr
  }
}

function getType(attrType) {
  if (typeof attrType === 'string') {
    return convertType(attrType)
  } else {
    return attrType.map((str) => convertType(str)).join('|')
  }
}

function getDescription(obj) {
  return obj.description ? `/** ${obj.description} */\n` : ''
}

function getSlotPropType(type) {
  return type
    .replaceAll('eventName', 'eventName: string')
    .replaceAll(':"', ':')
    .replaceAll('",', ',')
    .replaceAll('"}', '}')
    .replace(/\/\/.*/, '')
    .replaceAll('):', ')=>')
    .replace(/(aria-[a-z]*):/g, '"$1":')
    .replaceAll('Function', '(...args: any[]) => any')
    .replaceAll('object', '{ [key: keyof any]: any }')
}

function getSlotName(name) {
  if (name === 'header.<name>') {
    return '[name:`header.${string}`]'
  } else if (name === 'item.<name>') {
    return '[name:`item.${string}`]'
  }
  return `'${name}'`
}

const types = webTypes.contributions.html.tags
  .map((vm) =>
    !blackList.includes(vm.name)
      ? vm.name +
        ': DefineComponent<{' +
        vm.attributes
          .map(
            (attr) =>
              getDescription(attr) +
              `${attr.name.replace(/-./g, (x) =>
                x[1].toUpperCase()
              )}?: ${getType(attr.value.type)}`
          )
          .join('\n') +
        '}' +
        (vm.slots?.length
          ? ',{$scopedSlots: Readonly<{\n' +
            vm.slots
              .map(
                (slot) =>
                  getDescription(slot) +
                  `${getSlotName(slot.name)}:${
                    slot['vue-properties']
                      ? '(args: {' +
                        slot['vue-properties']
                          .map(
                            (prop) =>
                              prop.name + ':' + getSlotPropType(prop.type)
                          )
                          .join('\n') +
                        '}) => VNode[]'
                      : 'undefined'
                  }`
              )
              .join('\n') +
            '}>}\n'
          : '') +
        '>'
      : ''
  )
  .join('\n')

console.log(`
import type { DefineComponent, VNode } from '@vue/runtime-dom'
import type { DataTableHeader, DataOptions } from 'vuetify'
type eventHandler = Function

declare module '@vue/runtime-dom' {
  export interface GlobalComponents {
    ${types}
  }
}

export {}`
)

Output:
image

Volar:
image

You can add this script in package.json and run it once the web-types of vuetify 2 is updated.

"scripts": {
  /* ... */
  "type:vuetify": "node ./scripts/vuetify-type.mjs > ./src/vuetify2.d.ts"
},
npm run type:vuetify

@kingyue737
Copy link
Contributor

Hey @dschreij, I've updated my script. Now we can get types and intellisense of slots in Vuetify 2 components.
Before running this script, Vuetify needs to be updated to v2.6.9 released today which fixed some errors in web-types #15472 #15478 #15480

Screenshot 2022-08-10 212442

For detailed settings, you can refer to my Vue 2.7 starter template https://github.com/kingyue737/vitify-admin

@dschreij
Copy link
Contributor

@kingyue737 thanks for the update!
I just ran your script and it works perfectly. Types for Vuetify all over the place :)

@ascott18
Copy link
Contributor

I packaged up @kingyue737's script and its output, along with a few corrections for presumably recent changes in Vuetify since 2.6.9, to make it easier to use.

NPM: https://www.npmjs.com/package/vuetify2-component-types
GH: https://github.com/IntelliTect/vuetify2-component-types

logue added a commit to logue/vite-vue2-vuetify-ts-starter that referenced this issue Apr 5, 2023
Add vuetify2 prop type.
Update dependencies.

see vuetifyjs/vuetify#14798 (comment)
@GabrielHangor
Copy link

Hey @dschreij, I've updated my script. Now we can get types and intellisense of slots in Vuetify 2 components. Before running this script, Vuetify needs to be updated to v2.6.9 released today which fixed some errors in web-types #15472 #15478 #15480

Screenshot 2022-08-10 212442

For detailed settings, you can refer to my Vue 2.7 starter template https://github.com/kingyue737/vitify-admin

Unfortunately the script is not working for me....
Throwing an error that type.replaceAll is not a function
Any ideas why it might happen? I've tried it with vue 2.7 and Vuetify 2.6.15

@GabrielHangor
Copy link

GabrielHangor commented Jun 18, 2023

Ok, putting this block in try/catch actually helped. Got all the types now :) Great!

function getSlotPropType(type) {
  try {
    return type
      .replaceAll('eventName', 'eventName: string')
      .replaceAll(':"', ':')
      .replaceAll('",', ',')
      .replaceAll('"}', '}')
      .replace(/\/\/.*/, '')
      .replaceAll('):', ')=>')
      .replace(/(aria-[a-z]*):/g, '"$1":')
      .replaceAll('Function', '(...args: any[]) => any')
      .replaceAll('object', '{ [key: keyof any]: any }');
  } catch (e) {
    console.log(e);
  }
}

@johnleider johnleider removed this from the v2.7.0 (Nirvana) milestone Jul 5, 2023
@johnleider
Copy link
Member

This is something that we would still like to do but will not be completed before the v2.7 release. Due to the nature of the issue, once resolved, we can simply release as part of a regular PATCH.

@kingyue737
Copy link
Contributor

kingyue737 commented Sep 27, 2023

I've updated the script to include types of emits of Vuetify2 components. Besides props and slots, now we can have autocompletion and type-check of v-on directives and event handlers in SFC template.

vuetify-event

You can also add the latest vuetify2-component-types to try this feature.

pnpm add vuetify2-component-types -D

@GabrielHangor
Copy link

After updating to the new version of Volar (Vue - Official 2.0.24), it is no longer working for me... Vue 2..7.16

@MartinX3
Copy link

MartinX3 commented Jul 2, 2024

Vue 2 is end of life since 2024-01-01.

Vuetify 2 recieves only fixes for security vulnerabilities and critical bugs since 2023-07-05.

@kingyue737
Copy link
Contributor

@GabrielHangor
I'm also using the latest vue extension (Vue - Official 2.0.24). It works fine
image

Can you provide a minimal reproduction

@GabrielHangor
Copy link

GabrielHangor commented Jul 2, 2024

@kingyue737 Sure, what info is required?

When switching to Vue Official 1.8.27 (not the old Volar) it is working as expected. I guess it can also be related to the fact that our codebase has lot's of class components. Components declared via defineComponent and setup works fine...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
framework Issues and Feature Requests that have needs framework-wide. has workaround help wanted We are looking for community help T: enhancement Functionality that enhances existing features
Projects
None yet
Development

No branches or pull requests

8 participants