Skip to content

Commit 3ee3608

Browse files
committed
Extract rule: template-no-block-params-for-html-elements
1 parent 2a8b954 commit 3ee3608

4 files changed

Lines changed: 282 additions & 8 deletions

File tree

README.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -188,14 +188,15 @@ rules in templates can be disabled with eslint directives with mustache or html
188188

189189
### Best Practices
190190

191-
| Name | Description | 💼 | 🔧 | 💡 |
192-
| :----------------------------------------------------------------------------------------------- | :-------------------------------------------------------- | :- | :- | :- |
193-
| [template-builtin-component-arguments](docs/rules/template-builtin-component-arguments.md) | disallow setting certain attributes on builtin components | | | |
194-
| [template-no-action-modifiers](docs/rules/template-no-action-modifiers.md) | disallow usage of {{action}} modifiers | | | |
195-
| [template-no-arguments-for-html-elements](docs/rules/template-no-arguments-for-html-elements.md) | disallow @arguments on HTML elements | | | |
196-
| [template-no-array-prototype-extensions](docs/rules/template-no-array-prototype-extensions.md) | disallow usage of Ember Array prototype extensions | | | |
197-
| [template-no-debugger](docs/rules/template-no-debugger.md) | disallow {{debugger}} in templates | | | |
198-
| [template-no-log](docs/rules/template-no-log.md) | disallow {{log}} in templates | | | |
191+
| Name | Description | 💼 | 🔧 | 💡 |
192+
| :----------------------------------------------------------------------------------------------------- | :-------------------------------------------------------- | :- | :- | :- |
193+
| [template-builtin-component-arguments](docs/rules/template-builtin-component-arguments.md) | disallow setting certain attributes on builtin components | | | |
194+
| [template-no-action-modifiers](docs/rules/template-no-action-modifiers.md) | disallow usage of {{action}} modifiers | | | |
195+
| [template-no-arguments-for-html-elements](docs/rules/template-no-arguments-for-html-elements.md) | disallow @arguments on HTML elements | | | |
196+
| [template-no-array-prototype-extensions](docs/rules/template-no-array-prototype-extensions.md) | disallow usage of Ember Array prototype extensions | | | |
197+
| [template-no-block-params-for-html-elements](docs/rules/template-no-block-params-for-html-elements.md) | disallow block params on HTML elements | | | |
198+
| [template-no-debugger](docs/rules/template-no-debugger.md) | disallow {{debugger}} in templates | | | |
199+
| [template-no-log](docs/rules/template-no-log.md) | disallow {{log}} in templates | | | |
199200

200201
### Components
201202

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# ember/template-no-block-params-for-html-elements
2+
3+
<!-- end auto-generated rule header -->
4+
5+
💼 This rule is enabled in the following [configs](https://github.com/ember-cli/eslint-plugin-ember#-configurations): `strict-gjs`, `strict-gts`.
6+
7+
Disallow block params on HTML elements.
8+
9+
Block params (using the `as |param|` syntax) are a feature specific to Ember components and block helpers. They should not be used on regular HTML elements.
10+
11+
## Rule Details
12+
13+
This rule disallows using block params on HTML elements. Use components if you need to pass block params.
14+
15+
## Examples
16+
17+
### Incorrect ❌
18+
19+
```gjs
20+
<template>
21+
<div as |content|>
22+
{{content}}
23+
</div>
24+
</template>
25+
```
26+
27+
```gjs
28+
<template>
29+
<section as |data|>
30+
<p>{{data}}</p>
31+
</section>
32+
</template>
33+
```
34+
35+
```gjs
36+
<template>
37+
<ul as |items|>
38+
<li>{{items}}</li>
39+
</ul>
40+
</template>
41+
```
42+
43+
### Correct ✅
44+
45+
```gjs
46+
<template>
47+
<div>Content</div>
48+
</template>
49+
```
50+
51+
```gjs
52+
<template>
53+
<MyComponent as |item|>
54+
{{item.name}}
55+
</MyComponent>
56+
</template>
57+
```
58+
59+
```gjs
60+
<template>
61+
{{#each this.items as |item|}}
62+
<li>{{item}}</li>
63+
{{/each}}
64+
</template>
65+
```
66+
67+
## Related Rules
68+
69+
- [template-no-arguments-for-html-elements](./template-no-arguments-for-html-elements.md)
70+
71+
## References
72+
73+
- [Ember Guides - Block Content](https://guides.emberjs.com/release/components/block-content/)
74+
- [eslint-plugin-ember template-no-yield-only](https://github.com/ember-cli/eslint-plugin-ember/blob/master/docs/rules/template-no-yield-only.md)
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
/** @type {import('eslint').Rule.RuleModule} */
2+
module.exports = {
3+
meta: {
4+
type: 'problem',
5+
docs: {
6+
description: 'disallow block params on HTML 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-block-params-for-html-elements.md',
11+
},
12+
fixable: null,
13+
schema: [],
14+
messages: {
15+
noBlockParamsForHtmlElements:
16+
'Block params can only be used with components, not HTML elements.',
17+
},
18+
},
19+
20+
create(context) {
21+
const HTML_ELEMENTS = new Set([
22+
'a',
23+
'abbr',
24+
'address',
25+
'area',
26+
'article',
27+
'aside',
28+
'audio',
29+
'b',
30+
'base',
31+
'bdi',
32+
'bdo',
33+
'blockquote',
34+
'body',
35+
'br',
36+
'button',
37+
'canvas',
38+
'caption',
39+
'cite',
40+
'code',
41+
'col',
42+
'colgroup',
43+
'data',
44+
'datalist',
45+
'dd',
46+
'del',
47+
'details',
48+
'dfn',
49+
'dialog',
50+
'div',
51+
'dl',
52+
'dt',
53+
'em',
54+
'embed',
55+
'fieldset',
56+
'figcaption',
57+
'figure',
58+
'footer',
59+
'form',
60+
'h1',
61+
'h2',
62+
'h3',
63+
'h4',
64+
'h5',
65+
'h6',
66+
'head',
67+
'header',
68+
'hr',
69+
'html',
70+
'i',
71+
'iframe',
72+
'img',
73+
'input',
74+
'ins',
75+
'kbd',
76+
'label',
77+
'legend',
78+
'li',
79+
'link',
80+
'main',
81+
'map',
82+
'mark',
83+
'meta',
84+
'meter',
85+
'nav',
86+
'noscript',
87+
'object',
88+
'ol',
89+
'optgroup',
90+
'option',
91+
'output',
92+
'p',
93+
'param',
94+
'picture',
95+
'pre',
96+
'progress',
97+
'q',
98+
'rp',
99+
'rt',
100+
'ruby',
101+
's',
102+
'samp',
103+
'script',
104+
'section',
105+
'select',
106+
'small',
107+
'source',
108+
'span',
109+
'strong',
110+
'style',
111+
'sub',
112+
'summary',
113+
'sup',
114+
'table',
115+
'tbody',
116+
'td',
117+
'template',
118+
'textarea',
119+
'tfoot',
120+
'th',
121+
'thead',
122+
'time',
123+
'title',
124+
'tr',
125+
'track',
126+
'u',
127+
'ul',
128+
'var',
129+
'video',
130+
'wbr',
131+
]);
132+
133+
return {
134+
GlimmerElementNode(node) {
135+
// Check if this is an HTML element (lowercase)
136+
if (!HTML_ELEMENTS.has(node.tag)) {
137+
return;
138+
}
139+
140+
// Check for block params
141+
if (node.blockParams && node.blockParams.length > 0) {
142+
context.report({
143+
node,
144+
messageId: 'noBlockParamsForHtmlElements',
145+
});
146+
}
147+
},
148+
};
149+
},
150+
};
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
const rule = require('../../../lib/rules/template-no-block-params-for-html-elements');
2+
const RuleTester = require('eslint').RuleTester;
3+
4+
const ruleTester = new RuleTester({
5+
parser: require.resolve('ember-eslint-parser'),
6+
parserOptions: { ecmaVersion: 2022, sourceType: 'module' },
7+
});
8+
9+
ruleTester.run('template-no-block-params-for-html-elements', rule, {
10+
valid: [
11+
'<template><div>Content</div></template>',
12+
'<template><MyComponent as |item|>{{item.name}}</MyComponent></template>',
13+
'<template>{{#each this.items as |item|}}<li>{{item}}</li>{{/each}}</template>',
14+
'<template><button>Click</button></template>',
15+
],
16+
17+
invalid: [
18+
{
19+
code: '<template><div as |content|>{{content}}</div></template>',
20+
output: null,
21+
errors: [
22+
{
23+
message: 'Block params can only be used with components, not HTML elements.',
24+
type: 'GlimmerElementNode',
25+
},
26+
],
27+
},
28+
{
29+
code: '<template><section as |data|><p>{{data}}</p></section></template>',
30+
output: null,
31+
errors: [
32+
{
33+
message: 'Block params can only be used with components, not HTML elements.',
34+
type: 'GlimmerElementNode',
35+
},
36+
],
37+
},
38+
{
39+
code: '<template><ul as |items|><li>{{items}}</li></ul></template>',
40+
output: null,
41+
errors: [
42+
{
43+
message: 'Block params can only be used with components, not HTML elements.',
44+
type: 'GlimmerElementNode',
45+
},
46+
],
47+
},
48+
],
49+
});

0 commit comments

Comments
 (0)