From 02c44c0ed18a52852a85a8831ef595f3aa05b44d Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Thu, 19 Feb 2026 16:30:24 -0500 Subject: [PATCH] Extract rule: template-no-action-modifiers --- README.md | 1 + docs/rules/template-no-action-modifiers.md | 64 +++++++++++++++++++ lib/rules/template-no-action-modifiers.js | 42 ++++++++++++ .../lib/rules/template-no-action-modifiers.js | 51 +++++++++++++++ 4 files changed, 158 insertions(+) create mode 100644 docs/rules/template-no-action-modifiers.md create mode 100644 lib/rules/template-no-action-modifiers.js create mode 100644 tests/lib/rules/template-no-action-modifiers.js diff --git a/README.md b/README.md index 384e45ca98..330bed0756 100644 --- a/README.md +++ b/README.md @@ -190,6 +190,7 @@ rules in templates can be disabled with eslint directives with mustache or html | 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-debugger](docs/rules/template-no-debugger.md) | disallow {{debugger}} in templates | | | | | [template-no-log](docs/rules/template-no-log.md) | disallow {{log}} in templates | | | | diff --git a/docs/rules/template-no-action-modifiers.md b/docs/rules/template-no-action-modifiers.md new file mode 100644 index 0000000000..d62ca80549 --- /dev/null +++ b/docs/rules/template-no-action-modifiers.md @@ -0,0 +1,64 @@ +# ember/template-no-action-modifiers + + + +💼 This rule is enabled in the following [configs](https://github.com/ember-cli/eslint-plugin-ember#-configurations): `strict-gjs`, `strict-gts`. + +Disallow usage of `{{action}}` modifiers in templates. + +The `{{action}}` modifier has been deprecated in favor of the `{{on}}` modifier. The `{{on}}` modifier provides a more explicit and flexible way to handle events. + +## Rule Details + +This rule disallows using `{{action}}` as an element modifier. + +## Examples + +### Incorrect ❌ + +```gjs + +``` + +```gjs + +``` + +```gjs + +``` + +### Correct ✅ + +```gjs + +``` + +```gjs + +``` + +```gjs + +``` + +## Related Rules + +- [template-no-action](./template-no-action.md) + +## References + +- [Ember Octane Guide - Element Modifiers](https://guides.emberjs.com/release/components/template-lifecycle-dom-and-modifiers/) +- [eslint-plugin-ember template-no-action](https://github.com/ember-cli/eslint-plugin-ember/blob/master/docs/rules/template-no-action.md) diff --git a/lib/rules/template-no-action-modifiers.js b/lib/rules/template-no-action-modifiers.js new file mode 100644 index 0000000000..5aa37f74be --- /dev/null +++ b/lib/rules/template-no-action-modifiers.js @@ -0,0 +1,42 @@ +/** @type {import('eslint').Rule.RuleModule} */ +module.exports = { + meta: { + type: 'suggestion', + docs: { + description: 'disallow usage of {{action}} modifiers', + category: 'Best Practices', + strictGjs: true, + strictGts: true, + url: 'https://github.com/ember-cli/eslint-plugin-ember/tree/master/docs/rules/template-no-action-modifiers.md', + }, + fixable: null, + schema: [], + messages: { + noActionModifier: 'Do not use action modifiers. Use on modifier with a function instead.', + }, + }, + + create(context) { + function checkForActionModifier(node) { + // Check if this is an action modifier (not action helper in mustache) + if ( + node.path && + node.path.type === 'GlimmerPathExpression' && + node.path.original === 'action' && + node.path.head?.type !== 'AtHead' && + node.path.head?.type !== 'ThisHead' + ) { + context.report({ + node, + messageId: 'noActionModifier', + }); + } + } + + return { + GlimmerElementModifierStatement(node) { + checkForActionModifier(node); + }, + }; + }, +}; diff --git a/tests/lib/rules/template-no-action-modifiers.js b/tests/lib/rules/template-no-action-modifiers.js new file mode 100644 index 0000000000..ad9debaa67 --- /dev/null +++ b/tests/lib/rules/template-no-action-modifiers.js @@ -0,0 +1,51 @@ +const rule = require('../../../lib/rules/template-no-action-modifiers'); +const RuleTester = require('eslint').RuleTester; + +const ruleTester = new RuleTester({ + parser: require.resolve('ember-eslint-parser'), + parserOptions: { ecmaVersion: 2022, sourceType: 'module' }, +}); + +ruleTester.run('template-no-action-modifiers', rule, { + valid: [ + '', + '', + '', + '', + '', + '', + ], + + invalid: [ + { + code: '', + output: null, + errors: [ + { + message: 'Do not use action modifiers. Use on modifier with a function instead.', + type: 'GlimmerElementModifierStatement', + }, + ], + }, + { + code: '', + output: null, + errors: [ + { + message: 'Do not use action modifiers. Use on modifier with a function instead.', + type: 'GlimmerElementModifierStatement', + }, + ], + }, + { + code: '', + output: null, + errors: [ + { + message: 'Do not use action modifiers. Use on modifier with a function instead.', + type: 'GlimmerElementModifierStatement', + }, + ], + }, + ], +});