diff --git a/lib/checks/color/color-contrast-enhanced.json b/lib/checks/color/color-contrast-enhanced.json index b09a326907..f641840718 100644 --- a/lib/checks/color/color-contrast-enhanced.json +++ b/lib/checks/color/color-contrast-enhanced.json @@ -44,7 +44,8 @@ "equalRatio": "Element has a 1:1 contrast ratio with the background", "shortTextContent": "Element content is too short to determine if it is actual text content", "nonBmp": "Element content contains only non-text characters", - "pseudoContent": "Element's background color could not be determined due to a pseudo element" + "pseudoContent": "Element's background color could not be determined due to a pseudo element", + "colorParse": "Could not parse color string ${data.colorParse}" } } } diff --git a/lib/checks/color/color-contrast-evaluate.js b/lib/checks/color/color-contrast-evaluate.js index 8916bd0971..2319f253c6 100644 --- a/lib/checks/color/color-contrast-evaluate.js +++ b/lib/checks/color/color-contrast-evaluate.js @@ -122,12 +122,24 @@ export default function colorContrastEvaluate(node, options, virtualNode) { // if fgColor or bgColor are missing, get more information. let missing; + let colorParse; + if (bgColor === null) { - missing = incompleteData.get('bgColor'); + if (incompleteData.get('colorParse')) { + missing = 'colorParse'; + colorParse = incompleteData.get('colorParse'); + } else { + missing = incompleteData.get('bgColor'); + } } else if (!isValid) { missing = contrastContributor; } + if (fgColor === null && incompleteData.get('colorParse')) { + missing = 'colorParse'; + colorParse = incompleteData.get('colorParse'); + } + const equalRatio = truncatedResult === 1; const shortTextContent = visibleText.length === 1; if (equalRatio) { @@ -146,7 +158,8 @@ export default function colorContrastEvaluate(node, options, virtualNode) { fontWeight: bold ? 'bold' : 'normal', messageKey: missing, expectedContrastRatio: expected + ':1', - shadowColor: shadowColor ? shadowColor.toHexString() : undefined + shadowColor: shadowColor ? shadowColor.toHexString() : undefined, + colorParse: colorParse }); // We don't know, so we'll put it into Can't Tell diff --git a/lib/checks/color/color-contrast.json b/lib/checks/color/color-contrast.json index 135eeae4e7..6e309208dc 100644 --- a/lib/checks/color/color-contrast.json +++ b/lib/checks/color/color-contrast.json @@ -46,7 +46,8 @@ "equalRatio": "Element has a 1:1 contrast ratio with the background", "shortTextContent": "Element content is too short to determine if it is actual text content", "nonBmp": "Element content contains only non-text characters", - "pseudoContent": "Element's background color could not be determined due to a pseudo element" + "pseudoContent": "Element's background color could not be determined due to a pseudo element", + "colorParse": "Could not parse color string ${data.colorParse}" } } } diff --git a/lib/commons/color/color.js b/lib/commons/color/color.js index ebfa4082e4..de8e6ea625 100644 --- a/lib/commons/color/color.js +++ b/lib/commons/color/color.js @@ -1,4 +1,5 @@ import { Colorjs, ArrayFrom } from '../../core/imports'; +import incompleteData from './incomplete-data'; const hexRegex = /^#[0-9a-f]{3,8}$/i; const hslRegex = /hsl\(\s*([-\d.]+)(rad|turn)/; @@ -172,6 +173,7 @@ export default class Color { // color.alpha is a Number object so convert it to a number this.alpha = +color.alpha; } catch { + incompleteData.set('colorParse', colorString); throw new Error(`Unable to parse color "${colorString}"`); } diff --git a/lib/commons/color/get-background-color.js b/lib/commons/color/get-background-color.js index 69eb1352a6..136b227505 100644 --- a/lib/commons/color/get-background-color.js +++ b/lib/commons/color/get-background-color.js @@ -75,9 +75,17 @@ function _getBackgroundColor(elm, bgElms, shadowOutlineEmMax) { } // Get the background color - const bgColor = getOwnBackgroundColor(bgElmStyle); - if (bgColor.alpha === 0) { - continue; + let bgColor; + try { + bgColor = getOwnBackgroundColor(bgElmStyle); + if (bgColor.alpha === 0) { + continue; + } + } catch (error) { + if (error && incompleteData.get('colorParse')) { + return null; + } + throw error; } // abort if a node is partially obscured and obscuring element has a background diff --git a/lib/commons/color/get-foreground-color.js b/lib/commons/color/get-foreground-color.js index dca800421e..bc9864c7dd 100644 --- a/lib/commons/color/get-foreground-color.js +++ b/lib/commons/color/get-foreground-color.js @@ -32,17 +32,24 @@ export default function getForegroundColor(node, _, bgColor, options = {}) { ]; let fgColors = []; - for (const colorFn of colorStack) { - const color = colorFn(); - if (!color) { - continue; - } + try { + for (const colorFn of colorStack) { + const color = colorFn(); + if (!color) { + continue; + } - fgColors = fgColors.concat(color); + fgColors = fgColors.concat(color); - if (color.alpha === 1) { - break; + if (color.alpha === 1) { + break; + } + } + } catch (error) { + if (error && incompleteData.get('colorParse')) { + return null; } + throw error; } const fgColor = fgColors.reduce((source, backdrop) => { diff --git a/locales/_template.json b/locales/_template.json index f6239a1f92..d1993f0d82 100644 --- a/locales/_template.json +++ b/locales/_template.json @@ -628,7 +628,8 @@ "equalRatio": "Element has a 1:1 contrast ratio with the background", "shortTextContent": "Element content is too short to determine if it is actual text content", "nonBmp": "Element content contains only non-text characters", - "pseudoContent": "Element's background color could not be determined due to a pseudo element" + "pseudoContent": "Element's background color could not be determined due to a pseudo element", + "colorParse": "Could not parse color string ${data.colorParse}" } }, "color-contrast": { @@ -655,7 +656,8 @@ "equalRatio": "Element has a 1:1 contrast ratio with the background", "shortTextContent": "Element content is too short to determine if it is actual text content", "nonBmp": "Element content contains only non-text characters", - "pseudoContent": "Element's background color could not be determined due to a pseudo element" + "pseudoContent": "Element's background color could not be determined due to a pseudo element", + "colorParse": "Could not parse color string ${data.colorParse}" } }, "link-in-text-block-style": { diff --git a/test/checks/color/color-contrast.js b/test/checks/color/color-contrast.js index 312674d66c..c7e2dd6bf5 100644 --- a/test/checks/color/color-contrast.js +++ b/test/checks/color/color-contrast.js @@ -15,6 +15,45 @@ describe('color-contrast', function () { axe._tree = undefined; }); + it('should return undefined if cannot handle color', function () { + var params = checkSetup( + '