hyperframes 0.7.22 → 0.7.23

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.
@@ -45,6 +45,45 @@ window.__contrastAudit = async function (imgBase64, time) {
45
45
  return s[Math.floor(s.length / 2)];
46
46
  }
47
47
 
48
+ function hasClipPath(el) {
49
+ for (var ce = el; ce; ce = ce.parentElement) {
50
+ var cp = getComputedStyle(ce).clipPath;
51
+ if (cp && cp !== "none") return true;
52
+ }
53
+ return false;
54
+ }
55
+
56
+ var CLIP_PROBE_COLS = [0.05, 0.25, 0.5, 0.75, 0.95];
57
+ var CLIP_PROBE_ROWS = [0.25, 0.5, 0.75];
58
+
59
+ function paintsAnyProbePoint(el, rect) {
60
+ // Keep probe resolution aligned with layout-audit.browser.js. Edge strips
61
+ // narrower than the nearest probe point are treated as clipped away to
62
+ // avoid noisy typewriter pre-reveal contrast reports.
63
+ for (var ci = 0; ci < CLIP_PROBE_COLS.length; ci++) {
64
+ for (var ri = 0; ri < CLIP_PROBE_ROWS.length; ri++) {
65
+ var x = rect.left + rect.width * CLIP_PROBE_COLS[ci];
66
+ var y = rect.top + rect.height * CLIP_PROBE_ROWS[ri];
67
+ var hit = document.elementFromPoint(x, y);
68
+ if (hit === el || el.contains(hit)) return true;
69
+ }
70
+ }
71
+ return false;
72
+ }
73
+
74
+ // A clip-path can shrink an element's painted region to nothing (a typewriter
75
+ // span pre-reveal at `inset(0 100% 0 0)`, or `circle(0px)`) while its box and
76
+ // colours read normally; it then paints zero pixels and measures a meaningless
77
+ // background-on-background ratio. clip-path drives hit-testing, so a fully
78
+ // clipped element is unreachable by elementFromPoint across its box. Probe only
79
+ // when a clip-path is in effect (self or ancestor) so genuinely-occluded but
80
+ // unclipped text is not skipped.
81
+ function isClippedAway(el, rect) {
82
+ if (typeof document.elementFromPoint !== "function") return false;
83
+ if (!hasClipPath(el)) return false;
84
+ return !paintsAnyProbePoint(el, rect);
85
+ }
86
+
48
87
  // Decode screenshot into canvas pixel data
49
88
  var img = new Image();
50
89
  await new Promise(function (resolve) {
@@ -110,6 +149,7 @@ window.__contrastAudit = async function (imgBase64, time) {
110
149
  var rect = el.getBoundingClientRect();
111
150
  if (rect.width < 8 || rect.height < 8) continue;
112
151
  if (rect.right <= 0 || rect.bottom <= 0 || rect.left >= w || rect.top >= h) continue;
152
+ if (isClippedAway(el, rect)) continue;
113
153
 
114
154
  var fg = parseColor(cs.color);
115
155
  if (fg[3] <= 0.01) continue;
@@ -98,6 +98,50 @@
98
98
  return opacity;
99
99
  }
100
100
 
101
+ // A clip-path can shrink an element's painted region to nothing (e.g. a
102
+ // typewriter span pre-reveal at `inset(0 100% 0 0)`, or `circle(0px)`) while
103
+ // its layout box, opacity, visibility and display all still read as present.
104
+ // Such an element paints zero pixels, so flagging it for overlap/occlusion is
105
+ // a false positive. clip-path also drives hit-testing, so an element clipped
106
+ // to nothing is unreachable by elementFromPoint anywhere in its box; only run
107
+ // the probe when a clip-path is actually in effect (self or ancestor) to avoid
108
+ // mistaking a genuinely-occluded element for a clipped one.
109
+ function hasClipPath(element) {
110
+ for (let current = element; current; current = current.parentElement) {
111
+ const clip = getComputedStyle(current).clipPath;
112
+ if (clip && clip !== "none") return true;
113
+ }
114
+ return false;
115
+ }
116
+
117
+ const CLIP_PROBE_COLS = [0.05, 0.25, 0.5, 0.75, 0.95];
118
+ const CLIP_PROBE_ROWS = [0.25, 0.5, 0.75];
119
+
120
+ function paintsAnyProbePoint(element, rect) {
121
+ // Probe resolution intentionally treats edge strips narrower than the
122
+ // nearest probe point as clipped away. That avoids noisy reports for
123
+ // typewriter pre-reveal states; if a real visible-strip bug appears, add
124
+ // edge probes here before widening the audit surface.
125
+ for (const fx of CLIP_PROBE_COLS) {
126
+ for (const fy of CLIP_PROBE_ROWS) {
127
+ const hit = document.elementFromPoint(
128
+ rect.left + rect.width * fx,
129
+ rect.top + rect.height * fy,
130
+ );
131
+ if (hit === element || element.contains(hit)) return true;
132
+ }
133
+ }
134
+ return false;
135
+ }
136
+
137
+ function isClippedAway(element) {
138
+ if (typeof document.elementFromPoint !== "function") return false;
139
+ if (!hasClipPath(element)) return false;
140
+ const rect = element.getBoundingClientRect();
141
+ if (rect.width <= 0.5 || rect.height <= 0.5) return false;
142
+ return !paintsAnyProbePoint(element, rect);
143
+ }
144
+
101
145
  function isVisibleElement(element) {
102
146
  if (IGNORE_TAGS.has(element.tagName)) return false;
103
147
  if (hasIgnoreFlag(element)) return false;
@@ -111,7 +155,8 @@
111
155
  }
112
156
  if (opacityChain(element) < 0.2) return false;
113
157
  const rect = element.getBoundingClientRect();
114
- return rect.width > 0.5 && rect.height > 0.5;
158
+ if (rect.width <= 0.5 || rect.height <= 0.5) return false;
159
+ return !isClippedAway(element);
115
160
  }
116
161
 
117
162
  function textContentFor(element) {