From e0150b838b371c089e8421d53c19a9e622cf8802 Mon Sep 17 00:00:00 2001
From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com>
Date: Fri, 20 Feb 2026 11:50:55 -0500
Subject: [PATCH] Extract rule: template-no-block-params-for-html-elements
---
README.md | 17 ++---
...plate-no-block-params-for-html-elements.md | 72 +++++++++++++++++++
...plate-no-block-params-for-html-elements.js | 50 +++++++++++++
...plate-no-block-params-for-html-elements.js | 54 ++++++++++++++
4 files changed, 185 insertions(+), 8 deletions(-)
create mode 100644 docs/rules/template-no-block-params-for-html-elements.md
create mode 100644 lib/rules/template-no-block-params-for-html-elements.js
create mode 100644 tests/lib/rules/template-no-block-params-for-html-elements.js
diff --git a/README.md b/README.md
index 5a853147d1..4f98de208e 100644
--- a/README.md
+++ b/README.md
@@ -189,14 +189,15 @@ rules in templates can be disabled with eslint directives with mustache or html
### Best Practices
-| Name | Description | 💼 | 🔧 | 💡 |
-| :----------------------------------------------------------------------------------------------- | :-------------------------------------------------------- | :- | :- | :- |
-| [template-builtin-component-arguments](docs/rules/template-builtin-component-arguments.md) | disallow setting certain attributes on builtin components | | | |
-| [template-no-action-modifiers](docs/rules/template-no-action-modifiers.md) | disallow usage of {{action}} modifiers | | | |
-| [template-no-arguments-for-html-elements](docs/rules/template-no-arguments-for-html-elements.md) | disallow @arguments on HTML elements | | | |
-| [template-no-array-prototype-extensions](docs/rules/template-no-array-prototype-extensions.md) | disallow usage of Ember Array prototype extensions | | | |
-| [template-no-debugger](docs/rules/template-no-debugger.md) | disallow {{debugger}} in templates | | | |
-| [template-no-log](docs/rules/template-no-log.md) | disallow {{log}} in templates | | | |
+| Name | Description | 💼 | 🔧 | 💡 |
+| :----------------------------------------------------------------------------------------------------- | :-------------------------------------------------------- | :- | :- | :- |
+| [template-builtin-component-arguments](docs/rules/template-builtin-component-arguments.md) | disallow setting certain attributes on builtin components | | | |
+| [template-no-action-modifiers](docs/rules/template-no-action-modifiers.md) | disallow usage of {{action}} modifiers | | | |
+| [template-no-arguments-for-html-elements](docs/rules/template-no-arguments-for-html-elements.md) | disallow @arguments on HTML elements | | | |
+| [template-no-array-prototype-extensions](docs/rules/template-no-array-prototype-extensions.md) | disallow usage of Ember Array prototype extensions | | | |
+| [template-no-block-params-for-html-elements](docs/rules/template-no-block-params-for-html-elements.md) | disallow block params on HTML elements | | | |
+| [template-no-debugger](docs/rules/template-no-debugger.md) | disallow {{debugger}} in templates | | | |
+| [template-no-log](docs/rules/template-no-log.md) | disallow {{log}} in templates | | | |
### Components
diff --git a/docs/rules/template-no-block-params-for-html-elements.md b/docs/rules/template-no-block-params-for-html-elements.md
new file mode 100644
index 0000000000..9ae6bfb21d
--- /dev/null
+++ b/docs/rules/template-no-block-params-for-html-elements.md
@@ -0,0 +1,72 @@
+# ember/template-no-block-params-for-html-elements
+
+
+
+Disallow block params on HTML elements.
+
+Block params (using the `as |param|` syntax) are a feature specific to Ember components and block helpers. They should not be used on regular HTML elements.
+
+## Rule Details
+
+This rule disallows using block params on HTML elements. Use components if you need to pass block params.
+
+## Examples
+
+### Incorrect ❌
+
+```gjs
+
+
+ {{content}}
+
+
+```
+
+```gjs
+
+
+
+```
+
+```gjs
+
+
+
+```
+
+### Correct ✅
+
+```gjs
+
+ Content
+
+```
+
+```gjs
+
+
+ {{item.name}}
+
+
+```
+
+```gjs
+
+ {{#each this.items as |item|}}
+ {{item}}
+ {{/each}}
+
+```
+
+## Related Rules
+
+- [template-no-arguments-for-html-elements](./template-no-arguments-for-html-elements.md)
+
+## References
+
+- [Ember Guides - Block Content](https://guides.emberjs.com/release/components/block-content/)
+- [eslint-plugin-ember template-no-yield-only](https://github.com/ember-cli/eslint-plugin-ember/blob/master/docs/rules/template-no-yield-only.md)
diff --git a/lib/rules/template-no-block-params-for-html-elements.js b/lib/rules/template-no-block-params-for-html-elements.js
new file mode 100644
index 0000000000..d1f9eb3da6
--- /dev/null
+++ b/lib/rules/template-no-block-params-for-html-elements.js
@@ -0,0 +1,50 @@
+/** @type {import('eslint').Rule.RuleModule} */
+const htmlTags = require('html-tags');
+
+module.exports = {
+ meta: {
+ type: 'problem',
+ docs: {
+ description: 'disallow block params on HTML elements',
+ category: 'Best Practices',
+ strictGjs: true,
+ strictGts: true,
+ url: 'https://github.com/ember-cli/eslint-plugin-ember/tree/master/docs/rules/template-no-block-params-for-html-elements.md',
+ },
+ fixable: null,
+ schema: [],
+ messages: {
+ noBlockParamsForHtmlElements:
+ 'Block params can only be used with components, not HTML elements.',
+ },
+ },
+
+ create(context) {
+ const sourceCode = context.sourceCode;
+ const HTML_ELEMENTS = new Set(htmlTags);
+
+ return {
+ GlimmerElementNode(node) {
+ // Check if this is an HTML element (lowercase)
+ if (!HTML_ELEMENTS.has(node.tag)) {
+ return;
+ }
+
+ // If the tag name is a variable in scope, it's being used as a component, not an HTML element
+ const scope = sourceCode.getScope(node.parent);
+ const isVariable = scope.references.some((ref) => ref.identifier === node.parts[0]);
+ if (isVariable) {
+ return;
+ }
+
+ // Check for block params
+ if (node.blockParams && node.blockParams.length > 0) {
+ context.report({
+ node,
+ messageId: 'noBlockParamsForHtmlElements',
+ });
+ }
+ },
+ };
+ },
+};
diff --git a/tests/lib/rules/template-no-block-params-for-html-elements.js b/tests/lib/rules/template-no-block-params-for-html-elements.js
new file mode 100644
index 0000000000..c7a50ad9dc
--- /dev/null
+++ b/tests/lib/rules/template-no-block-params-for-html-elements.js
@@ -0,0 +1,54 @@
+const rule = require('../../../lib/rules/template-no-block-params-for-html-elements');
+const RuleTester = require('eslint').RuleTester;
+
+const ruleTester = new RuleTester({
+ parser: require.resolve('ember-eslint-parser'),
+ parserOptions: { ecmaVersion: 2022, sourceType: 'module' },
+});
+
+ruleTester.run('template-no-block-params-for-html-elements', rule, {
+ valid: [
+ `let div = {{yield "hello"}} ;
+
+ {{greeting}}
+
+ `,
+ 'Content
',
+ '{{item.name}} ',
+ '{{#each this.items as |item|}}{{item}} {{/each}} ',
+ 'Click ',
+ ],
+
+ invalid: [
+ {
+ code: '{{content}}
',
+ output: null,
+ errors: [
+ {
+ message: 'Block params can only be used with components, not HTML elements.',
+ type: 'GlimmerElementNode',
+ },
+ ],
+ },
+ {
+ code: ' ',
+ output: null,
+ errors: [
+ {
+ message: 'Block params can only be used with components, not HTML elements.',
+ type: 'GlimmerElementNode',
+ },
+ ],
+ },
+ {
+ code: ' ',
+ output: null,
+ errors: [
+ {
+ message: 'Block params can only be used with components, not HTML elements.',
+ type: 'GlimmerElementNode',
+ },
+ ],
+ },
+ ],
+});