Skip to content

Commit 87cbd47

Browse files
Merge pull request #2565 from NullVoxPopuli/nvp/template-lint-extract-rule-template-no-potential-path-strings
Extract rule: template-no-potential-path-strings
2 parents 0464492 + c9c9fcb commit 87cbd47

4 files changed

Lines changed: 243 additions & 0 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ rules in templates can be disabled with eslint directives with mustache or html
257257
| [template-no-obsolete-elements](docs/rules/template-no-obsolete-elements.md) | disallow obsolete HTML elements | | | |
258258
| [template-no-outlet-outside-routes](docs/rules/template-no-outlet-outside-routes.md) | disallow {{outlet}} outside of route templates | | | |
259259
| [template-no-page-title-component](docs/rules/template-no-page-title-component.md) | disallow usage of ember-page-title component | | | |
260+
| [template-no-potential-path-strings](docs/rules/template-no-potential-path-strings.md) | disallow potential path strings in attribute values | | | |
260261
| [template-no-splattributes-with-class](docs/rules/template-no-splattributes-with-class.md) | disallow splattributes with class attribute | | | |
261262
| [template-no-trailing-spaces](docs/rules/template-no-trailing-spaces.md) | disallow trailing whitespace at the end of lines in templates | | 🔧 | |
262263
| [template-no-unavailable-this](docs/rules/template-no-unavailable-this.md) | disallow `this` in templates that are not inside a class or function | | | |
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# ember/template-no-potential-path-strings
2+
3+
<!-- end auto-generated rule header -->
4+
5+
It might happen sometimes that `{{` and `}}` are forgotten when invoking a component, and the string that is passed was actually supposed to be a property path or argument.
6+
7+
This rule warns about all arguments and attributes that start with `this.` or `@`, but are missing the surrounding `{{` and `}}` characters.
8+
9+
## Examples
10+
11+
This rule **forbids** the following:
12+
13+
```hbs
14+
<img src='this.picture' />
15+
```
16+
17+
```hbs
18+
<img src='@img' />
19+
```
20+
21+
This rule **allows** the following:
22+
23+
```hbs
24+
<img src={{this.picture}} />
25+
```
26+
27+
```hbs
28+
<img src={{@img}} />
29+
```
30+
31+
## Migration
32+
33+
- Replace the surrounding `"` characters with `{{`/`}}`
34+
35+
## Related Rules
36+
37+
- [no-arguments-for-html-elements](template-no-arguments-for-html-elements.md)
38+
39+
## References
40+
41+
- [Component Arguments and HTML Attributes](https://guides.emberjs.com/release/components/component-arguments-and-html-attributes/)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
const FINE_SYMBOLS = ['|', '/', '\\'];
2+
3+
/** @type {import('eslint').Rule.RuleModule} */
4+
module.exports = {
5+
meta: {
6+
type: 'suggestion',
7+
docs: {
8+
description: 'disallow potential path strings in attribute values',
9+
category: 'Best Practices',
10+
url: 'https://github.com/ember-cli/eslint-plugin-ember/tree/master/docs/rules/template-no-potential-path-strings.md',
11+
templateMode: 'both',
12+
},
13+
fixable: null,
14+
schema: [],
15+
messages: {
16+
noPotentialPathStrings:
17+
'Potential path in attribute string detected. Did you mean {{{{path}}}}?',
18+
},
19+
originallyFrom: {
20+
name: 'ember-template-lint',
21+
rule: 'lib/rules/no-potential-path-strings.js',
22+
docs: 'docs/rule/no-potential-path-strings.md',
23+
tests: 'test/unit/rules/no-potential-path-strings-test.js',
24+
},
25+
},
26+
27+
create(context) {
28+
return {
29+
GlimmerAttrNode(node) {
30+
if (!node.value || node.value.type !== 'GlimmerTextNode') {
31+
return;
32+
}
33+
34+
const chars = node.value.chars;
35+
const hasSpecialPrefix = chars.startsWith('this.') || chars.startsWith('@');
36+
37+
if (hasSpecialPrefix && !FINE_SYMBOLS.some((symbol) => chars.includes(symbol))) {
38+
context.report({
39+
node: node.value,
40+
messageId: 'noPotentialPathStrings',
41+
data: { path: chars },
42+
});
43+
}
44+
},
45+
};
46+
},
47+
};
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
const { RuleTester } = require('eslint');
2+
const rule = require('../../../lib/rules/template-no-potential-path-strings');
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-potential-path-strings', rule, {
10+
valid: [
11+
'<template><img src="foo.png"></template>',
12+
'<template><img src={{picture}}></template>',
13+
'<template><img src={{this.picture}}></template>',
14+
'<template><img src={{@img}}></template>',
15+
'<template><SomeComponent @foo={{@bar}} /></template>',
16+
'<template><Ui::Demo @title="@my-org/my-package" /></template>',
17+
'<template><Ui::Demo @title="@my-org\\my-package" /></template>',
18+
'<template><Ui::Demo @title="@my-org|my-package" /></template>',
19+
],
20+
21+
invalid: [
22+
{
23+
code: '<template><img src="this.picture"></template>',
24+
output: null,
25+
errors: [
26+
{
27+
message: 'Potential path in attribute string detected. Did you mean {{this.picture}}?',
28+
},
29+
],
30+
},
31+
{
32+
code: '<template><img src=this.picture></template>',
33+
output: null,
34+
errors: [
35+
{
36+
message: 'Potential path in attribute string detected. Did you mean {{this.picture}}?',
37+
},
38+
],
39+
},
40+
{
41+
code: '<template><img src="@img"></template>',
42+
output: null,
43+
errors: [
44+
{
45+
message: 'Potential path in attribute string detected. Did you mean {{@img}}?',
46+
},
47+
],
48+
},
49+
{
50+
code: '<template><img src=@img></template>',
51+
output: null,
52+
errors: [
53+
{
54+
message: 'Potential path in attribute string detected. Did you mean {{@img}}?',
55+
},
56+
],
57+
},
58+
{
59+
code: '<template><SomeComponent @foo=@bar /></template>',
60+
output: null,
61+
errors: [
62+
{
63+
message: 'Potential path in attribute string detected. Did you mean {{@bar}}?',
64+
},
65+
],
66+
},
67+
{
68+
code: '<template><SomeComponent @foo=this.bar /></template>',
69+
output: null,
70+
errors: [
71+
{
72+
message: 'Potential path in attribute string detected. Did you mean {{this.bar}}?',
73+
},
74+
],
75+
},
76+
],
77+
});
78+
79+
const hbsRuleTester = new RuleTester({
80+
parser: require.resolve('ember-eslint-parser/hbs'),
81+
parserOptions: {
82+
ecmaVersion: 2022,
83+
sourceType: 'module',
84+
},
85+
});
86+
87+
hbsRuleTester.run('template-no-potential-path-strings', rule, {
88+
valid: [
89+
'<img src="foo.png">',
90+
'<img src={{picture}}>',
91+
'<img src={{this.picture}}>',
92+
'<img src={{@img}}>',
93+
'<SomeComponent @foo={{@bar}} />',
94+
'<Ui::Demo @title="@my-org/my-package" />',
95+
'<Ui::Demo @title="@my-org\\my-package" />',
96+
'<Ui::Demo @title="@my-org|my-package" />',
97+
],
98+
invalid: [
99+
{
100+
code: '<img src="this.picture">',
101+
output: null,
102+
errors: [
103+
{
104+
message: 'Potential path in attribute string detected. Did you mean {{this.picture}}?',
105+
},
106+
],
107+
},
108+
{
109+
code: '<img src=this.picture>',
110+
output: null,
111+
errors: [
112+
{
113+
message: 'Potential path in attribute string detected. Did you mean {{this.picture}}?',
114+
},
115+
],
116+
},
117+
{
118+
code: '<img src="@img">',
119+
output: null,
120+
errors: [
121+
{
122+
message: 'Potential path in attribute string detected. Did you mean {{@img}}?',
123+
},
124+
],
125+
},
126+
{
127+
code: '<img src=@img>',
128+
output: null,
129+
errors: [
130+
{
131+
message: 'Potential path in attribute string detected. Did you mean {{@img}}?',
132+
},
133+
],
134+
},
135+
{
136+
code: '<SomeComponent @foo=@bar />',
137+
output: null,
138+
errors: [
139+
{
140+
message: 'Potential path in attribute string detected. Did you mean {{@bar}}?',
141+
},
142+
],
143+
},
144+
{
145+
code: '<SomeComponent @foo=this.bar />',
146+
output: null,
147+
errors: [
148+
{
149+
message: 'Potential path in attribute string detected. Did you mean {{this.bar}}?',
150+
},
151+
],
152+
},
153+
],
154+
});

0 commit comments

Comments
 (0)