Skip to content

Commit

Permalink
Move map constructing code into a function
Browse files Browse the repository at this point in the history
  • Loading branch information
khiga8 committed Jul 12, 2023
1 parent aaca700 commit 40c0b2b
Showing 1 changed file with 30 additions and 19 deletions.
49 changes: 30 additions & 19 deletions lib/utils/get-role.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,38 @@ const {elementRoles} = require('aria-query')
const {getElementType} = require('./get-element-type')
const ObjectMap = require('./object-map')

// Clean-up `elementRoles` from `aria-query`.
const elementRolesMap = new ObjectMap()
for (const [key, value] of elementRoles.entries()) {
// - Remove empty `attributes` key
if (!key.attributes || key.attributes?.length === 0) {
delete key.attributes
const elementRolesMap = cleanElementRolesMap()

/*
Returns an element roles map which uses `aria-query`'s elementRoles as the foundation.
We additionally clean the data so we're able to fetch a role using a key we construct based on the node we're looking at.
In a few scenarios, we stray from the roles returned by `aria-query` and hard code the mapping.
*/
function cleanElementRolesMap() {
const rolesMap = new ObjectMap()

for (const [key, value] of elementRoles.entries()) {
// - Remove empty `attributes` key
if (!key.attributes || key.attributes?.length === 0) {
delete key.attributes
}
rolesMap.set(key, value)
}
elementRolesMap.set(key, value)
}
// Remove insufficiently-disambiguated `menuitem` entry
elementRolesMap.delete({name: 'menuitem'})
// Disambiguate `menuitem` and `menu` roles by `type`
elementRolesMap.set({name: 'menuitem', attributes: [{name: 'type', value: 'command'}]}, ['menuitem'])
elementRolesMap.set({name: 'menuitem', attributes: [{name: 'type', value: 'radio'}]}, ['menuitemradio'])
elementRolesMap.set({name: 'menuitem', attributes: [{name: 'type', value: 'toolbar'}]}, ['toolbar'])
elementRolesMap.set({name: 'menu', attributes: [{name: 'type', value: 'toolbar'}]}, ['toolbar'])
// Remove insufficiently-disambiguated `menuitem` entry
rolesMap.delete({name: 'menuitem'})
// Disambiguate `menuitem` and `menu` roles by `type`
rolesMap.set({name: 'menuitem', attributes: [{name: 'type', value: 'command'}]}, ['menuitem'])
rolesMap.set({name: 'menuitem', attributes: [{name: 'type', value: 'radio'}]}, ['menuitemradio'])
rolesMap.set({name: 'menuitem', attributes: [{name: 'type', value: 'toolbar'}]}, ['toolbar'])
rolesMap.set({name: 'menu', attributes: [{name: 'type', value: 'toolbar'}]}, ['toolbar'])

/* These have constraints defined in aria-query's `elementRoles` which depend on knowledge of ancestor roles which we cant accurately determine in a linter context.
However, we benefit more from assuming the role, than assuming it's generic or undefined so we opt to hard code the mapping */
elementRolesMap.set({name: 'aside'}, ['complementary']) // `aside` still maps to `complementary` in https://www.w3.org/TR/html-aria/#docconformance.
elementRolesMap.set({name: 'li'}, ['listitem']) // `li` can be generic if it's not within a list but we would never want to render `li` outside of a list.
/* These have constraints defined in aria-query's `elementRoles` which depend on knowledge of ancestor roles which we cant accurately determine in a linter context.
However, we benefit more from assuming the role, than assuming it's generic or undefined so we opt to hard code the mapping */
rolesMap.set({name: 'aside'}, ['complementary']) // `aside` still maps to `complementary` in https://www.w3.org/TR/html-aria/#docconformance.
rolesMap.set({name: 'li'}, ['listitem']) // `li` can be generic if it's not within a list but we would never want to render `li` outside of a list.

return rolesMap
}

/*
Determine role of an element, based on its name and attributes.
Expand Down

0 comments on commit 40c0b2b

Please sign in to comment.