diff --git a/build/tasks/esbuild.js b/build/tasks/esbuild.js index 30dbeb4ef..ad074a52b 100644 --- a/build/tasks/esbuild.js +++ b/build/tasks/esbuild.js @@ -23,6 +23,7 @@ module.exports = function (grunt) { entryPoints: [entry], outfile: path.join(dest, name), minify: false, + format: 'esm', bundle: true }) .then(done) diff --git a/lib/commons/dom/create-grid.js b/lib/commons/dom/create-grid.js index 612e885bb..7af1b0016 100644 --- a/lib/commons/dom/create-grid.js +++ b/lib/commons/dom/create-grid.js @@ -27,6 +27,10 @@ export default function createGrid( ) { // Prevent multiple calls per run if (cache.get('gridCreated') && !parentVNode) { + // a11y-engine-domforge change + if (cache.get('gridSize')) { + return cache.get('gridSize'); + } return constants.gridSize; } cache.set('gridCreated', true); @@ -110,6 +114,11 @@ export default function createGrid( node = treeWalker.nextNode(); } + + // a11y-engine-domforge change + if (cache.get('gridSize')) { + return cache.get('gridSize'); + } return constants.gridSize; } @@ -430,6 +439,10 @@ class Grid { * @returns {number} */ toGridIndex(num) { + // a11y-engine-domforge change + if (cache.get('gridSize')) { + return Math.floor(num / cache.get('gridSize')); + } return Math.floor(num / constants.gridSize); } @@ -442,10 +455,18 @@ class Grid { assert(this.boundaries, 'Grid does not have cells added'); const rowIndex = this.toGridIndex(y); const colIndex = this.toGridIndex(x); - assert( - isPointInRect({ y: rowIndex, x: colIndex }, this.boundaries), - 'Element midpoint exceeds the grid bounds' - ); + + // a11y-engine-domforge change + if (cache.get('ruleId') === 'resize-2x-zoom') { + if (!isPointInRect({ y: rowIndex, x: colIndex }, this.boundaries)) { + return []; + } + } else { + assert( + isPointInRect({ y: rowIndex, x: colIndex }, this.boundaries), + 'Element midpoint exceeds the grid bounds' + ); + } const row = this.cells[rowIndex - this.cells._negativeIndex] ?? []; return row[colIndex - row._negativeIndex] ?? []; } diff --git a/lib/commons/dom/get-element-stack.js b/lib/commons/dom/get-element-stack.js index 132a20f2b..510b7a811 100644 --- a/lib/commons/dom/get-element-stack.js +++ b/lib/commons/dom/get-element-stack.js @@ -9,7 +9,9 @@ import createGrid from './create-grid'; * @param {Node} node * @return {Node[]} */ -function getElementStack(node) { + +// Additional props isCoordsPassed, x, y for a11y-engine-domforge +function getElementStack(node, isCoordsPassed = false, x = null, y = null) { createGrid(); const vNode = getNodeFromTree(node); @@ -19,7 +21,15 @@ function getElementStack(node) { return []; } - return getRectStack(grid, vNode.boundingClientRect); + // Additional props isCoordsPassed, x, y for a11y-engine-domforge + return getRectStack( + grid, + vNode.boundingClientRect, + false, + isCoordsPassed, + x, + y + ); } export default getElementStack; diff --git a/lib/commons/dom/get-overflow-hidden-ancestors.js b/lib/commons/dom/get-overflow-hidden-ancestors.js index 01ab696e2..79ca04cee 100644 --- a/lib/commons/dom/get-overflow-hidden-ancestors.js +++ b/lib/commons/dom/get-overflow-hidden-ancestors.js @@ -1,3 +1,4 @@ +import cache from '../../core/base/cache'; import memoize from '../../core/utils/memoize'; /** @@ -17,8 +18,19 @@ const getOverflowHiddenAncestors = memoize( const overflow = vNode.getComputedStylePropertyValue('overflow'); - if (overflow === 'hidden') { - ancestors.push(vNode); + // a11y-engine-domforge change + if (cache.get('ruleId') && cache.get('ruleId') === 'resize-2x-zoom') { + if ( + overflow.includes('hidden') || + overflow.includes('clip') || + overflow.includes('scroll') + ) { + ancestors.push(vNode); + } + } else { + if (overflow.includes('hidden')) { + ancestors.push(vNode); + } } return ancestors.concat(getOverflowHiddenAncestors(vNode.parent)); diff --git a/lib/commons/dom/get-rect-stack.js b/lib/commons/dom/get-rect-stack.js index 4c51bf3b3..36489a504 100644 --- a/lib/commons/dom/get-rect-stack.js +++ b/lib/commons/dom/get-rect-stack.js @@ -1,12 +1,27 @@ import visuallySort from './visually-sort'; import { getRectCenter } from '../math'; -export function getRectStack(grid, rect, recursed = false) { +// Additional props isCoordsPassed, x, y for a11y-engine-domforge +export function getRectStack( + grid, + rect, + recursed = false, + isCoordsPassed = false, + x = null, + y = null +) { const center = getRectCenter(rect); const gridCell = grid.getCellFromPoint(center) || []; - const floorX = Math.floor(center.x); - const floorY = Math.floor(center.y); + let floorX = Math.floor(center.x); + let floorY = Math.floor(center.y); + + // a11y-engine-domforge change + if (isCoordsPassed) { + floorX = Math.floor(x); + floorY = Math.floor(y); + } + let stack = gridCell.filter(gridCellNode => { return gridCellNode.clientRects.some(clientRect => { const rectX = clientRect.left; diff --git a/lib/commons/dom/get-visible-child-text-rects.js b/lib/commons/dom/get-visible-child-text-rects.js index 02611798e..2cd01773a 100644 --- a/lib/commons/dom/get-visible-child-text-rects.js +++ b/lib/commons/dom/get-visible-child-text-rects.js @@ -1,7 +1,8 @@ import { getNodeFromTree, memoize } from '../../core/utils'; import { sanitize } from '../text'; -import { getRectCenter, isPointInRect, getIntersectionRect } from '../math'; +import { getIntersectionRect, getRectCenter, isPointInRect } from '../math'; import getOverflowHiddenAncestors from './get-overflow-hidden-ancestors'; +import cache from '../../core/base/cache'; /** * Get the visible text client rects of a node. @@ -23,13 +24,21 @@ const getVisibleChildTextRects = memoize( } const contentRects = getContentRects(textNode); - if (isOutsideNodeBounds(contentRects, nodeRect)) { + if (isOutsideNodeBounds(contentRects, nodeRect) && !cache.get('ruleId')) { return; } clientRects.push(...filterHiddenRects(contentRects, overflowHiddenNodes)); }); + // a11y-engine-domforge change + if ( + clientRects.length <= 0 && + cache.get('ruleId') && + cache.get('ruleId') === 'resize-2x-zoom' + ) { + return []; + } /** * if all text rects are larger than the bounds of the node, * or goes outside of the bounds of the node, we need to use diff --git a/lib/core/public/load.js b/lib/core/public/load.js index e80d3d8f6..0d7e0caf4 100644 --- a/lib/core/public/load.js +++ b/lib/core/public/load.js @@ -42,7 +42,10 @@ function runCommand(data, keepalive, callback) { //a11y-engine iframe rules error merging logic const errors = a11yEngine.getErrors(); if (Object.keys(errors).length !== 0) { - if (results[results.length - 1].a11yEngineErrors) { + if ( + results.length > 0 && + results[results.length - 1]?.a11yEngineErrors + ) { const error = results.pop(); delete error.a11yEngineErrors; const mergedErrors = mergeErrors(error, errors); diff --git a/lib/core/public/run-rules.js b/lib/core/public/run-rules.js index 8e04c13dc..9193d4373 100644 --- a/lib/core/public/run-rules.js +++ b/lib/core/public/run-rules.js @@ -67,7 +67,10 @@ 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 - if (results[results.length - 1].a11yEngineErrors) { + if ( + results.length > 0 && + results[results.length - 1]?.a11yEngineErrors + ) { const error = results.pop(); delete error.a11yEngineErrors; a11yEngine.mergeErrors(error); diff --git a/lib/core/utils/merge-results.js b/lib/core/utils/merge-results.js index 0e6277132..79aa935b1 100644 --- a/lib/core/utils/merge-results.js +++ b/lib/core/utils/merge-results.js @@ -86,7 +86,7 @@ function mergeResults(frameResults, options) { const frameSpec = getFrameSpec(frameResult); // Extract existing errors and merge with new ones - if (results[results.length - 1].a11yEngineErrors) { + if (results.length > 0 && results[results.length - 1]?.a11yEngineErrors) { const error = results.pop(); delete error.a11yEngineErrors; mergedErrors = mergeErrors(mergedErrors, error, frameSpec);