Skip to content

Commit 61e93d8

Browse files
check for siblings and refactor checkForKey func
1 parent 77af4b4 commit 61e93d8

File tree

1 file changed

+56
-25
lines changed

1 file changed

+56
-25
lines changed

lib/rules/v-if-else-key.js

Lines changed: 56 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,33 @@ const casing = require('../utils/casing')
2525
* @property {VElement | null} else - The node associated with the 'v-else' directive, or null if there isn't one.
2626
*/
2727

28+
/**
29+
* Checks if a given node has sibling nodes of the same type that are also conditionally rendered.
30+
* This is used to determine if multiple instances of the same component are being conditionally
31+
* rendered within the same parent scope.
32+
*
33+
* @param {VElement} node - The Vue component node to check for conditional rendering siblings.
34+
* @param {string} componentName - The name of the component to check for sibling instances.
35+
* @returns {boolean} True if there are sibling nodes of the same type and conditionally rendered, false otherwise.
36+
*/
37+
const hasConditionalRenderedSiblings = (node, componentName) => {
38+
if (node.parent && node.parent.type === 'VElement') {
39+
const siblings = node.parent.children.filter(
40+
(child) => child.type === 'VElement'
41+
)
42+
43+
return siblings.some(
44+
(sibling) =>
45+
sibling !== node &&
46+
sibling.type === 'VElement' &&
47+
sibling.rawName === componentName &&
48+
hasConditionalDirective(sibling)
49+
)
50+
}
51+
52+
return false
53+
}
54+
2855
/**
2956
* Checks for the presence of a 'key' attribute in the given node. If the 'key' attribute is missing
3057
* and the node is part of a conditional family a report is generated.
@@ -44,35 +71,39 @@ const checkForKey = (
4471
uniqueKey,
4572
conditionalFamilies
4673
) => {
47-
if (node.parent && node.parent.type === 'VElement') {
74+
if (
75+
node.parent &&
76+
node.parent.type === 'VElement' &&
77+
hasConditionalRenderedSiblings(node, componentName)
78+
) {
4879
const conditionalFamily = conditionalFamilies.get(node.parent)
4980

50-
if (
51-
conditionalFamily &&
52-
(utils.hasDirective(node, 'bind', 'key') ||
53-
utils.hasAttribute(node, 'key') ||
54-
!hasConditionalDirective(node) ||
55-
!(conditionalFamily.else || conditionalFamily.elseIf.length > 0))
56-
) {
57-
return
58-
}
81+
if (conditionalFamily && !utils.hasAttribute(node, 'key')) {
82+
let needsKey = false
5983

60-
context.report({
61-
node: node.startTag,
62-
loc: node.startTag.loc,
63-
messageId: 'requireKey',
64-
data: {
65-
componentName
66-
},
67-
fix(fixer) {
68-
const afterComponentNamePosition =
69-
node.startTag.range[0] + componentName.length + 1
70-
return fixer.insertTextBeforeRange(
71-
[afterComponentNamePosition, afterComponentNamePosition],
72-
` key="${uniqueKey}"`
73-
)
84+
if (node === conditionalFamily.if || node === conditionalFamily.else) {
85+
needsKey = true
86+
} else if (conditionalFamily.elseIf.includes(node)) {
87+
needsKey = true
7488
}
75-
})
89+
90+
if (needsKey) {
91+
context.report({
92+
node: node.startTag,
93+
loc: node.startTag.loc,
94+
messageId: 'requireKey',
95+
data: { componentName },
96+
fix(fixer) {
97+
const afterComponentNamePosition =
98+
node.startTag.range[0] + componentName.length + 1
99+
return fixer.insertTextBeforeRange(
100+
[afterComponentNamePosition, afterComponentNamePosition],
101+
` key="${uniqueKey}"`
102+
)
103+
}
104+
})
105+
}
106+
}
76107
}
77108
}
78109

0 commit comments

Comments
 (0)