Skip to content

Latest commit

 

History

History
383 lines (312 loc) · 7.72 KB

README.md

File metadata and controls

383 lines (312 loc) · 7.72 KB

vue3-script-setup-custom-rules

  • This package contains custom rules to enforce the order of declarations within <script setup> in Vue 3.

🛠 Concept

📌 Order

The declarations in <script setup> are sorted in the following fixed order:

"type",
"defineProps",
"defineEmits",
"defineSlots",
"defineModel",
"defineOptions",
"class",
"plainVars",
"reactiveVars",
"composables",
"computed",
"watchers",
"lifecycle",
"unknowns",
"functions",
"defineExpose"

📌 Separation Between Groups

A single blank line (which corresponds to two consecutive newline characters) is inserted between different groups.
This means that if you have a group of define declarations followed by another group (such as "plainVars"),
there will be one blank line between these groups in the final sorted output.

Example: Consider the following two groups:
Group 1 (defineProps):

const aa = defineProps<{ msg: string }>();

Group 2 (plain variable declarations):

const hello = "Hello World!";
const count = 0

The final sorted output will be:

const aa = defineProps<{ msg: string }>();

const hello = "Hello World!";
const count = 0

Notice the blank line between the two groups, which helps visually separate different types of declarations.



🛠 Section Order Customization

By default, the rule enforces the predefined order of declarations within <script setup>.
However, you can customize the declaration order by specifying the sectionOrder option in eslint.config.js.

📌 Default Order

By default, the rule follows this order:

"type",
"defineProps",
"defineEmits",
"defineSlots",
"defineModel",
"defineOptions",
"class",
"plainVars",
"reactiveVars",
"composables",
"computed",
"watchers",
"lifecycle",
"unknowns",
"functions",
"defineExpose"

📌 Customizing the Order

If you want to specify a custom order, you can do so in eslint.config.js by providing a sectionOrder array.

Example: Prioritizing defineProps and plainVars

// eslint.config.js
export default [
  {
    files: ["**/*.vue"],
    languageOptions: {
      parser: vueEslintParser,
      parserOptions: {
        parser: typescriptEslintParser,
        ecmaVersion: 2022,
        sourceType: "module",
      },
    },
    plugins: {
      "vue3-script-setup": {
        rules: {
          "declaration-order": eslintVueSetupOrderRule,
        },
      },
    },
    rules: {
      "vue3-script-setup/declaration-order": [
        "error",
        {
          sectionOrder: ["defineProps", "plainVars"], // this!!
        },
      ],
    },
  },
];

In this case:

  • defineProps will always be placed before plainVars.
  • Other declarations will follow their default order.

📌 Invalid Section Order Handling

If an invalid section is provided in sectionOrder, an ESLint error will be thrown.

For example, this incorrect configuration:

"vue3-script-setup/declaration-order": [
  "error",
  {
    sectionOrder: ["defineProps", "invalidSection"],
  },
],

will result in the following error:

Error: Invalid "sectionOrder" option: "invalidSection" is not a recognized section. Valid sections: defineProps, defineEmits, defineOthers, plainVars, reactiveVars, composables, computed, watchers, lifecycle, functions, unknowns.
This ensures that only valid sections are allowed, preventing misconfiguration.

With this customization, you can fine-tune the declaration order to suit your project’s coding style while still enforcing consistency. 🚀



🛠 lifecycle Order Customization

By default, the rule enforces the predefined order of declarations within <script setup>.
However, you can customize the declaration order by specifying the lifecycleOrder option in eslint.config.js.

📌 Default Order

By default, the rule follows this order:

onBeforeMount: 0,
onMounted: 1,
onBeforeUpdate: 2,
onUpdated: 3,
onBeforeUnmount: 4,
onUnmounted: 5,
onErrorCaptured: 6,
onRenderTracked: 7,
onRenderTriggered: 8,
onActivated: 9,
onDeactivated: 10,
onServerPrefetch: 11,

📌 Customizing the Order

If you want to specify a custom order, you can do so in eslint.config.js by providing a lifecycleOrder object.

Example: Prioritizing defineProps and plainVars

// eslint.config.js
export default [
  {
    files: ["**/*.vue"],
    languageOptions: {
      parser: vueEslintParser,
      parserOptions: {
        parser: typescriptEslintParser,
        ecmaVersion: 2022,
        sourceType: "module",
      },
    },
    plugins: {
      "vue3-script-setup": {
        rules: {
          "declaration-order": eslintVueSetupOrderRule,
        },
      },
    },
    rules: {
      "vue3-script-setup/declaration-order": [
        "error",
        {
          lifecycleOrder: { // this!!
            onMounted: 0,
            onBeforeMount: 1,
          }
        },
      ],
    },
  },
];

In this case:

  • onMounted will always be placed before onBeforeMount.

🛠 How to Apply

📌 Method 1: Install via npm

pnpm install eslint-vue-setup-rules

OR

yarn add eslint-vue-setup-rules

OR 

pnpm install https://github.com/KumJungMin/eslint-vue-setup-order

Then, add the ESLint plugin to your eslint.config.js (for ESLint v9 using the flat config pattern):

// eslint.config.js
import vueSetupRules from "eslint-vue-setup-rules";

export default [
  {
    // Add the plugin object here:
    plugins: { "vue3-script-setup": vueSetupRules },
    rules: { "vue3-script-setup/declaration-order": "error" },
  },
  {
    files: ["**/*.vue"],
    languageOptions: {
      parser: vueEslintParser,
      parserOptions: {
        parser: typescriptEslintParser,
        ecmaVersion: 2022,
        sourceType: "module",
      },
    },
  },
  // ... other settings
];

📌 Method 2: Include the Rules File in Your Project

Alternatively, you can add the rule file directly to your project:

  1. Add the file rules/declaration-order.js to your project directory:
your-project/
├── src/
   └── eslint-rules/
       └── declaration-order.js
├── eslint.config.js
└── ...
  1. Then, update your eslint.config.js to include the custom rule:
import eslintVueSetupOrderRule from "./src/eslint-rules/declaration-order.js";
 
export default [
  {
    files: ["**/*.vue"],
    languageOptions: {
      parser: vueEslintParser,
      parserOptions: {
        parser: typescriptEslintParser,
        ecmaVersion: 2022,
        sourceType: "module",
      },
    },
    plugins: {
      "vue3-script-setup": {
        rules: {
          "declaration-order": eslintVueSetupOrderRule, // this!
        },
      },
    },
    rules: {
      "vue3-script-setup/declaration-order": "error",
    },
  },
  // ... other settings
];

🛠 Testing

When you run the command:

npx eslint .

If the declaration order is incorrect, the rule will automatically fix it. For example:
Before:

<script setup lang="ts">
import { onBeforeMount, ref } from "vue";

const count = ref(0);
const msg = ref("");
const aa = defineProps<{ msg: string }>();
const emits = defineEmits();
const hello = "Hello World!";

const changeMsg = () => {};
function handleClick() {
  emits("click");
}

onBeforeMount(() => {
  console.log("onBeforeMount");
});
</script>

<template>
</template>

After (fixed):

<script setup lang="ts">
import { onBeforeMount, ref } from "vue";

const aa = defineProps<{ msg: string }>();
const emits = defineEmits();

const hello = "Hello World!";

const count = ref(0);
const msg = ref("");

onBeforeMount(() => {
  console.log("onBeforeMount");
});

const changeMsg = () => {};
function handleClick() {
  emits("click");
}
</script>