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 + } + } ]