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