Vize

Vue Rule Options

Vue rule option examples cover component name casing, prop mutation depth, SFC block order, self-closing tags, event names, and attribute casing. The main Rule Options page lists the complete option table, unknown-field behavior, and scoped replacement semantics.

vue/valid-v-slot

By default, static and dynamic slot arguments reject modifiers such as #item.memo and #[name].memo. Enable allowModifiers when a component API uses dotted slot names, as Vuetify data tables do:

import { defineConfig } from "vize/config";

export default defineConfig({
  linter: {
    rules: { "vue/valid-v-slot": "error" },
    ruleOptions: {
      "vue/valid-v-slot": { allowModifiers: true },
    },
  },
});

Allowed with this config:

<FancyPanel>
  <template #item.memo="{ item }">{{ item.memo }}</template>
  <template #[name].memo="slot">{{ slot }}</template>
</FancyPanel>

An argless v-slot.memo remains invalid with either setting. A dynamic name such as #[slot.name]="slot" also remains invalid: the name is evaluated before that slot's parameters exist. The option only changes modifier policy and does not enable a disabled rule. An explicit allowModifiers: false in a matching entry restores the default policy even when the root config allows modifiers.

vue/component-name-in-template-casing

Use this option when a project wants component tags in templates to be consistently PascalCase or kebab-case. By default, it checks registered component names from <script setup> declarations and direct components registrations. Unregistered tags and scriptless templates stay clear. Use registeredComponentsOnly: false to check all custom tags, or globals: ["PrimaryButton"] for explicitly registered global components. Global names are literal strings; regex patterns and the ESLint ignores option remain unsupported. Native HTML, SVG, MathML, slot and dynamic component tags are skipped.

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  "lint": {
    "vize": {
      "rules": {
        "vue/component-name-in-template-casing": "warn"
      },
      "ruleOptions": {
        "vue/component-name-in-template-casing": {
          "casing": "kebab-case"
        }
      }
    }
  }
});

Bad with the config above:

<script setup>
import PrimaryButton from "./PrimaryButton.vue";
</script>
<template>
  <PrimaryButton />
</template>

Good:

<script setup>
import PrimaryButton from "./PrimaryButton.vue";
</script>
<template>
  <primary-button />
</template>

vue/no-mutating-props

Use shallowOnly when a migration allows nested prop mutation for now but still forbids replacing the prop binding itself. The default false reports both direct and nested mutations.

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  "lint": {
    "vize": {
      "rules": {
        "vue/no-mutating-props": "error"
      },
      "ruleOptions": {
        "vue/no-mutating-props": {
          "shallowOnly": true
        }
      }
    }
  }
});

Bad with the config above:

<script setup>
const props = defineProps<{ count: number; settings: { dense: boolean } }>();

props.count = 2;
</script>

Good with the config above:

<script setup>
const props = defineProps<{ settings: { dense: boolean } }>();

props.settings.dense = true;
</script>

vue/sfc-element-order

Use this option when a project has a fixed SFC block order. A string is one rank; a nested array means any listed block selector may appear at that rank. Supported built-in selectors are script, script:not([setup]), script[setup], template, and style; other non-empty strings match custom block names.

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  "lint": {
    "vize": {
      "rules": {
        "vue/sfc-element-order": "warn"
      },
      "ruleOptions": {
        "vue/sfc-element-order": {
          "order": [
            "template",
            "script:not([setup])",
            "script[setup]",
            "i18n",
            "style"
          ]
        }
      }
    }
  }
});

Bad with the config above:

<style scoped></style>
<template></template>
<script setup></script>

Good:

<template></template>
<script setup></script>
<style scoped></style>

vue/html-self-closing

Use this option to choose self-closing style per element family. always requires empty elements to self-close, never requires paired start/end tags, and any accepts both forms. Omitted nested fields keep the Vize defaults.

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  "lint": {
    "vize": {
      "rules": {
        "vue/html-self-closing": "warn"
      },
      "ruleOptions": {
        "vue/html-self-closing": {
          "html": {
            "void": "always",
            "normal": "never",
            "component": "always"
          },
          "svg": "always",
          "math": "always"
        }
      }
    }
  }
});

Bad with the config above:

<template>
  <div />
  <PrimaryButton></PrimaryButton>
</template>

Good:

<template>
  <div></div>
  <PrimaryButton />
</template>

vue/v-on-event-hyphenation

Use this option for static custom event listener names on components. always reports camelCase listener arguments such as @saveItem; never reports hyphenated listener arguments. Native HTML events, object syntax, and dynamic arguments are skipped.

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  "lint": {
    "vize": {
      "rules": {
        "vue/v-on-event-hyphenation": "warn"
      },
      "ruleOptions": {
        "vue/v-on-event-hyphenation": "always"
      }
    }
  }
});

Bad with the config above:

<template>
  <PrimaryButton @saveItem="save" />
</template>

Good:

<template>
  <PrimaryButton @save-item="save" />
  <button @saveItem="save" />
</template>

vue/attribute-hyphenation

Use this option for static prop names on custom components. always reports camelCase-authored attributes; never reports authored attributes that are hyphenated. Native attributes, aria-*, data-*, SVG mixed-case attributes, dynamic arguments, and directive shorthand that is parsed as an attribute are skipped.

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  "lint": {
    "vize": {
      "rules": {
        "vue/attribute-hyphenation": "warn"
      },
      "ruleOptions": {
        "vue/attribute-hyphenation": "never"
      }
    }
  }
});

Bad with the config above:

<template>
  <UserCard user-name="Ada" />
</template>

Good:

<template>
  <UserCard userName="Ada" aria-label="Ada Lovelace" />
</template>