From 7d3c8b1ce5e1884b2a25c1916d6dbccdc4bf4b9a Mon Sep 17 00:00:00 2001 From: Lindsey Wild <35239154+lindseywild@users.noreply.github.com> Date: Tue, 11 Jul 2023 11:06:54 +0000 Subject: [PATCH 1/8] adds test for svg-has-accessible-name rule --- tests/a11y-svg-has-accessible-name.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 tests/a11y-svg-has-accessible-name.js diff --git a/tests/a11y-svg-has-accessible-name.js b/tests/a11y-svg-has-accessible-name.js new file mode 100644 index 00000000..291ef60b --- /dev/null +++ b/tests/a11y-svg-has-accessible-name.js @@ -0,0 +1,26 @@ +const rule = require('../lib/rules/a11y-svg-has-accessible-name') +const RuleTester = require('eslint').RuleTester + +const ruleTester = new RuleTester({ + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + ecmaFeatures: { + jsx: true, + }, + }, +}) + +const errorMessage = + 'SVG elements should have an accessible name. Add a `Codestin Search App"}, + {code: ""}, + {code: ""}, + ], + invalid: [ + {code: ";", errors: [{message: errorMessage}]}, + ], +}) From 46fa4a676a00d2c227e08993f7146be45470c370 Mon Sep 17 00:00:00 2001 From: Lindsey Wild <35239154+lindseywild@users.noreply.github.com> Date: Tue, 11 Jul 2023 11:09:07 +0000 Subject: [PATCH 2/8] updates text --- tests/a11y-svg-has-accessible-name.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/a11y-svg-has-accessible-name.js b/tests/a11y-svg-has-accessible-name.js index 291ef60b..d50f32ae 100644 --- a/tests/a11y-svg-has-accessible-name.js +++ b/tests/a11y-svg-has-accessible-name.js @@ -12,7 +12,7 @@ const ruleTester = new RuleTester({ }) const errorMessage = - 'SVG elements should have an accessible name. Add a `Codestin Search App"}, {code: ""}, {code: ""}, + {code: ""}, + {code: ""}, ], invalid: [ {code: ";", errors: [{message: errorMessage}]}, From 4a59a5b3712b017e599390a51195a594139cc5e7 Mon Sep 17 00:00:00 2001 From: Lindsey Wild <35239154+lindseywild@users.noreply.github.com> Date: Tue, 11 Jul 2023 11:08:07 -0400 Subject: [PATCH 4/8] adds code for checking for accessible svg --- lib/rules/a11y-svg-has-accessible-name.js | 41 +++++++++++++++++++++++ tests/a11y-svg-has-accessible-name.js | 37 +++++++++++++++----- 2 files changed, 70 insertions(+), 8 deletions(-) create mode 100644 lib/rules/a11y-svg-has-accessible-name.js diff --git a/lib/rules/a11y-svg-has-accessible-name.js b/lib/rules/a11y-svg-has-accessible-name.js new file mode 100644 index 00000000..c1a6d15f --- /dev/null +++ b/lib/rules/a11y-svg-has-accessible-name.js @@ -0,0 +1,41 @@ +const {hasProp} = require('jsx-ast-utils') +const {getElementType} = require('../utils/get-element-type') + +module.exports = { + meta: { + docs: { + description: 'svg must have an accessible name', + url: require('../url')(module), + }, + schema: [], + }, + + create(context) { + return { + JSXOpeningElement: node => { + const elementType = getElementType(context, node) + + // Check if there is a nested title element that is the first child of the `` + const hasNestedTitleAsFirstChild = + node.parent.children.length && + node.parent.children[0].type === 'JSXElement' && + node.parent.children[0].openingElement.name.name === 'title' + + // Check if `aria-label` or `aria-labelledby` is set + const hasAccessibleName = hasProp(node.attributes, 'aria-label') || hasProp(node.attributes, 'aria-labelledby') + + // Check if SVG is decorative + const isDecorative = + hasProp(node.attributes, 'role', 'presentation') || hasProp(node.attributes, 'aria-hidden', 'true') + + if (elementType === 'svg' && !hasAccessibleName && !isDecorative && !hasNestedTitleAsFirstChild) { + context.report({ + node, + message: + '`` must have accessible text. Set `aria-label` or `aria-labelledby`, or nest a `Codestin Search App"}, - {code: ""}, - {code: ""}, - {code: ""}, - {code: ""}, + { + code: "Codestin Search App", + }, + { + code: "", + }, + { + code: "", + }, + { + code: "", + }, + { + code: "", + }, ], invalid: [ - {code: ";", errors: [{message: errorMessage}]}, + { + code: "", + errors: [{message: errorMessage}], + }, + { + code: "", + errors: [{message: errorMessage}], + }, + { + code: "Codestin Search App", + errors: [{message: errorMessage}], + }, ], }) From ce88c1998bb972c8211a4489649d69ce38ba8169 Mon Sep 17 00:00:00 2001 From: Lindsey Wild <35239154+lindseywild@users.noreply.github.com> Date: Tue, 11 Jul 2023 11:17:08 -0400 Subject: [PATCH 5/8] adds docs --- docs/rules/a11y-svg-has-accessible-name.md | 73 ++++++++++++++++++++++ lib/rules/a11y-svg-has-accessible-name.js | 4 +- tests/a11y-svg-has-accessible-name.js | 2 +- 3 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 docs/rules/a11y-svg-has-accessible-name.md diff --git a/docs/rules/a11y-svg-has-accessible-name.md b/docs/rules/a11y-svg-has-accessible-name.md new file mode 100644 index 00000000..088e918b --- /dev/null +++ b/docs/rules/a11y-svg-has-accessible-name.md @@ -0,0 +1,73 @@ +# SVGs must have an accessible name (`github/a11y-svg-has-accessible-name`) + +💼 This rule is enabled in the ⚛️ `react` config. + + + +## Rule Details + +An `` must have an accessible name. Set `aria-label` or `aria-labelledby`, or nest a `Codestin Search App + +``` + +### **Correct** code for this rule 👍 + +```html + + Codestin Search App + + +``` + +```html + + + +``` + +```html + + + +``` + +```html + +``` + +```html + + + +``` + +## Version diff --git a/lib/rules/a11y-svg-has-accessible-name.js b/lib/rules/a11y-svg-has-accessible-name.js index c1a6d15f..9ac064ce 100644 --- a/lib/rules/a11y-svg-has-accessible-name.js +++ b/lib/rules/a11y-svg-has-accessible-name.js @@ -4,7 +4,7 @@ const {getElementType} = require('../utils/get-element-type') module.exports = { meta: { docs: { - description: 'svg must have an accessible name', + description: 'SVGs must have an accessible name', url: require('../url')(module), }, schema: [], @@ -32,7 +32,7 @@ module.exports = { context.report({ node, message: - '`` must have accessible text. Set `aria-label` or `aria-labelledby`, or nest a `` element. However, if the `` is purely decorative, hide it with `aria-hidden="true"` or `role="presentation"`.', + '`` must have an accessible name. Set `aria-label` or `aria-labelledby`, or nest a `` element. However, if the `` is purely decorative, hide it with `aria-hidden="true"` or `role="presentation"`.', }) } }, diff --git a/tests/a11y-svg-has-accessible-name.js b/tests/a11y-svg-has-accessible-name.js index 169b192e..c708ee9a 100644 --- a/tests/a11y-svg-has-accessible-name.js +++ b/tests/a11y-svg-has-accessible-name.js @@ -12,7 +12,7 @@ const ruleTester = new RuleTester({ }) const errorMessage = - '`` must have accessible text. Set `aria-label` or `aria-labelledby`, or nest a `` element. However, if the `` is purely decorative, hide it with `aria-hidden="true"` or `role="presentation"`.' + '`` must have an accessible name. Set `aria-label` or `aria-labelledby`, or nest a `` element. However, if the `` is purely decorative, hide it with `aria-hidden="true"` or `role="presentation"`.' ruleTester.run('a11y-svg-has-accessible-name', rule, { valid: [ From 485a104dd1ea4adee5196db146faad40891bf9d7 Mon Sep 17 00:00:00 2001 From: Lindsey Wild <35239154+lindseywild@users.noreply.github.com> Date: Tue, 11 Jul 2023 11:18:07 -0400 Subject: [PATCH 6/8] adds to react preset --- lib/configs/react.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/configs/react.js b/lib/configs/react.js index 63021526..2644a266 100644 --- a/lib/configs/react.js +++ b/lib/configs/react.js @@ -11,6 +11,7 @@ module.exports = { 'jsx-a11y/role-supports-aria-props': 'off', // Override with github/role-supports-aria-props until https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/issues/910 is resolved 'github/a11y-aria-label-is-well-formatted': 'error', 'github/a11y-no-visually-hidden-interactive-element': 'error', + 'github/a11y-svg-has-accessible-name': 'error', 'github/role-supports-aria-props': 'error', 'jsx-a11y/no-aria-hidden-on-focusable': 'error', 'jsx-a11y/no-autofocus': 'off', From c633deb48025ed7a13b0fcbfc15ec32a623cdf98 Mon Sep 17 00:00:00 2001 From: Lindsey Wild <35239154+lindseywild@users.noreply.github.com> Date: Tue, 11 Jul 2023 11:20:44 -0400 Subject: [PATCH 7/8] adds to index --- README.md | 1 + lib/index.js | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index 67bdfb84..9364f4d1 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,7 @@ This config will be interpreted in the following way: | [a11y-aria-label-is-well-formatted](docs/rules/a11y-aria-label-is-well-formatted.md) | [aria-label] text should be formatted as you would visual text. | ⚛️ | | | | [a11y-no-generic-link-text](docs/rules/a11y-no-generic-link-text.md) | disallow generic link text | | | ❌ | | [a11y-no-visually-hidden-interactive-element](docs/rules/a11y-no-visually-hidden-interactive-element.md) | Ensures that interactive elements are not visually hidden | ⚛️ | | | +| [a11y-svg-has-accessible-name](docs/rules/a11y-svg-has-accessible-name.md) | SVGs must have an accessible name | ⚛️ | | | | [array-foreach](docs/rules/array-foreach.md) | enforce `for..of` loops over `Array.forEach` | ✅ | | | | [async-currenttarget](docs/rules/async-currenttarget.md) | disallow `event.currentTarget` calls inside of async functions | 🔍 | | | | [async-preventdefault](docs/rules/async-preventdefault.md) | disallow `event.preventDefault` calls inside of async functions | 🔍 | | | diff --git a/lib/index.js b/lib/index.js index e3bd98a5..d6a08fa3 100644 --- a/lib/index.js +++ b/lib/index.js @@ -3,6 +3,7 @@ module.exports = { 'a11y-no-visually-hidden-interactive-element': require('./rules/a11y-no-visually-hidden-interactive-element'), 'a11y-no-generic-link-text': require('./rules/a11y-no-generic-link-text'), 'a11y-aria-label-is-well-formatted': require('./rules/a11y-aria-label-is-well-formatted'), + 'a11y-svg-has-accessible-name': require('./rules/a11y-svg-has-accessible-name'), 'array-foreach': require('./rules/array-foreach'), 'async-currenttarget': require('./rules/async-currenttarget'), 'async-preventdefault': require('./rules/async-preventdefault'), From e77c35ed96ae707b3dda01c38a6804316728a3d8 Mon Sep 17 00:00:00 2001 From: Lindsey Wild <35239154+lindseywild@users.noreply.github.com> Date: Tue, 11 Jul 2023 12:14:15 -0400 Subject: [PATCH 8/8] Apply suggestions from code review Co-authored-by: Keith Cirkel --- lib/rules/a11y-svg-has-accessible-name.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/rules/a11y-svg-has-accessible-name.js b/lib/rules/a11y-svg-has-accessible-name.js index 9ac064ce..e8c92a8f 100644 --- a/lib/rules/a11y-svg-has-accessible-name.js +++ b/lib/rules/a11y-svg-has-accessible-name.js @@ -14,12 +14,12 @@ module.exports = { return { JSXOpeningElement: node => { const elementType = getElementType(context, node) + if (elementType !== 'svg') return // Check if there is a nested title element that is the first child of the `` const hasNestedTitleAsFirstChild = - node.parent.children.length && - node.parent.children[0].type === 'JSXElement' && - node.parent.children[0].openingElement.name.name === 'title' + node.parent.children?.[0]?.type === 'JSXElement' && + node.parent.children?.[0]?.openingElement?.name?.name === 'title' // Check if `aria-label` or `aria-labelledby` is set const hasAccessibleName = hasProp(node.attributes, 'aria-label') || hasProp(node.attributes, 'aria-labelledby')