Skip to content

Commit 00fc467

Browse files
committed
Add ElementNode attribute checking and hash pair guards for view references
1 parent 131cd12 commit 00fc467

2 files changed

Lines changed: 63 additions & 0 deletions

File tree

lib/rules/template-deprecated-inline-view-helper.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,22 @@ module.exports = {
6060

6161
function checkHashForViewPaths(node) {
6262
if (node.hash && node.hash.pairs) {
63+
// Skip {{yield}} invocations — yield hash pairs are not view references
64+
const isYield =
65+
node.path &&
66+
node.path.type === 'GlimmerPathExpression' &&
67+
node.path.original === 'yield' &&
68+
node.path.head?.type !== 'ThisHead' &&
69+
node.path.head?.type !== 'AtHead';
70+
if (isYield) {
71+
return false;
72+
}
73+
6374
for (const pair of node.hash.pairs) {
75+
// Skip hash pairs with key "to" (e.g., {{yield to="inverse"}})
76+
if (pair.key === 'to') {
77+
continue;
78+
}
6479
if (isViewPath(pair.value)) {
6580
const strippedValue = pair.value.original.replace('view.', '');
6681
context.report({
@@ -135,6 +150,26 @@ module.exports = {
135150
},
136151

137152
GlimmerElementNode(node) {
153+
// Check element attributes for view.* references (e.g., <div class={{view.something}}>)
154+
if (node.attributes) {
155+
for (const attr of node.attributes) {
156+
if (
157+
attr.value &&
158+
attr.value.type === 'GlimmerMustacheStatement' &&
159+
isViewPath(attr.value.path)
160+
) {
161+
const strippedValue = attr.value.path.original.replace('view.', '');
162+
context.report({
163+
node: attr.value,
164+
messageId: 'deprecated',
165+
fix(fixer) {
166+
return fixer.replaceText(attr.value.path, strippedValue);
167+
},
168+
});
169+
}
170+
}
171+
}
172+
138173
if (node.blockParams && node.blockParams.length > 0) {
139174
pushLocals(node.blockParams);
140175
}
@@ -146,6 +181,11 @@ module.exports = {
146181
},
147182

148183
GlimmerMustacheStatement(node) {
184+
// Skip mustache statements that are element attribute values;
185+
// those are handled by the GlimmerElementNode visitor instead.
186+
if (node.parent && node.parent.type === 'GlimmerAttrNode') {
187+
return;
188+
}
149189
checkForView(node);
150190
},
151191
};

tests/lib/rules/template-deprecated-inline-view-helper.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ ruleTester.run('template-deprecated-inline-view-helper', rule, {
2626
'<template>{{#let this.prop as |view|}} {{view}} {{/let}}</template>',
2727
// isLocal: view is a block param, view.name should not be flagged
2828
'<template>{{#each items as |view|}} {{view.name}} {{/each}}</template>',
29+
// yield with view hash pair should not be flagged
30+
'<template>{{yield hash=view.foo}}</template>',
31+
// hash pair with key "to" should not be flagged
32+
'<template>{{some-component to=view.foo}}</template>',
2933
],
3034
invalid: [
3135
{
@@ -53,6 +57,11 @@ ruleTester.run('template-deprecated-inline-view-helper', rule, {
5357
output: '<template>{{foo-bar bab=good baz=qux.qaz boo=okay}}</template>',
5458
errors: [{ messageId: 'deprecated' }],
5559
},
60+
{
61+
code: '<template><div class={{view.something}}></div></template>',
62+
output: '<template><div class={{something}}></div></template>',
63+
errors: [{ messageId: 'deprecated' }],
64+
},
5665
{
5766
code: '<template><div class="whatever-class" data-foo={{view.hallo}} sure=thing></div></template>',
5867
output:
@@ -93,6 +102,10 @@ hbsRuleTester.run('template-deprecated-inline-view-helper', rule, {
93102
'{{#let this.prop as |view|}} {{view}} {{/let}}',
94103
// isLocal: view is a block param, view.name should not be flagged
95104
'{{#each items as |view|}} {{view.name}} {{/each}}',
105+
// yield with view hash pair should not be flagged
106+
'{{yield hash=view.foo}}',
107+
// hash pair with key "to" should not be flagged
108+
'{{some-component to=view.foo}}',
96109
],
97110
invalid: [
98111
{
@@ -135,6 +148,16 @@ hbsRuleTester.run('template-deprecated-inline-view-helper', rule, {
135148
},
136149
],
137150
},
151+
{
152+
code: '<div class={{view.something}}></div>',
153+
output: '<div class={{something}}></div>',
154+
errors: [
155+
{
156+
message:
157+
'The inline form of `view` is deprecated. Please use `Ember.Component` instead. See http://emberjs.com/deprecations/v1.x/#toc_ember-view',
158+
},
159+
],
160+
},
138161
{
139162
code: '<div class="whatever-class" data-foo={{view.hallo}} sure=thing></div>',
140163
output: '<div class="whatever-class" data-foo={{hallo}} sure=thing></div>',

0 commit comments

Comments
 (0)