versioncam 0.4.1 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +78 -0
- package/README.md +164 -9
- package/dist/cli/commands/cloud.d.ts +59 -0
- package/dist/cli/commands/cloud.js +891 -0
- package/dist/cli/commands/cloud.js.map +1 -0
- package/dist/cli/commands/publish.d.ts +17 -1
- package/dist/cli/commands/publish.js +34 -15
- package/dist/cli/commands/publish.js.map +1 -1
- package/dist/cli/main.js +2 -0
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/usage.d.ts +4 -3
- package/dist/cli/usage.js +19 -2
- package/dist/cli/usage.js.map +1 -1
- package/dist/cloud/client.d.ts +54 -0
- package/dist/cloud/client.js +133 -0
- package/dist/cloud/client.js.map +1 -0
- package/dist/cloud/credentials.d.ts +35 -0
- package/dist/cloud/credentials.js +126 -0
- package/dist/cloud/credentials.js.map +1 -0
- package/dist/cloud/protocol.d.ts +220 -0
- package/dist/cloud/protocol.js +32 -0
- package/dist/cloud/protocol.js.map +1 -0
- package/dist/cloud/repository.d.ts +21 -0
- package/dist/cloud/repository.js +97 -0
- package/dist/cloud/repository.js.map +1 -0
- package/dist/cloud/wait.d.ts +43 -0
- package/dist/cloud/wait.js +110 -0
- package/dist/cloud/wait.js.map +1 -0
- package/dist/core/compose.d.ts +26 -1
- package/dist/core/compose.js +39 -0
- package/dist/core/compose.js.map +1 -1
- package/dist/driver/page-hooks.d.ts +7 -5
- package/dist/driver/page-hooks.js +38 -6
- package/dist/driver/page-hooks.js.map +1 -1
- package/dist/driver/settle.js +12 -7
- package/dist/driver/settle.js.map +1 -1
- package/dist/env.d.ts +6 -0
- package/dist/env.js +16 -3
- package/dist/env.js.map +1 -1
- package/dist/page/assets/index-BtUbUEdN.js +2 -0
- package/dist/page/index.html +1 -1
- package/package.json +1 -1
- package/plugin/README.md +25 -5
- package/plugin/skills/versioncam/SKILL.md +17 -5
- package/plugin/skills/versioncam/platform.md +201 -0
- package/dist/page/assets/index-fZtacWyp.js +0 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wait.js","sourceRoot":"","sources":["../../src/cloud/wait.ts"],"names":[],"mappings":"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"}
|
package/dist/core/compose.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Rect, Vec2 } from "./timeline.js";
|
|
1
|
+
import type { Rect, Timeline, Vec2 } from "./timeline.js";
|
|
2
2
|
/**
|
|
3
3
|
* Mapping from the captured page into the output frame.
|
|
4
4
|
*
|
|
@@ -34,5 +34,30 @@ export declare function fitFrameArea(canvas: {
|
|
|
34
34
|
* a cut never shows a duplicated still.
|
|
35
35
|
*/
|
|
36
36
|
export declare function crossfadeAlpha(frame: number, cutFrame: number, length: number): number;
|
|
37
|
+
/**
|
|
38
|
+
* Which state to show at `frame`, and what to crossfade it with.
|
|
39
|
+
*
|
|
40
|
+
* Only a settle produces a crossfade. Everywhere else a change between
|
|
41
|
+
* consecutive frames is a real one-frame change and must stay crisp —
|
|
42
|
+
* blurring those would smear the cursor's own motion.
|
|
43
|
+
*
|
|
44
|
+
* A settle whose page did not change (a menu already open, a form already
|
|
45
|
+
* filled) has the same state on both sides of its cut, and that is no
|
|
46
|
+
* crossfade at all. Reporting it as one had the renderer skip the previous
|
|
47
|
+
* state, which equals the current, and draw the current at the crossfade's
|
|
48
|
+
* alpha over the backdrop: about a sixth on the frame after the cut, a dip
|
|
49
|
+
* almost to black and back over six frames (0.5.0, found recording Vpogled's
|
|
50
|
+
* clips).
|
|
51
|
+
*
|
|
52
|
+
* Where two settles' windows overlap, the frame follows the later one, whose
|
|
53
|
+
* change it is showing. Following the earlier ran its dissolve to the end and
|
|
54
|
+
* then the later one's from part way, so the new state faded in, back out a
|
|
55
|
+
* little, and in again.
|
|
56
|
+
*/
|
|
57
|
+
export declare function stateForFrame(timeline: Pick<Timeline, "cuts" | "frames">, frame: number, crossfadeFrames: number): {
|
|
58
|
+
current: number;
|
|
59
|
+
previous: number | null;
|
|
60
|
+
alpha: number;
|
|
61
|
+
};
|
|
37
62
|
/** Linear fade in/out envelope, in seconds, for captions and highlights. */
|
|
38
63
|
export declare function fadeEnvelope(t: number, t0: number, t1: number, fade: number): number;
|
package/dist/core/compose.js
CHANGED
|
@@ -70,6 +70,45 @@ export function crossfadeAlpha(frame, cutFrame, length) {
|
|
|
70
70
|
return 1;
|
|
71
71
|
return clamp01((frame - cutFrame + 1) / length);
|
|
72
72
|
}
|
|
73
|
+
/**
|
|
74
|
+
* Which state to show at `frame`, and what to crossfade it with.
|
|
75
|
+
*
|
|
76
|
+
* Only a settle produces a crossfade. Everywhere else a change between
|
|
77
|
+
* consecutive frames is a real one-frame change and must stay crisp —
|
|
78
|
+
* blurring those would smear the cursor's own motion.
|
|
79
|
+
*
|
|
80
|
+
* A settle whose page did not change (a menu already open, a form already
|
|
81
|
+
* filled) has the same state on both sides of its cut, and that is no
|
|
82
|
+
* crossfade at all. Reporting it as one had the renderer skip the previous
|
|
83
|
+
* state, which equals the current, and draw the current at the crossfade's
|
|
84
|
+
* alpha over the backdrop: about a sixth on the frame after the cut, a dip
|
|
85
|
+
* almost to black and back over six frames (0.5.0, found recording Vpogled's
|
|
86
|
+
* clips).
|
|
87
|
+
*
|
|
88
|
+
* Where two settles' windows overlap, the frame follows the later one, whose
|
|
89
|
+
* change it is showing. Following the earlier ran its dissolve to the end and
|
|
90
|
+
* then the later one's from part way, so the new state faded in, back out a
|
|
91
|
+
* little, and in again.
|
|
92
|
+
*/
|
|
93
|
+
export function stateForFrame(timeline, frame, crossfadeFrames) {
|
|
94
|
+
const current = timeline.frames[frame];
|
|
95
|
+
let from = null;
|
|
96
|
+
for (const cut of timeline.cuts) {
|
|
97
|
+
if (frame > cut &&
|
|
98
|
+
frame <= cut + crossfadeFrames &&
|
|
99
|
+
timeline.frames[cut] !== current &&
|
|
100
|
+
(from === null || cut > from)) {
|
|
101
|
+
from = cut;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (from === null)
|
|
105
|
+
return { current, previous: null, alpha: 1 };
|
|
106
|
+
return {
|
|
107
|
+
current,
|
|
108
|
+
previous: timeline.frames[from],
|
|
109
|
+
alpha: crossfadeAlpha(frame, from + 1, crossfadeFrames),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
73
112
|
/** Linear fade in/out envelope, in seconds, for captions and highlights. */
|
|
74
113
|
export function fadeEnvelope(t, t0, t1, fade) {
|
|
75
114
|
if (t <= t0 || t >= t1)
|
package/dist/core/compose.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compose.js","sourceRoot":"","sources":["../../src/core/compose.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"compose.js","sourceRoot":"","sources":["../../src/core/compose.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,7 +10,7 @@ import type { Transitions } from "../config.js";
|
|
|
10
10
|
* from "the page has finished". Counting is far cheaper than diffing and
|
|
11
11
|
* needs no cooperation from the app.
|
|
12
12
|
*/
|
|
13
|
-
export declare const MUTATION_COUNTER_SCRIPT = "(() => {\n const state = {\n mutations: 0,\n ids: new WeakMap(),\n nextId: 1,\n idOf(el) {\n if (!el) return 0;\n let id = state.ids.get(el);\n if (!id) { id = state.nextId++; state.ids.set(el, id); }\n return id;\n },\n probe(t, x, y) {\n document.documentElement.style.setProperty(\"--recorder-t\", t);\n // Before the counts: a transition whose time is up is finished here
|
|
13
|
+
export declare const MUTATION_COUNTER_SCRIPT = "(() => {\n const state = {\n mutations: 0,\n ids: new WeakMap(),\n nextId: 1,\n idOf(el) {\n if (!el) return 0;\n let id = state.ids.get(el);\n if (!id) { id = state.nextId++; state.ids.set(el, id); }\n return id;\n },\n // A CSS animation is paused and scrubbed to authored time (freezeCss), and\n // a paused animation never finishes by itself: its `finished` promise\n // never resolves. Components that unmount once their exit animation has\n // finished, Base UI's dialogs, popovers, menus and tooltips among them,\n // waited on it for ever, and a closed dialog's backdrop, scrubbed to\n // opacity 0, stayed over the page and took the next click (0.5.0). So a\n // finite animation whose time is up is finished, as it would be in a\n // browser nobody is filming; one still under way keeps its scrub, and\n // one that repeats for ever never reaches an end. Transitions have their\n // clock (TRANSITION_CLOCK_SCRIPT), and animations a script made with\n // `element.animate()` are the app's own.\n finishEnded() {\n let finished = 0;\n for (const animation of document.getAnimations()) {\n if (!(\"animationName\" in animation) || !animation.effect) continue;\n if (animation.playState === \"finished\") continue;\n const timing = animation.effect.getComputedTiming();\n if (!Number.isFinite(timing.endTime)) continue;\n if (timing.localTime === null || timing.localTime < timing.endTime) continue;\n try {\n animation.finish();\n finished += 1;\n } catch {\n // An animation the page cancelled meanwhile: nothing to finish.\n }\n }\n return finished;\n },\n probe(t, x, y) {\n document.documentElement.style.setProperty(\"--recorder-t\", t);\n // Before the counts: an animation or a transition whose time is up is\n // finished here, and is no longer running when the animations are\n // counted.\n state.finishEnded();\n const clock = window.__recorderTransitions;\n const transitions = clock ? clock.sync() : 0;\n return {\n mutations: state.mutations,\n hovered: state.idOf(document.elementFromPoint(x, y)),\n animations: document.getAnimations().length,\n transitions,\n };\n },\n };\n window.__recorder = state;\n\n // The driver writes --recorder-t to <html style> on every single frame. Left\n // alone that write is a mutation like any other, so the counter would move\n // every frame and anything built on it \u2014 a settle that waits for quiet, a\n // gate that skips an unchanged frame \u2014 would be reading its own footprint.\n // Anything else that touches <html style>, a scroll lock or a theme switch,\n // still counts.\n const withoutScrub = (value) =>\n (value || \"\").replace(/--recorder-t\\s*:[^;]*;?/g, \"\").trim();\n\n const start = () => {\n const root = document.documentElement;\n const isOurScrub = (record) =>\n record.type === \"attributes\" &&\n record.target === root &&\n record.attributeName === \"style\" &&\n withoutScrub(record.oldValue) === withoutScrub(root.getAttribute(\"style\"));\n\n new MutationObserver((records) => {\n for (const record of records) {\n if (!isOurScrub(record)) state.mutations += 1;\n }\n }).observe(root || document, {\n childList: true,\n attributes: true,\n attributeOldValue: true,\n characterData: true,\n subtree: true,\n });\n };\n if (document.documentElement) start();\n else document.addEventListener(\"DOMContentLoaded\", start, { once: true });\n})();";
|
|
14
14
|
/**
|
|
15
15
|
* Plays the page's CSS transitions on the page's own clock.
|
|
16
16
|
*
|
|
@@ -47,11 +47,12 @@ export declare const MUTATION_COUNTER_SCRIPT = "(() => {\n const state = {\n
|
|
|
47
47
|
*/
|
|
48
48
|
export declare const TRANSITION_CLOCK_SCRIPT = "(() => {\n if (window !== window.top) return;\n const started = new WeakMap();\n window.__recorderTransitions = {\n sync() {\n const now = performance.now();\n let running = 0;\n for (const animation of document.getAnimations()) {\n if (!(\"transitionProperty\" in animation)) continue;\n let start = started.get(animation);\n if (start === undefined) {\n start = now;\n started.set(animation, start);\n }\n const end = animation.effect\n ? animation.effect.getComputedTiming().endTime\n : 0;\n if (now - start >= end) {\n animation.finish();\n continue;\n }\n animation.pause();\n animation.currentTime = now - start;\n running += 1;\n }\n return running;\n },\n };\n})();";
|
|
49
49
|
/**
|
|
50
|
-
* Moves every running transition to the page's clock,
|
|
51
|
-
*
|
|
52
|
-
*
|
|
50
|
+
* Moves every running transition to the page's clock, and finishes every CSS
|
|
51
|
+
* animation whose time is up, for the driver's waits that move the clock
|
|
52
|
+
* without making a frame. The frame probe and the settle loop do both as
|
|
53
|
+
* part of what they already ask the page.
|
|
53
54
|
*/
|
|
54
|
-
export declare const SYNC_TRANSITIONS
|
|
55
|
+
export declare const SYNC_TRANSITIONS: string;
|
|
55
56
|
/**
|
|
56
57
|
* Puts the page's CSS motion under the recorder's control.
|
|
57
58
|
*
|
|
@@ -116,6 +117,7 @@ declare global {
|
|
|
116
117
|
interface Window {
|
|
117
118
|
__recorder?: {
|
|
118
119
|
mutations: number;
|
|
120
|
+
finishEnded(): number;
|
|
119
121
|
probe(t: string, x: number, y: number): FrameProbe;
|
|
120
122
|
};
|
|
121
123
|
__recorderTransitions?: {
|
|
@@ -20,10 +20,40 @@ export const MUTATION_COUNTER_SCRIPT = `(() => {
|
|
|
20
20
|
if (!id) { id = state.nextId++; state.ids.set(el, id); }
|
|
21
21
|
return id;
|
|
22
22
|
},
|
|
23
|
+
// A CSS animation is paused and scrubbed to authored time (freezeCss), and
|
|
24
|
+
// a paused animation never finishes by itself: its \`finished\` promise
|
|
25
|
+
// never resolves. Components that unmount once their exit animation has
|
|
26
|
+
// finished, Base UI's dialogs, popovers, menus and tooltips among them,
|
|
27
|
+
// waited on it for ever, and a closed dialog's backdrop, scrubbed to
|
|
28
|
+
// opacity 0, stayed over the page and took the next click (0.5.0). So a
|
|
29
|
+
// finite animation whose time is up is finished, as it would be in a
|
|
30
|
+
// browser nobody is filming; one still under way keeps its scrub, and
|
|
31
|
+
// one that repeats for ever never reaches an end. Transitions have their
|
|
32
|
+
// clock (TRANSITION_CLOCK_SCRIPT), and animations a script made with
|
|
33
|
+
// \`element.animate()\` are the app's own.
|
|
34
|
+
finishEnded() {
|
|
35
|
+
let finished = 0;
|
|
36
|
+
for (const animation of document.getAnimations()) {
|
|
37
|
+
if (!("animationName" in animation) || !animation.effect) continue;
|
|
38
|
+
if (animation.playState === "finished") continue;
|
|
39
|
+
const timing = animation.effect.getComputedTiming();
|
|
40
|
+
if (!Number.isFinite(timing.endTime)) continue;
|
|
41
|
+
if (timing.localTime === null || timing.localTime < timing.endTime) continue;
|
|
42
|
+
try {
|
|
43
|
+
animation.finish();
|
|
44
|
+
finished += 1;
|
|
45
|
+
} catch {
|
|
46
|
+
// An animation the page cancelled meanwhile: nothing to finish.
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return finished;
|
|
50
|
+
},
|
|
23
51
|
probe(t, x, y) {
|
|
24
52
|
document.documentElement.style.setProperty("--recorder-t", t);
|
|
25
|
-
// Before the counts: a transition whose time is up is
|
|
26
|
-
// and is no longer running when the animations are
|
|
53
|
+
// Before the counts: an animation or a transition whose time is up is
|
|
54
|
+
// finished here, and is no longer running when the animations are
|
|
55
|
+
// counted.
|
|
56
|
+
state.finishEnded();
|
|
27
57
|
const clock = window.__recorderTransitions;
|
|
28
58
|
const transitions = clock ? clock.sync() : 0;
|
|
29
59
|
return {
|
|
@@ -132,11 +162,13 @@ export const TRANSITION_CLOCK_SCRIPT = `(() => {
|
|
|
132
162
|
};
|
|
133
163
|
})();`;
|
|
134
164
|
/**
|
|
135
|
-
* Moves every running transition to the page's clock,
|
|
136
|
-
*
|
|
137
|
-
*
|
|
165
|
+
* Moves every running transition to the page's clock, and finishes every CSS
|
|
166
|
+
* animation whose time is up, for the driver's waits that move the clock
|
|
167
|
+
* without making a frame. The frame probe and the settle loop do both as
|
|
168
|
+
* part of what they already ask the page.
|
|
138
169
|
*/
|
|
139
|
-
export const SYNC_TRANSITIONS = "window.
|
|
170
|
+
export const SYNC_TRANSITIONS = "(window.__recorder ? window.__recorder.finishEnded() : 0) + " +
|
|
171
|
+
"(window.__recorderTransitions ? window.__recorderTransitions.sync() : 0)";
|
|
140
172
|
/**
|
|
141
173
|
* Puts the page's CSS motion under the recorder's control.
|
|
142
174
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page-hooks.js","sourceRoot":"","sources":["../../src/driver/page-hooks.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG
|
|
1
|
+
{"version":3,"file":"page-hooks.js","sourceRoot":"","sources":["../../src/driver/page-hooks.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAwFjC,CAAC;AAEP;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;MA4BjC,CAAC;AAEP;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAC3B,8DAA8D;IAC9D,0EAA0E,CAAC;AAE7E;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,UAAU,SAAS,CAAC,eAAwB;IAChD,MAAM,WAAW,GAAG,eAAe;QACjC,CAAC,CAAC,6EAA6E;QAC/E,CAAC,CAAC,EAAE,CAAC;IACP,OAAO;EACP,WAAW;;;;EAIX,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,WAAwB;IACtD,OAAO;iBACQ,WAAW,KAAK,MAAM;uBAChB,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;;;;;;;;;MAStF,CAAC;AACP,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,OAAe,EAAE,CAAS,EAAE,CAAS,EAAU,EAAE,CAC3E,4BAA4B,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC"}
|
package/dist/driver/settle.js
CHANGED
|
@@ -29,13 +29,18 @@ export async function settlePage(page, inFlightRequests, options = {}) {
|
|
|
29
29
|
let lastMutations = -1;
|
|
30
30
|
let lastBlocker = "none";
|
|
31
31
|
for (;;) {
|
|
32
|
-
// The same round trip
|
|
33
|
-
//
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
// The same round trip finishes the CSS animations whose time is up, so
|
|
33
|
+
// whatever waits on them (a closed dialog unmounting) runs, and shows as
|
|
34
|
+
// DOM work on the next tick; moves the page's transitions to its clock,
|
|
35
|
+
// which the last tick advanced; and says how many are still running.
|
|
36
|
+
const probe = await page.evaluate(() => {
|
|
37
|
+
window.__recorder?.finishEnded();
|
|
38
|
+
return {
|
|
39
|
+
mutations: window.__recorder?.mutations ?? 0,
|
|
40
|
+
fontsLoaded: document.fonts ? document.fonts.status === "loaded" : true,
|
|
41
|
+
transitions: window.__recorderTransitions?.sync() ?? 0,
|
|
42
|
+
};
|
|
43
|
+
});
|
|
39
44
|
const requests = inFlightRequests();
|
|
40
45
|
const hookOk = options.hook ? await options.hook() : true;
|
|
41
46
|
// A running transition touches no DOM and no network, so the other
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settle.js","sourceRoot":"","sources":["../../src/driver/settle.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,IAAI,KAAK,EAAE,MAAM,sBAAsB,CAAC;AA0B3D,4EAA4E;AAC5E,MAAM,CAAC,MAAM,OAAO,GAAG,EAAE,CAAC;AAC1B,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAE5B;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,IAAU,EACV,gBAA8B,EAC9B,UAAyB,EAAE;IAE3B,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,GAAG,CAAC;IACvC,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,MAAM,CAAC;IAC9C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,QAAQ,CAAC;IACxC,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IAE9D,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC3B,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,aAAa,GAAG,CAAC,CAAC,CAAC;IACvB,IAAI,WAAW,GAAG,MAAM,CAAC;IAEzB,SAAS,CAAC;QACR,uEAAuE;QACvE
|
|
1
|
+
{"version":3,"file":"settle.js","sourceRoot":"","sources":["../../src/driver/settle.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,IAAI,KAAK,EAAE,MAAM,sBAAsB,CAAC;AA0B3D,4EAA4E;AAC5E,MAAM,CAAC,MAAM,OAAO,GAAG,EAAE,CAAC;AAC1B,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAE5B;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,IAAU,EACV,gBAA8B,EAC9B,UAAyB,EAAE;IAE3B,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,GAAG,CAAC;IACvC,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,MAAM,CAAC;IAC9C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,QAAQ,CAAC;IACxC,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IAE9D,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC3B,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,aAAa,GAAG,CAAC,CAAC,CAAC;IACvB,IAAI,WAAW,GAAG,MAAM,CAAC;IAEzB,SAAS,CAAC;QACR,uEAAuE;QACvE,yEAAyE;QACzE,wEAAwE;QACxE,qEAAqE;QACrE,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE;YACrC,MAAM,CAAC,UAAU,EAAE,WAAW,EAAE,CAAC;YACjC,OAAO;gBACL,SAAS,EAAE,MAAM,CAAC,UAAU,EAAE,SAAS,IAAI,CAAC;gBAC5C,WAAW,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI;gBACvE,WAAW,EAAE,MAAM,CAAC,qBAAqB,EAAE,IAAI,EAAE,IAAI,CAAC;aACvD,CAAC;QACJ,CAAC,CAAC,CAAC;QACH,MAAM,QAAQ,GAAG,gBAAgB,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QAE1D,mEAAmE;QACnE,0EAA0E;QAC1E,oEAAoE;QACpE,wEAAwE;QACxE,uDAAuD;QACvD,MAAM,KAAK,GACT,KAAK,CAAC,SAAS,KAAK,aAAa;YACjC,QAAQ,KAAK,CAAC;YACd,KAAK,CAAC,WAAW;YACjB,KAAK,CAAC,WAAW,KAAK,CAAC;YACvB,MAAM,CAAC;QAET,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,IAAI,KAAK,CAAC,SAAS,KAAK,aAAa;gBAAE,WAAW,GAAG,KAAK,CAAC;iBACtD,IAAI,QAAQ,GAAG,CAAC;gBAAE,WAAW,GAAG,YAAY,QAAQ,GAAG,CAAC;iBACxD,IAAI,CAAC,KAAK,CAAC,WAAW;gBAAE,WAAW,GAAG,OAAO,CAAC;iBAC9C,IAAI,KAAK,CAAC,WAAW,GAAG,CAAC;gBAC5B,WAAW,GAAG,eAAe,KAAK,CAAC,WAAW,GAAG,CAAC;;gBAC/C,WAAW,GAAG,MAAM,CAAC;QAC5B,CAAC;QAED,aAAa,GAAG,KAAK,CAAC,SAAS,CAAC;QAChC,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACxC,IAAI,UAAU,IAAI,WAAW,EAAE,CAAC;YAC9B,OAAO;gBACL,KAAK;gBACL,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO;gBAC/B,KAAK;gBACL,QAAQ,EAAE,KAAK;gBACf,WAAW;aACZ,CAAC;QACJ,CAAC;QAED,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,GAAG,SAAS,EAAE,CAAC;YACrC,sEAAsE;YACtE,wEAAwE;YACxE,mBAAmB;YACnB,OAAO,CAAC,IAAI,CACV,cAAc,KAAK,0BAA0B,SAAS,KAAK;gBACzD,UAAU,WAAW,4CAA4C;gBACjE,mBAAmB,CACtB,CAAC;YACF,OAAO;gBACL,KAAK;gBACL,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO;gBAC/B,KAAK;gBACL,QAAQ,EAAE,IAAI;gBACd,WAAW;aACZ,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACjC,MAAM,KAAK,CAAC,OAAO,CAAC,OAAO,IAAI,gBAAgB,CAAC,CAAC;QACjD,KAAK,IAAI,CAAC,CAAC;IACb,CAAC;AACH,CAAC"}
|
package/dist/env.d.ts
CHANGED
|
@@ -9,3 +9,9 @@
|
|
|
9
9
|
export declare function loadEnvFiles(cwd: string): void;
|
|
10
10
|
/** `process.env` as the shell handed it over: what a child should inherit. */
|
|
11
11
|
export declare function inheritedEnv(): NodeJS.ProcessEnv;
|
|
12
|
+
/**
|
|
13
|
+
* The file that set `name`, `.env.recording` or `.env`, or null when the
|
|
14
|
+
* shell set it or nothing did. A file never overrides the shell, so a name
|
|
15
|
+
* with a file is one the shell left unset.
|
|
16
|
+
*/
|
|
17
|
+
export declare function loadedFrom(name: string): string | null;
|
package/dist/env.js
CHANGED
|
@@ -10,9 +10,14 @@ import { resolve } from "node:path";
|
|
|
10
10
|
* are the reason `.env.recording` is a separate file at all, and Vite gives a
|
|
11
11
|
* variable already in its environment priority over the app's own `.env` —
|
|
12
12
|
* so a value the recorder loaded for itself would quietly change how the app
|
|
13
|
-
* it is filming behaves.
|
|
13
|
+
* it is filming behaves. And `versioncam cloud` takes nothing from a file at
|
|
14
|
+
* all: the files are the repository's, and a cloned repository must not
|
|
15
|
+
* choose where a person's sign-in goes.
|
|
16
|
+
*
|
|
17
|
+
* Each name maps to the file it came from, so a command that ignores one
|
|
18
|
+
* can say which file set it.
|
|
14
19
|
*/
|
|
15
|
-
const fromFiles = new
|
|
20
|
+
const fromFiles = new Map();
|
|
16
21
|
/**
|
|
17
22
|
* Load `.env.recording`, then `.env`, before anything reads the environment.
|
|
18
23
|
*
|
|
@@ -30,7 +35,7 @@ export function loadEnvFiles(cwd) {
|
|
|
30
35
|
process.loadEnvFile(file);
|
|
31
36
|
for (const key of Object.keys(process.env)) {
|
|
32
37
|
if (!before.has(key))
|
|
33
|
-
fromFiles.
|
|
38
|
+
fromFiles.set(key, name);
|
|
34
39
|
}
|
|
35
40
|
}
|
|
36
41
|
}
|
|
@@ -38,4 +43,12 @@ export function loadEnvFiles(cwd) {
|
|
|
38
43
|
export function inheritedEnv() {
|
|
39
44
|
return Object.fromEntries(Object.entries(process.env).filter(([key]) => !fromFiles.has(key)));
|
|
40
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* The file that set `name`, `.env.recording` or `.env`, or null when the
|
|
48
|
+
* shell set it or nothing did. A file never overrides the shell, so a name
|
|
49
|
+
* with a file is one the shell left unset.
|
|
50
|
+
*/
|
|
51
|
+
export function loadedFrom(name) {
|
|
52
|
+
return process.env[name] === undefined ? null : (fromFiles.get(name) ?? null);
|
|
53
|
+
}
|
|
41
54
|
//# sourceMappingURL=env.js.map
|
package/dist/env.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env.js","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;AAE5C;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,KAAK,MAAM,IAAI,IAAI,CAAC,gBAAgB,EAAE,MAAM,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAChC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,SAAS;QAChC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;QACjD,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAC1B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YAC3C,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,YAAY;IAC1B,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CACnE,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC;AAChF,CAAC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();function e(e){let n=t(e);return n*n*n*(10+n*(-15+6*n))}function t(e){return e<=0?0:e>=1?1:e}function n(e,t,n){return e+(t-e)*n}function r(e,t,r){let i=e.x+e.w/2,a=e.y+e.h/2,o=t.x+t.w/2,s=t.y+t.h/2,c=e.w*(t.w/e.w)**+r,l=e.h*(t.h/e.h)**+r,u=n(i,o,r),d=n(a,s,r);return{x:u-c/2,y:d-l/2,w:c,h:l}}function i(e,t,r){return{x:n(e.x,t.x,r),y:n(e.y,t.y,r),w:n(e.w,t.w,r),h:n(e.h,t.h,r)}}function a(t,n){if(t.length===0)throw Error(`evalCamera called with no keys`);if(n<=t[0].t)return t[0].rect;for(let a=1;a<t.length;a+=1){let o=t[a-1],s=t[a];if(n>=s.t)continue;if(s.ease===`hold`)return o.rect;let c=s.t-o.t,l=c<=0?1:(n-o.t)/c;return s.ease===`linear`?i(o.rect,s.rect,l):r(o.rect,s.rect,e(l))}return t[t.length-1].rect}function o(e,t,n,r){let i=1-r,a=i*i,o=2*i*r,s=r*r;return[a*e[0]+o*t[0]+s*n[0],a*e[1]+o*t[1]+s*n[1]]}function s(t,n){if(t.length===0)return[0,0];let r=t[0];if(n<=r.t0)return r.kind===`move`?r.from:r.at;for(let r of t){if(n>r.t1)continue;if(r.kind===`hold`)return r.at;let t=r.t1-r.t0,i=t<=0?1:(n-r.t0)/t;return o(r.from,r.ctrl,r.to,e(i))}let i=t[t.length-1];return i.kind===`move`?i.to:i.at}function c(e,t,n){let r=n.w/t.w;return[n.x+(e[0]-t.x)*r,n.y+(e[1]-t.y)*r]}function l(e,t,n){let r=n.w/t.w;return{x:n.x+(e.x-t.x)*r,y:n.y+(e.y-t.y)*r,w:e.w*r,h:e.h*r}}function u(e,t){return{x:e.x*t,y:e.y*t,w:e.w*t,h:e.h*t}}function d(e,t,n){let r=Math.min(e.width,e.height)*n,i=e.width-r*2,a=e.height-r*2,o=t.width/t.height,s=i,c=s/o;return c>a&&(c=a,s=c*o),{x:(e.width-s)/2,y:(e.height-c)/2,w:s,h:c}}function f(e,n,r){return r<=0?1:t((e-n+1)/r)}function p(e,t,n){let r=e.frames[t],i=null;for(let a of e.cuts)t>a&&t<=a+n&&e.frames[a]!==r&&(i===null||a>i)&&(i=a);return i===null?{current:r,previous:null,alpha:1}:{current:r,previous:e.frames[i],alpha:f(t,i+1,n)}}function m(e,n,r,i){return e<=n||e>=r?0:i<=0?1:Math.min(t((e-n)/i),t((r-e)/i))}function ee(e,t){return e/t}function te(e,t,n){let r=n?.padding??0;return!n||r<=0?{x:0,y:0,w:e.width,h:e.height}:d(e,t,r)}function h(e){let t=e?.caption??`auto`;return t===`none`?`none`:t===`below`||t===`overlay`?t:(e?.padding??0)>0?`below`:`overlay`}function ne(e,t){let n=e?.captionInset;return n?.right===void 0?{x:n?.left??40,align:`left`}:{x:t-n.right,align:`right`}}var g={radius:16,hairline:`rgba(255, 255, 255, 0.16)`,shadow:`rgba(0, 0, 0, 0.45)`,shadowBlur:60,shadowOffsetY:18,captionFont:`600 30px "Helvetica Neue", Helvetica, Arial, "Liberation Sans", sans-serif`,captionColor:`rgba(255, 255, 255, 0.94)`,captionShadow:`rgba(0, 0, 0, 0.5)`,captionScrim:`rgba(0, 0, 0, 0.45)`,captionScrimHeight:86,cursorFill:`#ffffff`,cursorStroke:`rgba(0, 0, 0, 0.55)`,cursorShadow:`rgba(0, 0, 0, 0.35)`,ringWidth:3,ringRadius:10,spotlightDim:.55,spotlightTint:`6, 2, 16`};function re(e,t){let n=/^#([0-9a-f]{6})$/i.exec(e.trim());if(!n)return e;let r=Number.parseInt(n[1],16);return`rgba(${r>>16&255}, ${r>>8&255}, ${r&255}, ${t})`}function _(e,t,n){let r=Math.min(n,t.w/2,t.h/2);e.beginPath(),e.moveTo(t.x+r,t.y),e.arcTo(t.x+t.w,t.y,t.x+t.w,t.y+t.h,r),e.arcTo(t.x+t.w,t.y+t.h,t.x,t.y+t.h,r),e.arcTo(t.x,t.y+t.h,t.x,t.y,r),e.arcTo(t.x,t.y,t.x+t.w,t.y,r),e.closePath()}function ie(e,t,n){if(typeof n==`string`)e.fillStyle=n;else{let r=e.createLinearGradient(0,0,t.width,t.height);r.addColorStop(0,n[0]),r.addColorStop(1,n[1]),e.fillStyle=r}e.fillRect(0,0,t.width,t.height)}function v(e,t,n,r,i,a,o){let s=u(i,t.viewport.dpr),{current:c,previous:l,alpha:d}=p(t,r,o.motion.crossfadeFrames),f=o.theme.presentation?.frame??!1;e.save(),f&&(_(e,a,g.radius),e.clip());let m=(t,r)=>{let i=n.images[t];i&&(e.globalAlpha=r,e.drawImage(i,s.x,s.y,s.w,s.h,a.x,a.y,a.w,a.h))};l!==null&&m(l,1),m(c,l===null?1:d),e.globalAlpha=1,e.restore()}function y(e,t){e.save(),e.shadowColor=g.shadow,e.shadowBlur=g.shadowBlur,e.shadowOffsetY=g.shadowOffsetY,e.fillStyle=`rgba(0,0,0,1)`,_(e,t,g.radius),e.fill(),e.restore()}function b(e,t){e.save(),e.strokeStyle=g.hairline,e.lineWidth=1,_(e,t,g.radius),e.stroke(),e.restore()}function x(e,t){return{x:e.x-t,y:e.y-t,w:e.w+t*2,h:e.h+t*2}}function S(e,t,n,r,i,a){let o=a.theme.presentation?.frame??!1;for(let s of t.highlights){let t=m(n,s.t0,s.t1,.25);if(t<=0)continue;let c=l(s.rect,r,i);e.save(),e.globalAlpha=t,s.style===`spotlight`?(e.save(),_(e,i,o?g.radius:0),e.clip(),e.fillStyle=`rgba(${g.spotlightTint}, ${g.spotlightDim})`,e.fillRect(i.x,i.y,i.w,i.h),e.globalCompositeOperation=`destination-out`,_(e,x(c,8),g.ringRadius),e.fill(),e.restore()):(e.strokeStyle=a.theme.accent,e.lineWidth=g.ringWidth,e.shadowColor=re(a.theme.accent,.35),e.shadowBlur=18,_(e,x(c,6),g.ringRadius),e.stroke()),e.restore()}}function C(e,t,n){let r=!1,i=[],a=0;for(let o of e.pointer){if(o.t>t)break;if(o.kind===`down`)r=!0,a=o.t;else{r=!1;let e=t-o.t;e>=0&&e<=n.motion.rippleMs/1e3&&i.push({at:o.at,age:e})}}let o=r?t-a:0,s=r?Math.min(1,o/(n.motion.pressScaleMs/1e3)):0;return{scale:1-(1-n.motion.pressScale)*s,ripples:i}}function w(e,t,n,r,i){for(let a of t){let t=a.age/(i.motion.rippleMs/1e3),[o,s]=c(a.at,n,r);e.save(),e.globalAlpha=(1-t)*.55,e.strokeStyle=i.theme.accent,e.lineWidth=2.5,e.beginPath(),e.arc(o,s,6+t*i.motion.rippleRadius,0,Math.PI*2),e.stroke(),e.restore()}}function T(e,t,n,r){let i=r*n;e.save(),e.translate(t[0],t[1]),e.scale(i,i),e.shadowColor=g.cursorShadow,e.shadowBlur=6/i,e.shadowOffsetY=2/i,e.beginPath(),e.moveTo(0,0),e.lineTo(0,16.6),e.lineTo(4.1,12.9),e.lineTo(6.9,18.9),e.lineTo(9.6,17.6),e.lineTo(6.9,11.8),e.lineTo(12.1,11.5),e.closePath(),e.fillStyle=g.cursorFill,e.fill(),e.shadowColor=`transparent`,e.strokeStyle=g.cursorStroke,e.lineWidth=1/i,e.stroke(),e.restore()}function E(e,t,n,r,i,a){let o=h(a.theme.presentation);if(o!==`none`)for(let s of t.captions){let t=m(n,s.t0,s.t1,a.motion.captionFadeS);if(t<=0)continue;if(e.save(),e.globalAlpha=t,o===`overlay`){let t=g.captionScrimHeight,n=e.createLinearGradient(0,i.height-t,0,i.height);n.addColorStop(0,`rgba(0, 0, 0, 0)`),n.addColorStop(1,g.captionScrim),e.fillStyle=n,e.fillRect(0,i.height-t,i.width,t)}e.font=g.captionFont,e.fillStyle=g.captionColor,e.textBaseline=`middle`,e.shadowColor=g.captionShadow,e.shadowBlur=8;let c=r.x,l=(r.y+r.h+i.height)/2;if(o===`overlay`){let t=ne(a.theme.presentation,i.width);e.textAlign=t.align,c=t.x,l=i.height-g.captionScrimHeight/2+4}e.fillText(s.text,c,l),e.restore()}}function ae(e,t,n,r,i,o){let l=ee(r,t.fps),u=a(t.camera,l),d=o.theme.presentation,f=te(i,t.viewport,d);d?.backdrop&&ie(e,i,d.backdrop),d?.frame&&y(e,f),v(e,t,n,r,u,f,o),d?.frame&&b(e,f),S(e,t,l,u,f,o);let{scale:p,ripples:m}=C(t,l,o);w(e,m,u,f,o),T(e,c(s(t.cursor,l),u,f),p,o.theme.cursorScale),E(e,t,l,f,i,o)}var D="versioncam reads scenes from a module's default export: a Record<string, Scene> keyed by scene id, as in `export default { [intro.id]: intro }`.";function O(e){return e==null?String(e):Array.isArray(e)?`an array`:`a ${typeof e}`}function k(e){return typeof e==`string`?JSON.stringify(e):String(e)}function A(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function oe(e,t){if(!A(t))return`"${e}" is ${O(t)}, not a scene`;let{draw:n,durationFrames:r,fps:i}=t;return typeof n==`function`?!Number.isInteger(r)||r<1?`"${e}" has durationFrames ${k(r)}, where a whole number of frames, 1 or more, belongs`:typeof i!=`number`||!Number.isFinite(i)||i<=0?`"${e}" has fps ${k(i)}, where a number above 0 belongs`:null:`"${e}" has no draw(ctx, frame, canvas)`}function j(e){if(!A(e))return O(e);if(typeof e.draw==`function`)return`a single scene rather than a record of them`;for(let[t,n]of Object.entries(e)){let e=oe(t,n);if(e)return`a record in which ${e}`}return null}function M(e,t){if(e.default===void 0){let n=Object.keys(e).filter(e=>e!=="default"),r=[`${t} has no default export.`+(n.length>0?` It exports ${n.join(`, `)}.`:``),D],i=n.filter(t=>j(e[t])===null&&Object.keys(e[t]).length>0);return i.length===1&&r.push(`${i[0]} is one: add \`export default ${i[0]}\`.`),{error:r.join(`
|
|
2
|
+
`)}}let n=j(e.default);return n?{error:`${t} default-exports ${n}.\n${D}`}:{scenes:e.default}}function N(e,t,n){let r=e.map(e=>`"${e}"`).join(`, `),i=`No scene${e.length===1?``:`s`} called ${r}.`;return n===null?`${i} The config names no \`scenes\` module.`:`${i} ${n} defines ${t.length>0?t.join(`, `):`none`}.`}var P=`modulepreload`,F=function(e,t){return new URL(e,t).href},I={},L=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e=document.getElementsByTagName(`link`),i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}function s(e){return import.meta.resolve?import.meta.resolve(e):new URL(e,import.meta.url).href}r=o(t.map(t=>{if(t=F(t,n),t=s(t),t in I)return;I[t]=!0;let r=t.endsWith(`.css`);for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}let i=document.createElement(`link`);if(i.rel=r?`stylesheet`:P,r||(i.as=`script`),i.crossOrigin=``,i.href=t,a&&i.setAttribute(`nonce`,a),document.head.appendChild(i),r)return new Promise((e,n)=>{i.addEventListener(`load`,e),i.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${t}`)))})}).filter(e=>e!==void 0))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})},R=new URLSearchParams(location.search),z=R.has(`recording`),B=R.get(`scene`),V=R.get(`headless`)===`1`;V&&document.body.classList.add(`headless`);var H=document.getElementById(`stage`),U=document.getElementById(`scrub`),W=document.getElementById(`status`),G=document.getElementById(`play`),K=document.getElementById(`error`);function q(e){throw K.textContent=e,Error(e)}async function J(e,t){let n=await fetch(e);return n.ok||q(`Could not load ${t} (${e}): ${n.status}`),await n.json()}async function se(e){let t=await fetch(e);return t.ok||q(`Could not load ${e}: ${t.status}`),createImageBitmap(await t.blob())}function Y(e){H.width=e.output.width,H.height=e.output.height,V?(H.style.width=`${e.output.width}px`,H.style.height=`${e.output.height}px`):(H.style.width=`min(100%, 1280px)`,H.style.height=`auto`);let t=H.getContext(`2d`,{alpha:!1});return t||q(`No 2D context`),t.imageSmoothingEnabled=!0,t.imageSmoothingQuality=`high`,t}function X(e,t,n,r){let i=!1;G.addEventListener(`click`,()=>{i=!i,G.textContent=i?`Pause`:`Play`;let a=performance.now(),o=s=>{i&&(s-a>=1e3/e&&(a=s,r((n()+1)%t)),requestAnimationFrame(o))};requestAnimationFrame(o)})}function Z(e,t,n,r){e.durationFrames=t,e.fps=n,e.setFrame=e=>new Promise(t=>{r(e),requestAnimationFrame(()=>requestAnimationFrame(()=>t()))})}async function Q(e,t){let n=await J(`/recording/timeline.json`,`the recording`),r=Y(t),i={images:await Promise.all(n.states.map(e=>se(`/recording/states/${e}`)))};await document.fonts.ready;let a=-1,o=e=>{let o=Math.max(0,Math.min(n.durationFrames-1,e));ae(r,n,i,o,H,t),a=o,V||(U.value=String(o),W.textContent=`${o+1} / ${n.durationFrames} · ${(o/n.fps).toFixed(2)}s · state ${n.frames[o]}`)};U.max=String(n.durationFrames-1),U.addEventListener(`input`,()=>o(Number(U.value))),X(n.fps,n.durationFrames,()=>a,o),o(Number(R.get(`frame`)??0)),Z(e,n.durationFrames,n.fps,o)}async function ce(e,t,n){t.scenes===null&&q(N([n],[],null));let r=M(await L(()=>import(`/scenes.js`),[],import.meta.url),t.scenes);`error`in r&&q(r.error);let i=r.scenes[n];i||q(N([n],Object.keys(r.scenes),t.scenes));let a=Y(t);await document.fonts.ready;let o=-1,s=e=>{let t=Math.max(0,Math.min(i.durationFrames-1,e));i.draw(a,t,H),o=t,V||(U.value=String(t),W.textContent=`${t+1} / ${i.durationFrames} · ${(t/i.fps).toFixed(2)}s`)};U.max=String(i.durationFrames-1),U.addEventListener(`input`,()=>s(Number(U.value))),X(i.fps,i.durationFrames,()=>o,s),s(Number(R.get(`frame`)??0)),Z(e,i.durationFrames,i.fps,s)}async function le(e){let t=await J(`/render-config.json`,`the render config`);if(B)return ce(e,t,B);if(z)return Q(e,t);q(`Pass ?recording or ?scene=<id>.`)}var $={ready:Promise.resolve(),setFrame:async()=>{},durationFrames:0,fps:60};window.__render=$,$.ready=le($);
|
package/dist/page/index.html
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="utf-8" />
|
|
5
5
|
<title>versioncam render</title>
|
|
6
6
|
<style>*{box-sizing:border-box;margin:0;padding:0;transition:none!important;animation:none!important}body{color:#e8e2f5;background:#0b0614;flex-direction:column;align-items:center;min-height:100vh;font-family:Helvetica Neue,Helvetica,Arial,sans-serif;display:flex}body.headless{background:0 0;display:block}#stage{display:block}body.headless #stage{position:fixed;inset:0}#controls{align-items:center;gap:14px;width:min(100%,1280px);padding:14px 18px 28px;font-size:13px;display:flex}body.headless #controls{display:none}#scrub{flex:1}#status{font-variant-numeric:tabular-nums;white-space:nowrap;opacity:.75}button{font:inherit;color:#fff;cursor:pointer;background:#2f6fed;border:0;border-radius:6px;padding:6px 14px}#error{color:#ff9a9a;white-space:pre-wrap;padding:24px;font-family:ui-monospace,Menlo,monospace}</style>
|
|
7
|
-
<script type="module" crossorigin src="./assets/index-
|
|
7
|
+
<script type="module" crossorigin src="./assets/index-BtUbUEdN.js"></script>
|
|
8
8
|
</head>
|
|
9
9
|
<body>
|
|
10
10
|
<canvas id="stage"></canvas>
|
package/package.json
CHANGED
package/plugin/README.md
CHANGED
|
@@ -6,9 +6,9 @@ what the reviewer finds. It stops when the reviewer passes the clip or the
|
|
|
6
6
|
rounds run out. The first time it runs in a repository, it sets the
|
|
7
7
|
repository up first.
|
|
8
8
|
|
|
9
|
-
Nothing here calls
|
|
10
|
-
skill, and the vision step is that session's file reader opening a
|
|
11
|
-
sheet. Everything is markdown, and you can edit all of it.
|
|
9
|
+
Nothing here calls a model's API. The model is whichever agent session runs
|
|
10
|
+
the skill, and the vision step is that session's file reader opening a
|
|
11
|
+
contact sheet. Everything is markdown, and you can edit all of it.
|
|
12
12
|
|
|
13
13
|
## Install
|
|
14
14
|
|
|
@@ -81,8 +81,28 @@ a checklist to the session's own sheet. The verdict records which, as
|
|
|
81
81
|
`"reviewer": "restricted"`, `"unrestricted"` or `"self"`. A clip passed by its
|
|
82
82
|
own author is a weaker claim, and says so.
|
|
83
83
|
|
|
84
|
-
|
|
85
|
-
|
|
84
|
+
Writing a clip never runs `git`. The clip lands in your clips directory as an
|
|
85
|
+
ordinary file, for you to read and commit yourself.
|
|
86
|
+
|
|
87
|
+
## version.cam
|
|
88
|
+
|
|
89
|
+
Once a repository publishes to version.cam, the same skill reads what is
|
|
90
|
+
there, and changes it, through the `versioncam cloud` commands
|
|
91
|
+
(`skills/versioncam/platform.md`):
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
/versioncam status which clips are broken, since when, and what plays meanwhile
|
|
95
|
+
/versioncam fix [clip] why one broke, a repair, and a pull request for it
|
|
96
|
+
/versioncam embed <clip> the snippet for a README, a docs page or a landing page
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
It answers questions about the project as well: who can see its clips, who
|
|
100
|
+
is told when one breaks, and the plan. It changes a setting only when you
|
|
101
|
+
ask, and the change waits for you to approve it in your browser. A fix ends
|
|
102
|
+
in a pull request, which it opens only with your yes. The token the commands
|
|
103
|
+
sign in with stays in its file, and the skill never reads or prints it.
|
|
104
|
+
Paying, deleting a project and tokens for CI outside GitHub stay on
|
|
105
|
+
app.version.cam.
|
|
86
106
|
|
|
87
107
|
## What it leaves behind
|
|
88
108
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: versioncam
|
|
3
|
-
description: Record a short demo clip — a screencast, a short video, a GIF of a feature — of this repository's web app from one sentence of what it should show, and iterate until a reviewer passes it from a contact sheet. Use when someone asks to record, film or make a demo of a feature, or to set versioncam up in a repository. Works in any repository with a web app — the first run writes versioncam.config.ts, works out how to start the app, and proves the app records the same way twice before anything is authored.
|
|
3
|
+
description: Record a short demo clip — a screencast, a short video, a GIF of a feature — of this repository's web app from one sentence of what it should show, and iterate until a reviewer passes it from a contact sheet. Use when someone asks to record, film or make a demo of a feature, or to set versioncam up in a repository. Works in any repository with a web app — the first run writes versioncam.config.ts, works out how to start the app, and proves the app records the same way twice before anything is authored. Also the repository's clips on version.cam: which are broken and why, fixing one, embedding one, who can see them, who is told, and the plan (/versioncam status, /versioncam fix [clip], /versioncam embed <clip>).
|
|
4
4
|
user-invocable: true
|
|
5
|
-
argument-hint: "\"<what the clip should show>\" [--id <slug>] [--max-rounds 6]"
|
|
5
|
+
argument-hint: "\"<what the clip should show>\" [--id <slug>] [--max-rounds 6] | status | fix [clip] | embed <clip>"
|
|
6
6
|
allowed-tools:
|
|
7
7
|
- Agent
|
|
8
8
|
- SendMessage
|
|
@@ -28,9 +28,21 @@ the clip; a reviewer who has never seen how it was written looks at a picture
|
|
|
28
28
|
of it and says whether it shows what it claims; and you go round again until it
|
|
29
29
|
does, or the rounds run out.
|
|
30
30
|
|
|
31
|
-
Follow these steps in order.
|
|
32
|
-
skill's directory: `onboarding.md` and `
|
|
33
|
-
when a step says to.
|
|
31
|
+
Follow these steps in order. Three more files sit beside this one, in this
|
|
32
|
+
skill's directory: `onboarding.md`, `authoring.md` and `platform.md`. They
|
|
33
|
+
are briefs, read when a step says to.
|
|
34
|
+
|
|
35
|
+
## Which brief
|
|
36
|
+
|
|
37
|
+
`/versioncam status`, `/versioncam fix [clip]`, `/versioncam embed <clip>`,
|
|
38
|
+
and any question about this repository's clips on version.cam (which are
|
|
39
|
+
broken, what plays meanwhile, who can see them, who is told when one breaks,
|
|
40
|
+
the plan) are not a clip to record. Read `platform.md` and follow it instead
|
|
41
|
+
of the steps below. It sends you to step 0 when it needs the app's
|
|
42
|
+
directory, and back to `authoring.md` and steps 3 and 4 to fix a clip.
|
|
43
|
+
|
|
44
|
+
Anything else is a clip to record, and so is a quoted sentence, whatever it
|
|
45
|
+
says (`/versioncam "Show the status page"`): go on with step 0.
|
|
34
46
|
|
|
35
47
|
## 0. Where, and which phase
|
|
36
48
|
|