You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: packages/cli/src/commands/layout-audit.browser.js
+8-37Lines changed: 8 additions & 37 deletions
Original file line number
Diff line number
Diff line change
@@ -1233,10 +1233,7 @@
1233
1233
constmapped=point.matrixTransform(matrix);
1234
1234
return{x: mapped.x,y: mapped.y};
1235
1235
};
1236
-
// getPointAtLength can still throw on a degenerate/malformed path even after
1237
-
// getTotalLength succeeded. This sampler runs once PER seeked frame, so one
1238
-
// bad path must degrade to "no endpoints" (skip this path), not abort the
1239
-
// whole check for every remaining path and frame.
1236
+
// getPointAtLength can throw on a degenerate path even after getTotalLength; skip that path instead of aborting the whole per-frame check.
1240
1237
try{
1241
1238
return{
1242
1239
start: toScreen(path.getPointAtLength(0)),
@@ -1743,34 +1740,20 @@
1743
1740
returnsamples;
1744
1741
};
1745
1742
1746
-
// connector_motion_detached sampling. Per seeked frame, report every diagram
1747
-
// connector's two screen-space endpoints AND every plausible node/box bbox.
1748
-
// Node accumulates these across the grid and flags an endpoint that stays
1749
-
// anchored to a node while the other endpoint sits in empty space on the held
1750
-
// frames — a connector whose coordinates were frozen (wrong rotation pivot, or
1751
-
// measured once at build) while its target kept moving. Icon-sized SVGs and
1752
-
// short strokes are filtered out so only real diagram connectors count.
1743
+
// connector_motion_detached sampling: per frame, report each connector's screen endpoints and every node bbox; icon-sized SVGs and short strokes are filtered out.
1753
1744
constCONNECTOR_MIN_SVG_PX=100;
1754
1745
constCONNECTOR_MIN_LEN_PX=60;
1755
-
// Gauge needles/pointers/ticks are one-end-anchored indicators, not node-to-node
1756
-
// connectors — a separate (gauge) check owns them. Skip by id/class of the line
1757
-
// or any group ancestor up to the SVG.
1746
+
// Gauge needles/pointers/ticks are one-end-anchored indicators owned by a separate check; skip by id/class of the line or any group ancestor.
// SVG dots/markers are small; keep the floor low but above sub-pixel decoration.
1761
1750
constCONNECTOR_NODE_MIN_DOT_AREA=16;
1762
1751
constCONNECTOR_NODE_CAP=300;
1763
-
// A stroke-drawn dial/hub ring may be an <path> arc (M...A...), not a <circle>.
1764
-
// Recognize near-circular stroke paths as ring nodes so connectors attaching
1765
-
// to them aren't false-flagged as detached, and so the gauge-indicator geometry
1766
-
// exclusion (which keys on ring nodes) can see arc-drawn dials too.
1752
+
// Recognize near-circular stroke <path> arcs as ring nodes so connectors attaching to them aren't false-flagged and the gauge exclusion sees arc-drawn dials.
1767
1753
constCONNECTOR_RING_MIN_LEN=120;
1768
1754
constCONNECTOR_RING_MIN_RADIUS=20;
1769
1755
constCONNECTOR_RING_MAX_RESIDUAL_FRAC=0.15;
1770
-
// Phantom-radius guard: a real ring/hub's fitted diameter tracks its bounding
1771
-
// box (full circle 1x, quarter arc ~2x). A shallow-curvature arc fits an
1772
-
// enormous circle with a tiny normalized residual, so the diameter runs many×
1773
-
// the box — reject beyond this factor.
1756
+
// Phantom-radius guard: a shallow arc fits an enormous circle with a tiny residual, so reject when the fitted diameter runs past this factor of the bbox.
1774
1757
constCONNECTOR_RING_MAX_DIAMETER_BBOX_FRAC=3;
1775
1758
1776
1759
functionisIndicatorConnector(line,svg){
@@ -1799,13 +1782,7 @@
1799
1782
};
1800
1783
}
1801
1784
1802
-
// Node/box candidates a connector could anchor to: sized, opaque or text-
1803
-
// bearing HTML elements plus SVG hub/ring/dot shapes. A shape drawn stroke-only
1804
-
// (fill:none) is a ring — the connector attaches to its stroke, so it is marked
1805
-
// `ring` and matched by perimeter, not hollow interior (see pointToNodeGap).
1806
-
// A near-circular stroke <path> read as a ring/hub node. Returns a node box
1807
-
// (ring flag from fill) or null when the path is not a resolvable circular hub.
1808
-
// getPointAtLength is guarded — one malformed path must not abort the sampler.
1785
+
// Read a near-circular stroke <path> as a ring/hub node box (ring flag from fill), or null if not a resolvable hub; getPointAtLength is guarded so one bad path can't abort the sampler.
// Reject the shallow-curvature phantom fit: normalized residual is small at
1834
-
// any radius, so a nearly-straight arc masquerades as a huge ring. The
1835
-
// fitted diameter must stay within a sane factor of the drawn bounding box.
1810
+
// Reject the shallow-curvature phantom fit: a nearly-straight arc masquerades as a huge ring, so the fitted diameter must stay within a sane factor of the bbox.
// Scoped-known seams (left as-is — narrow and not phantom-radius): a short
1841
-
// genuine partial arc under-samples its parent circle's box so a real hub
1842
-
// drawn as a sliver can still miss the span gate; and a curved connector
1843
-
// that is itself near-circular can be read as its own ring node. Both are
1844
-
// rare vs. the shallow-curvature false ring this gate closes.
1815
+
// Known narrow seams left as-is: a sliver partial arc can miss the span gate, and a near-circular connector can read as its own ring node — both rare vs. the false ring this gate closes.
// A near-full circle (diameter tracks its bbox) vs a shallow arc on a huge
891
-
// circle: the arc's Kåsa residual normalized by its enormous radius is tiny
892
-
// (passes the residual gate) yet its fitted diameter is ~10x its drawn box.
890
+
// Shallow arc on a huge circle passes the residual gate yet its fitted diameter is ~10x its drawn box — the phantom-radius case, vs a genuine near-full circle.
it("flags a loose end that only touches a node in ONE held frame then detaches the rest",()=>{
91
-
// End A stays pinned to the hub; end B lands on the satellite for a single
92
-
// held frame (t=4) then dangles ~120px away for the rest of the held window.
93
-
// A lone graze is NOT sustained attachment, so B must read as dangling and
94
-
// the connector must be flagged — not cleared by the single touch.
90
+
// A lone graze (B touches the satellite once at t=4, dangles the rest) is not sustained attachment, so B must still read as dangling and the connector be flagged.
it("still fires on a radial connector drifting toward the centre (not outward)",()=>{
159
-
// Anchored on a peripheral node; loose end drifts inward to empty space near
160
-
// a ring centre — the fuzz011 shape, opposite of a gauge pointer.
152
+
// Anchored on a peripheral node with the loose end drifting inward to empty space near a ring centre — the fuzz011 shape, opposite of a gauge pointer.
// Gauge-indicator geometry: the anchored end pivots near a ring/arc centre and
1105
-
// the loose end extends radially outward. That is a needle/pointer (owned by a
1106
-
// separate gauge check), not a broken node connector. A defective radial
1107
-
// connector points the other way — anchored on a peripheral node, loose end
1108
-
// drifting toward the centre — so this only excludes true centre-pivot pointers.
1089
+
// Gauge indicator: anchored end pivots near a ring centre, loose end extends outward — a needle (owned by a separate gauge check), so exclude only true centre-pivot pointers.
1109
1090
constGAUGE_HUB_CENTRE_FRACTION=0.25;
1110
1091
1111
1092
functionisGaugeIndicator(
@@ -1154,32 +1135,14 @@ function connectorDetachFinding(
1154
1135
};
1155
1136
}
1156
1137
1157
-
/**
1158
-
* connector_motion_detached: a connector (SVG <line>/<path>) that stays anchored
1159
-
* to a node at ONE endpoint while its OTHER endpoint sits in empty space — far
1160
-
* from every node — across the held (steady) frames. This is the sibling of the
1161
-
* per-frame `connector_detached` check, which requires BOTH endpoints far from
1162
-
* anchors on a single frame and so deliberately ignores the half-attached case.
1163
-
* But that half-attached case is the dominant real failure under motion: a
1164
-
* spoke/edge whose one end stays pinned (e.g. at a hub) while the other drifts
1165
-
* off a node that kept moving — rotated about a wrong pivot, or with a path
1166
-
* measured once at build then never updated as the target animated.
1167
-
*
1168
-
* FP-guarded, deliberately strict: one endpoint must be genuinely anchored
1169
-
* (structural, not a name match); the loose end must clear a high detach
1170
-
* threshold on ~all held frames (measured against a dense node-candidate set, so
1171
-
* only an endpoint in truly empty space fires — snug residual gaps and lead
1172
-
* lines to a nearby label do not); and a selector that aliases multiple
1173
-
* connectors in one frame is dropped.
1174
-
*/
1138
+
/** connector_motion_detached: the half-attached case connector_detached ignores — one endpoint pinned while the other drifts into empty space across held frames (wrong pivot, or coords measured once at build). Strict + FP-guarded. */
1175
1139
interfaceDanglePick{
1176
1140
anchored: {x: number;y: number};
1177
1141
dangling: {x: number;y: number};
1178
1142
gap: number;
1179
1143
}
1180
1144
1181
-
/** If exactly one endpoint is anchored and the other persistently dangles, name
1182
-
* the anchored/dangling points and the dangling gap; else null. */
1145
+
/** If exactly one endpoint is anchored and the other persistently dangles, name the anchored/dangling points and the gap; else null. */
1183
1146
functiondanglingEndpoint(
1184
1147
last: ConnectorObservation,
1185
1148
gapsA: EndpointHeldGaps,
@@ -1196,9 +1159,7 @@ function danglingEndpoint(
1196
1159
returnnull;
1197
1160
}
1198
1161
1199
-
/** One connector's held trajectory → a finding, or null. A finding needs one
1200
-
* endpoint anchored to a node and the other persistently in empty space, and is
1201
-
* suppressed for gauge-indicator geometry (see isGaugeIndicator). */
1162
+
/** One connector's held trajectory → a finding, or null; needs one anchored endpoint and one persistently in empty space, suppressed for gauge-indicator geometry. */
0 commit comments