GithubHelp home page GithubHelp logo

Comments (10)

grunghi avatar grunghi commented on May 29, 2024 3

Hi, I've came up with a temporary workaround until this is fixed on the IDE level - simple nuxt module that creates .components.gen.js file with component imports. This file sits outside of the .nuxt folder where it is picked up by Intellij IDE's for autocompletion etc.
The IDE ignores imports when the file is placed inside .nuxt folder for some reason.

  1. create a module in ~/modules/idea-imports-fix.js
import glob from 'glob'
import { resolve, join } from 'path'

export default function ideaImportsFix () {
  if (process.env.NODE_ENV === 'production') {
    return
  }

  const components = glob.sync(join(__dirname, '../components/**/*.vue')).map(file => {
    const name = file.match(/(\w*)\.vue$/)[1]
    return { name, file }
  })

  const getComponents = () => components

  this.addTemplate({
    src: resolve(__dirname, './templates', 'components.js'),
    fileName: '../.components.gen.js',
    options: { getComponents },
  })
}
  1. create a template in ~/modules/templates/components.js:
<%= options.getComponents().map(({ name, file }) => {
  return `import ${name} from '${file}'`
}).join('\n') %>

<%= options.getComponents().map(({ name, file }) => {
  return `Vue.component('${name}', ${name})`
}).join('\n') %>
  1. register module in nuxt buildModules property
export default {
  buildModules: [
  '~/modules/idea-imports-fix.js'
  ]
}
  1. add .components.gen.js to .gitignore

from components.

pi0 avatar pi0 commented on May 29, 2024

Hi @leeovery. Please ensure components: true (or with array value) is set inside nuxt.config. Not related to IDE.

from components.

leeovery avatar leeovery commented on May 29, 2024

from components.

leeovery avatar leeovery commented on May 29, 2024

@pi0 To be clear with what the issue is here....

Prior to the v0.3.4 update, the component imports were picked up by the IDE and therefore the use of the components didn't generate an IDE error.

However, now the importing layout seems to have changed in nuxt/components/index.js and as a result, the IDE is now not picking up the imports/definitions. This means that the component use in the templates is showing an error as the ide doesn't know where they live, or even whether they exist.

I'll add, in both cases I am correctly using the plugin. It's registered in buildModules and I have the component:true flag at the root level of the nuxt config. Importantly, the module is working, in that the components are being rendered in the browser.

The issue is the IDE isn't able to pick up the registration of the imports since the latest update.

And whilst this isn't a bug in the code as such - an issue like this will result in problems, because nobody likes seeing their code scattered with ide errors.

Edit: Another important issue is lack of autocompletion as a result of the IDE not being able to register the new import structure.

from components.

pi0 avatar pi0 commented on May 29, 2024

Hi @leeovery, Sorry but with all description you provided, I still can't figure out what's wrong with " not picking up the imports/definitions". If you wanted would be happy having a chat on discord (probably sharing screen) to see what's not working.

from components.

leeovery avatar leeovery commented on May 29, 2024

@pi0 That would be great, thank you. Im about whenever you are. username on discord is leeovery#1110

from components.

leeovery avatar leeovery commented on May 29, 2024

https://www.dropbox.com/s/rxjad3fsr2oqocg/Screenshot%202020-06-17%2016.13.49.png?dl=0

This error shows the issue. WebStorm doesnt know where the components are and whether they exist. Prior to the recent update, this was not the case. There was no error.

from components.

reinoldus avatar reinoldus commented on May 29, 2024

@grunghi Thank you very much for these snippets! I extended it a bit (I do not know much about nodeJs, just wanted to get it done):

I copied all the functions from this module (de-typescripted them):

// ~/modules/idea-imports-fix.js
import { resolve } from 'path'
import { basename, extname, join, dirname, relative } from 'upath'
import globby from 'globby'
import { pascalCase, splitByCase } from 'scule'
// const { basename, extname, join, dirname, relative } = require('upath')
//
// const globby = require('globby')
// const { pascalCase, splitByCase } = require('scule')

function sortDirsByPathLength({ path: pathA }, { path: pathB }) {
  return (
    pathB.split(/[\\/]/).filter(Boolean).length -
    pathA.split(/[\\/]/).filter(Boolean).length
  )
}

// vue@2 src/shared/util.js
function hyphenate(str) {
  return str.replace(/\B([A-Z])/g, '-$1').toLowerCase()
}

async function scanComponents(dirs, srcDir) {
  const components = []
  const filePaths = new Set()
  const scannedPaths = []

  for (const {
    path,
    pattern,
    ignore = [],
    prefix,
    extendComponent,
    pathPrefix,
    level,
  } of dirs.sort(sortDirsByPathLength)) {
    const resolvedNames = new Map()
    console.log(pattern)

    for (const _file of await globby(pattern, { cwd: path, ignore })) {
      const filePath = join(path, _file)

      if (scannedPaths.find((d) => filePath.startsWith(d))) {
        continue
      }

      if (filePaths.has(filePath)) {
        continue
      }
      filePaths.add(filePath)

      // Resolve componentName
      const prefixParts = [].concat(
        prefix ? splitByCase(prefix) : [],
        pathPrefix !== false
          ? splitByCase(relative(path, dirname(filePath)))
          : []
      )
      const fileName = basename(filePath, extname(filePath))
      const fileNameParts =
        fileName.toLowerCase() === 'index' ? [] : splitByCase(fileName)

      const componentNameParts = []

      while (
        prefixParts.length &&
        (prefixParts[0] || '').toLowerCase() !==
          (fileNameParts[0] || '').toLowerCase()
      ) {
        componentNameParts.push(prefixParts.shift())
      }

      const componentName =
        pascalCase(componentNameParts) + pascalCase(fileNameParts)

      if (resolvedNames.has(componentName)) {
        // eslint-disable-next-line no-console
        console.warn(
          `Two component files resolving to the same name \`${componentName}\`:\n` +
            `\n - ${filePath}` +
            `\n - ${resolvedNames.get(componentName)}`
        )
        continue
      }
      resolvedNames.set(componentName, filePath)

      const pascalName = pascalCase(componentName)
      const kebabName = hyphenate(componentName)
      const shortPath = relative(srcDir, filePath)
      const chunkName = 'components/' + kebabName

      let component = {
        filePath,
        pascalName,
        kebabName,
        chunkName,
        shortPath,
        import: '',
        asyncImport: '',
        export: 'default',
        global: Boolean(global),
        level: Number(level),
      }

      if (typeof extendComponent === 'function') {
        component = (await extendComponent(component)) || component
      }

      component.import =
        component.import ||
        `require('${component.filePath}').${component.export}`
      component.asyncImport =
        component.asyncImport ||
        `function () { return import('${component.filePath}' /* webpackChunkName: "${component.chunkName}" */).then(function(m) { return m['${component.export}'] || m }) }`

      // Check if component is already defined, used to overwite if level is inferiour
      const definedComponent = components.find(
        (c) => c.pascalName === component.pascalName
      )
      if (definedComponent && component.level < definedComponent.level) {
        Object.assign(definedComponent, component)
      } else if (!definedComponent) {
        components.push(component)
      }
    }

    scannedPaths.push(path)
  }

  return components
}

function matcher(tags, components) {
  return tags.reduce((matches, tag) => {
    const match = components.find(({ pascalName, kebabName }) =>
      [pascalName, kebabName].includes(tag)
    )
    match && matches.push(match)
    return matches
  }, [])
}

export default async function ideaImportsFix() {
  if (process.env.NODE_ENV === 'production') {
    return
  }

  const sh = require('shelljs')
  const c = sh.pwd()
  console.log(c)
  const data = await scanComponents(
    [
      {
        path: './components',
        pattern: '**',
      },
    ],
    '/home/ubuntu/git/wimj-website/'
  )
  let components = data.map(({ filePath: file, kebabName, pascalName }) => {
    if (file.match(/(\w*)\.vue$/)) {
      console.log(pascalName)
      return { name: pascalName, file, kebabName, pascalName }
    }
  })
  components = components.filter((v) => v !== undefined)
  const getComponents = () => components

  this.addTemplate({
    src: resolve(__dirname, './templates', 'components.js'),
    fileName: '../.components.gen.js',
    options: { getComponents },
  })
}

And altered the component.js template file to:

<%= options.getComponents().map(({ name, file,kebabName }) => {
return `import ${name} from '${file}'`
}).join('\n') %>

<%= options.getComponents().map(({ name, file, kebabName }) => {
  return `Vue.component('${name}', ${name})
Vue.component('${kebabName}', ${name})`
}).join('\n') %>

Finally webstorm is usable again. Once the file is imported you have to right click on it and select "inspect code" otherwise wouldn't work for me

from components.

acidjazz avatar acidjazz commented on May 29, 2024

@grunghi this is excellent work and would make a nice nuxt module until JetBrains does something!

from components.

JasonLandbridge avatar JasonLandbridge commented on May 29, 2024

For those looking for a solution: Nuxt-storm

from components.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.