styleproof 1.8.0 → 1.8.1

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/CHANGELOG.md CHANGED
@@ -7,6 +7,15 @@ this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.8.1]
11
+
12
+ ### Fixed
13
+
14
+ - The crop annotation now boxes the **innermost** changed elements (the added
15
+ avatars, the restyled cards) instead of the container the crop anchors on —
16
+ whose box just traced the whole frame and told you nothing. An element present
17
+ on only one side (added/removed) is boxed only there.
18
+
10
19
  ## [1.8.0]
11
20
 
12
21
  The crop now shows you where to look — without painting over the UI.
package/dist/report.js CHANGED
@@ -20,10 +20,17 @@ const union = (a, b) => {
20
20
  };
21
21
  const intersects = (a, b) => a.x < b.x + b.w && b.x < a.x + a.w && a.y < b.y + b.h && b.y < a.y + a.h;
22
22
  const visible = (b) => !!b && b.w > 0 && b.h > 0;
23
- /** Outermost changed paths: drop any path that has a changed strict ancestor. */
23
+ /** Outermost changed paths: drop any path that has a changed strict ancestor.
24
+ * Used to ANCHOR a crop (zoom to the whole changed region, not a leaf). */
24
25
  function outermost(paths) {
25
26
  return paths.filter((p) => !paths.some((q) => q !== p && p.startsWith(q + ' > ')));
26
27
  }
28
+ /** Innermost changed paths: drop any path that has a changed strict descendant.
29
+ * Used to ANNOTATE — box the leaf elements that actually changed (the added
30
+ * avatars, the restyled cards), not their container, whose box ≈ the whole crop. */
31
+ function innermost(paths) {
32
+ return paths.filter((p) => !paths.some((q) => q !== p && q.startsWith(p + ' > ')));
33
+ }
27
34
  /** Headline counts with the zeros dropped — `0 state-delta difference(s)` is noise. */
28
35
  function changeCountLabel(shown) {
29
36
  const parts = [];
@@ -748,10 +755,13 @@ export function generateStyleMapReport(opts) {
748
755
  const after = cropPng(pngB, cropBox, w, h);
749
756
  const composite = compositePair(before.png, after.png);
750
757
  writePng(path.join(outDir, `${stem}-composite.png`), composite);
751
- // Annotated twin: outline each changed element on both sides, so the eye
752
- // lands on what the bullet named. The clean image stays the default.
753
- const rectsA = g.paths.map((p) => mapA.elements[p]?.rect).filter((r) => !!r);
754
- const rectsB = g.paths.map((p) => mapB.elements[p]?.rect).filter((r) => !!r);
758
+ // Annotated twin: outline the LEAF changed elements (the added avatars, the
759
+ // restyled cards) on each side not the merged container the crop anchors
760
+ // on, whose box would just trace the whole frame. An element present on only
761
+ // one side (added/removed) is boxed only there.
762
+ const markPaths = innermost([...new Set(regionFindings.map((f) => f.path))]);
763
+ const rectsA = markPaths.map((p) => mapA.elements[p]?.rect).filter((r) => !!r);
764
+ const rectsB = markPaths.map((p) => mapB.elements[p]?.rect).filter((r) => !!r);
755
765
  const annotated = compositePair(annotateCrop(before, rectsA), annotateCrop(after, rectsB));
756
766
  writePng(path.join(outDir, `${stem}-annotated.png`), annotated);
757
767
  images = { composite: `${stem}-composite.png`, annotated: `${stem}-annotated.png` };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "styleproof",
3
- "version": "1.8.0",
3
+ "version": "1.8.1",
4
4
  "description": "Catch every CSS change before it ships — review PRs and certify refactors by the browser's computed styles, not pixels. Works with any styling system.",
5
5
  "keywords": [
6
6
  "playwright",