hyperframes 0.6.54 → 0.6.56

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 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.54" : "0.0.0-dev";
53
+ VERSION = true ? "0.6.56" : "0.0.0-dev";
54
54
  }
55
55
  });
56
56
 
@@ -3094,18 +3094,18 @@ function serializeValue(value) {
3094
3094
  }
3095
3095
  function serializeObject(obj) {
3096
3096
  const entries2 = Object.entries(obj).map(([key2, value]) => {
3097
- const safeKey = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key2) ? key2 : JSON.stringify(key2);
3098
- return `${safeKey}: ${serializeValue(value)}`;
3097
+ const safeKey2 = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key2) ? key2 : JSON.stringify(key2);
3098
+ return `${safeKey2}: ${serializeValue(value)}`;
3099
3099
  });
3100
3100
  return `{ ${entries2.join(", ")} }`;
3101
3101
  }
3102
3102
  function serializeExtras(extras) {
3103
3103
  return Object.entries(extras).map(([key2, value]) => {
3104
- const safeKey = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key2) ? key2 : JSON.stringify(key2);
3105
- return `${safeKey}: ${serializeValue(value)}`;
3104
+ const safeKey2 = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key2) ? key2 : JSON.stringify(key2);
3105
+ return `${safeKey2}: ${serializeValue(value)}`;
3106
3106
  }).join(", ");
3107
3107
  }
3108
- function getAnimationsForElement(animations, elementId) {
3108
+ function getAnimationsForElementId(animations, elementId) {
3109
3109
  const selector = `#${elementId}`;
3110
3110
  return animations.filter((a) => a.targetSelector === selector);
3111
3111
  }
@@ -35082,7 +35082,7 @@ __export(gsapParser_exports, {
35082
35082
  SUPPORTED_EASES: () => SUPPORTED_EASES,
35083
35083
  SUPPORTED_PROPS: () => SUPPORTED_PROPS,
35084
35084
  addAnimationToScript: () => addAnimationToScript,
35085
- getAnimationsForElement: () => getAnimationsForElement,
35085
+ getAnimationsForElementId: () => getAnimationsForElementId,
35086
35086
  gsapAnimationsToKeyframes: () => gsapAnimationsToKeyframes,
35087
35087
  keyframesToGsapAnimations: () => keyframesToGsapAnimations,
35088
35088
  parseGsapScript: () => parseGsapScript,
@@ -35156,6 +35156,112 @@ function resolveNode(node, scope) {
35156
35156
  function extractLiteralValue(node, scope) {
35157
35157
  return resolveNode(node, scope);
35158
35158
  }
35159
+ function selectorFromQueryCall(node, scope) {
35160
+ if (node?.type !== "CallExpression") return null;
35161
+ const callee = node.callee;
35162
+ if (callee?.type !== "MemberExpression" || callee.property?.type !== "Identifier") return null;
35163
+ const method = callee.property.name;
35164
+ const argValue = resolveNode(node.arguments?.[0], scope);
35165
+ if (typeof argValue !== "string" || argValue.length === 0) return null;
35166
+ if (QUERY_METHODS.has(method) || method === "toArray") return argValue;
35167
+ if (method === "getElementById") return `#${argValue}`;
35168
+ return null;
35169
+ }
35170
+ function enclosingScopeNode(path2) {
35171
+ let p2 = path2?.parentPath;
35172
+ while (p2) {
35173
+ if (SCOPE_NODE_TYPES.has(p2.node?.type)) return p2.node;
35174
+ p2 = p2.parentPath;
35175
+ }
35176
+ return null;
35177
+ }
35178
+ function scopeChainOf(path2) {
35179
+ const chain = [];
35180
+ let p2 = path2;
35181
+ while (p2) {
35182
+ if (SCOPE_NODE_TYPES.has(p2.node?.type)) chain.push(p2.node);
35183
+ p2 = p2.parentPath;
35184
+ }
35185
+ return chain;
35186
+ }
35187
+ function addBinding(bindings, scopeNode, name, selector) {
35188
+ let scoped = bindings.get(scopeNode);
35189
+ if (!scoped) {
35190
+ scoped = /* @__PURE__ */ new Map();
35191
+ bindings.set(scopeNode, scoped);
35192
+ }
35193
+ if (!scoped.has(name)) scoped.set(name, selector);
35194
+ }
35195
+ function collectTargetBindings(ast, scope) {
35196
+ const bindings = /* @__PURE__ */ new Map();
35197
+ recast.types.visit(ast, {
35198
+ visitVariableDeclarator(path2) {
35199
+ const name = path2.node.id?.name;
35200
+ const selector = selectorFromQueryCall(path2.node.init, scope);
35201
+ if (name && selector !== null) addBinding(bindings, enclosingScopeNode(path2), name, selector);
35202
+ this.traverse(path2);
35203
+ },
35204
+ visitAssignmentExpression(path2) {
35205
+ const left = path2.node.left;
35206
+ const selector = selectorFromQueryCall(path2.node.right, scope);
35207
+ if (left?.type === "Identifier" && selector !== null) {
35208
+ addBinding(bindings, enclosingScopeNode(path2), left.name, selector);
35209
+ }
35210
+ this.traverse(path2);
35211
+ }
35212
+ });
35213
+ recast.types.visit(ast, {
35214
+ visitCallExpression(path2) {
35215
+ const node = path2.node;
35216
+ const callee = node.callee;
35217
+ if (callee?.type === "MemberExpression" && callee.property?.type === "Identifier" && ITERATION_METHODS.has(callee.property.name)) {
35218
+ const collectionSelector = resolveCollectionSelector(callee.object, path2, scope, bindings);
35219
+ const fn = node.arguments?.[0];
35220
+ const param = fn?.params?.[0];
35221
+ if (collectionSelector && param?.type === "Identifier" && isFunctionNode(fn)) {
35222
+ addBinding(bindings, fn, param.name, collectionSelector);
35223
+ }
35224
+ }
35225
+ this.traverse(path2);
35226
+ }
35227
+ });
35228
+ return bindings;
35229
+ }
35230
+ function isFunctionNode(node) {
35231
+ return node?.type === "ArrowFunctionExpression" || node?.type === "FunctionExpression" || node?.type === "FunctionDeclaration";
35232
+ }
35233
+ function resolveCollectionSelector(node, callPath, scope, bindings) {
35234
+ if (node?.type === "Identifier") return lookupBinding(node.name, callPath, bindings);
35235
+ if (node?.type === "CallExpression") return selectorFromQueryCall(node, scope);
35236
+ return null;
35237
+ }
35238
+ function lookupBinding(name, path2, bindings) {
35239
+ for (const scopeNode of scopeChainOf(path2)) {
35240
+ const selector = bindings.get(scopeNode)?.get(name);
35241
+ if (selector !== void 0) return selector;
35242
+ }
35243
+ return null;
35244
+ }
35245
+ function resolveTargetSelector(node, path2, scope, bindings) {
35246
+ if (!node) return null;
35247
+ if (node.type === "StringLiteral" || node.type === "Literal") {
35248
+ return typeof node.value === "string" ? node.value : null;
35249
+ }
35250
+ if (node.type === "Identifier") {
35251
+ return lookupBinding(node.name, path2, bindings);
35252
+ }
35253
+ if (node.type === "CallExpression") {
35254
+ return selectorFromQueryCall(node, scope);
35255
+ }
35256
+ if (node.type === "ArrayExpression") {
35257
+ const parts = node.elements.map((el) => resolveTargetSelector(el, path2, scope, bindings)).filter((s2) => typeof s2 === "string" && s2.length > 0);
35258
+ return parts.length > 0 ? parts.join(", ") : null;
35259
+ }
35260
+ if (node.type === "MemberExpression" && node.object?.type === "Identifier") {
35261
+ return lookupBinding(node.object.name, path2, bindings);
35262
+ }
35263
+ return null;
35264
+ }
35159
35265
  function objectExpressionToRecord(node, scope) {
35160
35266
  const result = {};
35161
35267
  if (node?.type !== "ObjectExpression") return result;
@@ -35199,13 +35305,20 @@ function findTimelineVar(ast) {
35199
35305
  });
35200
35306
  return { timelineVar, timelineCount };
35201
35307
  }
35202
- function findAllTweenCalls(ast, timelineVar) {
35308
+ function isTimelineRootedCall(callNode, timelineVar) {
35309
+ let obj = callNode.callee?.object;
35310
+ while (obj?.type === "CallExpression") {
35311
+ obj = obj.callee?.object;
35312
+ }
35313
+ return obj?.type === "Identifier" && obj.name === timelineVar;
35314
+ }
35315
+ function findAllTweenCalls(ast, timelineVar, scope, targetBindings) {
35203
35316
  const results = [];
35204
35317
  recast.types.visit(ast, {
35205
35318
  visitCallExpression(path2) {
35206
35319
  const node = path2.node;
35207
35320
  const callee = node.callee;
35208
- if (callee?.type === "MemberExpression" && callee.object?.type === "Identifier" && callee.object.name === timelineVar && callee.property?.type === "Identifier") {
35321
+ if (callee?.type === "MemberExpression" && callee.property?.type === "Identifier" && isTimelineRootedCall(node, timelineVar)) {
35209
35322
  const method = callee.property.name;
35210
35323
  if (!GSAP_METHODS.has(method)) {
35211
35324
  this.traverse(path2);
@@ -35216,8 +35329,7 @@ function findAllTweenCalls(ast, timelineVar) {
35216
35329
  this.traverse(path2);
35217
35330
  return;
35218
35331
  }
35219
- const selectorArg = args[0];
35220
- const selectorValue = selectorArg.type === "StringLiteral" || selectorArg.type === "Literal" ? String(selectorArg.value) : null;
35332
+ const selectorValue = resolveTargetSelector(args[0], path2, scope, targetBindings);
35221
35333
  if (!selectorValue) {
35222
35334
  this.traverse(path2);
35223
35335
  return;
@@ -35316,14 +35428,25 @@ function assignStableIds(anims) {
35316
35428
  return { ...anim, id };
35317
35429
  });
35318
35430
  }
35431
+ function parseGsapAst(script) {
35432
+ const ast = parseScript(script);
35433
+ const scope = collectScopeBindings(ast);
35434
+ const targetBindings = collectTargetBindings(ast, scope);
35435
+ const detection = findTimelineVar(ast);
35436
+ const timelineVar = detection.timelineVar ?? "tl";
35437
+ const calls = findAllTweenCalls(ast, timelineVar, scope, targetBindings);
35438
+ const animations = assignStableIds(calls.map((call) => tweenCallToAnimation(call, scope)));
35439
+ const located = animations.map((animation, i2) => ({
35440
+ id: animation.id,
35441
+ call: calls[i2],
35442
+ animation
35443
+ }));
35444
+ return { ast, scope, timelineVar, detection, located };
35445
+ }
35319
35446
  function parseGsapScript(script) {
35320
35447
  try {
35321
- const ast = parseScript(script);
35322
- const scope = collectScopeBindings(ast);
35323
- const detection = findTimelineVar(ast);
35324
- const timelineVar = detection.timelineVar ?? "tl";
35325
- const calls = findAllTweenCalls(ast, timelineVar);
35326
- const animations = assignStableIds(calls.map((call) => tweenCallToAnimation(call, scope)));
35448
+ const { detection, timelineVar, located } = parseGsapAst(script);
35449
+ const animations = located.map((l) => l.animation);
35327
35450
  const timelineMatch = script.match(
35328
35451
  new RegExp(
35329
35452
  `^[\\s\\S]*?(?:const|let|var)\\s+${timelineVar}\\s*=\\s*gsap\\.timeline\\s*\\([^)]*\\)\\s*;?`
@@ -35348,52 +35471,203 @@ function parseGsapScript(script) {
35348
35471
  return { animations: [], timelineVar: "tl", preamble: "", postamble: "" };
35349
35472
  }
35350
35473
  }
35351
- function isParseFailure(parsed) {
35352
- return parsed.animations.length === 0 && !parsed.preamble;
35474
+ function valueToCode(value) {
35475
+ if (typeof value === "string" && value.startsWith("__raw:")) return value.slice(6);
35476
+ if (typeof value === "string") return JSON.stringify(value);
35477
+ return String(value);
35353
35478
  }
35354
- function updateAnimationInScript(script, animationId, updates) {
35355
- const parsed = parseGsapScript(script);
35356
- if (isParseFailure(parsed)) return script;
35357
- const updated = parsed.animations.map(
35358
- (anim) => anim.id === animationId ? { ...anim, ...updates } : anim
35479
+ function safeKey(key2) {
35480
+ return /^[A-Za-z_$][\w$]*$/.test(key2) ? key2 : JSON.stringify(key2);
35481
+ }
35482
+ function parseExpr(code) {
35483
+ return parseScript(`__hf__ = ${code};`).program.body[0].expression.right;
35484
+ }
35485
+ function propKeyName(prop2) {
35486
+ return prop2?.key?.name ?? prop2?.key?.value;
35487
+ }
35488
+ function isObjectProperty(prop2) {
35489
+ return prop2?.type === "ObjectProperty" || prop2?.type === "Property";
35490
+ }
35491
+ function isEditablePropertyKey(key2) {
35492
+ return !BUILTIN_VAR_KEYS.has(key2) && !DROPPED_VAR_KEYS.has(key2) && !EXTRAS_KEYS.has(key2);
35493
+ }
35494
+ function makeObjectProperty(key2, value) {
35495
+ const obj = parseExpr(`{ ${safeKey(key2)}: ${valueToCode(value)} }`);
35496
+ return obj.properties[0];
35497
+ }
35498
+ function setVarsKey(varsArg, key2, value) {
35499
+ if (varsArg?.type !== "ObjectExpression") return;
35500
+ const existing = varsArg.properties.find(
35501
+ (p2) => isObjectProperty(p2) && propKeyName(p2) === key2
35359
35502
  );
35360
- return serializeGsapAnimations(updated, parsed.timelineVar, {
35361
- preamble: parsed.preamble,
35362
- postamble: parsed.postamble
35503
+ if (existing) {
35504
+ existing.value = parseExpr(valueToCode(value));
35505
+ } else {
35506
+ varsArg.properties.push(makeObjectProperty(key2, value));
35507
+ }
35508
+ }
35509
+ function reconcileEditableProperties(varsArg, newProps) {
35510
+ if (varsArg?.type !== "ObjectExpression") return;
35511
+ varsArg.properties = varsArg.properties.filter((p2) => {
35512
+ if (!isObjectProperty(p2)) return true;
35513
+ const key2 = propKeyName(p2);
35514
+ if (typeof key2 !== "string") return true;
35515
+ if (!isEditablePropertyKey(key2)) return true;
35516
+ return key2 in newProps;
35363
35517
  });
35518
+ for (const [key2, value] of Object.entries(newProps)) {
35519
+ setVarsKey(varsArg, key2, value);
35520
+ }
35521
+ }
35522
+ function applyUpdatesToCall(call, updates) {
35523
+ if (updates.properties) reconcileEditableProperties(call.varsArg, updates.properties);
35524
+ if (updates.fromProperties && call.method === "fromTo") {
35525
+ reconcileEditableProperties(call.fromArg, updates.fromProperties);
35526
+ }
35527
+ if (updates.duration !== void 0) setVarsKey(call.varsArg, "duration", updates.duration);
35528
+ if (updates.ease !== void 0) setVarsKey(call.varsArg, "ease", updates.ease);
35529
+ if (updates.position !== void 0) {
35530
+ const posIdx = call.method === "fromTo" ? 3 : 2;
35531
+ call.node.arguments[posIdx] = parseExpr(valueToCode(updates.position));
35532
+ }
35533
+ }
35534
+ function findStatementPath(path2) {
35535
+ let p2 = path2;
35536
+ while (p2) {
35537
+ if (p2.node?.type === "ExpressionStatement") return p2;
35538
+ p2 = p2.parentPath;
35539
+ }
35540
+ return null;
35541
+ }
35542
+ function buildTweenStatementCode(timelineVar, anim) {
35543
+ const selector = JSON.stringify(anim.targetSelector);
35544
+ const props = { ...anim.properties };
35545
+ if (anim.method !== "set" && anim.duration !== void 0) props.duration = anim.duration;
35546
+ if (anim.ease) props.ease = anim.ease;
35547
+ const entries2 = Object.entries(props).map(([k2, v2]) => `${safeKey(k2)}: ${valueToCode(v2)}`);
35548
+ if (anim.extras) {
35549
+ for (const [k2, v2] of Object.entries(anim.extras)) {
35550
+ entries2.push(`${safeKey(k2)}: ${valueToCode(v2)}`);
35551
+ }
35552
+ }
35553
+ const objCode = `{ ${entries2.join(", ")} }`;
35554
+ const posCode = valueToCode(
35555
+ typeof anim.position === "number" ? anim.position : anim.position ?? 0
35556
+ );
35557
+ if (anim.method === "fromTo") {
35558
+ const fromEntries = Object.entries(anim.fromProperties ?? {}).map(
35559
+ ([k2, v2]) => `${safeKey(k2)}: ${valueToCode(v2)}`
35560
+ );
35561
+ const fromCode = `{ ${fromEntries.join(", ")} }`;
35562
+ return `${timelineVar}.fromTo(${selector}, ${fromCode}, ${objCode}, ${posCode});`;
35563
+ }
35564
+ return `${timelineVar}.${anim.method}(${selector}, ${objCode}, ${posCode});`;
35565
+ }
35566
+ function updateAnimationInScript(script, animationId, updates) {
35567
+ let parsed;
35568
+ try {
35569
+ parsed = parseGsapAst(script);
35570
+ } catch (e3) {
35571
+ console.warn("[gsap-parser] updateAnimationInScript parse failed:", e3);
35572
+ return script;
35573
+ }
35574
+ const target = parsed.located.find((l) => l.id === animationId);
35575
+ if (!target) return script;
35576
+ applyUpdatesToCall(target.call, updates);
35577
+ return recast.print(parsed.ast).code;
35364
35578
  }
35365
35579
  function addAnimationToScript(script, animation) {
35366
- const parsed = parseGsapScript(script);
35367
- if (isParseFailure(parsed)) return { script, id: "" };
35580
+ let parsed;
35581
+ try {
35582
+ parsed = parseGsapAst(script);
35583
+ } catch (e3) {
35584
+ console.warn("[gsap-parser] addAnimationToScript parse failed:", e3);
35585
+ return { script, id: "" };
35586
+ }
35587
+ if (parsed.located.length === 0 && parsed.detection.timelineVar === null) {
35588
+ return { script, id: "" };
35589
+ }
35368
35590
  const id = `anim-${Date.now()}`;
35369
- const newAnim = { ...animation, id };
35370
- const allAnimations = [...parsed.animations, newAnim];
35371
- return {
35372
- script: serializeGsapAnimations(allAnimations, parsed.timelineVar, {
35373
- preamble: parsed.preamble,
35374
- postamble: parsed.postamble
35375
- }),
35376
- id
35377
- };
35591
+ const statementCode = buildTweenStatementCode(parsed.timelineVar, animation);
35592
+ const newStatement = parseScript(statementCode).program.body[0];
35593
+ const lastCall = parsed.located[parsed.located.length - 1]?.call;
35594
+ const anchorPath = lastCall ? findStatementPath(lastCall.path) : findTimelineDeclarationPath(parsed.ast, parsed.timelineVar);
35595
+ if (anchorPath) {
35596
+ anchorPath.insertAfter(newStatement);
35597
+ } else {
35598
+ parsed.ast.program.body.push(newStatement);
35599
+ }
35600
+ return { script: recast.print(parsed.ast).code, id };
35378
35601
  }
35379
- function removeAnimationFromScript(script, animationId) {
35380
- const parsed = parseGsapScript(script);
35381
- if (isParseFailure(parsed)) return script;
35382
- const filtered = parsed.animations.filter((a) => a.id !== animationId);
35383
- return serializeGsapAnimations(filtered, parsed.timelineVar, {
35384
- preamble: parsed.preamble,
35385
- postamble: parsed.postamble
35602
+ function findTimelineDeclarationPath(ast, timelineVar) {
35603
+ let found = null;
35604
+ recast.types.visit(ast, {
35605
+ visitVariableDeclaration(path2) {
35606
+ if (found) return false;
35607
+ for (const decl of path2.node.declarations ?? []) {
35608
+ if (decl.id?.name === timelineVar && isGsapTimelineCall(decl.init)) {
35609
+ found = path2;
35610
+ return false;
35611
+ }
35612
+ }
35613
+ this.traverse(path2);
35614
+ }
35615
+ });
35616
+ return found;
35617
+ }
35618
+ function findChainParentCall(stmtNode, targetNode) {
35619
+ let found = null;
35620
+ recast.types.visit(stmtNode, {
35621
+ visitCallExpression(p2) {
35622
+ if (found) return false;
35623
+ if (p2.node.callee?.type === "MemberExpression" && p2.node.callee.object === targetNode) {
35624
+ found = p2.node;
35625
+ return false;
35626
+ }
35627
+ this.traverse(p2);
35628
+ }
35386
35629
  });
35630
+ return found;
35387
35631
  }
35388
- var recast, import_parser, GSAP_METHODS, BUILTIN_VAR_KEYS, DROPPED_VAR_KEYS, EXTRAS_KEYS;
35632
+ function removeAnimationFromScript(script, animationId) {
35633
+ let parsed;
35634
+ try {
35635
+ parsed = parseGsapAst(script);
35636
+ } catch (e3) {
35637
+ console.warn("[gsap-parser] removeAnimationFromScript parse failed:", e3);
35638
+ return script;
35639
+ }
35640
+ const target = parsed.located.find((l) => l.id === animationId);
35641
+ if (!target) return script;
35642
+ const node = target.call.node;
35643
+ const stmtPath = findStatementPath(target.call.path);
35644
+ if (!stmtPath) return script;
35645
+ const parentCall = findChainParentCall(stmtPath.node, node);
35646
+ if (parentCall) {
35647
+ parentCall.callee.object = node.callee.object;
35648
+ } else if (node.callee?.object?.type === "CallExpression") {
35649
+ stmtPath.node.expression = node.callee.object;
35650
+ } else {
35651
+ stmtPath.prune();
35652
+ }
35653
+ return recast.print(parsed.ast).code;
35654
+ }
35655
+ var recast, import_parser, GSAP_METHODS, QUERY_METHODS, ITERATION_METHODS, SCOPE_NODE_TYPES, BUILTIN_VAR_KEYS, DROPPED_VAR_KEYS, EXTRAS_KEYS;
35389
35656
  var init_gsapParser = __esm({
35390
35657
  "../core/src/parsers/gsapParser.ts"() {
35391
35658
  "use strict";
35392
35659
  recast = __toESM(require_main2(), 1);
35393
35660
  import_parser = __toESM(require_lib(), 1);
35394
35661
  init_gsapSerialize();
35395
- init_gsapSerialize();
35396
35662
  GSAP_METHODS = /* @__PURE__ */ new Set(["set", "to", "from", "fromTo"]);
35663
+ QUERY_METHODS = /* @__PURE__ */ new Set(["querySelector", "querySelectorAll"]);
35664
+ ITERATION_METHODS = /* @__PURE__ */ new Set(["forEach", "map"]);
35665
+ SCOPE_NODE_TYPES = /* @__PURE__ */ new Set([
35666
+ "Program",
35667
+ "FunctionDeclaration",
35668
+ "FunctionExpression",
35669
+ "ArrowFunctionExpression"
35670
+ ]);
35397
35671
  BUILTIN_VAR_KEYS = /* @__PURE__ */ new Set(["duration", "ease", "delay"]);
35398
35672
  DROPPED_VAR_KEYS = /* @__PURE__ */ new Set(["keyframes", "onComplete", "onStart", "onUpdate", "onRepeat"]);
35399
35673
  EXTRAS_KEYS = /* @__PURE__ */ new Set([
@@ -37086,122 +37360,51 @@ function readRegisteredTimelineCompositionId(script) {
37086
37360
  const match = script.match(WINDOW_TIMELINE_ASSIGN_PATTERN);
37087
37361
  return match?.[1] || null;
37088
37362
  }
37363
+ function unwrapRaw(value) {
37364
+ if (typeof value === "number") return value;
37365
+ if (typeof value !== "string") return void 0;
37366
+ const code = value.startsWith("__raw:") ? value.slice(6) : value;
37367
+ return code.replace(/^\s*["']|["']\s*$/g, "");
37368
+ }
37369
+ function extrasNumber(value) {
37370
+ const unwrapped = unwrapRaw(value);
37371
+ const numeric = typeof unwrapped === "number" ? unwrapped : Number(unwrapped);
37372
+ return Number.isFinite(numeric) ? numeric : 0;
37373
+ }
37374
+ function synthesizeWindowRaw(timelineVar, anim) {
37375
+ const entries2 = Object.entries(anim.properties).map(([k2, v2]) => {
37376
+ if (typeof v2 === "string" && v2.startsWith("__raw:")) return `${k2}: ${v2.slice(6)}`;
37377
+ return `${k2}: ${typeof v2 === "string" ? JSON.stringify(v2) : v2}`;
37378
+ });
37379
+ if (anim.duration !== void 0) entries2.push(`duration: ${anim.duration}`);
37380
+ if (anim.ease) entries2.push(`ease: ${JSON.stringify(anim.ease)}`);
37381
+ const pos = typeof anim.position === "number" ? anim.position : JSON.stringify(anim.position);
37382
+ return `${timelineVar}.${anim.method}("${anim.targetSelector}", { ${entries2.join(", ")} }, ${pos})`;
37383
+ }
37089
37384
  async function extractGsapWindows(script) {
37090
37385
  if (!/gsap\.timeline/.test(script)) return [];
37091
37386
  const parseGsapScript2 = await loadParseGsapScript();
37092
37387
  const parsed = parseGsapScript2(script);
37093
37388
  if (parsed.animations.length === 0) return [];
37094
37389
  const windows = [];
37095
- const timelineVar = parsed.timelineVar;
37096
- const methodPattern = new RegExp(
37097
- `${timelineVar}\\.(set|to|from|fromTo)\\s*\\(([^)]+(?:\\{[^}]*\\}[^)]*)+)\\)`,
37098
- "g"
37099
- );
37100
- let match;
37101
- let index = 0;
37102
- while ((match = methodPattern.exec(script)) !== null && index < parsed.animations.length) {
37103
- const raw = match[0];
37104
- const args = match[2] ?? "";
37105
- if (!/^\s*["']/.test(args)) continue;
37106
- const meta = parseGsapWindowMeta(match[1] ?? "", args);
37107
- const animation = parsed.animations[index];
37108
- index += 1;
37109
- if (!animation) continue;
37390
+ for (const animation of parsed.animations) {
37110
37391
  if (typeof animation.position !== "number") continue;
37392
+ const repeat = extrasNumber(animation.extras?.repeat);
37393
+ const cycleCount = repeat > 0 ? repeat + 1 : 1;
37394
+ const effectiveDuration = animation.method === "set" ? 0 : (animation.duration ?? 0) * cycleCount;
37111
37395
  windows.push({
37112
37396
  targetSelector: animation.targetSelector,
37113
37397
  position: animation.position,
37114
- end: animation.position + meta.effectiveDuration,
37115
- properties: meta.properties.length > 0 ? meta.properties : Object.keys(animation.properties),
37116
- propertyValues: meta.propertyValues,
37117
- overwriteAuto: meta.overwriteAuto,
37118
- method: match[1] ?? "to",
37119
- raw
37398
+ end: animation.position + effectiveDuration,
37399
+ properties: Object.keys(animation.properties),
37400
+ propertyValues: animation.properties,
37401
+ overwriteAuto: unwrapRaw(animation.extras?.overwrite) === "auto",
37402
+ method: animation.method,
37403
+ raw: synthesizeWindowRaw(parsed.timelineVar, animation)
37120
37404
  });
37121
37405
  }
37122
37406
  return windows;
37123
37407
  }
37124
- function parseGsapWindowMeta(method, argsStr) {
37125
- const emptyMeta = {
37126
- effectiveDuration: 0,
37127
- properties: [],
37128
- propertyValues: {},
37129
- overwriteAuto: false
37130
- };
37131
- const selectorMatch = argsStr.match(/^\s*["']([^"']+)["']\s*,/);
37132
- if (!selectorMatch) return emptyMeta;
37133
- const afterSelector = argsStr.slice(selectorMatch[0].length);
37134
- let properties = {};
37135
- let fromProperties = {};
37136
- if (method === "fromTo") {
37137
- const firstBrace = afterSelector.indexOf("{");
37138
- const firstEnd = findMatchingBrace(afterSelector, firstBrace);
37139
- if (firstBrace !== -1 && firstEnd !== -1) {
37140
- fromProperties = parseLooseObjectLiteral(afterSelector.slice(firstBrace, firstEnd + 1));
37141
- const secondPart = afterSelector.slice(firstEnd + 1);
37142
- const secondBrace = secondPart.indexOf("{");
37143
- const secondEnd = findMatchingBrace(secondPart, secondBrace);
37144
- if (secondBrace !== -1 && secondEnd !== -1) {
37145
- properties = parseLooseObjectLiteral(secondPart.slice(secondBrace, secondEnd + 1));
37146
- }
37147
- }
37148
- } else {
37149
- const braceStart = afterSelector.indexOf("{");
37150
- const braceEnd = findMatchingBrace(afterSelector, braceStart);
37151
- if (braceStart !== -1 && braceEnd !== -1) {
37152
- properties = parseLooseObjectLiteral(afterSelector.slice(braceStart, braceEnd + 1));
37153
- }
37154
- }
37155
- const duration = numberValue(properties.duration) || 0;
37156
- const repeat = numberValue(properties.repeat) || 0;
37157
- const cycleCount = repeat > 0 ? repeat + 1 : 1;
37158
- const effectiveDuration = duration * cycleCount;
37159
- const overwriteAuto = stringValue(properties.overwrite) === "auto";
37160
- const propertyNames = /* @__PURE__ */ new Set();
37161
- for (const key2 of Object.keys(fromProperties)) {
37162
- if (!META_GSAP_KEYS.has(key2)) propertyNames.add(key2);
37163
- }
37164
- for (const key2 of Object.keys(properties)) {
37165
- if (!META_GSAP_KEYS.has(key2)) propertyNames.add(key2);
37166
- }
37167
- return {
37168
- effectiveDuration: method === "set" ? 0 : effectiveDuration,
37169
- properties: [...propertyNames],
37170
- propertyValues: properties,
37171
- overwriteAuto
37172
- };
37173
- }
37174
- function parseLooseObjectLiteral(source) {
37175
- const result = {};
37176
- const cleaned = source.replace(/^\{|\}$/g, "").trim();
37177
- if (!cleaned) return result;
37178
- const propertyPattern = /(\w+)\s*:\s*("[^"]*"|'[^']*'|true|false|-?[\d.]+|[a-zA-Z_][\w.]*)/g;
37179
- let match;
37180
- while ((match = propertyPattern.exec(cleaned)) !== null) {
37181
- const key2 = match[1];
37182
- const rawValue = match[2];
37183
- if (!key2 || rawValue == null) continue;
37184
- if (rawValue.startsWith('"') && rawValue.endsWith('"') || rawValue.startsWith("'") && rawValue.endsWith("'")) {
37185
- result[key2] = rawValue.slice(1, -1);
37186
- continue;
37187
- }
37188
- const numeric = Number(rawValue);
37189
- result[key2] = Number.isFinite(numeric) ? numeric : rawValue;
37190
- }
37191
- return result;
37192
- }
37193
- function findMatchingBrace(source, startIndex) {
37194
- if (startIndex < 0) return -1;
37195
- let depth = 0;
37196
- for (let i2 = startIndex; i2 < source.length; i2++) {
37197
- if (source[i2] === "{") depth += 1;
37198
- else if (source[i2] === "}") {
37199
- depth -= 1;
37200
- if (depth === 0) return i2;
37201
- }
37202
- }
37203
- return -1;
37204
- }
37205
37408
  function numberValue(value) {
37206
37409
  if (typeof value === "number") return value;
37207
37410
  if (typeof value === "string" && value.trim()) {
@@ -37341,12 +37544,11 @@ function cssTransformToGsapProps(cssTransform) {
37341
37544
  }
37342
37545
  return parts.length > 0 ? parts.join(", ") : null;
37343
37546
  }
37344
- var META_GSAP_KEYS, SCENE_BOUNDARY_EPSILON_SECONDS, gsapRules;
37547
+ var SCENE_BOUNDARY_EPSILON_SECONDS, gsapRules;
37345
37548
  var init_gsap = __esm({
37346
37549
  "../core/src/lint/rules/gsap.ts"() {
37347
37550
  "use strict";
37348
37551
  init_utils2();
37349
- META_GSAP_KEYS = /* @__PURE__ */ new Set(["duration", "ease", "repeat", "yoyo", "overwrite", "delay"]);
37350
37552
  SCENE_BOUNDARY_EPSILON_SECONDS = 0.05;
37351
37553
  gsapRules = [
37352
37554
  // overlapping_gsap_tweens + gsap_animates_clip_element + unscoped_gsap_selector
@@ -42355,7 +42557,7 @@ __export(src_exports, {
42355
42557
  generateGsapTimelineScript: () => generateGsapTimelineScript,
42356
42558
  generateHyperframesHtml: () => generateHyperframesHtml,
42357
42559
  generateHyperframesStyles: () => generateHyperframesStyles,
42358
- getAnimationsForElement: () => getAnimationsForElement,
42560
+ getAnimationsForElementId: () => getAnimationsForElementId,
42359
42561
  getDefaultStageZoom: () => getDefaultStageZoom,
42360
42562
  getHyperframeRuntimeScript: () => getHyperframeRuntimeScript,
42361
42563
  getStageStyles: () => getStageStyles,
@@ -58183,7 +58385,12 @@ function updateReferences(projectDir, oldPath, newPath) {
58183
58385
  }
58184
58386
  function extractGsapScriptBlock(html) {
58185
58387
  const { document: document2 } = parseHTML(html);
58186
- const scripts = document2.querySelectorAll("script:not([src])");
58388
+ const scripts = [
58389
+ ...document2.querySelectorAll("script:not([src])"),
58390
+ ...Array.from(document2.querySelectorAll("template")).flatMap(
58391
+ (tmpl) => Array.from(tmpl.querySelectorAll("script:not([src])"))
58392
+ )
58393
+ ];
58187
58394
  for (const script of scripts) {
58188
58395
  const content = script.textContent || "";
58189
58396
  if (content.includes("gsap.timeline") || content.includes(".set(") || content.includes(".to(")) {
@@ -66719,6 +66926,101 @@ var init_videoFrameInjector = __esm({
66719
66926
  }
66720
66927
  });
66721
66928
 
66929
+ // ../engine/src/services/audioVolumeEnvelope.ts
66930
+ import { readFileSync as readFileSync22, renameSync as renameSync3, writeFileSync as writeFileSync14 } from "fs";
66931
+ import { randomBytes } from "crypto";
66932
+ function parseWavLayout(buffer) {
66933
+ if (buffer.length < 12 || buffer.toString("ascii", 0, 4) !== "RIFF") return null;
66934
+ if (buffer.toString("ascii", 8, 12) !== "WAVE") return null;
66935
+ let offset = 12;
66936
+ let fmt = null;
66937
+ let data = null;
66938
+ while (offset + 8 <= buffer.length) {
66939
+ const chunkId = buffer.toString("ascii", offset, offset + 4);
66940
+ const chunkSize = buffer.readUInt32LE(offset + 4);
66941
+ const body = offset + 8;
66942
+ if (chunkId === "fmt " && body + 16 <= buffer.length) {
66943
+ if (buffer.readUInt16LE(body) !== PCM_FORMAT) return null;
66944
+ fmt = {
66945
+ numChannels: buffer.readUInt16LE(body + 2),
66946
+ sampleRate: buffer.readUInt32LE(body + 4),
66947
+ bitsPerSample: buffer.readUInt16LE(body + 14)
66948
+ };
66949
+ } else if (chunkId === "data") {
66950
+ data = { offset: body, size: Math.min(chunkSize, buffer.length - body) };
66951
+ }
66952
+ offset = body + chunkSize + chunkSize % 2;
66953
+ }
66954
+ if (!fmt || !data) return null;
66955
+ if (fmt.bitsPerSample !== SUPPORTED_BITS || fmt.numChannels < 1) return null;
66956
+ return {
66957
+ numChannels: fmt.numChannels,
66958
+ sampleRate: fmt.sampleRate,
66959
+ dataOffset: data.offset,
66960
+ dataSize: data.size
66961
+ };
66962
+ }
66963
+ function toRelativeEnvelope(keyframes, trackStart, baseVolume) {
66964
+ const points = keyframes.filter((k2) => Number.isFinite(k2.time) && Number.isFinite(k2.volume)).map((k2) => ({
66965
+ time: Math.max(0, k2.time - trackStart),
66966
+ volume: Math.max(0, Math.min(1, k2.volume))
66967
+ })).sort((a, b2) => a.time - b2.time);
66968
+ const deduped = [];
66969
+ for (const point of points) {
66970
+ const previous = deduped.at(-1);
66971
+ if (previous && Math.abs(previous.time - point.time) < 1e-9) previous.volume = point.volume;
66972
+ else deduped.push(point);
66973
+ }
66974
+ if (deduped.length === 0) return deduped;
66975
+ if (deduped[0].time > 0) {
66976
+ deduped.unshift({ time: 0, volume: Math.max(0, Math.min(1, baseVolume)) });
66977
+ }
66978
+ return deduped;
66979
+ }
66980
+ function applyVolumeEnvelopeToWav(wavPath, keyframes, trackStart, baseVolume) {
66981
+ const envelope = toRelativeEnvelope(keyframes, trackStart, baseVolume);
66982
+ if (envelope.length === 0) return false;
66983
+ try {
66984
+ const buffer = readFileSync22(wavPath);
66985
+ const layout2 = parseWavLayout(buffer);
66986
+ if (!layout2) return false;
66987
+ const { numChannels, sampleRate, dataOffset, dataSize } = layout2;
66988
+ const bytesPerSample = SUPPORTED_BITS / 8;
66989
+ const frameBytes = numChannels * bytesPerSample;
66990
+ const frameCount = Math.floor(dataSize / frameBytes);
66991
+ let segment = 0;
66992
+ for (let frame = 0; frame < frameCount; frame += 1) {
66993
+ const time = frame / sampleRate;
66994
+ while (segment < envelope.length - 2 && time >= envelope[segment + 1].time) segment += 1;
66995
+ const a = envelope[segment];
66996
+ const b2 = envelope[segment + 1] ?? a;
66997
+ const span = b2.time - a.time;
66998
+ const progress = span <= 0 ? 0 : Math.min(1, Math.max(0, (time - a.time) / span));
66999
+ const gain = a.volume + (b2.volume - a.volume) * progress;
67000
+ const base = dataOffset + frame * frameBytes;
67001
+ for (let channel = 0; channel < numChannels; channel += 1) {
67002
+ const at3 = base + channel * bytesPerSample;
67003
+ const scaled = Math.round(buffer.readInt16LE(at3) * gain);
67004
+ buffer.writeInt16LE(scaled < -32768 ? -32768 : scaled > 32767 ? 32767 : scaled, at3);
67005
+ }
67006
+ }
67007
+ const tempPath = `${wavPath}.${randomBytes(6).toString("hex")}.tmp`;
67008
+ writeFileSync14(tempPath, buffer);
67009
+ renameSync3(tempPath, wavPath);
67010
+ return true;
67011
+ } catch {
67012
+ return false;
67013
+ }
67014
+ }
67015
+ var PCM_FORMAT, SUPPORTED_BITS;
67016
+ var init_audioVolumeEnvelope = __esm({
67017
+ "../engine/src/services/audioVolumeEnvelope.ts"() {
67018
+ "use strict";
67019
+ PCM_FORMAT = 1;
67020
+ SUPPORTED_BITS = 16;
67021
+ }
67022
+ });
67023
+
66722
67024
  // ../engine/src/services/audioMixer.ts
66723
67025
  import { existsSync as existsSync27, mkdirSync as mkdirSync16, rmSync as rmSync6 } from "fs";
66724
67026
  import { isAbsolute as isAbsolute6, join as join29, dirname as dirname10 } from "path";
@@ -66732,10 +67034,47 @@ function formatFilterNumber(value) {
66732
67034
  function escapeExpressionCommas(expression) {
66733
67035
  return expression.replace(/\\/g, "\\\\").replace(/,/g, "\\,");
66734
67036
  }
66735
- function buildVolumeExpression(track) {
67037
+ function simplifyVolumeKeyframes(keyframes) {
67038
+ if (keyframes.length < 3) return keyframes;
67039
+ const keep = new Array(keyframes.length).fill(false);
67040
+ keep[0] = true;
67041
+ keep[keyframes.length - 1] = true;
67042
+ const stack = [[0, keyframes.length - 1]];
67043
+ while (stack.length > 0) {
67044
+ const [startIndex, endIndex] = stack.pop();
67045
+ const start = keyframes[startIndex];
67046
+ const end = keyframes[endIndex];
67047
+ const span = end.time - start.time;
67048
+ let maxDistance = VOLUME_SIMPLIFY_EPSILON;
67049
+ let splitIndex = -1;
67050
+ for (let i2 = startIndex + 1; i2 < endIndex; i2 += 1) {
67051
+ const point = keyframes[i2];
67052
+ const interpolated = span === 0 ? start.volume : start.volume + (end.volume - start.volume) * (point.time - start.time) / span;
67053
+ const distance = Math.abs(point.volume - interpolated);
67054
+ if (distance > maxDistance) {
67055
+ maxDistance = distance;
67056
+ splitIndex = i2;
67057
+ }
67058
+ }
67059
+ if (splitIndex !== -1) {
67060
+ keep[splitIndex] = true;
67061
+ stack.push([startIndex, splitIndex], [splitIndex, endIndex]);
67062
+ }
67063
+ }
67064
+ const simplified = keyframes.filter((_, i2) => keep[i2]);
67065
+ if (simplified.length <= MAX_VOLUME_SEGMENTS) return simplified;
67066
+ const step = (simplified.length - 1) / (MAX_VOLUME_SEGMENTS - 1);
67067
+ const sampled = [];
67068
+ for (let i2 = 0; i2 < MAX_VOLUME_SEGMENTS; i2 += 1) {
67069
+ const point = simplified[Math.round(i2 * step)];
67070
+ if (sampled.length === 0 || point.time > sampled.at(-1).time) sampled.push(point);
67071
+ }
67072
+ return sampled;
67073
+ }
67074
+ function buildVolumeExpression(track, ignoreKeyframes = false) {
66736
67075
  const trimDuration = track.end - track.start;
66737
67076
  const staticVolume = clampVolume(track.volume);
66738
- const keyframes = (track.volumeKeyframes ?? []).filter((keyframe) => Number.isFinite(keyframe.time) && Number.isFinite(keyframe.volume)).map((keyframe) => ({
67077
+ const keyframes = (ignoreKeyframes ? [] : track.volumeKeyframes ?? []).filter((keyframe) => Number.isFinite(keyframe.time) && Number.isFinite(keyframe.volume)).map((keyframe) => ({
66739
67078
  time: Math.max(0, Math.min(trimDuration, keyframe.time - track.start)),
66740
67079
  volume: clampVolume(keyframe.volume)
66741
67080
  })).sort((a, b2) => a.time - b2.time);
@@ -66752,13 +67091,14 @@ function buildVolumeExpression(track) {
66752
67091
  deduped.push(keyframe);
66753
67092
  }
66754
67093
  }
66755
- if (deduped.length === 1) {
66756
- return `volume=${formatFilterNumber(deduped[0].volume)}`;
67094
+ const simplified = simplifyVolumeKeyframes(deduped);
67095
+ if (simplified.length === 1) {
67096
+ return `volume=${formatFilterNumber(simplified[0].volume)}`;
66757
67097
  }
66758
- let expression = formatFilterNumber(deduped.at(-1).volume);
66759
- for (let i2 = deduped.length - 2; i2 >= 0; i2 -= 1) {
66760
- const current = deduped[i2];
66761
- const next = deduped[i2 + 1];
67098
+ let expression = formatFilterNumber(simplified.at(-1).volume);
67099
+ for (let i2 = simplified.length - 2; i2 >= 0; i2 -= 1) {
67100
+ const current = simplified[i2];
67101
+ const next = simplified[i2 + 1];
66762
67102
  const currentTime = formatFilterNumber(current.time);
66763
67103
  const nextTime = formatFilterNumber(next.time);
66764
67104
  const currentVolume = formatFilterNumber(current.volume);
@@ -66926,38 +67266,49 @@ async function mixAudioTracks(tracks, outputPath, totalDuration, signal, config)
66926
67266
  }
66927
67267
  const outputDir = dirname10(outputPath);
66928
67268
  if (!existsSync27(outputDir)) mkdirSync16(outputDir, { recursive: true });
66929
- const inputs = [];
66930
- const filterParts = [];
66931
- tracks.forEach((track, i2) => {
66932
- inputs.push("-i", track.srcPath);
66933
- const delayMs = Math.round(track.start * 1e3);
66934
- const trimDuration = track.end - track.start;
66935
- const volumeFilter = buildVolumeExpression(track);
66936
- filterParts.push(
66937
- `[${i2}:a]atrim=0:${trimDuration},${volumeFilter},adelay=${delayMs}|${delayMs},apad=whole_dur=${totalDuration}[a${i2}]`
66938
- );
66939
- });
66940
- const mixInputs = tracks.map((_, i2) => `[a${i2}]`).join("");
66941
- const weights = tracks.map(() => "1").join(" ");
66942
- const mixFilter = `${mixInputs}amix=inputs=${tracks.length}:duration=longest:dropout_transition=0:normalize=0:weights='${weights}'[mixed]`;
66943
- const postMixGainFilter = `[mixed]volume=${masterOutputGain}[out]`;
66944
- const fullFilter = [...filterParts, mixFilter, postMixGainFilter].join(";");
66945
- const args = [
66946
- ...inputs,
66947
- "-filter_complex",
66948
- fullFilter,
66949
- "-map",
66950
- "[out]",
66951
- "-acodec",
66952
- "aac",
66953
- "-b:a",
66954
- "192k",
66955
- "-t",
66956
- String(totalDuration),
66957
- "-y",
66958
- outputPath
66959
- ];
66960
- const result = await runFfmpeg(args, { signal, timeout: ffmpegProcessTimeout });
67269
+ const buildArgs = (ignoreAutomation) => {
67270
+ const inputs = [];
67271
+ const filterParts = [];
67272
+ tracks.forEach((track, i2) => {
67273
+ inputs.push("-i", track.srcPath);
67274
+ const delayMs = Math.round(track.start * 1e3);
67275
+ const trimDuration = track.end - track.start;
67276
+ const volumeFilter = buildVolumeExpression(track, ignoreAutomation);
67277
+ filterParts.push(
67278
+ `[${i2}:a]atrim=0:${trimDuration},${volumeFilter},adelay=${delayMs}|${delayMs},apad=whole_dur=${totalDuration}[a${i2}]`
67279
+ );
67280
+ });
67281
+ const mixInputs = tracks.map((_, i2) => `[a${i2}]`).join("");
67282
+ const weights = tracks.map(() => "1").join(" ");
67283
+ const mixFilter = `${mixInputs}amix=inputs=${tracks.length}:duration=longest:dropout_transition=0:normalize=0:weights='${weights}'[mixed]`;
67284
+ const postMixGainFilter = `[mixed]volume=${masterOutputGain}[out]`;
67285
+ const fullFilter = [...filterParts, mixFilter, postMixGainFilter].join(";");
67286
+ return [
67287
+ ...inputs,
67288
+ "-filter_complex",
67289
+ fullFilter,
67290
+ "-map",
67291
+ "[out]",
67292
+ "-acodec",
67293
+ "aac",
67294
+ "-b:a",
67295
+ "192k",
67296
+ "-t",
67297
+ String(totalDuration),
67298
+ "-y",
67299
+ outputPath
67300
+ ];
67301
+ };
67302
+ let result = await runFfmpeg(buildArgs(false), { signal, timeout: ffmpegProcessTimeout });
67303
+ let degradedAutomation = false;
67304
+ const hasAutomation = tracks.some((track) => (track.volumeKeyframes?.length ?? 0) > 0);
67305
+ if (!result.success && !signal?.aborted && hasAutomation) {
67306
+ const retry = await runFfmpeg(buildArgs(true), { signal, timeout: ffmpegProcessTimeout });
67307
+ if (retry.success) {
67308
+ result = retry;
67309
+ degradedAutomation = true;
67310
+ }
67311
+ }
66961
67312
  if (signal?.aborted) {
66962
67313
  return {
66963
67314
  success: false,
@@ -66980,7 +67331,8 @@ async function mixAudioTracks(tracks, outputPath, totalDuration, signal, config)
66980
67331
  success: true,
66981
67332
  outputPath,
66982
67333
  durationMs: result.durationMs,
66983
- tracksProcessed: tracks.length
67334
+ tracksProcessed: tracks.length,
67335
+ error: degradedAutomation ? "Volume automation exceeded this ffmpeg build's expression limits; rendered at base volume" : void 0
66984
67336
  };
66985
67337
  }
66986
67338
  async function processCompositionAudio(elements, baseDir, workDir, outputPath, totalDuration, signal, config, compiledDir) {
@@ -67052,6 +67404,15 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
67052
67404
  }
67053
67405
  audioSrcPath = trimmedPath;
67054
67406
  }
67407
+ let bakedEnvelope = false;
67408
+ if (element.volumeKeyframes && element.volumeKeyframes.length > 0) {
67409
+ bakedEnvelope = applyVolumeEnvelopeToWav(
67410
+ audioSrcPath,
67411
+ element.volumeKeyframes,
67412
+ element.start,
67413
+ element.volume ?? 1
67414
+ );
67415
+ }
67055
67416
  tracks.push({
67056
67417
  id: element.id,
67057
67418
  srcPath: audioSrcPath,
@@ -67059,8 +67420,9 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
67059
67420
  end: element.end,
67060
67421
  mediaStart: element.mediaStart,
67061
67422
  duration: element.end - element.start,
67062
- volume: element.volume ?? 1,
67063
- volumeKeyframes: element.volumeKeyframes
67423
+ // Gain is already in the samples when baked, so mix at unity.
67424
+ volume: bakedEnvelope ? 1 : element.volume ?? 1,
67425
+ volumeKeyframes: bakedEnvelope ? void 0 : element.volumeKeyframes
67064
67426
  });
67065
67427
  } catch (err) {
67066
67428
  errors.push(`Error: ${element.id} \u2014 ${err instanceof Error ? err.message : String(err)}`);
@@ -67078,6 +67440,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
67078
67440
  error: errors.length > 0 ? `Warnings: ${errors.join(", ")}` : mixResult.error
67079
67441
  };
67080
67442
  }
67443
+ var MAX_VOLUME_SEGMENTS, VOLUME_SIMPLIFY_EPSILON;
67081
67444
  var init_audioMixer = __esm({
67082
67445
  "../engine/src/services/audioMixer.ts"() {
67083
67446
  "use strict";
@@ -67088,6 +67451,9 @@ var init_audioMixer = __esm({
67088
67451
  init_runFfmpeg();
67089
67452
  init_htmlTemplate();
67090
67453
  init_videoFrameExtractor();
67454
+ init_audioVolumeEnvelope();
67455
+ MAX_VOLUME_SEGMENTS = 32;
67456
+ VOLUME_SIMPLIFY_EPSILON = 5e-3;
67091
67457
  }
67092
67458
  });
67093
67459
 
@@ -67400,7 +67766,7 @@ var init_parallelCoordinator = __esm({
67400
67766
  // ../engine/src/services/fileServer.ts
67401
67767
  import { Hono as Hono2 } from "hono";
67402
67768
  import { serve } from "@hono/node-server";
67403
- import { readFileSync as readFileSync22, existsSync as existsSync29, statSync as statSync9 } from "fs";
67769
+ import { readFileSync as readFileSync23, existsSync as existsSync29, statSync as statSync9 } from "fs";
67404
67770
  import { join as join31, extname as extname7 } from "path";
67405
67771
  function createFileServer(options) {
67406
67772
  const { projectDir, compiledDir, port = 0, stripEmbeddedRuntime = true } = options;
@@ -67422,11 +67788,11 @@ function createFileServer(options) {
67422
67788
  const ext = extname7(filePath).toLowerCase();
67423
67789
  const contentType = MIME_TYPES2[ext] || "application/octet-stream";
67424
67790
  if (ext === ".html") {
67425
- const rawHtml = readFileSync22(filePath, "utf-8");
67791
+ const rawHtml = readFileSync23(filePath, "utf-8");
67426
67792
  const html = relativePath === "index.html" ? injectScriptsIntoHtml(rawHtml, headScripts, bodyScripts, stripEmbeddedRuntime) : rawHtml;
67427
67793
  return c3.text(html, 200, { "Content-Type": contentType });
67428
67794
  }
67429
- const content = readFileSync22(filePath);
67795
+ const content = readFileSync23(filePath);
67430
67796
  return new Response(content, {
67431
67797
  status: 200,
67432
67798
  headers: { "Content-Type": contentType }
@@ -69145,7 +69511,7 @@ __export(deterministicFonts_exports, {
69145
69511
  iterateFontFamilyDeclarations: () => iterateFontFamilyDeclarations,
69146
69512
  parseFontFamilyValue: () => parseFontFamilyValue
69147
69513
  });
69148
- import { existsSync as existsSync31, mkdirSync as mkdirSync18, readFileSync as readFileSync23, writeFileSync as writeFileSync14 } from "fs";
69514
+ import { existsSync as existsSync31, mkdirSync as mkdirSync18, readFileSync as readFileSync24, writeFileSync as writeFileSync15 } from "fs";
69149
69515
  import { homedir as homedir8, tmpdir as tmpdir3 } from "os";
69150
69516
  import { join as join33 } from "path";
69151
69517
  function parseFontFamilyValue(value) {
@@ -69329,7 +69695,7 @@ async function fetchGoogleFont(familyName, options) {
69329
69695
  continue;
69330
69696
  }
69331
69697
  const buffer = Buffer.from(await fontRes.arrayBuffer());
69332
- writeFileSync14(cachePath2, buffer);
69698
+ writeFileSync15(cachePath2, buffer);
69333
69699
  } catch (err) {
69334
69700
  if (err instanceof FontFetchError) throw err;
69335
69701
  if (options.failClosedFontFetch) {
@@ -69338,7 +69704,7 @@ async function fetchGoogleFont(familyName, options) {
69338
69704
  continue;
69339
69705
  }
69340
69706
  }
69341
- const fontBytes = readFileSync23(cachePath2);
69707
+ const fontBytes = readFileSync24(cachePath2);
69342
69708
  const dataUri = `data:font/woff2;base64,${fontBytes.toString("base64")}`;
69343
69709
  faces.push({ weight, style, dataUri });
69344
69710
  }
@@ -69538,7 +69904,7 @@ var init_deterministicFonts = __esm({
69538
69904
 
69539
69905
  // ../producer/src/services/hyperframeRuntimeLoader.ts
69540
69906
  import { createHash as createHash6 } from "crypto";
69541
- import { existsSync as existsSync32, readFileSync as readFileSync24 } from "fs";
69907
+ import { existsSync as existsSync32, readFileSync as readFileSync25 } from "fs";
69542
69908
  import { dirname as dirname11, resolve as resolve16 } from "path";
69543
69909
  import { fileURLToPath as fileURLToPath2 } from "url";
69544
69910
  function resolveHyperframeManifestPath() {
@@ -69567,7 +69933,7 @@ function resolveVerifiedHyperframeRuntime() {
69567
69933
  `[HyperframeRuntimeLoader] Missing manifest at ${manifestPath}. Build core runtime artifacts before rendering.`
69568
69934
  );
69569
69935
  }
69570
- const manifestRaw = readFileSync24(manifestPath, "utf8");
69936
+ const manifestRaw = readFileSync25(manifestPath, "utf8");
69571
69937
  const manifest = JSON.parse(manifestRaw);
69572
69938
  const runtimeFileName = manifest.artifacts?.iife;
69573
69939
  if (!runtimeFileName || !manifest.sha256) {
@@ -69579,7 +69945,7 @@ function resolveVerifiedHyperframeRuntime() {
69579
69945
  if (!existsSync32(runtimePath)) {
69580
69946
  throw new Error(`[HyperframeRuntimeLoader] Missing runtime artifact at ${runtimePath}.`);
69581
69947
  }
69582
- const runtimeSource = readFileSync24(runtimePath, "utf8");
69948
+ const runtimeSource = readFileSync25(runtimePath, "utf8");
69583
69949
  const runtimeSha = createHash6("sha256").update(runtimeSource, "utf8").digest("hex");
69584
69950
  if (runtimeSha !== manifest.sha256) {
69585
69951
  throw new Error(
@@ -69618,7 +69984,7 @@ var init_hyperframeRuntimeLoader = __esm({
69618
69984
  // ../producer/src/services/fileServer.ts
69619
69985
  import { Hono as Hono3 } from "hono";
69620
69986
  import { serve as serve2 } from "@hono/node-server";
69621
- import { readFileSync as readFileSync25, existsSync as existsSync33, realpathSync, statSync as statSync10 } from "fs";
69987
+ import { readFileSync as readFileSync26, existsSync as existsSync33, realpathSync, statSync as statSync10 } from "fs";
69622
69988
  import { join as join34, extname as extname8, resolve as resolve17, sep as sep5 } from "path";
69623
69989
  function isPathInside(child, parent, options = {}) {
69624
69990
  const { resolveSymlinks = false, pathModule } = options;
@@ -69813,7 +70179,7 @@ function createFileServer2(options) {
69813
70179
  const ext = extname8(filePath).toLowerCase();
69814
70180
  const contentType = MIME_TYPES3[ext] || "application/octet-stream";
69815
70181
  if (ext === ".html") {
69816
- const rawHtml = readFileSync25(filePath, "utf-8");
70182
+ const rawHtml = readFileSync26(filePath, "utf-8");
69817
70183
  const isIndex = relativePath === "index.html";
69818
70184
  let html = rawHtml;
69819
70185
  if (preHeadScripts.length > 0) {
@@ -69822,7 +70188,7 @@ function createFileServer2(options) {
69822
70188
  html = isIndex ? injectScriptsIntoHtml(html, headScripts, bodyScripts, stripEmbeddedRuntime) : html;
69823
70189
  return c3.text(html, 200, { "Content-Type": contentType });
69824
70190
  }
69825
- const content = readFileSync25(filePath);
70191
+ const content = readFileSync26(filePath);
69826
70192
  return new Response(content, {
69827
70193
  status: 200,
69828
70194
  headers: { "Content-Type": contentType }
@@ -70169,7 +70535,7 @@ var init_paths = __esm({
70169
70535
  });
70170
70536
 
70171
70537
  // ../producer/src/services/render/shared.ts
70172
- import { copyFileSync as copyFileSync2, cpSync, existsSync as existsSync34, mkdirSync as mkdirSync19, symlinkSync, writeFileSync as writeFileSync15 } from "fs";
70538
+ import { copyFileSync as copyFileSync2, cpSync, existsSync as existsSync34, mkdirSync as mkdirSync19, symlinkSync, writeFileSync as writeFileSync16 } from "fs";
70173
70539
  import { basename as basename4, dirname as dirname12, isAbsolute as isAbsolute7, join as join36, relative as relative5, resolve as resolve18 } from "path";
70174
70540
  function projectBrowserEndToCompositionTimeline(existingStart, browserStart, browserEnd) {
70175
70541
  return browserEnd + (existingStart - browserStart);
@@ -70208,11 +70574,11 @@ function resolveDeviceScaleFactor(input2) {
70208
70574
  function writeCompiledArtifacts(compiled, workDir, includeSummary) {
70209
70575
  const compileDir = join36(workDir, "compiled");
70210
70576
  mkdirSync19(compileDir, { recursive: true });
70211
- writeFileSync15(join36(compileDir, "index.html"), compiled.html, "utf-8");
70577
+ writeFileSync16(join36(compileDir, "index.html"), compiled.html, "utf-8");
70212
70578
  for (const [srcPath, html] of compiled.subCompositions) {
70213
70579
  const outPath = join36(compileDir, srcPath);
70214
70580
  mkdirSync19(dirname12(outPath), { recursive: true });
70215
- writeFileSync15(outPath, html, "utf-8");
70581
+ writeFileSync16(outPath, html, "utf-8");
70216
70582
  }
70217
70583
  for (const [relativePath, absolutePath] of compiled.externalAssets) {
70218
70584
  const outPath = resolve18(join36(compileDir, relativePath));
@@ -70246,7 +70612,7 @@ function writeCompiledArtifacts(compiled, workDir, includeSummary) {
70246
70612
  renderModeHints: compiled.renderModeHints,
70247
70613
  hasShaderTransitions: compiled.hasShaderTransitions
70248
70614
  };
70249
- writeFileSync15(join36(compileDir, "summary.json"), JSON.stringify(summary, null, 2), "utf-8");
70615
+ writeFileSync16(join36(compileDir, "summary.json"), JSON.stringify(summary, null, 2), "utf-8");
70250
70616
  }
70251
70617
  }
70252
70618
  function applyRenderModeHints(alreadyForced, compiled, log2 = defaultLogger) {
@@ -70926,7 +71292,7 @@ var init_urlDownloader2 = __esm({
70926
71292
  });
70927
71293
 
70928
71294
  // ../producer/src/services/htmlCompiler.ts
70929
- import { readFileSync as readFileSync26, existsSync as existsSync35, mkdirSync as mkdirSync20 } from "fs";
71295
+ import { readFileSync as readFileSync27, existsSync as existsSync35, mkdirSync as mkdirSync20 } from "fs";
70930
71296
  import { join as join38, dirname as dirname13, resolve as resolve19 } from "path";
70931
71297
  function dedupeElementsById(elements) {
70932
71298
  const deduped = /* @__PURE__ */ new Map();
@@ -71084,7 +71450,7 @@ async function parseSubCompositions(html, projectDir, downloadDir, parentOffset
71084
71450
  if (!existsSync35(filePath)) {
71085
71451
  continue;
71086
71452
  }
71087
- const rawSubHtml = readFileSync26(filePath, "utf-8");
71453
+ const rawSubHtml = readFileSync27(filePath, "utf-8");
71088
71454
  const nestedVisited = new Set(visited);
71089
71455
  nestedVisited.add(filePath);
71090
71456
  workItems.push({ srcPath, absoluteStart, absoluteEnd, filePath, rawSubHtml, nestedVisited });
@@ -71270,7 +71636,7 @@ function inlineSubCompositions2(html, subCompositions, projectDir) {
71270
71636
  if (!compHtml) {
71271
71637
  const filePath = resolve19(projectDir, srcPath);
71272
71638
  if (existsSync35(filePath)) {
71273
- compHtml = readFileSync26(filePath, "utf-8");
71639
+ compHtml = readFileSync27(filePath, "utf-8");
71274
71640
  }
71275
71641
  }
71276
71642
  return compHtml;
@@ -71428,9 +71794,9 @@ function collectExternalAssets(html, projectDir) {
71428
71794
  return null;
71429
71795
  }
71430
71796
  if (!existsSync35(absPath)) return null;
71431
- const safeKey = toExternalAssetKey(absPath);
71432
- externalAssets.set(safeKey, absPath);
71433
- return safeKey;
71797
+ const safeKey2 = toExternalAssetKey(absPath);
71798
+ externalAssets.set(safeKey2, absPath);
71799
+ return safeKey2;
71434
71800
  }
71435
71801
  const { document: document2 } = parseHTML(html);
71436
71802
  for (const el of document2.querySelectorAll("[src], [href]")) {
@@ -71486,7 +71852,7 @@ function rewriteUnresolvableGsapToCdn(html, projectDir) {
71486
71852
  );
71487
71853
  }
71488
71854
  async function compileForRender(projectDir, htmlPath, downloadDir, options = {}) {
71489
- const rawHtml = rewriteUnresolvableGsapToCdn(readFileSync26(htmlPath, "utf-8"), projectDir);
71855
+ const rawHtml = rewriteUnresolvableGsapToCdn(readFileSync27(htmlPath, "utf-8"), projectDir);
71490
71856
  const { html: compiledHtml, unresolvedCompositions } = await compileHtmlFile(
71491
71857
  rawHtml,
71492
71858
  projectDir,
@@ -72727,7 +73093,7 @@ var init_hdrImageTransferCache = __esm({
72727
73093
  });
72728
73094
 
72729
73095
  // ../producer/src/services/render/stages/captureHdrResources.ts
72730
- import { mkdirSync as mkdirSync21, openSync, readFileSync as readFileSync27, statSync as statSync11 } from "fs";
73096
+ import { mkdirSync as mkdirSync21, openSync, readFileSync as readFileSync28, statSync as statSync11 } from "fs";
72731
73097
  import { join as join43 } from "path";
72732
73098
  function planHdrResources(args) {
72733
73099
  const { composition, nativeHdrVideoIds, nativeHdrImageIds, projectDir, compiledDir } = args;
@@ -72872,7 +73238,7 @@ function decodeHdrImageBuffers(args) {
72872
73238
  const out = /* @__PURE__ */ new Map();
72873
73239
  for (const [imageId, srcPath] of hdrImageSrcPaths) {
72874
73240
  try {
72875
- const decoded = decodePngToRgb48le(readFileSync27(srcPath));
73241
+ const decoded = decodePngToRgb48le(readFileSync28(srcPath));
72876
73242
  const layout2 = prep.hdrExtractionDims.get(imageId);
72877
73243
  const fitInfo = prep.hdrImageFitInfo.get(imageId);
72878
73244
  if (layout2 && (layout2.width !== decoded.width || layout2.height !== decoded.height)) {
@@ -73143,7 +73509,7 @@ var init_captureHdrFrameShared = __esm({
73143
73509
  });
73144
73510
 
73145
73511
  // ../producer/src/services/render/stages/captureHdrSequentialLoop.ts
73146
- import { writeFileSync as writeFileSync16 } from "fs";
73512
+ import { writeFileSync as writeFileSync17 } from "fs";
73147
73513
  import { join as join44 } from "path";
73148
73514
  async function runSequentialLayeredFrameLoop(input2) {
73149
73515
  const {
@@ -73264,7 +73630,7 @@ async function runSequentialLayeredFrameLoop(input2) {
73264
73630
  await compositeHdrFrame(hdrCompositeCtx, normalCanvas, time, stackingInfo, void 0, i2);
73265
73631
  addHdrTiming(hdrPerf, "normalCompositeMs", timingStart);
73266
73632
  if (debugDumpEnabled && debugDumpDir && i2 % 30 === 0) {
73267
- writeFileSync16(
73633
+ writeFileSync17(
73268
73634
  join44(debugDumpDir, `frame_${String(i2).padStart(4, "0")}_final_rgb48le.bin`),
73269
73635
  normalCanvas
73270
73636
  );
@@ -73494,7 +73860,7 @@ var init_shaderTransitionWorkerPool = __esm({
73494
73860
  });
73495
73861
 
73496
73862
  // ../producer/src/services/render/stages/captureHdrHybridLoop.ts
73497
- import { writeFileSync as writeFileSync17 } from "fs";
73863
+ import { writeFileSync as writeFileSync18 } from "fs";
73498
73864
  import { join as join46 } from "path";
73499
73865
  async function runHybridLayeredFrameLoop(input2) {
73500
73866
  const {
@@ -73689,7 +74055,7 @@ async function runHybridLayeredFrameLoop(input2) {
73689
74055
  await compositeHdrFrame(wctx, canvas, time, stackingInfo, void 0, i2);
73690
74056
  addHdrTiming(hdrPerf, "normalCompositeMs", timingStart);
73691
74057
  if (debugDumpEnabled && debugDumpDir && i2 % 30 === 0) {
73692
- writeFileSync17(
74058
+ writeFileSync18(
73693
74059
  join46(debugDumpDir, `frame_${String(i2).padStart(4, "0")}_final_rgb48le.bin`),
73694
74060
  canvas
73695
74061
  );
@@ -74189,13 +74555,13 @@ var init_assembleStage = __esm({
74189
74555
  import {
74190
74556
  existsSync as existsSync40,
74191
74557
  mkdirSync as mkdirSync24,
74192
- readFileSync as readFileSync28,
74558
+ readFileSync as readFileSync29,
74193
74559
  readSync,
74194
74560
  closeSync,
74195
74561
  readdirSync as readdirSync16,
74196
74562
  rmSync as rmSync9,
74197
74563
  statSync as statSync12,
74198
- writeFileSync as writeFileSync18,
74564
+ writeFileSync as writeFileSync19,
74199
74565
  copyFileSync as copyFileSync4,
74200
74566
  appendFileSync
74201
74567
  } from "fs";
@@ -74796,7 +75162,7 @@ async function compositeHdrFrame(ctx, canvas, time, fullStacking, elementFilter,
74796
75162
  const after2 = countNonZeroRgb48(canvas);
74797
75163
  const dumpName = `frame_${String(debugFrameIndex).padStart(4, "0")}_layer_${String(layerIdx).padStart(2, "0")}_dom.png`;
74798
75164
  const dumpPath = join49(debugDumpDir, dumpName);
74799
- writeFileSync18(dumpPath, domPng);
75165
+ writeFileSync19(dumpPath, domPng);
74800
75166
  log2.info("[diag] dom layer blit", {
74801
75167
  frame: debugFrameIndex,
74802
75168
  layerIdx,
@@ -74926,7 +75292,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
74926
75292
  throw new Error(`Entry file not found: ${htmlPath}`);
74927
75293
  }
74928
75294
  assertNotAborted();
74929
- const rawEntry = readFileSync28(htmlPath, "utf-8");
75295
+ const rawEntry = readFileSync29(htmlPath, "utf-8");
74930
75296
  if (entryFile !== "index.html" && rawEntry.trimStart().startsWith("<template")) {
74931
75297
  const wrapperPath = join49(workDir, "standalone-entry.html");
74932
75298
  const projectIndexPath = join49(projectDir, "index.html");
@@ -74936,7 +75302,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
74936
75302
  );
74937
75303
  }
74938
75304
  const standaloneHtml = extractStandaloneEntryFromIndex(
74939
- readFileSync28(projectIndexPath, "utf-8"),
75305
+ readFileSync29(projectIndexPath, "utf-8"),
74940
75306
  entryFile
74941
75307
  );
74942
75308
  if (!standaloneHtml) {
@@ -74944,7 +75310,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
74944
75310
  `Entry file "${entryFile}" is not mounted from index.html via data-composition-src, so it cannot be rendered independently.`
74945
75311
  );
74946
75312
  }
74947
- writeFileSync18(wrapperPath, standaloneHtml, "utf-8");
75313
+ writeFileSync19(wrapperPath, standaloneHtml, "utf-8");
74948
75314
  htmlPath = wrapperPath;
74949
75315
  log2.info("Extracted standalone entry from index.html host context", {
74950
75316
  entryFile
@@ -75331,7 +75697,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
75331
75697
  job.perfSummary = perfSummary;
75332
75698
  if (job.config.debug) {
75333
75699
  try {
75334
- writeFileSync18(perfOutputPath, JSON.stringify(perfSummary, null, 2), "utf-8");
75700
+ writeFileSync19(perfOutputPath, JSON.stringify(perfSummary, null, 2), "utf-8");
75335
75701
  } catch (err) {
75336
75702
  log2.debug("Failed to write perf summary", {
75337
75703
  perfOutputPath,
@@ -75468,7 +75834,7 @@ var init_config3 = __esm({
75468
75834
  });
75469
75835
 
75470
75836
  // ../producer/src/services/hyperframeLint.ts
75471
- import { existsSync as existsSync41, readFileSync as readFileSync29, statSync as statSync13 } from "fs";
75837
+ import { existsSync as existsSync41, readFileSync as readFileSync30, statSync as statSync13 } from "fs";
75472
75838
  import { resolve as resolve21, join as join50 } from "path";
75473
75839
  function isStringRecord(value) {
75474
75840
  if (!value || typeof value !== "object" || Array.isArray(value)) {
@@ -75511,7 +75877,7 @@ function readProjectEntryFile(projectDir, preferredEntryFile) {
75511
75877
  if (existsSync41(absoluteEntryPath) && statSync13(absoluteEntryPath).isFile()) {
75512
75878
  return {
75513
75879
  entryFile,
75514
- html: readFileSync29(absoluteEntryPath, "utf-8"),
75880
+ html: readFileSync30(absoluteEntryPath, "utf-8"),
75515
75881
  source: "projectDir"
75516
75882
  };
75517
75883
  }
@@ -75610,7 +75976,7 @@ import {
75610
75976
  mkdirSync as mkdirSync25,
75611
75977
  statSync as statSync14,
75612
75978
  mkdtempSync as mkdtempSync2,
75613
- writeFileSync as writeFileSync19,
75979
+ writeFileSync as writeFileSync20,
75614
75980
  rmSync as rmSync10,
75615
75981
  createReadStream
75616
75982
  } from "fs";
@@ -75669,7 +76035,7 @@ async function prepareRenderBody(body) {
75669
76035
  }
75670
76036
  const tempRoot = process.env.PRODUCER_TMP_PROJECT_DIR || tmpdir4();
75671
76037
  const tempProjectDir = mkdtempSync2(join51(tempRoot, "producer-project-"));
75672
- writeFileSync19(join51(tempProjectDir, "index.html"), htmlContent, "utf-8");
76038
+ writeFileSync20(join51(tempProjectDir, "index.html"), htmlContent, "utf-8");
75673
76039
  return {
75674
76040
  prepared: {
75675
76041
  input: {
@@ -76161,7 +76527,7 @@ var init_planHash = __esm({
76161
76527
  });
76162
76528
 
76163
76529
  // ../producer/src/services/render/stages/freezePlan.ts
76164
- import { existsSync as existsSync43, mkdirSync as mkdirSync26, readFileSync as readFileSync30, readdirSync as readdirSync17, writeFileSync as writeFileSync20 } from "fs";
76530
+ import { existsSync as existsSync43, mkdirSync as mkdirSync26, readFileSync as readFileSync31, readdirSync as readdirSync17, writeFileSync as writeFileSync21 } from "fs";
76165
76531
  import { join as join52, relative as relative6, resolve as resolve23 } from "path";
76166
76532
  function stripUndefined(value) {
76167
76533
  if (Array.isArray(value)) return value.map(stripUndefined);
@@ -76204,11 +76570,11 @@ function collectPlanAssetShas(planDir) {
76204
76570
  const assets = [];
76205
76571
  for (const file of files) {
76206
76572
  if (file.planRelativePath === COMPILED_INDEX_RELATIVE_PATH) {
76207
- compositionHtml = readFileSync30(file.absolutePath);
76573
+ compositionHtml = readFileSync31(file.absolutePath);
76208
76574
  continue;
76209
76575
  }
76210
76576
  if (HASH_EXCLUDED_PLAN_FILES.has(file.planRelativePath)) continue;
76211
- const bytes = readFileSync30(file.absolutePath);
76577
+ const bytes = readFileSync31(file.absolutePath);
76212
76578
  assets.push({ path: file.planRelativePath, sha256: sha256Hex(bytes) });
76213
76579
  }
76214
76580
  if (compositionHtml === null) {
@@ -76227,8 +76593,8 @@ function recomputePlanHashFromPlanDir(planDir) {
76227
76593
  if (!existsSync43(encoderJsonPath)) {
76228
76594
  throw new Error(`[freezePlan] meta/encoder.json missing: ${encoderJsonPath}`);
76229
76595
  }
76230
- const planJson = JSON.parse(readFileSync30(planJsonPath, "utf-8"));
76231
- const encoderConfigCanonicalJson = readFileSync30(encoderJsonPath, "utf-8");
76596
+ const planJson = JSON.parse(readFileSync31(planJsonPath, "utf-8"));
76597
+ const encoderConfigCanonicalJson = readFileSync31(encoderJsonPath, "utf-8");
76232
76598
  const { compositionHtml, assets } = collectPlanAssetShas(planDir);
76233
76599
  return computePlanHash({
76234
76600
  compositionHtml,
@@ -76258,7 +76624,7 @@ async function freezePlan(input2) {
76258
76624
  }
76259
76625
  const metaDir = join52(planDir, "meta");
76260
76626
  if (!existsSync43(metaDir)) mkdirSync26(metaDir, { recursive: true });
76261
- writeFileSync20(
76627
+ writeFileSync21(
76262
76628
  join52(metaDir, "composition.json"),
76263
76629
  `${JSON.stringify(composition, null, 2)}
76264
76630
  `,
@@ -76266,8 +76632,8 @@ async function freezePlan(input2) {
76266
76632
  );
76267
76633
  const encoderForCanonical = stripUndefined(encoder);
76268
76634
  const encoderConfigCanonicalJson = canonicalJsonStringify(encoderForCanonical);
76269
- writeFileSync20(join52(metaDir, "encoder.json"), encoderConfigCanonicalJson, "utf-8");
76270
- writeFileSync20(join52(metaDir, "chunks.json"), `${JSON.stringify(chunks, null, 2)}
76635
+ writeFileSync21(join52(metaDir, "encoder.json"), encoderConfigCanonicalJson, "utf-8");
76636
+ writeFileSync21(join52(metaDir, "chunks.json"), `${JSON.stringify(chunks, null, 2)}
76271
76637
  `, "utf-8");
76272
76638
  const { compositionHtml, assets } = collectPlanAssetShas(planDir);
76273
76639
  const planHash = computePlanHash({
@@ -76291,7 +76657,7 @@ async function freezePlan(input2) {
76291
76657
  hasAudio
76292
76658
  };
76293
76659
  const planJsonPath = join52(planDir, "plan.json");
76294
- writeFileSync20(planJsonPath, `${JSON.stringify(planJson, null, 2)}
76660
+ writeFileSync21(planJsonPath, `${JSON.stringify(planJson, null, 2)}
76295
76661
  `, "utf-8");
76296
76662
  return { planJsonPath, planHash };
76297
76663
  }
@@ -76399,7 +76765,7 @@ var init_runtimeEnvSnapshot = __esm({
76399
76765
  // ../producer/src/services/distributed/shared.ts
76400
76766
  import { execFile as execFileCallback } from "child_process";
76401
76767
  import { dirname as dirname17, join as join53 } from "path";
76402
- import { existsSync as existsSync44, readFileSync as readFileSync31 } from "fs";
76768
+ import { existsSync as existsSync44, readFileSync as readFileSync32 } from "fs";
76403
76769
  import { fileURLToPath as fileURLToPath5 } from "url";
76404
76770
  import { promisify as promisify2 } from "util";
76405
76771
  async function readFfmpegVersion() {
@@ -76439,7 +76805,7 @@ function readProducerVersion() {
76439
76805
  const candidate = join53(current, "package.json");
76440
76806
  if (existsSync44(candidate)) {
76441
76807
  try {
76442
- const pkg = JSON.parse(readFileSync31(candidate, "utf-8"));
76808
+ const pkg = JSON.parse(readFileSync32(candidate, "utf-8"));
76443
76809
  if (pkg.name === "@hyperframes/producer" && typeof pkg.version === "string") {
76444
76810
  cachedProducerVersion = pkg.version;
76445
76811
  return pkg.version;
@@ -76473,10 +76839,10 @@ import {
76473
76839
  existsSync as existsSync45,
76474
76840
  mkdirSync as mkdirSync27,
76475
76841
  readdirSync as readdirSync18,
76476
- renameSync as renameSync3,
76842
+ renameSync as renameSync4,
76477
76843
  rmSync as rmSync11,
76478
76844
  statSync as statSync15,
76479
- writeFileSync as writeFileSync21
76845
+ writeFileSync as writeFileSync22
76480
76846
  } from "fs";
76481
76847
  import { join as join54, relative as relative7, sep as sep6 } from "path";
76482
76848
  function formatBytes(bytes) {
@@ -76756,12 +77122,12 @@ async function plan(projectDir, config, planDir) {
76756
77122
  const videoFramesDst = join54(planDir, "video-frames");
76757
77123
  if (existsSync45(videoFramesDst)) rmSync11(videoFramesDst, { recursive: true, force: true });
76758
77124
  if (existsSync45(stagedVideoFrames)) {
76759
- renameSync3(stagedVideoFrames, videoFramesDst);
77125
+ renameSync4(stagedVideoFrames, videoFramesDst);
76760
77126
  } else {
76761
77127
  mkdirSync27(videoFramesDst, { recursive: true });
76762
77128
  }
76763
77129
  if (existsSync45(finalCompiledDir)) rmSync11(finalCompiledDir, { recursive: true, force: true });
76764
- renameSync3(compiledDir, finalCompiledDir);
77130
+ renameSync4(compiledDir, finalCompiledDir);
76765
77131
  const planVideosJson = {
76766
77132
  videos: composition.videos,
76767
77133
  extracted: (extractResult.extractionResult?.extracted ?? []).map((ext) => ({
@@ -76774,14 +77140,14 @@ async function plan(projectDir, config, planDir) {
76774
77140
  }))
76775
77141
  };
76776
77142
  mkdirSync27(join54(planDir, "meta"), { recursive: true });
76777
- writeFileSync21(
77143
+ writeFileSync22(
76778
77144
  join54(planDir, PLAN_VIDEOS_META_RELATIVE_PATH),
76779
77145
  JSON.stringify(planVideosJson, null, 2),
76780
77146
  "utf-8"
76781
77147
  );
76782
77148
  const planAudioPath = join54(planDir, "audio.aac");
76783
77149
  if (audioResult.hasAudio && existsSync45(audioResult.audioOutputPath)) {
76784
- renameSync3(audioResult.audioOutputPath, planAudioPath);
77150
+ renameSync4(audioResult.audioOutputPath, planAudioPath);
76785
77151
  }
76786
77152
  const maxParallel = config.maxParallelChunks ?? DEFAULT_MAX_PARALLEL_CHUNKS;
76787
77153
  const { chunkCount, effectiveChunkSize } = resolveChunkPlan(
@@ -76918,8 +77284,8 @@ var init_plan = __esm({
76918
77284
  });
76919
77285
 
76920
77286
  // ../producer/src/services/distributed/renderChunk.ts
76921
- import { randomBytes } from "crypto";
76922
- import { existsSync as existsSync46, mkdirSync as mkdirSync28, readFileSync as readFileSync32, readdirSync as readdirSync19, rmSync as rmSync12, writeFileSync as writeFileSync22 } from "fs";
77287
+ import { randomBytes as randomBytes2 } from "crypto";
77288
+ import { existsSync as existsSync46, mkdirSync as mkdirSync28, readFileSync as readFileSync33, readdirSync as readdirSync19, rmSync as rmSync12, writeFileSync as writeFileSync23 } from "fs";
76923
77289
  import { extname as extname9, join as join55 } from "path";
76924
77290
  function rebuildExtractedFramesFromPlanDir(planDir, videos) {
76925
77291
  const result = [];
@@ -76958,10 +77324,10 @@ function rebuildExtractedFramesFromPlanDir(planDir, videos) {
76958
77324
  return result;
76959
77325
  }
76960
77326
  function hashChunkOutput(outputPath, kind) {
76961
- if (kind === "file") return sha256Hex(readFileSync32(outputPath));
77327
+ if (kind === "file") return sha256Hex(readFileSync33(outputPath));
76962
77328
  const entries2 = readdirSync19(outputPath).filter((name) => /\.(png|jpg|jpeg)$/i.test(name)).sort();
76963
77329
  const lines = entries2.map(
76964
- (name) => `${name}\0${sha256Hex(readFileSync32(join55(outputPath, name)))}`
77330
+ (name) => `${name}\0${sha256Hex(readFileSync33(join55(outputPath, name)))}`
76965
77331
  );
76966
77332
  return sha256Hex(lines.join("\0"));
76967
77333
  }
@@ -76985,14 +77351,14 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
76985
77351
  );
76986
77352
  }
76987
77353
  }
76988
- const plan2 = JSON.parse(readFileSync32(planJsonPath, "utf-8"));
76989
- const encoder = JSON.parse(readFileSync32(encoderJsonPath, "utf-8"));
76990
- const chunks = JSON.parse(readFileSync32(chunksJsonPath, "utf-8"));
77354
+ const plan2 = JSON.parse(readFileSync33(planJsonPath, "utf-8"));
77355
+ const encoder = JSON.parse(readFileSync33(encoderJsonPath, "utf-8"));
77356
+ const chunks = JSON.parse(readFileSync33(chunksJsonPath, "utf-8"));
76991
77357
  const videosJsonPath = join55(planDir, PLAN_VIDEOS_META_RELATIVE_PATH);
76992
77358
  let planVideos = null;
76993
77359
  if (existsSync46(videosJsonPath)) {
76994
77360
  try {
76995
- planVideos = JSON.parse(readFileSync32(videosJsonPath, "utf-8"));
77361
+ planVideos = JSON.parse(readFileSync33(videosJsonPath, "utf-8"));
76996
77362
  } catch (err) {
76997
77363
  throw new RenderChunkValidationError(
76998
77364
  MISSING_PLAN_ARTIFACT,
@@ -77074,7 +77440,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
77074
77440
  rebuildExtractedFramesFromPlanDir(planDir, planVideos.extracted)
77075
77441
  )
77076
77442
  ) : null;
77077
- const workDir = `${outputChunkPath}.work.${process.pid}.${randomBytes(4).toString("hex")}`;
77443
+ const workDir = `${outputChunkPath}.work.${process.pid}.${randomBytes2(4).toString("hex")}`;
77078
77444
  mkdirSync28(workDir, { recursive: true });
77079
77445
  const framesDir = join55(workDir, "captured-frames");
77080
77446
  mkdirSync28(framesDir, { recursive: true });
@@ -77205,7 +77571,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
77205
77571
  producerVersion: plan2.producerVersion,
77206
77572
  ffmpegVersion
77207
77573
  };
77208
- writeFileSync22(perfPath, `${JSON.stringify(perfPayload2, null, 2)}
77574
+ writeFileSync23(perfPath, `${JSON.stringify(perfPayload2, null, 2)}
77209
77575
  `, "utf-8");
77210
77576
  try {
77211
77577
  rmSync12(workDir, { recursive: true, force: true });
@@ -77468,11 +77834,11 @@ import {
77468
77834
  cpSync as cpSync3,
77469
77835
  existsSync as existsSync47,
77470
77836
  mkdirSync as mkdirSync29,
77471
- readFileSync as readFileSync33,
77837
+ readFileSync as readFileSync34,
77472
77838
  readdirSync as readdirSync20,
77473
77839
  rmSync as rmSync13,
77474
77840
  statSync as statSync16,
77475
- writeFileSync as writeFileSync23
77841
+ writeFileSync as writeFileSync24
77476
77842
  } from "fs";
77477
77843
  import { dirname as dirname18, join as join56 } from "path";
77478
77844
  async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
@@ -77488,8 +77854,8 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
77488
77854
  if (!existsSync47(chunksJsonPath)) {
77489
77855
  throw new Error(`[assemble] planDir missing meta/chunks.json: ${chunksJsonPath}`);
77490
77856
  }
77491
- const plan2 = JSON.parse(readFileSync33(planJsonPath, "utf-8"));
77492
- const chunks = JSON.parse(readFileSync33(chunksJsonPath, "utf-8"));
77857
+ const plan2 = JSON.parse(readFileSync34(planJsonPath, "utf-8"));
77858
+ const chunks = JSON.parse(readFileSync34(chunksJsonPath, "utf-8"));
77493
77859
  if (chunkPaths.length !== chunks.length) {
77494
77860
  throw new Error(
77495
77861
  `[assemble] chunkPaths length (${chunkPaths.length}) does not match chunks.json length (${chunks.length}). Adapters must pass one path per chunk, ordered by index.`
@@ -77526,7 +77892,7 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
77526
77892
  } else {
77527
77893
  const concatListPath = join56(workDir, "concat-list.txt");
77528
77894
  const concatBody = chunkPaths.map((path2) => `file '${path2.replace(/'/g, "'\\''")}'`).join("\n");
77529
- writeFileSync23(concatListPath, `${concatBody}
77895
+ writeFileSync24(concatListPath, `${concatBody}
77530
77896
  `, "utf-8");
77531
77897
  const concatArgs = [
77532
77898
  "-r",
@@ -77560,7 +77926,7 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
77560
77926
  if (!existsSync47(encoderJsonPath)) {
77561
77927
  throw new Error(`[assemble] planDir missing meta/encoder.json: ${encoderJsonPath}`);
77562
77928
  }
77563
- const encoderJson = JSON.parse(readFileSync33(encoderJsonPath, "utf-8"));
77929
+ const encoderJson = JSON.parse(readFileSync34(encoderJsonPath, "utf-8"));
77564
77930
  if (encoderJson.encoder === "libx265-software") {
77565
77931
  throw new Error(
77566
77932
  `[assemble] cfr=true is not yet supported with codec: "h265". The cfr re-encode pass uses libx264 and would silently transcode the h265 chunks. Either disable cfr or render with codec: "h264".`
@@ -77821,7 +78187,7 @@ __export(studioServer_exports, {
77821
78187
  });
77822
78188
  import { Hono as Hono5 } from "hono";
77823
78189
  import { streamSSE as streamSSE3 } from "hono/streaming";
77824
- import { existsSync as existsSync48, readFileSync as readFileSync34, writeFileSync as writeFileSync24, statSync as statSync17 } from "fs";
78190
+ import { existsSync as existsSync48, readFileSync as readFileSync35, writeFileSync as writeFileSync25, statSync as statSync17 } from "fs";
77825
78191
  import { resolve as resolve24, join as join57, basename as basename5 } from "path";
77826
78192
  function resolveDistDir() {
77827
78193
  return resolveStudioBundle().dir;
@@ -77870,7 +78236,7 @@ function readStudioManualEditManifestContent(projectDir) {
77870
78236
  const manifestPath = join57(projectDir, STUDIO_MANUAL_EDITS_PATH2);
77871
78237
  if (!existsSync48(manifestPath)) return "";
77872
78238
  try {
77873
- return readFileSync34(manifestPath, "utf-8");
78239
+ return readFileSync35(manifestPath, "utf-8");
77874
78240
  } catch {
77875
78241
  return "";
77876
78242
  }
@@ -77935,7 +78301,7 @@ async function closeThumbnailBrowser() {
77935
78301
  async function loadPreviewServerBuildSignature() {
77936
78302
  const runtimeSignature = await loadRuntimeSourceSignature();
77937
78303
  const studioBundle = resolveStudioBundle();
77938
- const studioIndex = studioBundle.available && existsSync48(studioBundle.indexPath) ? readFileSync34(studioBundle.indexPath, "utf-8") : "";
78304
+ const studioIndex = studioBundle.available && existsSync48(studioBundle.indexPath) ? readFileSync35(studioBundle.indexPath, "utf-8") : "";
77939
78305
  return hashSignatureParts([
77940
78306
  VERSION,
77941
78307
  runtimeSignature,
@@ -78029,7 +78395,7 @@ function createStudioServer(options) {
78029
78395
  state.status = "complete";
78030
78396
  state.progress = 100;
78031
78397
  const metaPath = opts.outputPath.replace(/\.(mp4|webm|mov)$/, ".meta.json");
78032
- writeFileSync24(
78398
+ writeFileSync25(
78033
78399
  metaPath,
78034
78400
  JSON.stringify({ status: "complete", durationMs: Date.now() - startTime })
78035
78401
  );
@@ -78040,7 +78406,7 @@ function createStudioServer(options) {
78040
78406
  emitStudioRenderError(opts, Date.now() - startTime, state.stage, err);
78041
78407
  try {
78042
78408
  const metaPath = opts.outputPath.replace(/\.(mp4|webm|mov)$/, ".meta.json");
78043
- writeFileSync24(metaPath, JSON.stringify({ status: "failed" }));
78409
+ writeFileSync25(metaPath, JSON.stringify({ status: "failed" }));
78044
78410
  } catch {
78045
78411
  }
78046
78412
  }
@@ -78125,19 +78491,19 @@ function createStudioServer(options) {
78125
78491
  async installRegistryBlock(opts) {
78126
78492
  const { resolveItem: resolveItem2 } = await Promise.resolve().then(() => (init_resolver(), resolver_exports));
78127
78493
  const { installItem: installItem2 } = await Promise.resolve().then(() => (init_installer(), installer_exports));
78128
- const { readFileSync: readFileSync57, writeFileSync: writeFileSync39, existsSync: existsSync81 } = await import("fs");
78494
+ const { readFileSync: readFileSync58, writeFileSync: writeFileSync40, existsSync: existsSync81 } = await import("fs");
78129
78495
  const { join: join91 } = await import("path");
78130
78496
  const item = await resolveItem2(opts.blockName);
78131
78497
  const { written } = await installItem2(item, { destDir: opts.project.dir });
78132
78498
  const indexPath = join91(opts.project.dir, "index.html");
78133
78499
  if (existsSync81(indexPath)) {
78134
- const indexHtml = readFileSync57(indexPath, "utf-8");
78500
+ const indexHtml = readFileSync58(indexPath, "utf-8");
78135
78501
  const hostW = indexHtml.match(/data-width="(\d+)"/)?.[1];
78136
78502
  const hostH = indexHtml.match(/data-height="(\d+)"/)?.[1];
78137
78503
  if (hostW && hostH) {
78138
78504
  for (const absPath of written) {
78139
78505
  if (!absPath.endsWith(".html")) continue;
78140
- let content = readFileSync57(absPath, "utf-8");
78506
+ let content = readFileSync58(absPath, "utf-8");
78141
78507
  content = content.replace(
78142
78508
  /(<meta\s+name="viewport"\s+content="width=)\d+(,\s*height=)\d+/i,
78143
78509
  `$1${hostW}$2${hostH}`
@@ -78151,7 +78517,7 @@ function createStudioServer(options) {
78151
78517
  return match;
78152
78518
  }
78153
78519
  );
78154
- writeFileSync39(absPath, content, "utf-8");
78520
+ writeFileSync40(absPath, content, "utf-8");
78155
78521
  }
78156
78522
  }
78157
78523
  }
@@ -78178,7 +78544,7 @@ function createStudioServer(options) {
78178
78544
  });
78179
78545
  app.get("/api/runtime.js", (c3) => {
78180
78546
  const serve4 = async () => {
78181
- const runtimeSource = await loadRuntimeSource() ?? (existsSync48(runtimePath) ? readFileSync34(runtimePath, "utf-8") : null);
78547
+ const runtimeSource = await loadRuntimeSource() ?? (existsSync48(runtimePath) ? readFileSync35(runtimePath, "utf-8") : null);
78182
78548
  if (!runtimeSource) return c3.text("runtime not available", 404);
78183
78549
  return c3.body(runtimeSource, 200, {
78184
78550
  "Content-Type": "text/javascript",
@@ -78226,7 +78592,7 @@ function createStudioServer(options) {
78226
78592
  const serveStudioStaticFile = (c3) => {
78227
78593
  const filePath = resolve24(studioDir, c3.req.path.slice(1));
78228
78594
  if (!existsSync48(filePath) || !statSync17(filePath).isFile()) return c3.text("not found", 404);
78229
- const content = readFileSync34(filePath);
78595
+ const content = readFileSync35(filePath);
78230
78596
  return new Response(content, {
78231
78597
  headers: { "Content-Type": getMimeType(filePath), "Cache-Control": "no-store" }
78232
78598
  });
@@ -78302,7 +78668,7 @@ function createStudioServer(options) {
78302
78668
  500
78303
78669
  );
78304
78670
  }
78305
- let html = readFileSync34(indexPath, "utf-8");
78671
+ let html = readFileSync35(indexPath, "utf-8");
78306
78672
  const envScript = buildRuntimeEnvScript();
78307
78673
  if (envScript) {
78308
78674
  html = html.replace("<head>", `<head>${envScript}`);
@@ -78817,8 +79183,8 @@ import {
78817
79183
  mkdirSync as mkdirSync31,
78818
79184
  copyFileSync as copyFileSync5,
78819
79185
  cpSync as cpSync4,
78820
- writeFileSync as writeFileSync25,
78821
- readFileSync as readFileSync35,
79186
+ writeFileSync as writeFileSync26,
79187
+ readFileSync as readFileSync36,
78822
79188
  readdirSync as readdirSync21
78823
79189
  } from "fs";
78824
79190
  import { resolve as resolve26, basename as basename7, join as join59, dirname as dirname20 } from "path";
@@ -78922,7 +79288,7 @@ function buildPackageScripts() {
78922
79288
  function writeDefaultPackageJson(destDir, projectName) {
78923
79289
  const packageJsonPath = resolve26(destDir, "package.json");
78924
79290
  if (existsSync50(packageJsonPath)) return;
78925
- writeFileSync25(
79291
+ writeFileSync26(
78926
79292
  packageJsonPath,
78927
79293
  `${JSON.stringify(
78928
79294
  {
@@ -78983,14 +79349,14 @@ ${html}`;
78983
79349
  }
78984
79350
  function writeTailwindSupport(destDir) {
78985
79351
  for (const file of listHtmlFiles(destDir)) {
78986
- const html = readFileSync35(file, "utf-8");
78987
- writeFileSync25(file, injectTailwindBrowserScript(html), "utf-8");
79352
+ const html = readFileSync36(file, "utf-8");
79353
+ writeFileSync26(file, injectTailwindBrowserScript(html), "utf-8");
78988
79354
  }
78989
79355
  }
78990
79356
  function patchVideoSrc(dir, videoFilename, durationSeconds) {
78991
79357
  const htmlFiles = readdirSync21(dir, { withFileTypes: true, recursive: true }).filter((e3) => e3.isFile() && e3.name.endsWith(".html")).map((e3) => join59(e3.parentPath, e3.name));
78992
79358
  for (const file of htmlFiles) {
78993
- let content = readFileSync35(file, "utf-8");
79359
+ let content = readFileSync36(file, "utf-8");
78994
79360
  if (videoFilename) {
78995
79361
  content = content.replaceAll("__VIDEO_SRC__", videoFilename);
78996
79362
  } else {
@@ -79001,7 +79367,7 @@ function patchVideoSrc(dir, videoFilename, durationSeconds) {
79001
79367
  }
79002
79368
  const dur = durationSeconds ? String(Math.round(durationSeconds * 100) / 100) : "10";
79003
79369
  content = content.replaceAll("__VIDEO_DURATION__", dur);
79004
- writeFileSync25(file, content, "utf-8");
79370
+ writeFileSync26(file, content, "utf-8");
79005
79371
  }
79006
79372
  }
79007
79373
  async function patchTranscript(dir, transcriptPath) {
@@ -79095,7 +79461,7 @@ async function handleVideoFile(videoPath, destDir, interactive) {
79095
79461
  function applyResolutionPreset(destDir, resolution) {
79096
79462
  const { width, height } = CANVAS_DIMENSIONS[resolution];
79097
79463
  for (const file of listHtmlFiles(destDir)) {
79098
- let html = readFileSync35(file, "utf-8");
79464
+ let html = readFileSync36(file, "utf-8");
79099
79465
  let changed = false;
79100
79466
  const dataWidthRe = /(data-width=)["'](\d+)["']/g;
79101
79467
  if (dataWidthRe.test(html)) {
@@ -79137,7 +79503,7 @@ function applyResolutionPreset(destDir, resolution) {
79137
79503
  html = html.replace(viewportRe, `$1width=${width}, height=${height}`);
79138
79504
  changed = true;
79139
79505
  }
79140
- if (changed) writeFileSync25(file, html, "utf-8");
79506
+ if (changed) writeFileSync26(file, html, "utf-8");
79141
79507
  }
79142
79508
  }
79143
79509
  async function scaffoldProject(destDir, name, templateId, localVideoName, durationSeconds, tailwind = false, resolution) {
@@ -79151,7 +79517,7 @@ async function scaffoldProject(destDir, name, templateId, localVideoName, durati
79151
79517
  patchVideoSrc(destDir, localVideoName, durationSeconds);
79152
79518
  if (tailwind) writeTailwindSupport(destDir);
79153
79519
  if (resolution) applyResolutionPreset(destDir, resolution);
79154
- writeFileSync25(
79520
+ writeFileSync26(
79155
79521
  resolve26(destDir, "meta.json"),
79156
79522
  JSON.stringify(
79157
79523
  {
@@ -80090,7 +80456,7 @@ __export(play_exports, {
80090
80456
  default: () => play_default,
80091
80457
  examples: () => examples5
80092
80458
  });
80093
- import { existsSync as existsSync53, readFileSync as readFileSync36 } from "fs";
80459
+ import { existsSync as existsSync53, readFileSync as readFileSync37 } from "fs";
80094
80460
  import { resolve as resolve30, dirname as dirname21 } from "path";
80095
80461
  function commandDir() {
80096
80462
  return dirname21(new URL(import.meta.url).pathname);
@@ -80257,13 +80623,13 @@ var init_play = __esm({
80257
80623
  const { createAdaptorServer } = await import("@hono/node-server");
80258
80624
  const app = new Hono6();
80259
80625
  app.get("/player.js", (ctx) => {
80260
- return ctx.body(readFileSync36(playerPath, "utf-8"), 200, {
80626
+ return ctx.body(readFileSync37(playerPath, "utf-8"), 200, {
80261
80627
  "Content-Type": "application/javascript",
80262
80628
  "Cache-Control": "no-cache"
80263
80629
  });
80264
80630
  });
80265
80631
  app.get("/runtime.js", (ctx) => {
80266
- return ctx.body(readFileSync36(runtimePath, "utf-8"), 200, {
80632
+ return ctx.body(readFileSync37(runtimePath, "utf-8"), 200, {
80267
80633
  "Content-Type": "application/javascript",
80268
80634
  "Cache-Control": "no-cache"
80269
80635
  });
@@ -80273,7 +80639,7 @@ var init_play = __esm({
80273
80639
  const filePath = resolve30(project.dir, reqPath);
80274
80640
  if (!filePath.startsWith(project.dir)) return ctx.text("Forbidden", 403);
80275
80641
  if (!existsSync53(filePath)) return ctx.text("Not found", 404);
80276
- const content = readFileSync36(filePath, "utf-8");
80642
+ const content = readFileSync37(filePath, "utf-8");
80277
80643
  if (filePath.endsWith(".html")) {
80278
80644
  const injected = injectRuntime(content);
80279
80645
  return ctx.html(injected);
@@ -80292,7 +80658,7 @@ var init_play = __esm({
80292
80658
  mp3: "audio/mpeg",
80293
80659
  wav: "audio/wav"
80294
80660
  };
80295
- return ctx.body(readFileSync36(filePath), 200, {
80661
+ return ctx.body(readFileSync37(filePath), 200, {
80296
80662
  "Content-Type": types4[ext] ?? "application/octet-stream"
80297
80663
  });
80298
80664
  });
@@ -80354,7 +80720,7 @@ var init_play = __esm({
80354
80720
 
80355
80721
  // src/utils/publishProject.ts
80356
80722
  import { basename as basename9, join as join60, relative as relative9 } from "path";
80357
- import { readdirSync as readdirSync22, readFileSync as readFileSync37, statSync as statSync19 } from "fs";
80723
+ import { readdirSync as readdirSync22, readFileSync as readFileSync38, statSync as statSync19 } from "fs";
80358
80724
  import AdmZip from "adm-zip";
80359
80725
  function isRecord2(value) {
80360
80726
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -80473,7 +80839,7 @@ function createPublishArchive(projectDir) {
80473
80839
  }
80474
80840
  const archive = new AdmZip();
80475
80841
  for (const filePath of filePaths) {
80476
- archive.addFile(filePath, readFileSync37(join60(projectDir, filePath)));
80842
+ archive.addFile(filePath, readFileSync38(join60(projectDir, filePath)));
80477
80843
  }
80478
80844
  return {
80479
80845
  buffer: archive.toBuffer(),
@@ -80701,9 +81067,9 @@ var init_dom = __esm({
80701
81067
  });
80702
81068
 
80703
81069
  // src/utils/variables.ts
80704
- import { readFileSync as readFileSync38 } from "fs";
81070
+ import { readFileSync as readFileSync39 } from "fs";
80705
81071
  import { resolve as resolve32 } from "path";
80706
- function parseVariablesArg(inline, filePath, readFile = (p2) => readFileSync38(resolve32(p2), "utf8")) {
81072
+ function parseVariablesArg(inline, filePath, readFile = (p2) => readFileSync39(resolve32(p2), "utf8")) {
80707
81073
  if (inline != null && filePath != null) {
80708
81074
  return { ok: false, error: { kind: "conflict" } };
80709
81075
  }
@@ -80786,7 +81152,7 @@ function validateVariablesAgainstProject(indexPath, values) {
80786
81152
  function loadProjectVariableSchema(indexPath) {
80787
81153
  let html;
80788
81154
  try {
80789
- html = readFileSync38(indexPath, "utf8");
81155
+ html = readFileSync39(indexPath, "utf8");
80790
81156
  } catch {
80791
81157
  return [];
80792
81158
  }
@@ -81050,7 +81416,7 @@ __export(render_exports, {
81050
81416
  renderLocal: () => renderLocal,
81051
81417
  resolveBrowserGpuForCli: () => resolveBrowserGpuForCli
81052
81418
  });
81053
- import { mkdirSync as mkdirSync32, readdirSync as readdirSync23, readFileSync as readFileSync39, statSync as statSync20, writeFileSync as writeFileSync26, rmSync as rmSync14 } from "fs";
81419
+ import { mkdirSync as mkdirSync32, readdirSync as readdirSync23, readFileSync as readFileSync40, statSync as statSync20, writeFileSync as writeFileSync27, rmSync as rmSync14 } from "fs";
81054
81420
  import { cpus as cpus4, freemem as freemem4, tmpdir as tmpdir5 } from "os";
81055
81421
  import { resolve as resolve33, dirname as dirname22, join as join62, basename as basename11 } from "path";
81056
81422
  import { execFileSync as execFileSync6, spawn as spawn13 } from "child_process";
@@ -81111,7 +81477,7 @@ function ensureDockerImage(version, quiet) {
81111
81477
  const dockerfilePath = resolveDockerfilePath();
81112
81478
  const tmpDir = join62(tmpdir5(), `hyperframes-docker-${Date.now()}`);
81113
81479
  mkdirSync32(tmpDir, { recursive: true });
81114
- writeFileSync26(join62(tmpDir, "Dockerfile"), readFileSync39(dockerfilePath));
81480
+ writeFileSync27(join62(tmpDir, "Dockerfile"), readFileSync40(dockerfilePath));
81115
81481
  try {
81116
81482
  execFileSync6(
81117
81483
  "docker",
@@ -81976,7 +82342,7 @@ var init_lint3 = __esm({
81976
82342
 
81977
82343
  // src/utils/staticProjectServer.ts
81978
82344
  import { createServer } from "http";
81979
- import { existsSync as existsSync55, readFileSync as readFileSync40 } from "fs";
82345
+ import { existsSync as existsSync55, readFileSync as readFileSync41 } from "fs";
81980
82346
  import { isAbsolute as isAbsolute9, relative as relative10, resolve as resolve34 } from "path";
81981
82347
  async function serveStaticProjectHtml(projectDir, html, bindErrorMessage = "Failed to bind local HTTP server") {
81982
82348
  const server = createServer((req, res) => {
@@ -81995,7 +82361,7 @@ async function serveStaticProjectHtml(projectDir, html, bindErrorMessage = "Fail
81995
82361
  }
81996
82362
  if (existsSync55(filePath)) {
81997
82363
  res.writeHead(200, { "Content-Type": getMimeType(filePath) });
81998
- res.end(readFileSync40(filePath));
82364
+ res.end(readFileSync41(filePath));
81999
82365
  return;
82000
82366
  }
82001
82367
  res.writeHead(404);
@@ -82171,7 +82537,7 @@ __export(layout_exports, {
82171
82537
  default: () => layout_default,
82172
82538
  examples: () => examples9
82173
82539
  });
82174
- import { existsSync as existsSync56, readFileSync as readFileSync41 } from "fs";
82540
+ import { existsSync as existsSync56, readFileSync as readFileSync42 } from "fs";
82175
82541
  import { dirname as dirname23, join as join63 } from "path";
82176
82542
  import { fileURLToPath as fileURLToPath8 } from "url";
82177
82543
  async function getCompositionDuration2(page) {
@@ -82322,7 +82688,7 @@ function loadLayoutAuditScript() {
82322
82688
  join63(__dirname2, "commands", "layout-audit.browser.js")
82323
82689
  ];
82324
82690
  for (const candidate of candidates) {
82325
- if (existsSync56(candidate)) return readFileSync41(candidate, "utf-8");
82691
+ if (existsSync56(candidate)) return readFileSync42(candidate, "utf-8");
82326
82692
  }
82327
82693
  throw new Error("Missing layout audit browser script");
82328
82694
  }
@@ -82530,7 +82896,7 @@ __export(info_exports, {
82530
82896
  default: () => info_default,
82531
82897
  examples: () => examples11
82532
82898
  });
82533
- import { readFileSync as readFileSync42, readdirSync as readdirSync24, statSync as statSync21 } from "fs";
82899
+ import { readFileSync as readFileSync43, readdirSync as readdirSync24, statSync as statSync21 } from "fs";
82534
82900
  import { join as join64 } from "path";
82535
82901
  function totalSize(dir) {
82536
82902
  let total = 0;
@@ -82567,7 +82933,7 @@ var init_info = __esm({
82567
82933
  },
82568
82934
  async run({ args }) {
82569
82935
  const project = resolveProject(args.dir);
82570
- const html = readFileSync42(project.indexPath, "utf-8");
82936
+ const html = readFileSync43(project.indexPath, "utf-8");
82571
82937
  ensureDOMParser();
82572
82938
  const parsed = parseHtml(html);
82573
82939
  const tracks = new Set(parsed.elements.map((el) => el.zIndex));
@@ -82625,7 +82991,7 @@ __export(compositions_exports, {
82625
82991
  examples: () => examples12,
82626
82992
  parseSubComposition: () => parseSubComposition
82627
82993
  });
82628
- import { existsSync as existsSync57, readFileSync as readFileSync43 } from "fs";
82994
+ import { existsSync as existsSync57, readFileSync as readFileSync44 } from "fs";
82629
82995
  import { resolve as resolve35, dirname as dirname24 } from "path";
82630
82996
  function countRenderableDescendants(root) {
82631
82997
  return Array.from(root.querySelectorAll("*")).filter(
@@ -82660,7 +83026,7 @@ function parseCompositions(html, baseDir) {
82660
83026
  if (compositionSrc) {
82661
83027
  const subPath = resolve35(baseDir, compositionSrc);
82662
83028
  if (existsSync57(subPath)) {
82663
- const subHtml = readFileSync43(subPath, "utf-8");
83029
+ const subHtml = readFileSync44(subPath, "utf-8");
82664
83030
  const subInfo = parseSubComposition(subHtml, id, width, height);
82665
83031
  compositions.push({ ...subInfo, source: compositionSrc });
82666
83032
  return;
@@ -82763,7 +83129,7 @@ var init_compositions = __esm({
82763
83129
  },
82764
83130
  async run({ args }) {
82765
83131
  const project = resolveProject(args.dir);
82766
- const html = readFileSync43(project.indexPath, "utf-8");
83132
+ const html = readFileSync44(project.indexPath, "utf-8");
82767
83133
  ensureDOMParser();
82768
83134
  const compositions = parseCompositions(html, dirname24(project.indexPath));
82769
83135
  if (compositions.length === 0) {
@@ -83891,7 +84257,7 @@ __export(transcribe_exports2, {
83891
84257
  default: () => transcribe_default,
83892
84258
  examples: () => examples16
83893
84259
  });
83894
- import { existsSync as existsSync61, writeFileSync as writeFileSync27 } from "fs";
84260
+ import { existsSync as existsSync61, writeFileSync as writeFileSync28 } from "fs";
83895
84261
  import { resolve as resolve38, join as join67, extname as extname11, dirname as dirname25 } from "path";
83896
84262
  async function importTranscript(inputPath, dir, json) {
83897
84263
  const { loadTranscript: loadTranscript2, patchCaptionHtml: patchCaptionHtml2 } = await Promise.resolve().then(() => (init_normalize(), normalize_exports));
@@ -83901,7 +84267,7 @@ async function importTranscript(inputPath, dir, json) {
83901
84267
  process.exit(1);
83902
84268
  }
83903
84269
  const outPath = join67(dir, "transcript.json");
83904
- writeFileSync27(outPath, JSON.stringify(words, null, 2));
84270
+ writeFileSync28(outPath, JSON.stringify(words, null, 2));
83905
84271
  patchCaptionHtml2(dir, words);
83906
84272
  if (json) {
83907
84273
  console.log(
@@ -83936,7 +84302,7 @@ async function transcribeAudio(inputPath, dir, opts) {
83936
84302
  );
83937
84303
  }
83938
84304
  }
83939
- writeFileSync27(result.transcriptPath, JSON.stringify(words, null, 2));
84305
+ writeFileSync28(result.transcriptPath, JSON.stringify(words, null, 2));
83940
84306
  patchCaptionHtml2(dir, words);
83941
84307
  if (opts.json) {
83942
84308
  console.log(
@@ -84144,7 +84510,7 @@ __export(synthesize_exports, {
84144
84510
  synthesize: () => synthesize
84145
84511
  });
84146
84512
  import { execFileSync as execFileSync7 } from "child_process";
84147
- import { existsSync as existsSync63, writeFileSync as writeFileSync28, mkdirSync as mkdirSync35, readdirSync as readdirSync25, unlinkSync as unlinkSync6 } from "fs";
84513
+ import { existsSync as existsSync63, writeFileSync as writeFileSync29, mkdirSync as mkdirSync35, readdirSync as readdirSync25, unlinkSync as unlinkSync6 } from "fs";
84148
84514
  import { join as join69, dirname as dirname26, basename as basename12 } from "path";
84149
84515
  import { homedir as homedir11 } from "os";
84150
84516
  function findPython() {
@@ -84183,7 +84549,7 @@ function hasPythonPackage(python, pkg) {
84183
84549
  function ensureSynthScript() {
84184
84550
  if (!existsSync63(SCRIPT_PATH)) {
84185
84551
  mkdirSync35(SCRIPT_DIR, { recursive: true });
84186
- writeFileSync28(SCRIPT_PATH, SYNTH_SCRIPT);
84552
+ writeFileSync29(SCRIPT_PATH, SYNTH_SCRIPT);
84187
84553
  const currentName = basename12(SCRIPT_PATH);
84188
84554
  try {
84189
84555
  for (const entry of readdirSync25(SCRIPT_DIR)) {
@@ -84310,7 +84676,7 @@ __export(tts_exports, {
84310
84676
  default: () => tts_default,
84311
84677
  examples: () => examples17
84312
84678
  });
84313
- import { existsSync as existsSync64, readFileSync as readFileSync44 } from "fs";
84679
+ import { existsSync as existsSync64, readFileSync as readFileSync45 } from "fs";
84314
84680
  import { resolve as resolve39, extname as extname12 } from "path";
84315
84681
  function listVoices(json) {
84316
84682
  const rows = BUNDLED_VOICES.map((v2) => ({ ...v2, defaultLang: inferLangFromVoiceId(v2.id) }));
@@ -84421,7 +84787,7 @@ var init_tts = __esm({
84421
84787
  let text;
84422
84788
  const maybeFile = resolve39(args.input);
84423
84789
  if (existsSync64(maybeFile) && extname12(maybeFile).toLowerCase() === ".txt") {
84424
- text = readFileSync44(maybeFile, "utf-8").trim();
84790
+ text = readFileSync45(maybeFile, "utf-8").trim();
84425
84791
  if (!text) {
84426
84792
  console.error(c2.error("File is empty."));
84427
84793
  process.exit(1);
@@ -84513,7 +84879,7 @@ __export(docs_exports, {
84513
84879
  default: () => docs_default,
84514
84880
  examples: () => examples18
84515
84881
  });
84516
- import { readFileSync as readFileSync45, existsSync as existsSync65 } from "fs";
84882
+ import { readFileSync as readFileSync46, existsSync as existsSync65 } from "fs";
84517
84883
  import { resolve as resolve40, dirname as dirname27, join as join70 } from "path";
84518
84884
  import { fileURLToPath as fileURLToPath9 } from "url";
84519
84885
  function docsDir() {
@@ -84623,7 +84989,7 @@ var init_docs = __esm({
84623
84989
  console.error(c2.error(`Doc file not found: ${filePath}`));
84624
84990
  process.exit(1);
84625
84991
  }
84626
- const content = readFileSync45(filePath, "utf-8");
84992
+ const content = readFileSync46(filePath, "utf-8");
84627
84993
  console.log();
84628
84994
  renderMarkdown(content);
84629
84995
  }
@@ -85176,7 +85542,7 @@ __export(validate_exports, {
85176
85542
  default: () => validate_default,
85177
85543
  shouldIgnoreRequestFailure: () => shouldIgnoreRequestFailure
85178
85544
  });
85179
- import { existsSync as existsSync66, readFileSync as readFileSync46 } from "fs";
85545
+ import { existsSync as existsSync66, readFileSync as readFileSync47 } from "fs";
85180
85546
  import { join as join71, dirname as dirname28 } from "path";
85181
85547
  import { fileURLToPath as fileURLToPath10 } from "url";
85182
85548
  function shouldIgnoreRequestFailure(url, errorText) {
@@ -85233,7 +85599,7 @@ function loadContrastAuditScript() {
85233
85599
  join71(__dirname3, "commands", "contrast-audit.browser.js")
85234
85600
  ];
85235
85601
  for (const candidate of candidates) {
85236
- if (existsSync66(candidate)) return readFileSync46(candidate, "utf-8");
85602
+ if (existsSync66(candidate)) return readFileSync47(candidate, "utf-8");
85237
85603
  }
85238
85604
  throw new Error("Missing contrast audit browser script");
85239
85605
  }
@@ -85253,7 +85619,7 @@ async function validateInBrowser(projectDir, opts) {
85253
85619
  const filePath = join71(projectDir, decodeURIComponent(url));
85254
85620
  if (existsSync66(filePath)) {
85255
85621
  res.writeHead(200, { "Content-Type": getMimeType2(filePath) });
85256
- res.end(readFileSync46(filePath));
85622
+ res.end(readFileSync47(filePath));
85257
85623
  return;
85258
85624
  }
85259
85625
  res.writeHead(404);
@@ -85455,7 +85821,7 @@ __export(contactSheet_exports, {
85455
85821
  createSvgContactSheet: () => createSvgContactSheet
85456
85822
  });
85457
85823
  import sharp from "sharp";
85458
- import { readdirSync as readdirSync26, readFileSync as readFileSync47, writeFileSync as writeFileSync29, unlinkSync as unlinkSync7, existsSync as existsSync67 } from "fs";
85824
+ import { readdirSync as readdirSync26, readFileSync as readFileSync48, writeFileSync as writeFileSync30, unlinkSync as unlinkSync7, existsSync as existsSync67 } from "fs";
85459
85825
  import { join as join72, extname as extname13, basename as basename13, dirname as dirname29 } from "path";
85460
85826
  async function createContactSheet(imagePaths, outputPath, opts = {}) {
85461
85827
  const {
@@ -85606,12 +85972,12 @@ async function createSvgContactSheet(svgsDir, outputPath, assetsRootDir) {
85606
85972
  const svgPath = svgPaths[i2];
85607
85973
  const tmpPath = join72(tmpDir, `.thumb-${i2}.png`);
85608
85974
  try {
85609
- const svgBuf = readFileSync47(svgPath);
85975
+ const svgBuf = readFileSync48(svgPath);
85610
85976
  const thumb = await sharp(svgBuf).resize(thumbSize, thumbSize, {
85611
85977
  fit: "contain",
85612
85978
  background: { r: 245, g: 245, b: 245, alpha: 1 }
85613
85979
  }).flatten({ background: { r: 245, g: 245, b: 245 } }).png().toBuffer();
85614
- writeFileSync29(tmpPath, thumb);
85980
+ writeFileSync30(tmpPath, thumb);
85615
85981
  tmpPaths.push(tmpPath);
85616
85982
  labels.push(svgFileNames[i2].replace(".svg", ""));
85617
85983
  } catch {
@@ -106390,7 +106756,7 @@ var require_websocket = __commonJS({
106390
106756
  var http4 = __require("http");
106391
106757
  var net2 = __require("net");
106392
106758
  var tls = __require("tls");
106393
- var { randomBytes: randomBytes3, createHash: createHash9 } = __require("crypto");
106759
+ var { randomBytes: randomBytes4, createHash: createHash9 } = __require("crypto");
106394
106760
  var { Duplex, Readable: Readable3 } = __require("stream");
106395
106761
  var { URL: URL2 } = __require("url");
106396
106762
  var PerMessageDeflate2 = require_permessage_deflate();
@@ -106920,7 +107286,7 @@ var require_websocket = __commonJS({
106920
107286
  }
106921
107287
  }
106922
107288
  const defaultPort = isSecure ? 443 : 80;
106923
- const key2 = randomBytes3(16).toString("base64");
107289
+ const key2 = randomBytes4(16).toString("base64");
106924
107290
  const request = isSecure ? https2.request : http4.request;
106925
107291
  const protocolSet = /* @__PURE__ */ new Set();
106926
107292
  let perMessageDeflate;
@@ -126164,7 +126530,7 @@ __export(snapshot_exports, {
126164
126530
  examples: () => examples23
126165
126531
  });
126166
126532
  import { spawn as spawn15 } from "child_process";
126167
- import { existsSync as existsSync68, mkdtempSync as mkdtempSync3, readFileSync as readFileSync48, mkdirSync as mkdirSync36, rmSync as rmSync15, writeFileSync as writeFileSync30 } from "fs";
126533
+ import { existsSync as existsSync68, mkdtempSync as mkdtempSync3, readFileSync as readFileSync49, mkdirSync as mkdirSync36, rmSync as rmSync15, writeFileSync as writeFileSync31 } from "fs";
126168
126534
  import { tmpdir as tmpdir6 } from "os";
126169
126535
  import { resolve as resolve41, join as join73, relative as relative11, isAbsolute as isAbsolute10 } from "path";
126170
126536
  async function extractVideoFrameToBuffer(videoPath, timeSeconds, useVp9AlphaDecoder = false) {
@@ -126210,7 +126576,7 @@ async function extractVideoFrameToBuffer(videoPath, timeSeconds, useVp9AlphaDeco
126210
126576
  }
126211
126577
  );
126212
126578
  if (result.code !== 0 || result.timedOut || !existsSync68(outPath)) return null;
126213
- return readFileSync48(outPath);
126579
+ return readFileSync49(outPath);
126214
126580
  } finally {
126215
126581
  try {
126216
126582
  rmSync15(tmp, { recursive: true, force: true });
@@ -126547,7 +126913,7 @@ ${c2.success("\u25C7")} ${paths.length} snapshots saved to snapshots/`);
126547
126913
  const filename = p2.replace("snapshots/", "");
126548
126914
  const filePath = join73(snapshotDir, filename);
126549
126915
  if (!existsSync68(filePath)) return { filename, desc: "file not found" };
126550
- const raw = readFileSync48(filePath);
126916
+ const raw = readFileSync49(filePath);
126551
126917
  let imageData;
126552
126918
  let mimeType = "image/png";
126553
126919
  if (sharpFn) {
@@ -126584,7 +126950,7 @@ ${c2.success("\u25C7")} ${paths.length} snapshots saved to snapshots/`);
126584
126950
  }
126585
126951
  }
126586
126952
  const descPath = join73(snapshotDir, "descriptions.md");
126587
- writeFileSync30(descPath, descriptions.join("\n"));
126953
+ writeFileSync31(descPath, descriptions.join("\n"));
126588
126954
  console.log(` ${c2.dim("descriptions.md")} (Gemini frame analysis)`);
126589
126955
  }
126590
126956
  } catch (descErr) {
@@ -126604,7 +126970,7 @@ ${c2.error("\u2717")} Snapshot failed: ${msg}`);
126604
126970
  });
126605
126971
 
126606
126972
  // src/capture/assetDownloader.ts
126607
- import { writeFileSync as writeFileSync31, mkdirSync as mkdirSync37 } from "fs";
126973
+ import { writeFileSync as writeFileSync32, mkdirSync as mkdirSync37 } from "fs";
126608
126974
  import { join as join74, extname as extname14 } from "path";
126609
126975
  async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks) {
126610
126976
  const assetsDir = join74(outputDir, "assets");
@@ -126628,7 +126994,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
126628
126994
  const name = `${finalSlug}.svg`;
126629
126995
  const localPath = `assets/svgs/${name}`;
126630
126996
  try {
126631
- writeFileSync31(join74(outputDir, localPath), svg.outerHTML, "utf-8");
126997
+ writeFileSync32(join74(outputDir, localPath), svg.outerHTML, "utf-8");
126632
126998
  assets.push({ url: "", localPath, type: "svg" });
126633
126999
  } catch {
126634
127000
  }
@@ -126641,7 +127007,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
126641
127007
  const localPath = `assets/${name}`;
126642
127008
  const buffer = await fetchBuffer(icon.href);
126643
127009
  if (buffer) {
126644
- writeFileSync31(join74(outputDir, localPath), buffer);
127010
+ writeFileSync32(join74(outputDir, localPath), buffer);
126645
127011
  assets.push({ url: icon.href, localPath, type: "favicon" });
126646
127012
  break;
126647
127013
  }
@@ -126698,7 +127064,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
126698
127064
  const name = `${slug}${ext}`;
126699
127065
  usedNames.add(slug);
126700
127066
  const localPath = `assets/${name}`;
126701
- writeFileSync31(join74(outputDir, localPath), buffer);
127067
+ writeFileSync32(join74(outputDir, localPath), buffer);
126702
127068
  assets.push({ url, localPath, type: "image" });
126703
127069
  imgIdx++;
126704
127070
  } catch {
@@ -126711,7 +127077,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks)
126711
127077
  const localPath = `assets/og-image${ext}`;
126712
127078
  const buffer = await fetchBuffer(tokens.ogImage);
126713
127079
  if (buffer && buffer.length > 5e3) {
126714
- writeFileSync31(join74(outputDir, localPath), buffer);
127080
+ writeFileSync32(join74(outputDir, localPath), buffer);
126715
127081
  assets.push({ url: tokens.ogImage, localPath, type: "image" });
126716
127082
  }
126717
127083
  } catch {
@@ -126774,7 +127140,7 @@ async function downloadAndRewriteFonts(css, outputDir) {
126774
127140
  const relativePath = `assets/fonts/${filename}`;
126775
127141
  const buffer = await fetchBuffer(fontUrl);
126776
127142
  if (buffer) {
126777
- writeFileSync31(localPath, buffer);
127143
+ writeFileSync32(localPath, buffer);
126778
127144
  rewritten = rewritten.split(fontUrl).join(relativePath);
126779
127145
  familyCounts.set(family, familyCount + 1);
126780
127146
  count++;
@@ -127741,7 +128107,7 @@ var init_designStyleExtractor = __esm({
127741
128107
  });
127742
128108
 
127743
128109
  // src/capture/fontMetadataExtractor.ts
127744
- import { readdirSync as readdirSync27, readFileSync as readFileSync49, writeFileSync as writeFileSync32, existsSync as existsSync69 } from "fs";
128110
+ import { readdirSync as readdirSync27, readFileSync as readFileSync50, writeFileSync as writeFileSync33, existsSync as existsSync69 } from "fs";
127745
128111
  import { join as join75 } from "path";
127746
128112
  import * as fontkit from "fontkit";
127747
128113
  function isFontCollection(value) {
@@ -127775,7 +128141,7 @@ function extractFontMetadata(fontsDir, outputPath) {
127775
128141
  tool: "fontkit"
127776
128142
  }
127777
128143
  };
127778
- writeFileSync32(outputPath, JSON.stringify(manifest, null, 2), "utf-8");
128144
+ writeFileSync33(outputPath, JSON.stringify(manifest, null, 2), "utf-8");
127779
128145
  return manifest;
127780
128146
  }
127781
128147
  function readSingleFont(fullPath, filename) {
@@ -127791,7 +128157,7 @@ function readSingleFont(fullPath, filename) {
127791
128157
  identified: false
127792
128158
  };
127793
128159
  try {
127794
- const buf = readFileSync49(fullPath);
128160
+ const buf = readFileSync50(fullPath);
127795
128161
  const created = fontkit.create(buf);
127796
128162
  const font = isFontCollection(created) ? created.fonts[0] : created;
127797
128163
  if (!font) return empty;
@@ -128047,7 +128413,7 @@ var init_animationCataloger = __esm({
128047
128413
  });
128048
128414
 
128049
128415
  // src/capture/mediaCapture.ts
128050
- import { mkdirSync as mkdirSync38, writeFileSync as writeFileSync33, readdirSync as readdirSync28, readFileSync as readFileSync50, statSync as statSync24 } from "fs";
128416
+ import { mkdirSync as mkdirSync38, writeFileSync as writeFileSync34, readdirSync as readdirSync28, readFileSync as readFileSync51, statSync as statSync24 } from "fs";
128051
128417
  import { join as join76 } from "path";
128052
128418
  async function saveLottieAnimations(discoveredLotties, lottieDir) {
128053
128419
  let savedCount = 0;
@@ -128081,7 +128447,7 @@ async function saveLottieAnimations(discoveredLotties, lottieDir) {
128081
128447
  const hash2 = buf.toString("base64").slice(0, 100);
128082
128448
  if (savedHashes.has(hash2)) continue;
128083
128449
  savedHashes.add(hash2);
128084
- writeFileSync33(join76(lottieDir, `animation-${savedCount}.lottie`), buf);
128450
+ writeFileSync34(join76(lottieDir, `animation-${savedCount}.lottie`), buf);
128085
128451
  savedCount++;
128086
128452
  continue;
128087
128453
  }
@@ -128099,7 +128465,7 @@ async function saveLottieAnimations(discoveredLotties, lottieDir) {
128099
128465
  } catch {
128100
128466
  continue;
128101
128467
  }
128102
- writeFileSync33(join76(lottieDir, `animation-${savedCount}.json`), jsonData, "utf-8");
128468
+ writeFileSync34(join76(lottieDir, `animation-${savedCount}.json`), jsonData, "utf-8");
128103
128469
  savedCount++;
128104
128470
  }
128105
128471
  } catch {
@@ -128114,7 +128480,7 @@ async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir) {
128114
128480
  for (const file of readdirSync28(lottieDir)) {
128115
128481
  if (!file.endsWith(".json")) continue;
128116
128482
  try {
128117
- const raw = JSON.parse(readFileSync50(join76(lottieDir, file), "utf-8"));
128483
+ const raw = JSON.parse(readFileSync51(join76(lottieDir, file), "utf-8"));
128118
128484
  const fr = raw.fr || 30;
128119
128485
  const dur = ((raw.op || 0) - (raw.ip || 0)) / fr;
128120
128486
  const previewName = file.replace(".json", "-preview.png");
@@ -128124,7 +128490,7 @@ async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir) {
128124
128490
  try {
128125
128491
  previewPage = await chromeBrowser.newPage();
128126
128492
  await previewPage.setViewport({ width: 400, height: 400 });
128127
- const animData = JSON.parse(readFileSync50(join76(lottieDir, file), "utf-8"));
128493
+ const animData = JSON.parse(readFileSync51(join76(lottieDir, file), "utf-8"));
128128
128494
  const midFrame = Math.floor(((raw.op || 0) - (raw.ip || 0)) * 0.3);
128129
128495
  await previewPage.setContent(
128130
128496
  `<!DOCTYPE html>
@@ -128177,7 +128543,7 @@ async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir) {
128177
128543
  }
128178
128544
  }
128179
128545
  if (manifest.length > 0) {
128180
- writeFileSync33(
128546
+ writeFileSync34(
128181
128547
  join76(outputDir, "extracted", "lottie-manifest.json"),
128182
128548
  JSON.stringify(manifest, null, 2),
128183
128549
  "utf-8"
@@ -128286,7 +128652,7 @@ async function captureVideoManifest(page, outputDir, progress) {
128286
128652
  });
128287
128653
  }
128288
128654
  if (videoManifest.length > 0) {
128289
- writeFileSync33(
128655
+ writeFileSync34(
128290
128656
  join76(outputDir, "extracted", "video-manifest.json"),
128291
128657
  JSON.stringify(videoManifest, null, 2),
128292
128658
  "utf-8"
@@ -128303,7 +128669,7 @@ var init_mediaCapture = __esm({
128303
128669
  });
128304
128670
 
128305
128671
  // src/capture/contentExtractor.ts
128306
- import { existsSync as existsSync70, readdirSync as readdirSync29, statSync as statSync25, readFileSync as readFileSync51 } from "fs";
128672
+ import { existsSync as existsSync70, readdirSync as readdirSync29, statSync as statSync25, readFileSync as readFileSync52 } from "fs";
128307
128673
  import { join as join77 } from "path";
128308
128674
  async function detectLibraries(page, capturedShaders) {
128309
128675
  let detectedLibraries = [];
@@ -128436,7 +128802,7 @@ async function captionImagesWithGemini(outputDir, progress, warnings) {
128436
128802
  const filePath = join77(outputDir, "assets", file);
128437
128803
  const stat3 = statSync25(filePath);
128438
128804
  if (stat3.size > 4e6) return { file, caption: "" };
128439
- const buffer = readFileSync51(filePath);
128805
+ const buffer = readFileSync52(filePath);
128440
128806
  const base64 = buffer.toString("base64");
128441
128807
  const ext = file.split(".").pop()?.toLowerCase() || "png";
128442
128808
  const mimeType = ext === "jpg" ? "image/jpeg" : `image/${ext}`;
@@ -128492,7 +128858,7 @@ async function captionImagesWithGemini(outputDir, progress, warnings) {
128492
128858
  const results = await Promise.allSettled(
128493
128859
  batch.map(async ({ relPath }) => {
128494
128860
  const filePath = join77(assetsDir, relPath);
128495
- let svgText = readFileSync51(filePath, "utf-8");
128861
+ let svgText = readFileSync52(filePath, "utf-8");
128496
128862
  if (svgText.length > MAX_SVG_CHARS) {
128497
128863
  svgText = svgText.slice(0, MAX_SVG_CHARS) + "\n<!-- truncated -->";
128498
128864
  }
@@ -128610,7 +128976,7 @@ var agentPromptGenerator_exports = {};
128610
128976
  __export(agentPromptGenerator_exports, {
128611
128977
  generateAgentPrompt: () => generateAgentPrompt
128612
128978
  });
128613
- import { writeFileSync as writeFileSync34, readdirSync as readdirSync30, existsSync as existsSync71 } from "fs";
128979
+ import { writeFileSync as writeFileSync35, readdirSync as readdirSync30, existsSync as existsSync71 } from "fs";
128614
128980
  import { join as join78 } from "path";
128615
128981
  function inferColorRole(hex) {
128616
128982
  const r2 = parseInt(hex.slice(1, 3), 16) / 255;
@@ -128630,9 +128996,9 @@ function inferColorRole(hex) {
128630
128996
  }
128631
128997
  function generateAgentPrompt(outputDir, url, tokens, _animations, hasScreenshot, hasLottie, hasShaders, _catalogedAssets, _detectedLibraries) {
128632
128998
  const prompt = buildPrompt(outputDir, url, tokens, hasScreenshot, hasLottie, hasShaders);
128633
- writeFileSync34(join78(outputDir, "AGENTS.md"), prompt, "utf-8");
128634
- writeFileSync34(join78(outputDir, "CLAUDE.md"), prompt, "utf-8");
128635
- writeFileSync34(join78(outputDir, ".cursorrules"), prompt, "utf-8");
128999
+ writeFileSync35(join78(outputDir, "AGENTS.md"), prompt, "utf-8");
129000
+ writeFileSync35(join78(outputDir, "CLAUDE.md"), prompt, "utf-8");
129001
+ writeFileSync35(join78(outputDir, ".cursorrules"), prompt, "utf-8");
128636
129002
  }
128637
129003
  function buildPrompt(outputDir, url, tokens, hasScreenshot, hasLottie, hasShaders) {
128638
129004
  const title = tokens.title || new URL(url).hostname.replace(/^www\./, "");
@@ -128745,7 +129111,7 @@ var init_agentPromptGenerator = __esm({
128745
129111
  });
128746
129112
 
128747
129113
  // src/capture/scaffolding.ts
128748
- import { existsSync as existsSync72, writeFileSync as writeFileSync35, readFileSync as readFileSync52 } from "fs";
129114
+ import { existsSync as existsSync72, writeFileSync as writeFileSync36, readFileSync as readFileSync53 } from "fs";
128749
129115
  import { join as join79, resolve as resolve42 } from "path";
128750
129116
  function loadEnvFile(startDir) {
128751
129117
  try {
@@ -128753,7 +129119,7 @@ function loadEnvFile(startDir) {
128753
129119
  for (let i2 = 0; i2 < 5; i2++) {
128754
129120
  const envPath = resolve42(dir, ".env");
128755
129121
  try {
128756
- const envContent = readFileSync52(envPath, "utf-8");
129122
+ const envContent = readFileSync53(envPath, "utf-8");
128757
129123
  for (const line of envContent.split("\n")) {
128758
129124
  const trimmed = line.trim();
128759
129125
  if (!trimmed || trimmed.startsWith("#")) continue;
@@ -128775,7 +129141,7 @@ async function generateProjectScaffold(outputDir, url, tokens, animationCatalog,
128775
129141
  const metaPath = join79(outputDir, "meta.json");
128776
129142
  if (!existsSync72(metaPath)) {
128777
129143
  const hostname = new URL(url).hostname.replace(/^www\./, "");
128778
- writeFileSync35(
129144
+ writeFileSync36(
128779
129145
  metaPath,
128780
129146
  JSON.stringify({ id: hostname + "-video", name: tokens.title || hostname }, null, 2),
128781
129147
  "utf-8"
@@ -128810,7 +129176,7 @@ var screenshotCapture_exports = {};
128810
129176
  __export(screenshotCapture_exports, {
128811
129177
  captureScrollScreenshots: () => captureScrollScreenshots
128812
129178
  });
128813
- import { writeFileSync as writeFileSync36, mkdirSync as mkdirSync39 } from "fs";
129179
+ import { writeFileSync as writeFileSync37, mkdirSync as mkdirSync39 } from "fs";
128814
129180
  import { join as join80 } from "path";
128815
129181
  async function captureScrollScreenshots(page, outputDir) {
128816
129182
  const screenshotsDir = join80(outputDir, "screenshots");
@@ -128907,7 +129273,7 @@ async function captureScrollScreenshots(page, outputDir) {
128907
129273
  const filename = `scroll-${String(Math.min(pct, 100)).padStart(3, "0")}.png`;
128908
129274
  const filePath = join80(screenshotsDir, filename);
128909
129275
  const buffer = await page.screenshot({ type: "png" });
128910
- writeFileSync36(filePath, buffer);
129276
+ writeFileSync37(filePath, buffer);
128911
129277
  filePaths.push(`screenshots/${filename}`);
128912
129278
  }
128913
129279
  await page.evaluate(`window.scrollTo(0, 0)`);
@@ -129180,7 +129546,7 @@ var capture_exports = {};
129180
129546
  __export(capture_exports, {
129181
129547
  captureWebsite: () => captureWebsite
129182
129548
  });
129183
- import { mkdirSync as mkdirSync40, writeFileSync as writeFileSync37, existsSync as existsSync73 } from "fs";
129549
+ import { mkdirSync as mkdirSync40, writeFileSync as writeFileSync38, existsSync as existsSync73 } from "fs";
129184
129550
  import { join as join81 } from "path";
129185
129551
  async function captureWebsite(opts, onProgress) {
129186
129552
  const {
@@ -129375,7 +129741,7 @@ async function captureWebsite(opts, onProgress) {
129375
129741
  return true;
129376
129742
  });
129377
129743
  capturedShaders = unique;
129378
- writeFileSync37(
129744
+ writeFileSync38(
129379
129745
  join81(outputDir, "extracted", "shaders.json"),
129380
129746
  JSON.stringify(unique, null, 2),
129381
129747
  "utf-8"
@@ -129390,7 +129756,7 @@ async function captureWebsite(opts, onProgress) {
129390
129756
  ...tokens,
129391
129757
  svgs: tokens.svgs.map(({ outerHTML: _, ...rest }) => rest)
129392
129758
  };
129393
- writeFileSync37(
129759
+ writeFileSync38(
129394
129760
  join81(outputDir, "extracted", "tokens.json"),
129395
129761
  JSON.stringify(tokensForDisk, null, 2),
129396
129762
  "utf-8"
@@ -129398,7 +129764,7 @@ async function captureWebsite(opts, onProgress) {
129398
129764
  progress("style", "Extracting design styles...");
129399
129765
  try {
129400
129766
  const designStyles = await extractDesignStyles(page1);
129401
- writeFileSync37(
129767
+ writeFileSync38(
129402
129768
  join81(outputDir, "extracted", "design-styles.json"),
129403
129769
  JSON.stringify(designStyles, null, 2),
129404
129770
  "utf-8"
@@ -129502,7 +129868,7 @@ ${err.stack}` : String(err);
129502
129868
  scrollTriggeredElements: (animationCatalog.scrollTargets || []).length,
129503
129869
  representativeAnimations: representativeAnims
129504
129870
  };
129505
- writeFileSync37(
129871
+ writeFileSync38(
129506
129872
  join81(outputDir, "extracted", "animations.json"),
129507
129873
  JSON.stringify(leanCatalog, null, 2),
129508
129874
  "utf-8"
@@ -129514,14 +129880,14 @@ ${err.stack}` : String(err);
129514
129880
  assets = await downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks);
129515
129881
  }
129516
129882
  if (visibleTextContent) {
129517
- writeFileSync37(join81(outputDir, "extracted", "visible-text.txt"), visibleTextContent, "utf-8");
129883
+ writeFileSync38(join81(outputDir, "extracted", "visible-text.txt"), visibleTextContent, "utf-8");
129518
129884
  }
129519
129885
  const geminiCaptions = await captionImagesWithGemini(outputDir, progress, warnings);
129520
129886
  progress("design", "Generating asset descriptions...");
129521
129887
  try {
129522
129888
  const lines = generateAssetDescriptions(outputDir, tokens, catalogedAssets, geminiCaptions);
129523
129889
  if (lines.length > 0) {
129524
- writeFileSync37(
129890
+ writeFileSync38(
129525
129891
  join81(outputDir, "extracted", "asset-descriptions.md"),
129526
129892
  "# Asset Descriptions\n\nOne line per file. Read this instead of opening every image individually.\n\n" + lines.map((l) => "- " + l).join("\n") + "\n",
129527
129893
  "utf-8"
@@ -129753,11 +130119,11 @@ var init_capture2 = __esm({
129753
130119
  } catch (err) {
129754
130120
  const errMsg = err instanceof Error ? err.message : String(err);
129755
130121
  try {
129756
- const { mkdirSync: mkdirSync44, writeFileSync: writeFileSync39 } = await import("fs");
130122
+ const { mkdirSync: mkdirSync44, writeFileSync: writeFileSync40 } = await import("fs");
129757
130123
  mkdirSync44(outputDir, { recursive: true });
129758
130124
  const isTimeout = /timeout|timed out/i.test(errMsg);
129759
130125
  const reason = isTimeout ? "Page navigation timed out \u2014 the site may be blocking headless browsers or requires authentication." : `Capture failed: ${errMsg}`;
129760
- writeFileSync39(
130126
+ writeFileSync40(
129761
130127
  `${outputDir}/BLOCKED.md`,
129762
130128
  `# Capture Failed
129763
130129
 
@@ -129800,7 +130166,7 @@ __export(state_exports, {
129800
130166
  stateFilePath: () => stateFilePath,
129801
130167
  writeStackOutputs: () => writeStackOutputs
129802
130168
  });
129803
- import { existsSync as existsSync74, mkdirSync as mkdirSync41, readdirSync as readdirSync31, readFileSync as readFileSync53, rmSync as rmSync16, writeFileSync as writeFileSync38 } from "fs";
130169
+ import { existsSync as existsSync74, mkdirSync as mkdirSync41, readdirSync as readdirSync31, readFileSync as readFileSync54, rmSync as rmSync16, writeFileSync as writeFileSync39 } from "fs";
129804
130170
  import { dirname as dirname30, join as join82 } from "path";
129805
130171
  function stateFilePath(stackName = DEFAULT_STACK_NAME, cwd = process.cwd()) {
129806
130172
  return join82(cwd, STATE_DIR_NAME, `${STATE_FILE_PREFIX}${stackName}.json`);
@@ -129808,14 +130174,14 @@ function stateFilePath(stackName = DEFAULT_STACK_NAME, cwd = process.cwd()) {
129808
130174
  function writeStackOutputs(outputs, cwd = process.cwd()) {
129809
130175
  const path2 = stateFilePath(outputs.stackName, cwd);
129810
130176
  mkdirSync41(dirname30(path2), { recursive: true });
129811
- writeFileSync38(path2, JSON.stringify(outputs, null, 2) + "\n");
130177
+ writeFileSync39(path2, JSON.stringify(outputs, null, 2) + "\n");
129812
130178
  return path2;
129813
130179
  }
129814
130180
  function readStackOutputs(stackName = DEFAULT_STACK_NAME, cwd = process.cwd()) {
129815
130181
  const path2 = stateFilePath(stackName, cwd);
129816
130182
  if (!existsSync74(path2)) return null;
129817
130183
  try {
129818
- return JSON.parse(readFileSync53(path2, "utf-8"));
130184
+ return JSON.parse(readFileSync54(path2, "utf-8"));
129819
130185
  } catch {
129820
130186
  return null;
129821
130187
  }
@@ -130137,14 +130503,14 @@ var init_sites = __esm({
130137
130503
  });
130138
130504
 
130139
130505
  // src/commands/lambda/_dimensions.ts
130140
- import { readFileSync as readFileSync54 } from "fs";
130506
+ import { readFileSync as readFileSync55 } from "fs";
130141
130507
  import { join as join85 } from "path";
130142
130508
  function warnOnDimensionMismatch(args) {
130143
130509
  if (args.quiet) return;
130144
130510
  if (args.outputResolution) return;
130145
130511
  let html;
130146
130512
  try {
130147
- html = readFileSync54(join85(args.projectDir, "index.html"), "utf-8");
130513
+ html = readFileSync55(join85(args.projectDir, "index.html"), "utf-8");
130148
130514
  } catch {
130149
130515
  return;
130150
130516
  }
@@ -130313,7 +130679,7 @@ __export(render_batch_exports, {
130313
130679
  runRenderBatch: () => runRenderBatch,
130314
130680
  runWithConcurrencyLimit: () => runWithConcurrencyLimit
130315
130681
  });
130316
- import { existsSync as existsSync79, readFileSync as readFileSync55 } from "fs";
130682
+ import { existsSync as existsSync79, readFileSync as readFileSync56 } from "fs";
130317
130683
  import { join as join87, resolve as resolvePath3 } from "path";
130318
130684
  async function loadSDK3() {
130319
130685
  return import("@hyperframes/aws-lambda/sdk");
@@ -130465,7 +130831,7 @@ function makePlaceholderSiteHandle(siteId, bucketName) {
130465
130831
  };
130466
130832
  }
130467
130833
  function parseBatchFile(path2) {
130468
- const raw = readFileSync55(path2, "utf8");
130834
+ const raw = readFileSync56(path2, "utf8");
130469
130835
  const lines = raw.split(/\r?\n/);
130470
130836
  const out = [];
130471
130837
  for (let i2 = 0; i2 < lines.length; i2++) {
@@ -130659,7 +131025,7 @@ __export(policies_exports, {
130659
131025
  runPolicies: () => runPolicies,
130660
131026
  validatePolicy: () => validatePolicy
130661
131027
  });
130662
- import { readFileSync as readFileSync56 } from "fs";
131028
+ import { readFileSync as readFileSync57 } from "fs";
130663
131029
  function allRequiredActions() {
130664
131030
  const set = /* @__PURE__ */ new Set();
130665
131031
  for (const group of Object.values(REQUIRED_ACTIONS)) {
@@ -130765,7 +131131,7 @@ async function runPolicies(args) {
130765
131131
  }
130766
131132
  }
130767
131133
  function validatePolicy(policyPath) {
130768
- const raw = readFileSync56(policyPath, "utf-8");
131134
+ const raw = readFileSync57(policyPath, "utf-8");
130769
131135
  const parsed = JSON.parse(raw);
130770
131136
  const statements = Array.isArray(parsed.Statement) ? parsed.Statement : parsed.Statement ? [
130771
131137
  parsed.Statement
@@ -131875,14 +132241,14 @@ var init_client3 = __esm({
131875
132241
  });
131876
132242
 
131877
132243
  // src/auth/pkce.ts
131878
- import { createHash as createHash8, randomBytes as randomBytes2 } from "crypto";
132244
+ import { createHash as createHash8, randomBytes as randomBytes3 } from "crypto";
131879
132245
  function generatePkcePair() {
131880
- const verifier = base64UrlEncode(randomBytes2(VERIFIER_BYTES));
132246
+ const verifier = base64UrlEncode(randomBytes3(VERIFIER_BYTES));
131881
132247
  const challenge = base64UrlEncode(createHash8("sha256").update(verifier).digest());
131882
132248
  return { verifier, challenge, method: "S256" };
131883
132249
  }
131884
132250
  function generateState() {
131885
- return base64UrlEncode(randomBytes2(32));
132251
+ return base64UrlEncode(randomBytes3(32));
131886
132252
  }
131887
132253
  function base64UrlEncode(buf) {
131888
132254
  return buf.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
@@ -134571,10 +134937,10 @@ if (rootVersionRequested) {
134571
134937
  process.exit(0);
134572
134938
  }
134573
134939
  try {
134574
- const { readFileSync: readFileSync57 } = await import("fs");
134940
+ const { readFileSync: readFileSync58 } = await import("fs");
134575
134941
  const { resolve: resolve46 } = await import("path");
134576
134942
  const envPath = resolve46(process.cwd(), ".env");
134577
- const envContent = readFileSync57(envPath, "utf-8");
134943
+ const envContent = readFileSync58(envPath, "utf-8");
134578
134944
  for (const rawLine of envContent.split("\n")) {
134579
134945
  let line = rawLine.trim();
134580
134946
  if (!line || line.startsWith("#")) continue;