Skip to content

Commit

Permalink
Merge branch 'v4.10.0_DAISY' into v4.10.1_DAISY
Browse files Browse the repository at this point in the history
  • Loading branch information
danielweck committed Oct 22, 2024
2 parents b581695 + 54e1d1a commit f1699a5
Show file tree
Hide file tree
Showing 92 changed files with 10,676 additions and 17,077 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/format.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
# This conditional prevents running the job on PRs from forks; won't
# have permissions to commit changes, so the job would fail if it ran.
# PRs from forks will instead rely on failing the fmt_check job in test.yml
if: github.event.pull_request.head.repo.full_name == github.repository
if: ${{ false }} # github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/semantic-pr-title.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ on:

jobs:
semantic-pr-title:
if: ${{ false }}
runs-on: ubuntu-latest
steps:
- uses: dequelabs/semantic-pr-title@v1
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,5 @@ typings/axe-core/axe-core-tests.js

# doc
doc/rule-descriptions.*.md

.history
2 changes: 1 addition & 1 deletion bower.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "axe-core",
"version": "4.10.1",
"version": "4.10.1-canary.1",
"deprecated": true,
"contributors": [
{
Expand Down
6 changes: 2 additions & 4 deletions build/configure.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,8 @@ var { encode } = require('html-entities');
var packageJSON = require('../package.json');
var doTRegex = /\{\{.+?\}\}/g;

var axeVersion = packageJSON.version.substring(
0,
packageJSON.version.lastIndexOf('.')
);
var _v = packageJSON.version.replace(/-\w+\.\w+$/, '');
var axeVersion = _v.substring(0, _v.lastIndexOf('.'));

var descriptionTableHeader =
'| Rule ID | Description | Impact | Tags | Issue Type | ACT Rules |\n| :------- | :------- | :------- | :------- | :------- | :------- |\n';
Expand Down
2 changes: 1 addition & 1 deletion build/tasks/update-help.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ module.exports = function (grunt) {
var options = this.options({
version: '1.0.0'
});
var v = options.version.split('.');
var v = options.version.replace(/-\w+\.\w+$/, '').split('.');
v.pop();
var baseUrl =
'https://dequeuniversity.com/rules/axe/' + v.join('.') + '/';
Expand Down
1 change: 1 addition & 0 deletions build/tasks/validate.js
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ function validateRule({ tags, metadata }) {
const miscTags = ['ACT', 'experimental', 'review-item', 'deprecated'];

const categories = [
'epub',
'aria',
'color',
'forms',
Expand Down
2 changes: 1 addition & 1 deletion doc/examples/qunit/Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module.exports = function (grunt) {

grunt.initConfig({
qunit: {
all: ['test/**/*.html'],
all: ['test/**/*.html', 'test/**/*__.xhtml'],
options: {
puppeteer: {
args: ['--disable-web-security', '--allow-file-access-from-files']
Expand Down
8 changes: 5 additions & 3 deletions doc/rule-descriptions.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,10 @@

These rules are disabled by default, until WCAG 2.2 is more widely adopted and required.

| Rule ID | Description | Impact | Tags | Issue Type | ACT Rules |
| :------------------------------------------------------------------------------------------------ | :-------------------------------------------------- | :------ | :--------------------------------------------- | :------------------------- | :-------- |
| [target-size](https://dequeuniversity.com/rules/axe/4.10/target-size?application=RuleDescription) | Ensure touch targets have sufficient size and space | Serious | cat.sensory-and-visual-cues, wcag22aa, wcag258 | failure, needs review | |
| Rule ID | Description | Impact | Tags | Issue Type | ACT Rules |
| :-------------------------------------------------------------------------------------------------------- | :-------------------------------------------------- | :------- | :--------------------------------------------- | :------------------------- | :-------- |
| [pagebreak-label](https://dequeuniversity.com/rules/axe/4.10/pagebreak-label?application=RuleDescription) | Ensure page markers have an accessible label | Moderate | cat.epub | failure | |
| [target-size](https://dequeuniversity.com/rules/axe/4.10/target-size?application=RuleDescription) | Ensure touch targets have sufficient size and space | Serious | cat.sensory-and-visual-cues, wcag22aa, wcag258 | failure, needs review | |

## Best Practices Rules

Expand All @@ -104,6 +105,7 @@ Rules that do not necessarily conform to WCAG success criterion but are industry
| [aria-treeitem-name](https://dequeuniversity.com/rules/axe/4.10/aria-treeitem-name?application=RuleDescription) | Ensure every ARIA treeitem node has an accessible name | Serious | cat.aria, best-practice | failure, needs review | |
| [empty-heading](https://dequeuniversity.com/rules/axe/4.10/empty-heading?application=RuleDescription) | Ensure headings have discernible text | Minor | cat.name-role-value, best-practice | failure, needs review | [ffd0e9](https://act-rules.github.io/rules/ffd0e9) |
| [empty-table-header](https://dequeuniversity.com/rules/axe/4.10/empty-table-header?application=RuleDescription) | Ensure table headers have discernible text | Minor | cat.name-role-value, best-practice | failure, needs review | |
| [epub-type-has-matching-role](https://dequeuniversity.com/rules/axe/4.10/epub-type-has-matching-role?application=RuleDescription) | Ensure the element has an ARIA role matching its epub:type | Moderate | cat.aria, best-practice | failure | |
| [frame-tested](https://dequeuniversity.com/rules/axe/4.10/frame-tested?application=RuleDescription) | Ensure <iframe> and <frame> elements contain the axe-core script | Critical | cat.structure, best-practice, review-item | failure, needs review | |
| [heading-order](https://dequeuniversity.com/rules/axe/4.10/heading-order?application=RuleDescription) | Ensure the order of headings is semantically correct | Moderate | cat.semantics, best-practice | failure, needs review | |
| [image-redundant-alt](https://dequeuniversity.com/rules/axe/4.10/image-redundant-alt?application=RuleDescription) | Ensure image alternative is not repeated as text | Minor | cat.text-alternatives, best-practice | failure | |
Expand Down
2 changes: 1 addition & 1 deletion lib/checks/aria/aria-prohibited-attr-evaluate.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export default function ariaProhibitedAttrEvaluate(
) {
const elementsAllowedAriaLabel = options?.elementsAllowedAriaLabel || [];
const { nodeName } = virtualNode.props;
const role = getRole(virtualNode, { chromium: true });
const role = getRole(virtualNode, { dpub: true, chromium: true });

const prohibitedList = listProhibitedAttrs(
virtualNode,
Expand Down
9 changes: 7 additions & 2 deletions lib/checks/aria/aria-required-children-evaluate.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ export default function ariaRequiredChildrenEvaluate(
*/
function getOwnedRoles(virtualNode, required) {
let vNode;
const parentRole = getRole(virtualNode, { dpub: true });

const ownedRoles = [];
const ownedVirtual = getOwnedVirtual(virtualNode);
while ((vNode = ownedVirtual.shift())) {
Expand All @@ -85,7 +87,8 @@ function getOwnedRoles(virtualNode, required) {
continue;
}

const role = getRole(vNode, { noPresentational: true });
const role = getRole(vNode, { noPresentational: true, dpub: true });

const globalAriaAttr = getGlobalAriaAttr(vNode);
const hasGlobalAriaOrFocusable = !!globalAriaAttr || isFocusable(vNode);

Expand All @@ -96,7 +99,9 @@ function getOwnedRoles(virtualNode, required) {
if (
(!role && !hasGlobalAriaOrFocusable) ||
(['group', 'rowgroup'].includes(role) &&
required.some(requiredRole => requiredRole === role))
required.some(requiredRole => requiredRole === role)) ||
(['list'].includes(role) &&
['doc-bibliography', 'doc-endnotes'].includes(parentRole))
) {
ownedVirtual.push(...vNode.children);
} else if (role || hasGlobalAriaOrFocusable) {
Expand Down
190 changes: 190 additions & 0 deletions lib/checks/aria/matching-aria-role-evaluate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
import { tokenList } from '../../core/utils';
import standards from '../../standards';
import { getRole } from '../../commons/aria';
import matchesSelector from '../../core/utils/element-matches';

function matchingAriaRoleEvaluate(node) {
// https://idpf.github.io/epub-guides/epub-aria-authoring/#sec-mappings
// https://www.w3.org/TR/dpub-aam-1.0/#mapping_role_table
// https://w3c.github.io/publ-cg/guides/aria-mapping.html#mapping-table
const mappings = new Map([
['abstract', 'doc-abstract'],
['acknowledgments', 'doc-acknowledgments'],
['afterword', 'doc-afterword'],
// ['answer', '??'],
// ['answers', '??'],
['appendix', 'doc-appendix'],
// ['assessment', '??'],
// ['assessments', '??'],
// ['backmatter', '??'],
// ['balloon', '??'],
// ['backlink', 'doc-backlink'], // ??
['biblioentry', 'doc-biblioentry'],
['bibliography', 'doc-bibliography'],
['biblioref', 'doc-biblioref'],
// ['bodymatter', '??'],
// ['bridgehead', '??'],
// ['case-study', '??'],
['chapter', 'doc-chapter'],
['colophon', 'doc-colophon'],
// ['concluding-sentence', '??'],
['conclusion', 'doc-conclusion'],
// ['contributors', '??'],
// ['copyright-page', '??'],
// ['cover', '??'],
// ['cover-image', 'doc-cover'], // ??
// ['covertitle', '??'],
['credit', 'doc-credit'],
['credits', 'doc-credits'],
['dedication', 'doc-dedication'],
// ['division', '??'],
['endnote', 'doc-endnote'],
['endnotes', 'doc-endnotes'],
['epigraph', 'doc-epigraph'],
['epilogue', 'doc-epilogue'],
['errata', 'doc-errata'],
// ['example', 'doc-example'],
// ['feedback', '??'],
['figure', 'figure'], // ARIA
// ['fill-in-the-blank-problem', '??'],
['footnote', 'doc-footnote'],
// ['footnotes', '??'],
['foreword', 'doc-foreword'],
// ['frontmatter', '??'],
// ['fulltitle', '??'],
// ['general-problem', '??'],
['glossary', 'doc-glossary'],
['glossdef', 'definition'], // ARIA
['glossref', 'doc-glossref'],
['glossterm', 'term'], // ARIA
// ['halftitle', '??'],
// ['halftitlepage', '??'],
// ['imprimatur', '??'],
// ['imprint', '??'],
['help', 'doc-tip'], // ??
['index', 'doc-index'],
// ['index-editor-note', '??'],
// ['index-entry', '??'],
// ['index-entry-list', '??'],
// ['index-group', '??'],
// ['index-headnotes', '??'],
// ['index-legend', '??'],
// ['index-locator', '??'],
// ['index-locator-list', '??'],
// ['index-locator-range', '??'],
// ['index-term', '??'],
// ['index-term-categories', '??'],
// ['index-term-category', '??'],
// ['index-xref-preferred', '??'],
// ['index-xref-related', '??'],
['introduction', 'doc-introduction'],
// ['keyword', '??'],
// ['keywords', '??'],
// ['label', '??'],
// ['landmarks', 'directory'], // ARIA (SKIPPED! NavDoc)
// ['learning-objective', '??'],
// ['learning-objectives', '??'],
// ['learning-outcome', '??'],
// ['learning-outcomes', '??'],
// ['learning-resource', '??'],
// ['learning-resources', '??'],
// ['learning-standard', '??'],
// ['learning-standards', '??'],
['list', 'list'], // ARIA
['list-item', 'listitem'], // ARIA
// ['loa', '??'],
// ['loi', '??'],
// ['lot', '??'],
// ['lov', '??'],
// ['match-problem', '??'],
// ['multiple-choice-problem', '??'],
['noteref', 'doc-noteref'],
['notice', 'doc-notice'],
// ['ordinal', '??'],
// ['other-credits', '??'],
['page-list', 'doc-pagelist'],
['pagebreak', 'doc-pagebreak'],
// ['panel', '??'],
// ['panel-group', '??'],
['part', 'doc-part'],
// ['practice', '??'],
// ['practices', '??'],
// ['preamble', '??'],
['preface', 'doc-preface'],
['prologue', 'doc-prologue'],
['pullquote', 'doc-pullquote'],
['qna', 'doc-qna'],
// ['question', '??'],
['referrer', 'doc-backlink'],
// ['revision-history', '??'],
// ['seriespage', '??'],
// ['sound-area', '??'],
// ['subchapter', '??'],
['subtitle', 'doc-subtitle'],
['table', 'table'],
['table-cell', 'cell'],
['table-row', 'row'],
// ['text-area', '??'],
['tip', 'doc-tip'],
// ['title', '??'],
// ['titlepage', '??'],
['toc', 'doc-toc']
// ['toc-brief', '??'],
// ['topic-sentence', '??'],
// ['true-false-problem', '??'],
// ['volume', '??'],
]);

const hasXmlEpubType = node.hasAttributeNS(
'http://www.idpf.org/2007/ops',
'type'
);
if (
hasXmlEpubType ||
node.hasAttribute('epub:type') // for unit tests that are not XML-aware due to fixture.innerHTML
) {
// abort if descendant of landmarks nav (nav with epub:type=landmarks)
if (
(hasXmlEpubType && matchesSelector(node, 'nav[*|type~="landmarks"] *')) ||
matchesSelector(node, 'nav[epub\\:type~="landmarks"] *')
) {
// console.log('BREAKPOINT');
// throw new Error('BREAKPOINT');
return true;
}

// iterate for each epub:type value
var types = tokenList(
hasXmlEpubType
? node.getAttributeNS('http://www.idpf.org/2007/ops', 'type')
: node.getAttribute('epub:type')
);
for (const type of types) {
// If there is a 1-1 mapping, check that the role is set (best practice)
if (mappings.has(type)) {
// Note: using axe’s `getRole` util returns the effective role of the element
// (either explicitly set with the role attribute or implicit)
// So this works for types mapping to core ARIA roles (eg. glossref/glossterm).
const mappedRole = mappings.get(type);
const role = getRole(node, { dpub: true });
const roleDefinition = standards.ariaRoles[mappedRole];
if (!roleDefinition || roleDefinition.deprecated) {
return true;
}
// if (mappedRole !== role) {
// console.log('BREAKPOINT: ', type, mappedRole, role);
// // throw new Error('BREAKPOINT');
// }
return mappedRole === role;
} else {
// e.g. cover, landmarks
// console.log('BREAKPOINT: ', type);
// throw new Error('BREAKPOINT');
}
}
}

return true;
}

export default matchingAriaRoleEvaluate;
11 changes: 11 additions & 0 deletions lib/checks/aria/matching-aria-role.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"id": "matching-aria-role",
"evaluate": "matching-aria-role-evaluate",
"metadata": {
"impact": "minor",
"messages": {
"pass": "Element has an ARIA role matching its epub:type",
"fail": "Element has no ARIA role matching its epub:type"
}
}
}
16 changes: 14 additions & 2 deletions lib/checks/landmarks/landmark-is-unique-after.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
function landmarkIsUniqueAfter(results) {
const uniqueLandmarks = [];

// console.log("landmarkIsUniqueAfter results: ", JSON.stringify(results, null, 4));

// filter out landmark elements that share the same role and accessible text
// so every non-unique landmark isn't reported as a failure (just the first)
return results.filter(currentResult => {
const findMatch = someResult => {
var filtered = results.filter(currentResult => {
if (!currentResult.data) {
// console.log('landmarkIsUniqueAfterlandmarkIsUniqueAfter NO DATA???!!!');
return false;
}

var findMatch = someResult => {
return (
// currentResult.data.isLandmark &&
// someResult.data.isLandmark &&
currentResult.data.role === someResult.data.role &&
currentResult.data.accessibleText === someResult.data.accessibleText
);
Expand All @@ -22,6 +31,9 @@ function landmarkIsUniqueAfter(results) {
currentResult.relatedNodes = [];
return true;
});

// console.log("landmarkIsUniqueAfter filtered: ", JSON.stringify(filtered, null, 4));
return filtered;
}

export default landmarkIsUniqueAfter;
Loading

0 comments on commit f1699a5

Please sign in to comment.