-
Notifications
You must be signed in to change notification settings - Fork 743
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: Solve several accessible-name issues #1163
Merged
Merged
Changes from 25 commits
Commits
Show all changes
29 commits
Select commit
Hold shift + click to select a range
8c80f14
chore(WIP): rewrite accessibleText
WilcoFiers 82e5c74
Merge branch 'develop' into a11y-name
WilcoFiers 9d2451e
chore: More refactoring for accname
WilcoFiers 305c864
chore(WIP): More improvements to accessibleName
WilcoFiers 8501f34
feat: Reimplement accessible name computation
WilcoFiers dec7220
chore: All accessible name tests passing
WilcoFiers abb0673
chore(accName): All tests passing
WilcoFiers 4de5489
chore: Add tests
WilcoFiers a98448b
chore: Test form-control-value
WilcoFiers e264958
chore: Merge develop
WilcoFiers 1aded4a
chore: Refactor and add docs to accessible-text
WilcoFiers 6e67b52
chore: Add tests for namedFromContents
WilcoFiers 2a5020e
chore: Refactor subtreeText method
WilcoFiers 6ff002b
chore: Refactor native accessible text methods
WilcoFiers 4c6c351
chore: Coverage for text.labelText
WilcoFiers 6917ec9
Merge branch 'develop' into a11y-name
WilcoFiers 73ded40
Merge branch 'develop' into a11y-name
jeeyyy 2244ed2
fix: update to axe.commons.matches usage
jeeyyy 6c35b51
Merge branch 'develop' into a11y-name
jeeyyy 9bddd36
test: fix nativeTextboxValue tests
jeeyyy 3f9a969
test: fix failing tests
jeeyyy 1227102
chore: merge from develop
jeeyyy dfa1bd7
fix: compute includeHidden as a part of accessibleName fn
jeeyyy d0f45e7
fix: do not mutate context in accessibleText
jeeyyy c3a1bdc
Merge branch 'develop' into a11y-name
jeeyyy c4f7b2b
Merge branch 'develop' into a11y-name
WilcoFiers 516952c
chore: Refactor a11yText method for readability
WilcoFiers 8fc69a3
chore: Update a11yText test results
WilcoFiers 994155b
Merge branch 'develop' into a11y-name
WilcoFiers File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,7 @@ | ||
var label = axe.commons.dom.findUpVirtual(virtualNode, 'label'); | ||
const { dom, text } = axe.commons; | ||
|
||
var label = dom.findUpVirtual(virtualNode, 'label'); | ||
if (label) { | ||
return !!axe.commons.text.accessibleTextVirtual(label); | ||
return !!text.accessibleText(label, { inControlContext: true }); | ||
} | ||
return false; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
var label = node.getAttribute('aria-label'); | ||
return !!(label ? axe.commons.text.sanitize(label).trim() : ''); | ||
const { text, aria } = axe.commons; | ||
return !!text.sanitize(aria.arialabelText(node)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,2 @@ | ||
var getIdRefs = axe.commons.dom.idrefs; | ||
|
||
return getIdRefs(node, 'aria-labelledby').some(function(elm) { | ||
return elm && axe.commons.text.accessibleText(elm, true); | ||
}); | ||
const { text, aria } = axe.commons; | ||
return !!text.sanitize(aria.arialabelledbyText(node)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
var title = node.getAttribute('title'); | ||
return !!(title ? axe.commons.text.sanitize(title).trim() : ''); | ||
const { text } = axe.commons; | ||
return !!text.sanitize(text.titleText(node)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
/* global aria */ | ||
|
||
/** | ||
* Get the text value of aria-label, if any | ||
* | ||
* @param {VirtualNode|Element} element | ||
* @return {string} ARIA label | ||
*/ | ||
aria.arialabelText = function arialabelText(node) { | ||
node = node.actualNode || node; | ||
if (node.nodeType !== 1) { | ||
return ''; | ||
} | ||
return node.getAttribute('aria-label') || ''; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
/* global aria, dom, text */ | ||
|
||
/** | ||
* Get the accessible name based on aria-labelledby | ||
* | ||
* @param {VirtualNode} element | ||
* @param {Object} context | ||
* @property {Bool} inLabelledByContext Whether or not the lookup is part of aria-labelledby reference | ||
* @property {Bool} inControlContext Whether or not the lookup is part of a native label reference | ||
* @property {Element} startNode First node in accessible name computation | ||
* @property {Bool} debug Enable logging for formControlValue | ||
* @return {string} Cancatinated text value for referenced elements | ||
*/ | ||
aria.arialabelledbyText = function arialabelledbyText(node, context = {}) { | ||
node = node.actualNode || node; | ||
/** | ||
* Note: The there are significant difference in how many "leads" browsers follow. | ||
* - Firefox stops after the first IDREF, so it | ||
* doesn't follow aria-labelledby after a for:>ID ref. | ||
* - Chrome seems to just keep iterating no matter how many levels deep. | ||
* - AccName-AAM 1.1 suggests going one level deep, but to treat | ||
* each ref type separately. | ||
* | ||
* Axe-core's implementation behaves most closely like Firefox as it seems | ||
* to be the most common deniminator. Main difference is that Firefox | ||
* includes the value of form controls in addition to aria-label(s), | ||
* something no other browser seems to do. Axe doesn't do that. | ||
*/ | ||
if ( | ||
node.nodeType !== 1 || | ||
context.inLabelledByContext || | ||
context.inControlContext | ||
) { | ||
return ''; | ||
} | ||
|
||
const refs = dom.idrefs(node, 'aria-labelledby').filter(elm => elm); | ||
return refs.reduce((accessibleName, elm) => { | ||
const accessibleNameAdd = text.accessibleText(elm, { | ||
// Prevent the infinite reference loop: | ||
inLabelledByContext: true, | ||
startNode: context.startNode || node, | ||
...context | ||
}); | ||
|
||
if (!accessibleName) { | ||
return accessibleNameAdd; | ||
} else { | ||
return `${accessibleName} ${accessibleNameAdd}`; | ||
} | ||
}, ''); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/* global aria, dom */ | ||
|
||
/** | ||
* Get an element's owned elements | ||
* | ||
* @param {VirtualNode} element | ||
* @return {VirtualNode[]} Owned elements | ||
*/ | ||
aria.getOwnedVirtual = function getOwned({ actualNode, children }) { | ||
jeeyyy marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (!actualNode || !children) { | ||
throw new Error('getOwnedVirtual requires a virtual node'); | ||
} | ||
// TODO: Check that the element has a role | ||
// TODO: Descend into children with role=presentation|none | ||
// TODO: Exclude descendents owned by other elements | ||
|
||
return dom.idrefs(actualNode, 'aria-owns').reduce((ownedElms, element) => { | ||
if (element) { | ||
const virtualNode = axe.utils.getNodeFromTree(axe._tree[0], element); | ||
ownedElms.push(virtualNode); | ||
} | ||
return ownedElms; | ||
}, children); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/* global aria */ | ||
|
||
/** | ||
* Check if an element is named from contents | ||
* | ||
* @param {Node|VirtualNode} element | ||
* @param {Object} options | ||
* @property {Bool} strict Whether or not to follow the spects strictly | ||
* @return {Bool} | ||
*/ | ||
aria.namedFromContents = function namedFromContents(node, { strict } = {}) { | ||
node = node.actualNode || node; | ||
if (node.nodeType !== 1) { | ||
return false; | ||
} | ||
|
||
const role = aria.getRole(node); | ||
const roleDef = aria.lookupTable.role[role]; | ||
|
||
if ( | ||
(roleDef && roleDef.nameFrom.includes('contents')) || | ||
// TODO: This is a workaround for axe-core's over-assertive implicitRole computation | ||
// once we fix that, this extra noImplicit check can be removed. | ||
node.nodeName.toUpperCase() === 'TABLE' | ||
) { | ||
return true; | ||
} | ||
|
||
/** | ||
* Note: Strictly speaking if the role is null, presentation, or none, the element | ||
* isn't named from contents. Axe-core often needs to know if an element | ||
* has content anyway, so we're allowing it here. | ||
* Use { strict: true } to disable this behavior. | ||
*/ | ||
if (strict) { | ||
return false; | ||
} | ||
return !roleDef || ['presentation', 'none'].includes(role); | ||
}; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: describe the way this works as "implementing the common denominator"