@juxtapose/core 0.4.0 → 0.5.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.
Files changed (131) hide show
  1. package/dist/agent/handoff.d.ts +8 -1
  2. package/dist/agent/handoff.js +75 -7
  3. package/dist/agent/handoff.js.map +1 -1
  4. package/dist/analysis/affected.d.ts +37 -0
  5. package/dist/analysis/affected.js +97 -22
  6. package/dist/analysis/affected.js.map +1 -1
  7. package/dist/analysis/cause.d.ts +32 -0
  8. package/dist/analysis/cause.js +187 -0
  9. package/dist/analysis/cause.js.map +1 -0
  10. package/dist/baseline/approve.d.ts +24 -0
  11. package/dist/baseline/approve.js +54 -0
  12. package/dist/baseline/approve.js.map +1 -0
  13. package/dist/baseline/git-store.d.ts +4 -0
  14. package/dist/baseline/git-store.js +22 -0
  15. package/dist/baseline/git-store.js.map +1 -1
  16. package/dist/browser/acquire.d.ts +11 -0
  17. package/dist/browser/acquire.js +15 -0
  18. package/dist/browser/acquire.js.map +1 -0
  19. package/dist/browser/browser.d.ts +53 -0
  20. package/dist/browser/browser.js +122 -0
  21. package/dist/browser/browser.js.map +1 -0
  22. package/dist/browser/cdp.d.ts +81 -0
  23. package/dist/browser/cdp.js +230 -0
  24. package/dist/browser/cdp.js.map +1 -0
  25. package/dist/browser/index.d.ts +9 -0
  26. package/dist/browser/index.js +10 -0
  27. package/dist/browser/index.js.map +1 -0
  28. package/dist/browser/install.d.ts +33 -0
  29. package/dist/browser/install.js +167 -0
  30. package/dist/browser/install.js.map +1 -0
  31. package/dist/browser/launch.d.ts +37 -0
  32. package/dist/browser/launch.js +265 -0
  33. package/dist/browser/launch.js.map +1 -0
  34. package/dist/browser/page.d.ts +125 -0
  35. package/dist/browser/page.js +564 -0
  36. package/dist/browser/page.js.map +1 -0
  37. package/dist/browser/pins.d.ts +12 -0
  38. package/dist/browser/pins.js +57 -0
  39. package/dist/browser/pins.js.map +1 -0
  40. package/dist/browser/resolve.d.ts +25 -0
  41. package/dist/browser/resolve.js +115 -0
  42. package/dist/browser/resolve.js.map +1 -0
  43. package/dist/browser/selectors.d.ts +10 -0
  44. package/dist/browser/selectors.js +60 -0
  45. package/dist/browser/selectors.js.map +1 -0
  46. package/dist/browser/transport.d.ts +39 -0
  47. package/dist/browser/transport.js +99 -0
  48. package/dist/browser/transport.js.map +1 -0
  49. package/dist/browser/zip.d.ts +27 -0
  50. package/dist/browser/zip.js +241 -0
  51. package/dist/browser/zip.js.map +1 -0
  52. package/dist/capture/capture.d.ts +7 -1
  53. package/dist/capture/capture.js +25 -8
  54. package/dist/capture/capture.js.map +1 -1
  55. package/dist/capture/env.d.ts +1 -1
  56. package/dist/capture/launch.d.ts +19 -1
  57. package/dist/capture/launch.js +91 -1
  58. package/dist/capture/launch.js.map +1 -1
  59. package/dist/capture/pool.d.ts +1 -1
  60. package/dist/capture/pool.js +41 -8
  61. package/dist/capture/pool.js.map +1 -1
  62. package/dist/capture/settle.d.ts +1 -1
  63. package/dist/capture/settle.js +2 -0
  64. package/dist/capture/settle.js.map +1 -1
  65. package/dist/capture/snap.d.ts +43 -0
  66. package/dist/capture/snap.js +103 -0
  67. package/dist/capture/snap.js.map +1 -0
  68. package/dist/capture/structure.d.ts +77 -0
  69. package/dist/capture/structure.js +498 -0
  70. package/dist/capture/structure.js.map +1 -0
  71. package/dist/diff/compare.d.ts +19 -0
  72. package/dist/diff/compare.js +19 -0
  73. package/dist/diff/compare.js.map +1 -0
  74. package/dist/diff/crops.d.ts +26 -0
  75. package/dist/diff/crops.js +92 -0
  76. package/dist/diff/crops.js.map +1 -0
  77. package/dist/diff/structural/classify.d.ts +29 -0
  78. package/dist/diff/structural/classify.js +113 -0
  79. package/dist/diff/structural/classify.js.map +1 -0
  80. package/dist/diff/structural/coverage.d.ts +11 -0
  81. package/dist/diff/structural/coverage.js +37 -0
  82. package/dist/diff/structural/coverage.js.map +1 -0
  83. package/dist/diff/structural/deltas.d.ts +29 -0
  84. package/dist/diff/structural/deltas.js +218 -0
  85. package/dist/diff/structural/deltas.js.map +1 -0
  86. package/dist/diff/structural/disambiguate.d.ts +3 -0
  87. package/dist/diff/structural/disambiguate.js +89 -0
  88. package/dist/diff/structural/disambiguate.js.map +1 -0
  89. package/dist/diff/structural/label.d.ts +15 -0
  90. package/dist/diff/structural/label.js +64 -0
  91. package/dist/diff/structural/label.js.map +1 -0
  92. package/dist/diff/structural/match.d.ts +13 -0
  93. package/dist/diff/structural/match.js +135 -0
  94. package/dist/diff/structural/match.js.map +1 -0
  95. package/dist/diff/structural/shift.d.ts +2 -0
  96. package/dist/diff/structural/shift.js +144 -0
  97. package/dist/diff/structural/shift.js.map +1 -0
  98. package/dist/diff/structural/summary.d.ts +31 -0
  99. package/dist/diff/structural/summary.js +420 -0
  100. package/dist/diff/structural/summary.js.map +1 -0
  101. package/dist/diff/structural.d.ts +40 -0
  102. package/dist/diff/structural.js +219 -0
  103. package/dist/diff/structural.js.map +1 -0
  104. package/dist/index.d.ts +25 -3
  105. package/dist/index.js +29 -2
  106. package/dist/index.js.map +1 -1
  107. package/dist/platform.d.ts +1 -1
  108. package/dist/platforms/urls.d.ts +3 -0
  109. package/dist/platforms/urls.js +89 -0
  110. package/dist/platforms/urls.js.map +1 -0
  111. package/dist/report/comment.js +9 -3
  112. package/dist/report/comment.js.map +1 -1
  113. package/dist/report/format.d.ts +18 -0
  114. package/dist/report/format.js +20 -0
  115. package/dist/report/format.js.map +1 -1
  116. package/dist/report/html.js +2 -2
  117. package/dist/report/html.js.map +1 -1
  118. package/dist/run/groups.d.ts +2 -0
  119. package/dist/run/groups.js +45 -0
  120. package/dist/run/groups.js.map +1 -0
  121. package/dist/run/run.d.ts +6 -2
  122. package/dist/run/run.js +74 -6
  123. package/dist/run/run.js.map +1 -1
  124. package/dist/shell-quote.d.ts +2 -0
  125. package/dist/shell-quote.js +10 -0
  126. package/dist/shell-quote.js.map +1 -0
  127. package/dist/types.d.ts +199 -1
  128. package/dist/url-platform.d.ts +2 -2
  129. package/dist/url-platform.js +2 -2
  130. package/dist/url-platform.js.map +1 -1
  131. package/package.json +5 -10
@@ -0,0 +1,420 @@
1
+ // Deterministic prose. No model, no adjectives: the classification, the
2
+ // changes that caused it, and whether they account for the pixels. 300 chars,
3
+ // met by construction: labels and values are capped, the tail is reserved
4
+ // first, and each clause has shorter forms down to `el prop changed`, so the
5
+ // hard cut at the end is a backstop no input reaches.
6
+ //
7
+ // The summary is the line an agent reads first, so it leads with causes
8
+ // (text, attr, style, added, removed) and only then consequences (shift,
9
+ // resize, move). Fact order is document order, which puts `main resized` —
10
+ // a consequence of every reflow — first; read as-is, five of the 18 corpus
11
+ // summaries opened with it and the actual change came second or third.
12
+ import { selfPaintingAt } from './classify.js';
13
+ import { clip, label } from './label.js';
14
+ export const MAX_SUMMARY = 300;
15
+ /** `change`: the summary's lead clauses without the per-story tail. */
16
+ export const MAX_CHANGE = 160;
17
+ const CHANGE_ITEMS = 2;
18
+ const LEAD_ITEMS = 3;
19
+ /** Changes listed in one element's clause; the rest join "(+N more)". */
20
+ const CLAUSE_CHANGES = 3;
21
+ /** Longest value shown in prose. Not deltas.ts's MAX_VALUE (200), which caps
22
+ * what the JSON stores; this caps what a sentence repeats of it. */
23
+ const MAX_SHOWN_VALUE = 40;
24
+ export function describeDelta(d) {
25
+ switch (d.kind) {
26
+ case 'text':
27
+ case 'style':
28
+ case 'attr':
29
+ return `${d.el} ${change(d)}`;
30
+ case 'added':
31
+ return `added ${d.el} (${d.rect.w}×${d.rect.h} at ${d.rect.x},${d.rect.y})`;
32
+ case 'removed':
33
+ return `removed ${d.el} (${d.rect.w}×${d.rect.h} at ${d.rect.x},${d.rect.y})`;
34
+ case 'moved':
35
+ return `${d.el} moved ${direction(d.dx, d.dy)}`;
36
+ case 'resized':
37
+ return `${d.el} resized ${extent(d.dw, d.dh)}`;
38
+ case 'shift':
39
+ return `${d.count} elements after ${d.after} moved ${direction(d.dx, d.dy)}`;
40
+ }
41
+ }
42
+ /** The deltas as indented display lines for a human, grouped by element:
43
+ * the element's content changes (four-side longhands collapsed), then its
44
+ * resize and move on one line. Groups run causes first — content, added and
45
+ * removed, and a move a shift is blamed on; then shifts; then other moves;
46
+ * then resizes, so an ancestor's consequential `resized` comes last. Every
47
+ * delta passed in is stated on some line; `total` is the verdict's
48
+ * `deltaCount`, which says whether `deltas` is the whole set. */
49
+ export function describeDeltas(deltas, total = deltas.length) {
50
+ const ctx = context(deltas, total);
51
+ const lines = [];
52
+ const ordered = groupByElement(deltas)
53
+ .map((g, i) => ({ g, i, rank: groupRank(g, ctx) }))
54
+ .sort((a, b) => a.rank - b.rank || a.i - b.i);
55
+ for (const { g } of ordered) {
56
+ if (g.solo !== undefined) {
57
+ lines.push(` ${describe(g.solo, ctx)}`);
58
+ continue;
59
+ }
60
+ const effects = [
61
+ g.resized && `resized ${extent(g.resized.dw, g.resized.dh)}`,
62
+ g.moved && `moved ${direction(g.moved.dx, g.moved.dy)}`,
63
+ ].filter((x) => typeof x === 'string');
64
+ const own = [
65
+ ...shorthand(g.content, ' → ').map((p) => p.text),
66
+ ...(effects.length ? [effects.join(', ')] : []),
67
+ ];
68
+ if (own.length === 1)
69
+ lines.push(` ${g.el} ${own[0]}`);
70
+ else {
71
+ lines.push(` ${g.el}`);
72
+ for (const l of own)
73
+ lines.push(` ${l}`);
74
+ }
75
+ }
76
+ return lines;
77
+ }
78
+ /** Facts about one element are adjacent in `deltas` (they sort by element
79
+ * position first) and, since `disambiguate`, distinct elements never share
80
+ * a label — so an element is a run of one label, not every delta with that
81
+ * label. The run also splits when a kind or property repeats, which only an
82
+ * older verdict with colliding labels can produce: two elements, never one
83
+ * element stating `background-color` twice. */
84
+ function groupByElement(deltas) {
85
+ const groups = [];
86
+ let open;
87
+ for (const d of deltas) {
88
+ if (d.kind === 'added' || d.kind === 'removed' || d.kind === 'shift') {
89
+ groups.push({ content: [], solo: d });
90
+ open = undefined;
91
+ continue;
92
+ }
93
+ const fact = d.kind === 'style'
94
+ ? `style:${d.prop}`
95
+ : d.kind === 'attr'
96
+ ? `attr:${d.attr}`
97
+ : d.kind;
98
+ if (!open || open.g.el !== d.el || open.seen.has(fact)) {
99
+ open = { g: { el: d.el, content: [] }, seen: new Set() };
100
+ groups.push(open.g);
101
+ }
102
+ open.seen.add(fact);
103
+ if (d.kind === 'moved')
104
+ open.g.moved = d;
105
+ else if (d.kind === 'resized')
106
+ open.g.resized = d;
107
+ else
108
+ open.g.content.push(d);
109
+ }
110
+ return groups;
111
+ }
112
+ const disp = (d) => `${d.dx},${d.dy}`;
113
+ function context(deltas, total) {
114
+ const anchors = new Set();
115
+ const displacements = new Map();
116
+ // An element with its own content change is the cause through that change
117
+ // (padding grew); its move is a consequence like any other.
118
+ const changed = new Set(deltas
119
+ .filter((d) => d.kind === 'text' || d.kind === 'style' || d.kind === 'attr')
120
+ .map((d) => d.el));
121
+ for (const d of deltas) {
122
+ if (d.kind === 'shift' && !changed.has(d.after))
123
+ anchors.add(d.after);
124
+ if (d.kind === 'shift' || d.kind === 'moved')
125
+ displacements.set(disp(d), (displacements.get(disp(d)) ?? 0) + 1);
126
+ }
127
+ const still = total === deltas.length &&
128
+ !deltas.some((d) => d.kind === 'shift' || d.kind === 'moved' || d.kind === 'resized');
129
+ return { anchors, displacements, still };
130
+ }
131
+ /** A move a shift names as its cause (a reordered item) reads with the
132
+ * causes; a move with a displacement nothing else shares reads before ones
133
+ * that are part of a crowd. */
134
+ function moveRank(d, ctx) {
135
+ if (ctx.anchors.has(d.el))
136
+ return 0.5;
137
+ return (ctx.displacements.get(disp(d)) ?? 0) > 1 ? 3.5 : 3;
138
+ }
139
+ function groupRank(g, ctx) {
140
+ if (g.solo)
141
+ return g.solo.kind === 'shift' ? 1 : 0;
142
+ if (g.content.length)
143
+ return 0;
144
+ // 0.5 (blamed by a shift), else 2 or 2.5: after shifts, before resizes.
145
+ if (g.moved) {
146
+ const r = moveRank(g.moved, ctx);
147
+ return r === 0.5 ? r : r - 1;
148
+ }
149
+ return 4;
150
+ }
151
+ /** `describeDelta`, except that a removal with nothing moving or resizing
152
+ * around it may not be a removal: the capture drops `visibility: hidden`
153
+ * boxes, which leave their space behind. `display: none` and a real removal
154
+ * reflow what follows; this does not. The JSON `kind` stays `removed` —
155
+ * that is what the structure says — only the prose hedges. */
156
+ function describe(d, ctx) {
157
+ if (d.kind === 'removed' && ctx.still)
158
+ return `hidden or removed ${d.el} (${d.rect.w}×${d.rect.h} at ${d.rect.x},${d.rect.y})`;
159
+ return describeDelta(d);
160
+ }
161
+ /** `prop from→to`, without the element. */
162
+ function change(d, arrow = '→') {
163
+ if (d.kind === 'text')
164
+ return `text "${trim(d.from)}"${arrow}"${trim(d.to)}"`;
165
+ return `${changedName(d)} ${value(d.from)}${arrow}${value(d.to)}`;
166
+ }
167
+ const changedName = (d) => d.kind === 'style' ? d.prop : d.kind === 'attr' ? d.attr : 'text';
168
+ const headOf = (a) => a.styleTags.length > 0
169
+ ? `${a.classification} (${a.styleTags.join(', ')})`
170
+ : a.classification;
171
+ /** The change alone, for naming what several stories share: the summary's
172
+ * own clause wording with every element reduced to its role|tag (the
173
+ * caller passes `deltas` already abstracted), no coverage or tolerance
174
+ * tail, at most two clauses. */
175
+ export function buildChange(a) {
176
+ return clip(lead(headOf(a), a, [], MAX_CHANGE, CHANGE_ITEMS), MAX_CHANGE);
177
+ }
178
+ export function buildSummary(a) {
179
+ const head = headOf(a);
180
+ const subThreshold = a.flags.includes('sub-threshold');
181
+ const missing = a.flags.includes('no-baseline-structure')
182
+ ? 'baseline'
183
+ : a.flags.includes('no-current-structure')
184
+ ? 'current'
185
+ : undefined;
186
+ const tail = [];
187
+ const trunc = [a.baseline, a.current].find((s) => s?.truncated)?.truncated;
188
+ if (trunc)
189
+ tail.push(`Structure truncated (${trunc.kept}/${trunc.total} elements)`);
190
+ let body;
191
+ if (a.classification === 'identical') {
192
+ body = missing
193
+ ? `identical: images byte-identical; no ${missing} structure to compare`
194
+ : 'identical: images byte-identical, no structural change';
195
+ }
196
+ else if (a.classification === 'dimension-change') {
197
+ // Regions do not exist across sizes, so there is no region tail here.
198
+ const b = a.baseline && size(a.baseline);
199
+ const c = a.current && size(a.current);
200
+ body =
201
+ b && c && b !== c
202
+ ? `${head}: ${b} → ${c}; compare at one viewport`
203
+ : b && c
204
+ ? `${head}: image dimensions differ at the same ${b} viewport`
205
+ : `${head}: image dimensions differ; no ${missing} structure to name the sizes`;
206
+ }
207
+ else if (missing) {
208
+ body = `${head}: no ${missing} structure, so nothing explains the pixels; re-snap (or re-approve) with structure capture enabled`;
209
+ tail.unshift(subThreshold
210
+ ? 'Pixel diff below tolerance'
211
+ : `${a.regionCount} changed region${a.regionCount === 1 ? '' : 's'}`);
212
+ }
213
+ else if (a.deltas.length === 0) {
214
+ const painter = a.current && selfPaintingAt(a.current, a.unexplainedRegions);
215
+ body = painter
216
+ ? `${head}: structure and styles identical; the change is inside ${label(painter)}, which paints its own pixels`
217
+ : subThreshold
218
+ ? `${head}: structure and styles identical; pixels differ below the diff's tolerance`
219
+ : `${head}: structure and styles identical, pixels differ`;
220
+ if (!subThreshold)
221
+ tail.unshift(regions(a));
222
+ }
223
+ else {
224
+ tail.unshift(subThreshold
225
+ ? 'Pixel diff below tolerance; structure explains it'
226
+ : a.imagesIdentical
227
+ ? 'Images byte-identical: the change paints nothing at this viewport'
228
+ : regions(a));
229
+ body = lead(head, a, tail);
230
+ }
231
+ const out = [body, ...tail].join('. ') + '.';
232
+ return clip(out, MAX_SUMMARY);
233
+ }
234
+ /** Up to LEAD_ITEMS clauses, causes first. Each clause takes the richest
235
+ * form that fits beside the reserved tail — a clause cut mid-value would
236
+ * misstate the change — and whatever is left over is counted in
237
+ * "(+N more)". */
238
+ function lead(head, a, tail, max = MAX_SUMMARY, items = LEAD_ITEMS) {
239
+ const budget = max - tail.reduce((n, t) => n + t.length + 2, 0) - 1;
240
+ const render = (texts, more) => `${head}: ${texts.join('; ')}${more > 0 ? ` (+${more} more)` : ''}`;
241
+ const shown = [];
242
+ let used = 0;
243
+ for (const item of leadItems(a.deltas, a.deltaCount).slice(0, items)) {
244
+ const fit = item.find((o) => render([...shown, o.text], a.deltaCount - used - o.consumed).length <= budget) ?? (shown.length === 0 ? item.at(-1) : undefined);
245
+ if (!fit)
246
+ break;
247
+ shown.push(fit.text);
248
+ used += fit.consumed;
249
+ }
250
+ return render(shown, a.deltaCount - used);
251
+ }
252
+ /** Causes before consequences; within a rank, fact (document) order. A
253
+ * move is ranked by `moveRank`. */
254
+ const CAUSE_RANK = {
255
+ removed: 0,
256
+ added: 0,
257
+ text: 0,
258
+ attr: 0,
259
+ style: 0,
260
+ shift: 1,
261
+ resized: 2,
262
+ moved: 3,
263
+ };
264
+ function leadItems(deltas, total) {
265
+ const ctx = context(deltas, total);
266
+ const rank = (d) => (d.kind === 'moved' ? moveRank(d, ctx) : CAUSE_RANK[d.kind]);
267
+ // Content changes on one element read as one clause: `el a→b, c→d`; its
268
+ // resize and move stay separate clauses, ranked as consequences.
269
+ const items = [];
270
+ for (const g of groupByElement(deltas)) {
271
+ const i = items.length;
272
+ if (g.solo) {
273
+ items.push({
274
+ rank: rank(g.solo),
275
+ i,
276
+ item: [{ text: describe(g.solo, ctx), consumed: 1 }],
277
+ });
278
+ continue;
279
+ }
280
+ if (g.content.length)
281
+ items.push({ rank: 0, i, item: contentForms(g.el, g.content) });
282
+ for (const d of [g.resized, g.moved])
283
+ if (d)
284
+ items.push({
285
+ rank: rank(d),
286
+ i: items.length,
287
+ item: [{ text: describeDelta(d), consumed: 1 }],
288
+ });
289
+ }
290
+ return items.sort((x, y) => x.rank - y.rank || x.i - y.i).map((x) => x.item);
291
+ }
292
+ function contentForms(el, content) {
293
+ const parts = shorthand(content);
294
+ const forms = [];
295
+ for (let k = Math.min(CLAUSE_CHANGES, parts.length); k >= 1; k--) {
296
+ const some = parts.slice(0, k);
297
+ forms.push({
298
+ text: `${el} ${some.map((p) => p.text).join(', ')}`,
299
+ consumed: some.reduce((n, p) => n + p.consumed, 0),
300
+ });
301
+ }
302
+ forms.push({ text: `${el} ${parts[0].name} changed`, consumed: parts[0].consumed });
303
+ return forms;
304
+ }
305
+ /** CSS box properties whose four longhands collapse to one shorthand, in the
306
+ * shorthand's own value order (top, right, bottom, left / corners clockwise
307
+ * from top-left). */
308
+ const BOXES = [
309
+ ['padding', ['padding-top', 'padding-right', 'padding-bottom', 'padding-left']],
310
+ ['margin', ['margin-top', 'margin-right', 'margin-bottom', 'margin-left']],
311
+ [
312
+ 'border-width',
313
+ [
314
+ 'border-top-width',
315
+ 'border-right-width',
316
+ 'border-bottom-width',
317
+ 'border-left-width',
318
+ ],
319
+ ],
320
+ [
321
+ 'border-color',
322
+ [
323
+ 'border-top-color',
324
+ 'border-right-color',
325
+ 'border-bottom-color',
326
+ 'border-left-color',
327
+ ],
328
+ ],
329
+ [
330
+ 'border-radius',
331
+ [
332
+ 'border-top-left-radius',
333
+ 'border-top-right-radius',
334
+ 'border-bottom-right-radius',
335
+ 'border-bottom-left-radius',
336
+ ],
337
+ ],
338
+ ];
339
+ /** One element's changes as `prop from→to` strings; when all four longhands
340
+ * of a box changed, they read as the shorthand (`padding 8px 12px→12px
341
+ * 16px`), placed where the first of them was. */
342
+ function shorthand(changes, arrow = '→') {
343
+ const style = new Map();
344
+ for (const c of changes)
345
+ if (c.kind === 'style')
346
+ style.set(c.prop, c);
347
+ const collapsed = new Map(); // first longhand seen → clause
348
+ const absorbed = new Set();
349
+ for (const [name, sides] of BOXES) {
350
+ const ds = sides.map((p) => style.get(p));
351
+ if (ds.some((d) => d === undefined))
352
+ continue;
353
+ const four = ds;
354
+ const first = changes.find((c) => c.kind === 'style' && sides.includes(c.prop));
355
+ if (first?.kind !== 'style')
356
+ continue;
357
+ collapsed.set(first.prop, {
358
+ name,
359
+ text: `${name} ${value(boxValue(four.map((d) => d.from)))}${arrow}${value(boxValue(four.map((d) => d.to)))}`,
360
+ consumed: 4,
361
+ });
362
+ for (const p of sides)
363
+ absorbed.add(p);
364
+ }
365
+ const out = [];
366
+ for (const c of changes) {
367
+ const box = c.kind === 'style' ? collapsed.get(c.prop) : undefined;
368
+ if (box)
369
+ out.push(box);
370
+ else if (c.kind !== 'style' || !absorbed.has(c.prop))
371
+ out.push({ name: changedName(c), text: change(c, arrow), consumed: 1 });
372
+ }
373
+ return out;
374
+ }
375
+ /** CSS shorthand value compression: `a a a a` → `a`, `a b a b` → `a b`,
376
+ * `a b c b` → `a b c`. */
377
+ function boxValue([t, r, b, l]) {
378
+ if (r === l) {
379
+ if (t === b)
380
+ return t === r ? t : `${t} ${r}`;
381
+ return `${t} ${r} ${b}`;
382
+ }
383
+ return `${t} ${r} ${b} ${l}`;
384
+ }
385
+ /** How many changed regions the structure accounts for, by count. */
386
+ function regions(a) {
387
+ const n = a.regionCount;
388
+ const u = a.unexplainedRegions.length;
389
+ const the = n === 1
390
+ ? 'the changed region'
391
+ : n === 2
392
+ ? 'both changed regions'
393
+ : `all ${n} changed regions`;
394
+ if (u === 0)
395
+ return `Structure explains ${the}`;
396
+ if (u === n)
397
+ return n === 1
398
+ ? 'Nothing in the structure explains the changed region'
399
+ : n === 2
400
+ ? 'Nothing in the structure explains either changed region'
401
+ : `Nothing in the structure explains the ${n} changed regions`;
402
+ return `${u} of ${n} changed regions unexplained`;
403
+ }
404
+ const size = (s) => `${s.viewport.width}×${s.viewport.height}`;
405
+ const signed = (n) => (n > 0 ? `+${n}` : `${n}`);
406
+ const trim = (s) => clip(s, MAX_SHOWN_VALUE);
407
+ /** Opaque `rgb(r, g, b)` as `#rrggbb`: a third the length, and the form a
408
+ * developer greps their stylesheet for. Alpha colours stay as they are. */
409
+ const value = (s) => trim(s.replace(/rgb\((\d+), (\d+), (\d+)\)/g, (_, r, g, b) => [r, g, b].reduce((hex, c) => hex + Number(c).toString(16).padStart(2, '0'), '#')));
410
+ const direction = (dx, dy) => dx === 0
411
+ ? `${dy > 0 ? 'down' : 'up'} ${Math.abs(dy)}px`
412
+ : dy === 0
413
+ ? `${dx > 0 ? 'right' : 'left'} ${Math.abs(dx)}px`
414
+ : `${signed(dx)},${signed(dy)}px`;
415
+ const extent = (dw, dh) => dw === 0
416
+ ? `height ${signed(dh)}px`
417
+ : dh === 0
418
+ ? `width ${signed(dw)}px`
419
+ : `${signed(dw)}×${signed(dh)}px`;
420
+ //# sourceMappingURL=summary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summary.js","sourceRoot":"","sources":["../../../src/diff/structural/summary.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import type { DiffOutput } from './diff.js';
2
+ import type { Cause, ChangedRegion, StructureSnapshot, StructuralVerdict } from '../types.js';
3
+ export interface StructuralDiffInput {
4
+ baseline?: StructureSnapshot;
5
+ current?: StructureSnapshot;
6
+ /** The two encoded images are byte-identical (equal hashes). Only this
7
+ * makes a verdict `identical`: a pixel diff with 0 mismatches can still
8
+ * hide a real change below its tolerance. It implies no changed regions
9
+ * and no dimension mismatch; if `pixels` contradicts it, the pixel
10
+ * evidence wins and the verdict is not `identical`. */
11
+ imagesIdentical: boolean;
12
+ pixels: Pick<DiffOutput, 'changedRegions' | 'dimensionMismatch'>;
13
+ /** The exact tier-3 command; core does not know how the CLI is spelled. */
14
+ escalate: {
15
+ command: string;
16
+ };
17
+ /** From `jux run --since`; `jux diff` has no changed-file set. */
18
+ cause?: Cause;
19
+ }
20
+ export declare const MAX_DELTAS = 20;
21
+ /** JSON.stringify(verdict).length never exceeds this. */
22
+ export declare const MAX_VERDICT = 1500;
23
+ /** `cause.files` is capped here as well as in the index: the budget is a
24
+ * guarantee for any input. */
25
+ export declare const MAX_CAUSE_FILES = 5;
26
+ /** Longest `cause.files[].path`. The tail is kept: the file name is what a
27
+ * reader greps for; a 10-deep monorepo prefix is not. */
28
+ export declare const MAX_CAUSE_PATH = 80;
29
+ /** The verdict plus every unexplained region: the verdict's own list is the
30
+ * prefix that fits the budget, and crops must order and label from the whole. */
31
+ export declare function structuralDiffWithCoverage(input: StructuralDiffInput): {
32
+ verdict: StructuralVerdict;
33
+ unexplainedRegions: ChangedRegion[];
34
+ /** One box per element the deltas name, in delta order: the union of its
35
+ * old and new rects, rounded outward to whole px. What `--crops` shows
36
+ * when the pixel diff marked nothing (sub-threshold). */
37
+ elementRegions: ChangedRegion[];
38
+ };
39
+ /** The verdict alone; what every caller but `--crops` wants. */
40
+ export declare function structuralDiff(input: StructuralDiffInput): StructuralVerdict;