Script Rule Options
Script rule option examples cover restricted globals, restricted members, compiler macro order, and custom event casing. The main Rule Options page lists the complete option table, unknown-field behavior, and scoped replacement semantics.
script/no-restricted-globals
Use this rule when runtime globals must go through project-owned wrappers. Without options, the
rule reports process, localStorage, and sessionStorage. A non-empty globals list replaces
that built-in list; an empty list falls back to the built-ins so a config typo cannot silently
disable the rule.
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({}).withVue({
linter: {
rules: {
"script/no-restricted-globals": "error",
},
ruleOptions: {
"script/no-restricted-globals": {
globals: [
{
name: "process",
message: "Read env through useRuntimeConfig().",
},
{
name: "localStorage",
},
],
},
},
},
});
Bad:
const flag = process.env.FEATURE_FLAG;
const token = localStorage.getItem("auth.token");
Good:
const flag = useRuntimeConfig().featureFlag;
const token = authStorage.read("auth.token");
script/no-restricted-members
Use this rule for project-local member access bans, such as moving browser APIs behind SSR-safe
helpers. The rule has no built-in deny list; it only reports when members is non-empty and the
rule is enabled. Each entry matches a bare identifier receiver plus a static property name.
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({}).withVue({
linter: {
rules: {
"script/no-restricted-members": "error",
},
ruleOptions: {
"script/no-restricted-members": {
members: [
{
object: "window",
property: "localStorage",
message: "Use authStorage.",
},
{
object: "globalThis",
property: "process",
},
],
},
},
},
});
Bad:
const token = window.localStorage.getItem("auth.token");
const env = globalThis.process.env;
Good:
const token = authStorage.read("auth.token");
const env = readServerEnv();
script/custom-event-name-casing
Use this option when emitted custom events should follow one casing convention across both script
and template usage. The default is camelCase; set kebab-case for projects that author emitted
event names in their template-facing form.
Component v-model events beginning with update: are accepted in either mode because their
suffix mirrors the corresponding prop name.
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({}).withVue({
linter: {
rules: {
"script/custom-event-name-casing": "error",
},
ruleOptions: {
"script/custom-event-name-casing": {
casing: "kebab-case",
},
},
},
});
Bad with the config above:
const emit = defineEmits(["saveItem"]);
emit("saveItem");
Good:
const emit = defineEmits(["save-item"]);
emit("save-item");
script/define-macros-order
Use order to choose which compiler macros must appear first in <script setup> and in what
sequence. The default is ["defineProps", "defineEmits"]. Macros omitted from the list behave
like ordinary statements.
The public lintPatinaSfc API accepts this policy through ruleOptionsJson. An entry there
overrides the compatibility defineMacrosOrder option; an empty policy object restores the
default order, while an omitted entry keeps the compatibility policy. Options alone do not
enable an unselected rule.
Patina currently reports macro-order diagnostics without text edits. The pinned ESLint rule
can reorder statements; this configuration support does not add that fixer or defineExposeLast.
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({}).withVue({
linter: {
rules: { "script/define-macros-order": "warn" },
ruleOptions: {
"script/define-macros-order": {
order: ["defineOptions", "defineProps", "defineEmits", "defineSlots"],
},
},
},
});
Bad with the config above:
<script setup lang="ts">
const props = defineProps<{ label: string }>();
defineOptions({ inheritAttrs: false });
</script>
Good:
<script setup lang="ts">
defineOptions({ inheritAttrs: false });
const props = defineProps<{ label: string }>();
</script>
script/define-props-destructuring
The default, only-when-assigned, requires a destructured binding when the result is assigned.
A bare defineProps<Props>() is allowed. always also reports bare calls; never reports
destructured bindings instead. Vue 3.5 preserves reactivity when destructuring props.
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({}).withVue({
linter: {
preset: "incremental",
rules: { "script/define-props-destructuring": "warn" },
ruleOptions: { "script/define-props-destructuring": { destructure: "only-when-assigned" } },
},
});
Bad:
<script setup lang="ts">
const props = defineProps<{ size?: string }>();
</script>
Good:
<script setup lang="ts">
const { size = "md" } = defineProps<{ size?: string }>();
</script>
When migrating from ESLint, use the Vize rule ID and typed options separately:
rules: { "vue/define-props-destructuring": ["warn", "always"] }
rules: { "script/define-props-destructuring": "warn" },
ruleOptions: { "script/define-props-destructuring": { destructure: "always" } }
Place the added entries inside the linter object passed to withVue in the Vite+ config above.