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
3 changes: 2 additions & 1 deletion lib/checks/color/color-contrast-enhanced.json
Original file line number Diff line number Diff line change
Expand Up @@ -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}"
}
}
}
Expand Down
17 changes: 15 additions & 2 deletions lib/checks/color/color-contrast-evaluate.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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
Expand Down
3 changes: 2 additions & 1 deletion lib/checks/color/color-contrast.json
Original file line number Diff line number Diff line change
Expand Up @@ -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}"
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions lib/commons/color/color.js
Original file line number Diff line number Diff line change
@@ -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)/;
Expand Down Expand Up @@ -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}"`);
}

Expand Down
14 changes: 11 additions & 3 deletions lib/commons/color/get-background-color.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
23 changes: 15 additions & 8 deletions lib/commons/color/get-foreground-color.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down
6 changes: 4 additions & 2 deletions locales/_template.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand All @@ -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": {
Expand Down
39 changes: 39 additions & 0 deletions test/checks/color/color-contrast.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,45 @@ describe('color-contrast', function () {
axe._tree = undefined;
});

it('should return undefined if cannot handle color', function () {
var params = checkSetup(
'<div id="divundertest" style="color: oklch(0.961073 0.000047911 none / 0.2); background-color: black; font-size: 14pt; font-weight: 900;">' +
'<span id="target" style="font-weight:lighter;">My text</span></div>'
);

var expectedRelatedNodes = fixture.querySelector('#divundertest');
assert.isUndefined(contrastEvaluate.apply(checkContext, params));
assert.deepEqual(checkContext._relatedNodes, [expectedRelatedNodes]);
assert.deepEqual(checkContext._data.messageKey, 'colorParse');
assert.equal(
checkContext._data.colorParse,
'oklch(0.961073 0.000047911 none / 0.2)'
);
});

it('should return undefined if cannot handle backgroundcolor', function () {
var params = checkSetup(
'<div style="color: gray; background-color: oklch(0.961073 0.000047911 none / 0.2); font-size: 14pt; font-weight: 900;">' +
'<span id="target" style="font-weight:lighter;">My text</span></div>'
);
assert.isUndefined(contrastEvaluate.apply(checkContext, params));
assert.deepEqual(checkContext._relatedNodes, []);
assert.deepEqual(checkContext._data.messageKey, 'colorParse');
assert.equal(
checkContext._data.colorParse,
'oklch(0.961073 0.000047911 none / 0.2)'
);
});

it('should return undefined if cannot handle text-shadow', function () {
var params = checkSetup(
'<div id="target" style="background-color: #fff; color:#000; text-shadow: 1px 1px oklch(0.961073 0.000047911 none / 0.2);">My text</div>'
);

assert.isUndefined(contrastEvaluate.apply(checkContext, params));
assert.deepEqual(checkContext._relatedNodes, []);
});

it('should return true for hidden element', function () {
var params = checkSetup(
'<div style="color: gray; background-color: white; font-size: 14pt; font-weight: 100;">' +
Expand Down
38 changes: 38 additions & 0 deletions test/integration/rules/color-contrast/color-contrast.html
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,44 @@
</div>
</div>

<div
style="
color: oklch(0.961073 0.000047911 none / 0.2);
background-color: black;
font-size: 14pt;
font-weight: 900;
"
>
<span id="canttell21" style="font-weight: lighter"
>This is a foreground colorParse fail!</span
>
</div>

<div
style="
color: gray;
background-color: oklch(0.961073 0.000047911 none / 0.2);
font-size: 14pt;
font-weight: 900;
"
>
<span id="canttell22" style="font-weight: lighter"
>This is a background colorParse fail!</span
>
</div>

<div
style="
background-color: #fff;
color: #000;
text-shadow: 1px 1px oklch(0.961073 0.000047911 none / 0.2);
"
>
<span id="canttell23" style="font-weight: lighter"
>This is a text-shadow colorParse fail!</span
>
</div>

<p
style="
text-overflow: ellipsis;
Expand Down
5 changes: 4 additions & 1 deletion test/integration/rules/color-contrast/color-contrast.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@
["#canttell17"],
["#canttell18"],
["#canttell19"],
["#canttell20"]
["#canttell20"],
["#canttell21"],
["#canttell22"],
["#canttell23"]
]
}