Skip to content

Commit a77ab85

Browse files
Merge pull request #2444 from NullVoxPopuli/nvp/template-lint-extract-rule-template-no-input-placeholder
Extract rule: template-no-input-placeholder
2 parents 3b3b95e + 562a732 commit a77ab85

File tree

4 files changed

+158
-0
lines changed

4 files changed

+158
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ rules in templates can be disabled with eslint directives with mustache or html
203203
| [template-no-chained-this](docs/rules/template-no-chained-this.md) | disallow redundant `this.this` in templates | | 🔧 | |
204204
| [template-no-debugger](docs/rules/template-no-debugger.md) | disallow {{debugger}} in templates | | | |
205205
| [template-no-element-event-actions](docs/rules/template-no-element-event-actions.md) | disallow element event actions (use {{on}} modifier instead) | | | |
206+
| [template-no-input-placeholder](docs/rules/template-no-input-placeholder.md) | disallow placeholder attribute on input elements | | | |
206207
| [template-no-input-tagname](docs/rules/template-no-input-tagname.md) | disallow tagName attribute on {{input}} helper | | | |
207208
| [template-no-log](docs/rules/template-no-log.md) | disallow {{log}} in templates | | | |
208209

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# ember/template-no-input-placeholder
2+
3+
<!-- end auto-generated rule header -->
4+
5+
Disallows `placeholder` attribute on input elements.
6+
7+
## Rule Details
8+
9+
The `placeholder` attribute should not be used as it has accessibility issues. Use proper labels instead.
10+
11+
## Examples
12+
13+
Examples of **incorrect** code for this rule:
14+
15+
```gjs
16+
<template>
17+
<input placeholder="Enter username" />
18+
</template>
19+
```
20+
21+
```gjs
22+
<template>
23+
<input type="text" placeholder="Username" />
24+
</template>
25+
```
26+
27+
Examples of **correct** code for this rule:
28+
29+
```gjs
30+
<template>
31+
<label>
32+
Username
33+
<input type="text" />
34+
</label>
35+
</template>
36+
```
37+
38+
```gjs
39+
<template>
40+
<input type="text" aria-label="Username" />
41+
</template>
42+
```
43+
44+
## References
45+
46+
- [eslint-plugin-ember template-no-input-placeholder](https://github.com/ember-cli/eslint-plugin-ember/blob/master/docs/rules/template-no-input-placeholder.md)
47+
- [Placeholders in Form Fields Are Harmful](https://www.nngroup.com/articles/form-design-placeholders/)
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/** @type {import('eslint').Rule.RuleModule} */
2+
module.exports = {
3+
meta: {
4+
type: 'suggestion',
5+
docs: {
6+
description: 'disallow placeholder attribute on input elements',
7+
category: 'Best Practices',
8+
strictGjs: true,
9+
strictGts: true,
10+
url: 'https://github.com/ember-cli/eslint-plugin-ember/tree/master/docs/rules/template-no-input-placeholder.md',
11+
},
12+
fixable: null,
13+
schema: [],
14+
messages: {
15+
noPlaceholder:
16+
'Do not use placeholder attribute. Use a label instead for better accessibility.',
17+
},
18+
},
19+
20+
create(context) {
21+
return {
22+
GlimmerElementNode(node) {
23+
if (node.tag === 'input' && node.attributes) {
24+
for (const attr of node.attributes) {
25+
if (attr.type === 'GlimmerAttrNode' && attr.name === 'placeholder') {
26+
context.report({
27+
node: attr,
28+
messageId: 'noPlaceholder',
29+
});
30+
}
31+
}
32+
}
33+
},
34+
};
35+
},
36+
};
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
//------------------------------------------------------------------------------
2+
// Requirements
3+
//------------------------------------------------------------------------------
4+
5+
const rule = require('../../../lib/rules/template-no-input-placeholder');
6+
const RuleTester = require('eslint').RuleTester;
7+
8+
//------------------------------------------------------------------------------
9+
// Tests
10+
//------------------------------------------------------------------------------
11+
12+
const ruleTester = new RuleTester({
13+
parser: require.resolve('ember-eslint-parser'),
14+
parserOptions: { ecmaVersion: 2022, sourceType: 'module' },
15+
});
16+
17+
ruleTester.run('template-no-input-placeholder', rule, {
18+
valid: [
19+
`<template>
20+
<label>
21+
Username
22+
<input type="text" />
23+
</label>
24+
</template>`,
25+
`<template>
26+
<input type="text" aria-label="Username" />
27+
</template>`,
28+
`<template>
29+
<div></div>
30+
</template>`,
31+
],
32+
33+
invalid: [
34+
{
35+
code: `<template>
36+
<input placeholder="Enter username" />
37+
</template>`,
38+
output: null,
39+
errors: [
40+
{
41+
message:
42+
'Do not use placeholder attribute. Use a label instead for better accessibility.',
43+
type: 'GlimmerAttrNode',
44+
},
45+
],
46+
},
47+
{
48+
code: `<template>
49+
<input type="text" placeholder="Username" />
50+
</template>`,
51+
output: null,
52+
errors: [
53+
{
54+
message:
55+
'Do not use placeholder attribute. Use a label instead for better accessibility.',
56+
type: 'GlimmerAttrNode',
57+
},
58+
],
59+
},
60+
{
61+
code: `<template>
62+
<input type="email" placeholder="Email" />
63+
</template>`,
64+
output: null,
65+
errors: [
66+
{
67+
message:
68+
'Do not use placeholder attribute. Use a label instead for better accessibility.',
69+
type: 'GlimmerAttrNode',
70+
},
71+
],
72+
},
73+
],
74+
});

0 commit comments

Comments
 (0)