Skip to content

Commit 438984d

Browse files
committed
Extract rule: template-deprecated-inline-view-helper
1 parent 98128eb commit 438984d

4 files changed

Lines changed: 293 additions & 0 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ rules in templates can be disabled with eslint directives with mustache or html
288288
| [no-observers](docs/rules/no-observers.md) | disallow usage of observers || | |
289289
| [no-old-shims](docs/rules/no-old-shims.md) | disallow usage of old shims for modules || 🔧 | |
290290
| [no-string-prototype-extensions](docs/rules/no-string-prototype-extensions.md) | disallow usage of `String` prototype extensions || | |
291+
| [template-deprecated-inline-view-helper](docs/rules/template-deprecated-inline-view-helper.md) | disallow inline {{view}} helper | | | |
291292
| [template-no-action](docs/rules/template-no-action.md) | disallow {{action}} helper | | | |
292293
| [template-no-attrs-in-components](docs/rules/template-no-attrs-in-components.md) | disallow attrs in component templates | | | |
293294
| [template-no-link-to-positional-params](docs/rules/template-no-link-to-positional-params.md) | disallow positional params in LinkTo component | | | |
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# ember/template-deprecated-inline-view-helper
2+
3+
> **HBS Only**: This rule applies to classic `.hbs` template files only (loose mode). It is not relevant for `gjs`/`gts` files (strict mode), where these patterns cannot occur.
4+
5+
<!-- end auto-generated rule header -->
6+
7+
In Ember 1.12, support for invoking the inline View helper was deprecated.
8+
9+
## Rule Details
10+
11+
This rule flags:
12+
13+
- `{{view}}` mustache or block statements that have params or hash pair arguments (e.g., `{{view 'foo'}}`, `{{view 'foo' key=value}}`).
14+
- `{{view.property}}` path expressions (e.g., `{{view.also-bad}}`).
15+
- Hash values referencing `view.*` paths (e.g., `please=view.stop`).
16+
17+
## Examples
18+
19+
This rule **forbids** the following:
20+
21+
```hbs
22+
{{view 'this-is-bad'}}
23+
24+
{{view.also-bad}}
25+
26+
{{qux-qaz please=view.stop}}
27+
28+
{{#not-this please=view.stop}}{{/not-this}}
29+
30+
<div foo={{view.bar}}></div>
31+
```
32+
33+
This rule **allows** the following:
34+
35+
```hbs
36+
{{this-is-better}}
37+
38+
{{qux-qaz this=good}}
39+
40+
{{#ok-this yay=nice}}{{/ok-this}}
41+
42+
<div foo={{bar}}></div>
43+
```
44+
45+
## References
46+
47+
- More information is available at the [Deprecation Guide](http://emberjs.com/deprecations/v1.x/#toc_ember-view).
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
function isViewPath(pathNode) {
2+
return (
3+
pathNode &&
4+
pathNode.type === 'GlimmerPathExpression' &&
5+
pathNode.original &&
6+
pathNode.original.startsWith('view.') &&
7+
pathNode.head?.type !== 'ThisHead' &&
8+
pathNode.head?.type !== 'AtHead'
9+
);
10+
}
11+
12+
/** @type {import('eslint').Rule.RuleModule} */
13+
module.exports = {
14+
meta: {
15+
type: 'suggestion',
16+
docs: {
17+
description: 'disallow inline {{view}} helper',
18+
category: 'Deprecations',
19+
url: 'https://github.com/ember-cli/eslint-plugin-ember/tree/master/docs/rules/template-deprecated-inline-view-helper.md',
20+
templateMode: 'loose',
21+
},
22+
fixable: null,
23+
schema: [],
24+
messages: {
25+
deprecated:
26+
'The inline form of `view` is deprecated. Please use `Ember.Component` instead. See http://emberjs.com/deprecations/v1.x/#toc_ember-view',
27+
},
28+
originallyFrom: {
29+
name: 'ember-template-lint',
30+
rule: 'lib/rules/deprecated-inline-view-helper.js',
31+
docs: 'docs/rule/deprecated-inline-view-helper.md',
32+
tests: 'test/unit/rules/deprecated-inline-view-helper-test.js',
33+
},
34+
},
35+
36+
create(context) {
37+
function checkHashForViewPaths(node) {
38+
if (node.hash && node.hash.pairs) {
39+
for (const pair of node.hash.pairs) {
40+
if (isViewPath(pair.value)) {
41+
context.report({
42+
node,
43+
messageId: 'deprecated',
44+
});
45+
return true;
46+
}
47+
}
48+
}
49+
return false;
50+
}
51+
52+
function checkForView(node) {
53+
if (node.path && node.path.type === 'GlimmerPathExpression') {
54+
// Check for {{view ...}} with params or hash pairs
55+
if (node.path.original === 'view') {
56+
if (
57+
(node.hash && node.hash.pairs && node.hash.pairs.length > 0) ||
58+
(node.params && node.params.length > 0)
59+
) {
60+
context.report({
61+
node,
62+
messageId: 'deprecated',
63+
});
64+
return;
65+
}
66+
}
67+
// Check for {{view.something}} paths
68+
if (isViewPath(node.path)) {
69+
context.report({
70+
node,
71+
messageId: 'deprecated',
72+
});
73+
return;
74+
}
75+
}
76+
// Check hash values for view.* references
77+
checkHashForViewPaths(node);
78+
}
79+
80+
return {
81+
GlimmerMustacheStatement(node) {
82+
checkForView(node);
83+
},
84+
85+
GlimmerBlockStatement(node) {
86+
checkForView(node);
87+
},
88+
};
89+
},
90+
};
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
const rule = require('../../../lib/rules/template-deprecated-inline-view-helper');
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-deprecated-inline-view-helper', rule, {
10+
valid: [
11+
'<template><MyComponent /></template>',
12+
'<template>{{view}}</template>',
13+
'<template>{{great-fishsticks}}</template>',
14+
'<template>{{input placeholder=(t "email") value=email}}</template>',
15+
'<template>{{title "CrossCheck Web" prepend=true separator=" | "}}</template>',
16+
'<template>{{false}}</template>',
17+
'<template>{{"foo"}}</template>',
18+
'<template>{{42}}</template>',
19+
'<template>{{null}}</template>',
20+
'<template>{{undefined}}</template>',
21+
'<template>{{has-block "view"}}</template>',
22+
'<template>{{yield to="view"}}</template>',
23+
'<template>{{#if (has-block "view")}}{{yield to="view"}}{{/if}}</template>',
24+
'<template>{{this.view}}</template>',
25+
'<template>{{@view}}</template>',
26+
'<template>{{#let this.prop as |view|}} {{view}} {{/let}}</template>',
27+
],
28+
invalid: [
29+
{
30+
code: '<template>{{view class="foo"}}</template>',
31+
output: null,
32+
errors: [{ messageId: 'deprecated' }],
33+
},
34+
35+
{
36+
code: "<template>{{view 'awful-fishsticks'}}</template>",
37+
output: null,
38+
errors: [{ messageId: 'deprecated' }],
39+
},
40+
{
41+
code: '<template>{{view.bad-fishsticks}}</template>',
42+
output: null,
43+
errors: [{ messageId: 'deprecated' }],
44+
},
45+
{
46+
code: '<template>{{view.terrible.fishsticks}}</template>',
47+
output: null,
48+
errors: [{ messageId: 'deprecated' }],
49+
},
50+
{
51+
code: '<template>{{foo-bar bab=good baz=view.qux.qaz boo=okay}}</template>',
52+
output: null,
53+
errors: [{ messageId: 'deprecated' }],
54+
},
55+
{
56+
code: '<template><div class="whatever-class" data-foo={{view.hallo}} sure=thing></div></template>',
57+
output: null,
58+
errors: [{ messageId: 'deprecated' }],
59+
},
60+
{
61+
code: '<template>{{#foo-bar derp=view.whoops thing=whatever}}{{/foo-bar}}</template>',
62+
output: null,
63+
errors: [{ messageId: 'deprecated' }],
64+
},
65+
],
66+
});
67+
68+
const hbsRuleTester = new RuleTester({
69+
parser: require.resolve('ember-eslint-parser/hbs'),
70+
parserOptions: {
71+
ecmaVersion: 2022,
72+
sourceType: 'module',
73+
},
74+
});
75+
76+
hbsRuleTester.run('template-deprecated-inline-view-helper', rule, {
77+
valid: [
78+
'{{great-fishsticks}}',
79+
'{{input placeholder=(t "email") value=email}}',
80+
'{{title "CrossCheck Web" prepend=true separator=" | "}}',
81+
'{{false}}',
82+
'{{"foo"}}',
83+
'{{42}}',
84+
'{{null}}',
85+
'{{undefined}}',
86+
'{{has-block "view"}}',
87+
'{{yield to="view"}}',
88+
'{{#if (has-block "view")}}{{yield to="view"}}{{/if}}',
89+
'{{this.view}}',
90+
'{{@view}}',
91+
'{{#let this.prop as |view|}} {{view}} {{/let}}',
92+
],
93+
invalid: [
94+
{
95+
code: "{{view 'awful-fishsticks'}}",
96+
output: null,
97+
errors: [
98+
{
99+
message:
100+
'The inline form of `view` is deprecated. Please use `Ember.Component` instead. See http://emberjs.com/deprecations/v1.x/#toc_ember-view',
101+
},
102+
],
103+
},
104+
{
105+
code: '{{view.bad-fishsticks}}',
106+
output: null,
107+
errors: [
108+
{
109+
message:
110+
'The inline form of `view` is deprecated. Please use `Ember.Component` instead. See http://emberjs.com/deprecations/v1.x/#toc_ember-view',
111+
},
112+
],
113+
},
114+
{
115+
code: '{{view.terrible.fishsticks}}',
116+
output: null,
117+
errors: [
118+
{
119+
message:
120+
'The inline form of `view` is deprecated. Please use `Ember.Component` instead. See http://emberjs.com/deprecations/v1.x/#toc_ember-view',
121+
},
122+
],
123+
},
124+
{
125+
code: '{{foo-bar bab=good baz=view.qux.qaz boo=okay}}',
126+
output: null,
127+
errors: [
128+
{
129+
message:
130+
'The inline form of `view` is deprecated. Please use `Ember.Component` instead. See http://emberjs.com/deprecations/v1.x/#toc_ember-view',
131+
},
132+
],
133+
},
134+
{
135+
code: '<div class="whatever-class" data-foo={{view.hallo}} sure=thing></div>',
136+
output: null,
137+
errors: [
138+
{
139+
message:
140+
'The inline form of `view` is deprecated. Please use `Ember.Component` instead. See http://emberjs.com/deprecations/v1.x/#toc_ember-view',
141+
},
142+
],
143+
},
144+
{
145+
code: '{{#foo-bar derp=view.whoops thing=whatever}}{{/foo-bar}}',
146+
output: null,
147+
errors: [
148+
{
149+
message:
150+
'The inline form of `view` is deprecated. Please use `Ember.Component` instead. See http://emberjs.com/deprecations/v1.x/#toc_ember-view',
151+
},
152+
],
153+
},
154+
],
155+
});

0 commit comments

Comments
 (0)