Skip to content

Configure v-for-delimiter-style per loop type (array, object, number, string, iterable) #1397

Open
@FloEdelmann

Description

@FloEdelmann

What rule do you want to change?
v-for-delimiter-style

Does this change cause the rule to produce more or fewer warnings?
Without a configuration change, the number won't change.

How will the change be implemented? (New option, new default behavior, etc.)?
New option contextual (instead of in or of).

Please provide some example code that this change will affect:

<template>
  <!-- ✓ GOOD -->
  <div v-for="x of array" />
  <div v-for="x in object" />

  <!-- ✗ BAD -->
  <div v-for="x in array" />
  <div v-for="x of object" />
</template>

<script>
export default {
  data: () => ({
    array: [],
    object: {}
  })
}
</script>

What does the rule currently do for this code?
Either in or of are required everywhere.

What will the rule do after it's changed?
With the contextual option, this rule requires using in when looping through object entries, and of for arrays. When the loop variable type can't be determined, the rule should not enforce either in or of with the contextual style.

When using this contextual style, just glancing over the template is enough to know the loop variable type (array or object), because it mimics a native JavaScript for … in or for … of loop.

Additional context
I've created a diff file that updates the rule documentation and tests:

Diff
diff --git a/docs/rules/v-for-delimiter-style.md b/docs/rules/v-for-delimiter-style.md
index 7239ef0..486de70 100644
--- a/docs/rules/v-for-delimiter-style.md
+++ b/docs/rules/v-for-delimiter-style.md
@@ -34,12 +34,13 @@ Default is set to `in`.
 
 ```json
 {
-  "vue/v-for-delimiter-style": ["error", "in" | "of"]
+  "vue/v-for-delimiter-style": ["error", "in" | "of" | "contextual"]
 }
 ```
 
 - `"in"` (default) ... requires using `in`.
 - `"of"` ... requires using `of`.
+- `"contextual"` ... requires using `in` when looping through object entries, and `of` for arrays.
 
 ### `"of"`
 
@@ -55,6 +56,31 @@ Default is set to `in`.
 </template>
 ```
 
+### `"contextual"`
+
+<eslint-code-block fix :rules="{'vue/v-for-delimiter-style': ['error', 'contextual']}">
+
+```vue
+<template>
+  <!-- ✓ GOOD -->
+  <div v-for="x of array" />
+  <div v-for="x in object" />
+
+  <!-- ✗ BAD -->
+  <div v-for="x in array" />
+  <div v-for="x of object" />
+</template>
+
+<script>
+export default {
+  data: () => ({
+    array: [],
+    object: {}
+  })
+}
+</script>
+```
+
 </eslint-code-block>
 
 ## :books: Further Reading
diff --git a/tests/lib/rules/v-for-delimiter-style.js b/tests/lib/rules/v-for-delimiter-style.js
index 4b232a2..e6ebdaa 100644
--- a/tests/lib/rules/v-for-delimiter-style.js
+++ b/tests/lib/rules/v-for-delimiter-style.js
@@ -53,6 +53,38 @@ tester.run('v-for-delimiter-style', rule, {
       filename: 'test.vue',
       code: '<template><div v-for="x of xs"></div></template>',
       options: ['of']
+    },
+    {
+      filename: 'test.vue',
+      code: '<template><div v-for="x in xs"></div></template>',
+      options: ['contextual']
+    },
+    {
+      filename: 'test.vue',
+      code: '<template><div v-for="x of xs"></div></template>',
+      options: ['contextual']
+    },
+    {
+      filename: 'test.vue',
+      code: `
+        <template><div v-for="x of array"></div></template>
+        <script>
+          export default {
+            data: () => ({ array: [] })
+          }
+        </script>`,
+      options: ['contextual']
+    },
+    {
+      filename: 'test.vue',
+      code: `
+        <template><div v-for="x in object"></div></template>
+        <script>
+          export default {
+            data: () => ({ object: {} })
+          }
+        </script>`,
+      options: ['contextual']
     }
   ],
   invalid: [
@@ -123,6 +155,54 @@ tester.run('v-for-delimiter-style', rule, {
           column: 23
         }
       ]
+    },
+    {
+      filename: 'test.vue',
+      options: ['contextual'],
+      code: `
+        <template><div v-for="x in array"></div></template>
+        <script>
+          export default {
+            data: () => ({ array: [] })
+          }
+        </script>`,
+      output: `
+        <template><div v-for="x of array"></div></template>
+        <script>
+          export default {
+            data: () => ({ array: [] })
+          }
+        </script>`,
+      errors: [
+        {
+          message: "Expected 'of' instead of 'in' in 'v-for'.",
+          column: 23
+        }
+      ]
+    },
+    {
+      filename: 'test.vue',
+      options: ['contextual'],
+      code: `
+        <template><div v-for="x of object"></div></template>
+        <script>
+          export default {
+            data: () => ({ object: {} })
+          }
+        </script>`,
+      output: `
+        <template><div v-for="x in object"></div></template>
+        <script>
+          export default {
+            data: () => ({ object: {} })
+          }
+        </script>`,
+      errors: [
+        {
+          message: "Expected 'in' instead of 'of' in 'v-for'.",
+          column: 23
+        }
+      ]
     }
   ]
 })

v-for-delimiter-contextual.diff.txt

Unfortunately, the type of the loop variable can't be easily determined, so implementing the actual code is too involved for me.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions