@juangadm/pre-post 1.3.0 → 1.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/README.md +43 -288
- package/assets/labels/post.png +0 -0
- package/assets/labels/pre.png +0 -0
- package/dist/attach.d.ts +59 -0
- package/dist/attach.d.ts.map +1 -0
- package/dist/attach.js +137 -0
- package/dist/attach.js.map +1 -0
- package/dist/baseline.d.ts +26 -1
- package/dist/baseline.d.ts.map +1 -1
- package/dist/baseline.js +92 -19
- package/dist/baseline.js.map +1 -1
- package/dist/bin/cli.js +40 -16
- package/dist/bin/cli.js.map +1 -1
- package/dist/browser.d.ts +79 -3
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +179 -38
- package/dist/browser.js.map +1 -1
- package/dist/commands/compare.d.ts.map +1 -1
- package/dist/commands/compare.js +5 -5
- package/dist/commands/compare.js.map +1 -1
- package/dist/commands/detect.d.ts +5 -0
- package/dist/commands/detect.d.ts.map +1 -1
- package/dist/commands/detect.js +3 -0
- package/dist/commands/detect.js.map +1 -1
- package/dist/commands/doctor.d.ts +6 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +21 -0
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/pr.d.ts +5 -0
- package/dist/commands/pr.d.ts.map +1 -1
- package/dist/commands/pr.js +167 -113
- package/dist/commands/pr.js.map +1 -1
- package/dist/comparison.d.ts +5 -0
- package/dist/comparison.d.ts.map +1 -1
- package/dist/comparison.js +5 -5
- package/dist/comparison.js.map +1 -1
- package/dist/compose.d.ts +72 -0
- package/dist/compose.d.ts.map +1 -0
- package/dist/compose.js +237 -0
- package/dist/compose.js.map +1 -0
- package/dist/diff-worker.d.ts +1 -0
- package/dist/diff-worker.d.ts.map +1 -1
- package/dist/diff-worker.js +1 -0
- package/dist/diff-worker.js.map +1 -1
- package/dist/diff.d.ts +42 -0
- package/dist/diff.d.ts.map +1 -1
- package/dist/diff.js +142 -24
- package/dist/diff.js.map +1 -1
- package/dist/doctor.d.ts +4 -1
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +5 -1
- package/dist/doctor.js.map +1 -1
- package/dist/drift.d.ts +29 -0
- package/dist/drift.d.ts.map +1 -0
- package/dist/drift.js +106 -0
- package/dist/drift.js.map +1 -0
- package/dist/errors.d.ts +6 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +6 -0
- package/dist/errors.js.map +1 -1
- package/dist/ffmpeg.d.ts +35 -0
- package/dist/ffmpeg.d.ts.map +1 -0
- package/dist/ffmpeg.js +143 -0
- package/dist/ffmpeg.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/moments.d.ts +83 -0
- package/dist/moments.d.ts.map +1 -0
- package/dist/moments.js +170 -0
- package/dist/moments.js.map +1 -0
- package/dist/record.d.ts +69 -0
- package/dist/record.d.ts.map +1 -0
- package/dist/record.js +223 -0
- package/dist/record.js.map +1 -0
- package/dist/report.d.ts +29 -1
- package/dist/report.d.ts.map +1 -1
- package/dist/report.js +174 -42
- package/dist/report.js.map +1 -1
- package/dist/routes/imports.d.ts +21 -1
- package/dist/routes/imports.d.ts.map +1 -1
- package/dist/routes/imports.js +32 -2
- package/dist/routes/imports.js.map +1 -1
- package/dist/routes.d.ts +18 -0
- package/dist/routes.d.ts.map +1 -1
- package/dist/routes.js +110 -29
- package/dist/routes.js.map +1 -1
- package/dist/run.d.ts +48 -12
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +140 -18
- package/dist/run.js.map +1 -1
- package/dist/timeline.d.ts +46 -0
- package/dist/timeline.d.ts.map +1 -0
- package/dist/timeline.js +80 -0
- package/dist/timeline.js.map +1 -0
- package/dist/types.d.ts +95 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -1
- package/dist/video.d.ts +19 -0
- package/dist/video.d.ts.map +1 -0
- package/dist/video.js +109 -0
- package/dist/video.js.map +1 -0
- package/package.json +4 -2
- package/skill/SKILL.md +38 -10
package/dist/comparison.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"comparison.d.ts","sourceRoot":"","sources":["../src/comparison.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAErD,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE3D,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,UAAU,GAAG,OAAO,CAAC;AAE7D,MAAM,WAAW,IAAI;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,wEAAwE;IACxE,MAAM,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,KAAK,CAAC,EAAE,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"comparison.d.ts","sourceRoot":"","sources":["../src/comparison.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAErD,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE3D,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,UAAU,GAAG,OAAO,CAAC;AAE7D,MAAM,WAAW,IAAI;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,wEAAwE;IACxE,MAAM,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAGD,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,YAAY,CAAC;IACvB,MAAM,EAAE,IAAI,CAAC;IACb,KAAK,EAAE,IAAI,CAAC;IACZ,wEAAwE;IACxE,KAAK,EAAE,OAAO,CAAC;IACf,mEAAmE;IACnE,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,EAAE,EAAE,cAAc,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,aAAa,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,SAAS,EAAE,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAClC,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IAC7C;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6CAA6C;IAC7C,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,0EAA0E;IAC1E,aAAa,CAAC,EAAE,OAAO,eAAe,CAAC;IACvC,4EAA4E;IAC5E,SAAS,CAAC,EAAE,OAAO,gBAAgB,CAAC;IACpC,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3B,wEAAwE;IACxE,OAAO,CAAC,EAAE,SAAS,CAAC;CACrB;AAoMD;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,CAMhF;AAED,qBAAa,WAAY,SAAQ,eAAe;;CAK/C;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,uBAAwB,SAAQ,eAAe;gBAC9C,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAAA;KAAE;CAIrF;AAaD,qBAAa,eAAgB,SAAQ,eAAe;;CAKnD;AAED,2EAA2E;AAC3E,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,UAAU,GAAG,MAAM,EAAE,CAU1D"}
|
package/dist/comparison.js
CHANGED
|
@@ -17,7 +17,7 @@ import { NeedsHumanError } from './doctor.js';
|
|
|
17
17
|
import { isLocalUrl, normalizeUrl } from './url.js';
|
|
18
18
|
import { mergeBase } from './git.js';
|
|
19
19
|
const noop = async () => undefined;
|
|
20
|
-
const side = (url, detail, probe) => ({ url: normalizeUrl(url), detail, probe });
|
|
20
|
+
const side = (url, detail, probe, label) => ({ url: normalizeUrl(url), detail, probe, label });
|
|
21
21
|
/**
|
|
22
22
|
* The one place a Comparison is built, so `mixed` is derived rather than
|
|
23
23
|
* recomputed — a construction site that forgot it would report a production
|
|
@@ -135,7 +135,7 @@ async function localPair(ctx, deployed) {
|
|
|
135
135
|
const running = await ctx.devServer;
|
|
136
136
|
let after = ctx.after
|
|
137
137
|
? side(ctx.after, 'passed with --after')
|
|
138
|
-
: running ? side(running, 'local dev server') : null;
|
|
138
|
+
: running ? side(running, 'local dev server', undefined, 'this branch') : null;
|
|
139
139
|
// Nothing deployed and nothing running is not a reason to stop: this is the
|
|
140
140
|
// command you hit on the way out of a PR, so it starts the dev server itself
|
|
141
141
|
// rather than handing back a chore.
|
|
@@ -171,7 +171,7 @@ async function localPair(ctx, deployed) {
|
|
|
171
171
|
throw postResult.reason;
|
|
172
172
|
}
|
|
173
173
|
if (postServer)
|
|
174
|
-
after = side(postServer.url, 'working tree, served locally');
|
|
174
|
+
after = side(postServer.url, 'working tree, served locally', undefined, 'this branch');
|
|
175
175
|
if (!after) {
|
|
176
176
|
await stopPre();
|
|
177
177
|
throw deployed.preview ? new NoDeployedBaselineError(deployed.preview.url, deployed.rejectedBaseline) : new NoPostError();
|
|
@@ -183,8 +183,8 @@ async function localPair(ctx, deployed) {
|
|
|
183
183
|
if (ctx.before)
|
|
184
184
|
return pair('explicit', side(ctx.before, 'passed with --before'), after, stopPost);
|
|
185
185
|
if (baseline) {
|
|
186
|
-
const before = side(baseline.url, `base commit ${baseSha.slice(0, 7)}, served locally`);
|
|
187
|
-
return pair('local', before, after, async () => { await baseline.stop()
|
|
186
|
+
const before = side(baseline.url, `base commit ${baseSha.slice(0, 7)}, served locally`, undefined, `base \`${baseSha.slice(0, 7)}\``);
|
|
187
|
+
return pair('local', before, after, async () => { await Promise.all([baseline.stop(), stopPost()]); });
|
|
188
188
|
}
|
|
189
189
|
// Nothing local could be built; a configured URL beats no comparison at all,
|
|
190
190
|
// unless the caller asked for both sides to be local.
|
package/dist/comparison.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"comparison.js","sourceRoot":"","sources":["../src/comparison.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AACzG,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,EAAE,eAAe,EAAe,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAEpD,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"comparison.js","sourceRoot":"","sources":["../src/comparison.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pre beside Post, in one clip.
|
|
3
|
+
*
|
|
4
|
+
* Two separate players cannot be kept in step — a reviewer presses play twice
|
|
5
|
+
* and compares by eye — so the two recordings are drawn side by side into one
|
|
6
|
+
* video, on the step-aligned timeline from `timeline.ts`. Drawn by the capture
|
|
7
|
+
* browser on a canvas, like the summary sheet: the bundled ffmpeg has no
|
|
8
|
+
* `hstack` and no text rendering, and the browser has both for free.
|
|
9
|
+
*
|
|
10
|
+
* On top of the frames: the PRE / Post lockup from the brand, the Moment's
|
|
11
|
+
* name and the step in progress (so someone who never saw the code can follow
|
|
12
|
+
* what is being done), a marker where each click lands, and a card over a
|
|
13
|
+
* side that could not do a step — the usual reason being that the feature is
|
|
14
|
+
* new in this PR.
|
|
15
|
+
*/
|
|
16
|
+
import { Step } from './moments.js';
|
|
17
|
+
import type { PointerMark, SideRecording } from './record.js';
|
|
18
|
+
import { Tick } from './timeline.js';
|
|
19
|
+
export declare const FPS = 30;
|
|
20
|
+
/** Widest a pane is drawn; a desktop page is scaled down to it, a phone is not. */
|
|
21
|
+
export declare const MAX_PANE_WIDTH = 800;
|
|
22
|
+
export interface Layout {
|
|
23
|
+
width: number;
|
|
24
|
+
height: number;
|
|
25
|
+
paneWidth: number;
|
|
26
|
+
paneHeight: number;
|
|
27
|
+
/** CSS px of the page → px of the pane. */
|
|
28
|
+
scale: number;
|
|
29
|
+
}
|
|
30
|
+
/** Canvas size for a viewport. Even on both axes, which VP8's 4:2:0 needs. */
|
|
31
|
+
export declare function layoutFor(viewport: {
|
|
32
|
+
width: number;
|
|
33
|
+
height: number;
|
|
34
|
+
}): Layout;
|
|
35
|
+
/** A card drawn over one pane: why that side shows nothing, or stopped. */
|
|
36
|
+
export interface Card {
|
|
37
|
+
title: string;
|
|
38
|
+
detail?: string;
|
|
39
|
+
}
|
|
40
|
+
interface PointerDraw {
|
|
41
|
+
side: 'a' | 'b';
|
|
42
|
+
x: number;
|
|
43
|
+
y: number;
|
|
44
|
+
kind: 'click' | 'hover';
|
|
45
|
+
/** 0..1 through the click marker's fade. */
|
|
46
|
+
p: number;
|
|
47
|
+
}
|
|
48
|
+
/** What to draw for a tick's pointer marks, if anything. */
|
|
49
|
+
export declare function pointersFor(tick: Tick, steps: Step[], pre: PointerMark[], post: PointerMark[]): PointerDraw[];
|
|
50
|
+
/** The line under the clip: which step of how many, in words. */
|
|
51
|
+
export declare function captionFor(tick: Tick, steps: Step[]): string;
|
|
52
|
+
export interface ComposeInput {
|
|
53
|
+
name: string;
|
|
54
|
+
steps: Step[];
|
|
55
|
+
/** Null when Pre has no such page: the pane shows `preCard` throughout. */
|
|
56
|
+
pre: SideRecording | null;
|
|
57
|
+
post: SideRecording;
|
|
58
|
+
/** Shown over Pre once it has run out of steps, or throughout when `pre` is null. */
|
|
59
|
+
preCard?: Card;
|
|
60
|
+
/** The clip, `.webm`. */
|
|
61
|
+
out: string;
|
|
62
|
+
/** Its last frame, `.jpg`: the result of the interaction, for places video cannot play. */
|
|
63
|
+
poster: string;
|
|
64
|
+
}
|
|
65
|
+
export interface ComposeResult {
|
|
66
|
+
durationMs: number;
|
|
67
|
+
bytes: number;
|
|
68
|
+
}
|
|
69
|
+
/** Draw, encode and size-check one Moment's clip. */
|
|
70
|
+
export declare function composeMoment(input: ComposeInput): Promise<ComposeResult>;
|
|
71
|
+
export {};
|
|
72
|
+
//# sourceMappingURL=compose.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAKH,OAAO,EAAgB,IAAI,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAsC,IAAI,EAAoB,MAAM,eAAe,CAAC;AAG3F,eAAO,MAAM,GAAG,KAAK,CAAC;AACtB,mFAAmF;AACnF,eAAO,MAAM,cAAc,MAAM,CAAC;AAQlC,MAAM,WAAW,MAAM;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC;CACf;AAID,8EAA8E;AAC9E,wBAAgB,SAAS,CAAC,QAAQ,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAK7E;AAaD,2EAA2E;AAC3E,MAAM,WAAW,IAAI;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,WAAW;IACnB,IAAI,EAAE,GAAG,GAAG,GAAG,CAAC;IAChB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IACxB,4CAA4C;IAC5C,CAAC,EAAE,MAAM,CAAC;CACX;AAED,4DAA4D;AAC5D,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE,CAc7G;AAED,iEAAiE;AACjE,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,MAAM,CAO5D;AA+FD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,2EAA2E;IAC3E,GAAG,EAAE,aAAa,GAAG,IAAI,CAAC;IAC1B,IAAI,EAAE,aAAa,CAAC;IACpB,qFAAqF;IACrF,OAAO,CAAC,EAAE,IAAI,CAAC;IACf,yBAAyB;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,2FAA2F;IAC3F,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,qDAAqD;AACrD,wBAAsB,aAAa,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,CA4D/E"}
|
package/dist/compose.js
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pre beside Post, in one clip.
|
|
3
|
+
*
|
|
4
|
+
* Two separate players cannot be kept in step — a reviewer presses play twice
|
|
5
|
+
* and compares by eye — so the two recordings are drawn side by side into one
|
|
6
|
+
* video, on the step-aligned timeline from `timeline.ts`. Drawn by the capture
|
|
7
|
+
* browser on a canvas, like the summary sheet: the bundled ffmpeg has no
|
|
8
|
+
* `hstack` and no text rendering, and the browser has both for free.
|
|
9
|
+
*
|
|
10
|
+
* On top of the frames: the PRE / Post lockup from the brand, the Moment's
|
|
11
|
+
* name and the step in progress (so someone who never saw the code can follow
|
|
12
|
+
* what is being done), a marker where each click lands, and a card over a
|
|
13
|
+
* side that could not do a step — the usual reason being that the feature is
|
|
14
|
+
* new in this PR.
|
|
15
|
+
*/
|
|
16
|
+
import fs from 'fs';
|
|
17
|
+
import { fileURLToPath } from 'url';
|
|
18
|
+
import { getBrowser } from './browser.js';
|
|
19
|
+
import { describeStep } from './moments.js';
|
|
20
|
+
import { alignTimeline, frameAt, timelineDuration } from './timeline.js';
|
|
21
|
+
import { ensureFfmpeg, fitSize, startEncoder } from './ffmpeg.js';
|
|
22
|
+
export const FPS = 30;
|
|
23
|
+
/** Widest a pane is drawn; a desktop page is scaled down to it, a phone is not. */
|
|
24
|
+
export const MAX_PANE_WIDTH = 800;
|
|
25
|
+
const PAD = 20;
|
|
26
|
+
const HEADER = 56;
|
|
27
|
+
const FOOTER = 44;
|
|
28
|
+
/** How long a click marker takes to fade, in output ms. */
|
|
29
|
+
const CLICK_MARK_MS = 450;
|
|
30
|
+
const JPEG_QUALITY = 0.9;
|
|
31
|
+
const even = (n) => Math.ceil(n / 2) * 2;
|
|
32
|
+
/** Canvas size for a viewport. Even on both axes, which VP8's 4:2:0 needs. */
|
|
33
|
+
export function layoutFor(viewport) {
|
|
34
|
+
const scale = Math.min(1, MAX_PANE_WIDTH / viewport.width);
|
|
35
|
+
const paneWidth = Math.round(viewport.width * scale);
|
|
36
|
+
const paneHeight = Math.round(viewport.height * scale);
|
|
37
|
+
return { width: even(PAD * 3 + paneWidth * 2), height: even(HEADER + paneHeight + FOOTER), paneWidth, paneHeight, scale };
|
|
38
|
+
}
|
|
39
|
+
function labelUri(name) {
|
|
40
|
+
try {
|
|
41
|
+
const file = fileURLToPath(new URL(`../assets/labels/${name}.png`, import.meta.url));
|
|
42
|
+
return `data:image/png;base64,${fs.readFileSync(file).toString('base64')}`;
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
let labels;
|
|
49
|
+
/** What to draw for a tick's pointer marks, if anything. */
|
|
50
|
+
export function pointersFor(tick, steps, pre, post) {
|
|
51
|
+
if (tick.step < 0)
|
|
52
|
+
return [];
|
|
53
|
+
const step = steps[tick.step];
|
|
54
|
+
if (!step || (step.verb !== 'click' && step.verb !== 'hover' && step.verb !== 'type'))
|
|
55
|
+
return [];
|
|
56
|
+
const out = [];
|
|
57
|
+
const add = (side, marks, missing) => {
|
|
58
|
+
const mark = !missing && marks.find(m => m.step === tick.step);
|
|
59
|
+
if (!mark)
|
|
60
|
+
return;
|
|
61
|
+
if (step.verb === 'hover')
|
|
62
|
+
out.push({ side, x: mark.x, y: mark.y, kind: 'hover', p: 0 });
|
|
63
|
+
else if (tick.sinceStep < CLICK_MARK_MS)
|
|
64
|
+
out.push({ side, x: mark.x, y: mark.y, kind: 'click', p: tick.sinceStep / CLICK_MARK_MS });
|
|
65
|
+
};
|
|
66
|
+
add('a', pre, tick.aMissing);
|
|
67
|
+
add('b', post, tick.bMissing);
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
70
|
+
/** The line under the clip: which step of how many, in words. */
|
|
71
|
+
export function captionFor(tick, steps) {
|
|
72
|
+
if (tick.step < 0 || !steps.length)
|
|
73
|
+
return '';
|
|
74
|
+
let i = Math.min(tick.step, steps.length - 1);
|
|
75
|
+
// "Wait" says nothing to a viewer; keep showing what they are watching the result of.
|
|
76
|
+
while (i > 0 && steps[i].verb === 'wait')
|
|
77
|
+
i--;
|
|
78
|
+
if (steps[i].verb === 'wait')
|
|
79
|
+
return '';
|
|
80
|
+
return `${i + 1}/${steps.length} · ${describeStep(steps[i])}`;
|
|
81
|
+
}
|
|
82
|
+
/** In-page drawing code. Plain JS, run by the compositor page. */
|
|
83
|
+
const PAGE_SCRIPT = `
|
|
84
|
+
const cfg = window.__cfg;
|
|
85
|
+
const c = document.getElementById('c');
|
|
86
|
+
const g = c.getContext('2d');
|
|
87
|
+
// One decoded frame per side: ticks only move forward, so the frame being
|
|
88
|
+
// replaced is never needed again.
|
|
89
|
+
const shown = { a: null, b: null };
|
|
90
|
+
const labels = {};
|
|
91
|
+
const load = src => new Promise((res, rej) => { const i = new Image(); i.onload = () => res(i); i.onerror = rej; i.src = src; });
|
|
92
|
+
window.init = async () => {
|
|
93
|
+
if (cfg.labels.pre) labels.pre = await load(cfg.labels.pre);
|
|
94
|
+
if (cfg.labels.post) labels.post = await load(cfg.labels.post);
|
|
95
|
+
};
|
|
96
|
+
function rounded(x, y, w, h, r) { g.beginPath(); g.roundRect(x, y, w, h, r); }
|
|
97
|
+
function paneX(side) { return side === 'a' ? cfg.pad : cfg.pad * 2 + cfg.paneWidth; }
|
|
98
|
+
function drawLabel(side) {
|
|
99
|
+
const img = side === 'a' ? labels.pre : labels.post;
|
|
100
|
+
const x = paneX(side);
|
|
101
|
+
const baseline = cfg.header - 10;
|
|
102
|
+
if (img) {
|
|
103
|
+
const h = img.height / 2, w = img.width / 2;
|
|
104
|
+
// Each image carries its own padding; these offsets put both glyphs'
|
|
105
|
+
// baselines on one line (measured on the rendered labels).
|
|
106
|
+
g.drawImage(img, x - 4, baseline - h + (side === 'a' ? 13 : 5), w, h);
|
|
107
|
+
} else {
|
|
108
|
+
g.fillStyle = '#262626'; g.font = '600 20px system-ui, sans-serif';
|
|
109
|
+
g.fillText(side === 'a' ? 'PRE' : 'Post', x, baseline);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function drawPane(side, img, card) {
|
|
113
|
+
const x = paneX(side), y = cfg.header;
|
|
114
|
+
g.save();
|
|
115
|
+
rounded(x, y, cfg.paneWidth, cfg.paneHeight, 8);
|
|
116
|
+
g.fillStyle = '#fff'; g.fill();
|
|
117
|
+
g.clip();
|
|
118
|
+
if (img) g.drawImage(img, x, y, cfg.paneWidth, cfg.paneHeight);
|
|
119
|
+
if (card) {
|
|
120
|
+
g.fillStyle = img ? 'rgba(245,245,245,0.86)' : '#fafafa';
|
|
121
|
+
g.fillRect(x, y, cfg.paneWidth, cfg.paneHeight);
|
|
122
|
+
g.textAlign = 'center';
|
|
123
|
+
g.fillStyle = '#262626'; g.font = '600 17px system-ui, sans-serif';
|
|
124
|
+
g.fillText(card.title, x + cfg.paneWidth / 2, y + cfg.paneHeight / 2 - (card.detail ? 6 : -6));
|
|
125
|
+
if (card.detail) {
|
|
126
|
+
g.fillStyle = '#737373'; g.font = '14px system-ui, sans-serif';
|
|
127
|
+
g.fillText(card.detail, x + cfg.paneWidth / 2, y + cfg.paneHeight / 2 + 18);
|
|
128
|
+
}
|
|
129
|
+
g.textAlign = 'left';
|
|
130
|
+
}
|
|
131
|
+
g.restore();
|
|
132
|
+
g.save();
|
|
133
|
+
rounded(x + 0.5, y + 0.5, cfg.paneWidth - 1, cfg.paneHeight - 1, 8);
|
|
134
|
+
g.strokeStyle = '#e5e5e5'; g.lineWidth = 1; g.stroke();
|
|
135
|
+
g.restore();
|
|
136
|
+
}
|
|
137
|
+
function drawPointer(pt) {
|
|
138
|
+
const x = paneX(pt.side) + pt.x * cfg.scale, y = cfg.header + pt.y * cfg.scale;
|
|
139
|
+
g.save();
|
|
140
|
+
if (pt.kind === 'hover') {
|
|
141
|
+
g.beginPath(); g.arc(x, y, 7, 0, Math.PI * 2);
|
|
142
|
+
g.fillStyle = 'rgba(246, 105, 108, 0.45)'; g.fill();
|
|
143
|
+
g.strokeStyle = '#fff'; g.lineWidth = 2; g.stroke();
|
|
144
|
+
} else {
|
|
145
|
+
const a = 1 - pt.p;
|
|
146
|
+
g.beginPath(); g.arc(x, y, 8 + 16 * pt.p, 0, Math.PI * 2);
|
|
147
|
+
g.strokeStyle = 'rgba(246, 105, 108,' + a + ')'; g.lineWidth = 3; g.stroke();
|
|
148
|
+
g.beginPath(); g.arc(x, y, 5, 0, Math.PI * 2);
|
|
149
|
+
g.fillStyle = 'rgba(246, 105, 108,' + a + ')'; g.fill();
|
|
150
|
+
}
|
|
151
|
+
g.restore();
|
|
152
|
+
}
|
|
153
|
+
async function frame(side, data) {
|
|
154
|
+
if (data) shown[side] = await load('data:image/jpeg;base64,' + data);
|
|
155
|
+
return shown[side];
|
|
156
|
+
}
|
|
157
|
+
window.draw = async t => {
|
|
158
|
+
const [a, b] = await Promise.all([frame('a', t.a), frame('b', t.b)]);
|
|
159
|
+
g.fillStyle = '#f5f5f5'; g.fillRect(0, 0, c.width, c.height);
|
|
160
|
+
drawLabel('a'); drawLabel('b');
|
|
161
|
+
drawPane('a', a, t.aCard); drawPane('b', b, null);
|
|
162
|
+
for (const pt of t.pointers) drawPointer(pt);
|
|
163
|
+
const fy = cfg.header + cfg.paneHeight + cfg.footer / 2 + 5;
|
|
164
|
+
g.fillStyle = '#262626'; g.font = '600 15px system-ui, sans-serif';
|
|
165
|
+
g.fillText(cfg.name, cfg.pad, fy);
|
|
166
|
+
if (t.caption) {
|
|
167
|
+
g.textAlign = 'right'; g.fillStyle = '#737373'; g.font = '14px ui-monospace, Menlo, Consolas, monospace';
|
|
168
|
+
g.fillText(t.caption, c.width - cfg.pad, fy);
|
|
169
|
+
g.textAlign = 'left';
|
|
170
|
+
}
|
|
171
|
+
return c.toDataURL('image/jpeg', ${JPEG_QUALITY}).slice('data:image/jpeg;base64,'.length);
|
|
172
|
+
};
|
|
173
|
+
`;
|
|
174
|
+
/** Draw, encode and size-check one Moment's clip. */
|
|
175
|
+
export async function composeMoment(input) {
|
|
176
|
+
const { pre, post, steps } = input;
|
|
177
|
+
const layout = layoutFor(post.viewport);
|
|
178
|
+
const preTiming = pre ?? { start: post.start, end: post.start, marks: [] };
|
|
179
|
+
const ticks = alignTimeline(preTiming, post, FPS);
|
|
180
|
+
const timesA = pre?.frames.map(f => f.t) ?? [];
|
|
181
|
+
const timesB = post.frames.map(f => f.t);
|
|
182
|
+
const [ffmpeg, browser] = await Promise.all([ensureFfmpeg(), getBrowser()]);
|
|
183
|
+
const ctx = await browser.newContext({ viewport: { width: layout.width, height: layout.height }, deviceScaleFactor: 1 });
|
|
184
|
+
const encoder = startEncoder(ffmpeg, input.out, FPS);
|
|
185
|
+
let last = null;
|
|
186
|
+
try {
|
|
187
|
+
const page = await ctx.newPage();
|
|
188
|
+
const cfg = {
|
|
189
|
+
pad: PAD, header: HEADER, footer: FOOTER, name: input.name,
|
|
190
|
+
paneWidth: layout.paneWidth, paneHeight: layout.paneHeight, scale: layout.scale,
|
|
191
|
+
labels: labels ??= { pre: labelUri('pre'), post: labelUri('post') },
|
|
192
|
+
};
|
|
193
|
+
await page.setContent(`<!doctype html><body style="margin:0"><canvas id="c" width="${layout.width}" height="${layout.height}"></canvas>`
|
|
194
|
+
+ `<script>window.__cfg = ${JSON.stringify(cfg)};${PAGE_SCRIPT}</script>`);
|
|
195
|
+
await page.evaluate('window.init()');
|
|
196
|
+
let sentA = -1;
|
|
197
|
+
let sentB = -1;
|
|
198
|
+
let lastKey = '';
|
|
199
|
+
for (const tick of ticks) {
|
|
200
|
+
const ia = pre ? frameAt(timesA, tick.a) : -1;
|
|
201
|
+
const ib = frameAt(timesB, tick.b);
|
|
202
|
+
const aCard = (!pre || tick.aMissing) && input.preCard ? input.preCard : null;
|
|
203
|
+
const pointers = pointersFor(tick, steps, pre?.pointers ?? [], post.pointers);
|
|
204
|
+
const caption = captionFor(tick, steps);
|
|
205
|
+
// An unchanged picture is the same JPEG: most of a clip is a page
|
|
206
|
+
// holding still between steps, and those ticks cost nothing to draw.
|
|
207
|
+
const key = `${ia}|${ib}|${aCard ? 1 : 0}|${caption}|${pointers.map(p => `${p.side}${Math.round(p.p * 20)}`).join()}`;
|
|
208
|
+
if (key !== lastKey || !last) {
|
|
209
|
+
// Only a frame the page is not already showing crosses over.
|
|
210
|
+
const a = ia >= 0 && ia !== sentA ? pre.frames[ia].data.toString('base64') : null;
|
|
211
|
+
const b = ib >= 0 && ib !== sentB ? post.frames[ib].data.toString('base64') : null;
|
|
212
|
+
sentA = ia;
|
|
213
|
+
sentB = ib;
|
|
214
|
+
const jpeg = await page.evaluate(t => window.draw(t), {
|
|
215
|
+
a, b, aCard, pointers, caption,
|
|
216
|
+
});
|
|
217
|
+
last = Buffer.from(jpeg, 'base64');
|
|
218
|
+
lastKey = key;
|
|
219
|
+
}
|
|
220
|
+
await encoder.write(last);
|
|
221
|
+
}
|
|
222
|
+
await encoder.finish();
|
|
223
|
+
}
|
|
224
|
+
catch (err) {
|
|
225
|
+
await encoder.finish().catch(() => undefined);
|
|
226
|
+
throw err;
|
|
227
|
+
}
|
|
228
|
+
finally {
|
|
229
|
+
await ctx.close().catch(() => undefined);
|
|
230
|
+
}
|
|
231
|
+
if (last)
|
|
232
|
+
fs.writeFileSync(input.poster, last);
|
|
233
|
+
const durationMs = timelineDuration(ticks, FPS);
|
|
234
|
+
const bytes = await fitSize(ffmpeg, input.out, durationMs);
|
|
235
|
+
return { durationMs, bytes };
|
|
236
|
+
}
|
|
237
|
+
//# sourceMappingURL=compose.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compose.js","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAQ,MAAM,cAAc,CAAC;AAElD,OAAO,EAAE,aAAa,EAAE,OAAO,EAAoB,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC3F,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAElE,MAAM,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;AACtB,mFAAmF;AACnF,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,CAAC;AAClC,MAAM,GAAG,GAAG,EAAE,CAAC;AACf,MAAM,MAAM,GAAG,EAAE,CAAC;AAClB,MAAM,MAAM,GAAG,EAAE,CAAC;AAClB,2DAA2D;AAC3D,MAAM,aAAa,GAAG,GAAG,CAAC;AAC1B,MAAM,YAAY,GAAG,GAAG,CAAC;AAWzB,MAAM,IAAI,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;AAEjD,8EAA8E;AAC9E,MAAM,UAAU,SAAS,CAAC,QAA2C;IACnE,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,cAAc,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC3D,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC;IACrD,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC;IACvD,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,GAAG,SAAS,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;AAC5H,CAAC;AAED,SAAS,QAAQ,CAAC,IAAoB;IACpC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,oBAAoB,IAAI,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACrF,OAAO,yBAAyB,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;IAC7E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,IAAI,MAA+D,CAAC;AAiBpE,4DAA4D;AAC5D,MAAM,UAAU,WAAW,CAAC,IAAU,EAAE,KAAa,EAAE,GAAkB,EAAE,IAAmB;IAC5F,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IAC7B,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9B,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC;QAAE,OAAO,EAAE,CAAC;IACjG,MAAM,GAAG,GAAkB,EAAE,CAAC;IAC9B,MAAM,GAAG,GAAG,CAAC,IAAe,EAAE,KAAoB,EAAE,OAAgB,EAAE,EAAE;QACtE,MAAM,IAAI,GAAG,CAAC,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/D,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO;YAAE,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;aACpF,IAAI,IAAI,CAAC,SAAS,GAAG,aAAa;YAAE,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,SAAS,GAAG,aAAa,EAAE,CAAC,CAAC;IACtI,CAAC,CAAC;IACF,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC7B,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC9B,OAAO,GAAG,CAAC;AACb,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,UAAU,CAAC,IAAU,EAAE,KAAa;IAClD,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IAC9C,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC9C,sFAAsF;IACtF,OAAO,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM;QAAE,CAAC,EAAE,CAAC;IAC9C,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,EAAE,CAAC;IACxC,OAAO,GAAG,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,MAAM,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAChE,CAAC;AAED,kEAAkE;AAClE,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qCAwFiB,YAAY;;CAEhD,CAAC;AAqBF,qDAAqD;AACrD,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,KAAmB;IACrD,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;IACnC,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACxC,MAAM,SAAS,GAAe,GAAG,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IACvF,MAAM,KAAK,GAAG,aAAa,CAAC,SAAS,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;IAClD,MAAM,MAAM,GAAG,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAEzC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC;IAC5E,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,EAAE,iBAAiB,EAAE,CAAC,EAAE,CAAC,CAAC;IACzH,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACrD,IAAI,IAAI,GAAkB,IAAI,CAAC;IAC/B,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC;QACjC,MAAM,GAAG,GAAG;YACV,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI;YAC1D,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK;YAC/E,MAAM,EAAE,MAAM,KAAK,EAAE,GAAG,EAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE;SACpE,CAAC;QACF,MAAM,IAAI,CAAC,UAAU,CAAC,+DAA+D,MAAM,CAAC,KAAK,aAAa,MAAM,CAAC,MAAM,aAAa;cACpI,0BAA0B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,WAAW,WAAW,CAAC,CAAC;QAC7E,MAAM,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;QAErC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC;QACf,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC;QACf,IAAI,OAAO,GAAG,EAAE,CAAC;QACjB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9C,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;YACnC,MAAM,KAAK,GAAG,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;YAC9E,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,QAAQ,IAAI,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC9E,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACxC,kEAAkE;YAClE,qEAAqE;YACrE,MAAM,GAAG,GAAG,GAAG,EAAE,IAAI,EAAE,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,OAAO,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;YACtH,IAAI,GAAG,KAAK,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC;gBAC7B,6DAA6D;gBAC7D,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,KAAK,CAAC,CAAC,CAAC,GAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;gBACnF,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;gBACnF,KAAK,GAAG,EAAE,CAAC;gBACX,KAAK,GAAG,EAAE,CAAC;gBACX,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAE,MAA+D,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;oBAC9G,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO;iBAC/B,CAAC,CAAC;gBACH,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;gBACnC,OAAO,GAAG,GAAG,CAAC;YAChB,CAAC;YACD,MAAM,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;QACD,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC;IACzB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC9C,MAAM,GAAG,CAAC;IACZ,CAAC;YAAS,CAAC;QACT,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAC3C,CAAC;IACD,IAAI,IAAI;QAAE,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,gBAAgB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAChD,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAC3D,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;AAC/B,CAAC"}
|
package/dist/diff-worker.d.ts
CHANGED
|
@@ -26,6 +26,7 @@ export interface DiffJobResult {
|
|
|
26
26
|
hasHighlight: boolean;
|
|
27
27
|
/** Plain numbers, so the summary survives the structured clone back to the pool. */
|
|
28
28
|
shift?: ShiftSummary;
|
|
29
|
+
fingerprint?: string;
|
|
29
30
|
error?: string;
|
|
30
31
|
}
|
|
31
32
|
export declare function executeDiffJob(job: DiffJob): DiffJobResult;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diff-worker.d.ts","sourceRoot":"","sources":["../src/diff-worker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAc,WAAW,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,WAAW,OAAO;IACtB,+EAA+E;IAC/E,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,UAAU,CAAC;IAClB,iEAAiE;IACjE,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAChG,OAAO,CAAC,EAAE,WAAW,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,OAAO,CAAC;IACtB,oFAAoF;IACpF,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,aAAa,
|
|
1
|
+
{"version":3,"file":"diff-worker.d.ts","sourceRoot":"","sources":["../src/diff-worker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAc,WAAW,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,WAAW,OAAO;IACtB,+EAA+E;IAC/E,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,UAAU,CAAC;IAClB,iEAAiE;IACjE,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAChG,OAAO,CAAC,EAAE,WAAW,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,OAAO,CAAC;IACtB,oFAAoF;IACpF,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,aAAa,CAoB1D"}
|
package/dist/diff-worker.js
CHANGED
package/dist/diff-worker.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diff-worker.js","sourceRoot":"","sources":["../src/diff-worker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAe,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"diff-worker.js","sourceRoot":"","sources":["../src/diff-worker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAe,MAAM,WAAW,CAAC;AAwBpD,MAAM,UAAU,cAAc,CAAC,GAAY;IACzC,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC5F,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,UAAU,EAAE,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACxF,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7C,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IACtD,IAAI,MAAM,CAAC,SAAS;QAAE,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;IAC3E,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAChB,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC7D,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7D,CAAC;IACD,OAAO;QACL,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC;QAC7B,YAAY,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC;QACvC,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,WAAW,EAAE,MAAM,CAAC,WAAW;KAChC,CAAC;AACJ,CAAC;AAED,IAAI,UAAU,EAAE,CAAC;IACf,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,GAAY,EAAE,EAAE;QACxC,IAAI,CAAC;YACH,UAAW,CAAC,WAAW,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,UAAW,CAAC,WAAW,CAAC,EAAE,KAAK,EAAG,GAAa,CAAC,OAAO,EAAmB,CAAC,CAAC;QAC9E,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/diff.d.ts
CHANGED
|
@@ -27,10 +27,52 @@ export interface DiffOptions {
|
|
|
27
27
|
* Image mode still writes diff.png.
|
|
28
28
|
*/
|
|
29
29
|
highlight?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* What counts as a change, in device pixels and share of the canvas — the
|
|
32
|
+
* same rule the verdict uses (`isChanged`). Default: any pixel.
|
|
33
|
+
*
|
|
34
|
+
* The crop used to be drawn around every differing pixel while the verdict
|
|
35
|
+
* applied this rule, so the two disagreed: a pure move left a few pixels of
|
|
36
|
+
* animation noise, the report said "nothing else changed", and the crop
|
|
37
|
+
* showed the noise. Now a crop is only drawn around change the rule counts.
|
|
38
|
+
*/
|
|
39
|
+
rule?: ChangeRule;
|
|
40
|
+
/** Changed pixels closer than this (device px) belong to one patch. Default 48. */
|
|
41
|
+
clusterGap?: number;
|
|
30
42
|
}
|
|
43
|
+
export interface ChangeRule {
|
|
44
|
+
/** Smallest changed area that counts, in device pixels. */
|
|
45
|
+
minPixels: number;
|
|
46
|
+
/** Smallest changed share of the canvas that counts, 0..1. */
|
|
47
|
+
minRatio: number;
|
|
48
|
+
}
|
|
49
|
+
/** Do this many changed pixels, this share of the canvas, count under the rule? */
|
|
50
|
+
export declare function meetsRule(pixels: number, ratio: number, rule: ChangeRule): boolean;
|
|
31
51
|
/** Box-filter downscale by an integer factor. */
|
|
32
52
|
export declare function downscale(src: PNG, factor: number): PNG;
|
|
33
53
|
export declare function decodePng(buffer: Buffer): PNG;
|
|
54
|
+
/** A patch of change: nearby changed pixels, merged. */
|
|
55
|
+
export interface Cluster extends DiffRegion {
|
|
56
|
+
pixels: number;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Group changed pixels into patches, merging any closer than `gap`.
|
|
60
|
+
*
|
|
61
|
+
* One box around every changed pixel is what produced an 808x1356 crop for a
|
|
62
|
+
* header-link change: the link, plus a few pixels of an animated image far
|
|
63
|
+
* below it, made one box spanning both. As patches, the link is one and the
|
|
64
|
+
* specks are another, and each can be judged on its own.
|
|
65
|
+
*
|
|
66
|
+
* Works on a grid of `gap`-sized cells, joining neighbouring cells, so the
|
|
67
|
+
* cost is one pass over the pixels plus one over the occupied cells.
|
|
68
|
+
*/
|
|
69
|
+
export declare function findClusters(diff: PNG, gap: number): Cluster[];
|
|
70
|
+
/**
|
|
71
|
+
* The part of the page a crop should show: every patch that counts on its own,
|
|
72
|
+
* or, when none does but together they do, all of them. The second case is
|
|
73
|
+
* several small real edits — five recoloured icons — which must still be shown.
|
|
74
|
+
*/
|
|
75
|
+
export declare function regionOfInterest(clusters: Cluster[], rule: ChangeRule): DiffRegion | null;
|
|
34
76
|
/** Expand a region by padding and to a minimum size, clamped to the canvas. */
|
|
35
77
|
export declare function expandRegion(region: DiffRegion, canvas: {
|
|
36
78
|
width: number;
|
package/dist/diff.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../src/diff.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../src/diff.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,UAAU,EAAgB,MAAM,YAAY,CAAC;AAGlE,MAAM,WAAW,WAAW;IAC1B,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0DAA0D;IAC1D,OAAO,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,0FAA0F;IAC1F,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;;;;;OAQG;IACH,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,mFAAmF;IACnF,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,2DAA2D;IAC3D,SAAS,EAAE,MAAM,CAAC;IAClB,8DAA8D;IAC9D,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,mFAAmF;AACnF,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAGlF;AAkFD,iDAAiD;AACjD,wBAAgB,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAG,GAAG,CAoBvD;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,GAAG,CAE7C;AAkBD,wDAAwD;AACxD,MAAM,WAAW,OAAQ,SAAQ,UAAU;IACzC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,EAAE,CAkD9D;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,UAAU,GAAG,UAAU,GAAG,IAAI,CAGzF;AAgCD,+EAA+E;AAC/E,wBAAgB,YAAY,CAC1B,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EACzC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACrC,UAAU,CAqBZ;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,UAAU,CAuHrG"}
|