From a9b5b0a9295fd9c63252e36cc856e65a76eabebb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Lins?= Date: Tue, 5 May 2020 22:44:50 -0300 Subject: [PATCH] A11y rule no-onchange --- src/compiler/compile/nodes/Element.ts | 24 +++++++++++++- .../samples/a11y-no-onchange/input.svelte | 16 ++++++++++ .../samples/a11y-no-onchange/warnings.json | 32 +++++++++++++++++++ 3 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 test/validator/samples/a11y-no-onchange/input.svelte create mode 100644 test/validator/samples/a11y-no-onchange/warnings.json diff --git a/src/compiler/compile/nodes/Element.ts b/src/compiler/compile/nodes/Element.ts index 93997ae66e..b25b57c76f 100644 --- a/src/compiler/compile/nodes/Element.ts +++ b/src/compiler/compile/nodes/Element.ts @@ -56,6 +56,11 @@ const a11y_required_content = new Set([ 'h6' ]); +const a11y_no_onchange = new Set([ + 'select', + 'option' +]); + const invisible_elements = new Set(['meta', 'html', 'script', 'style']); const valid_modifiers = new Set([ @@ -424,13 +429,18 @@ export default class Element extends Node { } validate_special_cases() { - const { component,attributes } = this; + const { component, attributes, handlers } = this; const attribute_map = new Map(); + const handlers_map = new Map(); attributes.forEach(attribute => ( attribute_map.set(attribute.name, attribute) )); + handlers.forEach(handler => ( + handlers_map.set(handler.name, handler) + )); + if (this.name === 'a') { const href_attribute = attribute_map.get('href') || attribute_map.get('xlink:href'); const id_attribute = attribute_map.get('id'); @@ -496,6 +506,18 @@ export default class Element extends Node { } } } + + if (a11y_no_onchange.has(this.name)) { + const change_handler = handlers_map.get('change'); + const blur_handler = handlers_map.get('blur'); + + if (change_handler && !blur_handler) { + component.warn(this, { + code: `a11y-no-onchange`, + message: `A11y: onBlur must be used instead of onchange, unless absolutely necessary and it causes no negative consequences for keyboard only or screen reader users.` + }); + } + } } validate_bindings() { diff --git a/test/validator/samples/a11y-no-onchange/input.svelte b/test/validator/samples/a11y-no-onchange/input.svelte new file mode 100644 index 0000000000..af2041f406 --- /dev/null +++ b/test/validator/samples/a11y-no-onchange/input.svelte @@ -0,0 +1,16 @@ + + + + \ No newline at end of file diff --git a/test/validator/samples/a11y-no-onchange/warnings.json b/test/validator/samples/a11y-no-onchange/warnings.json new file mode 100644 index 0000000000..7103ee523c --- /dev/null +++ b/test/validator/samples/a11y-no-onchange/warnings.json @@ -0,0 +1,32 @@ +[ + { + "code": "a11y-no-onchange", + "end": { + "character": 88, + "column": 9, + "line": 4 + }, + "message": "A11y: onBlur must be used instead of onchange, unless absolutely necessary and it causes no negative consequences for keyboard only or screen reader users.", + "pos": 0, + "start": { + "character": 0, + "column": 0, + "line": 1 + } + }, + { + "code": "a11y-no-onchange", + "end": { + "character": 249, + "column": 44, + "line": 10 + }, + "message": "A11y: onBlur must be used instead of onchange, unless absolutely necessary and it causes no negative consequences for keyboard only or screen reader users.", + "pos": 209, + "start": { + "character": 209, + "column": 4, + "line": 10 + } + } +] \ No newline at end of file