diff --git a/src/validate/html/a11y.ts b/src/validate/html/a11y.ts index c7d50f17e3..4cb1c0be8e 100644 --- a/src/validate/html/a11y.ts +++ b/src/validate/html/a11y.ts @@ -1,9 +1,13 @@ import * as namespaces from '../../utils/namespaces'; import getStaticAttributeValue from '../../utils/getStaticAttributeValue'; +import fuzzymatch from '../utils/fuzzymatch'; import validateEventHandler from './validateEventHandler'; import { Validator } from '../index'; import { Node } from '../../interfaces'; +const ariaAttributes = 'activedescendant atomic autocomplete busy checked controls describedby disabled dropeffect expanded flowto grabbed haspopup hidden invalid label labelledby level live multiline multiselectable orientation owns posinset pressed readonly relevant required selected setsize sort valuemax valuemin valuenow valuetext'.split(' '); +const ariaSet = new Set(ariaAttributes); + export default function a11y( validator: Validator, node: Node, @@ -18,6 +22,17 @@ export default function a11y( const attributeMap = new Map(); node.attributes.forEach((attribute: Node) => { + if (attribute.name.startsWith('aria-')) { + const name = attribute.name.slice(5); + if (!ariaSet.has(name)) { + const match = fuzzymatch(name, ariaAttributes); + let message = `A11y: Unknown aria attribute 'aria-${name}'`; + if (match) message += ` (did you mean '${match}'?)`; + + validator.warn(message, attribute.start); + } + } + attributeMap.set(attribute.name, attribute); }); @@ -28,13 +43,8 @@ export default function a11y( attributes.slice(0, -1).join(', ') + ` or ${attributes[attributes.length - 1]}` : attributes[0]; - console.log(`warning about ${name}: ${sequence}`) validator.warn(`A11y: <${name}> element should have ${article} ${sequence} attribute`, node.start); } - - else { - console.log('ok', node.name); - } } if (node.name === 'a') { diff --git a/test/validator/samples/a11y-aria-props/input.html b/test/validator/samples/a11y-aria-props/input.html new file mode 100644 index 0000000000..21c6327960 --- /dev/null +++ b/test/validator/samples/a11y-aria-props/input.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/validator/samples/a11y-aria-props/warnings.json b/test/validator/samples/a11y-aria-props/warnings.json new file mode 100644 index 0000000000..5c0ce2c49e --- /dev/null +++ b/test/validator/samples/a11y-aria-props/warnings.json @@ -0,0 +1,19 @@ +[ + { + "message": "A11y: Unknown aria attribute 'aria-labeledby' (did you mean 'labelledby'?)", + "loc": { + "line": 1, + "column": 20 + }, + "pos": 20 + }, + + { + "message": "A11y: element should have an alt, aria-label or aria-labelledby attribute", + "loc": { + "column": 0, + "line": 1 + }, + "pos": 0 + } +]