Skip to content

Commit fa51c92

Browse files
committed
fix: normalize attr names to lowercase; add isNativeElement scope check; tests for UPPERCASE attrs
1 parent a48260c commit fa51c92

2 files changed

Lines changed: 15 additions & 1 deletion

File tree

lib/rules/template-valid-input-attributes.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
// Logic adapted from html-validate (MIT), Copyright 2017 David Sveningsson.
44

5+
const { isNativeElement } = require('../utils/is-native-element');
6+
57
const RESTRICTED = new Map([
68
['accept', new Set(['file'])],
79
['alt', new Set(['image'])],
@@ -124,11 +126,15 @@ module.exports = {
124126
},
125127

126128
create(context) {
129+
const sourceCode = context.sourceCode || context.getSourceCode();
127130
return {
128131
GlimmerElementNode(node) {
129132
if (node.tag !== 'input') {
130133
return;
131134
}
135+
if (!isNativeElement(node, sourceCode)) {
136+
return;
137+
}
132138
// Per HTML §4.10.5, an <input> with missing, valueless, empty, or
133139
// unknown `type` falls back to the Text state. Only a DYNAMIC type
134140
// (mustache/concat) is opaque to static analysis — skip those.
@@ -151,7 +157,7 @@ module.exports = {
151157
const type = KNOWN_INPUT_TYPES.has(normalized) ? normalized : 'text';
152158

153159
for (const attr of node.attributes || []) {
154-
const validTypes = RESTRICTED.get(attr.name);
160+
const validTypes = RESTRICTED.get(attr.name.toLowerCase());
155161
if (!validTypes) {
156162
continue;
157163
}

tests/lib/rules/template-valid-input-attributes.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ const validHbs = [
2424
'<input pattern="\\d+" />',
2525
'<input type />',
2626
'<input maxlength="100" size="20" readonly />',
27+
// Attribute name case — HTML attributes are case-insensitive; rule normalizes.
28+
'<input type="text" MAXLENGTH="5" />',
29+
'<input type="text" Pattern="\\d+" />',
2730
// Not an input — rule doesn't apply.
2831
'<textarea maxlength="10"></textarea>',
2932
// Empty/whitespace/unknown type values fall back to the Text state per HTML
@@ -63,6 +66,11 @@ const invalidHbs = [
6366
code: '<input type="TEXT" accept="image/*" />',
6467
errors: [{ message: err('accept', 'text') }],
6568
},
69+
// Uppercase attribute name — normalized before restriction lookup.
70+
{
71+
code: '<input type="number" PATTERN="x" />',
72+
errors: [{ message: err('PATTERN', 'number') }],
73+
},
6674
// Text-state fallback — <input> with missing/valueless/empty/unknown type
6775
// is the Text state per HTML spec. Attributes incompatible with text are
6876
// flagged as `type="text"` in the error message.

0 commit comments

Comments
 (0)