@@ -27,18 +27,30 @@ function isLabelElement(
2727 return isMatchingElement ( node , allLabelComponents ) ;
2828}
2929
30- function hasLabelElement (
30+ function hasNestedLabelElement (
3131 node : AST . VElement ,
3232 options : FormControlHasLabelOptions
3333) : boolean {
3434 const { parent } = node ;
3535
36- return (
37- [ parent , ...parent . children ] . some ( ( node ) =>
38- isLabelElement ( node , options )
39- ) ||
40- ( parent && parent . type === "VElement" && hasLabelElement ( parent , options ) )
41- ) ;
36+ if ( isLabelElement ( parent , options ) ) {
37+ return true ;
38+ }
39+
40+ return ( parent && parent . type === "VElement" && hasNestedLabelElement ( parent , options ) ) ;
41+ }
42+
43+ /**
44+ * Check if the form control at least has an "id" to be associated with a label
45+ * Can't really check for the label with a matching "for" attribute, because
46+ * checking every element in the file may lead to bad performance.
47+ */
48+ function hasIdForLabelElement (
49+ node : AST . VElement
50+ ) : boolean {
51+ const id = getElementAttributeValue ( node , "id" ) ;
52+
53+ return Boolean ( id ) ;
4254}
4355
4456const rule : Rule . RuleModule = {
@@ -104,7 +116,8 @@ const rule: Rule.RuleModule = {
104116 if (
105117 ! isAriaHidden ( node ) &&
106118 ! hasAriaLabel ( node ) &&
107- ! hasLabelElement ( node , options )
119+ ! hasNestedLabelElement ( node , options ) &&
120+ ! hasIdForLabelElement ( node )
108121 ) {
109122 context . report ( { node : node as any , messageId : "default" } ) ;
110123 }
0 commit comments