44// `roles.get(r).prohibitedProps` list drives the flag/allow decision.
55
66const { roles, elementRoles } = require ( 'aria-query' ) ;
7+ const { isNativeElement } = require ( '../utils/is-native-element' ) ;
78
89function findAttr ( node , name ) {
910 return node . attributes ?. find ( ( attr ) => attr . name === name ) ;
@@ -17,11 +18,6 @@ function getStaticAttrString(node, name) {
1718 return attr . value . chars ;
1819}
1920
20- function isHtmlElement ( node ) {
21- const tag = node . tag || '' ;
22- return / ^ [ a - z ] / . test ( tag ) && ! tag . includes ( '.' ) && ! tag . startsWith ( '@' ) ;
23- }
24-
2521// Score how well an elementRoles entry matches the given node. Returns `null`
2622// if any constraint fails; otherwise the number of satisfied conditions
2723// (higher = more specific, used to pick the best match).
@@ -162,10 +158,16 @@ module.exports = {
162158
163159 create ( context ) {
164160 const strictTabindex = Boolean ( context . options [ 0 ] ?. strictTabindex ) ;
161+ const sourceCode = context . sourceCode || context . getSourceCode ( ) ;
165162
166163 return {
167164 GlimmerElementNode ( node ) {
168- if ( ! isHtmlElement ( node ) ) {
165+ // Gate on `isNativeElement` to correctly exclude custom elements
166+ // (<my-widget>), colon-namespaced tags (<svg:rect>), named blocks
167+ // (<:slot>), PascalCase components, dotted/at-prefixed path tags,
168+ // and scope-shadowed bindings. The previous first-char regex was
169+ // permissive and misclassified custom elements as native HTML.
170+ if ( ! isNativeElement ( node , sourceCode ) ) {
169171 return ;
170172 }
171173 if ( isExplicitlyDecorative ( node ) ) {
0 commit comments