Skip to content

Commit 1bec1a2

Browse files
Merge pull request #2654 from johanrd/night_fix/template-no-action-modifiers
Post-merge-review: Fix `template-no-action-modifiers` autofix: skip when hash pairs are present
2 parents 26de552 + a32284a commit 1bec1a2

2 files changed

Lines changed: 40 additions & 9 deletions

File tree

lib/rules/template-no-action-modifiers.js

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,33 +49,46 @@ module.exports = {
4949
node.path.head?.type !== 'AtHead' &&
5050
node.path.head?.type !== 'ThisHead'
5151
) {
52-
// Only offer autofix when the first param is a path expression
52+
// Only offer autofix when the first param is a path expression.
53+
// If hash pairs are present, only fix when the sole hash pair is `on="<event>"` —
54+
// we can read the event name from there and drop the pair in the output.
5355
const maybePath = node.params?.[0];
54-
const canFix = maybePath && maybePath.type === 'GlimmerPathExpression';
56+
const hashPairs = node.hash?.pairs || [];
57+
const onPair = hashPairs.find((p) => p.key === 'on');
58+
const otherPairs = hashPairs.filter((p) => p.key !== 'on');
59+
60+
const canFix =
61+
maybePath &&
62+
maybePath.type === 'GlimmerPathExpression' &&
63+
otherPairs.length === 0 &&
64+
(onPair === undefined || onPair.value.type === 'GlimmerStringLiteral');
5565

5666
context.report({
5767
node,
5868
messageId: 'noActionModifier',
5969
fix: canFix
6070
? (fixer) => {
71+
const eventName =
72+
onPair && onPair.value.type === 'GlimmerStringLiteral'
73+
? onPair.value.value
74+
: 'click';
75+
6176
const args = node.params.slice(1);
6277
const pathText = sourceCode.getText(maybePath);
6378

6479
let replacement;
6580
if (args.length === 0) {
6681
// {{action this.handleClick}} → {{on "click" this.handleClick}}
67-
replacement = `on "click" ${pathText}`;
82+
// {{action this.handleClick on="submit"}} → {{on "submit" this.handleClick}}
83+
replacement = `on "${eventName}" ${pathText}`;
6884
} else {
6985
// {{action this.handleClick "arg"}} → {{on "click" (fn this.handleClick "arg")}}
7086
const argsText = args.map((a) => sourceCode.getText(a)).join(' ');
71-
replacement = `on "click" (fn ${pathText} ${argsText})`;
87+
replacement = `on "${eventName}" (fn ${pathText} ${argsText})`;
7288
}
7389

74-
const lastParam = node.params.at(-1);
75-
return fixer.replaceTextRange(
76-
[node.path.range[0], lastParam.range[1]],
77-
replacement
78-
);
90+
// Replace from start of `action` to just before `}}`, covering any hash pairs
91+
return fixer.replaceTextRange([node.path.range[0], node.range[1] - 2], replacement);
7992
}
8093
: null,
8194
});

tests/lib/rules/template-no-action-modifiers.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,5 +61,23 @@ ruleTester.run('template-no-action-modifiers', rule, {
6161
'<template><button {{on "click" (fn this.handleClick "arg1" "arg2")}}>Save</button></template>',
6262
errors: [{ messageId: 'noActionModifier' }],
6363
},
64+
{
65+
// Path expression with on="click" hash — autofix reads event from hash and drops it
66+
code: '<template><button {{action this.handleClick on="click"}}>Save</button></template>',
67+
output: '<template><button {{on "click" this.handleClick}}>Save</button></template>',
68+
errors: [{ messageId: 'noActionModifier' }],
69+
},
70+
{
71+
// Path expression with on="submit" hash — autofix reads event from hash and drops it
72+
code: '<template><form {{action this.handleSubmit on="submit"}}>Submit</form></template>',
73+
output: '<template><form {{on "submit" this.handleSubmit}}>Submit</form></template>',
74+
errors: [{ messageId: 'noActionModifier' }],
75+
},
76+
{
77+
// Non-`on` hash pair present — no autofix (can't safely translate other hash pairs)
78+
code: '<template><button {{action this.handleClick bubbles=false}}>Save</button></template>',
79+
output: null,
80+
errors: [{ messageId: 'noActionModifier' }],
81+
},
6482
],
6583
});

0 commit comments

Comments
 (0)