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>