From 419641bb3eefb53b4c627005b3637882e5e5342f Mon Sep 17 00:00:00 2001 From: Niko Simonson Date: Mon, 8 Aug 2022 09:01:54 -0700 Subject: [PATCH] Recursively check label children for input control (#5323) * Recursively check label children for input control * Add another test case * Update snapshot * clean up test Co-authored-by: tanhauhau --- src/compiler/compile/nodes/Element.ts | 20 ++++++- .../input.svelte | 3 + .../warnings.json | 1 + .../input.svelte | 6 ++ .../warnings.json | 60 +++++++++---------- 5 files changed, 58 insertions(+), 32 deletions(-) create mode 100644 test/validator/samples/a11y-label-has-associated-control-2/input.svelte create mode 100644 test/validator/samples/a11y-label-has-associated-control-2/warnings.json diff --git a/src/compiler/compile/nodes/Element.ts b/src/compiler/compile/nodes/Element.ts index e351a02499c..119e1879540 100644 --- a/src/compiler/compile/nodes/Element.ts +++ b/src/compiler/compile/nodes/Element.ts @@ -626,8 +626,24 @@ export default class Element extends Node { } if (this.name === 'label') { - const has_input_child = this.children.some(i => (i instanceof Element && a11y_labelable.has(i.name) )); - if (!attribute_map.has('for') && !has_input_child) { + const has_input_child = (children: INode[]) => { + if (children.some(child => (child instanceof Element && (a11y_labelable.has(child.name) || child.name === 'slot')))) { + return true; + } + + for (const child of children) { + if (!('children' in child) || child.children.length === 0) { + continue; + } + if (has_input_child(child.children)) { + return true; + } + } + + return false; + }; + + if (!attribute_map.has('for') && !has_input_child(this.children)) { component.warn(this, compiler_warnings.a11y_label_has_associated_control); } } diff --git a/test/validator/samples/a11y-label-has-associated-control-2/input.svelte b/test/validator/samples/a11y-label-has-associated-control-2/input.svelte new file mode 100644 index 00000000000..de26d50782d --- /dev/null +++ b/test/validator/samples/a11y-label-has-associated-control-2/input.svelte @@ -0,0 +1,3 @@ + diff --git a/test/validator/samples/a11y-label-has-associated-control-2/warnings.json b/test/validator/samples/a11y-label-has-associated-control-2/warnings.json new file mode 100644 index 00000000000..fe51488c706 --- /dev/null +++ b/test/validator/samples/a11y-label-has-associated-control-2/warnings.json @@ -0,0 +1 @@ +[] diff --git a/test/validator/samples/a11y-label-has-associated-control/input.svelte b/test/validator/samples/a11y-label-has-associated-control/input.svelte index 43304689dc2..124888c089a 100644 --- a/test/validator/samples/a11y-label-has-associated-control/input.svelte +++ b/test/validator/samples/a11y-label-has-associated-control/input.svelte @@ -1,6 +1,12 @@ + + + +G diff --git a/test/validator/samples/a11y-label-has-associated-control/warnings.json b/test/validator/samples/a11y-label-has-associated-control/warnings.json index b70a1a47de7..f618e169734 100644 --- a/test/validator/samples/a11y-label-has-associated-control/warnings.json +++ b/test/validator/samples/a11y-label-has-associated-control/warnings.json @@ -1,32 +1,32 @@ [ - { - "code": "a11y-label-has-associated-control", - "end": { - "character": 16, - "column": 16, - "line": 1 - }, - "message": "A11y: A form label must be associated with a control.", - "pos": 0, - "start": { - "character": 0, - "column": 0, - "line": 1 - } - }, - { - "code": "a11y-label-has-associated-control", - "end": { - "character": 149, - "column": 30, - "line": 6 - }, - "message": "A11y: A form label must be associated with a control.", - "pos": 119, - "start": { - "character": 119, - "column": 0, - "line": 6 - } - } + { + "code": "a11y-label-has-associated-control", + "end": { + "character": 82, + "column": 16, + "line": 5 + }, + "message": "A11y: A form label must be associated with a control.", + "pos": 66, + "start": { + "character": 66, + "column": 0, + "line": 5 + } + }, + { + "code": "a11y-label-has-associated-control", + "end": { + "character": 215, + "column": 30, + "line": 10 + }, + "message": "A11y: A form label must be associated with a control.", + "pos": 185, + "start": { + "character": 185, + "column": 0, + "line": 10 + } + } ]