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 + +``` + +```gjs + +``` + +```gjs + +``` + +### Correct ✅ + +```gjs + +``` + +```gjs + +``` + +```gjs + +``` + +## 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 = ; + + `, + '', + '', + '', + '', + ], + + invalid: [ + { + 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', + }, + ], + }, + { + code: '', + output: null, + errors: [ + { + message: 'Block params can only be used with components, not HTML elements.', + type: 'GlimmerElementNode', + }, + ], + }, + ], +});