pour-engine 1.27.0 → 1.28.0
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
package/engine/lib/contrast.js
CHANGED
|
@@ -130,6 +130,7 @@ let opacityAnimatorsCache = null;
|
|
|
130
130
|
let mediaRectsCache = null;
|
|
131
131
|
let panelRectsCache = null;
|
|
132
132
|
let pseudoCache = new WeakMap();
|
|
133
|
+
let zeroClipCache = new WeakMap();
|
|
133
134
|
const HAS_IMAGE = Symbol('background-image in chain');
|
|
134
135
|
|
|
135
136
|
export function resetAuditCaches() {
|
|
@@ -139,6 +140,49 @@ export function resetAuditCaches() {
|
|
|
139
140
|
mediaRectsCache = null;
|
|
140
141
|
panelRectsCache = null;
|
|
141
142
|
pseudoCache = new WeakMap();
|
|
143
|
+
zeroClipCache = new WeakMap();
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* True when the element sits inside a subtree erased by a ZERO-AREA clip —
|
|
148
|
+
* the sr-only recipe (clip: rect(0,0,0,0) / clip-path: inset(50%) on an
|
|
149
|
+
* absolutely positioned wrapper) applied to an ANCESTOR, which is where it
|
|
150
|
+
* usually lives: a chart's accessible data table hides the table, and the
|
|
151
|
+
* judged element is a cell inside it. Only provably zero-area patterns
|
|
152
|
+
* count: a clip rect with no width or height (any `auto` component keeps
|
|
153
|
+
* the element judged), or a percentage inset consuming a full axis.
|
|
154
|
+
* Partial clips never hide. Verdicts cache per ancestor, so a page pays
|
|
155
|
+
* per container, not per descendant.
|
|
156
|
+
*/
|
|
157
|
+
export function inZeroClipSubtree(element) {
|
|
158
|
+
for (let a = element; a; a = a.parentElement) {
|
|
159
|
+
let hidden = zeroClipCache.get(a);
|
|
160
|
+
if (hidden === undefined) {
|
|
161
|
+
const s = getComputedStyle(a);
|
|
162
|
+
hidden = false;
|
|
163
|
+
if (s.clip !== 'auto' && s.position !== 'static') {
|
|
164
|
+
const m = /rect\(([^)]+)\)/.exec(s.clip);
|
|
165
|
+
if (m) {
|
|
166
|
+
const parts = m[1].split(',').map((v) => v.trim());
|
|
167
|
+
if (!parts.includes('auto') && parts.length === 4) {
|
|
168
|
+
const [t, r, b, l] = parts.map(parseFloat);
|
|
169
|
+
if (r - l <= 0 || b - t <= 0) hidden = true;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if (!hidden && s.clipPath && s.clipPath !== 'none') {
|
|
174
|
+
const m = /inset\(([^)]+)\)/.exec(s.clipPath);
|
|
175
|
+
if (m && !m[1].includes('px')) {
|
|
176
|
+
const parts = m[1].trim().split(/\s+/).map(parseFloat);
|
|
177
|
+
const [t, r = t, b = t, l = r] = parts;
|
|
178
|
+
if (t + b >= 100 || l + r >= 100) hidden = true;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
zeroClipCache.set(a, hidden);
|
|
182
|
+
}
|
|
183
|
+
if (hidden) return true;
|
|
184
|
+
}
|
|
185
|
+
return false;
|
|
142
186
|
}
|
|
143
187
|
|
|
144
188
|
/**
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
parseColor, contrastRatio, composite, effectiveBackground, backgroundObscured,
|
|
4
4
|
backgroundImageSource, backgroundImagePaintRect, imagePaintRectInBox, imageLuminanceRange,
|
|
5
5
|
gradientLuminanceRange, rangeVerdict, rangeWithBackdrop, isLargeText, cumulativeOpacity,
|
|
6
|
-
opacityAnimating, restingOpacity, mediaRects,
|
|
6
|
+
opacityAnimating, restingOpacity, mediaRects, inZeroClipSubtree,
|
|
7
7
|
paintedBackdrop, opaquePanelRects, viewportVeil, textShadowHalo, textShadowNegligible,
|
|
8
8
|
pseudoBackdropForText, filmedContrastBounds, backgroundColorSource, scrimPaint, applyOverlays,
|
|
9
9
|
showRatio,
|
|
@@ -138,13 +138,15 @@ function textVisuallyHidden(element, style, foreground) {
|
|
|
138
138
|
const indent = parseFloat(style.textIndent) || 0;
|
|
139
139
|
const clipped = /hidden|clip/.test(`${style.overflow} ${style.overflowX} ${style.overflowY}`)
|
|
140
140
|
|| style.clipPath !== 'none' || (style.clip !== 'auto' && style.position === 'absolute');
|
|
141
|
-
// Nothing hints at hiding:
|
|
142
|
-
//
|
|
143
|
-
|
|
141
|
+
// Nothing on the element itself hints at hiding: the recipe may still sit
|
|
142
|
+
// on a WRAPPER (a chart's sr-only data table hides the table; the judged
|
|
143
|
+
// cell inside computes clip: auto) — the ancestor walk is cached per
|
|
144
|
+
// container, so this stays affordable on every text element.
|
|
145
|
+
if (!clipped && Math.abs(indent) <= 1000) return inZeroClipSubtree(element);
|
|
144
146
|
const rect = element.getBoundingClientRect();
|
|
145
147
|
if ((rect.width <= 1 || rect.height <= 1) && clipped) return true;
|
|
146
148
|
if (Math.abs(indent) > rect.width && (clipped || Math.abs(indent) > 1000)) return true;
|
|
147
|
-
return
|
|
149
|
+
return inZeroClipSubtree(element);
|
|
148
150
|
}
|
|
149
151
|
|
|
150
152
|
// Turn a luminance-range bracket into a rule outcome (or null = can't tell).
|
package/package.json
CHANGED