hyperframes 0.6.63 → 0.6.65
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 +213 -58
- package/dist/skills/hyperframes/references/techniques.md +15 -30
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -50,7 +50,7 @@ var VERSION;
|
|
|
50
50
|
var init_version = __esm({
|
|
51
51
|
"src/version.ts"() {
|
|
52
52
|
"use strict";
|
|
53
|
-
VERSION = true ? "0.6.
|
|
53
|
+
VERSION = true ? "0.6.65" : "0.0.0-dev";
|
|
54
54
|
}
|
|
55
55
|
});
|
|
56
56
|
|
|
@@ -36438,6 +36438,19 @@ function extractCompositionIdsFromCss(css) {
|
|
|
36438
36438
|
}
|
|
36439
36439
|
return [...ids];
|
|
36440
36440
|
}
|
|
36441
|
+
function extractTimelineRegistryKeys(source) {
|
|
36442
|
+
const keys2 = /* @__PURE__ */ new Set();
|
|
36443
|
+
let match;
|
|
36444
|
+
const pattern = new RegExp(
|
|
36445
|
+
TIMELINE_REGISTRY_KEY_PATTERN.source,
|
|
36446
|
+
TIMELINE_REGISTRY_KEY_PATTERN.flags
|
|
36447
|
+
);
|
|
36448
|
+
while ((match = pattern.exec(source)) !== null) {
|
|
36449
|
+
const key2 = match[1] ?? match[2];
|
|
36450
|
+
if (key2) keys2.add(key2);
|
|
36451
|
+
}
|
|
36452
|
+
return [...keys2];
|
|
36453
|
+
}
|
|
36441
36454
|
function getInlineScriptSyntaxError(source) {
|
|
36442
36455
|
if (!source.trim()) return null;
|
|
36443
36456
|
try {
|
|
@@ -36457,7 +36470,7 @@ function truncateSnippet(value, maxLength = 220) {
|
|
|
36457
36470
|
if (normalized.length <= maxLength) return normalized;
|
|
36458
36471
|
return `${normalized.slice(0, maxLength - 3)}...`;
|
|
36459
36472
|
}
|
|
36460
|
-
var TAG_PATTERN, STYLE_BLOCK_PATTERN, SCRIPT_BLOCK_PATTERN, COMPOSITION_ID_IN_CSS_PATTERN, TIMELINE_REGISTRY_INIT_PATTERN, TIMELINE_REGISTRY_ASSIGN_PATTERN, WINDOW_TIMELINE_ASSIGN_PATTERN, INVALID_SCRIPT_CLOSE_PATTERN;
|
|
36473
|
+
var TAG_PATTERN, STYLE_BLOCK_PATTERN, SCRIPT_BLOCK_PATTERN, COMPOSITION_ID_IN_CSS_PATTERN, TIMELINE_REGISTRY_INIT_PATTERN, TIMELINE_REGISTRY_ASSIGN_PATTERN, WINDOW_TIMELINE_ASSIGN_PATTERN, INVALID_SCRIPT_CLOSE_PATTERN, TIMELINE_REGISTRY_KEY_PATTERN;
|
|
36461
36474
|
var init_utils2 = __esm({
|
|
36462
36475
|
"../core/src/lint/utils.ts"() {
|
|
36463
36476
|
"use strict";
|
|
@@ -36466,9 +36479,10 @@ var init_utils2 = __esm({
|
|
|
36466
36479
|
SCRIPT_BLOCK_PATTERN = /<script\b([^>]*)>([\s\S]*?)<\/script>/gi;
|
|
36467
36480
|
COMPOSITION_ID_IN_CSS_PATTERN = /\[data-composition-id=["']([^"']+)["']\]/g;
|
|
36468
36481
|
TIMELINE_REGISTRY_INIT_PATTERN = /window\.__timelines\s*=\s*window\.__timelines\s*\|\|\s*\{\}|window\.__timelines\s*=\s*\{\}|window\.__timelines\s*\?\?=\s*\{\}/i;
|
|
36469
|
-
TIMELINE_REGISTRY_ASSIGN_PATTERN = /window\.__timelines
|
|
36470
|
-
WINDOW_TIMELINE_ASSIGN_PATTERN = /window\.__timelines
|
|
36482
|
+
TIMELINE_REGISTRY_ASSIGN_PATTERN = /window\.__timelines(?:\[[^\]]+\]|\.[A-Za-z_$][\w$]*)\s*=/i;
|
|
36483
|
+
WINDOW_TIMELINE_ASSIGN_PATTERN = /window\.__timelines(?:\[\s*["']([^"']+)["']\s*\]|\.\s*([A-Za-z_$][\w$]*))\s*=\s*([A-Za-z_$][\w$]*)/i;
|
|
36471
36484
|
INVALID_SCRIPT_CLOSE_PATTERN = /<script[^>]*>[\s\S]*?<\s*\/\s*script(?!>)/i;
|
|
36485
|
+
TIMELINE_REGISTRY_KEY_PATTERN = /window\.__timelines(?:\[\s*["']([^"']+)["']\s*\]|\.\s*([A-Za-z_$][\w$]*))\s*=/g;
|
|
36472
36486
|
}
|
|
36473
36487
|
});
|
|
36474
36488
|
|
|
@@ -36604,13 +36618,12 @@ var init_core = __esm({
|
|
|
36604
36618
|
const htmlCompIds = /* @__PURE__ */ new Set();
|
|
36605
36619
|
const timelineRegKeys = /* @__PURE__ */ new Set();
|
|
36606
36620
|
const compIdRe = /data-composition-id\s*=\s*["']([^"']+)["']/gi;
|
|
36607
|
-
const tlKeyRe = /window\.__timelines\[\s*["']([^"']+)["']\s*\]/g;
|
|
36608
36621
|
let m2;
|
|
36609
36622
|
while ((m2 = compIdRe.exec(source)) !== null) {
|
|
36610
36623
|
if (m2[1]) htmlCompIds.add(m2[1]);
|
|
36611
36624
|
}
|
|
36612
|
-
|
|
36613
|
-
|
|
36625
|
+
for (const key2 of extractTimelineRegistryKeys(source)) {
|
|
36626
|
+
timelineRegKeys.add(key2);
|
|
36614
36627
|
}
|
|
36615
36628
|
for (const key2 of timelineRegKeys) {
|
|
36616
36629
|
if (!htmlCompIds.has(key2)) {
|
|
@@ -37358,7 +37371,7 @@ function countClassUsage(tags) {
|
|
|
37358
37371
|
}
|
|
37359
37372
|
function readRegisteredTimelineCompositionId(script) {
|
|
37360
37373
|
const match = script.match(WINDOW_TIMELINE_ASSIGN_PATTERN);
|
|
37361
|
-
return match?.[1] || null;
|
|
37374
|
+
return match?.[1] || match?.[2] || null;
|
|
37362
37375
|
}
|
|
37363
37376
|
function unwrapRaw(value) {
|
|
37364
37377
|
if (typeof value === "number") return value;
|
|
@@ -67373,9 +67386,9 @@ async function mixAudioTracks(tracks, outputPath, totalDuration, signal, config)
|
|
|
67373
67386
|
);
|
|
67374
67387
|
});
|
|
67375
67388
|
const mixInputs = tracks.map((_, i2) => `[a${i2}]`).join("");
|
|
67376
|
-
const
|
|
67377
|
-
const
|
|
67378
|
-
const postMixGainFilter = `[mixed]volume=${
|
|
67389
|
+
const mixFilter = `${mixInputs}amix=inputs=${tracks.length}:duration=longest:dropout_transition=0[mixed]`;
|
|
67390
|
+
const compensatedGain = masterOutputGain * tracks.length;
|
|
67391
|
+
const postMixGainFilter = `[mixed]volume=${formatFilterNumber(compensatedGain)}[out]`;
|
|
67379
67392
|
const fullFilter = [...filterParts, mixFilter, postMixGainFilter].join(";");
|
|
67380
67393
|
return [
|
|
67381
67394
|
...inputs,
|
|
@@ -71420,7 +71433,7 @@ var init_urlDownloader2 = __esm({
|
|
|
71420
71433
|
|
|
71421
71434
|
// ../producer/src/services/htmlCompiler.ts
|
|
71422
71435
|
import { readFileSync as readFileSync27, existsSync as existsSync35, mkdirSync as mkdirSync20 } from "fs";
|
|
71423
|
-
import { join as join39, dirname as dirname13, resolve as resolve19 } from "path";
|
|
71436
|
+
import { join as join39, dirname as dirname13, resolve as resolve19, basename as basename5 } from "path";
|
|
71424
71437
|
function dedupeElementsById(elements) {
|
|
71425
71438
|
const deduped = /* @__PURE__ */ new Map();
|
|
71426
71439
|
for (const element of elements) {
|
|
@@ -71552,6 +71565,8 @@ async function compileHtmlFile(html, baseDir, downloadDir) {
|
|
|
71552
71565
|
compiledHtml = clampDurations(compiledHtml, clampList);
|
|
71553
71566
|
}
|
|
71554
71567
|
compiledHtml = compiledHtml.replace(/(<video\b[^>]*)\s+crossorigin(?:=["'][^"']*["'])?/gi, "$1");
|
|
71568
|
+
compiledHtml = compiledHtml.replace(/(<img\b[^>]*)\s+crossorigin(?:=["'][^"']*["'])?/gi, "$1");
|
|
71569
|
+
compiledHtml = compiledHtml.replace(/(<audio\b[^>]*)\s+crossorigin(?:=["'][^"']*["'])?/gi, "$1");
|
|
71555
71570
|
return { html: compiledHtml, unresolvedCompositions };
|
|
71556
71571
|
}
|
|
71557
71572
|
async function parseSubCompositions(html, projectDir, downloadDir, parentOffset = 0, parentEnd = Infinity, visited = /* @__PURE__ */ new Set()) {
|
|
@@ -71964,6 +71979,46 @@ function collectExternalAssets(html, projectDir) {
|
|
|
71964
71979
|
externalAssets
|
|
71965
71980
|
};
|
|
71966
71981
|
}
|
|
71982
|
+
async function localizeRemoteMediaSources(html, downloadDir) {
|
|
71983
|
+
const remoteDir = join39(downloadDir, REMOTE_MEDIA_SUBDIR);
|
|
71984
|
+
const urlSet = /* @__PURE__ */ new Set();
|
|
71985
|
+
const re2 = new RegExp(REMOTE_MEDIA_TAG_RE.source, REMOTE_MEDIA_TAG_RE.flags);
|
|
71986
|
+
let m2;
|
|
71987
|
+
while ((m2 = re2.exec(html)) !== null) {
|
|
71988
|
+
if (m2[1]) urlSet.add(m2[1]);
|
|
71989
|
+
}
|
|
71990
|
+
if (urlSet.size === 0) return { html, remoteMediaAssets: /* @__PURE__ */ new Map() };
|
|
71991
|
+
if (!existsSync35(remoteDir)) mkdirSync20(remoteDir, { recursive: true });
|
|
71992
|
+
const urlToLocal = /* @__PURE__ */ new Map();
|
|
71993
|
+
await Promise.all(
|
|
71994
|
+
[...urlSet].map(async (url) => {
|
|
71995
|
+
try {
|
|
71996
|
+
const localPath = await downloadToTemp(url, remoteDir);
|
|
71997
|
+
urlToLocal.set(url, localPath);
|
|
71998
|
+
} catch (err) {
|
|
71999
|
+
console.warn(
|
|
72000
|
+
`[Compiler] Remote media download failed for ${url} \u2014 using original URL as fallback. ${err instanceof Error ? err.message : String(err)}`
|
|
72001
|
+
);
|
|
72002
|
+
}
|
|
72003
|
+
})
|
|
72004
|
+
);
|
|
72005
|
+
if (urlToLocal.size === 0) return { html, remoteMediaAssets: /* @__PURE__ */ new Map() };
|
|
72006
|
+
const remoteMediaAssets = /* @__PURE__ */ new Map();
|
|
72007
|
+
const urlToRelPath = /* @__PURE__ */ new Map();
|
|
72008
|
+
for (const [url, absPath] of urlToLocal) {
|
|
72009
|
+
const relPath = `${REMOTE_MEDIA_SUBDIR}/${basename5(absPath)}`;
|
|
72010
|
+
remoteMediaAssets.set(relPath, absPath);
|
|
72011
|
+
urlToRelPath.set(url, relPath);
|
|
72012
|
+
}
|
|
72013
|
+
let result = html;
|
|
72014
|
+
for (const [url, relPath] of urlToRelPath) {
|
|
72015
|
+
result = result.replaceAll(`"${url}"`, `"${relPath}"`).replaceAll(`'${url}'`, `'${relPath}'`);
|
|
72016
|
+
}
|
|
72017
|
+
console.log(
|
|
72018
|
+
`[Compiler] Localized ${urlToLocal.size} remote media source(s) to ${REMOTE_MEDIA_SUBDIR}/`
|
|
72019
|
+
);
|
|
72020
|
+
return { html: result, remoteMediaAssets };
|
|
72021
|
+
}
|
|
71967
72022
|
function rewriteUnresolvableGsapToCdn(html, projectDir) {
|
|
71968
72023
|
return html.replace(
|
|
71969
72024
|
/(<script\b[^>]*\bsrc=["'])([^"']*gsap[^"']*\/dist\/([^"']+))(["'][^>]*>)/gi,
|
|
@@ -72014,10 +72069,17 @@ async function compileForRender(projectDir, htmlPath, downloadDir, options = {})
|
|
|
72014
72069
|
'data-hf-studio-motion="'
|
|
72015
72070
|
];
|
|
72016
72071
|
const hasPositionEdits = HF_POSITION_ATTRS.some((attr) => htmlWithAssets.includes(attr));
|
|
72017
|
-
const
|
|
72072
|
+
const htmlWithPositionScript = hasPositionEdits ? htmlWithAssets.replace(
|
|
72018
72073
|
/<\/body>/i,
|
|
72019
72074
|
`<script>${createStudioPositionSeekReapplyScript()}</script></body>`
|
|
72020
72075
|
) : htmlWithAssets;
|
|
72076
|
+
const { html, remoteMediaAssets } = await localizeRemoteMediaSources(
|
|
72077
|
+
htmlWithPositionScript,
|
|
72078
|
+
downloadDir
|
|
72079
|
+
);
|
|
72080
|
+
for (const [relPath, absPath] of remoteMediaAssets) {
|
|
72081
|
+
externalAssets.set(relPath, absPath);
|
|
72082
|
+
}
|
|
72021
72083
|
const mainVideos = parseVideoElements(html);
|
|
72022
72084
|
const mainAudios = parseAudioElements(html);
|
|
72023
72085
|
const mainImages = parseImageElements(html);
|
|
@@ -72298,7 +72360,7 @@ async function recompileWithResolutions(compiled, resolutions, projectDir, downl
|
|
|
72298
72360
|
hasShaderTransitions: compiled.hasShaderTransitions
|
|
72299
72361
|
};
|
|
72300
72362
|
}
|
|
72301
|
-
var INLINE_SCRIPT_PATTERN, COMPILER_MOUNT_BLOCK_START, COMPILER_MOUNT_BLOCK_END, SHADER_TRANSITION_USAGE_PATTERN, GSAP_CDN_BASE;
|
|
72363
|
+
var INLINE_SCRIPT_PATTERN, COMPILER_MOUNT_BLOCK_START, COMPILER_MOUNT_BLOCK_END, SHADER_TRANSITION_USAGE_PATTERN, REMOTE_MEDIA_SUBDIR, REMOTE_MEDIA_TAG_RE, GSAP_CDN_BASE;
|
|
72302
72364
|
var init_htmlCompiler2 = __esm({
|
|
72303
72365
|
"../producer/src/services/htmlCompiler.ts"() {
|
|
72304
72366
|
"use strict";
|
|
@@ -72315,6 +72377,8 @@ var init_htmlCompiler2 = __esm({
|
|
|
72315
72377
|
COMPILER_MOUNT_BLOCK_START = "/* __HF_COMPILER_MOUNT_START__ */";
|
|
72316
72378
|
COMPILER_MOUNT_BLOCK_END = "/* __HF_COMPILER_MOUNT_END__ */";
|
|
72317
72379
|
SHADER_TRANSITION_USAGE_PATTERN = /\b(?:(?:window|globalThis)\s*\.\s*)?HyperShader\s*\.\s*init\s*\(|\b__hf\s*\.\s*transitions\s*=/;
|
|
72380
|
+
REMOTE_MEDIA_SUBDIR = "_remote_media";
|
|
72381
|
+
REMOTE_MEDIA_TAG_RE = /<(?:video|audio)\b[^>]*?\bsrc\s*=\s*["'](https?:\/\/[^"']+)["'][^>]*>/gi;
|
|
72318
72382
|
GSAP_CDN_BASE = "https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/";
|
|
72319
72383
|
}
|
|
72320
72384
|
});
|
|
@@ -78329,7 +78393,7 @@ __export(studioServer_exports, {
|
|
|
78329
78393
|
import { Hono as Hono5 } from "hono";
|
|
78330
78394
|
import { streamSSE as streamSSE3 } from "hono/streaming";
|
|
78331
78395
|
import { existsSync as existsSync48, readFileSync as readFileSync35, writeFileSync as writeFileSync25, statSync as statSync17 } from "fs";
|
|
78332
|
-
import { resolve as resolve24, join as join58, basename as
|
|
78396
|
+
import { resolve as resolve24, join as join58, basename as basename6 } from "path";
|
|
78333
78397
|
function resolveDistDir() {
|
|
78334
78398
|
return resolveStudioBundle().dir;
|
|
78335
78399
|
}
|
|
@@ -78456,7 +78520,7 @@ async function loadPreviewServerBuildSignature() {
|
|
|
78456
78520
|
}
|
|
78457
78521
|
function createStudioServer(options) {
|
|
78458
78522
|
const { projectDir, projectName } = options;
|
|
78459
|
-
const projectId = projectName ||
|
|
78523
|
+
const projectId = projectName || basename6(projectDir);
|
|
78460
78524
|
const studioDir = resolveDistDir();
|
|
78461
78525
|
const runtimePath = resolveRuntimePath();
|
|
78462
78526
|
const watcher = createProjectWatcher(projectDir);
|
|
@@ -78632,19 +78696,19 @@ function createStudioServer(options) {
|
|
|
78632
78696
|
async installRegistryBlock(opts) {
|
|
78633
78697
|
const { resolveItem: resolveItem2 } = await Promise.resolve().then(() => (init_resolver(), resolver_exports));
|
|
78634
78698
|
const { installItem: installItem2 } = await Promise.resolve().then(() => (init_installer(), installer_exports));
|
|
78635
|
-
const { readFileSync:
|
|
78699
|
+
const { readFileSync: readFileSync59, writeFileSync: writeFileSync40, existsSync: existsSync81 } = await import("fs");
|
|
78636
78700
|
const { join: join92 } = await import("path");
|
|
78637
78701
|
const item = await resolveItem2(opts.blockName);
|
|
78638
78702
|
const { written } = await installItem2(item, { destDir: opts.project.dir });
|
|
78639
78703
|
const indexPath = join92(opts.project.dir, "index.html");
|
|
78640
78704
|
if (existsSync81(indexPath)) {
|
|
78641
|
-
const indexHtml =
|
|
78705
|
+
const indexHtml = readFileSync59(indexPath, "utf-8");
|
|
78642
78706
|
const hostW = indexHtml.match(/data-width="(\d+)"/)?.[1];
|
|
78643
78707
|
const hostH = indexHtml.match(/data-height="(\d+)"/)?.[1];
|
|
78644
78708
|
if (hostW && hostH) {
|
|
78645
78709
|
for (const absPath of written) {
|
|
78646
78710
|
if (!absPath.endsWith(".html")) continue;
|
|
78647
|
-
let content =
|
|
78711
|
+
let content = readFileSync59(absPath, "utf-8");
|
|
78648
78712
|
content = content.replace(
|
|
78649
78713
|
/(<meta\s+name="viewport"\s+content="width=)\d+(,\s*height=)\d+/i,
|
|
78650
78714
|
`$1${hostW}$2${hostH}`
|
|
@@ -78842,14 +78906,14 @@ __export(preview_exports, {
|
|
|
78842
78906
|
});
|
|
78843
78907
|
import { spawn as spawn11 } from "child_process";
|
|
78844
78908
|
import { existsSync as existsSync49, lstatSync as lstatSync2, symlinkSync as symlinkSync2, unlinkSync as unlinkSync5, readlinkSync, mkdirSync as mkdirSync30 } from "fs";
|
|
78845
|
-
import { resolve as resolve25, dirname as dirname19, basename as
|
|
78909
|
+
import { resolve as resolve25, dirname as dirname19, basename as basename7, join as join59 } from "path";
|
|
78846
78910
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
78847
78911
|
import { createRequire as createRequire2 } from "module";
|
|
78848
78912
|
async function runDevMode(dir, options) {
|
|
78849
78913
|
const thisFile = fileURLToPath6(import.meta.url);
|
|
78850
78914
|
const repoRoot2 = resolve25(dirname19(thisFile), "..", "..", "..", "..");
|
|
78851
78915
|
const projectsDir = join59(repoRoot2, "packages", "studio", "data", "projects");
|
|
78852
|
-
const pName = options?.projectName ??
|
|
78916
|
+
const pName = options?.projectName ?? basename7(dir);
|
|
78853
78917
|
const symlinkPath = join59(projectsDir, pName);
|
|
78854
78918
|
mkdirSync30(projectsDir, { recursive: true });
|
|
78855
78919
|
let createdSymlink = false;
|
|
@@ -78939,7 +79003,7 @@ function hasLocalStudio(dir) {
|
|
|
78939
79003
|
async function runLocalStudioMode(dir, options) {
|
|
78940
79004
|
const req = createRequire2(join59(dir, "package.json"));
|
|
78941
79005
|
const studioPkgPath = dirname19(req.resolve("@hyperframes/studio/package.json"));
|
|
78942
|
-
const pName = options?.projectName ??
|
|
79006
|
+
const pName = options?.projectName ?? basename7(dir);
|
|
78943
79007
|
const projectsDir = join59(studioPkgPath, "data", "projects");
|
|
78944
79008
|
const symlinkPath = join59(projectsDir, pName);
|
|
78945
79009
|
mkdirSync30(projectsDir, { recursive: true });
|
|
@@ -79010,7 +79074,7 @@ async function runLocalStudioMode(dir, options) {
|
|
|
79010
79074
|
}
|
|
79011
79075
|
async function runEmbeddedMode(dir, startPort, options) {
|
|
79012
79076
|
const { createStudioServer: createStudioServer2, loadPreviewServerBuildSignature: loadPreviewServerBuildSignature2, resolveStudioBundle: resolveStudioBundle2 } = await Promise.resolve().then(() => (init_studioServer(), studioServer_exports));
|
|
79013
|
-
const pName = options?.projectName ??
|
|
79077
|
+
const pName = options?.projectName ?? basename7(dir);
|
|
79014
79078
|
const studioBundle = resolveStudioBundle2();
|
|
79015
79079
|
ge(c2.bold("hyperframes preview"));
|
|
79016
79080
|
const s2 = ft();
|
|
@@ -79240,7 +79304,7 @@ var init_preview2 = __esm({
|
|
|
79240
79304
|
const rawArg = args.dir;
|
|
79241
79305
|
const dir = resolve25(rawArg ?? ".");
|
|
79242
79306
|
const isImplicitCwd = !rawArg || rawArg === "." || rawArg === "./";
|
|
79243
|
-
const projectName = isImplicitCwd ?
|
|
79307
|
+
const projectName = isImplicitCwd ? basename7(process.env.PWD ?? dir) : basename7(dir);
|
|
79244
79308
|
const indexPath = join59(dir, "index.html");
|
|
79245
79309
|
if (existsSync49(indexPath)) {
|
|
79246
79310
|
const project = { dir, name: projectName, indexPath };
|
|
@@ -79328,7 +79392,7 @@ import {
|
|
|
79328
79392
|
readFileSync as readFileSync36,
|
|
79329
79393
|
readdirSync as readdirSync21
|
|
79330
79394
|
} from "fs";
|
|
79331
|
-
import { resolve as resolve26, basename as
|
|
79395
|
+
import { resolve as resolve26, basename as basename8, join as join60, dirname as dirname20 } from "path";
|
|
79332
79396
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
79333
79397
|
import { execFileSync as execFileSync5, spawn as spawn12 } from "child_process";
|
|
79334
79398
|
function probeVideo(filePath) {
|
|
@@ -79409,7 +79473,7 @@ function getSharedTemplateDir() {
|
|
|
79409
79473
|
return resolveAssetDir(["..", "templates", "_shared"], ["templates", "_shared"]);
|
|
79410
79474
|
}
|
|
79411
79475
|
function toPackageName(projectName) {
|
|
79412
|
-
const normalized =
|
|
79476
|
+
const normalized = basename8(projectName).trim().toLowerCase().replace(/^[._]+/, "").replace(/[^a-z0-9._~-]+/g, "-").replace(/-+/g, "-").replace(/^[-.]+|[-.]+$/g, "");
|
|
79413
79477
|
return normalized || "hyperframes-project";
|
|
79414
79478
|
}
|
|
79415
79479
|
function getHyperframesPackageSpecifier() {
|
|
@@ -79520,7 +79584,7 @@ async function patchTranscript(dir, transcriptPath) {
|
|
|
79520
79584
|
async function handleVideoFile(videoPath, destDir, interactive) {
|
|
79521
79585
|
const probed = probeVideo(videoPath);
|
|
79522
79586
|
let meta = { ...DEFAULT_META };
|
|
79523
|
-
let localVideoName =
|
|
79587
|
+
let localVideoName = basename8(videoPath);
|
|
79524
79588
|
if (probed) {
|
|
79525
79589
|
meta = probed;
|
|
79526
79590
|
if (interactive) {
|
|
@@ -79870,8 +79934,8 @@ var init_init = __esm({
|
|
|
79870
79934
|
process.exit(1);
|
|
79871
79935
|
}
|
|
79872
79936
|
sourceFilePath2 = audioPath;
|
|
79873
|
-
copyFileSync5(audioPath, resolve26(destDir2,
|
|
79874
|
-
console.log(`Audio: ${
|
|
79937
|
+
copyFileSync5(audioPath, resolve26(destDir2, basename8(audioPath)));
|
|
79938
|
+
console.log(`Audio: ${basename8(audioPath)}`);
|
|
79875
79939
|
}
|
|
79876
79940
|
if (sourceFilePath2 && !skipTranscribe) {
|
|
79877
79941
|
try {
|
|
@@ -79895,7 +79959,7 @@ var init_init = __esm({
|
|
|
79895
79959
|
try {
|
|
79896
79960
|
await scaffoldProject(
|
|
79897
79961
|
destDir2,
|
|
79898
|
-
|
|
79962
|
+
basename8(destDir2),
|
|
79899
79963
|
templateId2,
|
|
79900
79964
|
localVideoName2,
|
|
79901
79965
|
videoDuration2,
|
|
@@ -80002,8 +80066,8 @@ var init_init = __esm({
|
|
|
80002
80066
|
}
|
|
80003
80067
|
mkdirSync31(destDir, { recursive: true });
|
|
80004
80068
|
sourceFilePath = audioPath;
|
|
80005
|
-
copyFileSync5(audioPath, resolve26(destDir,
|
|
80006
|
-
R2.info(`Audio copied to ${c2.accent(
|
|
80069
|
+
copyFileSync5(audioPath, resolve26(destDir, basename8(audioPath)));
|
|
80070
|
+
R2.info(`Audio copied to ${c2.accent(basename8(audioPath))}`);
|
|
80007
80071
|
}
|
|
80008
80072
|
if (sourceFilePath) {
|
|
80009
80073
|
const transcribeChoice = await ue({
|
|
@@ -80565,10 +80629,10 @@ var init_format = __esm({
|
|
|
80565
80629
|
|
|
80566
80630
|
// src/utils/project.ts
|
|
80567
80631
|
import { existsSync as existsSync52, statSync as statSync18 } from "fs";
|
|
80568
|
-
import { resolve as resolve29, basename as
|
|
80632
|
+
import { resolve as resolve29, basename as basename9 } from "path";
|
|
80569
80633
|
function resolveProject(dirArg) {
|
|
80570
80634
|
const dir = resolve29(dirArg ?? ".");
|
|
80571
|
-
const name =
|
|
80635
|
+
const name = basename9(dir);
|
|
80572
80636
|
const indexPath = resolve29(dir, "index.html");
|
|
80573
80637
|
if (!existsSync52(dir) || !statSync18(dir).isDirectory()) {
|
|
80574
80638
|
errorBox("Not a directory: " + dir);
|
|
@@ -80860,7 +80924,7 @@ var init_play = __esm({
|
|
|
80860
80924
|
});
|
|
80861
80925
|
|
|
80862
80926
|
// src/utils/publishProject.ts
|
|
80863
|
-
import { basename as
|
|
80927
|
+
import { basename as basename10, join as join61, relative as relative9 } from "path";
|
|
80864
80928
|
import { readdirSync as readdirSync22, readFileSync as readFileSync38, statSync as statSync19 } from "fs";
|
|
80865
80929
|
import AdmZip from "adm-zip";
|
|
80866
80930
|
function isRecord2(value) {
|
|
@@ -81074,7 +81138,7 @@ async function publishProjectArchiveStaged(apiBaseUrl2, title, archive) {
|
|
|
81074
81138
|
return publishedProject;
|
|
81075
81139
|
}
|
|
81076
81140
|
async function publishProjectArchive(projectDir) {
|
|
81077
|
-
const title =
|
|
81141
|
+
const title = basename10(projectDir);
|
|
81078
81142
|
const archive = createPublishArchive(projectDir);
|
|
81079
81143
|
const apiBaseUrl2 = getPublishApiBaseUrl();
|
|
81080
81144
|
const stagedResult = await publishProjectArchiveStaged(apiBaseUrl2, title, archive);
|
|
@@ -81100,7 +81164,7 @@ __export(publish_exports, {
|
|
|
81100
81164
|
default: () => publish_default,
|
|
81101
81165
|
examples: () => examples6
|
|
81102
81166
|
});
|
|
81103
|
-
import { basename as
|
|
81167
|
+
import { basename as basename11, resolve as resolve31 } from "path";
|
|
81104
81168
|
import { existsSync as existsSync54 } from "fs";
|
|
81105
81169
|
import { join as join62 } from "path";
|
|
81106
81170
|
var examples6, publish_default;
|
|
@@ -81136,7 +81200,7 @@ var init_publish = __esm({
|
|
|
81136
81200
|
const rawArg = args.dir;
|
|
81137
81201
|
const dir = resolve31(rawArg ?? ".");
|
|
81138
81202
|
const isImplicitCwd = !rawArg || rawArg === "." || rawArg === "./";
|
|
81139
|
-
const projectName = isImplicitCwd ?
|
|
81203
|
+
const projectName = isImplicitCwd ? basename11(process.env["PWD"] ?? dir) : basename11(dir);
|
|
81140
81204
|
const indexPath = join62(dir, "index.html");
|
|
81141
81205
|
if (existsSync54(indexPath)) {
|
|
81142
81206
|
const lintResult = await lintProject({ dir, name: projectName, indexPath });
|
|
@@ -81559,7 +81623,7 @@ __export(render_exports, {
|
|
|
81559
81623
|
});
|
|
81560
81624
|
import { mkdirSync as mkdirSync32, readdirSync as readdirSync23, readFileSync as readFileSync40, statSync as statSync20, writeFileSync as writeFileSync27, rmSync as rmSync14 } from "fs";
|
|
81561
81625
|
import { cpus as cpus4, freemem as freemem4, tmpdir as tmpdir5 } from "os";
|
|
81562
|
-
import { resolve as resolve33, dirname as dirname22, join as join63, basename as
|
|
81626
|
+
import { resolve as resolve33, dirname as dirname22, join as join63, basename as basename12 } from "path";
|
|
81563
81627
|
import { execFileSync as execFileSync6, spawn as spawn13 } from "child_process";
|
|
81564
81628
|
function formatFpsParseError(input2, reason) {
|
|
81565
81629
|
switch (reason) {
|
|
@@ -81663,7 +81727,7 @@ async function renderDocker(projectDir, outputPath, options) {
|
|
|
81663
81727
|
process.exit(1);
|
|
81664
81728
|
}
|
|
81665
81729
|
const outputDir = dirname22(outputPath);
|
|
81666
|
-
const outputFilename =
|
|
81730
|
+
const outputFilename = basename12(outputPath);
|
|
81667
81731
|
const dockerArgs = buildDockerRunArgs({
|
|
81668
81732
|
imageTag,
|
|
81669
81733
|
projectDir: resolve33(projectDir),
|
|
@@ -84652,7 +84716,7 @@ __export(synthesize_exports, {
|
|
|
84652
84716
|
});
|
|
84653
84717
|
import { execFileSync as execFileSync7 } from "child_process";
|
|
84654
84718
|
import { existsSync as existsSync63, writeFileSync as writeFileSync29, mkdirSync as mkdirSync35, readdirSync as readdirSync25, unlinkSync as unlinkSync6 } from "fs";
|
|
84655
|
-
import { join as join70, dirname as dirname26, basename as
|
|
84719
|
+
import { join as join70, dirname as dirname26, basename as basename13 } from "path";
|
|
84656
84720
|
import { homedir as homedir11 } from "os";
|
|
84657
84721
|
function findPython() {
|
|
84658
84722
|
for (const name of ["python3", "python"]) {
|
|
@@ -84691,7 +84755,7 @@ function ensureSynthScript() {
|
|
|
84691
84755
|
if (!existsSync63(SCRIPT_PATH)) {
|
|
84692
84756
|
mkdirSync35(SCRIPT_DIR, { recursive: true });
|
|
84693
84757
|
writeFileSync29(SCRIPT_PATH, SYNTH_SCRIPT);
|
|
84694
|
-
const currentName =
|
|
84758
|
+
const currentName = basename13(SCRIPT_PATH);
|
|
84695
84759
|
try {
|
|
84696
84760
|
for (const entry of readdirSync25(SCRIPT_DIR)) {
|
|
84697
84761
|
if (entry !== currentName && /^synth(-v\d+)?\.py$/.test(entry)) {
|
|
@@ -85963,7 +86027,7 @@ __export(contactSheet_exports, {
|
|
|
85963
86027
|
});
|
|
85964
86028
|
import sharp from "sharp";
|
|
85965
86029
|
import { readdirSync as readdirSync26, readFileSync as readFileSync48, writeFileSync as writeFileSync30, unlinkSync as unlinkSync7, existsSync as existsSync67 } from "fs";
|
|
85966
|
-
import { join as join73, extname as extname13, basename as
|
|
86030
|
+
import { join as join73, extname as extname13, basename as basename14, dirname as dirname29 } from "path";
|
|
85967
86031
|
async function createContactSheet(imagePaths, outputPath, opts = {}) {
|
|
85968
86032
|
const {
|
|
85969
86033
|
cols = 3,
|
|
@@ -85996,7 +86060,7 @@ async function createContactSheet(imagePaths, outputPath, opts = {}) {
|
|
|
85996
86060
|
overlays.push({ input: resized, left: x3, top: y + labelH });
|
|
85997
86061
|
let labelText = `${i2 + 1}`;
|
|
85998
86062
|
if (labelMode === "filename") {
|
|
85999
|
-
labelText = `${i2 + 1}. ${
|
|
86063
|
+
labelText = `${i2 + 1}. ${basename14(files[i2]).replace(extname13(files[i2]), "")}`;
|
|
86000
86064
|
} else if (labelMode === "custom" && labels?.[i2]) {
|
|
86001
86065
|
labelText = `${i2 + 1}. ${labels[i2]}`;
|
|
86002
86066
|
}
|
|
@@ -93094,7 +93158,7 @@ var require_node_domexception = __commonJS({
|
|
|
93094
93158
|
|
|
93095
93159
|
// ../../node_modules/.bun/fetch-blob@3.2.0/node_modules/fetch-blob/from.js
|
|
93096
93160
|
import { statSync as statSync23, createReadStream as createReadStream2, promises as fs2 } from "fs";
|
|
93097
|
-
import { basename as
|
|
93161
|
+
import { basename as basename15 } from "path";
|
|
93098
93162
|
var import_node_domexception, stat, blobFromSync, blobFrom, fileFrom, fileFromSync, fromBlob, fromFile, BlobDataItem;
|
|
93099
93163
|
var init_from = __esm({
|
|
93100
93164
|
"../../node_modules/.bun/fetch-blob@3.2.0/node_modules/fetch-blob/from.js"() {
|
|
@@ -93118,7 +93182,7 @@ var init_from = __esm({
|
|
|
93118
93182
|
size: stat3.size,
|
|
93119
93183
|
lastModified: stat3.mtimeMs,
|
|
93120
93184
|
start: 0
|
|
93121
|
-
})],
|
|
93185
|
+
})], basename15(path2), { type, lastModified: stat3.mtimeMs });
|
|
93122
93186
|
BlobDataItem = class _BlobDataItem {
|
|
93123
93187
|
#path;
|
|
93124
93188
|
#start;
|
|
@@ -131852,6 +131916,57 @@ ${HELP}`);
|
|
|
131852
131916
|
}
|
|
131853
131917
|
});
|
|
131854
131918
|
|
|
131919
|
+
// src/cloud/detectAspectRatio.ts
|
|
131920
|
+
import { readFileSync as readFileSync58 } from "fs";
|
|
131921
|
+
function extractAttributeNumber(tag, re2) {
|
|
131922
|
+
const match = tag.match(re2);
|
|
131923
|
+
if (!match) return null;
|
|
131924
|
+
const raw = match[1] ?? match[2] ?? match[3];
|
|
131925
|
+
if (raw === void 0) return null;
|
|
131926
|
+
const value = Number(raw);
|
|
131927
|
+
return Number.isFinite(value) ? value : null;
|
|
131928
|
+
}
|
|
131929
|
+
function detectAspectRatioFromHtml(entryHtmlPath) {
|
|
131930
|
+
let html;
|
|
131931
|
+
try {
|
|
131932
|
+
html = readFileSync58(entryHtmlPath, "utf-8");
|
|
131933
|
+
} catch (err) {
|
|
131934
|
+
return { kind: "read-error", error: err instanceof Error ? err.message : String(err) };
|
|
131935
|
+
}
|
|
131936
|
+
return detectAspectRatioFromHtmlString(html);
|
|
131937
|
+
}
|
|
131938
|
+
function detectAspectRatioFromHtmlString(html) {
|
|
131939
|
+
const tagMatch = html.match(ROOT_COMPOSITION_DIV_RE);
|
|
131940
|
+
if (!tagMatch) return { kind: "no-root-div" };
|
|
131941
|
+
const openTag = tagMatch[0];
|
|
131942
|
+
const width = extractAttributeNumber(openTag, DATA_WIDTH_RE);
|
|
131943
|
+
const height = extractAttributeNumber(openTag, DATA_HEIGHT_RE);
|
|
131944
|
+
if (width === null || height === null) return { kind: "no-dims" };
|
|
131945
|
+
if (width <= 0 || height <= 0) return { kind: "invalid-dims", width, height };
|
|
131946
|
+
const ratio = width / height;
|
|
131947
|
+
for (const candidate of SUPPORTED_RATIOS) {
|
|
131948
|
+
if (Math.abs(ratio - candidate.ratio) <= RATIO_TOLERANCE) {
|
|
131949
|
+
return { kind: "matched", aspectRatio: candidate.value, width, height };
|
|
131950
|
+
}
|
|
131951
|
+
}
|
|
131952
|
+
return { kind: "no-match", width, height, ratio };
|
|
131953
|
+
}
|
|
131954
|
+
var RATIO_TOLERANCE, SUPPORTED_RATIOS, ROOT_COMPOSITION_DIV_RE, DATA_WIDTH_RE, DATA_HEIGHT_RE;
|
|
131955
|
+
var init_detectAspectRatio = __esm({
|
|
131956
|
+
"src/cloud/detectAspectRatio.ts"() {
|
|
131957
|
+
"use strict";
|
|
131958
|
+
RATIO_TOLERANCE = 0.05;
|
|
131959
|
+
SUPPORTED_RATIOS = [
|
|
131960
|
+
{ value: "16:9", ratio: 16 / 9 },
|
|
131961
|
+
{ value: "9:16", ratio: 9 / 16 },
|
|
131962
|
+
{ value: "1:1", ratio: 1 }
|
|
131963
|
+
];
|
|
131964
|
+
ROOT_COMPOSITION_DIV_RE = /<div\b[^>]*?\bdata-composition-id\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+)[^>]*>/i;
|
|
131965
|
+
DATA_WIDTH_RE = /\bdata-width\s*=\s*(?:"(\d+(?:\.\d+)?)"|'(\d+(?:\.\d+)?)'|(\d+(?:\.\d+)?))(?=\s|>|\/)/i;
|
|
131966
|
+
DATA_HEIGHT_RE = /\bdata-height\s*=\s*(?:"(\d+(?:\.\d+)?)"|'(\d+(?:\.\d+)?)'|(\d+(?:\.\d+)?))(?=\s|>|\/)/i;
|
|
131967
|
+
}
|
|
131968
|
+
});
|
|
131969
|
+
|
|
131855
131970
|
// src/cloud/poll.ts
|
|
131856
131971
|
function isTerminal(status) {
|
|
131857
131972
|
return TERMINAL_STATUSES.has(status);
|
|
@@ -133307,6 +133422,40 @@ function resolveProjectInput(opts) {
|
|
|
133307
133422
|
if (explicit.url) return { kind: "url", url: opts.url };
|
|
133308
133423
|
return { kind: "dir", dir: opts.dir ?? "." };
|
|
133309
133424
|
}
|
|
133425
|
+
function maybeAutoDetectAspectRatio(project, compositionArg, asJson) {
|
|
133426
|
+
if (project.kind !== "dir") {
|
|
133427
|
+
const reason = project.kind === "asset_id" ? "--asset-id" : "--url";
|
|
133428
|
+
logDetection(asJson, `Auto-detect skipped (project is ${reason})`);
|
|
133429
|
+
return void 0;
|
|
133430
|
+
}
|
|
133431
|
+
const dir = project.dir ?? ".";
|
|
133432
|
+
const entryRelative = compositionArg ?? "index.html";
|
|
133433
|
+
const entryPath = resolvePath4(dir, entryRelative);
|
|
133434
|
+
const detection = detectAspectRatioFromHtml(entryPath);
|
|
133435
|
+
logDetection(asJson, summarizeDetection(detection, entryRelative));
|
|
133436
|
+
return detection.kind === "matched" ? detection.aspectRatio : void 0;
|
|
133437
|
+
}
|
|
133438
|
+
function logDetection(asJson, message) {
|
|
133439
|
+
if (asJson) return;
|
|
133440
|
+
const suffix = message.startsWith("Detected aspect ratio") ? "" : `; ${ASPECT_FALLBACK_HINT}`;
|
|
133441
|
+
console.log(c2.dim(` ${message}${suffix}`));
|
|
133442
|
+
}
|
|
133443
|
+
function summarizeDetection(detection, entryRelative) {
|
|
133444
|
+
switch (detection.kind) {
|
|
133445
|
+
case "matched":
|
|
133446
|
+
return `Detected aspect ratio: ${detection.aspectRatio} (from ${entryRelative} dims ${detection.width}\xD7${detection.height})`;
|
|
133447
|
+
case "no-root-div":
|
|
133448
|
+
return `No <div data-composition-id> found in ${entryRelative}`;
|
|
133449
|
+
case "no-dims":
|
|
133450
|
+
return `${entryRelative} root composition has no data-width / data-height`;
|
|
133451
|
+
case "invalid-dims":
|
|
133452
|
+
return `${entryRelative} root has invalid dims (${detection.width}\xD7${detection.height})`;
|
|
133453
|
+
case "no-match":
|
|
133454
|
+
return `${entryRelative} dims ${detection.width}\xD7${detection.height} (ratio ${detection.ratio.toFixed(2)}) don't match 16:9, 9:16, or 1:1`;
|
|
133455
|
+
case "read-error":
|
|
133456
|
+
return `Couldn't read ${entryRelative} for aspect-ratio detection (${detection.error})`;
|
|
133457
|
+
}
|
|
133458
|
+
}
|
|
133310
133459
|
function resolveVariablesAndValidateIfLocal(inline, filePath, strict, source) {
|
|
133311
133460
|
const variables = resolveVariablesArg(inline, filePath);
|
|
133312
133461
|
if (!variables || Object.keys(variables).length === 0) return variables;
|
|
@@ -133384,6 +133533,7 @@ function buildRenderBody(opts) {
|
|
|
133384
133533
|
if (opts.quality !== void 0) body.quality = opts.quality;
|
|
133385
133534
|
if (opts.format !== void 0) body.format = opts.format;
|
|
133386
133535
|
if (opts.resolution !== void 0) body.resolution = opts.resolution;
|
|
133536
|
+
if (opts.aspectRatio !== void 0) body.aspect_ratio = opts.aspectRatio;
|
|
133387
133537
|
if (opts.composition !== void 0) body.composition = opts.composition;
|
|
133388
133538
|
if (opts.variables !== void 0) body.variables = opts.variables;
|
|
133389
133539
|
if (opts.title !== void 0) body.title = opts.title;
|
|
@@ -133476,11 +133626,12 @@ async function streamVideo(url, destPath, asJson) {
|
|
|
133476
133626
|
process.exit(1);
|
|
133477
133627
|
}
|
|
133478
133628
|
}
|
|
133479
|
-
var VALID_QUALITY2, VALID_FORMAT2, VALID_RESOLUTION, FORMAT_EXT2, examples26, render_default2, IDEMPOTENCY_KEY_RE;
|
|
133629
|
+
var VALID_QUALITY2, VALID_FORMAT2, VALID_RESOLUTION, VALID_ASPECT_RATIO, FORMAT_EXT2, examples26, render_default2, IDEMPOTENCY_KEY_RE, ASPECT_FALLBACK_HINT;
|
|
133480
133630
|
var init_render4 = __esm({
|
|
133481
133631
|
"src/commands/cloud/render.ts"() {
|
|
133482
133632
|
"use strict";
|
|
133483
133633
|
init_dist();
|
|
133634
|
+
init_detectAspectRatio();
|
|
133484
133635
|
init_colors();
|
|
133485
133636
|
init_format();
|
|
133486
133637
|
init_project();
|
|
@@ -133493,14 +133644,8 @@ var init_render4 = __esm({
|
|
|
133493
133644
|
init_statusColor();
|
|
133494
133645
|
VALID_QUALITY2 = ["draft", "standard", "high"];
|
|
133495
133646
|
VALID_FORMAT2 = ["mp4", "webm", "mov"];
|
|
133496
|
-
VALID_RESOLUTION = [
|
|
133497
|
-
|
|
133498
|
-
"portrait",
|
|
133499
|
-
"landscape-4k",
|
|
133500
|
-
"portrait-4k",
|
|
133501
|
-
"square",
|
|
133502
|
-
"square-4k"
|
|
133503
|
-
];
|
|
133647
|
+
VALID_RESOLUTION = ["1080p", "4k"];
|
|
133648
|
+
VALID_ASPECT_RATIO = ["16:9", "9:16", "1:1"];
|
|
133504
133649
|
FORMAT_EXT2 = { mp4: ".mp4", webm: ".webm", mov: ".mov" };
|
|
133505
133650
|
examples26 = [
|
|
133506
133651
|
["Render the current directory in the cloud", "hyperframes cloud render"],
|
|
@@ -133528,7 +133673,11 @@ var init_render4 = __esm({
|
|
|
133528
133673
|
format: { type: "string", description: "mp4 | webm | mov (default: mp4)" },
|
|
133529
133674
|
resolution: {
|
|
133530
133675
|
type: "string",
|
|
133531
|
-
description: "Resolution
|
|
133676
|
+
description: "Resolution tier: 1080p | 4k (default: 1080p; 4k is billed at 1.5x)"
|
|
133677
|
+
},
|
|
133678
|
+
"aspect-ratio": {
|
|
133679
|
+
type: "string",
|
|
133680
|
+
description: "Aspect ratio: 16:9 | 9:16 | 1:1 (default: 16:9)"
|
|
133532
133681
|
},
|
|
133533
133682
|
composition: {
|
|
133534
133683
|
type: "string",
|
|
@@ -133611,6 +133760,9 @@ var init_render4 = __esm({
|
|
|
133611
133760
|
const resolution = parseEnumFlag(args.resolution, VALID_RESOLUTION, {
|
|
133612
133761
|
flag: "--resolution"
|
|
133613
133762
|
});
|
|
133763
|
+
const explicitAspectRatio = parseEnumFlag(args["aspect-ratio"], VALID_ASPECT_RATIO, {
|
|
133764
|
+
flag: "--aspect-ratio"
|
|
133765
|
+
});
|
|
133614
133766
|
const pollIntervalMs = parsePollIntervalMs(args["poll-interval"]);
|
|
133615
133767
|
const maxWaitMs = parseMaxWaitMs(args["max-wait"]);
|
|
133616
133768
|
validateIdempotencyKey(args["idempotency-key"]);
|
|
@@ -133619,6 +133771,7 @@ var init_render4 = __esm({
|
|
|
133619
133771
|
assetId: args["asset-id"],
|
|
133620
133772
|
url: args.url
|
|
133621
133773
|
});
|
|
133774
|
+
const aspectRatio = explicitAspectRatio ?? maybeAutoDetectAspectRatio(project, args.composition, asJson);
|
|
133622
133775
|
const variables = resolveVariablesAndValidateIfLocal(
|
|
133623
133776
|
args.variables,
|
|
133624
133777
|
args["variables-file"],
|
|
@@ -133633,6 +133786,7 @@ var init_render4 = __esm({
|
|
|
133633
133786
|
quality,
|
|
133634
133787
|
format,
|
|
133635
133788
|
resolution,
|
|
133789
|
+
aspectRatio,
|
|
133636
133790
|
composition: args.composition,
|
|
133637
133791
|
variables,
|
|
133638
133792
|
title: args.title,
|
|
@@ -133693,6 +133847,7 @@ var init_render4 = __esm({
|
|
|
133693
133847
|
}
|
|
133694
133848
|
});
|
|
133695
133849
|
IDEMPOTENCY_KEY_RE = /^[A-Za-z0-9_:.-]{1,255}$/;
|
|
133850
|
+
ASPECT_FALLBACK_HINT = "server will default aspect_ratio to 16:9. Pass --aspect-ratio to override.";
|
|
133696
133851
|
}
|
|
133697
133852
|
});
|
|
133698
133853
|
|
|
@@ -135077,10 +135232,10 @@ if (rootVersionRequested) {
|
|
|
135077
135232
|
process.exit(0);
|
|
135078
135233
|
}
|
|
135079
135234
|
try {
|
|
135080
|
-
const { readFileSync:
|
|
135235
|
+
const { readFileSync: readFileSync59 } = await import("fs");
|
|
135081
135236
|
const { resolve: resolve46 } = await import("path");
|
|
135082
135237
|
const envPath = resolve46(process.cwd(), ".env");
|
|
135083
|
-
const envContent =
|
|
135238
|
+
const envContent = readFileSync59(envPath, "utf-8");
|
|
135084
135239
|
for (const rawLine of envContent.split("\n")) {
|
|
135085
135240
|
let line = rawLine.trim();
|
|
135086
135241
|
if (!line || line.startsWith("#")) continue;
|
|
@@ -181,38 +181,23 @@ The slide distance DECAYS per word (80→12px) — mimics a camera settling.
|
|
|
181
181
|
Vector animations that play inside a composition. Use for logos, character animations, icons.
|
|
182
182
|
|
|
183
183
|
```html
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
The element tag is <dotlottie-wc>. -->
|
|
187
|
-
<script
|
|
188
|
-
src="https://cdn.jsdelivr.net/npm/@lottiefiles/dotlottie-wc/dist/dotlottie-wc.js"
|
|
189
|
-
type="module"
|
|
190
|
-
></script>
|
|
191
|
-
<dotlottie-wc
|
|
192
|
-
class="lottie"
|
|
193
|
-
src="capture/assets/lottie/animation-0.json"
|
|
194
|
-
autoplay
|
|
195
|
-
loop
|
|
196
|
-
speed="1.5"
|
|
197
|
-
style="width:500px;height:500px;"
|
|
198
|
-
>
|
|
199
|
-
</dotlottie-wc>
|
|
184
|
+
<div id="anim" class="lottie"></div>
|
|
185
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/bodymovin/5.12.2/lottie.min.js"></script>
|
|
200
186
|
<script>
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
187
|
+
window.__hfLottie = window.__hfLottie || [];
|
|
188
|
+
|
|
189
|
+
const anim = lottie.loadAnimation({
|
|
190
|
+
container: document.getElementById("anim"),
|
|
191
|
+
renderer: "svg",
|
|
192
|
+
loop: false,
|
|
193
|
+
autoplay: false,
|
|
194
|
+
path: "capture/assets/lottie/animation-0.json",
|
|
195
|
+
});
|
|
196
|
+
window.__hfLottie.push(anim);
|
|
207
197
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
renderer: "svg",
|
|
212
|
-
loop: false,
|
|
213
|
-
autoplay: false,
|
|
214
|
-
path: "capture/assets/lottie/animation-0.json",
|
|
215
|
-
});
|
|
198
|
+
gsap.set("#anim", { scale: 0.3, opacity: 0 });
|
|
199
|
+
tl.to("#anim", { scale: 1, opacity: 1, duration: 0.35, ease: "back.out(1.6)" }, 0.2);
|
|
200
|
+
</script>
|
|
216
201
|
```
|
|
217
202
|
|
|
218
203
|
---
|