Skip to content

Instantly share code, notes, and snippets.

@KarmaBlackshaw
Last active October 24, 2024 07:09
Show Gist options
  • Save KarmaBlackshaw/52fb8558ee17db00b73ccce1b140bf3e to your computer and use it in GitHub Desktop.
Save KarmaBlackshaw/52fb8558ee17db00b73ccce1b140bf3e to your computer and use it in GitHub Desktop.
Nuxt Eslint Globals
module.exports = {
root: true,
env: {
node: true,
browser: true
},
globals: {
define: true
},
extends: [
'eslint:recommended',
'plugin:vue/essential',
'plugin:vue/recommended',
'./.nuxt/.eslint-globals.json'
],
parser: 'vue-eslint-parser',
rules: {
'array-bracket-spacing': ['error', 'never'],
'array-callback-return': 'error',
'arrow-parens': ['error', 'as-needed'],
'object-curly-spacing': ['error', 'always'],
'arrow-spacing': 'error',
'block-spacing': 'error',
'brace-style': 'error',
camelcase: 'off',
'comma-dangle': 'error',
'default-case': 'error',
eqeqeq: 'off',
indent: [
'error',
2,
{
ignoredNodes: ['TemplateLiteral'],
SwitchCase: 1
}
],
'no-alert': 'off',
'no-await-in-loop': 'off',
'no-console': 'off',
'no-debugger': 'off',
'no-else-return': 'error',
'no-empty-function': 'error',
'no-labels': 'off',
'no-loop-func': 'error',
'no-multiple-empty-lines': [
'error',
{
max: 1
}
],
'no-new': 'off',
'no-prototype-builtins': 'off',
'no-return-await': 'error',
'no-shadow': 'error',
'no-useless-catch': 'off',
'no-var': 'error',
'prefer-const': 'error',
'prefer-rest-params': 'error',
'prefer-spread': 'error',
semi: ['error', 'never'],
quotes: [
'error',
'single',
{
avoidEscape: true
}
],
'require-await': 'error',
'template-curly-spacing': 'off',
'vue/comma-spacing': [
'error',
{
before: false,
after: true
}
],
'vue/component-definition-name-casing': ['error', 'PascalCase'],
'vue/component-name-in-template-casing': ['error', 'kebab-case'],
'vue/custom-event-name-casing': [
'error',
'kebab-case',
{
ignores: ['/^[a-z]+(?:-[a-z]+)*:[a-z]+(?:-[a-z]+)*$/u']
}
],
'vue/html-closing-bracket-newline': [
'error',
{
singleline: 'never',
multiline: 'always'
}
],
'vue/html-end-tags': 'error',
'vue/html-indent': [
'error',
2,
{
attribute: 1,
baseIndent: 1,
closeBracket: 0,
alignAttributesVertically: true,
ignores: []
}
],
'vue/html-self-closing': [
'error',
{
html: {
void: 'never',
normal: 'never',
component: 'always'
},
svg: 'always',
math: 'always'
}
],
'vue/match-component-file-name': [
'error',
{
extensions: ['vue'],
shouldMatchCase: false
}
],
'vue/max-attributes-per-line': [
'error',
{
singleline: 1
}
],
'vue/no-unused-properties': [
'error',
{
groups: ['props', 'data', 'computed', 'methods']
}
],
'vue/no-v-html': 'off',
'vue/require-default-prop': 'off',
'vue/this-in-template': ['error', 'never'],
'vue/v-bind-style': ['error', 'shorthand'],
'vue/v-on-style': ['error', 'shorthand']
}
}
  1. Create a file called modules/eslint.js
  2. Copy the content below to modules/eslint.js
import { basename, resolve } from 'path'
import { addTemplate, defineNuxtModule } from '@nuxt/kit'

const padding = ' '.repeat(4)
const autoImportEslint = defineNuxtModule({
  setup (_, nuxt) {
    const autoImports = {
      global: [
        '$fetch',
        'useCloneDeep',
        'defineNuxtConfig',
        'definePageMeta',
        'defineI18nConfig'
      ]
    }

    nuxt.hook('imports:context', async context => {
      const imports = await context.getImports()
      imports.forEach(autoImport => {
        const list = autoImports[autoImport.from] || []
        const name = autoImport.as ? autoImport.as.toString() : autoImport.name.toString()
        autoImports[autoImport.from] = list.concat([name])
      })
    })

    nuxt.hook('imports:extend', composableImport => {
      autoImports.composables = composableImport.map(autoImport => {
        if (autoImport.as) return autoImport.as.toString()
        return autoImport.name.toString()
      })
    })

    nuxt.hook('modules:done', () => {
      const outDir = basename(nuxt.options.buildDir)
      const filename = '.eslint.globals.json'
      const fullPath = resolve(outDir, filename)

      const getContents = () => {
        // To prevent formatter accidentally fix padding of template string
        let contents = ''
        contents += '{\n'
        contents += '  "globals": {'
        for (const autoImport in autoImports) {
          for (let i = 0; i < autoImports[autoImport].length; i++) {
            const curr = autoImports[autoImport][i]
            contents += '\n'
            contents += `${padding}"${curr}": "readonly",`
          }
        }
        contents = `${contents.slice(0, -1)}\n`
        contents += '  }\n'
        contents += '}\n'

        return contents
      }

      addTemplate({
        filename,
        getContents,
        write: true
      })

      console.log(`globals file is generated at ${fullPath}`)
    })
  }
})

export default autoImportEslint
  1. Restart the server and it should generate a json file with all the auto imported variables in the app.
  2. Import the json file
export default [
  js.configs.recommended,
  ...pluginVue.configs['flat/recommended'],
  ...[
    {
      languageOptions: languageOptions,
      'rules': {
        'vue/multi-word-component-names': 'off',
        ...
      },
    },
  ],
]

That's it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment