//eslint-plugin-harlanzwbyharlan-zw

eslint-plugin-harlanzw

My opinionated ESLint rules for Vue apps

23
0
23
3
TypeScript

eslint-plugin-harlanzw

npm version
npm downloads
License

Harlan’s ESLint rules for Vue projects with focus on link hygiene, Nuxt best practices, and Vue reactivity patterns.

Made possible by my Sponsor Program 💖
Follow me @harlan_zw 🐦

Playground

Try the rules in action with a Nuxt ESLint interactive playground:

Open in StackBlitz

Rules

undefinedNote: These rules are experimental and may change. They will be submitted to the official Vue ESLint plugin for consideration.

The rules are organized into the following categories:

  • undefinedLink Rules - Ensure link URLs are clean, accessible, and SEO-friendly
  • undefinedNuxt Rules - Best practices for Nuxt applications
  • undefinedVue Rules - Vue composition API and reactivity best practices
Rule Description
link-ascii-only ensure link URLs contain only ASCII characters
link-lowercase ensure link URLs do not contain uppercase characters
link-no-double-slashes ensure link URLs do not contain consecutive slashes
link-no-whitespace ensure link URLs do not contain whitespace characters
nuxt-await-navigate-to enforce awaiting navigateTo() calls
nuxt-no-redundant-import-meta disallow redundant import.meta.server or import.meta.client checks in scoped components
nuxt-no-side-effects-in-async-data-handler disallow side effects in async data handlers
nuxt-no-side-effects-in-setup disallow side effects in setup functions
nuxt-prefer-navigate-to-over-router-push-replace prefer navigateTo() over router.push() or router.replace()
nuxt-prefer-nuxt-link-over-router-link prefer NuxtLink over RouterLink
vue-no-faux-composables stop fake composables that don’t use Vue reactivity
vue-no-nested-reactivity don’t mix ref() and reactive() together
vue-no-passing-refs-as-props don’t pass refs as props - unwrap them first
vue-no-reactive-destructuring avoid destructuring reactive objects
vue-no-ref-access-in-templates don’t use .value in Vue templates
vue-no-torefs-on-props don’t use toRefs() on the props object

Installation

Install the plugin:

pnpm add -D eslint-plugin-harlanzw

Usage

With @antfu/eslint-config

// eslint.config.js
import antfu from '@antfu/eslint-config'
import harlanzw from 'eslint-plugin-harlanzw'

export default antfu(
  {
    vue: true,
  },
  {
    plugins: {
      harlanzw
    },
    rules: {
      'harlanzw/link-ascii-only': 'error',
      'harlanzw/link-lowercase': 'error',
      'harlanzw/link-no-double-slashes': 'error',
      'harlanzw/link-no-whitespace': 'error',
      'harlanzw/nuxt-await-navigate-to': 'error',
      'harlanzw/nuxt-no-redundant-import-meta': 'error',
      'harlanzw/nuxt-no-side-effects-in-async-data-handler': 'error',
      'harlanzw/nuxt-no-side-effects-in-setup': 'error',
      'harlanzw/nuxt-prefer-navigate-to-over-router-push-replace': 'error',
      'harlanzw/nuxt-prefer-nuxt-link-over-router-link': 'error',
      'harlanzw/vue-no-faux-composables': 'error',
      'harlanzw/vue-no-nested-reactivity': 'error',
      'harlanzw/vue-no-passing-refs-as-props': 'error',
      'harlanzw/vue-no-reactive-destructuring': 'error',
      'harlanzw/vue-no-ref-access-in-templates': 'error',
      'harlanzw/vue-no-torefs-on-props': 'error'
    }
  }
)

With Nuxt ESLint

// eslint.config.mjs
import harlanzw from 'eslint-plugin-harlanzw'
import withNuxt from './.nuxt/eslint.config.mjs'

export default withNuxt([{
  plugins: {
    harlanzw
  },
  rules: {
    'harlanzw/link-ascii-only': 'error',
    'harlanzw/link-lowercase': 'error',
    'harlanzw/link-no-double-slashes': 'error',
    'harlanzw/link-no-whitespace': 'error',
    'harlanzw/nuxt-await-navigate-to': 'error',
    'harlanzw/nuxt-no-redundant-import-meta': 'error',
    'harlanzw/nuxt-no-side-effects-in-async-data-handler': 'error',
    'harlanzw/nuxt-no-side-effects-in-setup': 'error',
    'harlanzw/nuxt-prefer-navigate-to-over-router-push-replace': 'error',
    'harlanzw/nuxt-prefer-nuxt-link-over-router-link': 'error',
    'harlanzw/vue-no-faux-composables': 'error',
    'harlanzw/vue-no-nested-reactivity': 'error',
    'harlanzw/vue-no-passing-refs-as-props': 'error',
    'harlanzw/vue-no-reactive-destructuring': 'error',
    'harlanzw/vue-no-ref-access-in-templates': 'error',
    'harlanzw/vue-no-torefs-on-props': 'error'
  }
}])

Standalone Usage

Add the plugin to your ESLint configuration:

// eslint.config.js
import harlanzw from 'eslint-plugin-harlanzw'
import vueParser from 'vue-eslint-parser'

export default [
  {
    files: ['**/*.vue'],
    languageOptions: {
      parser: vueParser
    },
    plugins: {
      harlanzw
    },
    rules: {
      'harlanzw/link-ascii-only': 'error',
      'harlanzw/link-lowercase': 'error',
      'harlanzw/link-no-double-slashes': 'error',
      'harlanzw/link-no-whitespace': 'error',
      'harlanzw/nuxt-await-navigate-to': 'error',
      'harlanzw/nuxt-no-redundant-import-meta': 'error',
      'harlanzw/nuxt-no-side-effects-in-async-data-handler': 'error',
      'harlanzw/nuxt-no-side-effects-in-setup': 'error',
      'harlanzw/nuxt-prefer-navigate-to-over-router-push-replace': 'error',
      'harlanzw/nuxt-prefer-nuxt-link-over-router-link': 'error',
      'harlanzw/vue-no-faux-composables': 'error',
      'harlanzw/vue-no-nested-reactivity': 'error',
      'harlanzw/vue-no-passing-refs-as-props': 'error',
      'harlanzw/vue-no-reactive-destructuring': 'error',
      'harlanzw/vue-no-ref-access-in-templates': 'error',
      'harlanzw/vue-no-torefs-on-props': 'error'
    }
  }
]

Sponsors

Credits

This plugin is based on eslint-plugin-antfu by Anthony Fu.

License

Licensed under the MIT license.

[beta]v0.13.0