@calibrate-ds/core 0.1.40 → 0.1.42

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.
@@ -1,4 +1,5 @@
1
- export type { VerifyReport, VerifyScreenshots, PixelMatchResult, AIFeedback, AIDifference, } from "./types.js";
1
+ export type { VerifyReport, VerifyScreenshots, PixelMatchResult, AIFeedback, AIDifference, StructureExpectations, StructureFound, } from "./types.js";
2
2
  export { fetchFigmaScreenshot } from "./fetch-figma-screenshot.js";
3
3
  export { runPixelDiff } from "./pixel-diff.js";
4
+ export { extractStructuralExpectations, computeStructureScore } from "./structure-check.js";
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/verify/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACR,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EACV,YAAY,GACf,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/verify/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACR,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EACV,YAAY,EACZ,qBAAqB,EACrB,cAAc,GACjB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,6BAA6B,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC"}
@@ -1,3 +1,4 @@
1
1
  export { fetchFigmaScreenshot } from "./fetch-figma-screenshot.js";
2
2
  export { runPixelDiff } from "./pixel-diff.js";
3
+ export { extractStructuralExpectations, computeStructureScore } from "./structure-check.js";
3
4
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/verify/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/verify/index.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,6BAA6B,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC"}
@@ -2,13 +2,16 @@ import type { PixelMatchResult } from "./types.js";
2
2
  /**
3
3
  * Compares two PNG files pixel-by-pixel using pixelmatch.
4
4
  * Saves an annotated diff image to diffOutputPath.
5
- * Returns the match score (0–1, 1 = identical), or null if comparison fails.
5
+ * Returns the match scores (0–1, 1 = identical), or null if comparison fails.
6
6
  *
7
- * Dimension mismatch handling in order:
8
- * 1. If impl is ≥1.5× larger in both dimensions (e.g. 2× DPR retina capture),
9
- * scale it down to the Figma reference size before comparing.
10
- * 2. Otherwise, crop/pad the impl to match the Figma frame is the authoritative
11
- * target viewport.
7
+ * Dimension mismatch: always scale impl to Figma reference dimensions (never pad
8
+ * with white, which inflates scores on mostly-white components).
9
+ *
10
+ * Content score: if high-variance (photographic/raster) regions are detected in
11
+ * the Figma reference, a second masked comparison excludes those patches and
12
+ * reports contentScore — the fidelity of the non-image UI regions only. This
13
+ * prevents placeholder-image differences from killing the score for otherwise
14
+ * faithful implementations.
12
15
  */
13
16
  export declare function runPixelDiff(figmaPath: string, implPath: string, diffOutputPath: string): Promise<PixelMatchResult | null>;
14
17
  //# sourceMappingURL=pixel-diff.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pixel-diff.d.ts","sourceRoot":"","sources":["../../src/verify/pixel-diff.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AA0BnD;;;;;;;;;;GAUG;AACH,wBAAsB,YAAY,CAC9B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,GACvB,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAsClC"}
1
+ {"version":3,"file":"pixel-diff.d.ts","sourceRoot":"","sources":["../../src/verify/pixel-diff.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAgGnD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,YAAY,CAC9B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,GACvB,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAoElC"}
@@ -1,9 +1,12 @@
1
1
  import * as fs from "node:fs/promises";
2
2
  import * as path from "node:path";
3
+ // Patch size (px) and luminance-variance threshold for raster region detection.
4
+ // Photos/textures → variance >> 600; flat UI (solid fills, gradients) → variance < 300.
5
+ const PATCH_SIZE = 16;
6
+ const RASTER_VARIANCE_THRESHOLD = 600;
3
7
  /**
4
- * Nearest-neighbor downscale. Used to normalise a DPR impl screenshot to
5
- * the reference dimensions before pixel-diffing avoids the "every row is
6
- * shifted" artifact that crop/pad produces on retina captures.
8
+ * Nearest-neighbor scale to target dimensions (handles both up and down).
9
+ * Used to align impl screenshot to Figma reference dimensions before diffing.
7
10
  */
8
11
  function scaleDown(src, targetW, targetH, PNG) {
9
12
  const out = new PNG({ width: targetW, height: targetH });
@@ -23,16 +26,69 @@ function scaleDown(src, targetW, targetH, PNG) {
23
26
  }
24
27
  return out;
25
28
  }
29
+ /**
30
+ * Divides the Figma reference into PATCH_SIZE×PATCH_SIZE tiles and marks tiles
31
+ * whose luminance variance exceeds RASTER_VARIANCE_THRESHOLD as "raster" patches.
32
+ * Returns the boolean mask (indexed row-major by patch) plus the patch grid dimensions.
33
+ */
34
+ function buildRasterMask(data, imgWidth, imgHeight, patchSize, threshold) {
35
+ const patchCols = Math.ceil(imgWidth / patchSize);
36
+ const patchRows = Math.ceil(imgHeight / patchSize);
37
+ const mask = [];
38
+ for (let pr = 0; pr < patchRows; pr++) {
39
+ for (let pc = 0; pc < patchCols; pc++) {
40
+ const lums = [];
41
+ for (let py = pr * patchSize; py < Math.min((pr + 1) * patchSize, imgHeight); py++) {
42
+ for (let px = pc * patchSize; px < Math.min((pc + 1) * patchSize, imgWidth); px++) {
43
+ const i = (py * imgWidth + px) * 4;
44
+ lums.push(0.299 * data[i] + 0.587 * data[i + 1] + 0.114 * data[i + 2]);
45
+ }
46
+ }
47
+ const mean = lums.reduce((a, b) => a + b, 0) / lums.length;
48
+ const variance = lums.reduce((acc, v) => acc + (v - mean) ** 2, 0) / lums.length;
49
+ mask.push(variance > threshold);
50
+ }
51
+ }
52
+ return { mask, patchCols, patchRows };
53
+ }
54
+ /**
55
+ * Fills masked patches in-place with neutral mid-gray (128,128,128,255).
56
+ * When applied to both images before pixelmatch, masked patches contribute
57
+ * 0 diff pixels, so only non-masked (content) pixels affect the score.
58
+ * Returns the number of pixels filled.
59
+ */
60
+ function applyRasterMask(target, mask, patchSize, patchCols, imgWidth, imgHeight) {
61
+ const patchRows = Math.ceil(imgHeight / patchSize);
62
+ let maskedPixels = 0;
63
+ for (let pr = 0; pr < patchRows; pr++) {
64
+ for (let pc = 0; pc < patchCols; pc++) {
65
+ if (!mask[pr * patchCols + pc])
66
+ continue;
67
+ for (let py = pr * patchSize; py < Math.min((pr + 1) * patchSize, imgHeight); py++) {
68
+ for (let px = pc * patchSize; px < Math.min((pc + 1) * patchSize, imgWidth); px++) {
69
+ const i = (py * imgWidth + px) * 4;
70
+ target[i] = target[i + 1] = target[i + 2] = 128;
71
+ target[i + 3] = 255;
72
+ maskedPixels++;
73
+ }
74
+ }
75
+ }
76
+ }
77
+ return maskedPixels;
78
+ }
26
79
  /**
27
80
  * Compares two PNG files pixel-by-pixel using pixelmatch.
28
81
  * Saves an annotated diff image to diffOutputPath.
29
- * Returns the match score (0–1, 1 = identical), or null if comparison fails.
82
+ * Returns the match scores (0–1, 1 = identical), or null if comparison fails.
83
+ *
84
+ * Dimension mismatch: always scale impl to Figma reference dimensions (never pad
85
+ * with white, which inflates scores on mostly-white components).
30
86
  *
31
- * Dimension mismatch handling in order:
32
- * 1. If impl is ≥1.5× larger in both dimensions (e.g. DPR retina capture),
33
- * scale it down to the Figma reference size before comparing.
34
- * 2. Otherwise, crop/pad the impl to match — the Figma frame is the authoritative
35
- * target viewport.
87
+ * Content score: if high-variance (photographic/raster) regions are detected in
88
+ * the Figma reference, a second masked comparison excludes those patches and
89
+ * reports contentScore the fidelity of the non-image UI regions only. This
90
+ * prevents placeholder-image differences from killing the score for otherwise
91
+ * faithful implementations.
36
92
  */
37
93
  export async function runPixelDiff(figmaPath, implPath, diffOutputPath) {
38
94
  try {
@@ -41,21 +97,36 @@ export async function runPixelDiff(figmaPath, implPath, diffOutputPath) {
41
97
  const figmaPng = PNG.sync.read(await fs.readFile(figmaPath));
42
98
  let implPng = PNG.sync.read(await fs.readFile(implPath));
43
99
  const { width, height } = figmaPng;
44
- // Align impl to Figma dimensions so pixelmatch can compare.
45
- // Always scale (never pad with white) — padding inflates scores on white-background components.
100
+ // Align impl to Figma dimensions scale always, never pad with white.
46
101
  if (implPng.width !== width || implPng.height !== height) {
47
102
  implPng = scaleDown(implPng, width, height, PNG);
48
103
  }
104
+ // ── Full-frame diff (primary score + diff image) ─────────────────────
49
105
  const diffPng = new PNG({ width, height });
50
106
  const totalPixels = width * height;
51
107
  const diffPixels = pixelmatch(figmaPng.data, implPng.data, diffPng.data, width, height, { threshold: 0.1, includeAA: false });
52
108
  await fs.mkdir(path.dirname(diffOutputPath), { recursive: true });
53
109
  await fs.writeFile(diffOutputPath, PNG.sync.write(diffPng));
54
- return {
55
- score: parseFloat((1 - diffPixels / totalPixels).toFixed(4)),
56
- diffPixels,
57
- totalPixels,
58
- };
110
+ const score = parseFloat((1 - diffPixels / totalPixels).toFixed(4));
111
+ // ── Content-only score (exclude raster image patches) ────────────────
112
+ const { mask, patchCols } = buildRasterMask(figmaPng.data, width, height, PATCH_SIZE, RASTER_VARIANCE_THRESHOLD);
113
+ const rasterPatchCount = mask.filter(Boolean).length;
114
+ if (rasterPatchCount === 0) {
115
+ return { score, diffPixels, totalPixels };
116
+ }
117
+ // At least one raster patch: run a second comparison on masked copies.
118
+ // Both images get the same patches filled with mid-gray → pixelmatch sees
119
+ // 0 diff in those patches → contentDiffPixels counts content regions only.
120
+ const figmaMasked = Buffer.from(figmaPng.data);
121
+ const implMasked = Buffer.from(implPng.data);
122
+ const maskedPixels = applyRasterMask(figmaMasked, mask, PATCH_SIZE, patchCols, width, height);
123
+ applyRasterMask(implMasked, mask, PATCH_SIZE, patchCols, width, height);
124
+ const diffMasked = new PNG({ width, height });
125
+ const contentDiffPixels = pixelmatch(figmaMasked, implMasked, diffMasked.data, width, height, { threshold: 0.1, includeAA: false });
126
+ const contentPixels = totalPixels - maskedPixels;
127
+ const contentScore = parseFloat((contentPixels > 0 ? 1 - contentDiffPixels / contentPixels : 1).toFixed(4));
128
+ const rasterPixelRatio = parseFloat((maskedPixels / totalPixels).toFixed(4));
129
+ return { score, contentScore, rasterPixelRatio, diffPixels, totalPixels };
59
130
  }
60
131
  catch {
61
132
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"pixel-diff.js","sourceRoot":"","sources":["../../src/verify/pixel-diff.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAIlC;;;;GAIG;AACH,SAAS,SAAS,CAAC,GAAgB,EAAE,OAAe,EAAE,OAAe,EAAE,GAAQ;IAC3E,MAAM,GAAG,GAAgB,IAAI,GAAG,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;IACtE,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,GAAG,OAAO,CAAC;IACnC,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,GAAG,OAAO,CAAC;IACpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC;YAC/B,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;YAClC,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;YAClC,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;YACpC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;YAChC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAO,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC9B,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAClC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAClC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACtC,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC;AACf,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAC9B,SAAiB,EACjB,QAAgB,EAChB,cAAsB;IAEtB,IAAI,CAAC;QACD,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC;QACtC,MAAM,UAAU,GAAG,CAAC,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC;QAExD,MAAM,QAAQ,GAAgB,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;QAC1E,IAAI,OAAO,GAAmB,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;QAEzE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,QAAQ,CAAC;QAEnC,4DAA4D;QAC5D,gGAAgG;QAChG,IAAI,OAAO,CAAC,KAAK,KAAK,KAAK,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YACvD,OAAO,GAAG,SAAS,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;QACrD,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QAC3C,MAAM,WAAW,GAAG,KAAK,GAAG,MAAM,CAAC;QACnC,MAAM,UAAU,GAAG,UAAU,CACzB,QAAQ,CAAC,IAAI,EACb,OAAO,CAAC,IAAI,EACZ,OAAO,CAAC,IAAI,EACZ,KAAK,EACL,MAAM,EACN,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,CACvC,CAAC;QAEF,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAClE,MAAM,EAAE,CAAC,SAAS,CAAC,cAAc,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAE5D,OAAO;YACH,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,UAAU,GAAG,WAAW,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YAC5D,UAAU;YACV,WAAW;SACd,CAAC;IACN,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,IAAI,CAAC;IAChB,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"pixel-diff.js","sourceRoot":"","sources":["../../src/verify/pixel-diff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { StructureExpectations, StructureFound } from "./types.js";
2
+ /**
3
+ * Walks a LayoutTreeNode tree (children only, not childOverrides which are
4
+ * variant branches) and counts structural slot types that must be present
5
+ * in the rendered DOM for a faithful implementation.
6
+ */
7
+ export declare function extractStructuralExpectations(renderTree: any): StructureExpectations;
8
+ /**
9
+ * Returns a 0–1 structure score — the fraction of expected structural slots
10
+ * that are present and non-empty in the rendered DOM.
11
+ *
12
+ * Returns undefined when there are no trackable slots (e.g. icon components),
13
+ * signalling the caller to fall back to the pixel score.
14
+ *
15
+ * Scoring weights:
16
+ * - text slots: 70% of the total (more numerous and meaningful)
17
+ * - image slots: 30% (binary — either the <img> exists or it doesn't)
18
+ * When only one slot type is present its weight becomes 100%.
19
+ */
20
+ export declare function computeStructureScore(exp: StructureExpectations, found: StructureFound): number | undefined;
21
+ //# sourceMappingURL=structure-check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structure-check.d.ts","sourceRoot":"","sources":["../../src/verify/structure-check.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAExE;;;;GAIG;AACH,wBAAgB,6BAA6B,CAAC,UAAU,EAAE,GAAG,GAAG,qBAAqB,CA8BpF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CACjC,GAAG,EAAE,qBAAqB,EAC1B,KAAK,EAAE,cAAc,GACtB,MAAM,GAAG,SAAS,CAqBpB"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Walks a LayoutTreeNode tree (children only, not childOverrides which are
3
+ * variant branches) and counts structural slot types that must be present
4
+ * in the rendered DOM for a faithful implementation.
5
+ */
6
+ export function extractStructuralExpectations(renderTree) {
7
+ let textSlots = 0;
8
+ let imageSlots = 0;
9
+ const TEXT_ROLES = new Set([
10
+ "text", "title", "label", "description",
11
+ "placeholder-text", "error-text", "helper-text",
12
+ ]);
13
+ function walk(node) {
14
+ if (!node)
15
+ return;
16
+ const isTextByRole = TEXT_ROLES.has(node.role ?? "");
17
+ const isTextByType = node.rawStyles?.nodeType === "TEXT";
18
+ const isTextByValue = node.textContent !== undefined && node.type === "leaf";
19
+ if (isTextByRole || isTextByType || isTextByValue) {
20
+ textSlots++;
21
+ }
22
+ if (node.imageAssetPath) {
23
+ imageSlots++;
24
+ }
25
+ for (const child of node.children ?? [])
26
+ walk(child);
27
+ // intentionally skip childOverrides — those are variant branches, not distinct slots
28
+ }
29
+ walk(renderTree);
30
+ return { textSlots, imageSlots };
31
+ }
32
+ /**
33
+ * Returns a 0–1 structure score — the fraction of expected structural slots
34
+ * that are present and non-empty in the rendered DOM.
35
+ *
36
+ * Returns undefined when there are no trackable slots (e.g. icon components),
37
+ * signalling the caller to fall back to the pixel score.
38
+ *
39
+ * Scoring weights:
40
+ * - text slots: 70% of the total (more numerous and meaningful)
41
+ * - image slots: 30% (binary — either the <img> exists or it doesn't)
42
+ * When only one slot type is present its weight becomes 100%.
43
+ */
44
+ export function computeStructureScore(exp, found) {
45
+ const hasText = exp.textSlots > 0;
46
+ const hasImage = exp.imageSlots > 0;
47
+ if (!hasText && !hasImage)
48
+ return undefined;
49
+ const parts = [];
50
+ if (hasText) {
51
+ // Partial credit: having MORE text nodes than expected is fine (min cap at 1).
52
+ // A rendered component that has all slots is worth 1; each missing slot reduces.
53
+ parts.push({ value: Math.min(1, found.textNodes / exp.textSlots), weight: 0.7 });
54
+ }
55
+ if (hasImage) {
56
+ // Binary: either the image region is rendered or it isn't.
57
+ parts.push({ value: found.imageElements > 0 ? 1 : 0, weight: 0.3 });
58
+ }
59
+ const totalWeight = parts.reduce((s, p) => s + p.weight, 0);
60
+ const weighted = parts.reduce((s, p) => s + p.value * p.weight, 0);
61
+ return parseFloat((weighted / totalWeight).toFixed(4));
62
+ }
63
+ //# sourceMappingURL=structure-check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structure-check.js","sourceRoot":"","sources":["../../src/verify/structure-check.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,UAAU,6BAA6B,CAAC,UAAe;IACzD,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,UAAU,GAAG,CAAC,CAAC;IAEnB,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC;QACvB,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa;QACvC,kBAAkB,EAAE,YAAY,EAAE,aAAa;KAClD,CAAC,CAAC;IAEH,SAAS,IAAI,CAAC,IAAS;QACnB,IAAI,CAAC,IAAI;YAAE,OAAO;QAElB,MAAM,YAAY,GAAI,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;QACtD,MAAM,YAAY,GAAI,IAAI,CAAC,SAAS,EAAE,QAAQ,KAAK,MAAM,CAAC;QAC1D,MAAM,aAAa,GAAG,IAAI,CAAC,WAAW,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC;QAE7E,IAAI,YAAY,IAAI,YAAY,IAAI,aAAa,EAAE,CAAC;YAChD,SAAS,EAAE,CAAC;QAChB,CAAC;QAED,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACtB,UAAU,EAAE,CAAC;QACjB,CAAC;QAED,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,IAAI,EAAE;YAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QACrD,qFAAqF;IACzF,CAAC;IAED,IAAI,CAAC,UAAU,CAAC,CAAC;IACjB,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC;AACrC,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,qBAAqB,CACjC,GAA0B,EAC1B,KAAqB;IAErB,MAAM,OAAO,GAAI,GAAG,CAAC,SAAS,GAAI,CAAC,CAAC;IACpC,MAAM,QAAQ,GAAG,GAAG,CAAC,UAAU,GAAG,CAAC,CAAC;IAEpC,IAAI,CAAC,OAAO,IAAI,CAAC,QAAQ;QAAE,OAAO,SAAS,CAAC;IAE5C,MAAM,KAAK,GAA6C,EAAE,CAAC;IAE3D,IAAI,OAAO,EAAE,CAAC;QACV,+EAA+E;QAC/E,iFAAiF;QACjF,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,GAAG,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;IACrF,CAAC;IACD,IAAI,QAAQ,EAAE,CAAC;QACX,2DAA2D;QAC3D,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC5D,MAAM,QAAQ,GAAM,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACtE,OAAO,UAAU,CAAC,CAAC,QAAQ,GAAG,WAAW,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3D,CAAC"}
@@ -5,8 +5,29 @@ export type VerifyScreenshots = {
5
5
  impl: string | null;
6
6
  diff: string | null;
7
7
  };
8
+ export type StructureExpectations = {
9
+ /** Number of text-type leaf slots detected in the Figma renderTree. */
10
+ textSlots: number;
11
+ /** Number of image-fill slots detected in the Figma renderTree. */
12
+ imageSlots: number;
13
+ };
14
+ export type StructureFound = {
15
+ /** Non-empty leaf text elements in the rendered DOM. */
16
+ textNodes: number;
17
+ /** <img> elements + elements with a background-image CSS value. */
18
+ imageElements: number;
19
+ };
8
20
  export type PixelMatchResult = {
21
+ /** Full-frame raw pixel match score (0–1, 1 = identical). */
9
22
  score: number;
23
+ /**
24
+ * Score computed only over non-raster regions — excludes high-variance patches
25
+ * (detected photographic images) that are expected to differ (placeholder vs real asset).
26
+ * Present only when at least one raster patch was detected.
27
+ */
28
+ contentScore?: number;
29
+ /** Fraction of total pixels identified as raster image regions (0–1). */
30
+ rasterPixelRatio?: number;
10
31
  diffPixels: number;
11
32
  totalPixels: number;
12
33
  };
@@ -34,5 +55,16 @@ export type VerifyReport = {
34
55
  resolvedStoryId?: string;
35
56
  /** Human-readable error when resolved=false. */
36
57
  error?: string;
58
+ /**
59
+ * Structural slot presence score (0–1). Measures whether the expected number
60
+ * of text and image regions from the Figma renderTree are rendered in the DOM —
61
+ * independent of what text is actually shown (props are dynamic).
62
+ * Undefined for components with no trackable slots (e.g. icons).
63
+ */
64
+ structureScore?: number;
65
+ /** Slot counts extracted from the Figma renderTree. */
66
+ structureExpectations?: StructureExpectations;
67
+ /** Slot counts found in the rendered Storybook DOM. */
68
+ structureFound?: StructureFound;
37
69
  };
38
70
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/verify/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG;IAC5B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,yFAAyF;IACzF,WAAW,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAAC;IACzC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,YAAY,EAAE,CAAC;IAC5B,iBAAiB,EAAE,SAAS,GAAG,mBAAmB,GAAG,yBAAyB,CAAC;CAClF,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,EAAE,iBAAiB,CAAC;IAC/B,UAAU,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACpC,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9B,qFAAqF;IACrF,QAAQ,EAAE,OAAO,CAAC;IAClB,gGAAgG;IAChG,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/verify/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG;IAC5B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,yFAAyF;IACzF,WAAW,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAAC;IACzC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAChC,uEAAuE;IACvE,SAAS,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,UAAU,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IACzB,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,aAAa,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC3B,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,YAAY,EAAE,CAAC;IAC5B,iBAAiB,EAAE,SAAS,GAAG,mBAAmB,GAAG,yBAAyB,CAAC;CAClF,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,EAAE,iBAAiB,CAAC;IAC/B,UAAU,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACpC,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9B,qFAAqF;IACrF,QAAQ,EAAE,OAAO,CAAC;IAClB,gGAAgG;IAChG,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uDAAuD;IACvD,qBAAqB,CAAC,EAAE,qBAAqB,CAAC;IAC9C,uDAAuD;IACvD,cAAc,CAAC,EAAE,cAAc,CAAC;CACnC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@calibrate-ds/core",
3
- "version": "0.1.40",
3
+ "version": "0.1.42",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -27,8 +27,8 @@
27
27
  "pixelmatch": "^6.0.0",
28
28
  "pngjs": "^7.0.0",
29
29
  "zod": "^4.3.6",
30
- "@calibrate-ds/shared-types": "^0.1.40",
31
- "@calibrate-ds/figma-client": "^0.1.40"
30
+ "@calibrate-ds/shared-types": "^0.1.42",
31
+ "@calibrate-ds/figma-client": "^0.1.42"
32
32
  },
33
33
  "scripts": {
34
34
  "build": "tsc -p tsconfig.json",