UNPKG

eslint-plugin-ember

Version:
104 lines (97 loc) 2.83 kB
function isInsideForm(node) { let current = node.parent; while (current) { if (current.type === 'GlimmerElementNode' && current.tag === 'form') { // <form method="dialog"> closes the dialog on submit without navigating, // so click handlers on submit buttons are intentional and correct. // See https://github.com/ember-template-lint/ember-template-lint/issues/2989 const methodAttr = current.attributes?.find((a) => a.name === 'method'); if ( methodAttr && methodAttr.value?.type === 'GlimmerTextNode' && methodAttr.value.chars.toLowerCase() === 'dialog' ) { return false; } return true; } current = current.parent; } return false; } function isSubmitButton(node) { for (const attr of node.attributes || []) { if ( attr.name === 'type' && attr.value?.type === 'GlimmerTextNode' && attr.value.chars !== 'submit' ) { return false; } } return true; } function hasClickHandlingModifier(node) { for (const mod of node.modifiers || []) { if (mod.path?.original === 'action') { // {{action ...}} defaults to click event const onPair = mod.hash?.pairs?.find((p) => p.key === 'on'); if (!onPair) { return true; } const eventValue = onPair.value?.value ?? onPair.value?.chars; if (eventValue === 'click') { return true; } } if (mod.path?.original === 'on') { // {{on "event" handler}} if (mod.params?.length > 0 && mod.params[0].value === 'click') { return true; } } } return false; } /** @type {import('eslint').Rule.RuleModule} */ module.exports = { meta: { type: 'problem', docs: { description: 'disallow action attribute on submit buttons', category: 'Best Practices', url: 'https://github.com/ember-cli/eslint-plugin-ember/tree/master/docs/rules/template-no-action-on-submit-button.md', templateMode: 'both', }, fixable: null, schema: [], messages: { noActionOnSubmitButton: 'In a `<form>`, a `<button>` with `type="submit"` should have no click action', }, originallyFrom: { name: 'ember-template-lint', rule: 'lib/rules/no-action-on-submit-button.js', docs: 'docs/rule/no-action-on-submit-button.md', tests: 'test/unit/rules/no-action-on-submit-button-test.js', }, }, create(context) { return { GlimmerElementNode(node) { if (node.tag !== 'button') { return; } if (!isInsideForm(node)) { return; } if (isSubmitButton(node) && hasClickHandlingModifier(node)) { context.report({ node, messageId: 'noActionOnSubmitButton', }); } }, }; }, };