@juxtapose/core 0.2.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.
- package/dist/agent/handoff.d.ts +8 -1
- package/dist/agent/handoff.js +75 -7
- package/dist/agent/handoff.js.map +1 -1
- package/dist/analysis/affected.d.ts +58 -0
- package/dist/analysis/affected.js +134 -22
- package/dist/analysis/affected.js.map +1 -1
- package/dist/analysis/cause.d.ts +32 -0
- package/dist/analysis/cause.js +187 -0
- package/dist/analysis/cause.js.map +1 -0
- package/dist/baseline/approve.d.ts +24 -0
- package/dist/baseline/approve.js +54 -0
- package/dist/baseline/approve.js.map +1 -0
- package/dist/baseline/git-store.d.ts +4 -0
- package/dist/baseline/git-store.js +22 -0
- package/dist/baseline/git-store.js.map +1 -1
- package/dist/browser/acquire.d.ts +11 -0
- package/dist/browser/acquire.js +15 -0
- package/dist/browser/acquire.js.map +1 -0
- package/dist/browser/browser.d.ts +53 -0
- package/dist/browser/browser.js +122 -0
- package/dist/browser/browser.js.map +1 -0
- package/dist/browser/cdp.d.ts +81 -0
- package/dist/browser/cdp.js +230 -0
- package/dist/browser/cdp.js.map +1 -0
- package/dist/browser/index.d.ts +9 -0
- package/dist/browser/index.js +10 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/install.d.ts +33 -0
- package/dist/browser/install.js +167 -0
- package/dist/browser/install.js.map +1 -0
- package/dist/browser/launch.d.ts +37 -0
- package/dist/browser/launch.js +265 -0
- package/dist/browser/launch.js.map +1 -0
- package/dist/browser/page.d.ts +125 -0
- package/dist/browser/page.js +564 -0
- package/dist/browser/page.js.map +1 -0
- package/dist/browser/pins.d.ts +12 -0
- package/dist/browser/pins.js +57 -0
- package/dist/browser/pins.js.map +1 -0
- package/dist/browser/resolve.d.ts +25 -0
- package/dist/browser/resolve.js +115 -0
- package/dist/browser/resolve.js.map +1 -0
- package/dist/browser/selectors.d.ts +10 -0
- package/dist/browser/selectors.js +60 -0
- package/dist/browser/selectors.js.map +1 -0
- package/dist/browser/transport.d.ts +39 -0
- package/dist/browser/transport.js +99 -0
- package/dist/browser/transport.js.map +1 -0
- package/dist/browser/zip.d.ts +27 -0
- package/dist/browser/zip.js +241 -0
- package/dist/browser/zip.js.map +1 -0
- package/dist/capture/capture.d.ts +7 -1
- package/dist/capture/capture.js +27 -3
- package/dist/capture/capture.js.map +1 -1
- package/dist/capture/env.d.ts +8 -0
- package/dist/capture/env.js +38 -0
- package/dist/capture/env.js.map +1 -0
- package/dist/capture/launch.d.ts +19 -1
- package/dist/capture/launch.js +91 -1
- package/dist/capture/launch.js.map +1 -1
- package/dist/capture/pool.d.ts +1 -1
- package/dist/capture/pool.js +41 -8
- package/dist/capture/pool.js.map +1 -1
- package/dist/capture/settle.d.ts +1 -1
- package/dist/capture/settle.js +2 -0
- package/dist/capture/settle.js.map +1 -1
- package/dist/capture/snap.d.ts +43 -0
- package/dist/capture/snap.js +103 -0
- package/dist/capture/snap.js.map +1 -0
- package/dist/capture/structure.d.ts +77 -0
- package/dist/capture/structure.js +498 -0
- package/dist/capture/structure.js.map +1 -0
- package/dist/diff/compare.d.ts +19 -0
- package/dist/diff/compare.js +19 -0
- package/dist/diff/compare.js.map +1 -0
- package/dist/diff/crops.d.ts +26 -0
- package/dist/diff/crops.js +92 -0
- package/dist/diff/crops.js.map +1 -0
- package/dist/diff/structural/classify.d.ts +29 -0
- package/dist/diff/structural/classify.js +113 -0
- package/dist/diff/structural/classify.js.map +1 -0
- package/dist/diff/structural/coverage.d.ts +11 -0
- package/dist/diff/structural/coverage.js +37 -0
- package/dist/diff/structural/coverage.js.map +1 -0
- package/dist/diff/structural/deltas.d.ts +29 -0
- package/dist/diff/structural/deltas.js +218 -0
- package/dist/diff/structural/deltas.js.map +1 -0
- package/dist/diff/structural/disambiguate.d.ts +3 -0
- package/dist/diff/structural/disambiguate.js +89 -0
- package/dist/diff/structural/disambiguate.js.map +1 -0
- package/dist/diff/structural/label.d.ts +15 -0
- package/dist/diff/structural/label.js +64 -0
- package/dist/diff/structural/label.js.map +1 -0
- package/dist/diff/structural/match.d.ts +13 -0
- package/dist/diff/structural/match.js +135 -0
- package/dist/diff/structural/match.js.map +1 -0
- package/dist/diff/structural/shift.d.ts +2 -0
- package/dist/diff/structural/shift.js +144 -0
- package/dist/diff/structural/shift.js.map +1 -0
- package/dist/diff/structural/summary.d.ts +31 -0
- package/dist/diff/structural/summary.js +420 -0
- package/dist/diff/structural/summary.js.map +1 -0
- package/dist/diff/structural.d.ts +40 -0
- package/dist/diff/structural.js +219 -0
- package/dist/diff/structural.js.map +1 -0
- package/dist/index.d.ts +34 -12
- package/dist/index.js +55 -11
- package/dist/index.js.map +1 -1
- package/dist/platform.d.ts +1 -1
- package/dist/platforms/urls.d.ts +3 -0
- package/dist/platforms/urls.js +89 -0
- package/dist/platforms/urls.js.map +1 -0
- package/dist/report/comment.d.ts +2 -1
- package/dist/report/comment.js +305 -57
- package/dist/report/comment.js.map +1 -1
- package/dist/report/format.d.ts +20 -0
- package/dist/report/format.js +32 -0
- package/dist/report/format.js.map +1 -0
- package/dist/report/github.d.ts +12 -0
- package/dist/report/github.js +21 -0
- package/dist/report/github.js.map +1 -1
- package/dist/report/html.d.ts +12 -0
- package/dist/report/html.js +202 -0
- package/dist/report/html.js.map +1 -0
- package/dist/run/groups.d.ts +2 -0
- package/dist/run/groups.js +45 -0
- package/dist/run/groups.js.map +1 -0
- package/dist/run/phases.d.ts +19 -0
- package/dist/run/phases.js +50 -0
- package/dist/run/phases.js.map +1 -0
- package/dist/run/run.d.ts +10 -2
- package/dist/run/run.js +97 -9
- package/dist/run/run.js.map +1 -1
- package/dist/shell-quote.d.ts +2 -0
- package/dist/shell-quote.js +10 -0
- package/dist/shell-quote.js.map +1 -0
- package/dist/types.d.ts +234 -3
- package/dist/url-platform.d.ts +2 -2
- package/dist/url-platform.js +2 -2
- package/dist/url-platform.js.map +1 -1
- package/package.json +14 -10
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
// Structural diff → tier-0 verdict. Pure, no browser, no I/O.
|
|
2
|
+
//
|
|
3
|
+
// Composition: match → facts → shifts → unique labels → coverage → classify → summary, then a
|
|
4
|
+
// signature over the abstracted facts. Every list is sorted by a documented
|
|
5
|
+
// key and the result is built as one literal, so the same inputs always
|
|
6
|
+
// serialize to the same bytes (the CLI promises that in its JSON contract).
|
|
7
|
+
import { createHash } from 'node:crypto';
|
|
8
|
+
import { classify, computeFlags } from './structural/classify.js';
|
|
9
|
+
import { computeCoverage } from './structural/coverage.js';
|
|
10
|
+
import { disambiguate } from './structural/disambiguate.js';
|
|
11
|
+
import { compareCodeUnits, computeFacts } from './structural/deltas.js';
|
|
12
|
+
import { matchElements } from './structural/match.js';
|
|
13
|
+
import { synthesizeShifts } from './structural/shift.js';
|
|
14
|
+
import { buildChange, buildSummary } from './structural/summary.js';
|
|
15
|
+
export const MAX_DELTAS = 20;
|
|
16
|
+
/** JSON.stringify(verdict).length never exceeds this. */
|
|
17
|
+
export const MAX_VERDICT = 1500;
|
|
18
|
+
/** `cause.files` is capped here as well as in the index: the budget is a
|
|
19
|
+
* guarantee for any input. */
|
|
20
|
+
export const MAX_CAUSE_FILES = 5;
|
|
21
|
+
/** Longest `cause.files[].path`. The tail is kept: the file name is what a
|
|
22
|
+
* reader greps for; a 10-deep monorepo prefix is not. */
|
|
23
|
+
export const MAX_CAUSE_PATH = 80;
|
|
24
|
+
/** The verdict plus every unexplained region: the verdict's own list is the
|
|
25
|
+
* prefix that fits the budget, and crops must order and label from the whole. */
|
|
26
|
+
export function structuralDiffWithCoverage(input) {
|
|
27
|
+
const { baseline, current, pixels, imagesIdentical } = input;
|
|
28
|
+
const comparable = baseline !== undefined &&
|
|
29
|
+
current !== undefined &&
|
|
30
|
+
!pixels.dimensionMismatch &&
|
|
31
|
+
baseline.viewport.width === current.viewport.width &&
|
|
32
|
+
baseline.viewport.height === current.viewport.height;
|
|
33
|
+
// With a truncated side, the elements past the cap exist but were not
|
|
34
|
+
// recorded; reporting them as removed would be a lie the summary already
|
|
35
|
+
// tells more honestly as a count.
|
|
36
|
+
// Labels are made unique last, so only elements still named after the
|
|
37
|
+
// shift collapse — the ones a reader will see — are renamed.
|
|
38
|
+
const facts = comparable
|
|
39
|
+
? disambiguate(synthesizeShifts(computeFacts(baseline, current, matchElements(baseline, current)).filter((f) => !(f.delta.kind === 'removed' && current.truncated) &&
|
|
40
|
+
!(f.delta.kind === 'added' && baseline.truncated))), baseline, current)
|
|
41
|
+
: [];
|
|
42
|
+
const cov = computeCoverage(pixels.changedRegions, facts);
|
|
43
|
+
const ctx = {
|
|
44
|
+
baseline,
|
|
45
|
+
current,
|
|
46
|
+
facts,
|
|
47
|
+
explained: cov.explained,
|
|
48
|
+
unexplainedRegions: cov.unexplainedRegions,
|
|
49
|
+
pixels: {
|
|
50
|
+
imagesIdentical,
|
|
51
|
+
dimensionMismatch: pixels.dimensionMismatch,
|
|
52
|
+
hasRegions: cov.regionCount > 0,
|
|
53
|
+
subThreshold: !imagesIdentical && !pixels.dimensionMismatch && cov.regionCount === 0,
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
const { classification, styleTags } = classify(ctx);
|
|
57
|
+
const flags = computeFlags(ctx);
|
|
58
|
+
const deltas = facts.slice(0, MAX_DELTAS).map((f) => f.delta);
|
|
59
|
+
const summary = buildSummary({
|
|
60
|
+
classification,
|
|
61
|
+
styleTags,
|
|
62
|
+
deltas,
|
|
63
|
+
deltaCount: facts.length,
|
|
64
|
+
regionCount: cov.regionCount,
|
|
65
|
+
unexplainedRegions: cov.unexplainedRegions,
|
|
66
|
+
flags,
|
|
67
|
+
imagesIdentical,
|
|
68
|
+
baseline,
|
|
69
|
+
current,
|
|
70
|
+
});
|
|
71
|
+
// The same clauses with `el` swapped for role|tag, so it reads the same on
|
|
72
|
+
// every page that made the change. Absent when there is nothing to state.
|
|
73
|
+
const change = facts.length > 0
|
|
74
|
+
? buildChange({
|
|
75
|
+
classification,
|
|
76
|
+
styleTags,
|
|
77
|
+
deltas: facts
|
|
78
|
+
.slice(0, MAX_DELTAS)
|
|
79
|
+
.map((f) => f.delta.kind === 'shift'
|
|
80
|
+
? { ...f.delta, after: f.abstract }
|
|
81
|
+
: { ...f.delta, el: f.abstract }),
|
|
82
|
+
deltaCount: facts.length,
|
|
83
|
+
regionCount: 0,
|
|
84
|
+
unexplainedRegions: [],
|
|
85
|
+
flags,
|
|
86
|
+
imagesIdentical,
|
|
87
|
+
})
|
|
88
|
+
: undefined;
|
|
89
|
+
const sig = signature(classification, facts);
|
|
90
|
+
// Fitted here, not trusted from the caller: the budget is a guarantee for
|
|
91
|
+
// any input, and the index's cap is a courtesy.
|
|
92
|
+
const cause = input.cause && fitCause(input.cause);
|
|
93
|
+
// One literal, one key order: the CLI's byte-stability rests on it.
|
|
94
|
+
const build = (ds, regions) => ({
|
|
95
|
+
schema: 'juxtapose.verdict/v1',
|
|
96
|
+
classification,
|
|
97
|
+
styleTags,
|
|
98
|
+
summary,
|
|
99
|
+
...(change ? { change } : {}),
|
|
100
|
+
deltas: ds,
|
|
101
|
+
deltaCount: facts.length,
|
|
102
|
+
coverage: cov.coverage,
|
|
103
|
+
explained: cov.explained,
|
|
104
|
+
unexplainedRegions: regions,
|
|
105
|
+
flags,
|
|
106
|
+
...(cause ? { cause } : {}),
|
|
107
|
+
signature: sig,
|
|
108
|
+
escalate: { command: input.escalate.command },
|
|
109
|
+
});
|
|
110
|
+
// The tier-0 budget is a guarantee, not a corpus statistic. Labels (60)
|
|
111
|
+
// and values (200) are capped, but one delta is still 70–400 chars, so 20
|
|
112
|
+
// of them (or a diff with hundreds of regions) would pass 1,500: one button
|
|
113
|
+
// with 10 realistic style changes measured 1,701. Each list keeps the
|
|
114
|
+
// prefix that fits — deltas first, they are the "what" — while deltaCount,
|
|
115
|
+
// coverage and explained still describe the whole. Holds for any input
|
|
116
|
+
// except an escalate command that alone exceeds the budget.
|
|
117
|
+
let room = MAX_VERDICT - JSON.stringify(build([], [])).length;
|
|
118
|
+
const fit = (items) => {
|
|
119
|
+
const out = [];
|
|
120
|
+
for (const x of items) {
|
|
121
|
+
const n = JSON.stringify(x).length + (out.length > 0 ? 1 : 0);
|
|
122
|
+
if (n > room)
|
|
123
|
+
break;
|
|
124
|
+
room -= n;
|
|
125
|
+
out.push(x);
|
|
126
|
+
}
|
|
127
|
+
return out;
|
|
128
|
+
};
|
|
129
|
+
const kept = fit(deltas);
|
|
130
|
+
return {
|
|
131
|
+
verdict: build(kept, fit(cov.unexplainedRegions)),
|
|
132
|
+
unexplainedRegions: cov.unexplainedRegions,
|
|
133
|
+
elementRegions: elementRegions(facts),
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
/** Facts are grouped by element identity (`source`), not label: two
|
|
137
|
+
* `div.card`s are two boxes. A shift carries its anchor's source but its
|
|
138
|
+
* run's rects, so it is a box of its own rather than swelling the anchor's.
|
|
139
|
+
* Zero-area unions carry no pixels and are dropped. */
|
|
140
|
+
function elementRegions(facts) {
|
|
141
|
+
const boxes = new Map();
|
|
142
|
+
for (const f of facts) {
|
|
143
|
+
const key = `${f.delta.kind === 'shift' ? 'shift:' : ''}${f.source.side}:${f.source.index}`;
|
|
144
|
+
for (const r of f.rects) {
|
|
145
|
+
const b = boxes.get(key);
|
|
146
|
+
const x0 = Math.floor(r.x);
|
|
147
|
+
const y0 = Math.floor(r.y);
|
|
148
|
+
const x1 = Math.ceil(r.x + r.w);
|
|
149
|
+
const y1 = Math.ceil(r.y + r.h);
|
|
150
|
+
boxes.set(key, b
|
|
151
|
+
? {
|
|
152
|
+
x0: Math.min(b.x0, x0),
|
|
153
|
+
y0: Math.min(b.y0, y0),
|
|
154
|
+
x1: Math.max(b.x1, x1),
|
|
155
|
+
y1: Math.max(b.y1, y1),
|
|
156
|
+
}
|
|
157
|
+
: { x0, y0, x1, y1 });
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return [...boxes.values()]
|
|
161
|
+
.map((b) => ({ x: b.x0, y: b.y0, width: b.x1 - b.x0, height: b.y1 - b.y0 }))
|
|
162
|
+
.filter((r) => r.width > 0 && r.height > 0);
|
|
163
|
+
}
|
|
164
|
+
/** The verdict alone; what every caller but `--crops` wants. */
|
|
165
|
+
export function structuralDiff(input) {
|
|
166
|
+
return structuralDiffWithCoverage(input).verdict;
|
|
167
|
+
}
|
|
168
|
+
/** sha256 of the classification, then the facts with each element reduced
|
|
169
|
+
* to role|tag and the values kept: "every button background
|
|
170
|
+
* #2563eb→#1d4ed8" hashes the same on any page that made that change. The
|
|
171
|
+
* classification leads so that verdicts with no facts — identical, a
|
|
172
|
+
* canvas redraw, a size change — do not all share one signature. Facts are
|
|
173
|
+
* sorted (by code unit) so order of discovery cannot leak in. */
|
|
174
|
+
function signature(classification, facts) {
|
|
175
|
+
const items = facts
|
|
176
|
+
.map((f) => {
|
|
177
|
+
const d = f.delta;
|
|
178
|
+
const rest = d.kind === 'text' || d.kind === 'style' || d.kind === 'attr'
|
|
179
|
+
? [
|
|
180
|
+
d.kind === 'style' ? d.prop : d.kind === 'attr' ? d.attr : 'text',
|
|
181
|
+
d.from,
|
|
182
|
+
d.to,
|
|
183
|
+
]
|
|
184
|
+
: d.kind === 'moved'
|
|
185
|
+
? ['moved', d.dx, d.dy]
|
|
186
|
+
: d.kind === 'resized'
|
|
187
|
+
? ['resized', d.dw, d.dh]
|
|
188
|
+
: d.kind === 'shift'
|
|
189
|
+
? ['shift', d.dx, d.dy, d.count]
|
|
190
|
+
: [d.kind];
|
|
191
|
+
return JSON.stringify([f.abstract, ...rest]);
|
|
192
|
+
})
|
|
193
|
+
.sort(compareCodeUnits);
|
|
194
|
+
return createHash('sha256')
|
|
195
|
+
.update([classification, ...items].join('\n'))
|
|
196
|
+
.digest('hex');
|
|
197
|
+
}
|
|
198
|
+
function fitCause(c) {
|
|
199
|
+
return {
|
|
200
|
+
kind: c.kind,
|
|
201
|
+
files: c.files.slice(0, MAX_CAUSE_FILES).map((f) => ({
|
|
202
|
+
path: clipHead(f.path, MAX_CAUSE_PATH),
|
|
203
|
+
distance: f.distance,
|
|
204
|
+
})),
|
|
205
|
+
...(c.partial ? { partial: true } : {}),
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
/** `…` plus at most the last `max - 1` code units, never starting on the
|
|
209
|
+
* low half of a surrogate pair: a lone surrogate is not valid UTF-8. */
|
|
210
|
+
function clipHead(s, max) {
|
|
211
|
+
if (s.length <= max)
|
|
212
|
+
return s;
|
|
213
|
+
let from = s.length - (max - 1);
|
|
214
|
+
const c = s.charCodeAt(from);
|
|
215
|
+
if (c >= 0xdc00 && c <= 0xdfff)
|
|
216
|
+
from++;
|
|
217
|
+
return '…' + s.slice(from);
|
|
218
|
+
}
|
|
219
|
+
//# sourceMappingURL=structural.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"structural.js","sourceRoot":"","sources":["../../src/diff/structural.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,17 +1,39 @@
|
|
|
1
|
-
export type { StoryParams, Viewport, StoryManifest, Snapshot, ChangedRegion, DiffStatus, DiffResult, RunReport, ApprovalMeta, BaselineEntry, BaselineManifest, ProjectConfig, StorageConfig, BaselineStore, } from './types.js';
|
|
1
|
+
export type { StoryParams, Viewport, StoryManifest, Snapshot, StructureSnapshot, StructureElement, StructureRect, CaptureEnv, ChangedRegion, Delta, Classification, StyleTag, Flag, StructuralVerdict, Cause, CauseKind, DiffStatus, DiffResult, RunReport, RunGroup, ApprovalMeta, BaselineEntry, BaselineManifest, ProjectConfig, UrlEntry, StorageConfig, BaselineStore, } from './types.js';
|
|
2
2
|
export type { Platform, EnumerateTarget, SettleContext } from './platform.js';
|
|
3
3
|
export { navigateToStory } from './url-platform.js';
|
|
4
|
-
export {
|
|
4
|
+
export { createUrlPlatform } from './platforms/urls.js';
|
|
5
|
+
export { waitForSelector } from './capture/settle.js';
|
|
5
6
|
export { GitBaselineStore, encodeStoryId } from './baseline/git-store.js';
|
|
7
|
+
export { hashImage } from './baseline/status.js';
|
|
8
|
+
export type { BaselineStatus, AncestryCheck } from './baseline/status.js';
|
|
6
9
|
export { createAncestryCheck, alwaysAncestor } from './git/ancestry.js';
|
|
7
|
-
export {
|
|
8
|
-
export {
|
|
9
|
-
export {
|
|
10
|
-
export {
|
|
11
|
-
export {
|
|
12
|
-
export {
|
|
13
|
-
export {
|
|
10
|
+
export { encodeStructure, decodeStructure } from './capture/structure.js';
|
|
11
|
+
export { approveCapture, readRunStructure, type RunStructure, } from './baseline/approve.js';
|
|
12
|
+
export { structuralDiff, structuralDiffWithCoverage, type StructuralDiffInput, } from './diff/structural.js';
|
|
13
|
+
export { compareSnaps, type SnapSide, type SnapComparison } from './diff/compare.js';
|
|
14
|
+
export { renderCrops, MAX_CROPS, MAX_CROP_SIDE, type Crop } from './diff/crops.js';
|
|
15
|
+
export { describeDelta, describeDeltas } from './diff/structural/summary.js';
|
|
16
|
+
export { compareCodeUnits } from './diff/structural/deltas.js';
|
|
17
|
+
export { shellQuote } from './shell-quote.js';
|
|
14
18
|
export { runCapture, DEFAULT_VIEWPORT, type RunOptions, type RunArtifact, } from './run/run.js';
|
|
15
|
-
export {
|
|
16
|
-
export {
|
|
17
|
-
export {
|
|
19
|
+
export { computeGroups } from './run/groups.js';
|
|
20
|
+
export { phases, formatPhases, type Phases } from './run/phases.js';
|
|
21
|
+
export { snapPage, snapPages, type SnapOptions, type SnapResult, type SnapPagesOptions, type SnapPageResult, } from './capture/snap.js';
|
|
22
|
+
export { deterministicLaunchOptions, type LaunchOptions } from './capture/launch.js';
|
|
23
|
+
export { chromeArgs, PARITY_CHROMIUM_ARGS } from './capture/launch.js';
|
|
24
|
+
export type { Browser, BrowserContext } from './browser/browser.js';
|
|
25
|
+
export { BrowserDiedError } from './browser/browser.js';
|
|
26
|
+
export { TargetClosedError } from './browser/cdp.js';
|
|
27
|
+
export { PageCrashedError, TimeoutError, type Page } from './browser/page.js';
|
|
28
|
+
export { acquireBrowser, type AcquireOptions } from './browser/acquire.js';
|
|
29
|
+
export { resolveChrome, juxCacheDir, noBrowserMessage, NO_BROWSER_MESSAGE, type ChromeSource, type ResolvedChrome, } from './browser/resolve.js';
|
|
30
|
+
export { installChrome, proxyReexecArgs, stderrProgress, type InstallOptions, type InstallResult, } from './browser/install.js';
|
|
31
|
+
export { CHROME_VERSION, CHROME_PINS, chromePlatform } from './browser/pins.js';
|
|
32
|
+
export { assertCssSelector } from './browser/selectors.js';
|
|
33
|
+
export { resolveAffected, resolveAffectedFromPaths, gitIsCommit, type AffectedOptions, type AffectedResult, } from './analysis/affected.js';
|
|
34
|
+
export { buildCauseIndex, prepareCause, type CauseIndex, type CauseSources, type ChangedFile, } from './analysis/cause.js';
|
|
35
|
+
export { buildHandoffPrompt, describeCause, type HandoffPayload, } from './agent/handoff.js';
|
|
36
|
+
export { buildComment, type CommentOptions } from './report/comment.js';
|
|
37
|
+
export { buildHtmlReport, type HtmlReportOptions } from './report/html.js';
|
|
38
|
+
export { formatPercent } from './report/format.js';
|
|
39
|
+
export { resolveArtifactUrl, resolveGitHubContext, postComment, type GitHubContext, } from './report/github.js';
|
package/dist/index.js
CHANGED
|
@@ -1,16 +1,60 @@
|
|
|
1
|
+
// The public surface of @juxtapose/core.
|
|
2
|
+
//
|
|
3
|
+
// Everything here is a semver commitment once this publishes, so it is chosen
|
|
4
|
+
// rather than accumulated. The settle pipeline, the diff internals and the
|
|
5
|
+
// worker pool are deliberately NOT exported: CLAUDE.md describes them as
|
|
6
|
+
// load-bearing and easy to break, and exporting them invites downstream code
|
|
7
|
+
// to pin exactly the parts that most need freedom to change.
|
|
8
|
+
//
|
|
9
|
+
// If you are writing a third-party adapter or baseline store, the types and
|
|
10
|
+
// helpers below are what you need. If something is missing for that, the seam
|
|
11
|
+
// needs widening — say so rather than reaching into the package.
|
|
1
12
|
export { navigateToStory } from './url-platform.js';
|
|
2
|
-
export {
|
|
13
|
+
export { createUrlPlatform } from './platforms/urls.js';
|
|
14
|
+
export { waitForSelector } from './capture/settle.js';
|
|
15
|
+
// Implementing a baseline store. `encodeStoryId` matters for anyone building
|
|
16
|
+
// keys from a story id — they are platform-supplied and not path-safe.
|
|
3
17
|
export { GitBaselineStore, encodeStoryId } from './baseline/git-store.js';
|
|
18
|
+
// hashImage is exported because anything comparing against a manifest entry
|
|
19
|
+
// must use the same function the manifest was written with, not its own copy.
|
|
20
|
+
export { hashImage } from './baseline/status.js';
|
|
4
21
|
export { createAncestryCheck, alwaysAncestor } from './git/ancestry.js';
|
|
5
|
-
|
|
6
|
-
export {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
export {
|
|
10
|
-
|
|
11
|
-
export {
|
|
22
|
+
// Structure sidecars: read and write the gzipped snapshot beside an image.
|
|
23
|
+
export { encodeStructure, decodeStructure } from './capture/structure.js';
|
|
24
|
+
// Approving a run capture with its sidecar: every approval path (CLI approve,
|
|
25
|
+
// init, the review server) goes through this so they cannot disagree.
|
|
26
|
+
export { approveCapture, readRunStructure, } from './baseline/approve.js';
|
|
27
|
+
// Structural diff: two sidecars + a pixel diff → the tier-0 verdict.
|
|
28
|
+
export { structuralDiff, structuralDiffWithCoverage, } from './diff/structural.js';
|
|
29
|
+
export { compareSnaps } from './diff/compare.js';
|
|
30
|
+
// Tier-3 crops: two images + regions → side-by-side PNG strips, no browser.
|
|
31
|
+
export { renderCrops, MAX_CROPS, MAX_CROP_SIDE } from './diff/crops.js';
|
|
32
|
+
export { describeDelta, describeDeltas } from './diff/structural/summary.js';
|
|
33
|
+
export { compareCodeUnits } from './diff/structural/deltas.js';
|
|
34
|
+
export { shellQuote } from './shell-quote.js';
|
|
35
|
+
// Driving a run.
|
|
12
36
|
export { runCapture, DEFAULT_VIEWPORT, } from './run/run.js';
|
|
13
|
-
export {
|
|
14
|
-
|
|
15
|
-
export {
|
|
37
|
+
export { computeGroups } from './run/groups.js';
|
|
38
|
+
// Per-phase timings, so a slow run can say which phase was slow.
|
|
39
|
+
export { phases, formatPhases } from './run/phases.js';
|
|
40
|
+
export { snapPage, snapPages, } from './capture/snap.js';
|
|
41
|
+
export { deterministicLaunchOptions } from './capture/launch.js';
|
|
42
|
+
export { chromeArgs, PARITY_CHROMIUM_ARGS } from './capture/launch.js';
|
|
43
|
+
export { BrowserDiedError } from './browser/browser.js';
|
|
44
|
+
export { TargetClosedError } from './browser/cdp.js';
|
|
45
|
+
export { PageCrashedError, TimeoutError } from './browser/page.js';
|
|
46
|
+
export { acquireBrowser } from './browser/acquire.js';
|
|
47
|
+
export { resolveChrome, juxCacheDir, noBrowserMessage, NO_BROWSER_MESSAGE, } from './browser/resolve.js';
|
|
48
|
+
export { installChrome, proxyReexecArgs, stderrProgress, } from './browser/install.js';
|
|
49
|
+
export { CHROME_VERSION, CHROME_PINS, chromePlatform } from './browser/pins.js';
|
|
50
|
+
export { assertCssSelector } from './browser/selectors.js';
|
|
51
|
+
export { resolveAffected, resolveAffectedFromPaths, gitIsCommit, } from './analysis/affected.js';
|
|
52
|
+
// Cause: the story's import closure intersected with the changed files.
|
|
53
|
+
export { buildCauseIndex, prepareCause, } from './analysis/cause.js';
|
|
54
|
+
// Reporting on one.
|
|
55
|
+
export { buildHandoffPrompt, describeCause, } from './agent/handoff.js';
|
|
56
|
+
export { buildComment } from './report/comment.js';
|
|
57
|
+
export { buildHtmlReport } from './report/html.js';
|
|
58
|
+
export { formatPercent } from './report/format.js';
|
|
59
|
+
export { resolveArtifactUrl, resolveGitHubContext, postComment, } from './report/github.js';
|
|
16
60
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/platform.d.ts
CHANGED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// The null platform: an explicit list of URLs, no workbench (issue #11).
|
|
2
|
+
//
|
|
3
|
+
// Everything a workbench adapter contributes — enumeration, a render signal,
|
|
4
|
+
// componentPath — is absent here, which is exactly what the Platform seam was
|
|
5
|
+
// designed to allow: settling falls entirely to core's generic pipeline (DOM
|
|
6
|
+
// quiescence, fonts, images, animation freeze, paint barrier), and affected
|
|
7
|
+
// analysis sees an empty componentPath and falls back to capturing everything.
|
|
8
|
+
//
|
|
9
|
+
// Lives in core rather than its own adapter package because it has no
|
|
10
|
+
// knowledge of any workbench and `jux snap` must always have it.
|
|
11
|
+
export function createUrlPlatform(urls) {
|
|
12
|
+
const notHttp = (u) => new Error(`jux: url '${u.url}' for id '${u.id}' must be http(s)`);
|
|
13
|
+
const isHttp = (url) => url.protocol === 'http:' || url.protocol === 'https:';
|
|
14
|
+
// Ids are baseline keys. A Map would silently keep the last duplicate and
|
|
15
|
+
// two pages would share one baseline, so reject them up front.
|
|
16
|
+
const byId = new Map();
|
|
17
|
+
for (const u of urls) {
|
|
18
|
+
if (!u.id)
|
|
19
|
+
throw new Error('jux: url entry has an empty id');
|
|
20
|
+
// Validate with the same parser navigation uses. A regex disagrees with it:
|
|
21
|
+
// WHATWG strips leading/trailing C0 controls and spaces and removes tabs and
|
|
22
|
+
// newlines, so ' file:///x' or 'fi\tle:///x' looks relative to a regex but
|
|
23
|
+
// navigates to file:. A file:/javascript:/data: url would let whoever
|
|
24
|
+
// controls the config (a fork PR in CI) publish local file contents in the
|
|
25
|
+
// image and structure sidecar. 'localhost:3000/x' (scheme "localhost:")
|
|
26
|
+
// also becomes a clear error instead of a confusing navigation failure.
|
|
27
|
+
let abs = null;
|
|
28
|
+
try {
|
|
29
|
+
abs = new URL(u.url);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// relative; checked again against the origin in resolve()
|
|
33
|
+
}
|
|
34
|
+
if (abs && !isHttp(abs))
|
|
35
|
+
throw notHttp(u);
|
|
36
|
+
if (byId.has(u.id))
|
|
37
|
+
throw new Error(`jux: duplicate url id '${u.id}'`);
|
|
38
|
+
byId.set(u.id, u);
|
|
39
|
+
}
|
|
40
|
+
const resolve = (id, baseUrl) => {
|
|
41
|
+
const entry = byId.get(id);
|
|
42
|
+
if (!entry)
|
|
43
|
+
throw new Error(`jux: no url with id '${id}'`);
|
|
44
|
+
let final;
|
|
45
|
+
try {
|
|
46
|
+
final = new URL(entry.url);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
if (!/^https?:/i.test(baseUrl)) {
|
|
50
|
+
throw new Error(`jux: relative url '${entry.url}' needs --origin`);
|
|
51
|
+
}
|
|
52
|
+
final = new URL(entry.url, baseUrl);
|
|
53
|
+
}
|
|
54
|
+
// Navigate to exactly what was validated.
|
|
55
|
+
if (!isHttp(final))
|
|
56
|
+
throw notHttp(entry);
|
|
57
|
+
return final.href;
|
|
58
|
+
};
|
|
59
|
+
return {
|
|
60
|
+
name: 'urls',
|
|
61
|
+
async detect() {
|
|
62
|
+
return false;
|
|
63
|
+
},
|
|
64
|
+
async enumerate() {
|
|
65
|
+
return urls.map((u) => ({
|
|
66
|
+
storyId: u.id,
|
|
67
|
+
title: u.id,
|
|
68
|
+
name: u.id,
|
|
69
|
+
componentPath: '',
|
|
70
|
+
params: u.params ?? {},
|
|
71
|
+
}));
|
|
72
|
+
},
|
|
73
|
+
async showStory(page, storyId, baseUrl) {
|
|
74
|
+
await page.goto(resolve(storyId, baseUrl));
|
|
75
|
+
},
|
|
76
|
+
previewUrl() {
|
|
77
|
+
return 'about:blank';
|
|
78
|
+
},
|
|
79
|
+
storyUrl(baseUrl, storyId) {
|
|
80
|
+
return resolve(storyId, baseUrl);
|
|
81
|
+
},
|
|
82
|
+
async settle() {
|
|
83
|
+
// No platform render signal. Core's generic settle runs after this.
|
|
84
|
+
},
|
|
85
|
+
configDirs: [],
|
|
86
|
+
storyFileGlobs: [],
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=urls.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"urls.js","sourceRoot":"","sources":["../../src/platforms/urls.ts"],"names":[],"mappings":"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"}
|
package/dist/report/comment.d.ts
CHANGED
|
@@ -10,7 +10,8 @@ export declare const COMMENT_MARKER = "<!-- juxtapose-bot -->";
|
|
|
10
10
|
export interface CommentOptions {
|
|
11
11
|
report: RunReport;
|
|
12
12
|
/** Where to point someone who wants the images. Omitted when there is no
|
|
13
|
-
* artifact to link to
|
|
13
|
+
* artifact to link to — a link to an empty artifacts list is worse than no
|
|
14
|
+
* link, so callers pass this only when they actually wrote a report. */
|
|
14
15
|
artifactUrl?: string;
|
|
15
16
|
}
|
|
16
17
|
export declare function buildComment({ report, artifactUrl }: CommentOptions): string;
|