Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/checks/color/color-contrast-evaluate.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
import { memoize } from '../../core/utils';

export default function colorContrastEvaluate(node, options, virtualNode) {
// a11y-color-contrast : Wrap entire check in try/catch
try {
const {
ignoreUnicode,
Expand Down
2 changes: 2 additions & 0 deletions lib/checks/color/link-in-text-block-evaluate.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,12 @@ function getColorContrast(node, parentBlock) {
nodeColor = getForegroundColor(node);
parentColor = getForegroundColor(parentBlock);

// a11y-critical : If nodeColor is missing, set to transparent black
if (!nodeColor) {
nodeColor = new axe.commons.color.Color(0, 0, 0, 0);
}

// a11y-critical : If parentColor is missing, set to transparent black
if (!parentColor) {
parentColor = new axe.commons.color.Color(0, 0, 0, 0);
}
Expand Down
55 changes: 32 additions & 23 deletions lib/checks/label/label-content-name-mismatch-evaluate.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
// eslint-disable-next-line no-restricted-imports
import stem from 'wink-porter2-stemmer';

// a11y-rule-label-content-name-mismatch: Similarity threshold for text comparison
const threshold = 0.75;

function cleanText(str) {
Expand All @@ -18,6 +19,7 @@ function cleanText(str) {
.trim();
}

// a11y-rule-label-content-name-mismatch: Replace special characters with text equivalents
function replaceSynonyms(text) {
const synonymMap = {
'&': 'and'
Expand All @@ -28,6 +30,7 @@ function replaceSynonyms(text) {
.join(' ');
}

// a11y-rule-label-content-name-mismatch: Normalize and stem text for comparison
function stringStemmer(str) {
return replaceSynonyms(str)
.split(/[^\p{L}\p{N}]+/u)
Expand All @@ -43,27 +46,8 @@ function stringStemmer(str) {
.join(' ');
}

/**
* Check if a given text exists in another
*
* @param {String} compare given text to check
* @param {String} compareWith text against which to be compared
* @returns {Boolean}
*/
function isStringContained(compare, compareWith) {
compare = stringStemmer(compare);
compareWith = stringStemmer(compareWith);

const curatedCompareWith = curateString(compareWith);
const curatedCompare = curateString(compare);
if (!curatedCompareWith || !curatedCompare) {
return false;
}
const res = curatedCompareWith.includes(curatedCompare);
if (res) {
return res;
}

// a11y-rule-label-content-name-mismatch: Calculate cosine similarity between strings
function isCosineSimilar(compare, compareWith) {
const tokensA = compare.split(/[^\p{L}\p{N}]+/u);
const tokensB = compareWith.split(/[^\p{L}\p{N}]+/u);
const freqA = {},
Expand Down Expand Up @@ -92,6 +76,31 @@ function isStringContained(compare, compareWith) {
return similarity >= threshold; // comparision with threshold as 75%
}

/**
*
* @param {String} compare given text to check
* @param {String} compareWith text against which to be compared
* @returns {Boolean}
*/
function isStringContained(compare, compareWith) {
// a11y-rule-label-content-name-mismatch: Apply stemming normalization
compare = stringStemmer(compare);
// a11y-rule-label-content-name-mismatch: Apply stemming normalization
compareWith = stringStemmer(compareWith);

const curatedCompareWith = curateString(compareWith);
const curatedCompare = curateString(compare);
if (!curatedCompareWith || !curatedCompare) {
return false;
}
// a11y-rule-label-content-name-mismatch: Fallback to cosine similarity comparison
const res = curatedCompareWith.includes(curatedCompare);
if (res) {
return res;
}
return isCosineSimilar(curatedCompare, curatedCompareWith);
}

/**
* Curate given text, by removing emoji's, punctuations, unicode and trim whitespace.
*
Expand All @@ -103,7 +112,7 @@ function curateString(str) {
emoji: true,
nonBmp: true,
punctuations: true,
whitespace: true
whitespace: true // a11y-rule-label-content-name-mismatch : To Skip for whitespace
});
return sanitize(noUnicodeStr);
}
Expand All @@ -119,7 +128,7 @@ function labelContentNameMismatchEvaluate(node, options, virtualNode) {
ignoreIconLigature: true,
pixelThreshold,
occurrenceThreshold,
ignoreNativeTextAlternative: true // To Skip for nativeTextAlternative
ignoreNativeTextAlternative: true // a11y-rule-label-content-name-mismatch : To Skip for nativeTextAlternative
})
).toLowerCase();

Expand Down
7 changes: 4 additions & 3 deletions lib/commons/color/get-foreground-color.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export default function getForegroundColor(node, _, bgColor, options = {}) {
}

fgColors = fgColors.concat(color);
// If any color in the array is fully opaque, break
// a11y-critical : If any color in the array is fully opaque, break
if (Array.isArray(color)) {
if (color.some(c => c && c.alpha === 1)) {
break;
Expand All @@ -49,6 +49,7 @@ export default function getForegroundColor(node, _, bgColor, options = {}) {
}
}

// a11y-critical : If any color in the array is fully opaque, break
if (!fgColors.length) {
// Could not determine foreground color
incompleteData.set('fgColor', 'No foreground color found');
Expand All @@ -63,14 +64,14 @@ export default function getForegroundColor(node, _, bgColor, options = {}) {
bgColor ??= getBackgroundColor(node, []);

if (bgColor === null) {
// Return the foreground color as-is if background color is not found
// a11y-critical : the foreground color as-is if background color is not found
return fgColor;
}

const stackingContexts = getStackingContext(node);
const context = findNodeInContexts(stackingContexts, node);

// If context is not found, fallback to blending with bgColor only
// a11y-critical : If context is not found, fallback to blending with bgColor only
if (!context) {
return flattenColors(fgColor, bgColor);
}
Expand Down
8 changes: 4 additions & 4 deletions lib/commons/dom/create-grid.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export default function createGrid(
) {
// Prevent multiple calls per run
if (cache.get('gridCreated') && !parentVNode) {
// a11y-engine-domforge change
// a11y-domforge : returning data from cache if available
if (cache.get('gridSize')) {
return cache.get('gridSize');
}
Expand Down Expand Up @@ -115,7 +115,7 @@ export default function createGrid(
node = treeWalker.nextNode();
}

// a11y-engine-domforge change
// a11y-domforge : returning data from cache if available
if (cache.get('gridSize')) {
return cache.get('gridSize');
}
Expand Down Expand Up @@ -439,7 +439,7 @@ class Grid {
* @returns {number}
*/
toGridIndex(num) {
// a11y-engine-domforge change
// a11y-domforge : returning data from cache if available
if (cache.get('gridSize')) {
return Math.floor(num / cache.get('gridSize'));
}
Expand All @@ -456,7 +456,7 @@ class Grid {
const rowIndex = this.toGridIndex(y);
const colIndex = this.toGridIndex(x);

// a11y-engine-domforge change
// a11y-domforge : special handling for resize-2x-zoom rule
if (cache.get('ruleId') === 'resize-2x-zoom') {
if (!isPointInRect({ y: rowIndex, x: colIndex }, this.boundaries)) {
return [];
Expand Down
4 changes: 2 additions & 2 deletions lib/commons/dom/get-element-stack.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ import getNodeGrid from './get-node-grid';
* @return {Node[]}
*/

// Additional props isCoordsPassed, x, y for a11y-engine-domforge
// a11y-domforge : Additional props isCoordsPassed, x, y
function getElementStack(node, isCoordsPassed = false, x = null, y = null) {
const grid = getNodeGrid(node);
if (!grid) {
return [];
}
const rect = getNodeFromTree(node).boundingClientRect;

// Additional props isCoordsPassed, x, y for a11y-engine-domforge
// a11y-domforge : Additional props isCoordsPassed, x, y
return getRectStack(grid, rect, false, isCoordsPassed, x, y);
}

Expand Down
6 changes: 4 additions & 2 deletions lib/commons/dom/get-overflow-hidden-ancestors.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const getOverflowHiddenAncestors = memoize(

const overflow = vNode.getComputedStylePropertyValue('overflow');

// a11y-engine-domforge change
// a11y-domforge : special handling for resize-2x-zoom rule
if (cache.get('ruleId') && cache.get('ruleId') === 'resize-2x-zoom') {
if (
overflow.includes('hidden') ||
Expand All @@ -28,7 +28,9 @@ const getOverflowHiddenAncestors = memoize(
) {
ancestors.push(vNode);
}
} else if (
}
// a11y-domforge : special handling for reflow-4x-zoom-scroll and color-contrast rules
else if (
cache.get('ruleId') &&
(cache.get('ruleId') === 'reflow-4x-zoom-scroll' ||
cache.get('ruleId') === 'color-contrast') &&
Expand Down
4 changes: 2 additions & 2 deletions lib/commons/dom/get-rect-stack.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import visuallySort from './visually-sort';
import { getRectCenter } from '../math';

// Additional props isCoordsPassed, x, y for a11y-engine-domforge
// a11y-domforge : Additional props isCoordsPassed, x, y
export function getRectStack(
grid,
rect,
Expand All @@ -16,7 +16,7 @@ export function getRectStack(
let floorX = Math.floor(center.x);
let floorY = Math.floor(center.y);

// a11y-engine-domforge change
// a11y-domforge : Use passed coordinates if provided
if (isCoordsPassed) {
floorX = Math.floor(x);
floorY = Math.floor(y);
Expand Down
2 changes: 1 addition & 1 deletion lib/commons/dom/get-visible-child-text-rect.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const getVisibleChildTextRect = memoize(
clientRects.push(...filterHiddenRects(contentRects, overflowHiddenNodes));
});

// a11y-engine-domforge change
// a11y-domforge : If no visible text rects found, return empty array
if (clientRects.length <= 0) {
return [];
}
Expand Down
5 changes: 4 additions & 1 deletion lib/commons/dom/get-visible-child-text-rects.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import cache from '../../core/base/cache';
* @instance
* @param {Element} node
*/
// a11y-domforge : added options to control certain behaviors
const getVisibleChildTextRects = (node, options = {}) => {
const {
checkTextRectOutsideNodeBoundingRect = false,
Expand All @@ -36,6 +37,7 @@ const getVisibleChildTextRects = (node, options = {}) => {
nodeRect,
checkTextRectOutsideNodeBoundingRect
) &&
// a11y-domforge : early return for certain rules
(!cache.get('ruleId') ||
cache.get('ruleId') === 'reflow-4x-zoom-scroll' ||
cache.get('ruleId') === 'color-contrast')
Expand All @@ -51,7 +53,7 @@ const getVisibleChildTextRects = (node, options = {}) => {
);
});

// a11y-engine-domforge change
// a11y-domforge : handle case when no visible text rects found
if (
clientRects.length <= 0 &&
((cache.get('ruleId') && cache.get('ruleId') === 'resize-2x-zoom') ||
Expand Down Expand Up @@ -91,6 +93,7 @@ function getContentRects(node) {
* when determining the rect stack we will also use the midpoint
* of the text rect to determine out of bounds
*/
// a11y-domforge : added checkTextRectOutsideNodeBoundingRect option
function isOutsideNodeBounds(
rects,
nodeRect,
Expand Down
1 change: 1 addition & 0 deletions lib/commons/dom/is-in-text-block.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import getRoleType from '../aria/get-role-type';

function walkDomNode(node, functor) {
if (functor(node.actualNode) !== false) {
// a11y-critical : avoid processing STYLE elements
if (
functor(node.actualNode) !== false &&
node.actualNode.nodeName !== 'STYLE'
Expand Down
1 change: 1 addition & 0 deletions lib/commons/text/native-text-alternative.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import nativeTextMethods from './native-text-methods';
* @return {String} Accessible text
*/
export default function nativeTextAlternative(virtualNode, context = {}) {
// a11y-rule-label-content-name-mismatch : Skip native text alternative if specified
if (context.ignoreNativeTextAlternative) {
return '';
}
Expand Down
2 changes: 2 additions & 0 deletions lib/commons/text/remove-unicode.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { emojiRegexText } from '../../core/imports';
* @returns {String}
*/
function removeUnicode(str, options) {
// a11y-rule-label-content-name-mismatch : remove whitespace characters
const { emoji, nonBmp, punctuations, whitespace } = options;

if (emoji) {
Expand All @@ -34,6 +35,7 @@ function removeUnicode(str, options) {
if (punctuations) {
str = str.replace(getPunctuationRegExp(), '');
}
// a11y-rule-label-content-name-mismatch : remove whitespace characters
if (whitespace) {
str = str.replace(/\s+/g, '');
}
Expand Down
2 changes: 2 additions & 0 deletions lib/commons/text/subtree-text.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ function subtreeText(virtualNode, context = {}) {

const phrasingElements = getElementsByContentType('phrasing').concat(['#text']);

// a11y-core : Skip inline elements with overflow hidden
function skipByInlineOverflow(virtualNode) {
const computedStyleOverflow = virtualNode._cache.computedStyle_overflow;
if (computedStyleOverflow && computedStyleOverflow === 'hidden') {
Expand All @@ -68,6 +69,7 @@ function skipByInlineOverflow(virtualNode) {
}

function appendAccessibleText(contentText, virtualNode, context) {
// a11y-core : Skip inline elements with overflow hidden when specified in context
if (
context.ignoreNativeTextAlternative &&
skipByInlineOverflow(virtualNode)
Expand Down
1 change: 1 addition & 0 deletions lib/core/base/rule.js
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ Rule.prototype.run = function run(context, options = {}, resolve, reject) {
try {
// Matches throws an error when it lacks support for document methods
nodes = this.gatherAndMatchNodes(context, options);
// a11y-critical : Cache the number of nodes gathered for this rule
cache.set(this.id, nodes.length);
} catch (error) {
reject(error);
Expand Down
2 changes: 1 addition & 1 deletion lib/core/public/load.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ function runCommand(data, keepalive, callback) {
// Serialize all DqElements
results = nodeSerializer.mapRawResults(results);

//a11y-engine iframe rules error merging logic
// a11y-critical : iframe rules error merging logic
const errors = a11yEngine.getErrors();
if (Object.keys(errors).length !== 0) {
if (
Expand Down
2 changes: 1 addition & 1 deletion lib/core/public/run-rules.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export default function runRules(context, options, resolve, reject) {

// after should only run once, so ensure we are in the top level window
if (context.initiator) {
// Return a11y-engine errors when at top level window
// a11y-critical : Return a11y-engine errors when at top level window
if (
results.length > 0 &&
results[results.length - 1]?.a11yEngineErrors
Expand Down
1 change: 1 addition & 0 deletions lib/core/utils/aggregate-checks.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ function aggregateChecks(nodeResOriginal) {
nodeResult[type].forEach(check => impacts.push(check.impact));
});

// a11y-critical : Removed define impact for failed nodes
nodeResult.impact = aggregate(constants.impact, impacts);

// Delete the old result and priority properties
Expand Down
1 change: 1 addition & 0 deletions lib/core/utils/check-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ function checkHelper(checkResult, options, resolve, reject) {
data(data) {
checkResult.data = data;
},
// a11y-critical : Added getCheckData method
getCheckData() {
return checkResult.data;
},
Expand Down
Loading
Loading