pour-engine 1.35.2 → 1.35.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/config/project.config.js
CHANGED
|
@@ -1014,6 +1014,47 @@ export function createContrastRule({ id, tags, help, helpUrl, thresholds }) {
|
|
|
1014
1014
|
message: 'This text overlaps a coloured block that isn’t its DOM ancestor, so its real background is ambiguous — check contrast by eye.',
|
|
1015
1015
|
};
|
|
1016
1016
|
}
|
|
1017
|
+
// The panel scan keeps to positioned and floated paint because only
|
|
1018
|
+
// those cross sibling boundaries. The TEXT can be the one crossing:
|
|
1019
|
+
// an absolutely positioned floating label sits on the static <input>
|
|
1020
|
+
// beside it, and the walk, which never leaves the label's ancestors,
|
|
1021
|
+
// read the grey section behind the form (worldbank.org sign-up,
|
|
1022
|
+
// 2026-08-27, asserted 4.44:1 against the wrapper while the glyphs
|
|
1023
|
+
// sit on the input's white, 4.67:1; the same label passed once
|
|
1024
|
+
// scrolled into view and hit-tested). When the text or an ancestor
|
|
1025
|
+
// up to its containing block is out of flow, the static opaque
|
|
1026
|
+
// boxes inside that containing block are candidates too. Bounded by
|
|
1027
|
+
// the containing block's subtree; a huge one keeps the walk-only
|
|
1028
|
+
// behaviour rather than paying a full-page style pass per element.
|
|
1029
|
+
if (!blindOnly) {
|
|
1030
|
+
let outOfFlow = false;
|
|
1031
|
+
let block = null;
|
|
1032
|
+
for (let node = element; node && node.nodeType === 1 && node !== doc.body; node = node.parentElement ?? node.getRootNode()?.host) {
|
|
1033
|
+
const position = getComputedStyle(node).position;
|
|
1034
|
+
if (node !== element && position !== 'static') { block = node; break; }
|
|
1035
|
+
if (position === 'absolute' || position === 'fixed') outOfFlow = true;
|
|
1036
|
+
}
|
|
1037
|
+
if (outOfFlow && block) {
|
|
1038
|
+
const inside = block.querySelectorAll('*');
|
|
1039
|
+
if (inside.length <= 2000) {
|
|
1040
|
+
for (const sibling of inside) {
|
|
1041
|
+
if (sibling === element || sibling.contains(element) || element.contains(sibling)) continue;
|
|
1042
|
+
const siblingStyle = getComputedStyle(sibling);
|
|
1043
|
+
if (siblingStyle.position !== 'static' || siblingStyle.visibility === 'hidden') continue;
|
|
1044
|
+
const paint = parseColor(siblingStyle.backgroundColor);
|
|
1045
|
+
if (!paint || paint.a < 1) continue;
|
|
1046
|
+
const siblingRect = sibling.getBoundingClientRect();
|
|
1047
|
+
if (siblingRect.width < 24 || siblingRect.height < 12 || !near(siblingRect) || !textIntersects(element, siblingRect)) continue;
|
|
1048
|
+
if ((contrastRatio(foreground, paint) >= required) !== (direction === 'pass')) {
|
|
1049
|
+
return {
|
|
1050
|
+
status: 'incomplete',
|
|
1051
|
+
message: 'This text is positioned over a coloured box that isn’t its DOM ancestor, so its real background is ambiguous — check contrast by eye.',
|
|
1052
|
+
};
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1017
1058
|
return null;
|
|
1018
1059
|
};
|
|
1019
1060
|
|
package/package.json
CHANGED