hyperframes 0.4.23 → 0.4.24
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/cli.js +955 -360
- package/dist/commands/layout-audit.browser.js +423 -0
- package/dist/skills/hyperframes/SKILL.md +17 -0
- package/dist/skills/hyperframes-cli/SKILL.md +26 -4
- package/dist/studio/assets/{index-D0VntLIQ.js → index-CAscydDF.js} +27 -27
- package/dist/studio/assets/{index-kT65pCwW.css → index-dpgHnQGg.css} +1 -1
- package/dist/studio/index.html +2 -2
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -54,7 +54,7 @@ var VERSION;
|
|
|
54
54
|
var init_version = __esm({
|
|
55
55
|
"src/version.ts"() {
|
|
56
56
|
"use strict";
|
|
57
|
-
VERSION = true ? "0.4.
|
|
57
|
+
VERSION = true ? "0.4.24" : "0.0.0-dev";
|
|
58
58
|
}
|
|
59
59
|
});
|
|
60
60
|
|
|
@@ -9973,7 +9973,7 @@ import { get as httpsGet } from "https";
|
|
|
9973
9973
|
import { pipeline } from "stream/promises";
|
|
9974
9974
|
function downloadFile(url, dest) {
|
|
9975
9975
|
const tmp = `${dest}.tmp`;
|
|
9976
|
-
return new Promise((
|
|
9976
|
+
return new Promise((resolve39, reject) => {
|
|
9977
9977
|
const follow = (u) => {
|
|
9978
9978
|
httpsGet(u, (res) => {
|
|
9979
9979
|
if (res.statusCode === 301 || res.statusCode === 302) {
|
|
@@ -9990,7 +9990,7 @@ function downloadFile(url, dest) {
|
|
|
9990
9990
|
const file = createWriteStream(tmp);
|
|
9991
9991
|
pipeline(res, file).then(() => {
|
|
9992
9992
|
renameSync(tmp, dest);
|
|
9993
|
-
|
|
9993
|
+
resolve39();
|
|
9994
9994
|
}).catch((err) => {
|
|
9995
9995
|
try {
|
|
9996
9996
|
unlinkSync(tmp);
|
|
@@ -10708,7 +10708,7 @@ function hasNpx() {
|
|
|
10708
10708
|
}
|
|
10709
10709
|
}
|
|
10710
10710
|
function runSkillsAdd(repo) {
|
|
10711
|
-
return new Promise((
|
|
10711
|
+
return new Promise((resolve39, reject) => {
|
|
10712
10712
|
const child = spawn("npx", ["skills", "add", repo, "--all"], {
|
|
10713
10713
|
stdio: "inherit",
|
|
10714
10714
|
timeout: 12e4,
|
|
@@ -10722,7 +10722,7 @@ function runSkillsAdd(repo) {
|
|
|
10722
10722
|
env: { ...process.env, GIT_CLONE_PROTECTION_ACTIVE: "0" }
|
|
10723
10723
|
});
|
|
10724
10724
|
child.on("close", (code, signal) => {
|
|
10725
|
-
if (code === 0)
|
|
10725
|
+
if (code === 0) resolve39();
|
|
10726
10726
|
else if (signal === "SIGINT" || code === 130) process.exit(0);
|
|
10727
10727
|
else reject(new Error(`npx skills add exited with code ${code}`));
|
|
10728
10728
|
});
|
|
@@ -14856,10 +14856,10 @@ function compareDocumentPosition(nodeA, nodeB) {
|
|
|
14856
14856
|
function uniqueSort(nodes) {
|
|
14857
14857
|
nodes = nodes.filter((node, i2, arr) => !arr.includes(node, i2 + 1));
|
|
14858
14858
|
nodes.sort((a, b) => {
|
|
14859
|
-
const
|
|
14860
|
-
if (
|
|
14859
|
+
const relative7 = compareDocumentPosition(a, b);
|
|
14860
|
+
if (relative7 & DocumentPosition.PRECEDING) {
|
|
14861
14861
|
return -1;
|
|
14862
|
-
} else if (
|
|
14862
|
+
} else if (relative7 & DocumentPosition.FOLLOWING) {
|
|
14863
14863
|
return 1;
|
|
14864
14864
|
}
|
|
14865
14865
|
return 0;
|
|
@@ -15321,8 +15321,8 @@ var init_custom_element_registry = __esm({
|
|
|
15321
15321
|
} : (element) => element.localName === localName;
|
|
15322
15322
|
registry.set(localName, { Class, check });
|
|
15323
15323
|
if (waiting.has(localName)) {
|
|
15324
|
-
for (const
|
|
15325
|
-
|
|
15324
|
+
for (const resolve39 of waiting.get(localName))
|
|
15325
|
+
resolve39(Class);
|
|
15326
15326
|
waiting.delete(localName);
|
|
15327
15327
|
}
|
|
15328
15328
|
ownerDocument.querySelectorAll(
|
|
@@ -15362,13 +15362,13 @@ var init_custom_element_registry = __esm({
|
|
|
15362
15362
|
*/
|
|
15363
15363
|
whenDefined(localName) {
|
|
15364
15364
|
const { registry, waiting } = this;
|
|
15365
|
-
return new Promise((
|
|
15365
|
+
return new Promise((resolve39) => {
|
|
15366
15366
|
if (registry.has(localName))
|
|
15367
|
-
|
|
15367
|
+
resolve39(registry.get(localName).Class);
|
|
15368
15368
|
else {
|
|
15369
15369
|
if (!waiting.has(localName))
|
|
15370
15370
|
waiting.set(localName, []);
|
|
15371
|
-
waiting.get(localName).push(
|
|
15371
|
+
waiting.get(localName).push(resolve39);
|
|
15372
15372
|
}
|
|
15373
15373
|
});
|
|
15374
15374
|
}
|
|
@@ -25731,7 +25731,7 @@ async function pollPageExpression(page, expression, timeoutMs, intervalMs = 100)
|
|
|
25731
25731
|
while (Date.now() < deadline) {
|
|
25732
25732
|
const ready = Boolean(await page.evaluate(expression));
|
|
25733
25733
|
if (ready) return true;
|
|
25734
|
-
await new Promise((
|
|
25734
|
+
await new Promise((resolve39) => setTimeout(resolve39, intervalMs));
|
|
25735
25735
|
}
|
|
25736
25736
|
return Boolean(await page.evaluate(expression));
|
|
25737
25737
|
}
|
|
@@ -25753,8 +25753,12 @@ async function initializeSession(session) {
|
|
|
25753
25753
|
}
|
|
25754
25754
|
});
|
|
25755
25755
|
page.on("pageerror", (err) => {
|
|
25756
|
-
const
|
|
25757
|
-
|
|
25756
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
25757
|
+
const text = `[Browser:PAGEERROR] ${message}`;
|
|
25758
|
+
const isPlayAbort = /^AbortError:/.test(message) && message.includes("play()") && message.includes("pause()");
|
|
25759
|
+
if (!isPlayAbort) {
|
|
25760
|
+
console.error(text);
|
|
25761
|
+
}
|
|
25758
25762
|
session.browserConsoleBuffer.push(text);
|
|
25759
25763
|
if (session.browserConsoleBuffer.length > BROWSER_CONSOLE_BUFFER_SIZE) {
|
|
25760
25764
|
session.browserConsoleBuffer.shift();
|
|
@@ -26020,7 +26024,7 @@ var init_frameCapture = __esm({
|
|
|
26020
26024
|
// ../engine/src/utils/gpuEncoder.ts
|
|
26021
26025
|
import { spawn as spawn2 } from "child_process";
|
|
26022
26026
|
async function detectGpuEncoder() {
|
|
26023
|
-
return new Promise((
|
|
26027
|
+
return new Promise((resolve39) => {
|
|
26024
26028
|
const ffmpeg = spawn2("ffmpeg", ["-encoders"], {
|
|
26025
26029
|
stdio: ["pipe", "pipe", "pipe"]
|
|
26026
26030
|
});
|
|
@@ -26029,13 +26033,13 @@ async function detectGpuEncoder() {
|
|
|
26029
26033
|
stdout2 += data.toString();
|
|
26030
26034
|
});
|
|
26031
26035
|
ffmpeg.on("close", () => {
|
|
26032
|
-
if (stdout2.includes("h264_nvenc"))
|
|
26033
|
-
else if (stdout2.includes("h264_videotoolbox"))
|
|
26034
|
-
else if (stdout2.includes("h264_vaapi"))
|
|
26035
|
-
else if (stdout2.includes("h264_qsv"))
|
|
26036
|
-
else
|
|
26036
|
+
if (stdout2.includes("h264_nvenc")) resolve39("nvenc");
|
|
26037
|
+
else if (stdout2.includes("h264_videotoolbox")) resolve39("videotoolbox");
|
|
26038
|
+
else if (stdout2.includes("h264_vaapi")) resolve39("vaapi");
|
|
26039
|
+
else if (stdout2.includes("h264_qsv")) resolve39("qsv");
|
|
26040
|
+
else resolve39(null);
|
|
26037
26041
|
});
|
|
26038
|
-
ffmpeg.on("error", () =>
|
|
26042
|
+
ffmpeg.on("error", () => resolve39(null));
|
|
26039
26043
|
});
|
|
26040
26044
|
}
|
|
26041
26045
|
async function getCachedGpuEncoder() {
|
|
@@ -26156,7 +26160,7 @@ async function runFfmpeg(args, opts) {
|
|
|
26156
26160
|
const signal = opts?.signal;
|
|
26157
26161
|
const timeout = opts?.timeout ?? DEFAULT_TIMEOUT;
|
|
26158
26162
|
const onStderr = opts?.onStderr;
|
|
26159
|
-
return new Promise((
|
|
26163
|
+
return new Promise((resolve39) => {
|
|
26160
26164
|
const ffmpeg = spawn3("ffmpeg", args);
|
|
26161
26165
|
let stderr = "";
|
|
26162
26166
|
const onAbort = () => {
|
|
@@ -26182,7 +26186,7 @@ async function runFfmpeg(args, opts) {
|
|
|
26182
26186
|
ffmpeg.on("close", (code) => {
|
|
26183
26187
|
clearTimeout(timer);
|
|
26184
26188
|
if (signal) signal.removeEventListener("abort", onAbort);
|
|
26185
|
-
|
|
26189
|
+
resolve39({
|
|
26186
26190
|
success: !signal?.aborted && code === 0,
|
|
26187
26191
|
exitCode: code,
|
|
26188
26192
|
stderr,
|
|
@@ -26192,7 +26196,7 @@ async function runFfmpeg(args, opts) {
|
|
|
26192
26196
|
ffmpeg.on("error", (err) => {
|
|
26193
26197
|
clearTimeout(timer);
|
|
26194
26198
|
if (signal) signal.removeEventListener("abort", onAbort);
|
|
26195
|
-
|
|
26199
|
+
resolve39({
|
|
26196
26200
|
success: false,
|
|
26197
26201
|
exitCode: null,
|
|
26198
26202
|
stderr: err.message,
|
|
@@ -26384,7 +26388,7 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
|
|
|
26384
26388
|
const inputPath = join20(framesDir, framePattern);
|
|
26385
26389
|
const inputArgs = ["-framerate", String(options.fps), "-i", inputPath];
|
|
26386
26390
|
const args = buildEncoderArgs(options, inputArgs, outputPath, gpuEncoder);
|
|
26387
|
-
return new Promise((
|
|
26391
|
+
return new Promise((resolve39) => {
|
|
26388
26392
|
const ffmpeg = spawn4("ffmpeg", args);
|
|
26389
26393
|
let stderr = "";
|
|
26390
26394
|
const onAbort = () => {
|
|
@@ -26409,7 +26413,7 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
|
|
|
26409
26413
|
if (signal) signal.removeEventListener("abort", onAbort);
|
|
26410
26414
|
const durationMs = Date.now() - startTime;
|
|
26411
26415
|
if (signal?.aborted) {
|
|
26412
|
-
|
|
26416
|
+
resolve39({
|
|
26413
26417
|
success: false,
|
|
26414
26418
|
outputPath,
|
|
26415
26419
|
durationMs,
|
|
@@ -26420,7 +26424,7 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
|
|
|
26420
26424
|
return;
|
|
26421
26425
|
}
|
|
26422
26426
|
if (code !== 0) {
|
|
26423
|
-
|
|
26427
|
+
resolve39({
|
|
26424
26428
|
success: false,
|
|
26425
26429
|
outputPath,
|
|
26426
26430
|
durationMs,
|
|
@@ -26431,12 +26435,12 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
|
|
|
26431
26435
|
return;
|
|
26432
26436
|
}
|
|
26433
26437
|
const fileSize = existsSync17(outputPath) ? statSync4(outputPath).size : 0;
|
|
26434
|
-
|
|
26438
|
+
resolve39({ success: true, outputPath, durationMs, framesEncoded: frameCount, fileSize });
|
|
26435
26439
|
});
|
|
26436
26440
|
ffmpeg.on("error", (err) => {
|
|
26437
26441
|
clearTimeout(timer);
|
|
26438
26442
|
if (signal) signal.removeEventListener("abort", onAbort);
|
|
26439
|
-
|
|
26443
|
+
resolve39({
|
|
26440
26444
|
success: false,
|
|
26441
26445
|
outputPath,
|
|
26442
26446
|
durationMs: Date.now() - startTime,
|
|
@@ -26494,18 +26498,18 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
|
|
|
26494
26498
|
let gpuEncoder = null;
|
|
26495
26499
|
if (options.useGpu) gpuEncoder = await getCachedGpuEncoder();
|
|
26496
26500
|
const args = buildEncoderArgs(options, inputArgs, chunkPath, gpuEncoder);
|
|
26497
|
-
const chunkResult = await new Promise((
|
|
26501
|
+
const chunkResult = await new Promise((resolve39) => {
|
|
26498
26502
|
const ffmpeg = spawn4("ffmpeg", args);
|
|
26499
26503
|
let stderr = "";
|
|
26500
26504
|
ffmpeg.stderr.on("data", (d) => {
|
|
26501
26505
|
stderr += d.toString();
|
|
26502
26506
|
});
|
|
26503
26507
|
ffmpeg.on("close", (code) => {
|
|
26504
|
-
if (code === 0)
|
|
26505
|
-
else
|
|
26508
|
+
if (code === 0) resolve39({ success: true });
|
|
26509
|
+
else resolve39({ success: false, error: `Chunk ${i2} encode failed: ${stderr.slice(-400)}` });
|
|
26506
26510
|
});
|
|
26507
26511
|
ffmpeg.on("error", (err) => {
|
|
26508
|
-
|
|
26512
|
+
resolve39({ success: false, error: `Chunk ${i2} encode error: ${err.message}` });
|
|
26509
26513
|
});
|
|
26510
26514
|
});
|
|
26511
26515
|
if (!chunkResult.success) {
|
|
@@ -26535,18 +26539,18 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
|
|
|
26535
26539
|
"-y",
|
|
26536
26540
|
outputPath
|
|
26537
26541
|
];
|
|
26538
|
-
const concatResult = await new Promise((
|
|
26542
|
+
const concatResult = await new Promise((resolve39) => {
|
|
26539
26543
|
const ffmpeg = spawn4("ffmpeg", concatArgs);
|
|
26540
26544
|
let stderr = "";
|
|
26541
26545
|
ffmpeg.stderr.on("data", (d) => {
|
|
26542
26546
|
stderr += d.toString();
|
|
26543
26547
|
});
|
|
26544
26548
|
ffmpeg.on("close", (code) => {
|
|
26545
|
-
if (code === 0)
|
|
26546
|
-
else
|
|
26549
|
+
if (code === 0) resolve39({ success: true });
|
|
26550
|
+
else resolve39({ success: false, error: `Chunk concat failed: ${stderr.slice(-400)}` });
|
|
26547
26551
|
});
|
|
26548
26552
|
ffmpeg.on("error", (err) => {
|
|
26549
|
-
|
|
26553
|
+
resolve39({ success: false, error: `Chunk concat error: ${err.message}` });
|
|
26550
26554
|
});
|
|
26551
26555
|
});
|
|
26552
26556
|
if (!concatResult.success) {
|
|
@@ -26646,37 +26650,37 @@ import { dirname as dirname7 } from "path";
|
|
|
26646
26650
|
function createFrameReorderBuffer(startFrame, endFrame) {
|
|
26647
26651
|
let cursor = startFrame;
|
|
26648
26652
|
const pending = /* @__PURE__ */ new Map();
|
|
26649
|
-
const enqueueAt = (frame,
|
|
26653
|
+
const enqueueAt = (frame, resolve39) => {
|
|
26650
26654
|
const list = pending.get(frame);
|
|
26651
26655
|
if (list === void 0) {
|
|
26652
|
-
pending.set(frame, [
|
|
26656
|
+
pending.set(frame, [resolve39]);
|
|
26653
26657
|
} else {
|
|
26654
|
-
list.push(
|
|
26658
|
+
list.push(resolve39);
|
|
26655
26659
|
}
|
|
26656
26660
|
};
|
|
26657
26661
|
const flushAt = (frame) => {
|
|
26658
26662
|
const list = pending.get(frame);
|
|
26659
26663
|
if (list === void 0) return;
|
|
26660
26664
|
pending.delete(frame);
|
|
26661
|
-
for (const
|
|
26665
|
+
for (const resolve39 of list) resolve39();
|
|
26662
26666
|
};
|
|
26663
|
-
const waitForFrame = (frame) => new Promise((
|
|
26667
|
+
const waitForFrame = (frame) => new Promise((resolve39) => {
|
|
26664
26668
|
if (frame === cursor) {
|
|
26665
|
-
|
|
26669
|
+
resolve39();
|
|
26666
26670
|
return;
|
|
26667
26671
|
}
|
|
26668
|
-
enqueueAt(frame,
|
|
26672
|
+
enqueueAt(frame, resolve39);
|
|
26669
26673
|
});
|
|
26670
26674
|
const advanceTo = (frame) => {
|
|
26671
26675
|
cursor = frame;
|
|
26672
26676
|
flushAt(frame);
|
|
26673
26677
|
};
|
|
26674
|
-
const waitForAllDone = () => new Promise((
|
|
26678
|
+
const waitForAllDone = () => new Promise((resolve39) => {
|
|
26675
26679
|
if (cursor >= endFrame) {
|
|
26676
|
-
|
|
26680
|
+
resolve39();
|
|
26677
26681
|
return;
|
|
26678
26682
|
}
|
|
26679
|
-
enqueueAt(endFrame,
|
|
26683
|
+
enqueueAt(endFrame, resolve39);
|
|
26680
26684
|
});
|
|
26681
26685
|
return { waitForFrame, advanceTo, waitForAllDone };
|
|
26682
26686
|
}
|
|
@@ -26838,7 +26842,7 @@ async function spawnStreamingEncoder(outputPath, options, signal, config) {
|
|
|
26838
26842
|
let stderr = "";
|
|
26839
26843
|
let exitCode = null;
|
|
26840
26844
|
let exitPromiseResolve = null;
|
|
26841
|
-
const exitPromise = new Promise((
|
|
26845
|
+
const exitPromise = new Promise((resolve39) => exitPromiseResolve = resolve39);
|
|
26842
26846
|
ffmpeg.stderr?.on("data", (data) => {
|
|
26843
26847
|
stderr += data.toString();
|
|
26844
26848
|
});
|
|
@@ -26884,8 +26888,8 @@ Process error: ${err.message}`;
|
|
|
26884
26888
|
if (signal) signal.removeEventListener("abort", onAbort);
|
|
26885
26889
|
const stdin = ffmpeg.stdin;
|
|
26886
26890
|
if (stdin && !stdin.destroyed) {
|
|
26887
|
-
await new Promise((
|
|
26888
|
-
stdin.end(() =>
|
|
26891
|
+
await new Promise((resolve39) => {
|
|
26892
|
+
stdin.end(() => resolve39());
|
|
26889
26893
|
});
|
|
26890
26894
|
}
|
|
26891
26895
|
await exitPromise;
|
|
@@ -26928,7 +26932,7 @@ import { spawn as spawn6 } from "child_process";
|
|
|
26928
26932
|
import { readFileSync as readFileSync15 } from "fs";
|
|
26929
26933
|
import { extname as extname4 } from "path";
|
|
26930
26934
|
function runFfprobe(args) {
|
|
26931
|
-
return new Promise((
|
|
26935
|
+
return new Promise((resolve39, reject) => {
|
|
26932
26936
|
const proc = spawn6("ffprobe", args);
|
|
26933
26937
|
let stdout2 = "";
|
|
26934
26938
|
let stderr = "";
|
|
@@ -26942,7 +26946,7 @@ function runFfprobe(args) {
|
|
|
26942
26946
|
if (code !== 0) {
|
|
26943
26947
|
reject(new Error(`[FFmpeg] ffprobe exited with code ${code}: ${stderr}`));
|
|
26944
26948
|
} else {
|
|
26945
|
-
|
|
26949
|
+
resolve39(stdout2);
|
|
26946
26950
|
}
|
|
26947
26951
|
});
|
|
26948
26952
|
proc.on("error", (err) => {
|
|
@@ -27484,7 +27488,7 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
|
|
|
27484
27488
|
args.push("-q:v", format === "jpg" ? String(Math.ceil((100 - quality) / 3)) : "0");
|
|
27485
27489
|
if (format === "png") args.push("-compression_level", "6");
|
|
27486
27490
|
args.push("-y", outputPattern);
|
|
27487
|
-
return new Promise((
|
|
27491
|
+
return new Promise((resolve39, reject) => {
|
|
27488
27492
|
const ffmpeg = spawn7("ffmpeg", args);
|
|
27489
27493
|
let stderr = "";
|
|
27490
27494
|
const onAbort = () => {
|
|
@@ -27519,7 +27523,7 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
|
|
|
27519
27523
|
files.forEach((file, index) => {
|
|
27520
27524
|
framePaths.set(index, join23(videoOutputDir, file));
|
|
27521
27525
|
});
|
|
27522
|
-
|
|
27526
|
+
resolve39({
|
|
27523
27527
|
videoId,
|
|
27524
27528
|
srcPath: videoPath,
|
|
27525
27529
|
outputDir: videoOutputDir,
|
|
@@ -28926,11 +28930,11 @@ function createFileServer(options) {
|
|
|
28926
28930
|
headers: { "Content-Type": contentType }
|
|
28927
28931
|
});
|
|
28928
28932
|
});
|
|
28929
|
-
return new Promise((
|
|
28933
|
+
return new Promise((resolve39) => {
|
|
28930
28934
|
const server = serve({ fetch: app.fetch, port }, (info) => {
|
|
28931
28935
|
const actualPort = info.port;
|
|
28932
28936
|
const url = `http://localhost:${actualPort}`;
|
|
28933
|
-
|
|
28937
|
+
resolve39({
|
|
28934
28938
|
url,
|
|
28935
28939
|
port: actualPort,
|
|
28936
28940
|
close: () => server.close()
|
|
@@ -31330,13 +31334,13 @@ function createFileServer2(options) {
|
|
|
31330
31334
|
let filePath = null;
|
|
31331
31335
|
if (compiledDir) {
|
|
31332
31336
|
const candidate = join29(compiledDir, relativePath);
|
|
31333
|
-
if (existsSync28(candidate) && isPathInside(candidate, compiledDir
|
|
31337
|
+
if (existsSync28(candidate) && isPathInside(candidate, compiledDir) && statSync8(candidate).isFile()) {
|
|
31334
31338
|
filePath = candidate;
|
|
31335
31339
|
}
|
|
31336
31340
|
}
|
|
31337
31341
|
if (!filePath) {
|
|
31338
31342
|
const candidate = join29(projectDir, relativePath);
|
|
31339
|
-
if (existsSync28(candidate) && isPathInside(candidate, projectDir
|
|
31343
|
+
if (existsSync28(candidate) && isPathInside(candidate, projectDir) && statSync8(candidate).isFile()) {
|
|
31340
31344
|
filePath = candidate;
|
|
31341
31345
|
}
|
|
31342
31346
|
}
|
|
@@ -31364,10 +31368,10 @@ function createFileServer2(options) {
|
|
|
31364
31368
|
headers: { "Content-Type": contentType }
|
|
31365
31369
|
});
|
|
31366
31370
|
});
|
|
31367
|
-
return new Promise((
|
|
31371
|
+
return new Promise((resolve39) => {
|
|
31368
31372
|
const connections = /* @__PURE__ */ new Set();
|
|
31369
31373
|
const server = serve2({ fetch: app.fetch, port }, (info) => {
|
|
31370
|
-
|
|
31374
|
+
resolve39({
|
|
31371
31375
|
url: `http://localhost:${info.port}`,
|
|
31372
31376
|
port: info.port,
|
|
31373
31377
|
close: () => {
|
|
@@ -35058,10 +35062,10 @@ var init_semaphore = __esm({
|
|
|
35058
35062
|
this.active++;
|
|
35059
35063
|
return () => this.release();
|
|
35060
35064
|
}
|
|
35061
|
-
return new Promise((
|
|
35065
|
+
return new Promise((resolve39) => {
|
|
35062
35066
|
this.queue.push(() => {
|
|
35063
35067
|
this.active++;
|
|
35064
|
-
|
|
35068
|
+
resolve39(() => this.release());
|
|
35065
35069
|
});
|
|
35066
35070
|
});
|
|
35067
35071
|
}
|
|
@@ -36044,8 +36048,8 @@ async function runDevMode(dir, projectName) {
|
|
|
36044
36048
|
}
|
|
36045
36049
|
});
|
|
36046
36050
|
}
|
|
36047
|
-
return new Promise((
|
|
36048
|
-
child.on("close", () =>
|
|
36051
|
+
return new Promise((resolve39) => {
|
|
36052
|
+
child.on("close", () => resolve39());
|
|
36049
36053
|
});
|
|
36050
36054
|
}
|
|
36051
36055
|
function hasLocalStudio(dir) {
|
|
@@ -36115,8 +36119,8 @@ async function runLocalStudioMode(dir, projectName) {
|
|
|
36115
36119
|
}
|
|
36116
36120
|
});
|
|
36117
36121
|
}
|
|
36118
|
-
return new Promise((
|
|
36119
|
-
child.on("close", () =>
|
|
36122
|
+
return new Promise((resolve39) => {
|
|
36123
|
+
child.on("close", () => resolve39());
|
|
36120
36124
|
});
|
|
36121
36125
|
}
|
|
36122
36126
|
async function runEmbeddedMode(dir, startPort, projectName, forceNew = false) {
|
|
@@ -36183,7 +36187,29 @@ async function runEmbeddedMode(dir, startPort, projectName, forceNew = false) {
|
|
|
36183
36187
|
console.log();
|
|
36184
36188
|
import("open").then((mod) => mod.default(`${url}#project/${pName}`)).catch(() => {
|
|
36185
36189
|
});
|
|
36186
|
-
|
|
36190
|
+
let rl;
|
|
36191
|
+
if (process.platform === "win32") {
|
|
36192
|
+
const readline = await import("readline");
|
|
36193
|
+
rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
36194
|
+
rl.on("SIGINT", () => {
|
|
36195
|
+
process.emit("SIGINT", "SIGINT");
|
|
36196
|
+
});
|
|
36197
|
+
}
|
|
36198
|
+
return new Promise((resolveRun) => {
|
|
36199
|
+
let shuttingDown = false;
|
|
36200
|
+
const shutdown = () => {
|
|
36201
|
+
if (shuttingDown) return;
|
|
36202
|
+
shuttingDown = true;
|
|
36203
|
+
process.off("SIGINT", shutdown);
|
|
36204
|
+
process.off("SIGTERM", shutdown);
|
|
36205
|
+
rl?.close();
|
|
36206
|
+
console.log();
|
|
36207
|
+
console.log(` ${c.dim("Shutting down studio...")}`);
|
|
36208
|
+
result.server.close(() => resolveRun());
|
|
36209
|
+
setTimeout(() => process.exit(0), 2e3).unref();
|
|
36210
|
+
};
|
|
36211
|
+
process.once("SIGINT", shutdown);
|
|
36212
|
+
process.once("SIGTERM", shutdown);
|
|
36187
36213
|
});
|
|
36188
36214
|
}
|
|
36189
36215
|
var examples, preview_default;
|
|
@@ -38551,6 +38577,558 @@ var init_lint3 = __esm({
|
|
|
38551
38577
|
}
|
|
38552
38578
|
});
|
|
38553
38579
|
|
|
38580
|
+
// src/utils/layoutAudit.ts
|
|
38581
|
+
function buildLayoutSampleTimes({ duration, samples, at: at2 }) {
|
|
38582
|
+
if (at2?.length) {
|
|
38583
|
+
return uniqueSortedTimes(
|
|
38584
|
+
at2.filter(
|
|
38585
|
+
(time) => Number.isFinite(time) && time >= 0 && (duration <= 0 || time <= duration)
|
|
38586
|
+
)
|
|
38587
|
+
);
|
|
38588
|
+
}
|
|
38589
|
+
if (!Number.isFinite(duration) || duration <= 0 || samples <= 0) return [];
|
|
38590
|
+
const count = Math.max(1, Math.floor(samples));
|
|
38591
|
+
return Array.from({ length: count }, (_2, index) => roundTime((index + 0.5) / count * duration));
|
|
38592
|
+
}
|
|
38593
|
+
function summarizeLayoutIssues(issues) {
|
|
38594
|
+
const errorCount = issues.filter((issue) => issue.severity === "error").length;
|
|
38595
|
+
const warningCount = issues.filter((issue) => issue.severity === "warning").length;
|
|
38596
|
+
const infoCount = issues.filter((issue) => issue.severity === "info").length;
|
|
38597
|
+
return {
|
|
38598
|
+
ok: errorCount === 0,
|
|
38599
|
+
errorCount,
|
|
38600
|
+
warningCount,
|
|
38601
|
+
infoCount,
|
|
38602
|
+
issueCount: issues.length
|
|
38603
|
+
};
|
|
38604
|
+
}
|
|
38605
|
+
function formatLayoutIssue(issue) {
|
|
38606
|
+
const timeLabel = issue.occurrences && issue.occurrences > 1 ? `t=${formatNumber(issue.firstSeen ?? issue.time)}-${formatNumber(issue.lastSeen ?? issue.time)}s (${issue.occurrences} samples)` : `t=${formatNumber(issue.time)}s`;
|
|
38607
|
+
const parts = [
|
|
38608
|
+
timeLabel,
|
|
38609
|
+
issue.code,
|
|
38610
|
+
issue.selector,
|
|
38611
|
+
issue.containerSelector ? `inside ${issue.containerSelector}` : "",
|
|
38612
|
+
issue.overflow ? `overflowed ${formatOverflow(issue.overflow)}` : "",
|
|
38613
|
+
issue.text ? quoteText(issue.text) : ""
|
|
38614
|
+
].filter(Boolean);
|
|
38615
|
+
const line = `${parts.join(" ")} \u2014 ${issue.message}`;
|
|
38616
|
+
return issue.fixHint ? `${line}
|
|
38617
|
+
Fix: ${issue.fixHint}` : line;
|
|
38618
|
+
}
|
|
38619
|
+
function dedupeLayoutIssues(issues) {
|
|
38620
|
+
const seen = /* @__PURE__ */ new Set();
|
|
38621
|
+
const result = [];
|
|
38622
|
+
for (const issue of issues) {
|
|
38623
|
+
const key2 = [
|
|
38624
|
+
issue.code,
|
|
38625
|
+
issue.severity,
|
|
38626
|
+
issue.time.toFixed(3),
|
|
38627
|
+
issue.selector,
|
|
38628
|
+
issue.containerSelector ?? "",
|
|
38629
|
+
issue.text ?? "",
|
|
38630
|
+
issue.overflow ? formatOverflow(issue.overflow) : ""
|
|
38631
|
+
].join("|");
|
|
38632
|
+
if (seen.has(key2)) continue;
|
|
38633
|
+
seen.add(key2);
|
|
38634
|
+
result.push(issue);
|
|
38635
|
+
}
|
|
38636
|
+
return result;
|
|
38637
|
+
}
|
|
38638
|
+
function collapseStaticLayoutIssues(issues) {
|
|
38639
|
+
const groups = /* @__PURE__ */ new Map();
|
|
38640
|
+
for (const issue of issues) {
|
|
38641
|
+
const key2 = staticIssueKey(issue);
|
|
38642
|
+
const existing = groups.get(key2);
|
|
38643
|
+
if (!existing) {
|
|
38644
|
+
groups.set(key2, {
|
|
38645
|
+
issue,
|
|
38646
|
+
firstSeen: issue.time,
|
|
38647
|
+
lastSeen: issue.time,
|
|
38648
|
+
occurrences: 1
|
|
38649
|
+
});
|
|
38650
|
+
continue;
|
|
38651
|
+
}
|
|
38652
|
+
existing.firstSeen = Math.min(existing.firstSeen, issue.time);
|
|
38653
|
+
existing.lastSeen = Math.max(existing.lastSeen, issue.time);
|
|
38654
|
+
existing.occurrences += 1;
|
|
38655
|
+
}
|
|
38656
|
+
return [...groups.values()].map(({ issue, firstSeen, lastSeen, occurrences }) => ({
|
|
38657
|
+
...issue,
|
|
38658
|
+
time: firstSeen,
|
|
38659
|
+
firstSeen,
|
|
38660
|
+
lastSeen,
|
|
38661
|
+
occurrences
|
|
38662
|
+
}));
|
|
38663
|
+
}
|
|
38664
|
+
function limitLayoutIssues(issues, maxIssues) {
|
|
38665
|
+
const limit = Math.max(1, Math.floor(maxIssues));
|
|
38666
|
+
const sortedIssues = [...issues].sort((a, b) => {
|
|
38667
|
+
const severityDelta = severityRank(a.severity) - severityRank(b.severity);
|
|
38668
|
+
if (severityDelta !== 0) return severityDelta;
|
|
38669
|
+
return a.time - b.time;
|
|
38670
|
+
});
|
|
38671
|
+
return {
|
|
38672
|
+
issues: sortedIssues.slice(0, limit),
|
|
38673
|
+
totalIssueCount: issues.length,
|
|
38674
|
+
truncated: issues.length > limit
|
|
38675
|
+
};
|
|
38676
|
+
}
|
|
38677
|
+
function severityRank(severity) {
|
|
38678
|
+
if (severity === "error") return 0;
|
|
38679
|
+
if (severity === "warning") return 1;
|
|
38680
|
+
return 2;
|
|
38681
|
+
}
|
|
38682
|
+
function staticIssueKey(issue) {
|
|
38683
|
+
return [
|
|
38684
|
+
issue.code,
|
|
38685
|
+
issue.severity,
|
|
38686
|
+
issue.selector,
|
|
38687
|
+
issue.containerSelector ?? "",
|
|
38688
|
+
issue.text ?? "",
|
|
38689
|
+
issue.overflow ? formatOverflow(issue.overflow) : ""
|
|
38690
|
+
].join("|");
|
|
38691
|
+
}
|
|
38692
|
+
function uniqueSortedTimes(times) {
|
|
38693
|
+
const rounded = times.map(roundTime);
|
|
38694
|
+
return [...new Set(rounded)].sort((a, b) => a - b);
|
|
38695
|
+
}
|
|
38696
|
+
function formatOverflow(overflow) {
|
|
38697
|
+
return ["left", "right", "top", "bottom"].flatMap((side) => {
|
|
38698
|
+
const value = overflow[side];
|
|
38699
|
+
return value == null ? [] : `${side} ${formatNumber(value)}px`;
|
|
38700
|
+
}).join(", ");
|
|
38701
|
+
}
|
|
38702
|
+
function quoteText(text) {
|
|
38703
|
+
const normalized = text.replace(/\s+/g, " ").trim();
|
|
38704
|
+
const truncated = normalized.length > 80 ? `${normalized.slice(0, 77)}...` : normalized;
|
|
38705
|
+
return `"${truncated}"`;
|
|
38706
|
+
}
|
|
38707
|
+
function formatNumber(value) {
|
|
38708
|
+
return Number.isInteger(value) ? String(value) : value.toFixed(2).replace(/0+$/, "").replace(/\.$/, "");
|
|
38709
|
+
}
|
|
38710
|
+
function roundTime(value) {
|
|
38711
|
+
return Math.round(value * 1e3) / 1e3;
|
|
38712
|
+
}
|
|
38713
|
+
var init_layoutAudit = __esm({
|
|
38714
|
+
"src/utils/layoutAudit.ts"() {
|
|
38715
|
+
"use strict";
|
|
38716
|
+
}
|
|
38717
|
+
});
|
|
38718
|
+
|
|
38719
|
+
// src/commands/layout.ts
|
|
38720
|
+
var layout_exports = {};
|
|
38721
|
+
__export(layout_exports, {
|
|
38722
|
+
createInspectCommand: () => createInspectCommand,
|
|
38723
|
+
default: () => layout_default,
|
|
38724
|
+
examples: () => examples9
|
|
38725
|
+
});
|
|
38726
|
+
import { createServer } from "http";
|
|
38727
|
+
import { existsSync as existsSync41, readFileSync as readFileSync29 } from "fs";
|
|
38728
|
+
import { dirname as dirname17, isAbsolute as isAbsolute6, join as join42, relative as relative5, resolve as resolve29 } from "path";
|
|
38729
|
+
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
38730
|
+
async function getCompositionDuration2(page) {
|
|
38731
|
+
return page.evaluate(() => {
|
|
38732
|
+
const win = window;
|
|
38733
|
+
if (typeof win.__hf?.duration === "number" && win.__hf.duration > 0) return win.__hf.duration;
|
|
38734
|
+
const playerDuration = win.__player?.duration;
|
|
38735
|
+
if (typeof playerDuration === "function") return playerDuration();
|
|
38736
|
+
if (typeof playerDuration === "number" && playerDuration > 0) return playerDuration;
|
|
38737
|
+
const root = document.querySelector("[data-composition-id][data-duration]");
|
|
38738
|
+
const attrDuration = root ? parseFloat(root.getAttribute("data-duration") ?? "0") : 0;
|
|
38739
|
+
if (attrDuration > 0) return attrDuration;
|
|
38740
|
+
const timelines = win.__timelines;
|
|
38741
|
+
if (timelines) {
|
|
38742
|
+
for (const timeline of Object.values(timelines)) {
|
|
38743
|
+
const duration = timeline.duration;
|
|
38744
|
+
if (typeof duration === "function") return duration();
|
|
38745
|
+
if (typeof duration === "number" && duration > 0) return duration;
|
|
38746
|
+
}
|
|
38747
|
+
}
|
|
38748
|
+
return 0;
|
|
38749
|
+
});
|
|
38750
|
+
}
|
|
38751
|
+
async function seekTo(page, time) {
|
|
38752
|
+
await page.evaluate((t3) => {
|
|
38753
|
+
const win = window;
|
|
38754
|
+
if (typeof win.__hf?.seek === "function") {
|
|
38755
|
+
win.__hf.seek(t3);
|
|
38756
|
+
return;
|
|
38757
|
+
}
|
|
38758
|
+
if (typeof win.__player?.seek === "function") {
|
|
38759
|
+
win.__player.seek(t3);
|
|
38760
|
+
return;
|
|
38761
|
+
}
|
|
38762
|
+
const timelines = win.__timelines;
|
|
38763
|
+
if (timelines) {
|
|
38764
|
+
for (const timeline of Object.values(timelines)) {
|
|
38765
|
+
if (typeof timeline.pause === "function") timeline.pause();
|
|
38766
|
+
if (typeof timeline.seek === "function") timeline.seek(t3);
|
|
38767
|
+
}
|
|
38768
|
+
}
|
|
38769
|
+
}, time);
|
|
38770
|
+
await page.evaluate(
|
|
38771
|
+
() => new Promise(
|
|
38772
|
+
(resolveFrame) => requestAnimationFrame(() => requestAnimationFrame(() => resolveFrame()))
|
|
38773
|
+
)
|
|
38774
|
+
);
|
|
38775
|
+
await page.evaluate(() => {
|
|
38776
|
+
const fonts = document.fonts;
|
|
38777
|
+
if (!fonts?.ready) return Promise.resolve();
|
|
38778
|
+
return Promise.race([
|
|
38779
|
+
fonts.ready.then(() => void 0),
|
|
38780
|
+
new Promise((resolve39) => setTimeout(resolve39, 500))
|
|
38781
|
+
]);
|
|
38782
|
+
}).catch(() => {
|
|
38783
|
+
});
|
|
38784
|
+
await new Promise((resolveSettle) => setTimeout(resolveSettle, SEEK_SETTLE_MS));
|
|
38785
|
+
}
|
|
38786
|
+
async function bundleProjectHtml(projectDir) {
|
|
38787
|
+
const { bundleToSingleHtml: bundleToSingleHtml2 } = await Promise.resolve().then(() => (init_compiler(), compiler_exports));
|
|
38788
|
+
let html = await bundleToSingleHtml2(projectDir);
|
|
38789
|
+
const runtimePath = resolve29(
|
|
38790
|
+
__dirname2,
|
|
38791
|
+
"..",
|
|
38792
|
+
"..",
|
|
38793
|
+
"..",
|
|
38794
|
+
"core",
|
|
38795
|
+
"dist",
|
|
38796
|
+
"hyperframe.runtime.iife.js"
|
|
38797
|
+
);
|
|
38798
|
+
if (existsSync41(runtimePath)) {
|
|
38799
|
+
const runtimeSource = readFileSync29(runtimePath, "utf-8");
|
|
38800
|
+
html = html.replace(
|
|
38801
|
+
/<script[^>]*data-hyperframes-preview-runtime[^>]*src="[^"]*"[^>]*><\/script>/,
|
|
38802
|
+
() => `<script data-hyperframes-preview-runtime="1">${runtimeSource}</script>`
|
|
38803
|
+
);
|
|
38804
|
+
}
|
|
38805
|
+
return html;
|
|
38806
|
+
}
|
|
38807
|
+
async function serveProject(projectDir, html) {
|
|
38808
|
+
const { getMimeType: getMimeType2 } = await Promise.resolve().then(() => (init_studio_api(), studio_api_exports));
|
|
38809
|
+
const server = createServer((req, res) => {
|
|
38810
|
+
const url = req.url ?? "/";
|
|
38811
|
+
if (url === "/" || url === "/index.html") {
|
|
38812
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
38813
|
+
res.end(html);
|
|
38814
|
+
return;
|
|
38815
|
+
}
|
|
38816
|
+
const filePath = resolve29(projectDir, decodeURIComponent(url).replace(/^\//, ""));
|
|
38817
|
+
const rel = relative5(projectDir, filePath);
|
|
38818
|
+
if (rel.startsWith("..") || isAbsolute6(rel)) {
|
|
38819
|
+
res.writeHead(403);
|
|
38820
|
+
res.end();
|
|
38821
|
+
return;
|
|
38822
|
+
}
|
|
38823
|
+
if (existsSync41(filePath)) {
|
|
38824
|
+
res.writeHead(200, { "Content-Type": getMimeType2(filePath) });
|
|
38825
|
+
res.end(readFileSync29(filePath));
|
|
38826
|
+
return;
|
|
38827
|
+
}
|
|
38828
|
+
res.writeHead(404);
|
|
38829
|
+
res.end();
|
|
38830
|
+
});
|
|
38831
|
+
const port = await new Promise((resolvePort, rejectPort) => {
|
|
38832
|
+
server.on("error", rejectPort);
|
|
38833
|
+
server.listen(0, () => {
|
|
38834
|
+
const addr = server.address();
|
|
38835
|
+
const resolvedPort = typeof addr === "object" && addr ? addr.port : 0;
|
|
38836
|
+
if (!resolvedPort) rejectPort(new Error("Failed to bind local layout audit server"));
|
|
38837
|
+
else resolvePort(resolvedPort);
|
|
38838
|
+
});
|
|
38839
|
+
});
|
|
38840
|
+
return {
|
|
38841
|
+
url: `http://127.0.0.1:${port}/`,
|
|
38842
|
+
close: () => new Promise((resolveClose) => {
|
|
38843
|
+
server.close(() => resolveClose());
|
|
38844
|
+
})
|
|
38845
|
+
};
|
|
38846
|
+
}
|
|
38847
|
+
async function alignViewportToComposition(page, url) {
|
|
38848
|
+
const size = await page.evaluate(() => {
|
|
38849
|
+
const root = document.querySelector("[data-composition-id][data-width][data-height]");
|
|
38850
|
+
const width = root ? parseInt(root.getAttribute("data-width") ?? "", 10) : 0;
|
|
38851
|
+
const height = root ? parseInt(root.getAttribute("data-height") ?? "", 10) : 0;
|
|
38852
|
+
return {
|
|
38853
|
+
width: Number.isFinite(width) && width > 0 ? Math.min(width, 4096) : 1920,
|
|
38854
|
+
height: Number.isFinite(height) && height > 0 ? Math.min(height, 4096) : 1080
|
|
38855
|
+
};
|
|
38856
|
+
});
|
|
38857
|
+
await page.setViewport(size);
|
|
38858
|
+
await page.goto(url, { waitUntil: "domcontentloaded", timeout: 1e4 });
|
|
38859
|
+
}
|
|
38860
|
+
async function runLayoutAudit(projectDir, opts) {
|
|
38861
|
+
const { ensureBrowser: ensureBrowser2 } = await Promise.resolve().then(() => (init_manager2(), manager_exports2));
|
|
38862
|
+
const puppeteer = await import("puppeteer-core");
|
|
38863
|
+
const html = await bundleProjectHtml(projectDir);
|
|
38864
|
+
const server = await serveProject(projectDir, html);
|
|
38865
|
+
let chromeBrowser;
|
|
38866
|
+
try {
|
|
38867
|
+
const browser = await ensureBrowser2();
|
|
38868
|
+
chromeBrowser = await puppeteer.default.launch({
|
|
38869
|
+
headless: true,
|
|
38870
|
+
executablePath: browser.executablePath,
|
|
38871
|
+
args: [
|
|
38872
|
+
"--no-sandbox",
|
|
38873
|
+
"--disable-gpu",
|
|
38874
|
+
"--disable-dev-shm-usage",
|
|
38875
|
+
"--enable-webgl",
|
|
38876
|
+
"--use-gl=angle",
|
|
38877
|
+
"--use-angle=swiftshader"
|
|
38878
|
+
]
|
|
38879
|
+
});
|
|
38880
|
+
const page = await chromeBrowser.newPage();
|
|
38881
|
+
await page.setViewport({ width: 1920, height: 1080 });
|
|
38882
|
+
await page.goto(server.url, { waitUntil: "domcontentloaded", timeout: 1e4 });
|
|
38883
|
+
await alignViewportToComposition(page, server.url);
|
|
38884
|
+
await page.waitForFunction(() => !!window.__timelines, {
|
|
38885
|
+
timeout: opts.timeout
|
|
38886
|
+
}).catch(() => {
|
|
38887
|
+
});
|
|
38888
|
+
await page.evaluate(() => {
|
|
38889
|
+
const fonts = document.fonts;
|
|
38890
|
+
if (!fonts?.ready) return Promise.resolve();
|
|
38891
|
+
return Promise.race([
|
|
38892
|
+
fonts.ready.then(() => void 0),
|
|
38893
|
+
new Promise((resolve39) => setTimeout(resolve39, 750))
|
|
38894
|
+
]);
|
|
38895
|
+
}).catch(() => {
|
|
38896
|
+
});
|
|
38897
|
+
await new Promise((resolveSettle) => setTimeout(resolveSettle, 250));
|
|
38898
|
+
const duration = await getCompositionDuration2(page);
|
|
38899
|
+
const samples = buildLayoutSampleTimes({ duration, samples: opts.samples, at: opts.at });
|
|
38900
|
+
if (samples.length === 0) return { duration, samples, rawIssues: [] };
|
|
38901
|
+
await page.addScriptTag({ content: loadLayoutAuditScript() });
|
|
38902
|
+
const issues = [];
|
|
38903
|
+
for (const time of samples) {
|
|
38904
|
+
await seekTo(page, time);
|
|
38905
|
+
const sampleIssues = await page.evaluate(
|
|
38906
|
+
(auditOptions) => {
|
|
38907
|
+
const win = window;
|
|
38908
|
+
return win.__hyperframesLayoutAudit?.(auditOptions) ?? [];
|
|
38909
|
+
},
|
|
38910
|
+
{ time, tolerance: opts.tolerance }
|
|
38911
|
+
);
|
|
38912
|
+
issues.push(...sampleIssues);
|
|
38913
|
+
}
|
|
38914
|
+
return {
|
|
38915
|
+
duration,
|
|
38916
|
+
samples,
|
|
38917
|
+
rawIssues: dedupeLayoutIssues(issues)
|
|
38918
|
+
};
|
|
38919
|
+
} finally {
|
|
38920
|
+
await chromeBrowser?.close().catch(() => {
|
|
38921
|
+
});
|
|
38922
|
+
await server.close();
|
|
38923
|
+
}
|
|
38924
|
+
}
|
|
38925
|
+
function loadLayoutAuditScript() {
|
|
38926
|
+
const candidates = [
|
|
38927
|
+
join42(__dirname2, "layout-audit.browser.js"),
|
|
38928
|
+
join42(__dirname2, "commands", "layout-audit.browser.js")
|
|
38929
|
+
];
|
|
38930
|
+
for (const candidate of candidates) {
|
|
38931
|
+
if (existsSync41(candidate)) return readFileSync29(candidate, "utf-8");
|
|
38932
|
+
}
|
|
38933
|
+
throw new Error("Missing layout audit browser script");
|
|
38934
|
+
}
|
|
38935
|
+
function parseAt(value) {
|
|
38936
|
+
if (!value) return void 0;
|
|
38937
|
+
const times = String(value).split(",").map((entry) => parseFloat(entry.trim())).filter((time) => Number.isFinite(time) && time >= 0);
|
|
38938
|
+
return times.length > 0 ? times : void 0;
|
|
38939
|
+
}
|
|
38940
|
+
function createInspectCommand(commandName) {
|
|
38941
|
+
return defineCommand({
|
|
38942
|
+
meta: {
|
|
38943
|
+
name: commandName,
|
|
38944
|
+
description: "Inspect rendered composition layout for text and container overflow"
|
|
38945
|
+
},
|
|
38946
|
+
args: {
|
|
38947
|
+
dir: { type: "positional", description: "Project directory", required: false },
|
|
38948
|
+
json: { type: "boolean", description: "Output agent-readable JSON", default: false },
|
|
38949
|
+
samples: {
|
|
38950
|
+
type: "string",
|
|
38951
|
+
description: "Number of midpoint samples across the duration (default: 9)",
|
|
38952
|
+
default: "9"
|
|
38953
|
+
},
|
|
38954
|
+
at: {
|
|
38955
|
+
type: "string",
|
|
38956
|
+
description: "Comma-separated timestamps in seconds (e.g., --at 1.5,4,7.25)"
|
|
38957
|
+
},
|
|
38958
|
+
tolerance: {
|
|
38959
|
+
type: "string",
|
|
38960
|
+
description: "Allowed pixel overflow before reporting an issue (default: 2)",
|
|
38961
|
+
default: "2"
|
|
38962
|
+
},
|
|
38963
|
+
timeout: {
|
|
38964
|
+
type: "string",
|
|
38965
|
+
description: "Ms to wait for runtime to initialize (default: 5000)",
|
|
38966
|
+
default: "5000"
|
|
38967
|
+
},
|
|
38968
|
+
"max-issues": {
|
|
38969
|
+
type: "string",
|
|
38970
|
+
description: "Maximum issues to print or return after static collapse (default: 80)",
|
|
38971
|
+
default: "80"
|
|
38972
|
+
},
|
|
38973
|
+
"collapse-static": {
|
|
38974
|
+
type: "boolean",
|
|
38975
|
+
description: "Collapse repeated static issues across samples (default: true)",
|
|
38976
|
+
default: true
|
|
38977
|
+
},
|
|
38978
|
+
strict: {
|
|
38979
|
+
type: "boolean",
|
|
38980
|
+
description: "Exit non-zero on warnings too",
|
|
38981
|
+
default: false
|
|
38982
|
+
}
|
|
38983
|
+
},
|
|
38984
|
+
async run({ args }) {
|
|
38985
|
+
const project = resolveProject(args.dir);
|
|
38986
|
+
const samples = Math.max(1, parseInt(args.samples, 10) || 9);
|
|
38987
|
+
const tolerance = Math.max(0, parseFloat(args.tolerance) || 2);
|
|
38988
|
+
const timeout = Math.max(500, parseInt(args.timeout, 10) || 5e3);
|
|
38989
|
+
const maxIssues = Math.max(1, parseInt(args["max-issues"], 10) || 80);
|
|
38990
|
+
const at2 = parseAt(args.at);
|
|
38991
|
+
const strict = !!args.strict;
|
|
38992
|
+
const collapseStatic = args["collapse-static"] !== false;
|
|
38993
|
+
if (!args.json) {
|
|
38994
|
+
const sampleLabel = at2 ? `${at2.length} explicit timestamp(s)` : `${samples} timeline samples`;
|
|
38995
|
+
console.log(
|
|
38996
|
+
`${c.accent("\u25C6")} Inspecting layout for ${c.accent(project.name)} (${sampleLabel})`
|
|
38997
|
+
);
|
|
38998
|
+
}
|
|
38999
|
+
try {
|
|
39000
|
+
const result = await runLayoutAudit(project.dir, {
|
|
39001
|
+
samples,
|
|
39002
|
+
at: at2,
|
|
39003
|
+
timeout,
|
|
39004
|
+
tolerance
|
|
39005
|
+
});
|
|
39006
|
+
const allIssues = collapseStatic ? collapseStaticLayoutIssues(result.rawIssues) : result.rawIssues;
|
|
39007
|
+
const limited = limitLayoutIssues(allIssues, maxIssues);
|
|
39008
|
+
const summary = summarizeLayoutIssues(allIssues);
|
|
39009
|
+
const ok = summary.errorCount === 0 && (!strict || summary.warningCount === 0);
|
|
39010
|
+
if (args.json) {
|
|
39011
|
+
console.log(
|
|
39012
|
+
JSON.stringify(
|
|
39013
|
+
withMeta({
|
|
39014
|
+
schemaVersion: INSPECT_SCHEMA_VERSION,
|
|
39015
|
+
duration: result.duration,
|
|
39016
|
+
samples: result.samples,
|
|
39017
|
+
tolerance,
|
|
39018
|
+
strict,
|
|
39019
|
+
collapseStatic,
|
|
39020
|
+
...summary,
|
|
39021
|
+
totalIssueCount: limited.totalIssueCount,
|
|
39022
|
+
truncated: limited.truncated,
|
|
39023
|
+
ok,
|
|
39024
|
+
issues: limited.issues
|
|
39025
|
+
}),
|
|
39026
|
+
null,
|
|
39027
|
+
2
|
|
39028
|
+
)
|
|
39029
|
+
);
|
|
39030
|
+
process.exit(ok ? 0 : 1);
|
|
39031
|
+
}
|
|
39032
|
+
if (result.samples.length === 0) {
|
|
39033
|
+
console.log();
|
|
39034
|
+
console.log(
|
|
39035
|
+
`${c.error("\u2717")} Could not determine composition duration \u2014 no layout samples run`
|
|
39036
|
+
);
|
|
39037
|
+
process.exit(1);
|
|
39038
|
+
}
|
|
39039
|
+
console.log();
|
|
39040
|
+
if (limited.issues.length === 0) {
|
|
39041
|
+
console.log(
|
|
39042
|
+
`${c.success("\u25C7")} 0 layout issues across ${result.samples.length} sample(s)`
|
|
39043
|
+
);
|
|
39044
|
+
return;
|
|
39045
|
+
}
|
|
39046
|
+
for (const issue of limited.issues) {
|
|
39047
|
+
const icon = issue.severity === "error" ? c.error("\u2717") : issue.severity === "warning" ? c.warn("\u26A0") : c.dim("\u2139");
|
|
39048
|
+
const formatted = formatLayoutIssue(issue).replace(/\n/g, "\n ");
|
|
39049
|
+
console.log(` ${icon} ${c.dim(formatted)}`);
|
|
39050
|
+
}
|
|
39051
|
+
console.log();
|
|
39052
|
+
const parts = [
|
|
39053
|
+
`${summary.errorCount} error(s)`,
|
|
39054
|
+
`${summary.warningCount} warning(s)`,
|
|
39055
|
+
`${summary.infoCount} info(s)`
|
|
39056
|
+
];
|
|
39057
|
+
const suffix = limited.truncated ? c.dim(`, truncated at ${maxIssues} issue(s)`) : "";
|
|
39058
|
+
console.log(`${ok ? c.success("\u25C7") : c.error("\u25C7")} ${parts.join(", ")}${suffix}`);
|
|
39059
|
+
process.exit(ok ? 0 : 1);
|
|
39060
|
+
} catch (err) {
|
|
39061
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
39062
|
+
if (args.json) {
|
|
39063
|
+
console.log(
|
|
39064
|
+
JSON.stringify(
|
|
39065
|
+
withMeta({
|
|
39066
|
+
schemaVersion: INSPECT_SCHEMA_VERSION,
|
|
39067
|
+
ok: false,
|
|
39068
|
+
error: message,
|
|
39069
|
+
issues: [],
|
|
39070
|
+
errorCount: 0,
|
|
39071
|
+
warningCount: 0,
|
|
39072
|
+
infoCount: 0,
|
|
39073
|
+
issueCount: 0
|
|
39074
|
+
}),
|
|
39075
|
+
null,
|
|
39076
|
+
2
|
|
39077
|
+
)
|
|
39078
|
+
);
|
|
39079
|
+
process.exit(1);
|
|
39080
|
+
}
|
|
39081
|
+
console.error(`${c.error("\u2717")} Inspect failed: ${message}`);
|
|
39082
|
+
process.exit(1);
|
|
39083
|
+
}
|
|
39084
|
+
}
|
|
39085
|
+
});
|
|
39086
|
+
}
|
|
39087
|
+
var __filename, __dirname2, SEEK_SETTLE_MS, INSPECT_SCHEMA_VERSION, examples9, layout_default;
|
|
39088
|
+
var init_layout2 = __esm({
|
|
39089
|
+
"src/commands/layout.ts"() {
|
|
39090
|
+
"use strict";
|
|
39091
|
+
init_dist();
|
|
39092
|
+
init_colors();
|
|
39093
|
+
init_project();
|
|
39094
|
+
init_updateCheck();
|
|
39095
|
+
init_layoutAudit();
|
|
39096
|
+
__filename = fileURLToPath6(import.meta.url);
|
|
39097
|
+
__dirname2 = dirname17(__filename);
|
|
39098
|
+
SEEK_SETTLE_MS = 120;
|
|
39099
|
+
INSPECT_SCHEMA_VERSION = 1;
|
|
39100
|
+
examples9 = [
|
|
39101
|
+
["Inspect visual layout across the current composition", "hyperframes layout"],
|
|
39102
|
+
["Inspect a specific project", "hyperframes layout ./my-video"],
|
|
39103
|
+
["Output agent-readable JSON", "hyperframes layout --json"],
|
|
39104
|
+
["Use explicit hero-frame timestamps", "hyperframes layout --at 1.5,4.0,7.25"]
|
|
39105
|
+
];
|
|
39106
|
+
layout_default = createInspectCommand("layout");
|
|
39107
|
+
}
|
|
39108
|
+
});
|
|
39109
|
+
|
|
39110
|
+
// src/commands/inspect.ts
|
|
39111
|
+
var inspect_exports = {};
|
|
39112
|
+
__export(inspect_exports, {
|
|
39113
|
+
default: () => inspect_default,
|
|
39114
|
+
examples: () => examples10
|
|
39115
|
+
});
|
|
39116
|
+
var examples10, inspect_default;
|
|
39117
|
+
var init_inspect = __esm({
|
|
39118
|
+
"src/commands/inspect.ts"() {
|
|
39119
|
+
"use strict";
|
|
39120
|
+
init_layout2();
|
|
39121
|
+
examples10 = [
|
|
39122
|
+
["Inspect visual layout across the current composition", "hyperframes inspect"],
|
|
39123
|
+
["Inspect a specific project", "hyperframes inspect ./my-video"],
|
|
39124
|
+
["Output agent-readable JSON", "hyperframes inspect --json"],
|
|
39125
|
+
["Use explicit hero-frame timestamps", "hyperframes inspect --at 1.5,4.0,7.25"],
|
|
39126
|
+
["Run the compatibility alias", "hyperframes layout --json"]
|
|
39127
|
+
];
|
|
39128
|
+
inspect_default = createInspectCommand("inspect");
|
|
39129
|
+
}
|
|
39130
|
+
});
|
|
39131
|
+
|
|
38554
39132
|
// src/utils/dom.ts
|
|
38555
39133
|
function ensureDOMParser() {
|
|
38556
39134
|
if (typeof globalThis.DOMParser === "undefined") {
|
|
@@ -38568,14 +39146,14 @@ var init_dom = __esm({
|
|
|
38568
39146
|
var info_exports = {};
|
|
38569
39147
|
__export(info_exports, {
|
|
38570
39148
|
default: () => info_default,
|
|
38571
|
-
examples: () =>
|
|
39149
|
+
examples: () => examples11
|
|
38572
39150
|
});
|
|
38573
|
-
import { readFileSync as
|
|
38574
|
-
import { join as
|
|
39151
|
+
import { readFileSync as readFileSync30, readdirSync as readdirSync16, statSync as statSync16 } from "fs";
|
|
39152
|
+
import { join as join43 } from "path";
|
|
38575
39153
|
function totalSize(dir) {
|
|
38576
39154
|
let total = 0;
|
|
38577
39155
|
for (const entry of readdirSync16(dir, { withFileTypes: true })) {
|
|
38578
|
-
const path2 =
|
|
39156
|
+
const path2 = join43(dir, entry.name);
|
|
38579
39157
|
if (entry.isDirectory()) {
|
|
38580
39158
|
total += totalSize(path2);
|
|
38581
39159
|
} else {
|
|
@@ -38584,7 +39162,7 @@ function totalSize(dir) {
|
|
|
38584
39162
|
}
|
|
38585
39163
|
return total;
|
|
38586
39164
|
}
|
|
38587
|
-
var
|
|
39165
|
+
var examples11, info_default;
|
|
38588
39166
|
var init_info = __esm({
|
|
38589
39167
|
"src/commands/info.ts"() {
|
|
38590
39168
|
"use strict";
|
|
@@ -38595,7 +39173,7 @@ var init_info = __esm({
|
|
|
38595
39173
|
init_dom();
|
|
38596
39174
|
init_project();
|
|
38597
39175
|
init_updateCheck();
|
|
38598
|
-
|
|
39176
|
+
examples11 = [
|
|
38599
39177
|
["Show project metadata", "hyperframes info"],
|
|
38600
39178
|
["Output as JSON", "hyperframes info --json"]
|
|
38601
39179
|
];
|
|
@@ -38607,7 +39185,7 @@ var init_info = __esm({
|
|
|
38607
39185
|
},
|
|
38608
39186
|
async run({ args }) {
|
|
38609
39187
|
const project = resolveProject(args.dir);
|
|
38610
|
-
const html =
|
|
39188
|
+
const html = readFileSync30(project.indexPath, "utf-8");
|
|
38611
39189
|
ensureDOMParser();
|
|
38612
39190
|
const parsed = parseHtml(html);
|
|
38613
39191
|
const tracks = new Set(parsed.elements.map((el) => el.zIndex));
|
|
@@ -38661,10 +39239,10 @@ var init_info = __esm({
|
|
|
38661
39239
|
var compositions_exports = {};
|
|
38662
39240
|
__export(compositions_exports, {
|
|
38663
39241
|
default: () => compositions_default,
|
|
38664
|
-
examples: () =>
|
|
39242
|
+
examples: () => examples12
|
|
38665
39243
|
});
|
|
38666
|
-
import { existsSync as
|
|
38667
|
-
import { resolve as
|
|
39244
|
+
import { existsSync as existsSync42, readFileSync as readFileSync31 } from "fs";
|
|
39245
|
+
import { resolve as resolve30, dirname as dirname18 } from "path";
|
|
38668
39246
|
function parseCompositions(html, baseDir) {
|
|
38669
39247
|
const parser = new DOMParser();
|
|
38670
39248
|
const doc = parser.parseFromString(html, "text/html");
|
|
@@ -38676,9 +39254,9 @@ function parseCompositions(html, baseDir) {
|
|
|
38676
39254
|
const height = parseInt(div.getAttribute("data-height") ?? "1080", 10);
|
|
38677
39255
|
const compositionSrc = div.getAttribute("data-composition-src");
|
|
38678
39256
|
if (compositionSrc) {
|
|
38679
|
-
const subPath =
|
|
38680
|
-
if (
|
|
38681
|
-
const subHtml =
|
|
39257
|
+
const subPath = resolve30(baseDir, compositionSrc);
|
|
39258
|
+
if (existsSync42(subPath)) {
|
|
39259
|
+
const subHtml = readFileSync31(subPath, "utf-8");
|
|
38682
39260
|
const subInfo = parseSubComposition(subHtml, id, width, height);
|
|
38683
39261
|
compositions.push({ ...subInfo, source: compositionSrc });
|
|
38684
39262
|
return;
|
|
@@ -38751,7 +39329,7 @@ function parseSubComposition(html, fallbackId, fallbackWidth, fallbackHeight) {
|
|
|
38751
39329
|
}
|
|
38752
39330
|
return { id, duration, width, height, elementCount };
|
|
38753
39331
|
}
|
|
38754
|
-
var
|
|
39332
|
+
var examples12, compositions_default;
|
|
38755
39333
|
var init_compositions = __esm({
|
|
38756
39334
|
"src/commands/compositions.ts"() {
|
|
38757
39335
|
"use strict";
|
|
@@ -38760,7 +39338,7 @@ var init_compositions = __esm({
|
|
|
38760
39338
|
init_dom();
|
|
38761
39339
|
init_project();
|
|
38762
39340
|
init_updateCheck();
|
|
38763
|
-
|
|
39341
|
+
examples12 = [
|
|
38764
39342
|
["List compositions in the current project", "hyperframes compositions"],
|
|
38765
39343
|
["Output as JSON", "hyperframes compositions --json"]
|
|
38766
39344
|
];
|
|
@@ -38772,9 +39350,9 @@ var init_compositions = __esm({
|
|
|
38772
39350
|
},
|
|
38773
39351
|
async run({ args }) {
|
|
38774
39352
|
const project = resolveProject(args.dir);
|
|
38775
|
-
const html =
|
|
39353
|
+
const html = readFileSync31(project.indexPath, "utf-8");
|
|
38776
39354
|
ensureDOMParser();
|
|
38777
|
-
const compositions = parseCompositions(html,
|
|
39355
|
+
const compositions = parseCompositions(html, dirname18(project.indexPath));
|
|
38778
39356
|
if (compositions.length === 0) {
|
|
38779
39357
|
console.log(`${c.success("\u25C7")} ${c.accent(project.name)} \u2014 no compositions found`);
|
|
38780
39358
|
return;
|
|
@@ -38808,11 +39386,11 @@ var init_compositions = __esm({
|
|
|
38808
39386
|
var benchmark_exports = {};
|
|
38809
39387
|
__export(benchmark_exports, {
|
|
38810
39388
|
default: () => benchmark_default,
|
|
38811
|
-
examples: () =>
|
|
39389
|
+
examples: () => examples13
|
|
38812
39390
|
});
|
|
38813
|
-
import { existsSync as
|
|
38814
|
-
import { resolve as
|
|
38815
|
-
var
|
|
39391
|
+
import { existsSync as existsSync43, statSync as statSync17 } from "fs";
|
|
39392
|
+
import { resolve as resolve31, join as join44 } from "path";
|
|
39393
|
+
var examples13, DEFAULT_CONFIGS, benchmark_default;
|
|
38816
39394
|
var init_benchmark = __esm({
|
|
38817
39395
|
"src/commands/benchmark.ts"() {
|
|
38818
39396
|
"use strict";
|
|
@@ -38823,7 +39401,7 @@ var init_benchmark = __esm({
|
|
|
38823
39401
|
init_format();
|
|
38824
39402
|
init_dist3();
|
|
38825
39403
|
init_updateCheck();
|
|
38826
|
-
|
|
39404
|
+
examples13 = [
|
|
38827
39405
|
["Run benchmarks with default settings (3 runs)", "hyperframes benchmark"],
|
|
38828
39406
|
["Run 5 iterations per config", "hyperframes benchmark --runs 5"],
|
|
38829
39407
|
["Output results as JSON", "hyperframes benchmark --json"]
|
|
@@ -38853,7 +39431,7 @@ var init_benchmark = __esm({
|
|
|
38853
39431
|
process.exit(1);
|
|
38854
39432
|
}
|
|
38855
39433
|
const jsonOutput = args.json ?? false;
|
|
38856
|
-
const benchDir =
|
|
39434
|
+
const benchDir = resolve31("renders", ".benchmark");
|
|
38857
39435
|
let producer = null;
|
|
38858
39436
|
try {
|
|
38859
39437
|
producer = await loadProducer();
|
|
@@ -38886,7 +39464,7 @@ var init_benchmark = __esm({
|
|
|
38886
39464
|
s2?.start(`Benchmarking ${config.label}...`);
|
|
38887
39465
|
for (let i2 = 0; i2 < runsPerConfig; i2++) {
|
|
38888
39466
|
s2?.message(`${config.label} \u2014 run ${i2 + 1}/${runsPerConfig}`);
|
|
38889
|
-
const outputPath =
|
|
39467
|
+
const outputPath = join44(
|
|
38890
39468
|
benchDir,
|
|
38891
39469
|
`${config.label.replace(/[^a-zA-Z0-9]/g, "_")}_run${i2}.mp4`
|
|
38892
39470
|
);
|
|
@@ -38900,7 +39478,7 @@ var init_benchmark = __esm({
|
|
|
38900
39478
|
await producer.executeRenderJob(job, project.dir, outputPath);
|
|
38901
39479
|
const elapsedMs = Date.now() - startTime;
|
|
38902
39480
|
let fileSize = null;
|
|
38903
|
-
if (
|
|
39481
|
+
if (existsSync43(outputPath)) {
|
|
38904
39482
|
const stat3 = statSync17(outputPath);
|
|
38905
39483
|
fileSize = stat3.size;
|
|
38906
39484
|
}
|
|
@@ -38983,7 +39561,7 @@ var init_benchmark = __esm({
|
|
|
38983
39561
|
var browser_exports = {};
|
|
38984
39562
|
__export(browser_exports, {
|
|
38985
39563
|
default: () => browser_default,
|
|
38986
|
-
examples: () =>
|
|
39564
|
+
examples: () => examples14
|
|
38987
39565
|
});
|
|
38988
39566
|
async function runEnsure() {
|
|
38989
39567
|
Wt2(c.bold("hyperframes browser ensure"));
|
|
@@ -39046,7 +39624,7 @@ function runClear() {
|
|
|
39046
39624
|
Gt(c.dim("No cached browser to remove."));
|
|
39047
39625
|
}
|
|
39048
39626
|
}
|
|
39049
|
-
var
|
|
39627
|
+
var examples14, browser_default;
|
|
39050
39628
|
var init_browser = __esm({
|
|
39051
39629
|
"src/commands/browser.ts"() {
|
|
39052
39630
|
"use strict";
|
|
@@ -39056,7 +39634,7 @@ var init_browser = __esm({
|
|
|
39056
39634
|
init_format();
|
|
39057
39635
|
init_manager2();
|
|
39058
39636
|
init_events();
|
|
39059
|
-
|
|
39637
|
+
examples14 = [
|
|
39060
39638
|
["Find or download Chrome for rendering", "hyperframes browser ensure"],
|
|
39061
39639
|
["Print the Chrome executable path", "hyperframes browser path"],
|
|
39062
39640
|
["Remove cached Chrome download", "hyperframes browser clear"]
|
|
@@ -39114,10 +39692,10 @@ Run ${c.accent("hyperframes browser --help")} for usage.`
|
|
|
39114
39692
|
var transcribe_exports2 = {};
|
|
39115
39693
|
__export(transcribe_exports2, {
|
|
39116
39694
|
default: () => transcribe_default,
|
|
39117
|
-
examples: () =>
|
|
39695
|
+
examples: () => examples15
|
|
39118
39696
|
});
|
|
39119
|
-
import { existsSync as
|
|
39120
|
-
import { resolve as
|
|
39697
|
+
import { existsSync as existsSync44, writeFileSync as writeFileSync17 } from "fs";
|
|
39698
|
+
import { resolve as resolve32, join as join45, extname as extname8 } from "path";
|
|
39121
39699
|
async function importTranscript(inputPath, dir, json) {
|
|
39122
39700
|
const { loadTranscript: loadTranscript2, patchCaptionHtml: patchCaptionHtml2 } = await Promise.resolve().then(() => (init_normalize(), normalize_exports));
|
|
39123
39701
|
const { words, format } = loadTranscript2(inputPath);
|
|
@@ -39125,7 +39703,7 @@ async function importTranscript(inputPath, dir, json) {
|
|
|
39125
39703
|
console.error(c.error("No words found in transcript."));
|
|
39126
39704
|
process.exit(1);
|
|
39127
39705
|
}
|
|
39128
|
-
const outPath =
|
|
39706
|
+
const outPath = join45(dir, "transcript.json");
|
|
39129
39707
|
writeFileSync17(outPath, JSON.stringify(words, null, 2));
|
|
39130
39708
|
patchCaptionHtml2(dir, words);
|
|
39131
39709
|
if (json) {
|
|
@@ -39192,7 +39770,7 @@ async function transcribeAudio(inputPath, dir, opts) {
|
|
|
39192
39770
|
process.exit(1);
|
|
39193
39771
|
}
|
|
39194
39772
|
}
|
|
39195
|
-
var
|
|
39773
|
+
var examples15, transcribe_default;
|
|
39196
39774
|
var init_transcribe2 = __esm({
|
|
39197
39775
|
"src/commands/transcribe.ts"() {
|
|
39198
39776
|
"use strict";
|
|
@@ -39200,7 +39778,7 @@ var init_transcribe2 = __esm({
|
|
|
39200
39778
|
init_dist3();
|
|
39201
39779
|
init_colors();
|
|
39202
39780
|
init_manager();
|
|
39203
|
-
|
|
39781
|
+
examples15 = [
|
|
39204
39782
|
["Transcribe an audio file", "hyperframes transcribe audio.mp3"],
|
|
39205
39783
|
["Transcribe a video file", "hyperframes transcribe video.mp4"],
|
|
39206
39784
|
["Use a larger model for better accuracy", "hyperframes transcribe audio.mp3 --model medium.en"],
|
|
@@ -39241,12 +39819,12 @@ var init_transcribe2 = __esm({
|
|
|
39241
39819
|
}
|
|
39242
39820
|
},
|
|
39243
39821
|
async run({ args }) {
|
|
39244
|
-
const inputPath =
|
|
39245
|
-
if (!
|
|
39822
|
+
const inputPath = resolve32(args.input);
|
|
39823
|
+
if (!existsSync44(inputPath)) {
|
|
39246
39824
|
console.error(c.error(`File not found: ${args.input}`));
|
|
39247
39825
|
process.exit(1);
|
|
39248
39826
|
}
|
|
39249
|
-
const dir =
|
|
39827
|
+
const dir = resolve32(args.dir ?? ".");
|
|
39250
39828
|
const ext = extname8(inputPath).toLowerCase();
|
|
39251
39829
|
const isImport = ext === ".json" || ext === ".srt" || ext === ".vtt";
|
|
39252
39830
|
if (isImport) {
|
|
@@ -39263,9 +39841,9 @@ var init_transcribe2 = __esm({
|
|
|
39263
39841
|
});
|
|
39264
39842
|
|
|
39265
39843
|
// src/tts/manager.ts
|
|
39266
|
-
import { existsSync as
|
|
39844
|
+
import { existsSync as existsSync45, mkdirSync as mkdirSync23 } from "fs";
|
|
39267
39845
|
import { homedir as homedir8 } from "os";
|
|
39268
|
-
import { join as
|
|
39846
|
+
import { join as join46 } from "path";
|
|
39269
39847
|
function inferLangFromVoiceId(voiceId) {
|
|
39270
39848
|
const first = voiceId.charAt(0).toLowerCase();
|
|
39271
39849
|
return VOICE_PREFIX_LANG[first] ?? "en-us";
|
|
@@ -39274,8 +39852,8 @@ function isSupportedLang(value) {
|
|
|
39274
39852
|
return SUPPORTED_LANGS.includes(value);
|
|
39275
39853
|
}
|
|
39276
39854
|
async function ensureModel2(model = DEFAULT_MODEL2, options) {
|
|
39277
|
-
const modelPath =
|
|
39278
|
-
if (
|
|
39855
|
+
const modelPath = join46(MODELS_DIR2, `${model}.onnx`);
|
|
39856
|
+
if (existsSync45(modelPath)) return modelPath;
|
|
39279
39857
|
const url = MODEL_URLS[model];
|
|
39280
39858
|
if (!url) {
|
|
39281
39859
|
throw new Error(
|
|
@@ -39285,18 +39863,18 @@ async function ensureModel2(model = DEFAULT_MODEL2, options) {
|
|
|
39285
39863
|
mkdirSync23(MODELS_DIR2, { recursive: true });
|
|
39286
39864
|
options?.onProgress?.(`Downloading TTS model ${model} (~311 MB)...`);
|
|
39287
39865
|
await downloadFile(url, modelPath);
|
|
39288
|
-
if (!
|
|
39866
|
+
if (!existsSync45(modelPath)) {
|
|
39289
39867
|
throw new Error(`Model download failed: ${model}`);
|
|
39290
39868
|
}
|
|
39291
39869
|
return modelPath;
|
|
39292
39870
|
}
|
|
39293
39871
|
async function ensureVoices(options) {
|
|
39294
|
-
const voicesPath =
|
|
39295
|
-
if (
|
|
39872
|
+
const voicesPath = join46(VOICES_DIR, "voices-v1.0.bin");
|
|
39873
|
+
if (existsSync45(voicesPath)) return voicesPath;
|
|
39296
39874
|
mkdirSync23(VOICES_DIR, { recursive: true });
|
|
39297
39875
|
options?.onProgress?.("Downloading voice data (~27 MB)...");
|
|
39298
39876
|
await downloadFile(VOICES_URL, voicesPath);
|
|
39299
|
-
if (!
|
|
39877
|
+
if (!existsSync45(voicesPath)) {
|
|
39300
39878
|
throw new Error("Voice data download failed");
|
|
39301
39879
|
}
|
|
39302
39880
|
return voicesPath;
|
|
@@ -39306,9 +39884,9 @@ var init_manager3 = __esm({
|
|
|
39306
39884
|
"src/tts/manager.ts"() {
|
|
39307
39885
|
"use strict";
|
|
39308
39886
|
init_download();
|
|
39309
|
-
CACHE_DIR3 =
|
|
39310
|
-
MODELS_DIR2 =
|
|
39311
|
-
VOICES_DIR =
|
|
39887
|
+
CACHE_DIR3 = join46(homedir8(), ".cache", "hyperframes", "tts");
|
|
39888
|
+
MODELS_DIR2 = join46(CACHE_DIR3, "models");
|
|
39889
|
+
VOICES_DIR = join46(CACHE_DIR3, "voices");
|
|
39312
39890
|
DEFAULT_MODEL2 = "kokoro-v1.0";
|
|
39313
39891
|
MODEL_URLS = {
|
|
39314
39892
|
"kokoro-v1.0": "https://github.com/thewh1teagle/kokoro-onnx/releases/download/model-files-v1.0/kokoro-v1.0.onnx"
|
|
@@ -39369,8 +39947,8 @@ __export(synthesize_exports, {
|
|
|
39369
39947
|
synthesize: () => synthesize
|
|
39370
39948
|
});
|
|
39371
39949
|
import { execFileSync as execFileSync6 } from "child_process";
|
|
39372
|
-
import { existsSync as
|
|
39373
|
-
import { join as
|
|
39950
|
+
import { existsSync as existsSync46, writeFileSync as writeFileSync18, mkdirSync as mkdirSync24, readdirSync as readdirSync17, unlinkSync as unlinkSync6 } from "fs";
|
|
39951
|
+
import { join as join47, dirname as dirname19, basename as basename10 } from "path";
|
|
39374
39952
|
import { homedir as homedir9 } from "os";
|
|
39375
39953
|
function findPython() {
|
|
39376
39954
|
for (const name of ["python3", "python"]) {
|
|
@@ -39406,7 +39984,7 @@ function hasPythonPackage(python, pkg) {
|
|
|
39406
39984
|
}
|
|
39407
39985
|
}
|
|
39408
39986
|
function ensureSynthScript() {
|
|
39409
|
-
if (!
|
|
39987
|
+
if (!existsSync46(SCRIPT_PATH)) {
|
|
39410
39988
|
mkdirSync24(SCRIPT_DIR, { recursive: true });
|
|
39411
39989
|
writeFileSync18(SCRIPT_PATH, SYNTH_SCRIPT);
|
|
39412
39990
|
const currentName = basename10(SCRIPT_PATH);
|
|
@@ -39414,7 +39992,7 @@ function ensureSynthScript() {
|
|
|
39414
39992
|
for (const entry of readdirSync17(SCRIPT_DIR)) {
|
|
39415
39993
|
if (entry !== currentName && /^synth(-v\d+)?\.py$/.test(entry)) {
|
|
39416
39994
|
try {
|
|
39417
|
-
unlinkSync6(
|
|
39995
|
+
unlinkSync6(join47(SCRIPT_DIR, entry));
|
|
39418
39996
|
} catch {
|
|
39419
39997
|
}
|
|
39420
39998
|
}
|
|
@@ -39448,7 +40026,7 @@ async function synthesize(text, outputPath, options) {
|
|
|
39448
40026
|
ensureVoices({ onProgress: options?.onProgress })
|
|
39449
40027
|
]);
|
|
39450
40028
|
const scriptPath = ensureSynthScript();
|
|
39451
|
-
mkdirSync24(
|
|
40029
|
+
mkdirSync24(dirname19(outputPath), { recursive: true });
|
|
39452
40030
|
options?.onProgress?.(`Generating speech with voice ${voice} (${lang})...`);
|
|
39453
40031
|
try {
|
|
39454
40032
|
const stdout2 = execFileSync6(
|
|
@@ -39460,7 +40038,7 @@ async function synthesize(text, outputPath, options) {
|
|
|
39460
40038
|
stdio: ["pipe", "pipe", "pipe"]
|
|
39461
40039
|
}
|
|
39462
40040
|
);
|
|
39463
|
-
if (!
|
|
40041
|
+
if (!existsSync46(outputPath)) {
|
|
39464
40042
|
throw new Error("Synthesis completed but no output file was created");
|
|
39465
40043
|
}
|
|
39466
40044
|
const lines = stdout2.trim().split("\n");
|
|
@@ -39473,7 +40051,7 @@ async function synthesize(text, outputPath, options) {
|
|
|
39473
40051
|
langApplied: result.langApplied
|
|
39474
40052
|
};
|
|
39475
40053
|
} catch (err) {
|
|
39476
|
-
if (err instanceof SyntaxError &&
|
|
40054
|
+
if (err instanceof SyntaxError && existsSync46(outputPath)) {
|
|
39477
40055
|
throw new Error(
|
|
39478
40056
|
"Speech was generated but metadata could not be read. Check the output file manually."
|
|
39479
40057
|
);
|
|
@@ -39524,8 +40102,8 @@ print(json.dumps({
|
|
|
39524
40102
|
"langApplied": bool(lang and supports_lang),
|
|
39525
40103
|
}))
|
|
39526
40104
|
`;
|
|
39527
|
-
SCRIPT_DIR =
|
|
39528
|
-
SCRIPT_PATH =
|
|
40105
|
+
SCRIPT_DIR = join47(homedir9(), ".cache", "hyperframes", "tts");
|
|
40106
|
+
SCRIPT_PATH = join47(SCRIPT_DIR, "synth-v2.py");
|
|
39529
40107
|
}
|
|
39530
40108
|
});
|
|
39531
40109
|
|
|
@@ -39533,10 +40111,10 @@ print(json.dumps({
|
|
|
39533
40111
|
var tts_exports = {};
|
|
39534
40112
|
__export(tts_exports, {
|
|
39535
40113
|
default: () => tts_default,
|
|
39536
|
-
examples: () =>
|
|
40114
|
+
examples: () => examples16
|
|
39537
40115
|
});
|
|
39538
|
-
import { existsSync as
|
|
39539
|
-
import { resolve as
|
|
40116
|
+
import { existsSync as existsSync47, readFileSync as readFileSync32 } from "fs";
|
|
40117
|
+
import { resolve as resolve33, extname as extname9 } from "path";
|
|
39540
40118
|
function listVoices(json) {
|
|
39541
40119
|
const rows = BUNDLED_VOICES.map((v) => ({ ...v, defaultLang: inferLangFromVoiceId(v.id) }));
|
|
39542
40120
|
if (json) {
|
|
@@ -39566,7 +40144,7 @@ ${c.bold("Available voices")} (Kokoro-82M)
|
|
|
39566
40144
|
`
|
|
39567
40145
|
);
|
|
39568
40146
|
}
|
|
39569
|
-
var
|
|
40147
|
+
var examples16, voiceList, langList, tts_default;
|
|
39570
40148
|
var init_tts = __esm({
|
|
39571
40149
|
"src/commands/tts.ts"() {
|
|
39572
40150
|
"use strict";
|
|
@@ -39575,7 +40153,7 @@ var init_tts = __esm({
|
|
|
39575
40153
|
init_colors();
|
|
39576
40154
|
init_format();
|
|
39577
40155
|
init_manager3();
|
|
39578
|
-
|
|
40156
|
+
examples16 = [
|
|
39579
40157
|
["Generate speech from text", 'hyperframes tts "Welcome to HyperFrames"'],
|
|
39580
40158
|
["Choose a voice", 'hyperframes tts "Hello world" --voice am_adam'],
|
|
39581
40159
|
["Save to a specific file", 'hyperframes tts "Intro" --voice bf_emma --output narration.wav'],
|
|
@@ -39644,9 +40222,9 @@ var init_tts = __esm({
|
|
|
39644
40222
|
process.exit(1);
|
|
39645
40223
|
}
|
|
39646
40224
|
let text;
|
|
39647
|
-
const maybeFile =
|
|
39648
|
-
if (
|
|
39649
|
-
text =
|
|
40225
|
+
const maybeFile = resolve33(args.input);
|
|
40226
|
+
if (existsSync47(maybeFile) && extname9(maybeFile).toLowerCase() === ".txt") {
|
|
40227
|
+
text = readFileSync32(maybeFile, "utf-8").trim();
|
|
39650
40228
|
if (!text) {
|
|
39651
40229
|
console.error(c.error("File is empty."));
|
|
39652
40230
|
process.exit(1);
|
|
@@ -39658,7 +40236,7 @@ var init_tts = __esm({
|
|
|
39658
40236
|
console.error(c.error("No text provided."));
|
|
39659
40237
|
process.exit(1);
|
|
39660
40238
|
}
|
|
39661
|
-
const output =
|
|
40239
|
+
const output = resolve33(args.output ?? "speech.wav");
|
|
39662
40240
|
const voice = args.voice ?? DEFAULT_VOICE;
|
|
39663
40241
|
const speed = args.speed ? parseFloat(args.speed) : 1;
|
|
39664
40242
|
if (isNaN(speed) || speed <= 0 || speed > 3) {
|
|
@@ -39736,17 +40314,17 @@ var init_tts = __esm({
|
|
|
39736
40314
|
var docs_exports = {};
|
|
39737
40315
|
__export(docs_exports, {
|
|
39738
40316
|
default: () => docs_default,
|
|
39739
|
-
examples: () =>
|
|
40317
|
+
examples: () => examples17
|
|
39740
40318
|
});
|
|
39741
|
-
import { readFileSync as
|
|
39742
|
-
import { resolve as
|
|
39743
|
-
import { fileURLToPath as
|
|
40319
|
+
import { readFileSync as readFileSync33, existsSync as existsSync48 } from "fs";
|
|
40320
|
+
import { resolve as resolve34, dirname as dirname20, join as join48 } from "path";
|
|
40321
|
+
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
39744
40322
|
function docsDir() {
|
|
39745
|
-
const thisFile =
|
|
39746
|
-
const dir =
|
|
39747
|
-
const devPath =
|
|
39748
|
-
const builtPath =
|
|
39749
|
-
return
|
|
40323
|
+
const thisFile = fileURLToPath7(import.meta.url);
|
|
40324
|
+
const dir = dirname20(thisFile);
|
|
40325
|
+
const devPath = resolve34(dir, "..", "docs");
|
|
40326
|
+
const builtPath = resolve34(dir, "docs");
|
|
40327
|
+
return existsSync48(devPath) ? devPath : builtPath;
|
|
39750
40328
|
}
|
|
39751
40329
|
function formatInlineCode(line) {
|
|
39752
40330
|
return line.replace(/`([^`]+)`/g, (_match, code) => c.accent(code));
|
|
@@ -39773,13 +40351,13 @@ function renderMarkdown(content) {
|
|
|
39773
40351
|
console.log(formatInlineCode(line));
|
|
39774
40352
|
}
|
|
39775
40353
|
}
|
|
39776
|
-
var
|
|
40354
|
+
var examples17, TOPICS, TOPIC_NAMES, docs_default;
|
|
39777
40355
|
var init_docs = __esm({
|
|
39778
40356
|
"src/commands/docs.ts"() {
|
|
39779
40357
|
"use strict";
|
|
39780
40358
|
init_dist();
|
|
39781
40359
|
init_colors();
|
|
39782
|
-
|
|
40360
|
+
examples17 = [
|
|
39783
40361
|
["List all available topics", "hyperframes docs"],
|
|
39784
40362
|
["Read about data attributes", "hyperframes docs data-attributes"],
|
|
39785
40363
|
["Read about rendering", "hyperframes docs rendering"],
|
|
@@ -39843,12 +40421,12 @@ var init_docs = __esm({
|
|
|
39843
40421
|
}
|
|
39844
40422
|
process.exit(1);
|
|
39845
40423
|
}
|
|
39846
|
-
const filePath =
|
|
39847
|
-
if (!
|
|
40424
|
+
const filePath = join48(docsDir(), entry.file);
|
|
40425
|
+
if (!existsSync48(filePath)) {
|
|
39848
40426
|
console.error(c.error(`Doc file not found: ${filePath}`));
|
|
39849
40427
|
process.exit(1);
|
|
39850
40428
|
}
|
|
39851
|
-
const content =
|
|
40429
|
+
const content = readFileSync33(filePath, "utf-8");
|
|
39852
40430
|
console.log();
|
|
39853
40431
|
renderMarkdown(content);
|
|
39854
40432
|
}
|
|
@@ -39860,7 +40438,7 @@ var init_docs = __esm({
|
|
|
39860
40438
|
var doctor_exports = {};
|
|
39861
40439
|
__export(doctor_exports, {
|
|
39862
40440
|
default: () => doctor_default,
|
|
39863
|
-
examples: () =>
|
|
40441
|
+
examples: () => examples18
|
|
39864
40442
|
});
|
|
39865
40443
|
import { execSync as execSync3 } from "child_process";
|
|
39866
40444
|
import { freemem as freemem4, platform as platform4 } from "os";
|
|
@@ -40002,7 +40580,7 @@ function checkEnvironment() {
|
|
|
40002
40580
|
}
|
|
40003
40581
|
return { ok: true, detail: parts.join(" \xB7 ") };
|
|
40004
40582
|
}
|
|
40005
|
-
var
|
|
40583
|
+
var examples18, doctor_default;
|
|
40006
40584
|
var init_doctor = __esm({
|
|
40007
40585
|
"src/commands/doctor.ts"() {
|
|
40008
40586
|
"use strict";
|
|
@@ -40013,7 +40591,7 @@ var init_doctor = __esm({
|
|
|
40013
40591
|
init_version();
|
|
40014
40592
|
init_updateCheck();
|
|
40015
40593
|
init_system();
|
|
40016
|
-
|
|
40594
|
+
examples18 = [["Check system dependencies", "hyperframes doctor"]];
|
|
40017
40595
|
doctor_default = defineCommand({
|
|
40018
40596
|
meta: { name: "doctor", description: "Check system dependencies and environment" },
|
|
40019
40597
|
args: {},
|
|
@@ -40068,10 +40646,10 @@ var init_doctor = __esm({
|
|
|
40068
40646
|
var upgrade_exports = {};
|
|
40069
40647
|
__export(upgrade_exports, {
|
|
40070
40648
|
default: () => upgrade_default,
|
|
40071
|
-
examples: () =>
|
|
40649
|
+
examples: () => examples19
|
|
40072
40650
|
});
|
|
40073
40651
|
import { execSync as execSync4 } from "child_process";
|
|
40074
|
-
var
|
|
40652
|
+
var examples19, upgrade_default;
|
|
40075
40653
|
var init_upgrade = __esm({
|
|
40076
40654
|
"src/commands/upgrade.ts"() {
|
|
40077
40655
|
"use strict";
|
|
@@ -40080,7 +40658,7 @@ var init_upgrade = __esm({
|
|
|
40080
40658
|
init_colors();
|
|
40081
40659
|
init_version();
|
|
40082
40660
|
init_updateCheck();
|
|
40083
|
-
|
|
40661
|
+
examples19 = [
|
|
40084
40662
|
["Check for updates interactively", "hyperframes upgrade"],
|
|
40085
40663
|
["Check for updates without prompting", "hyperframes upgrade --check"],
|
|
40086
40664
|
["Upgrade non-interactively", "hyperframes upgrade --yes"]
|
|
@@ -40158,7 +40736,7 @@ var init_upgrade = __esm({
|
|
|
40158
40736
|
var telemetry_exports = {};
|
|
40159
40737
|
__export(telemetry_exports, {
|
|
40160
40738
|
default: () => telemetry_default,
|
|
40161
|
-
examples: () =>
|
|
40739
|
+
examples: () => examples20
|
|
40162
40740
|
});
|
|
40163
40741
|
function runEnable() {
|
|
40164
40742
|
const config = readConfig();
|
|
@@ -40188,14 +40766,14 @@ function runStatus() {
|
|
|
40188
40766
|
console.log(` ${c.dim("Env var:")} ${c.accent("HYPERFRAMES_NO_TELEMETRY=1")}`);
|
|
40189
40767
|
console.log();
|
|
40190
40768
|
}
|
|
40191
|
-
var
|
|
40769
|
+
var examples20, telemetry_default;
|
|
40192
40770
|
var init_telemetry = __esm({
|
|
40193
40771
|
"src/commands/telemetry.ts"() {
|
|
40194
40772
|
"use strict";
|
|
40195
40773
|
init_dist();
|
|
40196
40774
|
init_colors();
|
|
40197
40775
|
init_config();
|
|
40198
|
-
|
|
40776
|
+
examples20 = [
|
|
40199
40777
|
["Check current telemetry status", "hyperframes telemetry status"],
|
|
40200
40778
|
["Disable telemetry", "hyperframes telemetry disable"],
|
|
40201
40779
|
["Enable telemetry", "hyperframes telemetry enable"]
|
|
@@ -40274,17 +40852,17 @@ var validate_exports = {};
|
|
|
40274
40852
|
__export(validate_exports, {
|
|
40275
40853
|
default: () => validate_default
|
|
40276
40854
|
});
|
|
40277
|
-
import { existsSync as
|
|
40278
|
-
import { resolve as
|
|
40279
|
-
import { fileURLToPath as
|
|
40280
|
-
async function
|
|
40855
|
+
import { existsSync as existsSync49, readFileSync as readFileSync34 } from "fs";
|
|
40856
|
+
import { resolve as resolve35, join as join49, dirname as dirname21 } from "path";
|
|
40857
|
+
import { fileURLToPath as fileURLToPath8 } from "url";
|
|
40858
|
+
async function getCompositionDuration3(page) {
|
|
40281
40859
|
return page.evaluate(() => {
|
|
40282
40860
|
if (window.__hf?.duration && window.__hf.duration > 0) return window.__hf.duration;
|
|
40283
40861
|
const root = document.querySelector("[data-composition-id][data-duration]");
|
|
40284
40862
|
return root ? parseFloat(root.getAttribute("data-duration") ?? "0") : 0;
|
|
40285
40863
|
});
|
|
40286
40864
|
}
|
|
40287
|
-
async function
|
|
40865
|
+
async function seekTo2(page, time) {
|
|
40288
40866
|
await page.evaluate((t3) => {
|
|
40289
40867
|
if (window.__hf && typeof window.__hf.seek === "function") {
|
|
40290
40868
|
window.__hf.seek(t3);
|
|
@@ -40297,16 +40875,16 @@ async function seekTo(page, time) {
|
|
|
40297
40875
|
}
|
|
40298
40876
|
}
|
|
40299
40877
|
}, time);
|
|
40300
|
-
await new Promise((r2) => setTimeout(r2,
|
|
40878
|
+
await new Promise((r2) => setTimeout(r2, SEEK_SETTLE_MS2));
|
|
40301
40879
|
}
|
|
40302
40880
|
async function runContrastAudit(page) {
|
|
40303
|
-
const duration = await
|
|
40881
|
+
const duration = await getCompositionDuration3(page);
|
|
40304
40882
|
if (duration <= 0) return [];
|
|
40305
40883
|
await page.addScriptTag({ content: contrast_audit_browser_default });
|
|
40306
40884
|
const results = [];
|
|
40307
40885
|
for (let i2 = 0; i2 < CONTRAST_SAMPLES; i2++) {
|
|
40308
40886
|
const t3 = +((i2 + 0.5) / CONTRAST_SAMPLES * duration).toFixed(3);
|
|
40309
|
-
await
|
|
40887
|
+
await seekTo2(page, t3);
|
|
40310
40888
|
const screenshot = await page.screenshot({ encoding: "base64", type: "png" });
|
|
40311
40889
|
const entries2 = await page.evaluate(
|
|
40312
40890
|
(b64, time) => typeof window.__contrastAudit === "function" ? window.__contrastAudit(b64, time) : [],
|
|
@@ -40321,8 +40899,8 @@ async function validateInBrowser(projectDir, opts) {
|
|
|
40321
40899
|
const { bundleToSingleHtml: bundleToSingleHtml2 } = await Promise.resolve().then(() => (init_compiler(), compiler_exports));
|
|
40322
40900
|
const { ensureBrowser: ensureBrowser2 } = await Promise.resolve().then(() => (init_manager2(), manager_exports2));
|
|
40323
40901
|
let html = await bundleToSingleHtml2(projectDir);
|
|
40324
|
-
const runtimePath =
|
|
40325
|
-
|
|
40902
|
+
const runtimePath = resolve35(
|
|
40903
|
+
__dirname3,
|
|
40326
40904
|
"..",
|
|
40327
40905
|
"..",
|
|
40328
40906
|
"..",
|
|
@@ -40330,26 +40908,26 @@ async function validateInBrowser(projectDir, opts) {
|
|
|
40330
40908
|
"dist",
|
|
40331
40909
|
"hyperframe.runtime.iife.js"
|
|
40332
40910
|
);
|
|
40333
|
-
if (
|
|
40334
|
-
const runtimeSource =
|
|
40911
|
+
if (existsSync49(runtimePath)) {
|
|
40912
|
+
const runtimeSource = readFileSync34(runtimePath, "utf-8");
|
|
40335
40913
|
html = html.replace(
|
|
40336
40914
|
/<script[^>]*data-hyperframes-preview-runtime[^>]*src="[^"]*"[^>]*><\/script>/,
|
|
40337
40915
|
() => `<script data-hyperframes-preview-runtime="1">${runtimeSource}</script>`
|
|
40338
40916
|
);
|
|
40339
40917
|
}
|
|
40340
|
-
const { createServer } = await import("http");
|
|
40918
|
+
const { createServer: createServer2 } = await import("http");
|
|
40341
40919
|
const { getMimeType: getMimeType2 } = await Promise.resolve().then(() => (init_studio_api(), studio_api_exports));
|
|
40342
|
-
const server =
|
|
40920
|
+
const server = createServer2((req, res) => {
|
|
40343
40921
|
const url = req.url ?? "/";
|
|
40344
40922
|
if (url === "/" || url === "/index.html") {
|
|
40345
40923
|
res.writeHead(200, { "Content-Type": "text/html" });
|
|
40346
40924
|
res.end(html);
|
|
40347
40925
|
return;
|
|
40348
40926
|
}
|
|
40349
|
-
const filePath =
|
|
40350
|
-
if (
|
|
40927
|
+
const filePath = join49(projectDir, decodeURIComponent(url));
|
|
40928
|
+
if (existsSync49(filePath)) {
|
|
40351
40929
|
res.writeHead(200, { "Content-Type": getMimeType2(filePath) });
|
|
40352
|
-
res.end(
|
|
40930
|
+
res.end(readFileSync34(filePath));
|
|
40353
40931
|
return;
|
|
40354
40932
|
}
|
|
40355
40933
|
res.writeHead(404);
|
|
@@ -40427,7 +41005,7 @@ function printContrastFailures(failures) {
|
|
|
40427
41005
|
);
|
|
40428
41006
|
}
|
|
40429
41007
|
}
|
|
40430
|
-
var
|
|
41008
|
+
var __filename2, __dirname3, CONTRAST_SAMPLES, SEEK_SETTLE_MS2, validate_default;
|
|
40431
41009
|
var init_validate = __esm({
|
|
40432
41010
|
"src/commands/validate.ts"() {
|
|
40433
41011
|
"use strict";
|
|
@@ -40436,10 +41014,10 @@ var init_validate = __esm({
|
|
|
40436
41014
|
init_colors();
|
|
40437
41015
|
init_updateCheck();
|
|
40438
41016
|
init_contrast_audit_browser();
|
|
40439
|
-
|
|
40440
|
-
|
|
41017
|
+
__filename2 = fileURLToPath8(import.meta.url);
|
|
41018
|
+
__dirname3 = dirname21(__filename2);
|
|
40441
41019
|
CONTRAST_SAMPLES = 5;
|
|
40442
|
-
|
|
41020
|
+
SEEK_SETTLE_MS2 = 150;
|
|
40443
41021
|
validate_default = defineCommand({
|
|
40444
41022
|
meta: {
|
|
40445
41023
|
name: "validate",
|
|
@@ -40537,16 +41115,16 @@ Examples:
|
|
|
40537
41115
|
var snapshot_exports = {};
|
|
40538
41116
|
__export(snapshot_exports, {
|
|
40539
41117
|
default: () => snapshot_default,
|
|
40540
|
-
examples: () =>
|
|
41118
|
+
examples: () => examples21
|
|
40541
41119
|
});
|
|
40542
41120
|
import { spawn as spawn11 } from "child_process";
|
|
40543
|
-
import { existsSync as
|
|
41121
|
+
import { existsSync as existsSync50, mkdtempSync as mkdtempSync3, readFileSync as readFileSync35, mkdirSync as mkdirSync25, rmSync as rmSync10 } from "fs";
|
|
40544
41122
|
import { tmpdir as tmpdir5 } from "os";
|
|
40545
|
-
import { resolve as
|
|
40546
|
-
import { fileURLToPath as
|
|
41123
|
+
import { resolve as resolve36, join as join50, dirname as dirname22, relative as relative6, isAbsolute as isAbsolute7 } from "path";
|
|
41124
|
+
import { fileURLToPath as fileURLToPath9 } from "url";
|
|
40547
41125
|
async function extractVideoFrameToBuffer(videoPath, timeSeconds, useVp9AlphaDecoder = false) {
|
|
40548
|
-
const tmp = mkdtempSync3(
|
|
40549
|
-
const outPath =
|
|
41126
|
+
const tmp = mkdtempSync3(join50(tmpdir5(), "hf-snapshot-frame-"));
|
|
41127
|
+
const outPath = join50(tmp, "frame.png");
|
|
40550
41128
|
try {
|
|
40551
41129
|
const result = await new Promise(
|
|
40552
41130
|
(resolvePromise) => {
|
|
@@ -40586,8 +41164,8 @@ async function extractVideoFrameToBuffer(videoPath, timeSeconds, useVp9AlphaDeco
|
|
|
40586
41164
|
});
|
|
40587
41165
|
}
|
|
40588
41166
|
);
|
|
40589
|
-
if (result.code !== 0 || result.timedOut || !
|
|
40590
|
-
return
|
|
41167
|
+
if (result.code !== 0 || result.timedOut || !existsSync50(outPath)) return null;
|
|
41168
|
+
return readFileSync35(outPath);
|
|
40591
41169
|
} finally {
|
|
40592
41170
|
try {
|
|
40593
41171
|
rmSync10(tmp, { recursive: true, force: true });
|
|
@@ -40600,8 +41178,8 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
40600
41178
|
const { ensureBrowser: ensureBrowser2 } = await Promise.resolve().then(() => (init_manager2(), manager_exports2));
|
|
40601
41179
|
const numFrames = opts.frames ?? 5;
|
|
40602
41180
|
let html = await bundleToSingleHtml2(projectDir);
|
|
40603
|
-
const runtimePath =
|
|
40604
|
-
|
|
41181
|
+
const runtimePath = resolve36(
|
|
41182
|
+
__dirname4,
|
|
40605
41183
|
"..",
|
|
40606
41184
|
"..",
|
|
40607
41185
|
"..",
|
|
@@ -40609,32 +41187,32 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
40609
41187
|
"dist",
|
|
40610
41188
|
"hyperframe.runtime.iife.js"
|
|
40611
41189
|
);
|
|
40612
|
-
if (
|
|
40613
|
-
const runtimeSource =
|
|
41190
|
+
if (existsSync50(runtimePath)) {
|
|
41191
|
+
const runtimeSource = readFileSync35(runtimePath, "utf-8");
|
|
40614
41192
|
html = html.replace(
|
|
40615
41193
|
/<script[^>]*data-hyperframes-preview-runtime[^>]*src="[^"]*"[^>]*><\/script>/,
|
|
40616
41194
|
() => `<script data-hyperframes-preview-runtime="1">${runtimeSource}</script>`
|
|
40617
41195
|
);
|
|
40618
41196
|
}
|
|
40619
|
-
const { createServer } = await import("http");
|
|
41197
|
+
const { createServer: createServer2 } = await import("http");
|
|
40620
41198
|
const { getMimeType: getMimeType2 } = await Promise.resolve().then(() => (init_studio_api(), studio_api_exports));
|
|
40621
|
-
const server =
|
|
41199
|
+
const server = createServer2((req, res) => {
|
|
40622
41200
|
const url = req.url ?? "/";
|
|
40623
41201
|
if (url === "/" || url === "/index.html") {
|
|
40624
41202
|
res.writeHead(200, { "Content-Type": "text/html" });
|
|
40625
41203
|
res.end(html);
|
|
40626
41204
|
return;
|
|
40627
41205
|
}
|
|
40628
|
-
const filePath =
|
|
40629
|
-
const rel =
|
|
40630
|
-
if (rel.startsWith("..") ||
|
|
41206
|
+
const filePath = resolve36(projectDir, decodeURIComponent(url).replace(/^\//, ""));
|
|
41207
|
+
const rel = relative6(projectDir, filePath);
|
|
41208
|
+
if (rel.startsWith("..") || isAbsolute7(rel)) {
|
|
40631
41209
|
res.writeHead(403);
|
|
40632
41210
|
res.end();
|
|
40633
41211
|
return;
|
|
40634
41212
|
}
|
|
40635
|
-
if (
|
|
41213
|
+
if (existsSync50(filePath)) {
|
|
40636
41214
|
res.writeHead(200, { "Content-Type": getMimeType2(filePath) });
|
|
40637
|
-
res.end(
|
|
41215
|
+
res.end(readFileSync35(filePath));
|
|
40638
41216
|
return;
|
|
40639
41217
|
}
|
|
40640
41218
|
res.writeHead(404);
|
|
@@ -40707,7 +41285,7 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
40707
41285
|
return [];
|
|
40708
41286
|
}
|
|
40709
41287
|
const positions = opts.at?.length ? opts.at : numFrames === 1 ? [duration / 2] : Array.from({ length: numFrames }, (_2, i2) => i2 / (numFrames - 1) * duration);
|
|
40710
|
-
const snapshotDir =
|
|
41288
|
+
const snapshotDir = join50(projectDir, "snapshots");
|
|
40711
41289
|
mkdirSync25(snapshotDir, { recursive: true });
|
|
40712
41290
|
let injectVideoFramesBatch2 = null;
|
|
40713
41291
|
let syncVideoFrameVisibility2 = null;
|
|
@@ -40780,9 +41358,9 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
40780
41358
|
try {
|
|
40781
41359
|
const url = new URL(v.src);
|
|
40782
41360
|
const decodedPath = decodeURIComponent(url.pathname).replace(/^\//, "");
|
|
40783
|
-
const candidate =
|
|
40784
|
-
const rel =
|
|
40785
|
-
if (!rel.startsWith("..") && !
|
|
41361
|
+
const candidate = resolve36(projectDir, decodedPath);
|
|
41362
|
+
const rel = relative6(projectDir, candidate);
|
|
41363
|
+
if (!rel.startsWith("..") && !isAbsolute7(rel) && existsSync50(candidate)) {
|
|
40786
41364
|
filePath = candidate;
|
|
40787
41365
|
}
|
|
40788
41366
|
} catch {
|
|
@@ -40812,7 +41390,7 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
40812
41390
|
}
|
|
40813
41391
|
const timeLabel = opts.at?.length ? `${time.toFixed(1)}s` : `${Math.round(time / duration * 100)}pct`;
|
|
40814
41392
|
const filename = `frame-${String(i2).padStart(2, "0")}-at-${timeLabel}.png`;
|
|
40815
|
-
const framePath =
|
|
41393
|
+
const framePath = join50(snapshotDir, filename);
|
|
40816
41394
|
await page.screenshot({ path: framePath, type: "png" });
|
|
40817
41395
|
savedPaths.push(`snapshots/${filename}`);
|
|
40818
41396
|
}
|
|
@@ -40824,17 +41402,17 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
40824
41402
|
}
|
|
40825
41403
|
return savedPaths;
|
|
40826
41404
|
}
|
|
40827
|
-
var
|
|
41405
|
+
var __filename3, __dirname4, FFMPEG_EXTRACT_TIMEOUT_MS, examples21, snapshot_default;
|
|
40828
41406
|
var init_snapshot = __esm({
|
|
40829
41407
|
"src/commands/snapshot.ts"() {
|
|
40830
41408
|
"use strict";
|
|
40831
41409
|
init_dist();
|
|
40832
41410
|
init_project();
|
|
40833
41411
|
init_colors();
|
|
40834
|
-
|
|
40835
|
-
|
|
41412
|
+
__filename3 = fileURLToPath9(import.meta.url);
|
|
41413
|
+
__dirname4 = dirname22(__filename3);
|
|
40836
41414
|
FFMPEG_EXTRACT_TIMEOUT_MS = 3e4;
|
|
40837
|
-
|
|
41415
|
+
examples21 = [
|
|
40838
41416
|
["Capture 5 key frames from a composition", "snapshot captures/stripe"],
|
|
40839
41417
|
["Capture 10 evenly-spaced frames", "snapshot captures/stripe --frames 10"]
|
|
40840
41418
|
];
|
|
@@ -40898,13 +41476,13 @@ ${c.error("\u2717")} Snapshot failed: ${msg}`);
|
|
|
40898
41476
|
|
|
40899
41477
|
// src/capture/assetDownloader.ts
|
|
40900
41478
|
import { writeFileSync as writeFileSync19, mkdirSync as mkdirSync26 } from "fs";
|
|
40901
|
-
import { join as
|
|
41479
|
+
import { join as join51, extname as extname10 } from "path";
|
|
40902
41480
|
async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks) {
|
|
40903
|
-
const assetsDir =
|
|
41481
|
+
const assetsDir = join51(outputDir, "assets");
|
|
40904
41482
|
mkdirSync26(assetsDir, { recursive: true });
|
|
40905
41483
|
const assets = [];
|
|
40906
41484
|
const downloadedUrls = /* @__PURE__ */ new Set();
|
|
40907
|
-
mkdirSync26(
|
|
41485
|
+
mkdirSync26(join51(outputDir, "assets", "svgs"), { recursive: true });
|
|
40908
41486
|
for (let i2 = 0; i2 < tokens.svgs.length && i2 < 30; i2++) {
|
|
40909
41487
|
const svg = tokens.svgs[i2];
|
|
40910
41488
|
if (!svg.outerHTML || svg.outerHTML.length < 50) continue;
|
|
@@ -40912,7 +41490,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
|
|
|
40912
41490
|
const name = label2 ? slugify(label2) + ".svg" : svg.isLogo ? `logo-${i2}.svg` : `icon-${i2}.svg`;
|
|
40913
41491
|
const localPath = `assets/svgs/${name}`;
|
|
40914
41492
|
try {
|
|
40915
|
-
writeFileSync19(
|
|
41493
|
+
writeFileSync19(join51(outputDir, localPath), svg.outerHTML, "utf-8");
|
|
40916
41494
|
assets.push({ url: "", localPath, type: "svg" });
|
|
40917
41495
|
} catch {
|
|
40918
41496
|
}
|
|
@@ -40925,7 +41503,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
|
|
|
40925
41503
|
const localPath = `assets/${name}`;
|
|
40926
41504
|
const buffer = await fetchBuffer(icon.href);
|
|
40927
41505
|
if (buffer) {
|
|
40928
|
-
writeFileSync19(
|
|
41506
|
+
writeFileSync19(join51(outputDir, localPath), buffer);
|
|
40929
41507
|
assets.push({ url: icon.href, localPath, type: "favicon" });
|
|
40930
41508
|
break;
|
|
40931
41509
|
}
|
|
@@ -40982,7 +41560,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
|
|
|
40982
41560
|
const slug = isMeaningful ? slugify(rawName) : `${prefix}-${imgIdx}`;
|
|
40983
41561
|
const name = `${slug}${ext}`;
|
|
40984
41562
|
const localPath = `assets/${name}`;
|
|
40985
|
-
writeFileSync19(
|
|
41563
|
+
writeFileSync19(join51(outputDir, localPath), buffer);
|
|
40986
41564
|
assets.push({ url, localPath, type: "image" });
|
|
40987
41565
|
imgIdx++;
|
|
40988
41566
|
} catch {
|
|
@@ -40995,7 +41573,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
|
|
|
40995
41573
|
const localPath = `assets/og-image${ext}`;
|
|
40996
41574
|
const buffer = await fetchBuffer(tokens.ogImage);
|
|
40997
41575
|
if (buffer && buffer.length > 5e3) {
|
|
40998
|
-
writeFileSync19(
|
|
41576
|
+
writeFileSync19(join51(outputDir, localPath), buffer);
|
|
40999
41577
|
assets.push({ url: tokens.ogImage, localPath, type: "image" });
|
|
41000
41578
|
}
|
|
41001
41579
|
} catch {
|
|
@@ -41018,7 +41596,7 @@ function normalizeUrl(u) {
|
|
|
41018
41596
|
}
|
|
41019
41597
|
}
|
|
41020
41598
|
async function downloadAndRewriteFonts(css, outputDir) {
|
|
41021
|
-
const assetsDir =
|
|
41599
|
+
const assetsDir = join51(outputDir, "assets", "fonts");
|
|
41022
41600
|
mkdirSync26(assetsDir, { recursive: true });
|
|
41023
41601
|
const fontUrlRegex = /url\(['"]?(https?:\/\/[^'")\s]+\.(?:woff2?|ttf|otf)[^'")\s]*?)['"]?\)/g;
|
|
41024
41602
|
const fontUrls = /* @__PURE__ */ new Set();
|
|
@@ -41054,7 +41632,7 @@ async function downloadAndRewriteFonts(css, outputDir) {
|
|
|
41054
41632
|
try {
|
|
41055
41633
|
const urlObj = new URL(fontUrl);
|
|
41056
41634
|
const filename = urlObj.pathname.split("/").pop() || `font-${count}.woff2`;
|
|
41057
|
-
const localPath =
|
|
41635
|
+
const localPath = join51(assetsDir, filename);
|
|
41058
41636
|
const relativePath = `assets/fonts/${filename}`;
|
|
41059
41637
|
const buffer = await fetchBuffer(fontUrl);
|
|
41060
41638
|
if (buffer) {
|
|
@@ -41851,8 +42429,8 @@ var init_animationCataloger = __esm({
|
|
|
41851
42429
|
});
|
|
41852
42430
|
|
|
41853
42431
|
// src/capture/mediaCapture.ts
|
|
41854
|
-
import { mkdirSync as mkdirSync27, writeFileSync as writeFileSync20, readdirSync as readdirSync18, readFileSync as
|
|
41855
|
-
import { join as
|
|
42432
|
+
import { mkdirSync as mkdirSync27, writeFileSync as writeFileSync20, readdirSync as readdirSync18, readFileSync as readFileSync36, statSync as statSync18 } from "fs";
|
|
42433
|
+
import { join as join52 } from "path";
|
|
41856
42434
|
async function saveLottieAnimations(discoveredLotties, lottieDir) {
|
|
41857
42435
|
let savedCount = 0;
|
|
41858
42436
|
const savedHashes = /* @__PURE__ */ new Set();
|
|
@@ -41885,7 +42463,7 @@ async function saveLottieAnimations(discoveredLotties, lottieDir) {
|
|
|
41885
42463
|
const hash2 = buf.toString("base64").slice(0, 100);
|
|
41886
42464
|
if (savedHashes.has(hash2)) continue;
|
|
41887
42465
|
savedHashes.add(hash2);
|
|
41888
|
-
writeFileSync20(
|
|
42466
|
+
writeFileSync20(join52(lottieDir, `animation-${savedCount}.lottie`), buf);
|
|
41889
42467
|
savedCount++;
|
|
41890
42468
|
continue;
|
|
41891
42469
|
}
|
|
@@ -41903,7 +42481,7 @@ async function saveLottieAnimations(discoveredLotties, lottieDir) {
|
|
|
41903
42481
|
} catch {
|
|
41904
42482
|
continue;
|
|
41905
42483
|
}
|
|
41906
|
-
writeFileSync20(
|
|
42484
|
+
writeFileSync20(join52(lottieDir, `animation-${savedCount}.json`), jsonData, "utf-8");
|
|
41907
42485
|
savedCount++;
|
|
41908
42486
|
}
|
|
41909
42487
|
} catch {
|
|
@@ -41913,22 +42491,22 @@ async function saveLottieAnimations(discoveredLotties, lottieDir) {
|
|
|
41913
42491
|
}
|
|
41914
42492
|
async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir) {
|
|
41915
42493
|
const manifest = [];
|
|
41916
|
-
const previewDir =
|
|
42494
|
+
const previewDir = join52(lottieDir, "previews");
|
|
41917
42495
|
mkdirSync27(previewDir, { recursive: true });
|
|
41918
42496
|
for (const file of readdirSync18(lottieDir)) {
|
|
41919
42497
|
if (!file.endsWith(".json")) continue;
|
|
41920
42498
|
try {
|
|
41921
|
-
const raw = JSON.parse(
|
|
42499
|
+
const raw = JSON.parse(readFileSync36(join52(lottieDir, file), "utf-8"));
|
|
41922
42500
|
const fr = raw.fr || 30;
|
|
41923
42501
|
const dur = ((raw.op || 0) - (raw.ip || 0)) / fr;
|
|
41924
42502
|
const previewName = file.replace(".json", "-preview.png");
|
|
41925
|
-
const fileSize = statSync18(
|
|
42503
|
+
const fileSize = statSync18(join52(lottieDir, file)).size;
|
|
41926
42504
|
if (fileSize > 2e6) continue;
|
|
41927
42505
|
let previewPage;
|
|
41928
42506
|
try {
|
|
41929
42507
|
previewPage = await chromeBrowser.newPage();
|
|
41930
42508
|
await previewPage.setViewport({ width: 400, height: 400 });
|
|
41931
|
-
const animData = JSON.parse(
|
|
42509
|
+
const animData = JSON.parse(readFileSync36(join52(lottieDir, file), "utf-8"));
|
|
41932
42510
|
const midFrame = Math.floor(((raw.op || 0) - (raw.ip || 0)) * 0.3);
|
|
41933
42511
|
await previewPage.setContent(
|
|
41934
42512
|
`<!DOCTYPE html>
|
|
@@ -41958,7 +42536,7 @@ async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir) {
|
|
|
41958
42536
|
await previewPage.waitForFunction(() => window.__READY === true, { timeout: 5e3 }).catch(() => {
|
|
41959
42537
|
});
|
|
41960
42538
|
await previewPage.screenshot({
|
|
41961
|
-
path:
|
|
42539
|
+
path: join52(previewDir, previewName),
|
|
41962
42540
|
type: "png",
|
|
41963
42541
|
omitBackground: true
|
|
41964
42542
|
});
|
|
@@ -41982,7 +42560,7 @@ async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir) {
|
|
|
41982
42560
|
}
|
|
41983
42561
|
if (manifest.length > 0) {
|
|
41984
42562
|
writeFileSync20(
|
|
41985
|
-
|
|
42563
|
+
join52(outputDir, "extracted", "lottie-manifest.json"),
|
|
41986
42564
|
JSON.stringify(manifest, null, 2),
|
|
41987
42565
|
"utf-8"
|
|
41988
42566
|
);
|
|
@@ -42044,15 +42622,15 @@ async function captureVideoManifest(page, outputDir, progress) {
|
|
|
42044
42622
|
return true;
|
|
42045
42623
|
});
|
|
42046
42624
|
if (uniqueVideos.length > 0) {
|
|
42047
|
-
const videoManifestDir =
|
|
42625
|
+
const videoManifestDir = join52(outputDir, "assets", "videos");
|
|
42048
42626
|
mkdirSync27(videoManifestDir, { recursive: true });
|
|
42049
|
-
const previewDir =
|
|
42627
|
+
const previewDir = join52(videoManifestDir, "previews");
|
|
42050
42628
|
mkdirSync27(previewDir, { recursive: true });
|
|
42051
42629
|
const videoManifest = [];
|
|
42052
42630
|
for (let vi = 0; vi < uniqueVideos.length && vi < 20; vi++) {
|
|
42053
42631
|
const v = uniqueVideos[vi];
|
|
42054
42632
|
const previewName = `video-${vi}-preview.png`;
|
|
42055
|
-
const previewPath =
|
|
42633
|
+
const previewPath = join52(previewDir, previewName);
|
|
42056
42634
|
try {
|
|
42057
42635
|
await page.evaluate(`window.scrollTo(0, ${Math.max(0, v.top - 100)})`);
|
|
42058
42636
|
await new Promise((r2) => setTimeout(r2, 300));
|
|
@@ -42091,7 +42669,7 @@ async function captureVideoManifest(page, outputDir, progress) {
|
|
|
42091
42669
|
}
|
|
42092
42670
|
if (videoManifest.length > 0) {
|
|
42093
42671
|
writeFileSync20(
|
|
42094
|
-
|
|
42672
|
+
join52(outputDir, "extracted", "video-manifest.json"),
|
|
42095
42673
|
JSON.stringify(videoManifest, null, 2),
|
|
42096
42674
|
"utf-8"
|
|
42097
42675
|
);
|
|
@@ -42373,7 +42951,7 @@ var require_p_retry = __commonJS({
|
|
|
42373
42951
|
return error;
|
|
42374
42952
|
};
|
|
42375
42953
|
var isNetworkError = (errorMessage) => networkErrorMsgs.includes(errorMessage);
|
|
42376
|
-
var pRetry2 = (input, options) => new Promise((
|
|
42954
|
+
var pRetry2 = (input, options) => new Promise((resolve39, reject) => {
|
|
42377
42955
|
options = {
|
|
42378
42956
|
onFailedAttempt: () => {
|
|
42379
42957
|
},
|
|
@@ -42383,7 +42961,7 @@ var require_p_retry = __commonJS({
|
|
|
42383
42961
|
const operation = retry.operation(options);
|
|
42384
42962
|
operation.attempt(async (attemptNumber) => {
|
|
42385
42963
|
try {
|
|
42386
|
-
|
|
42964
|
+
resolve39(await input(attemptNumber));
|
|
42387
42965
|
} catch (error) {
|
|
42388
42966
|
if (!(error instanceof Error)) {
|
|
42389
42967
|
reject(new TypeError(`Non-error was thrown: "${error}". You should only throw errors.`));
|
|
@@ -42919,8 +43497,8 @@ var require_retry3 = __commonJS({
|
|
|
42919
43497
|
}
|
|
42920
43498
|
const delay = getNextRetryDelay(config);
|
|
42921
43499
|
err.config.retryConfig.currentRetryAttempt += 1;
|
|
42922
|
-
const backoff = config.retryBackoff ? config.retryBackoff(err, delay) : new Promise((
|
|
42923
|
-
setTimeout(
|
|
43500
|
+
const backoff = config.retryBackoff ? config.retryBackoff(err, delay) : new Promise((resolve39) => {
|
|
43501
|
+
setTimeout(resolve39, delay);
|
|
42924
43502
|
});
|
|
42925
43503
|
if (config.onRetryAttempt) {
|
|
42926
43504
|
await config.onRetryAttempt(err);
|
|
@@ -43828,8 +44406,8 @@ var require_helpers = __commonJS({
|
|
|
43828
44406
|
function req(url, opts = {}) {
|
|
43829
44407
|
const href = typeof url === "string" ? url : url.href;
|
|
43830
44408
|
const req2 = (href.startsWith("https:") ? https2 : http4).request(url, opts);
|
|
43831
|
-
const promise = new Promise((
|
|
43832
|
-
req2.once("response",
|
|
44409
|
+
const promise = new Promise((resolve39, reject) => {
|
|
44410
|
+
req2.once("response", resolve39).once("error", reject).end();
|
|
43833
44411
|
});
|
|
43834
44412
|
req2.then = promise.then.bind(promise);
|
|
43835
44413
|
return req2;
|
|
@@ -44006,7 +44584,7 @@ var require_parse_proxy_response = __commonJS({
|
|
|
44006
44584
|
var debug_1 = __importDefault(require_src2());
|
|
44007
44585
|
var debug = (0, debug_1.default)("https-proxy-agent:parse-proxy-response");
|
|
44008
44586
|
function parseProxyResponse(socket) {
|
|
44009
|
-
return new Promise((
|
|
44587
|
+
return new Promise((resolve39, reject) => {
|
|
44010
44588
|
let buffersLength = 0;
|
|
44011
44589
|
const buffers = [];
|
|
44012
44590
|
function read() {
|
|
@@ -44072,7 +44650,7 @@ var require_parse_proxy_response = __commonJS({
|
|
|
44072
44650
|
}
|
|
44073
44651
|
debug("got proxy server response: %o %o", firstLine, headers);
|
|
44074
44652
|
cleanup();
|
|
44075
|
-
|
|
44653
|
+
resolve39({
|
|
44076
44654
|
connect: {
|
|
44077
44655
|
statusCode,
|
|
44078
44656
|
statusText,
|
|
@@ -44316,7 +44894,7 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
44316
44894
|
return new originalPromise(executor);
|
|
44317
44895
|
}
|
|
44318
44896
|
function promiseResolvedWith(value) {
|
|
44319
|
-
return newPromise((
|
|
44897
|
+
return newPromise((resolve39) => resolve39(value));
|
|
44320
44898
|
}
|
|
44321
44899
|
function promiseRejectedWith(reason) {
|
|
44322
44900
|
return originalPromiseReject(reason);
|
|
@@ -44486,8 +45064,8 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
44486
45064
|
return new TypeError("Cannot " + name + " a stream using a released reader");
|
|
44487
45065
|
}
|
|
44488
45066
|
function defaultReaderClosedPromiseInitialize(reader) {
|
|
44489
|
-
reader._closedPromise = newPromise((
|
|
44490
|
-
reader._closedPromise_resolve =
|
|
45067
|
+
reader._closedPromise = newPromise((resolve39, reject) => {
|
|
45068
|
+
reader._closedPromise_resolve = resolve39;
|
|
44491
45069
|
reader._closedPromise_reject = reject;
|
|
44492
45070
|
});
|
|
44493
45071
|
}
|
|
@@ -44661,8 +45239,8 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
44661
45239
|
}
|
|
44662
45240
|
let resolvePromise;
|
|
44663
45241
|
let rejectPromise;
|
|
44664
|
-
const promise = newPromise((
|
|
44665
|
-
resolvePromise =
|
|
45242
|
+
const promise = newPromise((resolve39, reject) => {
|
|
45243
|
+
resolvePromise = resolve39;
|
|
44666
45244
|
rejectPromise = reject;
|
|
44667
45245
|
});
|
|
44668
45246
|
const readRequest = {
|
|
@@ -44767,8 +45345,8 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
44767
45345
|
const reader = this._reader;
|
|
44768
45346
|
let resolvePromise;
|
|
44769
45347
|
let rejectPromise;
|
|
44770
|
-
const promise = newPromise((
|
|
44771
|
-
resolvePromise =
|
|
45348
|
+
const promise = newPromise((resolve39, reject) => {
|
|
45349
|
+
resolvePromise = resolve39;
|
|
44772
45350
|
rejectPromise = reject;
|
|
44773
45351
|
});
|
|
44774
45352
|
const readRequest = {
|
|
@@ -45787,8 +46365,8 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
45787
46365
|
}
|
|
45788
46366
|
let resolvePromise;
|
|
45789
46367
|
let rejectPromise;
|
|
45790
|
-
const promise = newPromise((
|
|
45791
|
-
resolvePromise =
|
|
46368
|
+
const promise = newPromise((resolve39, reject) => {
|
|
46369
|
+
resolvePromise = resolve39;
|
|
45792
46370
|
rejectPromise = reject;
|
|
45793
46371
|
});
|
|
45794
46372
|
const readIntoRequest = {
|
|
@@ -46100,10 +46678,10 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
46100
46678
|
wasAlreadyErroring = true;
|
|
46101
46679
|
reason = void 0;
|
|
46102
46680
|
}
|
|
46103
|
-
const promise = newPromise((
|
|
46681
|
+
const promise = newPromise((resolve39, reject) => {
|
|
46104
46682
|
stream._pendingAbortRequest = {
|
|
46105
46683
|
_promise: void 0,
|
|
46106
|
-
_resolve:
|
|
46684
|
+
_resolve: resolve39,
|
|
46107
46685
|
_reject: reject,
|
|
46108
46686
|
_reason: reason,
|
|
46109
46687
|
_wasAlreadyErroring: wasAlreadyErroring
|
|
@@ -46120,9 +46698,9 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
46120
46698
|
if (state === "closed" || state === "errored") {
|
|
46121
46699
|
return promiseRejectedWith(new TypeError(`The stream (in ${state} state) is not in the writable state and cannot be closed`));
|
|
46122
46700
|
}
|
|
46123
|
-
const promise = newPromise((
|
|
46701
|
+
const promise = newPromise((resolve39, reject) => {
|
|
46124
46702
|
const closeRequest = {
|
|
46125
|
-
_resolve:
|
|
46703
|
+
_resolve: resolve39,
|
|
46126
46704
|
_reject: reject
|
|
46127
46705
|
};
|
|
46128
46706
|
stream._closeRequest = closeRequest;
|
|
@@ -46135,9 +46713,9 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
46135
46713
|
return promise;
|
|
46136
46714
|
}
|
|
46137
46715
|
function WritableStreamAddWriteRequest(stream) {
|
|
46138
|
-
const promise = newPromise((
|
|
46716
|
+
const promise = newPromise((resolve39, reject) => {
|
|
46139
46717
|
const writeRequest = {
|
|
46140
|
-
_resolve:
|
|
46718
|
+
_resolve: resolve39,
|
|
46141
46719
|
_reject: reject
|
|
46142
46720
|
};
|
|
46143
46721
|
stream._writeRequests.push(writeRequest);
|
|
@@ -46753,8 +47331,8 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
46753
47331
|
return new TypeError("Cannot " + name + " a stream using a released writer");
|
|
46754
47332
|
}
|
|
46755
47333
|
function defaultWriterClosedPromiseInitialize(writer) {
|
|
46756
|
-
writer._closedPromise = newPromise((
|
|
46757
|
-
writer._closedPromise_resolve =
|
|
47334
|
+
writer._closedPromise = newPromise((resolve39, reject) => {
|
|
47335
|
+
writer._closedPromise_resolve = resolve39;
|
|
46758
47336
|
writer._closedPromise_reject = reject;
|
|
46759
47337
|
writer._closedPromiseState = "pending";
|
|
46760
47338
|
});
|
|
@@ -46790,8 +47368,8 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
46790
47368
|
writer._closedPromiseState = "resolved";
|
|
46791
47369
|
}
|
|
46792
47370
|
function defaultWriterReadyPromiseInitialize(writer) {
|
|
46793
|
-
writer._readyPromise = newPromise((
|
|
46794
|
-
writer._readyPromise_resolve =
|
|
47371
|
+
writer._readyPromise = newPromise((resolve39, reject) => {
|
|
47372
|
+
writer._readyPromise_resolve = resolve39;
|
|
46795
47373
|
writer._readyPromise_reject = reject;
|
|
46796
47374
|
});
|
|
46797
47375
|
writer._readyPromiseState = "pending";
|
|
@@ -46878,7 +47456,7 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
46878
47456
|
source._disturbed = true;
|
|
46879
47457
|
let shuttingDown = false;
|
|
46880
47458
|
let currentWrite = promiseResolvedWith(void 0);
|
|
46881
|
-
return newPromise((
|
|
47459
|
+
return newPromise((resolve39, reject) => {
|
|
46882
47460
|
let abortAlgorithm;
|
|
46883
47461
|
if (signal !== void 0) {
|
|
46884
47462
|
abortAlgorithm = () => {
|
|
@@ -47023,7 +47601,7 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
47023
47601
|
if (isError) {
|
|
47024
47602
|
reject(error);
|
|
47025
47603
|
} else {
|
|
47026
|
-
|
|
47604
|
+
resolve39(void 0);
|
|
47027
47605
|
}
|
|
47028
47606
|
return null;
|
|
47029
47607
|
}
|
|
@@ -47304,8 +47882,8 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
47304
47882
|
let branch1;
|
|
47305
47883
|
let branch2;
|
|
47306
47884
|
let resolveCancelPromise;
|
|
47307
|
-
const cancelPromise = newPromise((
|
|
47308
|
-
resolveCancelPromise =
|
|
47885
|
+
const cancelPromise = newPromise((resolve39) => {
|
|
47886
|
+
resolveCancelPromise = resolve39;
|
|
47309
47887
|
});
|
|
47310
47888
|
function pullAlgorithm() {
|
|
47311
47889
|
if (reading) {
|
|
@@ -47396,8 +47974,8 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
47396
47974
|
let branch1;
|
|
47397
47975
|
let branch2;
|
|
47398
47976
|
let resolveCancelPromise;
|
|
47399
|
-
const cancelPromise = newPromise((
|
|
47400
|
-
resolveCancelPromise =
|
|
47977
|
+
const cancelPromise = newPromise((resolve39) => {
|
|
47978
|
+
resolveCancelPromise = resolve39;
|
|
47401
47979
|
});
|
|
47402
47980
|
function forwardReaderError(thisReader) {
|
|
47403
47981
|
uponRejection(thisReader._closedPromise, (r2) => {
|
|
@@ -48177,8 +48755,8 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
48177
48755
|
const writableHighWaterMark = ExtractHighWaterMark(writableStrategy, 1);
|
|
48178
48756
|
const writableSizeAlgorithm = ExtractSizeAlgorithm(writableStrategy);
|
|
48179
48757
|
let startPromise_resolve;
|
|
48180
|
-
const startPromise = newPromise((
|
|
48181
|
-
startPromise_resolve =
|
|
48758
|
+
const startPromise = newPromise((resolve39) => {
|
|
48759
|
+
startPromise_resolve = resolve39;
|
|
48182
48760
|
});
|
|
48183
48761
|
InitializeTransformStream(this, startPromise, writableHighWaterMark, writableSizeAlgorithm, readableHighWaterMark, readableSizeAlgorithm);
|
|
48184
48762
|
SetUpTransformStreamDefaultControllerFromTransformer(this, transformer);
|
|
@@ -48271,8 +48849,8 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
48271
48849
|
if (stream._backpressureChangePromise !== void 0) {
|
|
48272
48850
|
stream._backpressureChangePromise_resolve();
|
|
48273
48851
|
}
|
|
48274
|
-
stream._backpressureChangePromise = newPromise((
|
|
48275
|
-
stream._backpressureChangePromise_resolve =
|
|
48852
|
+
stream._backpressureChangePromise = newPromise((resolve39) => {
|
|
48853
|
+
stream._backpressureChangePromise_resolve = resolve39;
|
|
48276
48854
|
});
|
|
48277
48855
|
stream._backpressure = backpressure;
|
|
48278
48856
|
}
|
|
@@ -48440,8 +49018,8 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
48440
49018
|
return controller._finishPromise;
|
|
48441
49019
|
}
|
|
48442
49020
|
const readable = stream._readable;
|
|
48443
|
-
controller._finishPromise = newPromise((
|
|
48444
|
-
controller._finishPromise_resolve =
|
|
49021
|
+
controller._finishPromise = newPromise((resolve39, reject) => {
|
|
49022
|
+
controller._finishPromise_resolve = resolve39;
|
|
48445
49023
|
controller._finishPromise_reject = reject;
|
|
48446
49024
|
});
|
|
48447
49025
|
const cancelPromise = controller._cancelAlgorithm(reason);
|
|
@@ -48467,8 +49045,8 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
48467
49045
|
return controller._finishPromise;
|
|
48468
49046
|
}
|
|
48469
49047
|
const readable = stream._readable;
|
|
48470
|
-
controller._finishPromise = newPromise((
|
|
48471
|
-
controller._finishPromise_resolve =
|
|
49048
|
+
controller._finishPromise = newPromise((resolve39, reject) => {
|
|
49049
|
+
controller._finishPromise_resolve = resolve39;
|
|
48472
49050
|
controller._finishPromise_reject = reject;
|
|
48473
49051
|
});
|
|
48474
49052
|
const flushPromise = controller._flushAlgorithm();
|
|
@@ -48498,8 +49076,8 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
48498
49076
|
return controller._finishPromise;
|
|
48499
49077
|
}
|
|
48500
49078
|
const writable = stream._writable;
|
|
48501
|
-
controller._finishPromise = newPromise((
|
|
48502
|
-
controller._finishPromise_resolve =
|
|
49079
|
+
controller._finishPromise = newPromise((resolve39, reject) => {
|
|
49080
|
+
controller._finishPromise_resolve = resolve39;
|
|
48503
49081
|
controller._finishPromise_reject = reject;
|
|
48504
49082
|
});
|
|
48505
49083
|
const cancelPromise = controller._cancelAlgorithm(reason);
|
|
@@ -50468,7 +51046,7 @@ import zlib from "zlib";
|
|
|
50468
51046
|
import Stream2, { PassThrough as PassThrough2, pipeline as pump } from "stream";
|
|
50469
51047
|
import { Buffer as Buffer3 } from "buffer";
|
|
50470
51048
|
async function fetch3(url, options_) {
|
|
50471
|
-
return new Promise((
|
|
51049
|
+
return new Promise((resolve39, reject) => {
|
|
50472
51050
|
const request = new Request2(url, options_);
|
|
50473
51051
|
const { parsedURL, options } = getNodeRequestOptions(request);
|
|
50474
51052
|
if (!supportedSchemas.has(parsedURL.protocol)) {
|
|
@@ -50477,7 +51055,7 @@ async function fetch3(url, options_) {
|
|
|
50477
51055
|
if (parsedURL.protocol === "data:") {
|
|
50478
51056
|
const data = dist_default(request.url);
|
|
50479
51057
|
const response2 = new Response2(data, { headers: { "Content-Type": data.typeFull } });
|
|
50480
|
-
|
|
51058
|
+
resolve39(response2);
|
|
50481
51059
|
return;
|
|
50482
51060
|
}
|
|
50483
51061
|
const send = (parsedURL.protocol === "https:" ? https : http3).request;
|
|
@@ -50599,7 +51177,7 @@ async function fetch3(url, options_) {
|
|
|
50599
51177
|
if (responseReferrerPolicy) {
|
|
50600
51178
|
requestOptions.referrerPolicy = responseReferrerPolicy;
|
|
50601
51179
|
}
|
|
50602
|
-
|
|
51180
|
+
resolve39(fetch3(new Request2(locationURL, requestOptions)));
|
|
50603
51181
|
finalize();
|
|
50604
51182
|
return;
|
|
50605
51183
|
}
|
|
@@ -50632,7 +51210,7 @@ async function fetch3(url, options_) {
|
|
|
50632
51210
|
const codings = headers.get("Content-Encoding");
|
|
50633
51211
|
if (!request.compress || request.method === "HEAD" || codings === null || response_.statusCode === 204 || response_.statusCode === 304) {
|
|
50634
51212
|
response = new Response2(body, responseOptions);
|
|
50635
|
-
|
|
51213
|
+
resolve39(response);
|
|
50636
51214
|
return;
|
|
50637
51215
|
}
|
|
50638
51216
|
const zlibOptions = {
|
|
@@ -50646,7 +51224,7 @@ async function fetch3(url, options_) {
|
|
|
50646
51224
|
}
|
|
50647
51225
|
});
|
|
50648
51226
|
response = new Response2(body, responseOptions);
|
|
50649
|
-
|
|
51227
|
+
resolve39(response);
|
|
50650
51228
|
return;
|
|
50651
51229
|
}
|
|
50652
51230
|
if (codings === "deflate" || codings === "x-deflate") {
|
|
@@ -50670,12 +51248,12 @@ async function fetch3(url, options_) {
|
|
|
50670
51248
|
});
|
|
50671
51249
|
}
|
|
50672
51250
|
response = new Response2(body, responseOptions);
|
|
50673
|
-
|
|
51251
|
+
resolve39(response);
|
|
50674
51252
|
});
|
|
50675
51253
|
raw.once("end", () => {
|
|
50676
51254
|
if (!response) {
|
|
50677
51255
|
response = new Response2(body, responseOptions);
|
|
50678
|
-
|
|
51256
|
+
resolve39(response);
|
|
50679
51257
|
}
|
|
50680
51258
|
});
|
|
50681
51259
|
return;
|
|
@@ -50687,11 +51265,11 @@ async function fetch3(url, options_) {
|
|
|
50687
51265
|
}
|
|
50688
51266
|
});
|
|
50689
51267
|
response = new Response2(body, responseOptions);
|
|
50690
|
-
|
|
51268
|
+
resolve39(response);
|
|
50691
51269
|
return;
|
|
50692
51270
|
}
|
|
50693
51271
|
response = new Response2(body, responseOptions);
|
|
50694
|
-
|
|
51272
|
+
resolve39(response);
|
|
50695
51273
|
});
|
|
50696
51274
|
writeToStream(request_, request).catch(reject);
|
|
50697
51275
|
});
|
|
@@ -56773,7 +57351,7 @@ var require_jwtaccess = __commonJS({
|
|
|
56773
57351
|
}
|
|
56774
57352
|
}
|
|
56775
57353
|
fromStreamAsync(inputStream) {
|
|
56776
|
-
return new Promise((
|
|
57354
|
+
return new Promise((resolve39, reject) => {
|
|
56777
57355
|
if (!inputStream) {
|
|
56778
57356
|
reject(new Error("Must pass in a stream containing the service account auth settings."));
|
|
56779
57357
|
}
|
|
@@ -56782,7 +57360,7 @@ var require_jwtaccess = __commonJS({
|
|
|
56782
57360
|
try {
|
|
56783
57361
|
const data = JSON.parse(s2);
|
|
56784
57362
|
this.fromJSON(data);
|
|
56785
|
-
|
|
57363
|
+
resolve39();
|
|
56786
57364
|
} catch (err) {
|
|
56787
57365
|
reject(err);
|
|
56788
57366
|
}
|
|
@@ -57021,7 +57599,7 @@ var require_jwtclient = __commonJS({
|
|
|
57021
57599
|
}
|
|
57022
57600
|
}
|
|
57023
57601
|
fromStreamAsync(inputStream) {
|
|
57024
|
-
return new Promise((
|
|
57602
|
+
return new Promise((resolve39, reject) => {
|
|
57025
57603
|
if (!inputStream) {
|
|
57026
57604
|
throw new Error("Must pass in a stream containing the service account auth settings.");
|
|
57027
57605
|
}
|
|
@@ -57030,7 +57608,7 @@ var require_jwtclient = __commonJS({
|
|
|
57030
57608
|
try {
|
|
57031
57609
|
const data = JSON.parse(s2);
|
|
57032
57610
|
this.fromJSON(data);
|
|
57033
|
-
|
|
57611
|
+
resolve39();
|
|
57034
57612
|
} catch (e2) {
|
|
57035
57613
|
reject(e2);
|
|
57036
57614
|
}
|
|
@@ -57163,7 +57741,7 @@ var require_refreshclient = __commonJS({
|
|
|
57163
57741
|
}
|
|
57164
57742
|
}
|
|
57165
57743
|
async fromStreamAsync(inputStream) {
|
|
57166
|
-
return new Promise((
|
|
57744
|
+
return new Promise((resolve39, reject) => {
|
|
57167
57745
|
if (!inputStream) {
|
|
57168
57746
|
return reject(new Error("Must pass in a stream containing the user refresh token."));
|
|
57169
57747
|
}
|
|
@@ -57172,7 +57750,7 @@ var require_refreshclient = __commonJS({
|
|
|
57172
57750
|
try {
|
|
57173
57751
|
const data = JSON.parse(s2);
|
|
57174
57752
|
this.fromJSON(data);
|
|
57175
|
-
return
|
|
57753
|
+
return resolve39();
|
|
57176
57754
|
} catch (err) {
|
|
57177
57755
|
return reject(err);
|
|
57178
57756
|
}
|
|
@@ -59005,7 +59583,7 @@ var require_pluggable_auth_handler = __commonJS({
|
|
|
59005
59583
|
* @return A promise that resolves with the executable response.
|
|
59006
59584
|
*/
|
|
59007
59585
|
retrieveResponseFromExecutable(envMap) {
|
|
59008
|
-
return new Promise((
|
|
59586
|
+
return new Promise((resolve39, reject) => {
|
|
59009
59587
|
const child = childProcess.spawn(this.commandComponents[0], this.commandComponents.slice(1), {
|
|
59010
59588
|
env: { ...process.env, ...Object.fromEntries(envMap) }
|
|
59011
59589
|
});
|
|
@@ -59027,7 +59605,7 @@ var require_pluggable_auth_handler = __commonJS({
|
|
|
59027
59605
|
try {
|
|
59028
59606
|
const responseJson = JSON.parse(output);
|
|
59029
59607
|
const response = new executable_response_1.ExecutableResponse(responseJson);
|
|
59030
|
-
return
|
|
59608
|
+
return resolve39(response);
|
|
59031
59609
|
} catch (error) {
|
|
59032
59610
|
if (error instanceof executable_response_1.ExecutableResponseError) {
|
|
59033
59611
|
return reject(error);
|
|
@@ -59930,7 +60508,7 @@ var require_googleauth = __commonJS({
|
|
|
59930
60508
|
}
|
|
59931
60509
|
}
|
|
59932
60510
|
fromStreamAsync(inputStream, options) {
|
|
59933
|
-
return new Promise((
|
|
60511
|
+
return new Promise((resolve39, reject) => {
|
|
59934
60512
|
if (!inputStream) {
|
|
59935
60513
|
throw new Error("Must pass in a stream containing the Google auth settings.");
|
|
59936
60514
|
}
|
|
@@ -59940,7 +60518,7 @@ var require_googleauth = __commonJS({
|
|
|
59940
60518
|
try {
|
|
59941
60519
|
const data = JSON.parse(chunks.join(""));
|
|
59942
60520
|
const r2 = this._cacheClientFromJSON(data, options);
|
|
59943
|
-
return
|
|
60521
|
+
return resolve39(r2);
|
|
59944
60522
|
} catch (err) {
|
|
59945
60523
|
if (!this.keyFilename)
|
|
59946
60524
|
throw err;
|
|
@@ -59950,7 +60528,7 @@ var require_googleauth = __commonJS({
|
|
|
59950
60528
|
});
|
|
59951
60529
|
this.cachedCredential = client;
|
|
59952
60530
|
this.setGapicJWTValues(client);
|
|
59953
|
-
return
|
|
60531
|
+
return resolve39(client);
|
|
59954
60532
|
}
|
|
59955
60533
|
} catch (err) {
|
|
59956
60534
|
return reject(err);
|
|
@@ -59986,17 +60564,17 @@ var require_googleauth = __commonJS({
|
|
|
59986
60564
|
* Run the Google Cloud SDK command that prints the default project ID
|
|
59987
60565
|
*/
|
|
59988
60566
|
async getDefaultServiceProjectId() {
|
|
59989
|
-
return new Promise((
|
|
60567
|
+
return new Promise((resolve39) => {
|
|
59990
60568
|
(0, child_process_1.exec)("gcloud config config-helper --format json", (err, stdout2) => {
|
|
59991
60569
|
if (!err && stdout2) {
|
|
59992
60570
|
try {
|
|
59993
60571
|
const projectId = JSON.parse(stdout2).configuration.properties.core.project;
|
|
59994
|
-
|
|
60572
|
+
resolve39(projectId);
|
|
59995
60573
|
return;
|
|
59996
60574
|
} catch (e2) {
|
|
59997
60575
|
}
|
|
59998
60576
|
}
|
|
59999
|
-
|
|
60577
|
+
resolve39(null);
|
|
60000
60578
|
});
|
|
60001
60579
|
});
|
|
60002
60580
|
}
|
|
@@ -67768,14 +68346,14 @@ function __asyncValues(o) {
|
|
|
67768
68346
|
}, i2);
|
|
67769
68347
|
function verb(n) {
|
|
67770
68348
|
i2[n] = o[n] && function(v) {
|
|
67771
|
-
return new Promise(function(
|
|
67772
|
-
v = o[n](v), settle(
|
|
68349
|
+
return new Promise(function(resolve39, reject) {
|
|
68350
|
+
v = o[n](v), settle(resolve39, reject, v.done, v.value);
|
|
67773
68351
|
});
|
|
67774
68352
|
};
|
|
67775
68353
|
}
|
|
67776
|
-
function settle(
|
|
68354
|
+
function settle(resolve39, reject, d, v) {
|
|
67777
68355
|
Promise.resolve(v).then(function(v2) {
|
|
67778
|
-
|
|
68356
|
+
resolve39({ value: v2, done: d });
|
|
67779
68357
|
}, reject);
|
|
67780
68358
|
}
|
|
67781
68359
|
}
|
|
@@ -78278,8 +78856,8 @@ var init_node4 = __esm({
|
|
|
78278
78856
|
const url = `${websocketBaseUrl}/ws/google.ai.generativelanguage.${apiVersion}.GenerativeService.BidiGenerateMusic?key=${apiKey}`;
|
|
78279
78857
|
let onopenResolve = () => {
|
|
78280
78858
|
};
|
|
78281
|
-
const onopenPromise = new Promise((
|
|
78282
|
-
onopenResolve =
|
|
78859
|
+
const onopenPromise = new Promise((resolve39) => {
|
|
78860
|
+
onopenResolve = resolve39;
|
|
78283
78861
|
});
|
|
78284
78862
|
const callbacks = params.callbacks;
|
|
78285
78863
|
const onopenAwaitedCallback = function() {
|
|
@@ -78485,8 +79063,8 @@ var init_node4 = __esm({
|
|
|
78485
79063
|
}
|
|
78486
79064
|
let onopenResolve = () => {
|
|
78487
79065
|
};
|
|
78488
|
-
const onopenPromise = new Promise((
|
|
78489
|
-
onopenResolve =
|
|
79066
|
+
const onopenPromise = new Promise((resolve39) => {
|
|
79067
|
+
onopenResolve = resolve39;
|
|
78490
79068
|
});
|
|
78491
79069
|
const callbacks = params.callbacks;
|
|
78492
79070
|
const onopenAwaitedCallback = function() {
|
|
@@ -80795,7 +81373,7 @@ var init_node4 = __esm({
|
|
|
80795
81373
|
return void 0;
|
|
80796
81374
|
}
|
|
80797
81375
|
};
|
|
80798
|
-
sleep$1 = (ms) => new Promise((
|
|
81376
|
+
sleep$1 = (ms) => new Promise((resolve39) => setTimeout(resolve39, ms));
|
|
80799
81377
|
FallbackEncoder = ({ headers, body }) => {
|
|
80800
81378
|
return {
|
|
80801
81379
|
bodyHeaders: {
|
|
@@ -81304,8 +81882,8 @@ ${underline2}`);
|
|
|
81304
81882
|
};
|
|
81305
81883
|
APIPromise = class _APIPromise extends Promise {
|
|
81306
81884
|
constructor(client, responsePromise, parseResponse = defaultParseResponse) {
|
|
81307
|
-
super((
|
|
81308
|
-
|
|
81885
|
+
super((resolve39) => {
|
|
81886
|
+
resolve39(null);
|
|
81309
81887
|
});
|
|
81310
81888
|
this.responsePromise = responsePromise;
|
|
81311
81889
|
this.parseResponse = parseResponse;
|
|
@@ -82546,8 +83124,8 @@ ${underline2}`);
|
|
|
82546
83124
|
});
|
|
82547
83125
|
|
|
82548
83126
|
// src/capture/contentExtractor.ts
|
|
82549
|
-
import { readdirSync as readdirSync19, statSync as statSync20, readFileSync as
|
|
82550
|
-
import { join as
|
|
83127
|
+
import { readdirSync as readdirSync19, statSync as statSync20, readFileSync as readFileSync37 } from "fs";
|
|
83128
|
+
import { join as join53 } from "path";
|
|
82551
83129
|
async function detectLibraries(page, capturedShaders) {
|
|
82552
83130
|
let detectedLibraries = [];
|
|
82553
83131
|
try {
|
|
@@ -82667,7 +83245,7 @@ async function captionImagesWithGemini(outputDir, progress, warnings) {
|
|
|
82667
83245
|
try {
|
|
82668
83246
|
const { GoogleGenAI: GoogleGenAI2 } = await Promise.resolve().then(() => (init_node4(), node_exports));
|
|
82669
83247
|
const ai = new GoogleGenAI2({ apiKey: geminiKey });
|
|
82670
|
-
const imageFiles = readdirSync19(
|
|
83248
|
+
const imageFiles = readdirSync19(join53(outputDir, "assets")).filter(
|
|
82671
83249
|
(f3) => /\.(png|jpg|jpeg|webp|gif)$/i.test(f3)
|
|
82672
83250
|
);
|
|
82673
83251
|
const model = process.env.HYPERFRAMES_GEMINI_MODEL || "gemini-3.1-flash-lite-preview";
|
|
@@ -82676,10 +83254,10 @@ async function captionImagesWithGemini(outputDir, progress, warnings) {
|
|
|
82676
83254
|
const batch = imageFiles.slice(i2, i2 + BATCH_SIZE);
|
|
82677
83255
|
const results = await Promise.allSettled(
|
|
82678
83256
|
batch.map(async (file) => {
|
|
82679
|
-
const filePath =
|
|
83257
|
+
const filePath = join53(outputDir, "assets", file);
|
|
82680
83258
|
const stat3 = statSync20(filePath);
|
|
82681
83259
|
if (stat3.size > 4e6) return { file, caption: "" };
|
|
82682
|
-
const buffer =
|
|
83260
|
+
const buffer = readFileSync37(filePath);
|
|
82683
83261
|
const base64 = buffer.toString("base64");
|
|
82684
83262
|
const ext = file.split(".").pop()?.toLowerCase() || "png";
|
|
82685
83263
|
const mimeType = ext === "jpg" ? "image/jpeg" : `image/${ext}`;
|
|
@@ -82725,11 +83303,11 @@ function generateAssetDescriptions(outputDir, tokens, catalogedAssets, geminiCap
|
|
|
82725
83303
|
const uncaptionedLines = [];
|
|
82726
83304
|
const svgLines = [];
|
|
82727
83305
|
const fontLines = [];
|
|
82728
|
-
const assetsPath =
|
|
83306
|
+
const assetsPath = join53(outputDir, "assets");
|
|
82729
83307
|
try {
|
|
82730
83308
|
for (const file of readdirSync19(assetsPath)) {
|
|
82731
83309
|
if (file === "svgs" || file === "fonts" || file === "lottie" || file === "videos") continue;
|
|
82732
|
-
const filePath =
|
|
83310
|
+
const filePath = join53(assetsPath, file);
|
|
82733
83311
|
const stat3 = statSync20(filePath);
|
|
82734
83312
|
if (!stat3.isFile()) continue;
|
|
82735
83313
|
const sizeKb = Math.round(stat3.size / 1024);
|
|
@@ -82758,7 +83336,7 @@ function generateAssetDescriptions(outputDir, tokens, catalogedAssets, geminiCap
|
|
|
82758
83336
|
} catch {
|
|
82759
83337
|
}
|
|
82760
83338
|
try {
|
|
82761
|
-
const svgsPath =
|
|
83339
|
+
const svgsPath = join53(assetsPath, "svgs");
|
|
82762
83340
|
for (const file of readdirSync19(svgsPath)) {
|
|
82763
83341
|
if (!file.endsWith(".svg")) continue;
|
|
82764
83342
|
const svgMatch = tokens.svgs.find(
|
|
@@ -82773,7 +83351,7 @@ function generateAssetDescriptions(outputDir, tokens, catalogedAssets, geminiCap
|
|
|
82773
83351
|
} catch {
|
|
82774
83352
|
}
|
|
82775
83353
|
try {
|
|
82776
|
-
const fontsPath =
|
|
83354
|
+
const fontsPath = join53(assetsPath, "fonts");
|
|
82777
83355
|
for (const file of readdirSync19(fontsPath)) {
|
|
82778
83356
|
fontLines.push(`fonts/${file} \u2014 font file`);
|
|
82779
83357
|
}
|
|
@@ -82793,12 +83371,12 @@ __export(agentPromptGenerator_exports, {
|
|
|
82793
83371
|
generateAgentPrompt: () => generateAgentPrompt
|
|
82794
83372
|
});
|
|
82795
83373
|
import { writeFileSync as writeFileSync21 } from "fs";
|
|
82796
|
-
import { join as
|
|
83374
|
+
import { join as join54 } from "path";
|
|
82797
83375
|
function generateAgentPrompt(outputDir, url, tokens, _animations, hasScreenshot, hasLottie, hasShaders, _catalogedAssets, detectedLibraries) {
|
|
82798
83376
|
const prompt = buildPrompt(url, tokens, hasScreenshot, hasLottie, hasShaders, detectedLibraries);
|
|
82799
|
-
writeFileSync21(
|
|
82800
|
-
writeFileSync21(
|
|
82801
|
-
writeFileSync21(
|
|
83377
|
+
writeFileSync21(join54(outputDir, "AGENTS.md"), prompt, "utf-8");
|
|
83378
|
+
writeFileSync21(join54(outputDir, "CLAUDE.md"), prompt, "utf-8");
|
|
83379
|
+
writeFileSync21(join54(outputDir, ".cursorrules"), prompt, "utf-8");
|
|
82802
83380
|
}
|
|
82803
83381
|
function buildPrompt(url, tokens, hasScreenshot, hasLottie, hasShaders, detectedLibraries) {
|
|
82804
83382
|
const title = tokens.title || new URL(url).hostname.replace(/^www\./, "");
|
|
@@ -82865,15 +83443,15 @@ var init_agentPromptGenerator = __esm({
|
|
|
82865
83443
|
});
|
|
82866
83444
|
|
|
82867
83445
|
// src/capture/scaffolding.ts
|
|
82868
|
-
import { existsSync as
|
|
82869
|
-
import { join as
|
|
83446
|
+
import { existsSync as existsSync51, writeFileSync as writeFileSync22, readFileSync as readFileSync38 } from "fs";
|
|
83447
|
+
import { join as join55, resolve as resolve37 } from "path";
|
|
82870
83448
|
function loadEnvFile(startDir) {
|
|
82871
83449
|
try {
|
|
82872
|
-
let dir =
|
|
83450
|
+
let dir = resolve37(startDir);
|
|
82873
83451
|
for (let i2 = 0; i2 < 5; i2++) {
|
|
82874
|
-
const envPath =
|
|
83452
|
+
const envPath = resolve37(dir, ".env");
|
|
82875
83453
|
try {
|
|
82876
|
-
const envContent =
|
|
83454
|
+
const envContent = readFileSync38(envPath, "utf-8");
|
|
82877
83455
|
for (const line of envContent.split("\n")) {
|
|
82878
83456
|
const trimmed = line.trim();
|
|
82879
83457
|
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
@@ -82885,15 +83463,15 @@ function loadEnvFile(startDir) {
|
|
|
82885
83463
|
}
|
|
82886
83464
|
break;
|
|
82887
83465
|
} catch {
|
|
82888
|
-
dir =
|
|
83466
|
+
dir = resolve37(dir, "..");
|
|
82889
83467
|
}
|
|
82890
83468
|
}
|
|
82891
83469
|
} catch {
|
|
82892
83470
|
}
|
|
82893
83471
|
}
|
|
82894
83472
|
async function generateProjectScaffold(outputDir, url, tokens, animationCatalog, hasScreenshots, hasLotties, hasShaders, catalogedAssets, progress, warnings, detectedLibraries) {
|
|
82895
|
-
const metaPath =
|
|
82896
|
-
if (!
|
|
83473
|
+
const metaPath = join55(outputDir, "meta.json");
|
|
83474
|
+
if (!existsSync51(metaPath)) {
|
|
82897
83475
|
const hostname = new URL(url).hostname.replace(/^www\./, "");
|
|
82898
83476
|
writeFileSync22(
|
|
82899
83477
|
metaPath,
|
|
@@ -82931,9 +83509,9 @@ __export(screenshotCapture_exports, {
|
|
|
82931
83509
|
captureScrollScreenshots: () => captureScrollScreenshots
|
|
82932
83510
|
});
|
|
82933
83511
|
import { writeFileSync as writeFileSync23, mkdirSync as mkdirSync28 } from "fs";
|
|
82934
|
-
import { join as
|
|
83512
|
+
import { join as join56 } from "path";
|
|
82935
83513
|
async function captureScrollScreenshots(page, outputDir) {
|
|
82936
|
-
const screenshotsDir =
|
|
83514
|
+
const screenshotsDir = join56(outputDir, "screenshots");
|
|
82937
83515
|
mkdirSync28(screenshotsDir, { recursive: true });
|
|
82938
83516
|
const MAX_SCREENSHOTS = 20;
|
|
82939
83517
|
const filePaths = [];
|
|
@@ -82967,7 +83545,7 @@ async function captureScrollScreenshots(page, outputDir) {
|
|
|
82967
83545
|
finalPositions[i2] / Math.max(1, scrollHeight - viewportHeight) * 100
|
|
82968
83546
|
);
|
|
82969
83547
|
const filename = `scroll-${String(Math.min(pct, 100)).padStart(3, "0")}.png`;
|
|
82970
|
-
const filePath =
|
|
83548
|
+
const filePath = join56(screenshotsDir, filename);
|
|
82971
83549
|
const buffer = await page.screenshot({ type: "png" });
|
|
82972
83550
|
writeFileSync23(filePath, buffer);
|
|
82973
83551
|
filePaths.push(`screenshots/${filename}`);
|
|
@@ -83280,8 +83858,8 @@ var capture_exports = {};
|
|
|
83280
83858
|
__export(capture_exports, {
|
|
83281
83859
|
captureWebsite: () => captureWebsite
|
|
83282
83860
|
});
|
|
83283
|
-
import { mkdirSync as mkdirSync29, writeFileSync as writeFileSync24, existsSync as
|
|
83284
|
-
import { join as
|
|
83861
|
+
import { mkdirSync as mkdirSync29, writeFileSync as writeFileSync24, existsSync as existsSync52 } from "fs";
|
|
83862
|
+
import { join as join57 } from "path";
|
|
83285
83863
|
async function captureWebsite(opts, onProgress) {
|
|
83286
83864
|
const {
|
|
83287
83865
|
url,
|
|
@@ -83298,9 +83876,9 @@ async function captureWebsite(opts, onProgress) {
|
|
|
83298
83876
|
onProgress?.(stage, detail);
|
|
83299
83877
|
};
|
|
83300
83878
|
loadEnvFile(outputDir);
|
|
83301
|
-
mkdirSync29(
|
|
83302
|
-
mkdirSync29(
|
|
83303
|
-
mkdirSync29(
|
|
83879
|
+
mkdirSync29(join57(outputDir, "extracted"), { recursive: true });
|
|
83880
|
+
mkdirSync29(join57(outputDir, "screenshots"), { recursive: true });
|
|
83881
|
+
mkdirSync29(join57(outputDir, "assets"), { recursive: true });
|
|
83304
83882
|
progress("browser", "Launching headless Chrome...");
|
|
83305
83883
|
const { ensureBrowser: ensureBrowser2 } = await Promise.resolve().then(() => (init_manager2(), manager_exports2));
|
|
83306
83884
|
const browser = await ensureBrowser2();
|
|
@@ -83456,7 +84034,7 @@ async function captureWebsite(opts, onProgress) {
|
|
|
83456
84034
|
} catch {
|
|
83457
84035
|
}
|
|
83458
84036
|
if (discoveredLotties.length > 0) {
|
|
83459
|
-
const lottieDir =
|
|
84037
|
+
const lottieDir = join57(outputDir, "assets", "lottie");
|
|
83460
84038
|
mkdirSync29(lottieDir, { recursive: true });
|
|
83461
84039
|
const savedCount = await saveLottieAnimations(discoveredLotties, lottieDir);
|
|
83462
84040
|
if (savedCount > 0) {
|
|
@@ -83476,7 +84054,7 @@ async function captureWebsite(opts, onProgress) {
|
|
|
83476
84054
|
});
|
|
83477
84055
|
capturedShaders = unique;
|
|
83478
84056
|
writeFileSync24(
|
|
83479
|
-
|
|
84057
|
+
join57(outputDir, "extracted", "shaders.json"),
|
|
83480
84058
|
JSON.stringify(unique, null, 2),
|
|
83481
84059
|
"utf-8"
|
|
83482
84060
|
);
|
|
@@ -83487,7 +84065,7 @@ async function captureWebsite(opts, onProgress) {
|
|
|
83487
84065
|
progress("tokens", "Extracting design tokens...");
|
|
83488
84066
|
const tokens = await extractTokens(page1);
|
|
83489
84067
|
writeFileSync24(
|
|
83490
|
-
|
|
84068
|
+
join57(outputDir, "extracted", "tokens.json"),
|
|
83491
84069
|
JSON.stringify(tokens, null, 2),
|
|
83492
84070
|
"utf-8"
|
|
83493
84071
|
);
|
|
@@ -83561,7 +84139,7 @@ async function captureWebsite(opts, onProgress) {
|
|
|
83561
84139
|
representativeAnimations: representativeAnims
|
|
83562
84140
|
};
|
|
83563
84141
|
writeFileSync24(
|
|
83564
|
-
|
|
84142
|
+
join57(outputDir, "extracted", "animations.json"),
|
|
83565
84143
|
JSON.stringify(leanCatalog, null, 2),
|
|
83566
84144
|
"utf-8"
|
|
83567
84145
|
);
|
|
@@ -83572,18 +84150,18 @@ async function captureWebsite(opts, onProgress) {
|
|
|
83572
84150
|
assets = await downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks);
|
|
83573
84151
|
}
|
|
83574
84152
|
if (visibleTextContent) {
|
|
83575
|
-
writeFileSync24(
|
|
84153
|
+
writeFileSync24(join57(outputDir, "extracted", "visible-text.txt"), visibleTextContent, "utf-8");
|
|
83576
84154
|
}
|
|
83577
84155
|
if (catalogedAssets.length > 0) {
|
|
83578
84156
|
writeFileSync24(
|
|
83579
|
-
|
|
84157
|
+
join57(outputDir, "extracted", "assets-catalog.json"),
|
|
83580
84158
|
JSON.stringify(catalogedAssets, null, 2),
|
|
83581
84159
|
"utf-8"
|
|
83582
84160
|
);
|
|
83583
84161
|
}
|
|
83584
84162
|
if (detectedLibraries.length > 0) {
|
|
83585
84163
|
writeFileSync24(
|
|
83586
|
-
|
|
84164
|
+
join57(outputDir, "extracted", "detected-libraries.json"),
|
|
83587
84165
|
JSON.stringify(detectedLibraries, null, 2),
|
|
83588
84166
|
"utf-8"
|
|
83589
84167
|
);
|
|
@@ -83594,7 +84172,7 @@ async function captureWebsite(opts, onProgress) {
|
|
|
83594
84172
|
const lines = generateAssetDescriptions(outputDir, tokens, catalogedAssets, geminiCaptions);
|
|
83595
84173
|
if (lines.length > 0) {
|
|
83596
84174
|
writeFileSync24(
|
|
83597
|
-
|
|
84175
|
+
join57(outputDir, "extracted", "asset-descriptions.md"),
|
|
83598
84176
|
"# Asset Descriptions\n\nOne line per file. Read this instead of opening every image individually.\n\n" + lines.map((l) => "- " + l).join("\n") + "\n",
|
|
83599
84177
|
"utf-8"
|
|
83600
84178
|
);
|
|
@@ -83610,7 +84188,7 @@ async function captureWebsite(opts, onProgress) {
|
|
|
83610
84188
|
animationCatalog,
|
|
83611
84189
|
screenshots.length > 0,
|
|
83612
84190
|
discoveredLotties.length > 0,
|
|
83613
|
-
|
|
84191
|
+
existsSync52(join57(outputDir, "extracted", "shaders.json")),
|
|
83614
84192
|
catalogedAssets,
|
|
83615
84193
|
progress,
|
|
83616
84194
|
warnings,
|
|
@@ -83650,15 +84228,15 @@ var init_capture = __esm({
|
|
|
83650
84228
|
var capture_exports2 = {};
|
|
83651
84229
|
__export(capture_exports2, {
|
|
83652
84230
|
default: () => capture_default,
|
|
83653
|
-
examples: () =>
|
|
84231
|
+
examples: () => examples22
|
|
83654
84232
|
});
|
|
83655
|
-
import { resolve as
|
|
83656
|
-
var
|
|
84233
|
+
import { resolve as resolve38 } from "path";
|
|
84234
|
+
var examples22, capture_default;
|
|
83657
84235
|
var init_capture2 = __esm({
|
|
83658
84236
|
"src/commands/capture.ts"() {
|
|
83659
84237
|
"use strict";
|
|
83660
84238
|
init_dist();
|
|
83661
|
-
|
|
84239
|
+
examples22 = [
|
|
83662
84240
|
["Capture a website", "hyperframes capture https://stripe.com"],
|
|
83663
84241
|
["Capture to a specific directory", "hyperframes capture https://linear.app -o linear-video"],
|
|
83664
84242
|
["JSON output for AI agents", "hyperframes capture https://example.com --json"]
|
|
@@ -83711,7 +84289,7 @@ var init_capture2 = __esm({
|
|
|
83711
84289
|
const hostname = new URL(url).hostname.replace(/^www\./, "");
|
|
83712
84290
|
outputName = `captures/${hostname.replace(/\./g, "-")}`;
|
|
83713
84291
|
}
|
|
83714
|
-
const outputDir =
|
|
84292
|
+
const outputDir = resolve38(outputName);
|
|
83715
84293
|
const isJson = args.json;
|
|
83716
84294
|
if (!isJson) {
|
|
83717
84295
|
const { c: c2 } = await Promise.resolve().then(() => (init_colors(), colors_exports));
|
|
@@ -83959,7 +84537,7 @@ __export(autoUpdate_exports, {
|
|
|
83959
84537
|
import { spawn as spawn12 } from "child_process";
|
|
83960
84538
|
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync30, openSync } from "fs";
|
|
83961
84539
|
import { homedir as homedir10 } from "os";
|
|
83962
|
-
import { join as
|
|
84540
|
+
import { join as join58 } from "path";
|
|
83963
84541
|
import { compareVersions as compareVersions2 } from "compare-versions";
|
|
83964
84542
|
function isAutoInstallDisabled() {
|
|
83965
84543
|
if (isDevMode()) return true;
|
|
@@ -83982,7 +84560,7 @@ function log(line) {
|
|
|
83982
84560
|
}
|
|
83983
84561
|
function launchDetachedInstall(installCommand, version) {
|
|
83984
84562
|
mkdirSync30(CONFIG_DIR2, { recursive: true, mode: 448 });
|
|
83985
|
-
const configFile =
|
|
84563
|
+
const configFile = join58(CONFIG_DIR2, "config.json");
|
|
83986
84564
|
const nodeScript = `
|
|
83987
84565
|
const { exec } = require("node:child_process");
|
|
83988
84566
|
const { readFileSync, renameSync, writeFileSync } = require("node:fs");
|
|
@@ -84101,18 +84679,31 @@ var init_autoUpdate = __esm({
|
|
|
84101
84679
|
init_config();
|
|
84102
84680
|
init_env();
|
|
84103
84681
|
init_installerDetection();
|
|
84104
|
-
CONFIG_DIR2 =
|
|
84105
|
-
LOG_FILE =
|
|
84682
|
+
CONFIG_DIR2 = join58(homedir10(), ".hyperframes");
|
|
84683
|
+
LOG_FILE = join58(CONFIG_DIR2, "auto-update.log");
|
|
84106
84684
|
PENDING_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
84107
84685
|
}
|
|
84108
84686
|
});
|
|
84109
84687
|
|
|
84688
|
+
// src/commands/layout-audit.browser.js
|
|
84689
|
+
var layout_audit_browser_exports = {};
|
|
84690
|
+
__export(layout_audit_browser_exports, {
|
|
84691
|
+
default: () => layout_audit_browser_default
|
|
84692
|
+
});
|
|
84693
|
+
var layout_audit_browser_default;
|
|
84694
|
+
var init_layout_audit_browser = __esm({
|
|
84695
|
+
"src/commands/layout-audit.browser.js"() {
|
|
84696
|
+
layout_audit_browser_default = '(function () {\n const IGNORE_TAGS = new Set(["SCRIPT", "STYLE", "TEMPLATE", "NOSCRIPT", "META", "LINK"]);\n\n function toRect(rect) {\n return {\n left: round(rect.left),\n top: round(rect.top),\n right: round(rect.right),\n bottom: round(rect.bottom),\n width: round(rect.width),\n height: round(rect.height),\n };\n }\n\n function rectFromOrigin(left, top, width, height) {\n return {\n left: round(left),\n top: round(top),\n right: round(left + width),\n bottom: round(top + height),\n width: round(width),\n height: round(height),\n };\n }\n\n function round(value) {\n return Math.round(value * 100) / 100;\n }\n\n function overflowFor(subject, container, tolerance) {\n const overflow = {};\n if (subject.left < container.left - tolerance)\n overflow.left = round(container.left - subject.left);\n if (subject.right > container.right + tolerance)\n overflow.right = round(subject.right - container.right);\n if (subject.top < container.top - tolerance) overflow.top = round(container.top - subject.top);\n if (subject.bottom > container.bottom + tolerance)\n overflow.bottom = round(subject.bottom - container.bottom);\n return Object.keys(overflow).length > 0 ? overflow : null;\n }\n\n function escapeCss(value) {\n if (window.CSS && typeof window.CSS.escape === "function") return window.CSS.escape(value);\n return value.replace(/[^a-zA-Z0-9_-]/g, "\\\\$&");\n }\n\n function escapeAttr(value) {\n return value.replace(/\\\\/g, "\\\\\\\\").replace(/"/g, \'\\\\"\');\n }\n\n function selectorFor(element) {\n if (element.id) return `#${escapeCss(element.id)}`;\n const dataName =\n element.getAttribute("data-layout-name") ||\n element.getAttribute("data-composition-id") ||\n element.getAttribute("data-start");\n if (dataName) {\n const attr = element.hasAttribute("data-layout-name")\n ? "data-layout-name"\n : element.hasAttribute("data-composition-id")\n ? "data-composition-id"\n : "data-start";\n const attrSelector = `[${attr}="${escapeAttr(dataName)}"]`;\n if (document.querySelectorAll(attrSelector).length === 1) return attrSelector;\n return `${element.tagName.toLowerCase()}${attrSelector}`;\n }\n const classes = Array.from(element.classList).slice(0, 2);\n if (classes.length > 0) {\n return `${element.tagName.toLowerCase()}.${classes.map(escapeCss).join(".")}`;\n }\n const parent = element.parentElement;\n if (!parent) return element.tagName.toLowerCase();\n const siblings = Array.from(parent.children).filter(\n (child) => child.tagName === element.tagName,\n );\n const index = siblings.indexOf(element) + 1;\n return `${selectorFor(parent)} > ${element.tagName.toLowerCase()}:nth-of-type(${index})`;\n }\n\n function hasIgnoreFlag(element) {\n return !!element.closest("[data-layout-ignore], [data-layout-check=\'ignore\']");\n }\n\n function hasAllowOverflowFlag(element) {\n return !!element.closest("[data-layout-allow-overflow]");\n }\n\n function opacityChain(element) {\n let opacity = 1;\n for (let current = element; current; current = current.parentElement) {\n const parsed = Number.parseFloat(getComputedStyle(current).opacity || "1");\n if (Number.isFinite(parsed)) opacity *= parsed;\n }\n return opacity;\n }\n\n function isVisibleElement(element) {\n if (IGNORE_TAGS.has(element.tagName)) return false;\n if (hasIgnoreFlag(element)) return false;\n const style = getComputedStyle(element);\n if (\n style.display === "none" ||\n style.visibility === "hidden" ||\n style.visibility === "collapse"\n ) {\n return false;\n }\n if (opacityChain(element) < 0.2) return false;\n const rect = element.getBoundingClientRect();\n return rect.width > 0.5 && rect.height > 0.5;\n }\n\n function textContentFor(element) {\n return (element.innerText || element.textContent || "").replace(/\\s+/g, " ").trim();\n }\n\n function hasOwnTextCandidate(element) {\n const text = textContentFor(element);\n if (!text) return false;\n for (const child of Array.from(element.children)) {\n if (isVisibleElement(child) && textContentFor(child)) return false;\n }\n return true;\n }\n\n function textRectFor(element) {\n const range = document.createRange();\n range.selectNodeContents(element);\n const rects = Array.from(range.getClientRects()).filter(\n (rect) => rect.width > 0.5 && rect.height > 0.5,\n );\n range.detach();\n if (rects.length === 0) return null;\n\n const union = rects.reduce(\n (acc, rect) => ({\n left: Math.min(acc.left, rect.left),\n top: Math.min(acc.top, rect.top),\n right: Math.max(acc.right, rect.right),\n bottom: Math.max(acc.bottom, rect.bottom),\n }),\n {\n left: Number.POSITIVE_INFINITY,\n top: Number.POSITIVE_INFINITY,\n right: Number.NEGATIVE_INFINITY,\n bottom: Number.NEGATIVE_INFINITY,\n },\n );\n\n return toRect({\n ...union,\n width: union.right - union.left,\n height: union.bottom - union.top,\n });\n }\n\n function parsePx(value) {\n const parsed = Number.parseFloat(value);\n return Number.isFinite(parsed) ? parsed : 0;\n }\n\n function hasMeaningfulBoxStyle(style) {\n return (\n parsePx(style.paddingTop) +\n parsePx(style.paddingRight) +\n parsePx(style.paddingBottom) +\n parsePx(style.paddingLeft) +\n parsePx(style.borderTopWidth) +\n parsePx(style.borderRightWidth) +\n parsePx(style.borderBottomWidth) +\n parsePx(style.borderLeftWidth) +\n parsePx(style.borderTopLeftRadius) +\n parsePx(style.borderTopRightRadius) +\n parsePx(style.borderBottomRightRadius) +\n parsePx(style.borderBottomLeftRadius) >\n 0\n );\n }\n\n function hasPaint(style) {\n const backgroundColor = style.backgroundColor || "";\n const hasBackground =\n backgroundColor !== "" &&\n backgroundColor !== "transparent" &&\n !backgroundColor.endsWith(", 0)") &&\n backgroundColor !== "rgba(0, 0, 0, 0)";\n const hasImage = style.backgroundImage && style.backgroundImage !== "none";\n const hasBorder =\n parsePx(style.borderTopWidth) +\n parsePx(style.borderRightWidth) +\n parsePx(style.borderBottomWidth) +\n parsePx(style.borderLeftWidth) >\n 0;\n const hasRadius =\n parsePx(style.borderTopLeftRadius) +\n parsePx(style.borderTopRightRadius) +\n parsePx(style.borderBottomRightRadius) +\n parsePx(style.borderBottomLeftRadius) >\n 0;\n return hasBackground || hasImage || hasBorder || hasRadius;\n }\n\n function clipsOverflow(style) {\n return [style.overflowX, style.overflowY, style.overflow].some(\n (value) => value && value !== "visible" && value !== "clip visible",\n );\n }\n\n function rootRectFor(root) {\n const measured = toRect(root.getBoundingClientRect());\n const authoredWidth = Number.parseFloat(root.getAttribute("data-width") || "");\n const authoredHeight = Number.parseFloat(root.getAttribute("data-height") || "");\n const hasAuthoredSize =\n Number.isFinite(authoredWidth) &&\n authoredWidth > 0 &&\n Number.isFinite(authoredHeight) &&\n authoredHeight > 0;\n\n if (!hasAuthoredSize) return measured;\n if (measured.width > 0.5 && measured.height > 0.5) return measured;\n return rectFromOrigin(measured.left, measured.top, authoredWidth, authoredHeight);\n }\n\n function isConstraintCandidate(element, root, rootRect) {\n if (element === root) return true;\n const style = getComputedStyle(element);\n if (clipsOverflow(style)) return true;\n if (element.hasAttribute("data-layout-boundary")) return true;\n if (!hasPaint(style)) return false;\n if (!hasMeaningfulBoxStyle(style)) return false;\n const rect = element.getBoundingClientRect();\n const rootArea = rootRect.width * rootRect.height;\n const area = rect.width * rect.height;\n return area > 0 && area < rootArea * 0.95;\n }\n\n function nearestConstraint(element, root, rootRect) {\n for (\n let current = element;\n current && current !== document.body;\n current = current.parentElement\n ) {\n if (!isVisibleElement(current)) continue;\n if (isConstraintCandidate(current, root, rootRect)) return current;\n if (current === root) return current;\n }\n return root;\n }\n\n function formatPx(value) {\n return `${Math.round(value)}px`;\n }\n\n function maxOverflow(overflow) {\n return Math.max(...Object.values(overflow).filter((value) => typeof value === "number"));\n }\n\n function textOverflowFixHint(textRect, containerRect, overflow, fontSize, targetName) {\n const horizontalOverflow = (overflow.left || 0) + (overflow.right || 0);\n const verticalOverflow = (overflow.top || 0) + (overflow.bottom || 0);\n const neededWidth = containerRect.width + horizontalOverflow;\n const neededHeight = containerRect.height + verticalOverflow;\n const widthRatio = containerRect.width > 0 ? containerRect.width / textRect.width : 0;\n const heightRatio = containerRect.height > 0 ? containerRect.height / textRect.height : 0;\n const limitingRatio = Math.min(\n widthRatio > 0 ? widthRatio : Number.POSITIVE_INFINITY,\n heightRatio > 0 ? heightRatio : Number.POSITIVE_INFINITY,\n );\n const shrinkPercent =\n Number.isFinite(limitingRatio) && limitingRatio < 1\n ? Math.ceil((1 - limitingRatio) * 100)\n : 0;\n const targetFont =\n shrinkPercent > 0 && Number.isFinite(fontSize) && fontSize > 0\n ? ` or shrink font-size from ${formatPx(fontSize)} to ~${formatPx(fontSize * limitingRatio)}`\n : "";\n const sizeTarget =\n horizontalOverflow > 0 && verticalOverflow > 0\n ? `resize ${targetName} to at least ~${formatPx(neededWidth)} x ${formatPx(neededHeight)}`\n : horizontalOverflow > 0\n ? `widen ${targetName} to at least ~${formatPx(neededWidth)}`\n : `increase ${targetName} height to at least ~${formatPx(neededHeight)}`;\n\n return `Text is ${formatPx(textRect.width)} x ${formatPx(textRect.height)} inside ${formatPx(containerRect.width)} x ${formatPx(containerRect.height)} and overflows by up to ${formatPx(maxOverflow(overflow))}; ${sizeTarget}${targetFont}, or allow wrapping with max-width/fitTextFontSize.`;\n }\n\n function clippedTextIssue(element, time, tolerance) {\n const style = getComputedStyle(element);\n if (!clipsOverflow(style)) return null;\n const overflowX = element.scrollWidth - element.clientWidth;\n const overflowY = element.scrollHeight - element.clientHeight;\n if (overflowX <= tolerance && overflowY <= tolerance) return null;\n const overflow = {};\n if (overflowX > tolerance) overflow.right = round(overflowX);\n if (overflowY > tolerance) overflow.bottom = round(overflowY);\n const selector = selectorFor(element);\n const text = textContentFor(element);\n const rect = toRect(element.getBoundingClientRect());\n const fontSize = parsePx(style.fontSize);\n return {\n code: "clipped_text",\n severity: "error",\n time,\n selector,\n text,\n message: "Text content is clipped by its own box.",\n rect,\n overflow,\n fixHint: textOverflowFixHint(rect, rect, overflow, fontSize, "the text box"),\n };\n }\n\n function textOverflowIssues(element, root, rootRect, time, tolerance) {\n const textRect = textRectFor(element);\n if (!textRect) return [];\n const text = textContentFor(element);\n const selector = selectorFor(element);\n const issues = [];\n\n const container = nearestConstraint(element, root, rootRect);\n const containerRect = container === root ? rootRect : toRect(container.getBoundingClientRect());\n const containerOverflow = overflowFor(textRect, containerRect, tolerance);\n if (containerOverflow && !hasAllowOverflowFlag(element)) {\n const style = getComputedStyle(element);\n issues.push({\n code: "text_box_overflow",\n severity: "error",\n time,\n selector,\n containerSelector: selectorFor(container),\n text,\n message: "Text extends outside its nearest visual/container box.",\n rect: textRect,\n containerRect,\n overflow: containerOverflow,\n fixHint: textOverflowFixHint(\n textRect,\n containerRect,\n containerOverflow,\n parsePx(style.fontSize),\n "the container",\n ),\n });\n }\n\n const canvasOverflow = overflowFor(textRect, rootRect, tolerance);\n if (canvasOverflow && !hasAllowOverflowFlag(element)) {\n issues.push({\n code: "canvas_overflow",\n severity: "info",\n time,\n selector,\n containerSelector: selectorFor(root),\n text,\n message: "Text extends outside the composition canvas.",\n rect: textRect,\n containerRect: rootRect,\n overflow: canvasOverflow,\n fixHint:\n "Move the text inward, reduce its size, or mark intentional off-canvas animation with data-layout-allow-overflow.",\n });\n }\n\n return issues;\n }\n\n function containerOverflowIssues(root, time, tolerance) {\n const issues = [];\n const containers = Array.from(root.querySelectorAll("*")).filter((element) => {\n if (!isVisibleElement(element) || hasAllowOverflowFlag(element)) return false;\n const style = getComputedStyle(element);\n return clipsOverflow(style) || element.hasAttribute("data-layout-boundary");\n });\n\n for (const container of containers) {\n const containerRect = toRect(container.getBoundingClientRect());\n for (const child of Array.from(container.children)) {\n if (!isVisibleElement(child) || hasAllowOverflowFlag(child)) continue;\n const childRect = toRect(child.getBoundingClientRect());\n const overflow = overflowFor(childRect, containerRect, tolerance);\n if (!overflow) continue;\n issues.push({\n code: "container_overflow",\n severity: "warning",\n time,\n selector: selectorFor(child),\n containerSelector: selectorFor(container),\n message: "Element extends outside a clipping layout container.",\n rect: childRect,\n containerRect,\n overflow,\n fixHint:\n "Resize/reposition the child or container, or mark intentional overflow with data-layout-allow-overflow.",\n });\n }\n }\n\n return issues;\n }\n\n window.__hyperframesLayoutAudit = function auditLayout(options) {\n const time = options && typeof options.time === "number" ? options.time : 0;\n const tolerance =\n options && typeof options.tolerance === "number" ? Math.max(0, options.tolerance) : 2;\n const root =\n document.querySelector("[data-composition-id][data-width][data-height]") ||\n document.querySelector("[data-composition-id]") ||\n document.body;\n const rootRect = rootRectFor(root);\n const elements = Array.from(root.querySelectorAll("*")).filter(isVisibleElement);\n const issues = [];\n\n for (const element of elements) {\n if (!hasOwnTextCandidate(element)) continue;\n const clipped = clippedTextIssue(element, time, tolerance);\n if (clipped) issues.push(clipped);\n issues.push(...textOverflowIssues(element, root, rootRect, time, tolerance));\n }\n\n issues.push(...containerOverflowIssues(root, time, tolerance));\n return issues;\n };\n})();\n';
|
|
84697
|
+
}
|
|
84698
|
+
});
|
|
84699
|
+
|
|
84110
84700
|
// import("./commands/**/*.js") in src/help.ts
|
|
84111
84701
|
var globImport_commands_js;
|
|
84112
84702
|
var init_ = __esm({
|
|
84113
84703
|
'import("./commands/**/*.js") in src/help.ts'() {
|
|
84114
84704
|
globImport_commands_js = __glob({
|
|
84115
|
-
"./commands/contrast-audit.browser.js": () => Promise.resolve().then(() => (init_contrast_audit_browser(), contrast_audit_browser_exports))
|
|
84705
|
+
"./commands/contrast-audit.browser.js": () => Promise.resolve().then(() => (init_contrast_audit_browser(), contrast_audit_browser_exports)),
|
|
84706
|
+
"./commands/layout-audit.browser.js": () => Promise.resolve().then(() => (init_layout_audit_browser(), layout_audit_browser_exports))
|
|
84116
84707
|
});
|
|
84117
84708
|
}
|
|
84118
84709
|
});
|
|
@@ -84155,10 +84746,10 @@ function renderRootHelp() {
|
|
|
84155
84746
|
lines.push(`Run ${c.cyan("hyperframes <command> --help")} for more information about a command.`);
|
|
84156
84747
|
return lines.join("\n");
|
|
84157
84748
|
}
|
|
84158
|
-
function formatExamples(
|
|
84749
|
+
function formatExamples(examples23) {
|
|
84159
84750
|
const lines = [];
|
|
84160
84751
|
lines.push(c.bold("Examples:"));
|
|
84161
|
-
for (const [comment, command2] of
|
|
84752
|
+
for (const [comment, command2] of examples23) {
|
|
84162
84753
|
lines.push(` ${c.gray(`# ${comment}`)}`);
|
|
84163
84754
|
lines.push(` ${command2}`);
|
|
84164
84755
|
lines.push("");
|
|
@@ -84175,9 +84766,9 @@ async function showUsage2(cmd, parent) {
|
|
|
84175
84766
|
console.log(usage + "\n");
|
|
84176
84767
|
const name = meta?.name;
|
|
84177
84768
|
if (name) {
|
|
84178
|
-
const
|
|
84179
|
-
if (
|
|
84180
|
-
console.log(formatExamples(
|
|
84769
|
+
const examples23 = STATIC_EXAMPLES[name] ?? await loadExamples(name);
|
|
84770
|
+
if (examples23) {
|
|
84771
|
+
console.log(formatExamples(examples23) + "\n");
|
|
84181
84772
|
}
|
|
84182
84773
|
}
|
|
84183
84774
|
}
|
|
@@ -84206,6 +84797,7 @@ var init_help = __esm({
|
|
|
84206
84797
|
title: "Project",
|
|
84207
84798
|
commands: [
|
|
84208
84799
|
["lint", "Validate a composition for common mistakes"],
|
|
84800
|
+
["inspect", "Inspect rendered visual layout across the timeline"],
|
|
84209
84801
|
["snapshot", "Capture key frames as PNG screenshots for visual verification"],
|
|
84210
84802
|
["info", "Print project metadata"],
|
|
84211
84803
|
["compositions", "List all compositions in a project"],
|
|
@@ -84247,6 +84839,7 @@ var init_help = __esm({
|
|
|
84247
84839
|
["Render to MP4", "hyperframes render -o out.mp4"],
|
|
84248
84840
|
["Transparent WebM overlay", "hyperframes render --format webm -o out.webm"],
|
|
84249
84841
|
["Validate your composition", "hyperframes lint"],
|
|
84842
|
+
["Inspect visual layout", "hyperframes inspect"],
|
|
84250
84843
|
["Check system dependencies", "hyperframes doctor"]
|
|
84251
84844
|
];
|
|
84252
84845
|
STATIC_EXAMPLES = {
|
|
@@ -84272,6 +84865,8 @@ var subCommands = {
|
|
|
84272
84865
|
publish: () => Promise.resolve().then(() => (init_publish(), publish_exports)).then((m2) => m2.default),
|
|
84273
84866
|
render: () => Promise.resolve().then(() => (init_render2(), render_exports)).then((m2) => m2.default),
|
|
84274
84867
|
lint: () => Promise.resolve().then(() => (init_lint3(), lint_exports2)).then((m2) => m2.default),
|
|
84868
|
+
inspect: () => Promise.resolve().then(() => (init_inspect(), inspect_exports)).then((m2) => m2.default),
|
|
84869
|
+
layout: () => Promise.resolve().then(() => (init_layout2(), layout_exports)).then((m2) => m2.default),
|
|
84275
84870
|
info: () => Promise.resolve().then(() => (init_info(), info_exports)).then((m2) => m2.default),
|
|
84276
84871
|
compositions: () => Promise.resolve().then(() => (init_compositions(), compositions_exports)).then((m2) => m2.default),
|
|
84277
84872
|
benchmark: () => Promise.resolve().then(() => (init_benchmark(), benchmark_exports)).then((m2) => m2.default),
|