Skip to content

Commit cdb0f91

Browse files
Merge pull request #2451 from NullVoxPopuli/nvp/template-lint-extract-rule-template-deprecated-render-helper
Extract rule: template-deprecated-render-helper
2 parents df7e054 + 38db42b commit cdb0f91

4 files changed

Lines changed: 175 additions & 0 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ rules in templates can be disabled with eslint directives with mustache or html
292292
| [no-old-shims](docs/rules/no-old-shims.md) | disallow usage of old shims for modules || 🔧 | |
293293
| [no-string-prototype-extensions](docs/rules/no-string-prototype-extensions.md) | disallow usage of `String` prototype extensions || | |
294294
| [template-deprecated-inline-view-helper](docs/rules/template-deprecated-inline-view-helper.md) | disallow inline {{view}} helper | | 🔧 | |
295+
| [template-deprecated-render-helper](docs/rules/template-deprecated-render-helper.md) | disallow {{render}} helper | | 🔧 | |
295296
| [template-no-action](docs/rules/template-no-action.md) | disallow {{action}} helper | | | |
296297
| [template-no-attrs-in-components](docs/rules/template-no-attrs-in-components.md) | disallow attrs in component templates | | | |
297298
| [template-no-link-to-positional-params](docs/rules/template-no-link-to-positional-params.md) | disallow positional params in LinkTo component | | | |
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# ember/template-deprecated-render-helper
2+
3+
🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).
4+
5+
> **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.
6+
7+
<!-- end auto-generated rule header -->
8+
9+
Disallows the {{render}} helper which is deprecated.
10+
11+
## Examples
12+
13+
Incorrect:
14+
15+
```hbs
16+
{{render 'user'}}
17+
```
18+
19+
Correct:
20+
21+
```hbs
22+
<User />
23+
```
24+
25+
## References
26+
27+
- [eslint-plugin-ember template-deprecated-render-helper](https://github.com/ember-cli/eslint-plugin-ember/blob/master/docs/rules/template-deprecated-render-helper.md)
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/** @type {import('eslint').Rule.RuleModule} */
2+
module.exports = {
3+
meta: {
4+
type: 'suggestion',
5+
docs: {
6+
description: 'disallow {{render}} helper',
7+
category: 'Deprecations',
8+
url: 'https://github.com/ember-cli/eslint-plugin-ember/tree/master/docs/rules/template-deprecated-render-helper.md',
9+
templateMode: 'loose',
10+
},
11+
fixable: 'code',
12+
schema: [],
13+
messages: {
14+
deprecated:
15+
'The render helper is deprecated in favor of using components. See https://emberjs.com/deprecations/v2.x/#toc_code-render-code-helper',
16+
},
17+
originallyFrom: {
18+
name: 'ember-template-lint',
19+
rule: 'lib/rules/deprecated-render-helper.js',
20+
docs: 'docs/rule/deprecated-render-helper.md',
21+
tests: 'test/unit/rules/deprecated-render-helper-test.js',
22+
},
23+
},
24+
25+
create(context) {
26+
const sourceCode = context.sourceCode;
27+
28+
function buildFix(node) {
29+
const first = node.params[0];
30+
if (!first || first.type !== 'GlimmerStringLiteral') {
31+
return null;
32+
}
33+
const templateName = first.value;
34+
35+
if (node.params.length === 1) {
36+
// {{render 'name'}} → {{name}}
37+
return (fixer) => fixer.replaceText(node, `{{${templateName}}}`);
38+
}
39+
40+
if (node.params.length === 2) {
41+
// {{render 'name' model}} → {{name model=model}}
42+
const model = sourceCode.getText(node.params[1]);
43+
return (fixer) => fixer.replaceText(node, `{{${templateName} model=${model}}}`);
44+
}
45+
46+
return null;
47+
}
48+
49+
function checkForRender(node) {
50+
if (
51+
node.path &&
52+
node.path.type === 'GlimmerPathExpression' &&
53+
node.path.original === 'render'
54+
) {
55+
context.report({
56+
node,
57+
messageId: 'deprecated',
58+
fix: buildFix(node),
59+
});
60+
}
61+
}
62+
63+
return {
64+
GlimmerMustacheStatement(node) {
65+
checkForRender(node);
66+
},
67+
68+
GlimmerBlockStatement(node) {
69+
checkForRender(node);
70+
},
71+
};
72+
},
73+
};
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
const rule = require('../../../lib/rules/template-deprecated-render-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-render-helper', rule, {
10+
valid: [
11+
'<template><MyComponent /></template>',
12+
'<template>{{this.render}}</template>',
13+
'<template>{{valid-compoennt}}</template>',
14+
'<template>{{input placeholder=(t "email") value=email}}</template>',
15+
'<template>{{title "CrossCheck Web" prepent=true separator=" | "}}</template>',
16+
'<template>{{hockey-player teamName="Boston Bruins"}}</template>',
17+
'<template>{{false}}</template>',
18+
'<template>{{"foo"}}</template>',
19+
'<template>{{42}}</template>',
20+
'<template>{{null}}</template>',
21+
'<template>{{undefined}}</template>',
22+
],
23+
invalid: [
24+
{
25+
code: '<template>{{render "user"}}</template>',
26+
output: '<template>{{user}}</template>',
27+
errors: [{ messageId: 'deprecated' }],
28+
},
29+
{
30+
code: "<template>{{render 'ken-griffey'}}</template>",
31+
output: '<template>{{ken-griffey}}</template>',
32+
errors: [{ messageId: 'deprecated' }],
33+
},
34+
{
35+
code: "<template>{{render 'baseball-player' pitcher}}</template>",
36+
output: '<template>{{baseball-player model=pitcher}}</template>',
37+
errors: [{ messageId: 'deprecated' }],
38+
},
39+
],
40+
});
41+
42+
const hbsRuleTester = new RuleTester({
43+
parser: require.resolve('ember-eslint-parser/hbs'),
44+
parserOptions: {
45+
ecmaVersion: 2022,
46+
sourceType: 'module',
47+
},
48+
});
49+
50+
hbsRuleTester.run('template-deprecated-render-helper', rule, {
51+
valid: [
52+
'{{valid-compoennt}}',
53+
'{{input placeholder=(t "email") value=email}}',
54+
'{{title "CrossCheck Web" prepent=true separator=" | "}}',
55+
'{{hockey-player teamName="Boston Bruins"}}',
56+
'{{false}}',
57+
'{{"foo"}}',
58+
'{{42}}',
59+
'{{null}}',
60+
'{{undefined}}',
61+
],
62+
invalid: [
63+
{
64+
code: "{{render 'ken-griffey'}}",
65+
output: '{{ken-griffey}}',
66+
errors: [{ messageId: 'deprecated' }],
67+
},
68+
{
69+
code: "{{render 'baseball-player' pitcher}}",
70+
output: '{{baseball-player model=pitcher}}',
71+
errors: [{ messageId: 'deprecated' }],
72+
},
73+
],
74+
});

0 commit comments

Comments
 (0)