Repository: vuejs/eslint-plugin-vue
Pull request #2160 (2023-05-13 01:24:29)

Add support for `defineOptions` to `vue/order-in-components` rule
Related to https://github.com/vuejs/eslint-plugin-vue/issues/2118


Patch:
diff --git a/docs/rules/valid-v-is.md b/docs/rules/valid-v-is.md
index 6eda3d99..0ef75aac 100644
--- a/docs/rules/valid-v-is.md
+++ b/docs/rules/valid-v-is.md
@@ -59,7 +59,7 @@ Nothing.
 
 ## :books: Further Reading
 
-- [API - v-is](https://vuejs.org/api/built-in-directives.html#v-is)
+- [API - v-is (Recent)](https://github.com/vuejs/docs/blob/8b4f11a4e94d01c7f1c91a60ceaa5b89d6b6de9f/src/api/built-in-directives.md#v-is-)
 - [API - v-is (Old)](https://github.com/vuejs/docs-next/blob/008613756c3d781128d96b64a2d27f7598f8f548/src/api/directives.md#v-is)
 
 ## :rocket: Version
diff --git a/lib/rules/component-definition-name-casing.js b/lib/rules/component-definition-name-casing.js
index e227d4b9..c3a5cbc3 100644
--- a/lib/rules/component-definition-name-casing.js
+++ b/lib/rules/component-definition-name-casing.js
@@ -77,8 +77,7 @@ module.exports = {
       }
     }
 
-    return Object.assign(
-      {},
+    return utils.compositingVisitors(
       utils.executeOnCallVueComponent(context, (node) => {
         if (node.arguments.length === 2) {
           const argument = node.arguments[0]
@@ -94,6 +93,17 @@ module.exports = {
         if (!node) return
         if (!canConvert(node.value)) return
         convertName(node.value)
+      }),
+      utils.defineScriptSetupVisitor(context, {
+        onDefineOptionsEnter(node) {
+          if (node.arguments.length === 0) return
+          const define = node.arguments[0]
+          if (define.type !== 'ObjectExpression') return
+          const nameNode = utils.findProperty(define, 'name')
+          if (!nameNode) return
+          if (!canConvert(nameNode.value)) return
+          convertName(nameNode.value)
+        }
       })
     )
   }
diff --git a/lib/rules/order-in-components.js b/lib/rules/order-in-components.js
index cf9dba9d..50e27062 100644
--- a/lib/rules/order-in-components.js
+++ b/lib/rules/order-in-components.js
@@ -334,8 +334,18 @@ module.exports = {
       }
     }
 
-    return utils.executeOnVue(context, (obj) => {
-      checkOrder(obj.properties)
-    })
+    return utils.compositingVisitors(
+      utils.executeOnVue(context, (obj) => {
+        checkOrder(obj.properties)
+      }),
+      utils.defineScriptSetupVisitor(context, {
+        onDefineOptionsEnter(node) {
+          if (node.arguments.length === 0) return
+          const define = node.arguments[0]
+          if (define.type !== 'ObjectExpression') return
+          checkOrder(define.properties)
+        }
+      })
+    )
   }
 }


Test patch:
diff --git a/tests/lib/rules/component-definition-name-casing.js b/tests/lib/rules/component-definition-name-casing.js
index ef9cbde8..2349f5d3 100644
--- a/tests/lib/rules/component-definition-name-casing.js
+++ b/tests/lib/rules/component-definition-name-casing.js
@@ -145,6 +145,26 @@ ruleTester.run('component-definition-name-casing', rule, {
       filename: 'test.js',
       code: `fn1(component.data)`,
       parserOptions
+    },
+    {
+      filename: 'test.vue',
+      code: `<script setup> defineOptions({}) </script>`,
+      parser: require.resolve('vue-eslint-parser'),
+      parserOptions
+    },
+    {
+      filename: 'test.vue',
+      code: `<script setup> defineOptions({name: 'FooBar'}) </script>`,
+      options: ['PascalCase'],
+      parser: require.resolve('vue-eslint-parser'),
+      parserOptions
+    },
+    {
+      filename: 'test.vue',
+      code: `<script setup> defineOptions({name: 'foo-bar'}) </script>`,
+      options: ['kebab-case'],
+      parser: require.resolve('vue-eslint-parser'),
+      parserOptions
     }
   ],
 
@@ -393,6 +413,34 @@ ruleTester.run('component-definition-name-casing', rule, {
           line: 1
         }
       ]
+    },
+    {
+      filename: 'test.vue',
+      code: `<script setup> defineOptions({name: 'foo-bar'}) </script>`,
+      output: `<script setup> defineOptions({name: 'FooBar'}) </script>`,
+      options: ['PascalCase'],
+      parser: require.resolve('vue-eslint-parser'),
+      parserOptions,
+      errors: [
+        {
+          message: 'Property name "foo-bar" is not PascalCase.',
+          line: 1
+        }
+      ]
+    },
+    {
+      filename: 'test.vue',
+      code: `<script setup> defineOptions({name: 'FooBar'}) </script>`,
+      output: `<script setup> defineOptions({name: 'foo-bar'}) </script>`,
+      options: ['kebab-case'],
+      parser: require.resolve('vue-eslint-parser'),
+      parserOptions,
+      errors: [
+        {
+          message: 'Property name "FooBar" is not kebab-case.',
+          line: 1
+        }
+      ]
     }
   ]
 })
diff --git a/tests/lib/rules/order-in-components.js b/tests/lib/rules/order-in-components.js
index 873df3b0..b12c41a3 100644
--- a/tests/lib/rules/order-in-components.js
+++ b/tests/lib/rules/order-in-components.js
@@ -165,6 +165,19 @@ ruleTester.run('order-in-components', rule, {
         new Vue()
       `,
       parserOptions: { ecmaVersion: 6 }
+    },
+    {
+      filename: 'example.vue',
+      code: `
+      <script setup>
+        defineOptions({
+          name: 'Foo',
+          inheritAttrs: true,
+        })
+      </script>
+      `,
+      parser: require.resolve('vue-eslint-parser'),
+      parserOptions
     }
   ],
 
@@ -943,6 +956,34 @@ ruleTester.run('order-in-components', rule, {
           line: 5
         }
       ]
+    },
+    {
+      filename: 'example.vue',
+      code: `
+      <script setup>
+        defineOptions({
+          inheritAttrs: true,
+          name: 'Foo',
+        })
+      </script>
+      `,
+      parser: require.resolve('vue-eslint-parser'),
+      parserOptions,
+      output: `
+      <script setup>
+        defineOptions({
+          name: 'Foo',
+          inheritAttrs: true,
+        })
+      </script>
+      `,
+      errors: [
+        {
+          message:
+            'The "name" property should be above the "inheritAttrs" property on line 4.',
+          line: 5
+        }
+      ]
     }
   ]
 })