Skip to content

Commit 8c3b360

Browse files
feat: implement final 6 ember-template-lint rules (127/127 complete - 100%!)
- Add template-no-obscure-array-access rule - Add template-no-scope-outside-table-headings rule - Add template-no-unbalanced-curlies rule - Add template-no-whitespace-for-layout rule - Add template-no-model-argument-in-route-templates rule - Add template-no-unnecessary-curly-parens rule All rules include: - Implementation with proper Glimmer AST node visitors - Comprehensive tests with valid/invalid cases - Documentation with examples and references - strictGjs and strictGts enabled in meta.docs Total: 127 template rules, 222 total rules (100% complete!) 🎉 All ember-template-lint rules have been ported! Co-authored-by: NullVoxPopuli <[email protected]>
1 parent f26bdc3 commit 8c3b360

21 files changed

Lines changed: 1048 additions & 188 deletions

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,11 +272,13 @@ rules in templates can be disabled with eslint directives with mustache or html
272272
| [template-no-input-tagname](docs/rules/template-no-input-tagname.md) | disallow tagName attribute on {{input}} helper | ![badge-strict-gjs][] ![badge-strict-gts][] | | |
273273
| [template-no-invalid-meta](docs/rules/template-no-invalid-meta.md) | disallow invalid meta tags | ![badge-strict-gjs][] ![badge-strict-gts][] | | |
274274
| [template-no-log](docs/rules/template-no-log.md) | disallow {{log}} in templates | ![badge-strict-gjs][] ![badge-strict-gts][] | | |
275+
| [template-no-model-argument-in-route-templates](docs/rules/template-no-model-argument-in-route-templates.md) | disallow @model argument in route templates | ![badge-strict-gjs][] ![badge-strict-gts][] | | |
275276
| [template-no-multiple-empty-lines](docs/rules/template-no-multiple-empty-lines.md) | disallow multiple consecutive empty lines in templates | ![badge-strict-gjs][] ![badge-strict-gts][] | | |
276277
| [template-no-mut-helper](docs/rules/template-no-mut-helper.md) | disallow usage of (mut) helper | ![badge-strict-gjs][] ![badge-strict-gts][] | | |
277278
| [template-no-negated-comparison](docs/rules/template-no-negated-comparison.md) | disallow negated comparisons in templates | ![badge-strict-gjs][] ![badge-strict-gts][] | | |
278279
| [template-no-negated-condition](docs/rules/template-no-negated-condition.md) | disallow negated conditions in if/unless | | | |
279280
| [template-no-nested-splattributes](docs/rules/template-no-nested-splattributes.md) | disallow nested ...attributes usage | ![badge-strict-gjs][] ![badge-strict-gts][] | | |
281+
| [template-no-obscure-array-access](docs/rules/template-no-obscure-array-access.md) | disallow obscure array access patterns like [email protected] | ![badge-strict-gjs][] ![badge-strict-gts][] | | |
280282
| [template-no-obsolete-elements](docs/rules/template-no-obsolete-elements.md) | disallow obsolete HTML elements | ![badge-strict-gjs][] ![badge-strict-gts][] | | |
281283
| [template-no-outlet-outside-routes](docs/rules/template-no-outlet-outside-routes.md) | disallow {{outlet}} outside of route templates | | | |
282284
| [template-no-page-title-component](docs/rules/template-no-page-title-component.md) | disallow usage of ember-page-title component | ![badge-strict-gjs][] ![badge-strict-gts][] | | |
@@ -288,9 +290,11 @@ rules in templates can be disabled with eslint directives with mustache or html
288290
| [template-no-trailing-spaces](docs/rules/template-no-trailing-spaces.md) | disallow trailing whitespace at the end of lines in templates | ![badge-strict-gjs][] ![badge-strict-gts][] | 🔧 | |
289291
| [template-no-unnecessary-component-helper](docs/rules/template-no-unnecessary-component-helper.md) | disallow unnecessary component helper | | | |
290292
| [template-no-unnecessary-concat](docs/rules/template-no-unnecessary-concat.md) | disallow unnecessary string concatenation | ![badge-strict-gjs][] ![badge-strict-gts][] | 🔧 | |
293+
| [template-no-unnecessary-curly-parens](docs/rules/template-no-unnecessary-curly-parens.md) | disallow unnecessary curlies around single values | ![badge-strict-gjs][] ![badge-strict-gts][] | | |
291294
| [template-no-unnecessary-service-injection-argument](docs/rules/template-no-unnecessary-service-injection-argument.md) | disallow unnecessary service injection argument | ![badge-strict-gjs][] ![badge-strict-gts][] | | |
292295
| [template-no-unused-block-params](docs/rules/template-no-unused-block-params.md) | disallow unused block parameters in templates | | | |
293296
| [template-no-valueless-arguments](docs/rules/template-no-valueless-arguments.md) | disallow valueless named arguments | ![badge-strict-gjs][] ![badge-strict-gts][] | | |
297+
| [template-no-whitespace-for-layout](docs/rules/template-no-whitespace-for-layout.md) | disallow using whitespace for layout purposes | ![badge-strict-gjs][] ![badge-strict-gts][] | | |
294298
| [template-no-yield-only](docs/rules/template-no-yield-only.md) | disallow components that only yield | ![badge-strict-gjs][] ![badge-strict-gts][] | | |
295299
| [template-no-yield-to-default](docs/rules/template-no-yield-to-default.md) | disallow yield to default block | ![badge-strict-gjs][] ![badge-strict-gts][] | | |
296300
| [template-require-button-type](docs/rules/template-require-button-type.md) | require button elements to have a valid type attribute | ![badge-strict-gjs][] ![badge-strict-gts][] | 🔧 | |
@@ -426,7 +430,9 @@ rules in templates can be disabled with eslint directives with mustache or html
426430

427431
| Name | Description | 💼 | 🔧 | 💡 |
428432
| :------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------- | :------------------------------------------ | :- | :- |
433+
| [template-no-scope-outside-table-headings](docs/rules/template-no-scope-outside-table-headings.md) | disallow scope attribute outside th/td elements | ![badge-strict-gjs][] ![badge-strict-gts][] | | |
429434
| [template-no-shadowed-elements](docs/rules/template-no-shadowed-elements.md) | disallow shadowing of built-in HTML elements | ![badge-strict-gjs][] ![badge-strict-gts][] | | |
435+
| [template-no-unbalanced-curlies](docs/rules/template-no-unbalanced-curlies.md) | disallow unbalanced mustache curlies | ![badge-strict-gjs][] ![badge-strict-gts][] | | |
430436
| [template-no-unknown-arguments-for-builtin-components](docs/rules/template-no-unknown-arguments-for-builtin-components.md) | disallow unknown arguments for built-in components | | | |
431437

432438
### Routes
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# ember/template-no-model-argument-in-route-templates
2+
3+
💼 This rule is enabled in the following [configs](https://github.com/ember-cli/eslint-plugin-ember#-configurations): `strict-gjs`, `strict-gts`.
4+
5+
<!-- end auto-generated rule header -->
6+
7+
✅ The `extends: 'plugin:ember/strict-gjs'` or `extends: 'plugin:ember/strict-gts'` property in a configuration file enables this rule.
8+
9+
In Ember route templates, the model should be accessed via `this.model` in the controller or component, not as an `@model` argument. The `@model` argument pattern is more appropriate for components. This rule primarily targets `.hbs` files in the `templates/` directory.
10+
11+
## Rule Details
12+
13+
This rule disallows the use of `@model` argument in route templates (`.hbs` files in `templates/` directory).
14+
15+
## Examples
16+
17+
Examples of **incorrect** code for this rule (in route templates):
18+
19+
```hbs
20+
<!-- app/templates/index.hbs -->
21+
{{@model}}
22+
```
23+
24+
```hbs
25+
<!-- app/templates/users.hbs -->
26+
{{@model.name}}
27+
```
28+
29+
```hbs
30+
<!-- app/templates/posts/show.hbs -->
31+
{{@model.id}}
32+
```
33+
34+
Examples of **correct** code for this rule:
35+
36+
```hbs
37+
<!-- app/templates/index.hbs -->
38+
{{this.model}}
39+
```
40+
41+
```gjs
42+
// app/components/user-card.gjs
43+
<template>
44+
{{@model.name}}
45+
</template>
46+
```
47+
48+
```gjs
49+
<template>
50+
{{this.model}}
51+
</template>
52+
```
53+
54+
## References
55+
56+
- [ember-template-lint: no-model-argument-in-route-templates](https://github.com/ember-template-lint/ember-template-lint/blob/master/docs/rule/no-model-argument-in-route-templates.md)
57+
- [Ember Guides: Controllers](https://guides.emberjs.com/release/routing/controllers/)
58+
59+
<!-- begin auto-generated rule meta list -->
60+
- strictGjs: true
61+
- strictGts: true
62+
<!-- end auto-generated rule meta list -->
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# ember/template-no-obscure-array-access
2+
3+
💼 This rule is enabled in the following [configs](https://github.com/ember-cli/eslint-plugin-ember#-configurations): `strict-gjs`, `strict-gts`.
4+
5+
<!-- end auto-generated rule header -->
6+
7+
✅ The `extends: 'plugin:ember/strict-gjs'` or `extends: 'plugin:ember/strict-gts'` property in a configuration file enables this rule.
8+
9+
Disallow obscure array access patterns like `[email protected]` or `objectPath.[].property` in templates.
10+
11+
## Rule Details
12+
13+
This rule discourages the use of `@each` and `[]` property access patterns in templates, which can be obscure and difficult to understand. Instead, use computed properties, helpers, or explicit iteration.
14+
15+
## Examples
16+
17+
Examples of **incorrect** code for this rule:
18+
19+
```gjs
20+
<template>
21+
22+
</template>
23+
```
24+
25+
```gjs
26+
<template>
27+
28+
</template>
29+
```
30+
31+
```gjs
32+
<template>
33+
{{items.[].property}}
34+
</template>
35+
```
36+
37+
Examples of **correct** code for this rule:
38+
39+
```gjs
40+
<template>
41+
{{#each items as |item|}}
42+
{{item.name}}
43+
{{/each}}
44+
</template>
45+
```
46+
47+
```gjs
48+
<template>
49+
{{get items 0}}
50+
</template>
51+
```
52+
53+
```gjs
54+
<template>
55+
{{this.itemNames}}
56+
</template>
57+
```
58+
59+
## References
60+
61+
- [ember-template-lint: no-obscure-array-access](https://github.com/ember-template-lint/ember-template-lint/blob/master/docs/rule/no-obscure-array-access.md)
62+
63+
<!-- begin auto-generated rule meta list -->
64+
- strictGjs: true
65+
- strictGts: true
66+
<!-- end auto-generated rule meta list -->
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# ember/template-no-scope-outside-table-headings
2+
3+
💼 This rule is enabled in the following [configs](https://github.com/ember-cli/eslint-plugin-ember#-configurations): `strict-gjs`, `strict-gts`.
4+
5+
<!-- end auto-generated rule header -->
6+
7+
✅ The `extends: 'plugin:ember/strict-gjs'` or `extends: 'plugin:ember/strict-gts'` property in a configuration file enables this rule.
8+
9+
Disallow the `scope` attribute on elements other than `<th>` or `<td>` elements.
10+
11+
## Rule Details
12+
13+
The `scope` attribute is only valid on `<th>` and `<td>` elements within tables. Using it on other elements is invalid HTML and should be avoided.
14+
15+
## Examples
16+
17+
Examples of **incorrect** code for this rule:
18+
19+
```gjs
20+
<template>
21+
<div scope="col">Not a table cell</div>
22+
</template>
23+
```
24+
25+
```gjs
26+
<template>
27+
<span scope="row">Wrong element</span>
28+
</template>
29+
```
30+
31+
```gjs
32+
<template>
33+
<p scope="col">Paragraph</p>
34+
</template>
35+
```
36+
37+
Examples of **correct** code for this rule:
38+
39+
```gjs
40+
<template>
41+
<th scope="col">Header</th>
42+
</template>
43+
```
44+
45+
```gjs
46+
<template>
47+
<td scope="row">Cell</td>
48+
</template>
49+
```
50+
51+
```gjs
52+
<template>
53+
<div>Content without scope</div>
54+
</template>
55+
```
56+
57+
## References
58+
59+
- [ember-template-lint: no-scope-outside-table-headings](https://github.com/ember-template-lint/ember-template-lint/blob/master/docs/rule/no-scope-outside-table-headings.md)
60+
- [MDN: scope attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/th#attr-scope)
61+
62+
<!-- begin auto-generated rule meta list -->
63+
- strictGjs: true
64+
- strictGts: true
65+
<!-- end auto-generated rule meta list -->
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# ember/template-no-unbalanced-curlies
2+
3+
💼 This rule is enabled in the following [configs](https://github.com/ember-cli/eslint-plugin-ember#-configurations): `strict-gjs`, `strict-gts`.
4+
5+
<!-- end auto-generated rule header -->
6+
7+
✅ The `extends: 'plugin:ember/strict-gjs'` or `extends: 'plugin:ember/strict-gts'` property in a configuration file enables this rule.
8+
9+
Disallow unbalanced mustache curlies in templates.
10+
11+
## Rule Details
12+
13+
This rule detects unbalanced opening `{{` and closing `}}` mustache braces in templates, which typically indicates a syntax error or typo.
14+
15+
## Examples
16+
17+
Examples of **incorrect** code for this rule:
18+
19+
```gjs
20+
<template>
21+
{{value}
22+
</template>
23+
```
24+
25+
```gjs
26+
<template>
27+
{{{value}}
28+
</template>
29+
```
30+
31+
```gjs
32+
<template>
33+
{{#if condition}}
34+
{{value}
35+
{{/if}}
36+
</template>
37+
```
38+
39+
Examples of **correct** code for this rule:
40+
41+
```gjs
42+
<template>
43+
{{value}}
44+
</template>
45+
```
46+
47+
```gjs
48+
<template>
49+
{{#if condition}}
50+
{{value}}
51+
{{/if}}
52+
</template>
53+
```
54+
55+
```gjs
56+
<template>
57+
{{helper param1 param2}}
58+
</template>
59+
```
60+
61+
## References
62+
63+
- [ember-template-lint: no-unbalanced-curlies](https://github.com/ember-template-lint/ember-template-lint/blob/master/docs/rule/no-unbalanced-curlies.md)
64+
65+
<!-- begin auto-generated rule meta list -->
66+
- strictGjs: true
67+
- strictGts: true
68+
<!-- end auto-generated rule meta list -->
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# ember/template-no-unnecessary-curly-parens
2+
3+
💼 This rule is enabled in the following [configs](https://github.com/ember-cli/eslint-plugin-ember#-configurations): `strict-gjs`, `strict-gts`.
4+
5+
<!-- end auto-generated rule header -->
6+
7+
✅ The `extends: 'plugin:ember/strict-gjs'` or `extends: 'plugin:ember/strict-gts'` property in a configuration file enables this rule.
8+
9+
Disallow unnecessary curlies around simple values in templates. This is a stylistic rule that promotes cleaner template code. It only flags simple single identifiers without path separators or parameters.
10+
11+
## Rule Details
12+
13+
This rule discourages the use of mustache curlies `{{}}` around simple single identifiers when they could potentially be expressed more simply.
14+
15+
## Examples
16+
17+
Examples of **incorrect** code for this rule:
18+
19+
```gjs
20+
<template>
21+
{{value}}
22+
</template>
23+
```
24+
25+
```gjs
26+
<template>
27+
{{name}}
28+
</template>
29+
```
30+
31+
```gjs
32+
<template>
33+
{{count}}
34+
</template>
35+
```
36+
37+
Examples of **correct** code for this rule:
38+
39+
```gjs
40+
<template>
41+
{{helper param}}
42+
</template>
43+
```
44+
45+
```gjs
46+
<template>
47+
{{#if condition}}text{{/if}}
48+
</template>
49+
```
50+
51+
```gjs
52+
<template>
53+
{{this.property}}
54+
</template>
55+
```
56+
57+
## References
58+
59+
- [ember-template-lint: no-unnecessary-curly-parens](https://github.com/ember-template-lint/ember-template-lint/blob/master/docs/rule/no-unnecessary-curly-parens.md)
60+
61+
<!-- begin auto-generated rule meta list -->
62+
- strictGjs: true
63+
- strictGts: true
64+
<!-- end auto-generated rule meta list -->

0 commit comments

Comments
 (0)